stupa-pdf-api/frontend/node_modules/react-pdf/src/StructTree.spec.tsx

143 lines
4.7 KiB
TypeScript

import { beforeAll, describe, expect, it } from 'vitest';
import React from 'react';
import { render } from '@testing-library/react';
import { pdfjs } from './index.test.js';
import StructTree from './StructTree.js';
import failingPage from '../../../__mocks__/_failing_page.js';
import { loadPDF, makeAsyncCallback, muteConsole, restoreConsole } from '../../../test-utils.js';
import PageContext from './PageContext.js';
import type { PDFPageProxy } from 'pdfjs-dist';
import type { PageContextType } from './shared/types.js';
import type { StructTreeNode } from 'pdfjs-dist/types/src/display/api.js';
const pdfFile = loadPDF('./../../__mocks__/_pdf.pdf');
function renderWithContext(children: React.ReactNode, context: Partial<PageContextType>) {
const { rerender, ...otherResult } = render(
<PageContext.Provider value={context as PageContextType}>{children}</PageContext.Provider>,
);
return {
...otherResult,
rerender: (nextChildren: React.ReactNode, nextContext: Partial<PageContextType> = context) =>
rerender(
<PageContext.Provider value={nextContext as PageContextType}>
{nextChildren}
</PageContext.Provider>,
),
};
}
describe('StructTree', () => {
// Loaded page
let page: PDFPageProxy;
let page2: PDFPageProxy;
// Loaded structure tree
let desiredStructTree: StructTreeNode;
let desiredStructTree2: StructTreeNode;
beforeAll(async () => {
const pdf = await pdfjs.getDocument({ data: pdfFile.arrayBuffer }).promise;
page = await pdf.getPage(1);
desiredStructTree = await page.getStructTree();
page2 = await pdf.getPage(2);
desiredStructTree2 = await page2.getStructTree();
});
describe('loading', () => {
it('loads structure tree and calls onGetStructTreeSuccess callback properly', async () => {
const { func: onGetStructTreeSuccess, promise: onGetStructTreeSuccessPromise } =
makeAsyncCallback();
renderWithContext(<StructTree />, {
onGetStructTreeSuccess,
page,
});
expect.assertions(1);
await expect(onGetStructTreeSuccessPromise).resolves.toMatchObject([desiredStructTree]);
});
it('calls onGetStructTreeError when failed to load annotations', async () => {
const { func: onGetStructTreeError, promise: onGetStructTreeErrorPromise } =
makeAsyncCallback();
muteConsole();
renderWithContext(<StructTree />, {
onGetStructTreeError,
page: failingPage,
});
expect.assertions(1);
await expect(onGetStructTreeErrorPromise).resolves.toMatchObject([expect.any(Error)]);
restoreConsole();
});
it('replaces structure tree properly when page is changed', async () => {
const { func: onGetStructTreeSuccess, promise: onGetStructTreeSuccessPromise } =
makeAsyncCallback();
const { rerender } = renderWithContext(<StructTree />, {
onGetStructTreeSuccess,
page,
});
expect.assertions(2);
await expect(onGetStructTreeSuccessPromise).resolves.toMatchObject([desiredStructTree]);
const { func: onGetStructTreeSuccess2, promise: onGetStructTreeSuccessPromise2 } =
makeAsyncCallback();
rerender(<StructTree />, {
onGetStructTreeSuccess: onGetStructTreeSuccess2,
page: page2,
});
await expect(onGetStructTreeSuccessPromise2).resolves.toMatchObject([desiredStructTree2]);
});
it('throws an error when placed outside Page', () => {
muteConsole();
expect(() => render(<StructTree />)).toThrow();
restoreConsole();
});
});
describe('rendering', () => {
it('renders structure tree properly', async () => {
const { func: onGetStructTreeSuccess, promise: onGetStructTreeSuccessPromise } =
makeAsyncCallback();
const { container } = renderWithContext(<StructTree />, {
onGetStructTreeSuccess,
page,
});
expect.assertions(1);
await onGetStructTreeSuccessPromise;
const wrapper = container.firstElementChild as HTMLSpanElement;
expect(wrapper.outerHTML).toBe(
'<span class="react-pdf__Page__structTree structTree"><span><span role="heading" aria-level="1" aria-owns="p3R_mc0"></span><span aria-owns="p3R_mc1"></span><span aria-owns="p3R_mc2"></span><span role="figure" aria-owns="p3R_mc12"></span><span aria-owns="p3R_mc3"></span><span aria-owns="p3R_mc4"></span><span role="heading" aria-level="2" aria-owns="p3R_mc5"></span><span aria-owns="p3R_mc6"></span><span><span aria-owns="p3R_mc7"></span><span role="link"><span aria-owns="13R"></span><span aria-owns="p3R_mc8"></span></span><span aria-owns="p3R_mc9"></span></span><span aria-owns="p3R_mc10"></span><span aria-owns="p3R_mc11"></span></span></span>',
);
});
});
});