| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673 |
- import { describe, expect, it, vi } from 'vitest';
- import { parseHTML } from 'linkedom';
- import {
- DEFAULT_FILE_VIEWER_RENDER_TARGET_CLASS,
- FILE_VIEWER_RENDER_SESSION_DISPOSE_ERROR_MESSAGE,
- WorkerRefImpl,
- applyFileViewerRenderSurfaceState,
- clearFileViewerRenderSurface,
- createFileRenderHandlerRendererSession,
- createFileRenderHandlerRegistry,
- createFileRenderHandlerLoader,
- createFileViewerRenderSurfaceActionHandlers,
- createFileViewerRenderReadinessTarget,
- createFileViewerRenderSurfaceState,
- createFileViewerRenderSurfaceStateTarget,
- createFileViewerRenderTarget,
- createFileViewerRendererDispatcher,
- disposeActiveFileViewerRendererSession,
- disposeFileViewerRendered,
- disposeFileViewerRendererSession,
- normalizeSource,
- removeFileViewerRenderTarget,
- resetFileViewerRenderSurface,
- renderFileViewerHandler,
- runFileViewerRenderSurfaceClear,
- runFileViewerRenderSurfaceMount,
- resolveFileViewerRenderSessionDisposeErrorMessage,
- reportFileViewerRenderSessionDisposeError,
- refWorker,
- type FileRenderContext,
- type FileRenderHandler,
- type RendererDefinition,
- } from '../packages/core/src';
- describe('@file-viewer/core worker and render contracts', () => {
- it('creates worker refs lazily and reuses the created worker', () => {
- const worker = { terminate: vi.fn() } as unknown as Worker;
- const provider = vi.fn(() => worker);
- const ref = refWorker('demo.worker.js');
- expect(ref.name).toBe('demo.worker.js');
- expect(ref.worker).toBeNull();
- expect(ref.defaults(provider)).toBe(worker);
- expect(ref.defaults(provider)).toBe(worker);
- expect(provider).toHaveBeenCalledTimes(1);
- });
- it('keeps WorkerRefImpl constructible for compatibility wrappers', () => {
- const worker = { postMessage: vi.fn() } as unknown as Worker;
- const ref = new WorkerRefImpl('compat.worker.js', worker);
- expect(ref.name).toBe('compat.worker.js');
- expect(ref.defaults(() => {
- throw new Error('should not replace existing worker');
- })).toBe(worker);
- });
- it('keeps the legacy one-argument WorkerRefImpl constructor working', () => {
- const worker = { postMessage: vi.fn() } as unknown as Worker;
- const ref = new WorkerRefImpl(worker);
- expect(ref.name).toBe('');
- expect(ref.defaults(() => {
- throw new Error('should not replace existing worker');
- })).toBe(worker);
- });
- it('exposes renderer context and handler contracts from core', async () => {
- const context: FileRenderContext = {
- filename: 'demo.pdf',
- url: '/demo.pdf',
- streamUrl: '/demo.pdf',
- onProgressiveRender: vi.fn(),
- registerExportAdapter: vi.fn(),
- };
- const handler: FileRenderHandler<string, HTMLDivElement> = async (_buffer, target, type, nextContext) => {
- nextContext?.onProgressiveRender?.();
- target.dataset.renderedType = type || '';
- return nextContext?.filename || '';
- };
- const target = { dataset: {} } as HTMLDivElement;
- await expect(handler(new ArrayBuffer(1), target, 'pdf', context)).resolves.toBe('demo.pdf');
- expect(target.dataset.renderedType).toBe('pdf');
- expect(context.onProgressiveRender).toHaveBeenCalledTimes(1);
- });
- it('invokes render handlers through the core dispatcher contract', async () => {
- const context: FileRenderContext = {
- filename: 'demo.pdf',
- onProgressiveRender: vi.fn(),
- };
- const handler: FileRenderHandler<string, HTMLDivElement> = async (_buffer, target, type, nextContext) => {
- nextContext?.onProgressiveRender?.();
- target.dataset.renderedType = type || '';
- return nextContext?.filename || '';
- };
- const dispatcher = createFileViewerRendererDispatcher({
- registry: {
- list: () => [{
- id: 'pdf',
- label: 'PDF',
- category: 'document',
- extensions: ['pdf'],
- } as RendererDefinition],
- register: () => undefined,
- unregister: () => false,
- getById: () => undefined,
- getByExtension: () => undefined,
- hasExtension: () => false,
- listExtensions: () => [],
- },
- handlers: [{ rendererId: 'pdf', handler }],
- });
- const target = { dataset: {} } as HTMLDivElement;
- await expect(renderFileViewerHandler({
- dispatcher,
- buffer: new ArrayBuffer(1),
- target,
- type: '.PDF',
- context,
- })).resolves.toBe('demo.pdf');
- expect(target.dataset.renderedType).toBe('pdf');
- expect(context.onProgressiveRender).toHaveBeenCalledTimes(1);
- });
- it('adapts legacy render handlers into renderer loaders', async () => {
- const unmount = vi.fn();
- const onProgressiveRender = vi.fn();
- const registerExportAdapter = vi.fn();
- const handler: FileRenderHandler<{ unmount: () => void }, HTMLDivElement> = async (_buffer, target, type, context) => {
- context?.onProgressiveRender?.();
- target.dataset.renderedType = type || '';
- target.dataset.filename = context?.filename || '';
- target.dataset.streamUrl = context?.streamUrl || '';
- return { unmount };
- };
- const loader = createFileRenderHandlerLoader({ handler });
- const target = { dataset: {} } as HTMLDivElement;
- const session = await loader({
- source: normalizeSource({
- buffer: new ArrayBuffer(1),
- filename: 'demo.docx',
- }),
- surface: { container: target },
- options: {},
- registerExportAdapter,
- renderContext: {
- filename: 'legacy.docx',
- streamUrl: '/legacy-stream.docx',
- onProgressiveRender,
- },
- });
- expect(target.dataset.renderedType).toBe('docx');
- expect(target.dataset.filename).toBe('legacy.docx');
- expect(target.dataset.streamUrl).toBe('/legacy-stream.docx');
- expect(onProgressiveRender).toHaveBeenCalledTimes(1);
- await session.destroy?.();
- expect(unmount).toHaveBeenCalledTimes(1);
- const destroy = vi.fn();
- disposeFileViewerRendered({ destroy });
- expect(destroy).toHaveBeenCalledTimes(1);
- });
- it('wraps legacy rendered instances into core renderer sessions', async () => {
- const unmount = vi.fn();
- const rendered = { unmount };
- const session = createFileRenderHandlerRendererSession(rendered);
- expect(session.rendered).toBe(rendered);
- await session.destroy?.();
- expect(unmount).toHaveBeenCalledTimes(1);
- });
- it('creates and clears framework-neutral render surface targets', () => {
- const { document } = parseHTML('<main id="root"><span>old</span></main>');
- const root = document.getElementById('root') as HTMLElement;
- clearFileViewerRenderSurface(root);
- expect(root.childElementCount).toBe(0);
- const target = createFileViewerRenderTarget(root);
- expect(target.className).toBe(DEFAULT_FILE_VIEWER_RENDER_TARGET_CLASS);
- expect(root.firstElementChild).toBe(target);
- const customTarget = createFileViewerRenderTarget(root, { className: 'custom-render' });
- expect(customTarget.className).toBe('custom-render');
- expect(root.childElementCount).toBe(2);
- expect(removeFileViewerRenderTarget(root, customTarget)).toBe(true);
- expect(removeFileViewerRenderTarget(root, customTarget)).toBe(false);
- });
- it('applies framework-neutral render surface state and disposes the active session', () => {
- const { document } = parseHTML('<main id="root"><section>rendered</section></main>');
- const root = document.getElementById('root') as HTMLElement;
- const onError = vi.fn();
- const destroy = vi.fn();
- const session = { destroy };
- const adapter = { print: true };
- const state = createFileViewerRenderSurfaceState<typeof session>();
- const readiness = {
- renderedReady: true,
- progressiveReady: true,
- };
- expect(state.session).toBeNull();
- expect(state.exportAdapter).toBeNull();
- expect(applyFileViewerRenderSurfaceState(state, {
- session,
- exportAdapter: adapter,
- })).toBe(state);
- expect(state.session).toBe(session);
- expect(state.exportAdapter).toBe(adapter);
- expect(disposeActiveFileViewerRendererSession(state, { onError })).toBe(session);
- expect(destroy).toHaveBeenCalledTimes(1);
- expect(onError).not.toHaveBeenCalled();
- expect(state.session).toBeNull();
- expect(state.exportAdapter).toBe(adapter);
- applyFileViewerRenderSurfaceState(state, { exportAdapter: null });
- expect(state.exportAdapter).toBeNull();
- applyFileViewerRenderSurfaceState(state, {
- session,
- exportAdapter: adapter,
- });
- expect(resetFileViewerRenderSurface({
- surfaceState: state,
- readinessState: readiness,
- container: root,
- disposeOptions: { onError },
- })).toBe(session);
- expect(destroy).toHaveBeenCalledTimes(2);
- expect(onError).not.toHaveBeenCalled();
- expect(state.session).toBeNull();
- expect(state.exportAdapter).toBeNull();
- expect(readiness).toEqual({
- renderedReady: false,
- progressiveReady: false,
- });
- expect(root.childElementCount).toBe(0);
- });
- it('creates render surface targets from framework accessors', () => {
- const { document } = parseHTML('<main id="root"><section>rendered</section></main>');
- const root = document.getElementById('root') as HTMLElement;
- const destroy = vi.fn();
- const session = { destroy };
- const adapter = { exportHtml: true };
- const stateBacking: {
- session: typeof session | null;
- exportAdapter: typeof adapter | null;
- } = {
- session: null,
- exportAdapter: null,
- };
- const readinessBacking = {
- renderedReady: true,
- progressiveReady: true,
- };
- const state = createFileViewerRenderSurfaceStateTarget<typeof session>({
- session: {
- get: () => stateBacking.session,
- set: value => {
- stateBacking.session = value;
- },
- },
- exportAdapter: {
- get: () => stateBacking.exportAdapter,
- set: value => {
- stateBacking.exportAdapter = value as typeof adapter | null;
- },
- },
- });
- const readiness = createFileViewerRenderReadinessTarget({
- renderedReady: {
- get: () => readinessBacking.renderedReady,
- set: value => {
- readinessBacking.renderedReady = value;
- },
- },
- progressiveReady: {
- get: () => readinessBacking.progressiveReady,
- set: value => {
- readinessBacking.progressiveReady = value;
- },
- },
- });
- expect(applyFileViewerRenderSurfaceState(state, {
- session,
- exportAdapter: adapter,
- })).toBe(state);
- expect(stateBacking).toEqual({
- session,
- exportAdapter: adapter,
- });
- expect(resetFileViewerRenderSurface({
- surfaceState: state,
- readinessState: readiness,
- container: root,
- })).toBe(session);
- expect(destroy).toHaveBeenCalledTimes(1);
- expect(stateBacking).toEqual({
- session: null,
- exportAdapter: null,
- });
- expect(readinessBacking).toEqual({
- renderedReady: false,
- progressiveReady: false,
- });
- expect(root.childElementCount).toBe(0);
- });
- it('runs framework-neutral render surface clear lifecycle orchestration', () => {
- const { document } = parseHTML('<main id="root"><section>rendered</section></main>');
- const root = document.getElementById('root') as HTMLElement;
- const session = { destroy: vi.fn() };
- const state = createFileViewerRenderSurfaceState<typeof session>();
- const readiness = {
- renderedReady: true,
- progressiveReady: true,
- };
- const events: string[] = [];
- const unloadContext = { phase: 'unload-start' as const };
- applyFileViewerRenderSurfaceState(state, {
- session,
- exportAdapter: { exportHtml: true },
- });
- const result = runFileViewerRenderSurfaceClear({
- reason: 'component-unmount',
- surfaceState: state,
- readinessState: readiness,
- container: root,
- onUnloadStart: reason => {
- events.push(`start:${reason}:${root.childElementCount}`)
- return unloadContext;
- },
- onClearActiveDocumentContext: () => events.push(`clear-active:${root.childElementCount}`),
- onClearDocumentState: () => events.push('clear-doc'),
- onStopZoomObserver: () => events.push('stop-zoom'),
- onClearZoomProvider: () => events.push('clear-zoom'),
- onUnloadComplete: (context, reason) => events.push(`complete:${reason}:${context === unloadContext}`),
- });
- expect(result).toEqual({
- reason: 'component-unmount',
- unloadContext,
- session,
- });
- expect(session.destroy).toHaveBeenCalledTimes(1);
- expect(state.session).toBeNull();
- expect(state.exportAdapter).toBeNull();
- expect(readiness).toEqual({
- renderedReady: false,
- progressiveReady: false,
- });
- expect(root.childElementCount).toBe(0);
- expect(events).toEqual([
- 'start:component-unmount:1',
- 'clear-active:0',
- 'clear-doc',
- 'stop-zoom',
- 'clear-zoom',
- 'complete:component-unmount:true',
- ]);
- });
- it('runs framework-neutral render surface mount orchestration', async () => {
- const { document } = parseHTML('<main id="root"><span>old</span></main>');
- const root = document.getElementById('root') as HTMLElement;
- const session = { destroy: vi.fn() };
- const adapter = { exportHtml: true };
- const state = createFileViewerRenderSurfaceState<typeof session>();
- const readiness = {
- renderedReady: false,
- progressiveReady: false,
- };
- const clearRenderedContent = vi.fn(() => clearFileViewerRenderSurface(root));
- const waitForContainer = vi.fn();
- const waitForPaint = vi.fn();
- const startZoomObserver = vi.fn();
- const refreshDocumentIndex = vi.fn();
- const refreshZoomProvider = vi.fn();
- const render = vi.fn(async context => {
- expect(context.type).toBe('pdf');
- expect(context.filename).toBe('demo.pdf');
- expect(context.sourceUrl).toBe('/example/demo.pdf');
- expect(context.streamUrl).toBe('/stream/demo.pdf');
- expect(context.target.className).toBe(DEFAULT_FILE_VIEWER_RENDER_TARGET_CLASS);
- context.registerExportAdapter(adapter);
- context.onProgressiveRender();
- context.target.appendChild(document.createElement('strong'));
- return session;
- });
- const result = await runFileViewerRenderSurfaceMount({
- buffer: new ArrayBuffer(4),
- file: new File(['demo'], 'demo.pdf'),
- version: 1,
- sourceUrl: '/example/demo.pdf',
- streamUrl: '/stream/demo.pdf',
- getContainer: () => root,
- surfaceState: state,
- readinessState: readiness,
- isCurrent: version => version === 1,
- clearRenderedContent,
- render,
- waitForContainer,
- waitForPaint,
- onStartZoomObserver: startZoomObserver,
- onRefreshDocumentIndex: refreshDocumentIndex,
- onRefreshZoomProvider: refreshZoomProvider,
- });
- expect(result).toBe(session);
- expect(clearRenderedContent).toHaveBeenCalledWith('replace');
- expect(waitForContainer).toHaveBeenCalledTimes(1);
- expect(waitForPaint).toHaveBeenCalledTimes(1);
- expect(startZoomObserver).toHaveBeenCalledTimes(1);
- expect(render).toHaveBeenCalledTimes(1);
- expect(root.innerHTML).not.toContain('old');
- expect(root.innerHTML).toContain('file-render');
- expect(root.innerHTML).toContain('strong');
- expect(state.exportAdapter).toBe(adapter);
- expect(readiness.progressiveReady).toBe(true);
- expect(refreshDocumentIndex).toHaveBeenCalledTimes(1);
- expect(refreshZoomProvider).toHaveBeenCalledTimes(1);
- });
- it('creates reusable render surface action handlers for framework wrappers', async () => {
- const { document } = parseHTML('<main id="root"><span>old</span></main>');
- const root = document.getElementById('root') as HTMLElement;
- const staleSession = { destroy: vi.fn() };
- const session = { destroy: vi.fn() };
- const adapter = { exportHtml: true };
- const state = createFileViewerRenderSurfaceState<typeof session>();
- const readiness = {
- renderedReady: true,
- progressiveReady: true,
- };
- const waitForContainer = vi.fn();
- const waitForPaint = vi.fn();
- const startZoomObserver = vi.fn();
- const stopZoomObserver = vi.fn();
- const clearZoomProvider = vi.fn();
- const refreshDocumentIndex = vi.fn();
- const refreshZoomProvider = vi.fn();
- const events: string[] = [];
- const unloadContext = { phase: 'facade-unload' as const };
- const render = vi.fn(async context => {
- expect(context.type).toBe('pdf');
- expect(context.filename).toBe('facade.pdf');
- context.registerExportAdapter(adapter);
- context.onProgressiveRender();
- context.target.appendChild(document.createElement('strong'));
- return session;
- });
- const actions = createFileViewerRenderSurfaceActionHandlers({
- getContainer: () => root,
- surfaceState: state,
- readinessState: readiness,
- isCurrent: version => version === 1,
- waitForContainer,
- waitForPaint,
- onUnloadStart: reason => {
- events.push(`start:${reason}`);
- return unloadContext;
- },
- onUnloadComplete: (context, reason) => {
- events.push(`complete:${reason}:${context === unloadContext}`);
- },
- onClearActiveDocumentContext: () => events.push('clear-active'),
- onClearDocumentState: () => events.push('clear-doc'),
- onStartZoomObserver: startZoomObserver,
- onStopZoomObserver: stopZoomObserver,
- onClearZoomProvider: clearZoomProvider,
- onRefreshDocumentIndex: refreshDocumentIndex,
- onRefreshZoomProvider: refreshZoomProvider,
- render,
- });
- expect(actions.setActiveRenderSession(staleSession)).toBe(state);
- expect(state.session).toBe(staleSession);
- const clearResult = actions.clearRenderedContent('replace');
- expect(clearResult).toEqual({
- reason: 'replace',
- unloadContext,
- session: staleSession,
- });
- expect(staleSession.destroy).toHaveBeenCalledTimes(1);
- expect(state.session).toBeNull();
- expect(state.exportAdapter).toBeNull();
- expect(readiness).toEqual({
- renderedReady: false,
- progressiveReady: false,
- });
- expect(root.childElementCount).toBe(0);
- root.appendChild(document.createElement('em'));
- const result = await actions.mountRenderedContent(
- new ArrayBuffer(4),
- new File(['demo'], 'facade.pdf'),
- 1,
- '/example/facade.pdf',
- '/stream/facade.pdf'
- );
- expect(result).toBe(session);
- expect(render).toHaveBeenCalledTimes(1);
- expect(root.innerHTML).not.toContain('em');
- expect(root.innerHTML).toContain('file-render');
- expect(root.innerHTML).toContain('strong');
- expect(state.exportAdapter).toBe(adapter);
- expect(readiness.progressiveReady).toBe(true);
- expect(waitForContainer).toHaveBeenCalledTimes(1);
- expect(waitForPaint).toHaveBeenCalledTimes(1);
- expect(startZoomObserver).toHaveBeenCalledTimes(1);
- expect(stopZoomObserver).toHaveBeenCalledTimes(2);
- expect(clearZoomProvider).toHaveBeenCalledTimes(2);
- expect(refreshDocumentIndex).toHaveBeenCalledTimes(1);
- expect(refreshZoomProvider).toHaveBeenCalledTimes(1);
- expect(events).toEqual([
- 'start:replace',
- 'clear-active',
- 'clear-doc',
- 'complete:replace:true',
- 'start:replace',
- 'clear-active',
- 'clear-doc',
- 'complete:replace:true',
- ]);
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
- const error = new Error('facade dispose failed');
- try {
- actions.destroyRenderSession({
- destroy: () => {
- throw error;
- },
- });
- expect(warn).toHaveBeenCalledWith('预览内容卸载失败', error);
- } finally {
- warn.mockRestore();
- }
- });
- it('removes stale render targets and disposes stale sessions during surface mount', async () => {
- const { document } = parseHTML('<main id="root"></main>');
- const root = document.getElementById('root') as HTMLElement;
- const session = { destroy: vi.fn() };
- const state = createFileViewerRenderSurfaceState<typeof session>();
- const readiness = {
- renderedReady: false,
- progressiveReady: false,
- };
- let currentVersion = 1;
- const render = vi.fn(async context => {
- context.target.appendChild(document.createElement('strong'));
- currentVersion = 2;
- return session;
- });
- await expect(runFileViewerRenderSurfaceMount({
- buffer: new ArrayBuffer(4),
- file: new File(['demo'], 'demo.pdf'),
- version: 1,
- getContainer: () => root,
- surfaceState: state,
- readinessState: readiness,
- isCurrent: version => version === currentVersion,
- clearRenderedContent: () => clearFileViewerRenderSurface(root),
- render,
- })).resolves.toBeUndefined();
- expect(render).toHaveBeenCalledTimes(1);
- expect(session.destroy).toHaveBeenCalledTimes(1);
- expect(root.innerHTML).not.toContain('file-render');
- });
- it('safely disposes renderer sessions and reports teardown errors', async () => {
- const onError = vi.fn();
- const syncError = new Error('sync teardown failed');
- const asyncError = new Error('async teardown failed');
- const syncDestroy = vi.fn(() => {
- throw syncError;
- });
- const asyncDestroy = vi.fn(() => Promise.reject(asyncError));
- disposeFileViewerRendererSession({ destroy: syncDestroy }, { onError });
- disposeFileViewerRendererSession({ destroy: asyncDestroy }, { onError });
- disposeFileViewerRendererSession(null, { onError });
- await Promise.resolve();
- expect(FILE_VIEWER_RENDER_SESSION_DISPOSE_ERROR_MESSAGE).toBe('预览内容卸载失败');
- expect(resolveFileViewerRenderSessionDisposeErrorMessage()).toBe('预览内容卸载失败');
- expect(resolveFileViewerRenderSessionDisposeErrorMessage({ message: '自定义卸载失败' })).toBe('自定义卸载失败');
- const loggedDisposeWarnings: Array<[string, unknown]> = [];
- expect(reportFileViewerRenderSessionDisposeError({
- error: syncError,
- onLogError: (message, error) => {
- loggedDisposeWarnings.push([message, error]);
- },
- })).toBe('预览内容卸载失败');
- expect(reportFileViewerRenderSessionDisposeError({
- message: '自定义卸载失败',
- error: asyncError,
- onLogError: (message, error) => {
- loggedDisposeWarnings.push([message, error]);
- },
- })).toBe('自定义卸载失败');
- expect(loggedDisposeWarnings).toEqual([
- ['预览内容卸载失败', syncError],
- ['自定义卸载失败', asyncError],
- ]);
- expect(syncDestroy).toHaveBeenCalledTimes(1);
- expect(asyncDestroy).toHaveBeenCalledTimes(1);
- expect(onError).toHaveBeenCalledWith(syncError);
- expect(onError).toHaveBeenCalledWith(asyncError);
- });
- it('builds renderer registries from legacy render handlers', async () => {
- const unmount = vi.fn();
- const handler: FileRenderHandler<{ unmount: () => void }, HTMLDivElement> = async (_buffer, target, type, context) => {
- target.dataset.renderedType = type || '';
- target.dataset.filename = context?.filename || '';
- return { unmount };
- };
- const target = { dataset: {} } as HTMLDivElement;
- const { registry, missingRendererIds } = createFileRenderHandlerRegistry({
- definitions: [{
- id: 'text-fixture',
- label: 'Text Fixture',
- category: 'code',
- extensions: ['txt-fixture'],
- }],
- handlers: [{
- rendererId: 'text-fixture',
- handler,
- }],
- });
- const renderer = registry.getByExtension('TXT-FIXTURE');
- expect(missingRendererIds).toEqual([]);
- expect(renderer?.load).toBeTypeOf('function');
- const session = await renderer?.load?.({
- source: normalizeSource({
- buffer: new ArrayBuffer(1),
- filename: 'demo.txt-fixture',
- }),
- surface: { container: target },
- options: {},
- });
- expect(target.dataset.renderedType).toBe('txt-fixture');
- expect(target.dataset.filename).toBe('demo.txt-fixture');
- await session?.destroy?.();
- expect(unmount).toHaveBeenCalledTimes(1);
- });
- });
|