202 lines
6.1 KiB
JavaScript
202 lines
6.1 KiB
JavaScript
import { mount } from "@vue/test-utils";
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
import NotificationBell from "@/components/NotificationBell.vue";
|
|
import { nextTick } from "vue";
|
|
|
|
describe("NotificationBell.vue", () => {
|
|
let axiosMock;
|
|
|
|
beforeEach(() => {
|
|
axiosMock = {
|
|
get: vi.fn().mockResolvedValue({
|
|
data: {
|
|
notifications: [],
|
|
unread_count: 0,
|
|
},
|
|
}),
|
|
post: vi.fn().mockResolvedValue({ data: {} }),
|
|
};
|
|
window.axios = axiosMock;
|
|
});
|
|
|
|
afterEach(() => {
|
|
delete window.axios;
|
|
});
|
|
|
|
const mountNotificationBell = () => {
|
|
return mount(NotificationBell, {
|
|
global: {
|
|
mocks: {
|
|
$t: (key) => key,
|
|
$router: { push: vi.fn() },
|
|
},
|
|
stubs: {
|
|
MaterialDesignIcon: true,
|
|
Teleport: true,
|
|
},
|
|
directives: {
|
|
"click-outside": {},
|
|
},
|
|
},
|
|
});
|
|
};
|
|
|
|
it("displays '9+' when unread count is greater than 9", async () => {
|
|
axiosMock.get.mockResolvedValueOnce({
|
|
data: {
|
|
notifications: [],
|
|
unread_count: 15,
|
|
},
|
|
});
|
|
|
|
const wrapper = mountNotificationBell();
|
|
await nextTick();
|
|
await nextTick();
|
|
|
|
expect(wrapper.text()).toContain("9+");
|
|
});
|
|
|
|
it("handles long notification names with truncation", async () => {
|
|
const longName = "A".repeat(100);
|
|
axiosMock.get.mockResolvedValue({
|
|
data: {
|
|
notifications: [
|
|
{
|
|
type: "lxmf_message",
|
|
destination_hash: "hash1",
|
|
display_name: longName,
|
|
updated_at: new Date().toISOString(),
|
|
content: "Short content",
|
|
},
|
|
],
|
|
unread_count: 1,
|
|
},
|
|
});
|
|
|
|
const wrapper = mountNotificationBell();
|
|
await nextTick();
|
|
|
|
// Open dropdown
|
|
await wrapper.find("button").trigger("click");
|
|
await nextTick();
|
|
await nextTick();
|
|
|
|
const nameElement = wrapper.find(".truncate");
|
|
expect(nameElement.exists()).toBe(true);
|
|
expect(nameElement.text()).toBe(longName);
|
|
expect(nameElement.attributes("title")).toBe(longName);
|
|
});
|
|
|
|
it("handles long notification content with line-clamp", async () => {
|
|
const longContent = "B".repeat(500);
|
|
axiosMock.get.mockResolvedValue({
|
|
data: {
|
|
notifications: [
|
|
{
|
|
type: "lxmf_message",
|
|
destination_hash: "hash1",
|
|
display_name: "User",
|
|
updated_at: new Date().toISOString(),
|
|
content: longContent,
|
|
},
|
|
],
|
|
unread_count: 1,
|
|
},
|
|
});
|
|
|
|
const wrapper = mountNotificationBell();
|
|
await nextTick();
|
|
|
|
// Open dropdown
|
|
await wrapper.find("button").trigger("click");
|
|
await nextTick();
|
|
await nextTick();
|
|
|
|
const contentElement = wrapper.find(".line-clamp-2");
|
|
expect(contentElement.exists()).toBe(true);
|
|
expect(contentElement.text().trim()).toBe(longContent);
|
|
expect(contentElement.attributes("title")).toBe(longContent);
|
|
});
|
|
|
|
it("handles a large number of notifications without crashing", async () => {
|
|
const manyNotifications = Array.from({ length: 50 }, (_, i) => ({
|
|
type: "lxmf_message",
|
|
destination_hash: `hash${i}`,
|
|
display_name: `User ${i}`,
|
|
updated_at: new Date().toISOString(),
|
|
content: `Message ${i}`,
|
|
}));
|
|
|
|
axiosMock.get.mockResolvedValue({
|
|
data: {
|
|
notifications: manyNotifications,
|
|
unread_count: 50,
|
|
},
|
|
});
|
|
|
|
const wrapper = mountNotificationBell();
|
|
await nextTick();
|
|
|
|
// Open dropdown
|
|
await wrapper.find("button").trigger("click");
|
|
await nextTick();
|
|
await nextTick();
|
|
|
|
// The buttons are v-for="notification in notifications"
|
|
// Let's find them by class .w-full and hover:bg-gray-50 which are on the same element
|
|
const notificationButtons = wrapper.findAll("div.overflow-y-auto button.w-full");
|
|
expect(notificationButtons.length).toBe(50);
|
|
});
|
|
|
|
it("navigates to voicemail tab when voicemail notification is clicked", async () => {
|
|
const routerPush = vi.fn();
|
|
axiosMock.get.mockResolvedValue({
|
|
data: {
|
|
notifications: [
|
|
{
|
|
type: "telephone_voicemail",
|
|
destination_hash: "hash1",
|
|
display_name: "User",
|
|
updated_at: new Date().toISOString(),
|
|
content: "New voicemail",
|
|
},
|
|
],
|
|
unread_count: 1,
|
|
},
|
|
});
|
|
|
|
const wrapper = mount(NotificationBell, {
|
|
global: {
|
|
mocks: {
|
|
$t: (key) => key,
|
|
$router: { push: routerPush },
|
|
},
|
|
stubs: {
|
|
MaterialDesignIcon: true,
|
|
Teleport: true,
|
|
},
|
|
directives: {
|
|
"click-outside": {},
|
|
},
|
|
},
|
|
});
|
|
|
|
await nextTick();
|
|
|
|
// Click bell to open dropdown
|
|
await wrapper.find("button").trigger("click");
|
|
await nextTick();
|
|
await nextTick();
|
|
|
|
// Click it
|
|
const button = wrapper.find("div.overflow-y-auto button.w-full");
|
|
expect(button.exists()).toBe(true);
|
|
await button.trigger("click");
|
|
|
|
expect(routerPush).toHaveBeenCalledWith({
|
|
name: "call",
|
|
query: { tab: "voicemail" },
|
|
});
|
|
});
|
|
});
|