import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import Stickies from '../components/stickies'; import { createTestWrapper } from './test-wrapper'; const MOCK_STICKIES = [ { id: 'note_001', text: 'Login flow feels confusing', x: 193, y: 191, author: 'user_5', color: 'yellow' }, { id: 'note_002', text: 'Export takes too long', x: 798, y: 211, author: 'user_2', color: 'green' }, ]; const MOCK_CLUSTER_RESPONSE = { clusters: [ { label: 'Auth Issues', noteIds: ['note_001'] }, { label: 'Export Issues', noteIds: ['note_002'] }, ], score: 0.74, }; let fetchMock: ReturnType; beforeEach(() => { fetchMock = vi.fn(); globalThis.fetch = fetchMock as unknown as typeof fetch; }); afterEach(() => { vi.restoreAllMocks(); }); const mockFetchOk = (data: unknown) => Promise.resolve({ ok: true, json: () => Promise.resolve(data) } as Response); const mockFetchFail = () => Promise.resolve({ ok: false, status: 500, json: () => Promise.resolve({}) } as Response); describe('Stickies', () => { it('should show a loading indicator while fetching notes', () => { fetchMock.mockReturnValue(new Promise(() => {})); const { Wrapper } = createTestWrapper(); render(, { wrapper: Wrapper }); expect(screen.getByText('Loading...')).toBeInTheDocument(); }); it('should render all sticky notes after fetch succeeds', async () => { fetchMock.mockReturnValue(mockFetchOk(MOCK_STICKIES)); const { Wrapper } = createTestWrapper(); render(, { wrapper: Wrapper }); expect(await screen.findByText('Login flow feels confusing')).toBeInTheDocument(); expect(screen.getByText('Export takes too long')).toBeInTheDocument(); }); it('should render the cluster button', async () => { fetchMock.mockReturnValue(mockFetchOk(MOCK_STICKIES)); const { Wrapper } = createTestWrapper(); render(, { wrapper: Wrapper }); expect(await screen.findByRole('button', { name: 'Group Stickies By Topic' })).toBeInTheDocument(); }); it('should show an error message when fetching notes fails', async () => { fetchMock.mockReturnValue(mockFetchFail()); const { Wrapper } = createTestWrapper(); render(, { wrapper: Wrapper }); expect(await screen.findByText(/Error:/)).toBeInTheDocument(); }); it('should show cluster labels after clustering succeeds', async () => { fetchMock .mockReturnValueOnce(mockFetchOk(MOCK_STICKIES)) .mockReturnValueOnce(mockFetchOk(MOCK_CLUSTER_RESPONSE)); const { Wrapper } = createTestWrapper(); render(, { wrapper: Wrapper }); const btn = await screen.findByRole('button', { name: 'Group Stickies By Topic' }); await userEvent.click(btn); await waitFor(() => { expect(screen.getByText('Auth Issues')).toBeInTheDocument(); expect(screen.getByText('Export Issues')).toBeInTheDocument(); }); }); it('should still render sticky note text inside clusters', async () => { fetchMock .mockReturnValueOnce(mockFetchOk(MOCK_STICKIES)) .mockReturnValueOnce(mockFetchOk(MOCK_CLUSTER_RESPONSE)); const { Wrapper } = createTestWrapper(); render(, { wrapper: Wrapper }); const btn = await screen.findByRole('button', { name: 'Group Stickies By Topic' }); await userEvent.click(btn); expect(await screen.findByText('Login flow feels confusing')).toBeInTheDocument(); expect(screen.getByText('Export takes too long')).toBeInTheDocument(); }); it('should display rank badges on clustered groups', async () => { fetchMock .mockReturnValueOnce(mockFetchOk(MOCK_STICKIES)) .mockReturnValueOnce(mockFetchOk(MOCK_CLUSTER_RESPONSE)); const { Wrapper } = createTestWrapper(); render(, { wrapper: Wrapper }); const btn = await screen.findByRole('button', { name: 'Group Stickies By Topic' }); await userEvent.click(btn); await waitFor(() => { expect(screen.getByLabelText('Priority 1')).toBeInTheDocument(); expect(screen.getByLabelText('Priority 2')).toBeInTheDocument(); }); }); it('should make cluster groups draggable', async () => { fetchMock .mockReturnValueOnce(mockFetchOk(MOCK_STICKIES)) .mockReturnValueOnce(mockFetchOk(MOCK_CLUSTER_RESPONSE)); const { Wrapper } = createTestWrapper(); render(, { wrapper: Wrapper }); const btn = await screen.findByRole('button', { name: 'Group Stickies By Topic' }); await userEvent.click(btn); await waitFor(() => { const groups = document.querySelectorAll('.cluster-draggable'); groups.forEach((group) => { expect(group).toHaveAttribute('draggable', 'true'); }); expect(groups.length).toBe(2); }); }); });