import { beforeAll, describe, expect, it, vi } from 'vitest'; import { fireEvent, getAllByRole, render, screen } from '@testing-library/react'; import { pdfjs } from './index.test.js'; import OutlineItem from './OutlineItem.js'; import { loadPDF, makeAsyncCallback } from '../../../test-utils.js'; import DocumentContext from './DocumentContext.js'; import OutlineContext from './OutlineContext.js'; import type { PDFDocumentProxy } from 'pdfjs-dist'; import type { DocumentContextType, OutlineContextType } from './shared/types.js'; const pdfFile = loadPDF('./../../__mocks__/_pdf.pdf'); type PDFOutline = Awaited>; type PDFOutlineItem = PDFOutline[number]; function renderWithContext( children: React.ReactNode, documentContext: Partial, outlineContext: Partial, ) { const { rerender, ...otherResult } = render( {children} , ); return { ...otherResult, rerender: ( nextChildren: React.ReactNode, nextDocumentContext: Partial = documentContext, nextOutlineContext: Partial = outlineContext, ) => rerender( {nextChildren} , ), }; } describe('OutlineItem', () => { // Loaded PDF file let pdf: PDFDocumentProxy; // Object with basic loaded outline item information let outlineItem: PDFOutlineItem; beforeAll(async () => { pdf = await pdfjs.getDocument({ data: pdfFile.arrayBuffer }).promise; const outlineItems = await pdf.getOutline(); [outlineItem] = outlineItems as [PDFOutlineItem]; }); describe('rendering', () => { it('renders an item properly', () => { const onItemClick = vi.fn(); renderWithContext(, { pdf }, { onItemClick }); const item = screen.getAllByRole('listitem')[0]; expect(item).toHaveTextContent(outlineItem.title); }); it("renders item's subitems properly", () => { const onItemClick = vi.fn(); renderWithContext(, { pdf }, { onItemClick }); const item = screen.getAllByRole('listitem')[0] as HTMLElement; const subitems = getAllByRole(item, 'listitem'); expect(subitems).toHaveLength(outlineItem.items.length); }); it('calls onItemClick with proper arguments when clicked a link', async () => { const { func: onItemClick, promise: onItemClickPromise } = makeAsyncCallback(); renderWithContext(, { pdf }, { onItemClick }); const item = screen.getAllByRole('listitem')[0] as HTMLElement; const link = getAllByRole(item, 'link')[0] as HTMLAnchorElement; fireEvent.click(link); await onItemClickPromise; expect(onItemClick).toHaveBeenCalled(); }); it('calls onItemClick with proper arguments multiple times when clicked a link multiple times', async () => { const { func: onItemClick, promise: onItemClickPromise } = makeAsyncCallback(); const { rerender } = renderWithContext( , { pdf }, { onItemClick }, ); const item = screen.getAllByRole('listitem')[0] as HTMLElement; const link = getAllByRole(item, 'link')[0] as HTMLAnchorElement; fireEvent.click(link); await onItemClickPromise; expect(onItemClick).toHaveBeenCalledTimes(1); const { func: onItemClick2, promise: onItemClickPromise2 } = makeAsyncCallback(); rerender(, { pdf }, { onItemClick: onItemClick2 }); fireEvent.click(link); await onItemClickPromise2; expect(onItemClick2).toHaveBeenCalledTimes(1); }); }); });