Files
MeshChatX/tests/frontend/CallPage.test.js
Sudo-Ivan 5a9e066b10
Some checks failed
CI / test-backend (push) Successful in 17s
CI / lint (push) Successful in 46s
Tests / test (push) Failing after 5m15s
CI / build-frontend (push) Successful in 9m33s
feat(tests): add comprehensive unit tests for various components including AboutPage, CallPage, and MessagesPage
2026-01-02 20:36:58 -06:00

124 lines
4.8 KiB
JavaScript

import { mount } from "@vue/test-utils";
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import CallPage from "@/components/call/CallPage.vue";
describe("CallPage.vue", () => {
let axiosMock;
beforeEach(() => {
axiosMock = {
get: vi.fn().mockImplementation((url) => {
const defaultData = {
config: {},
calls: [],
call_history: [],
announces: [],
voicemails: [],
active_call: null,
discovery: [],
contacts: [],
profiles: [],
ringtones: [],
voicemail: { unread_count: 0 },
};
if (url.includes("/api/v1/config")) return Promise.resolve({ data: { config: {} } });
if (url.includes("/api/v1/telephone/history")) return Promise.resolve({ data: { call_history: [] } });
if (url.includes("/api/v1/announces")) return Promise.resolve({ data: { announces: [] } });
if (url.includes("/api/v1/telephone/status")) return Promise.resolve({ data: { active_call: null } });
if (url.includes("/api/v1/telephone/voicemail/status"))
return Promise.resolve({ data: { has_espeak: false } });
if (url.includes("/api/v1/telephone/ringtones/status"))
return Promise.resolve({ data: { enabled: true } });
if (url.includes("/api/v1/telephone/ringtones")) return Promise.resolve({ data: { ringtones: [] } });
if (url.includes("/api/v1/telephone/audio-profiles"))
return Promise.resolve({ data: { audio_profiles: [], default_audio_profile_id: null } });
if (url.includes("/api/v1/contacts")) return Promise.resolve({ data: { contacts: [] } });
return Promise.resolve({ data: defaultData });
}),
post: vi.fn().mockResolvedValue({ data: {} }),
patch: vi.fn().mockResolvedValue({ data: {} }),
delete: vi.fn().mockResolvedValue({ data: {} }),
};
window.axios = axiosMock;
});
afterEach(() => {
delete window.axios;
});
const mountCallPage = () => {
return mount(CallPage, {
global: {
mocks: {
$t: (key) => key,
},
stubs: {
MaterialDesignIcon: true,
LoadingSpinner: true,
LxmfUserIcon: true,
},
},
});
};
it("renders tabs correctly", async () => {
const wrapper = mountCallPage();
await wrapper.vm.$nextTick();
// The tabs are hardcoded strings: Phone, Phonebook, Voicemail, Contacts
expect(wrapper.text()).toContain("Phone");
expect(wrapper.text()).toContain("Phonebook");
expect(wrapper.text()).toContain("Voicemail");
expect(wrapper.text()).toContain("Contacts");
});
it("switches tabs when clicked", async () => {
const wrapper = mountCallPage();
await wrapper.vm.$nextTick();
// Initial tab should be phone
expect(wrapper.vm.activeTab).toBe("phone");
// Click Phonebook tab
const buttons = wrapper.findAll("button");
const phonebookTab = buttons.find((b) => b.text() === "Phonebook");
if (phonebookTab) {
await phonebookTab.trigger("click");
expect(wrapper.vm.activeTab).toBe("phonebook");
} else {
throw new Error("Phonebook tab not found");
}
});
it("displays 'New Call' UI by default when no active call", async () => {
const wrapper = mountCallPage();
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain("New Call");
expect(wrapper.find('input[type="text"]').exists()).toBe(true);
});
it("attempts to place a call when 'Call' button is clicked", async () => {
const wrapper = mountCallPage();
await wrapper.vm.$nextTick();
const input = wrapper.find('input[type="text"]');
await input.setValue("test-destination");
// Find Call button - it's hardcoded "Call"
const buttons = wrapper.findAll("button");
const callButton = buttons.find((b) => b.text() === "Call");
if (callButton) {
await callButton.trigger("click");
// CallPage.vue uses window.axios.get(`/api/v1/telephone/call/${hashToCall}`)
expect(axiosMock.get).toHaveBeenCalledWith(
expect.stringContaining("/api/v1/telephone/call/test-destination")
);
} else {
throw new Error("Call button not found");
}
});
});