feat(notifications) : add profile pictures and guide previews
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
// @vitest-environment happy-dom
|
||||
import { act } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('@/lib/auth/client', () => ({ authClient: { useSession: () => ({ data: { user: { id: 'reader' } } }) } }));
|
||||
vi.mock('./push-client', () => ({ useSitePushDisabled: () => false }));
|
||||
|
||||
import { NotificationBell, NotificationProvider } from './notification-bell';
|
||||
|
||||
let container: HTMLDivElement;
|
||||
let root: Root;
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
vi.stubGlobal('EventSource', class { addEventListener() {} close() {} });
|
||||
vi.spyOn(HTMLImageElement.prototype, 'complete', 'get').mockReturnValue(true);
|
||||
vi.spyOn(HTMLImageElement.prototype, 'naturalWidth', 'get').mockReturnValue(64);
|
||||
const item = { body: 'A comment', readAt: '2026-10-12T00:00:00Z', authorName: 'Gunshin - dev', authorImage: 'https://profile.example/author.png', imageUrl: null };
|
||||
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true, json: async () => ({ unread: 0, nextCursor: null, items: [
|
||||
{ ...item, id: 'comment', title: 'Gunshin - dev แสดงความคิดเห็นใหม่ในไกด์ Lohen', url: '/admin/comments?comment=comment' },
|
||||
{ ...item, id: 'reply', title: 'Reader ตอบกลับความคิดเห็นของคุณ', url: '/lohen/comment?reply=reply', authorName: 'Reader', authorImage: null },
|
||||
{ ...item, id: 'commission', title: 'Commission message', url: '/commission/tickets/test', authorName: null, authorImage: null },
|
||||
{ ...item, id: 'guide', title: 'มีไกด์ใหม่แล้ว!', body: 'คุณสามารถดูไกด์ Lohen ได้แล้ว!', url: '/lohen', authorName: null, authorImage: null, imageUrl: 'https://buzz-cdn.astrxl.dev/guides/lohen.png' },
|
||||
] }) }));
|
||||
container = document.createElement('div');
|
||||
document.body.append(container);
|
||||
root = createRoot(container);
|
||||
});
|
||||
afterEach(async () => {
|
||||
await act(async () => root.unmount());
|
||||
container.remove();
|
||||
vi.restoreAllMocks();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
describe('comment profile pictures in the notification bell', () => {
|
||||
it.each([false, true])('shows the avatar or its initials when the image is broken: %s', async (broken) => {
|
||||
if (broken) vi.spyOn(HTMLImageElement.prototype, 'naturalWidth', 'get').mockReturnValue(0);
|
||||
await act(async () => root.render(<NotificationProvider><NotificationBell /></NotificationProvider>));
|
||||
await act(async () => container.querySelector<HTMLButtonElement>('button[aria-label="การแจ้งเตือน"]')!.click());
|
||||
const comment = document.querySelector<HTMLAnchorElement>('a[href="/admin/comments?comment=comment"]');
|
||||
expect(comment).not.toBeNull();
|
||||
expect(comment?.textContent).toContain('แสดงความคิดเห็นใหม่ในไกด์ Lohen');
|
||||
if (broken) expect(comment?.querySelector('[data-slot="avatar-fallback"]')?.textContent).toBe('Gu');
|
||||
else expect(comment?.querySelector('img')?.getAttribute('src')).toBe('https://profile.example/author.png');
|
||||
expect(document.querySelector('a[href="/lohen/comment?reply=reply"] [data-slot="avatar-fallback"]')?.textContent).toBe('Re');
|
||||
expect(document.querySelector('a[href="/commission/tickets/test"] [data-slot="avatar"]')).toBeNull();
|
||||
const guide = document.querySelector('a[href="/lohen"]');
|
||||
expect(guide?.querySelector('[data-slot="avatar"]')).toBeNull();
|
||||
const overview = guide?.querySelector('img');
|
||||
expect(overview?.getAttribute('width')).toBe('64');
|
||||
expect(overview?.getAttribute('height')).toBe('64');
|
||||
expect(overview?.classList.contains('rounded-full')).toBe(false);
|
||||
expect(overview?.getAttribute('src')).toContain('lohen.png');
|
||||
expect(guide?.firstElementChild).toBe(overview);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user