volleyball-dev-frontend/node_modules/react-pdf/src/OutlineItem.spec.tsx
2025-06-02 16:42:16 +00:00

129 lines
4.1 KiB
TypeScript

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<ReturnType<PDFDocumentProxy['getOutline']>>;
type PDFOutlineItem = PDFOutline[number];
function renderWithContext(
children: React.ReactNode,
documentContext: Partial<DocumentContextType>,
outlineContext: Partial<OutlineContextType>,
) {
const { rerender, ...otherResult } = render(
<DocumentContext.Provider value={documentContext as DocumentContextType}>
<OutlineContext.Provider value={outlineContext as OutlineContextType}>
{children}
</OutlineContext.Provider>
</DocumentContext.Provider>,
);
return {
...otherResult,
rerender: (
nextChildren: React.ReactNode,
nextDocumentContext: Partial<DocumentContextType> = documentContext,
nextOutlineContext: Partial<OutlineContextType> = outlineContext,
) =>
rerender(
<DocumentContext.Provider value={nextDocumentContext as DocumentContextType}>
<OutlineContext.Provider value={nextOutlineContext as OutlineContextType}>
{nextChildren}
</OutlineContext.Provider>
</DocumentContext.Provider>,
),
};
}
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(<OutlineItem item={outlineItem} />, { pdf }, { onItemClick });
const item = screen.getAllByRole('listitem')[0];
expect(item).toHaveTextContent(outlineItem.title);
});
it("renders item's subitems properly", () => {
const onItemClick = vi.fn();
renderWithContext(<OutlineItem item={outlineItem} />, { 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(<OutlineItem item={outlineItem} />, { 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(
<OutlineItem item={outlineItem} />,
{ 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(<OutlineItem item={outlineItem} />, { pdf }, { onItemClick: onItemClick2 });
fireEvent.click(link);
await onItemClickPromise2;
expect(onItemClick2).toHaveBeenCalledTimes(1);
});
});
});