diff --git a/packages/layout-engine/layout-bridge/bunfig.toml b/packages/layout-engine/layout-bridge/bunfig.toml new file mode 100644 index 0000000000..554f6fb8f2 --- /dev/null +++ b/packages/layout-engine/layout-bridge/bunfig.toml @@ -0,0 +1,2 @@ +[test] +timeout = 5000 diff --git a/packages/layout-engine/layout-bridge/package.json b/packages/layout-engine/layout-bridge/package.json index 3bab37d087..5db5e40de0 100644 --- a/packages/layout-engine/layout-bridge/package.json +++ b/packages/layout-engine/layout-bridge/package.json @@ -16,7 +16,9 @@ ], "scripts": { "build": "tsup src/index.ts --format esm,cjs --dts --clean --tsconfig tsconfig.build.json", - "test": "vitest run", + "test": "bun test $(grep -l \"from 'bun:test'\" test/*.test.ts)", + "test:vitest": "vitest run $(grep -l \"from 'vitest'\" test/*.test.ts)", + "test:all": "pnpm test && pnpm test:vitest", "lint": "eslint src --ext .ts", "dev": "tsup src/index.ts --format esm --watch" }, diff --git a/packages/layout-engine/layout-bridge/test/benchmarks.test.ts b/packages/layout-engine/layout-bridge/test/benchmarks.test.ts index 940cb6ec29..e00f5f8b91 100644 --- a/packages/layout-engine/layout-bridge/test/benchmarks.test.ts +++ b/packages/layout-engine/layout-bridge/test/benchmarks.test.ts @@ -2,7 +2,7 @@ * Tests for TypingPerfBenchmark */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { TypingPerfBenchmark } from '../src/benchmarks'; describe('TypingPerfBenchmark', () => { diff --git a/packages/layout-engine/layout-bridge/test/cache-warmer.test.ts b/packages/layout-engine/layout-bridge/test/cache-warmer.test.ts index da74b0c3d0..67e7c5f7f2 100644 --- a/packages/layout-engine/layout-bridge/test/cache-warmer.test.ts +++ b/packages/layout-engine/layout-bridge/test/cache-warmer.test.ts @@ -2,7 +2,7 @@ * Tests for CacheWarmer */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { CacheWarmer } from '../src/cache-warmer'; import { FontMetricsCache } from '../src/font-metrics-cache'; import { ParagraphLineCache } from '../src/paragraph-line-cache'; diff --git a/packages/layout-engine/layout-bridge/test/cache.test.ts b/packages/layout-engine/layout-bridge/test/cache.test.ts index 63035805f0..305b1939c0 100644 --- a/packages/layout-engine/layout-bridge/test/cache.test.ts +++ b/packages/layout-engine/layout-bridge/test/cache.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { MeasureCache } from '../src/cache'; import type { FlowBlock, ImageRun, TableBlock, TableCell } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/test/cacheInvalidation.test.ts b/packages/layout-engine/layout-bridge/test/cacheInvalidation.test.ts index b685f5f7ec..6b5c05649b 100644 --- a/packages/layout-engine/layout-bridge/test/cacheInvalidation.test.ts +++ b/packages/layout-engine/layout-bridge/test/cacheInvalidation.test.ts @@ -4,7 +4,7 @@ * Tests for cache invalidation logic for headers/footers and body content. */ -import { describe, it, expect, beforeEach, vi } from 'vitest'; +import { describe, it, expect, beforeEach, spyOn } from 'bun:test'; import type { FlowBlock, ParagraphBlock, SectionMetadata } from '@superdoc/contracts'; import type { HeaderFooterConstraints } from '../../layout-engine'; import { @@ -420,7 +420,7 @@ describe('Cache Invalidation', () => { }); it('should invalidate cache when content changes', () => { - const invalidateSpy = vi.spyOn(cache, 'invalidate'); + const invalidateSpy = spyOn(cache, 'invalidate'); const blocks1 = { default: [ @@ -452,7 +452,7 @@ describe('Cache Invalidation', () => { }); it('should invalidate cache when constraints change', () => { - const invalidateSpy = vi.spyOn(cache, 'invalidate'); + const invalidateSpy = spyOn(cache, 'invalidate'); const blocks = { default: [ @@ -485,7 +485,7 @@ describe('Cache Invalidation', () => { }); it('should invalidate cache when section metadata changes', () => { - const invalidateSpy = vi.spyOn(cache, 'invalidate'); + const invalidateSpy = spyOn(cache, 'invalidate'); const blocks = { default: [ @@ -522,7 +522,7 @@ describe('Cache Invalidation', () => { }); it('should not invalidate when nothing has changed', () => { - const invalidateSpy = vi.spyOn(cache, 'invalidate'); + const invalidateSpy = spyOn(cache, 'invalidate'); const blocks = { default: [ @@ -550,7 +550,7 @@ describe('Cache Invalidation', () => { }); it('should invalidate cache when overflowBaseHeight changes', () => { - const invalidateSpy = vi.spyOn(cache, 'invalidate'); + const invalidateSpy = spyOn(cache, 'invalidate'); const blocks = { default: [ diff --git a/packages/layout-engine/layout-bridge/test/clickToPosition.test.ts b/packages/layout-engine/layout-bridge/test/clickToPosition.test.ts index 9de2840e91..67013a7de3 100644 --- a/packages/layout-engine/layout-bridge/test/clickToPosition.test.ts +++ b/packages/layout-engine/layout-bridge/test/clickToPosition.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { clickToPosition, hitTestPage } from '../src/index.ts'; import type { Layout } from '@superdoc/contracts'; import { diff --git a/packages/layout-engine/layout-bridge/test/comment-key.test.ts b/packages/layout-engine/layout-bridge/test/comment-key.test.ts index 437cac51e6..6aa6d9759f 100644 --- a/packages/layout-engine/layout-bridge/test/comment-key.test.ts +++ b/packages/layout-engine/layout-bridge/test/comment-key.test.ts @@ -3,7 +3,7 @@ * Tests the comment hashing logic used for cache invalidation */ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import type { Run } from '@superdoc/contracts'; // Import the internal function for testing diff --git a/packages/layout-engine/layout-bridge/test/computeLinePmRange.test.ts b/packages/layout-engine/layout-bridge/test/computeLinePmRange.test.ts index f7777f8756..42fd1d6256 100644 --- a/packages/layout-engine/layout-bridge/test/computeLinePmRange.test.ts +++ b/packages/layout-engine/layout-bridge/test/computeLinePmRange.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { computeLinePmRange } from '../src/index.ts'; import type { FlowBlock, Line } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/test/diff.test.ts b/packages/layout-engine/layout-bridge/test/diff.test.ts index 04d42da5b7..da8eedfb2d 100644 --- a/packages/layout-engine/layout-bridge/test/diff.test.ts +++ b/packages/layout-engine/layout-bridge/test/diff.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import type { VectorShapeDrawing } from '@superdoc/contracts'; import { computeDirtyRegions } from '../src/diff'; diff --git a/packages/layout-engine/layout-bridge/test/dirty-tracker.test.ts b/packages/layout-engine/layout-bridge/test/dirty-tracker.test.ts index 546e1c288e..27116bc0b1 100644 --- a/packages/layout-engine/layout-bridge/test/dirty-tracker.test.ts +++ b/packages/layout-engine/layout-bridge/test/dirty-tracker.test.ts @@ -2,7 +2,7 @@ * Tests for DirtyTracker */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { DirtyTracker, type DirtyRange } from '../src/dirty-tracker'; describe('DirtyTracker', () => { diff --git a/packages/layout-engine/layout-bridge/test/displayPageTextEndToEnd.test.ts b/packages/layout-engine/layout-bridge/test/displayPageTextEndToEnd.test.ts index 183ecdae54..ef059d9153 100644 --- a/packages/layout-engine/layout-bridge/test/displayPageTextEndToEnd.test.ts +++ b/packages/layout-engine/layout-bridge/test/displayPageTextEndToEnd.test.ts @@ -6,7 +6,7 @@ * the system. */ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import type { Page, HeaderFooterPage, HeaderFooterLayout } from '@superdoc/contracts'; import { getBucketForPageNumber, getBucketRepresentative } from '../src/layoutHeaderFooter'; diff --git a/packages/layout-engine/layout-bridge/test/featureFlags.test.ts b/packages/layout-engine/layout-bridge/test/featureFlags.test.ts index 149b3ad93d..bdaa4c32fc 100644 --- a/packages/layout-engine/layout-bridge/test/featureFlags.test.ts +++ b/packages/layout-engine/layout-bridge/test/featureFlags.test.ts @@ -8,7 +8,7 @@ * different environment variable configurations. */ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { FeatureFlags, isFeatureEnabled, getAllFeatureFlags, type FeatureFlagKey } from '../src/featureFlags'; describe('Feature Flags', () => { diff --git a/packages/layout-engine/layout-bridge/test/footnoteColumnPlacement.test.ts b/packages/layout-engine/layout-bridge/test/footnoteColumnPlacement.test.ts index 34a5e26555..88eba5ba12 100644 --- a/packages/layout-engine/layout-bridge/test/footnoteColumnPlacement.test.ts +++ b/packages/layout-engine/layout-bridge/test/footnoteColumnPlacement.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, mock } from 'bun:test'; import type { FlowBlock, Measure } from '@superdoc/contracts'; import { incrementalLayout } from '../src/incrementalLayout'; @@ -34,7 +34,7 @@ describe('Footnotes in columns', () => { const footnoteOne = makeParagraph('footnote-1-0-paragraph', 'Footnote one', 0); const footnoteTwo = makeParagraph('footnote-2-0-paragraph', 'Footnote two', 0); - const measureBlock = vi.fn(async (block: FlowBlock) => { + const measureBlock = mock(async (block: FlowBlock) => { if (block.kind === 'columnBreak') { return { kind: 'columnBreak' } as Measure; } diff --git a/packages/layout-engine/layout-bridge/test/footnoteSeparatorSpacing.test.ts b/packages/layout-engine/layout-bridge/test/footnoteSeparatorSpacing.test.ts index 6c2636d7d9..4891bc4344 100644 --- a/packages/layout-engine/layout-bridge/test/footnoteSeparatorSpacing.test.ts +++ b/packages/layout-engine/layout-bridge/test/footnoteSeparatorSpacing.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, mock } from 'bun:test'; import type { FlowBlock, Measure } from '@superdoc/contracts'; import { incrementalLayout } from '../src/incrementalLayout'; @@ -43,7 +43,7 @@ const buildLayout = async ({ const dividerHeight = 1; const topPadding = 4; - const measureBlock = vi.fn(async (block: FlowBlock) => { + const measureBlock = mock(async (block: FlowBlock) => { if (block.id.startsWith('footnote-')) { return makeMeasure(footnoteLineHeight); } diff --git a/packages/layout-engine/layout-bridge/test/headerFooterIntegration.test.ts b/packages/layout-engine/layout-bridge/test/headerFooterIntegration.test.ts index fd08136fc0..2c37f9e9a1 100644 --- a/packages/layout-engine/layout-bridge/test/headerFooterIntegration.test.ts +++ b/packages/layout-engine/layout-bridge/test/headerFooterIntegration.test.ts @@ -7,7 +7,7 @@ * 3. Integration with incrementalLayout */ -import { describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, mock } from 'bun:test'; import type { FlowBlock, Measure, ParagraphBlock, TextRun, SectionMetadata } from '@superdoc/contracts'; import { incrementalLayout } from '../src/incrementalLayout'; import type { HeaderFooterBatch } from '../src/layoutHeaderFooter'; @@ -79,7 +79,7 @@ describe('End-to-End Header/Footer Token Resolution', () => { ]; // Mock measureBlock function - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); // Run incremental layout with headers const result = await incrementalLayout( @@ -133,7 +133,7 @@ describe('End-to-End Header/Footer Token Resolution', () => { default: [makePageNumberParagraph('header-large-doc')], }; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await incrementalLayout( [], @@ -187,7 +187,7 @@ describe('End-to-End Header/Footer Token Resolution', () => { default: [makePageNumberParagraph('footer-default')], }; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await incrementalLayout( [], @@ -239,7 +239,7 @@ describe('End-to-End Header/Footer Token Resolution', () => { default: [originalHeaderBlock], }; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); await incrementalLayout( [], @@ -278,7 +278,7 @@ describe('End-to-End Header/Footer Token Resolution', () => { }, ]; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await incrementalLayout( [], @@ -315,7 +315,7 @@ describe('End-to-End Header/Footer Token Resolution', () => { default: [makePageNumberParagraph('header-single')], }; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await incrementalLayout( [], @@ -345,7 +345,7 @@ describe('End-to-End Header/Footer Token Resolution', () => { makeTextParagraph(`body-${i}`, `Content ${i + 1}`), ); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await incrementalLayout( [], diff --git a/packages/layout-engine/layout-bridge/test/headerFooterUtils.test.ts b/packages/layout-engine/layout-bridge/test/headerFooterUtils.test.ts index 7d44000f83..089747cb5a 100644 --- a/packages/layout-engine/layout-bridge/test/headerFooterUtils.test.ts +++ b/packages/layout-engine/layout-bridge/test/headerFooterUtils.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from 'vitest'; +import { describe, expect, it } from 'bun:test'; import type { Layout } from '@superdoc/contracts'; import { defaultHeaderFooterIdentifier, diff --git a/packages/layout-engine/layout-bridge/test/hitTestFragment.test.ts b/packages/layout-engine/layout-bridge/test/hitTestFragment.test.ts index c8207f42ef..6520574724 100644 --- a/packages/layout-engine/layout-bridge/test/hitTestFragment.test.ts +++ b/packages/layout-engine/layout-bridge/test/hitTestFragment.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { hitTestPage, hitTestFragment } from '../src/index.ts'; import { columnsLayout, blocks, measures } from './mock-data'; diff --git a/packages/layout-engine/layout-bridge/test/ime-handler.test.ts b/packages/layout-engine/layout-bridge/test/ime-handler.test.ts index 68507acdf1..f0d961783a 100644 --- a/packages/layout-engine/layout-bridge/test/ime-handler.test.ts +++ b/packages/layout-engine/layout-bridge/test/ime-handler.test.ts @@ -2,7 +2,7 @@ * Tests for ImeHandler */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { ImeHandler } from '../src/ime-handler'; describe('ImeHandler', () => { diff --git a/packages/layout-engine/layout-bridge/test/instrumentation.test.ts b/packages/layout-engine/layout-bridge/test/instrumentation.test.ts index a61d65f139..d9f58b24a3 100644 --- a/packages/layout-engine/layout-bridge/test/instrumentation.test.ts +++ b/packages/layout-engine/layout-bridge/test/instrumentation.test.ts @@ -4,16 +4,16 @@ * Tests for debug logging and metrics collection. */ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import { describe, it, expect, beforeEach, afterEach, spyOn } from 'bun:test'; import { PageTokenLogger, HeaderFooterCacheLogger, MetricsCollector } from '../src/instrumentation'; describe('Instrumentation', () => { - let consoleLogSpy: ReturnType; - let consoleWarnSpy: ReturnType; + let consoleLogSpy: ReturnType; + let consoleWarnSpy: ReturnType; beforeEach(() => { - consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); - consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); + consoleLogSpy = spyOn(console, 'log').mockImplementation(() => {}); + consoleWarnSpy = spyOn(console, 'warn').mockImplementation(() => {}); }); afterEach(() => { diff --git a/packages/layout-engine/layout-bridge/test/layout-coordinator.test.ts b/packages/layout-engine/layout-bridge/test/layout-coordinator.test.ts index 5e728c1210..ca242c5a4c 100644 --- a/packages/layout-engine/layout-bridge/test/layout-coordinator.test.ts +++ b/packages/layout-engine/layout-bridge/test/layout-coordinator.test.ts @@ -2,7 +2,7 @@ * Tests for LayoutCoordinator */ -import { describe, it, expect, beforeEach, vi } from 'vitest'; +import { describe, it, expect, beforeEach, mock, spyOn } from 'bun:test'; import { LayoutCoordinator, type LayoutResult } from '../src/layout-coordinator'; import { Priority } from '../src/layout-scheduler'; import { LayoutVersionManager } from '../src/layout-version-manager'; @@ -10,9 +10,9 @@ import { LayoutVersionManager } from '../src/layout-version-manager'; describe('LayoutCoordinator', () => { let coordinator: LayoutCoordinator; let versionManager: LayoutVersionManager; - let executeP0: ReturnType; - let executeP1: ReturnType; - let executeWorker: ReturnType; + let executeP0: ReturnType; + let executeP1: ReturnType; + let executeWorker: ReturnType; const mockLayout = { pages: [], pageSize: { w: 612, h: 792 } }; @@ -28,9 +28,9 @@ describe('LayoutCoordinator', () => { aborted: false, }; - executeP0 = vi.fn().mockReturnValue(mockResult); - executeP1 = vi.fn().mockResolvedValue(mockResult); - executeWorker = vi.fn().mockResolvedValue(mockResult); + executeP0 = mock(() => mockResult); + executeP1 = mock(() => Promise.resolve(mockResult)); + executeWorker = mock(() => Promise.resolve(mockResult)); coordinator = new LayoutCoordinator({ layoutVersionManager: versionManager, @@ -144,7 +144,7 @@ describe('LayoutCoordinator', () => { describe('version management integration', () => { it('should notify version manager on P0 completion', () => { - const spy = vi.spyOn(versionManager, 'onLayoutComplete'); + const spy = spyOn(versionManager, 'onLayoutComplete'); coordinator.scheduleLayout(1, Priority.P0, { scope: 'paragraph' }); @@ -152,7 +152,7 @@ describe('LayoutCoordinator', () => { }); it('should notify version manager on async completion', async () => { - const spy = vi.spyOn(versionManager, 'onLayoutComplete'); + const spy = spyOn(versionManager, 'onLayoutComplete'); coordinator.scheduleLayout(1, Priority.P1, { scope: 'viewport' }); diff --git a/packages/layout-engine/layout-bridge/test/layout-scheduler.test.ts b/packages/layout-engine/layout-bridge/test/layout-scheduler.test.ts index af4af6c3a4..54222f5f36 100644 --- a/packages/layout-engine/layout-bridge/test/layout-scheduler.test.ts +++ b/packages/layout-engine/layout-bridge/test/layout-scheduler.test.ts @@ -2,7 +2,7 @@ * Tests for LayoutScheduler */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { LayoutScheduler, Priority, type LayoutRequest } from '../src/layout-scheduler'; describe('LayoutScheduler', () => { diff --git a/packages/layout-engine/layout-bridge/test/layout-worker.test.ts b/packages/layout-engine/layout-bridge/test/layout-worker.test.ts index ad885cce0d..61ab888ba6 100644 --- a/packages/layout-engine/layout-bridge/test/layout-worker.test.ts +++ b/packages/layout-engine/layout-bridge/test/layout-worker.test.ts @@ -2,7 +2,7 @@ * Tests for LayoutWorkerManager */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { LayoutWorkerManager } from '../src/layout-worker'; import { Priority } from '../src/layout-scheduler'; diff --git a/packages/layout-engine/layout-bridge/test/layoutHeaderFooterBucketing.test.ts b/packages/layout-engine/layout-bridge/test/layoutHeaderFooterBucketing.test.ts index 92a8c36d9f..2b823bb891 100644 --- a/packages/layout-engine/layout-bridge/test/layoutHeaderFooterBucketing.test.ts +++ b/packages/layout-engine/layout-bridge/test/layoutHeaderFooterBucketing.test.ts @@ -10,7 +10,7 @@ * - Backward compatibility with legacy API */ -import { describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, mock } from 'bun:test'; import type { FlowBlock, Measure, ParagraphBlock, TextRun } from '@superdoc/contracts'; import { layoutHeaderFooterWithCache, @@ -148,7 +148,7 @@ describe('layoutHeaderFooterWithCache - Backward Compatibility', () => { default: [makeBlock('header-1', 'Header text')], }; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -168,7 +168,7 @@ describe('layoutHeaderFooterWithCache - Backward Compatibility', () => { default: [makePageTokenBlock('header-with-tokens')], }; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -196,7 +196,7 @@ describe('layoutHeaderFooterWithCache - No-Token Fast Path', () => { totalPages: 150, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -222,7 +222,7 @@ describe('layoutHeaderFooterWithCache - No-Token Fast Path', () => { totalPages: 50, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -248,7 +248,7 @@ describe('layoutHeaderFooterWithCache - Per-Page Resolution (Small Docs)', () => totalPages: 50, // < 100 pages }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -275,7 +275,7 @@ describe('layoutHeaderFooterWithCache - Per-Page Resolution (Small Docs)', () => totalPages: 10, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -306,7 +306,7 @@ describe('layoutHeaderFooterWithCache - Digit Bucketing (Large Docs)', () => { totalPages: 150, // >= 100 pages }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -337,7 +337,7 @@ describe('layoutHeaderFooterWithCache - Digit Bucketing (Large Docs)', () => { totalPages: 1500, // All 4 buckets needed }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -367,7 +367,7 @@ describe('layoutHeaderFooterWithCache - Digit Bucketing (Large Docs)', () => { totalPages: 250, // Only d1, d2, d3 needed }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -412,7 +412,7 @@ describe('layoutHeaderFooterWithCache - Section-Aware Token Resolution', () => { }; }; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -441,7 +441,7 @@ describe('layoutHeaderFooterWithCache - Section-Aware Token Resolution', () => { }; }; - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, { width: 400, height: 80 }, @@ -468,7 +468,7 @@ describe('layoutHeaderFooterWithCache - Cache Behavior', () => { totalPages: 50, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); // First call await layoutHeaderFooterWithCache( @@ -514,7 +514,7 @@ describe('layoutHeaderFooterWithCache - Cache Behavior', () => { totalPages: 10, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); // First call await layoutHeaderFooterWithCache( @@ -562,7 +562,7 @@ describe('layoutHeaderFooterWithCache - Per-Variant Cloning', () => { totalPages: 5, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); await layoutHeaderFooterWithCache( sections, @@ -588,7 +588,7 @@ describe('layoutHeaderFooterWithCache - Per-Variant Cloning', () => { }); const capturedBlocks: FlowBlock[][] = []; - const measureBlock = vi.fn(async (block: FlowBlock) => { + const measureBlock = mock(async (block: FlowBlock) => { capturedBlocks.push([block]); return makeMeasure(20); }); @@ -624,7 +624,7 @@ describe('layoutHeaderFooterWithCache - Multiple Variants', () => { totalPages: 20, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, @@ -657,7 +657,7 @@ describe('layoutHeaderFooterWithCache - Multiple Variants', () => { totalPages: 50, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, @@ -685,7 +685,7 @@ describe('layoutHeaderFooterWithCache - Edge Cases', () => { totalPages: 10, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, @@ -710,7 +710,7 @@ describe('layoutHeaderFooterWithCache - Edge Cases', () => { totalPages: 1, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, @@ -735,7 +735,7 @@ describe('layoutHeaderFooterWithCache - Edge Cases', () => { totalPages: 10000, // Very large document }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, @@ -764,7 +764,7 @@ describe('layoutHeaderFooterWithCache - Edge Cases', () => { totalPages: 5, }); - const measureBlock = vi.fn(async () => makeMeasure(20)); + const measureBlock = mock(async () => makeMeasure(20)); const result = await layoutHeaderFooterWithCache( sections, diff --git a/packages/layout-engine/layout-bridge/test/list-indent-utils.test.ts b/packages/layout-engine/layout-bridge/test/list-indent-utils.test.ts index 57da7d232e..abb6cc512e 100644 --- a/packages/layout-engine/layout-bridge/test/list-indent-utils.test.ts +++ b/packages/layout-engine/layout-bridge/test/list-indent-utils.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import type { ParagraphBlock } from '@superdoc/contracts'; import { isListItem, diff --git a/packages/layout-engine/layout-bridge/test/local-paragraph-layout.test.ts b/packages/layout-engine/layout-bridge/test/local-paragraph-layout.test.ts index 235264e237..96757d4d4b 100644 --- a/packages/layout-engine/layout-bridge/test/local-paragraph-layout.test.ts +++ b/packages/layout-engine/layout-bridge/test/local-paragraph-layout.test.ts @@ -5,7 +5,7 @@ * @vitest-environment jsdom */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { LocalParagraphLayout } from '../src/local-paragraph-layout'; import { FontMetricsCache } from '../src/font-metrics-cache'; import type { TextRun } from '../src/local-paragraph-layout'; diff --git a/packages/layout-engine/layout-bridge/test/normalizeMargin.test.ts b/packages/layout-engine/layout-bridge/test/normalizeMargin.test.ts index 1e36838e53..be80614116 100644 --- a/packages/layout-engine/layout-bridge/test/normalizeMargin.test.ts +++ b/packages/layout-engine/layout-bridge/test/normalizeMargin.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { normalizeMargin } from '../src/incrementalLayout.js'; /** diff --git a/packages/layout-engine/layout-bridge/test/page-geometry-helper.test.ts b/packages/layout-engine/layout-bridge/test/page-geometry-helper.test.ts index daa5e6cb90..6afbc1e3d8 100644 --- a/packages/layout-engine/layout-bridge/test/page-geometry-helper.test.ts +++ b/packages/layout-engine/layout-bridge/test/page-geometry-helper.test.ts @@ -5,7 +5,7 @@ * and edge cases for mixed page sizes. */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { PageGeometryHelper } from '../src/page-geometry-helper'; import type { Layout } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/test/painterIntegration.test.ts b/packages/layout-engine/layout-bridge/test/painterIntegration.test.ts index ef65d136c1..19d8aa493e 100644 --- a/packages/layout-engine/layout-bridge/test/painterIntegration.test.ts +++ b/packages/layout-engine/layout-bridge/test/painterIntegration.test.ts @@ -6,7 +6,7 @@ * with bucket fallback when exact page matches are not found. */ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { getBucketForPageNumber, getBucketRepresentative, type DigitBucket } from '../src/layoutHeaderFooter'; import type { HeaderFooterLayout, HeaderFooterPage } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/test/paragraph-hash-utils.test.ts b/packages/layout-engine/layout-bridge/test/paragraph-hash-utils.test.ts index 8e3231a42d..975811ed0c 100644 --- a/packages/layout-engine/layout-bridge/test/paragraph-hash-utils.test.ts +++ b/packages/layout-engine/layout-bridge/test/paragraph-hash-utils.test.ts @@ -4,7 +4,7 @@ * @vitest-environment node */ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { hashBorderSpec, hashTableBorderValue, hashTableBorders, hashCellBorders } from '../src/paragraph-hash-utils'; import type { BorderSpec, TableBorders, CellBorders } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/test/paragraph-line-cache.test.ts b/packages/layout-engine/layout-bridge/test/paragraph-line-cache.test.ts index 53e68a1929..41753f99fd 100644 --- a/packages/layout-engine/layout-bridge/test/paragraph-line-cache.test.ts +++ b/packages/layout-engine/layout-bridge/test/paragraph-line-cache.test.ts @@ -2,7 +2,7 @@ * Tests for ParagraphLineCache */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { ParagraphLineCache, type ParagraphLines, type LineInfo } from '../src/paragraph-line-cache'; // Helper to create line info diff --git a/packages/layout-engine/layout-bridge/test/performance-metrics.test.ts b/packages/layout-engine/layout-bridge/test/performance-metrics.test.ts index c9e1e8a1b1..d190e284c5 100644 --- a/packages/layout-engine/layout-bridge/test/performance-metrics.test.ts +++ b/packages/layout-engine/layout-bridge/test/performance-metrics.test.ts @@ -2,7 +2,7 @@ * Tests for PerformanceMetricsCollector */ -import { describe, it, expect, beforeEach, vi } from 'vitest'; +import { describe, it, expect, beforeEach, vi } from 'bun:test'; import { PerformanceMetricsCollector } from '../src/performance-metrics'; describe('PerformanceMetricsCollector', () => { diff --git a/packages/layout-engine/layout-bridge/test/pm-position-validator.test.ts b/packages/layout-engine/layout-bridge/test/pm-position-validator.test.ts index 4d4669fe6e..d2a736bcd3 100644 --- a/packages/layout-engine/layout-bridge/test/pm-position-validator.test.ts +++ b/packages/layout-engine/layout-bridge/test/pm-position-validator.test.ts @@ -2,7 +2,7 @@ * Tests for PmPositionValidator */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { PmPositionValidator } from '../src/pm-position-validator'; import type { FlowBlock } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/test/remeasure.test.ts b/packages/layout-engine/layout-bridge/test/remeasure.test.ts index afc174a89a..fca6c2eb13 100644 --- a/packages/layout-engine/layout-bridge/test/remeasure.test.ts +++ b/packages/layout-engine/layout-bridge/test/remeasure.test.ts @@ -10,7 +10,7 @@ * - Edge cases (empty runs, very narrow widths, whitespace-only content) */ -import { beforeAll, describe, expect, it } from 'vitest'; +import { beforeAll, describe, expect, it } from 'bun:test'; import type { ParagraphBlock, Run, TabStop } from '@superdoc/contracts'; import { remeasureParagraph } from '../src/remeasure.ts'; diff --git a/packages/layout-engine/layout-bridge/test/resolveHeaderFooterTokens.test.ts b/packages/layout-engine/layout-bridge/test/resolveHeaderFooterTokens.test.ts index 5b594610a8..9f49c48841 100644 --- a/packages/layout-engine/layout-bridge/test/resolveHeaderFooterTokens.test.ts +++ b/packages/layout-engine/layout-bridge/test/resolveHeaderFooterTokens.test.ts @@ -4,7 +4,7 @@ * Tests the resolution of page number tokens in header and footer blocks. */ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { resolveHeaderFooterTokens, cloneHeaderFooterBlocks } from '../src/resolveHeaderFooterTokens'; import type { FlowBlock, ParagraphBlock, TextRun } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/test/selectionToRects.test.ts b/packages/layout-engine/layout-bridge/test/selectionToRects.test.ts index 7e57fde36e..caa35f5768 100644 --- a/packages/layout-engine/layout-bridge/test/selectionToRects.test.ts +++ b/packages/layout-engine/layout-bridge/test/selectionToRects.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { selectionToRects, getFragmentAtPosition } from '../src/index.ts'; import type { FlowBlock, Layout, Measure } from '@superdoc/contracts'; import { diff --git a/packages/layout-engine/layout-bridge/test/text-boundaries.test.ts b/packages/layout-engine/layout-bridge/test/text-boundaries.test.ts index 1cb3105148..1aab94677c 100644 --- a/packages/layout-engine/layout-bridge/test/text-boundaries.test.ts +++ b/packages/layout-engine/layout-bridge/test/text-boundaries.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { findWordBoundaries, findParagraphBoundaries } from '../src/index.ts'; import type { FlowBlock } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/test/text-measurement.test.ts b/packages/layout-engine/layout-bridge/test/text-measurement.test.ts index a6131acb30..637f418d55 100644 --- a/packages/layout-engine/layout-bridge/test/text-measurement.test.ts +++ b/packages/layout-engine/layout-bridge/test/text-measurement.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, describe, expect, it } from 'vitest'; +import { beforeAll, describe, expect, it } from 'bun:test'; import type { FlowBlock, Line, Run } from '@superdoc/contracts'; import { findCharacterAtX, measureCharacterX, charOffsetToPm } from '../src/text-measurement.ts'; diff --git a/packages/layout-engine/layout-bridge/test/track-changes-handler.test.ts b/packages/layout-engine/layout-bridge/test/track-changes-handler.test.ts index 2d229c477e..dd795993c6 100644 --- a/packages/layout-engine/layout-bridge/test/track-changes-handler.test.ts +++ b/packages/layout-engine/layout-bridge/test/track-changes-handler.test.ts @@ -2,7 +2,7 @@ * Tests for TrackChangesHandler */ -import { describe, it, expect, beforeEach } from 'vitest'; +import { describe, it, expect, beforeEach } from 'bun:test'; import { TrackChangesHandler, type TrackChangeSpan } from '../src/track-changes-handler'; describe('TrackChangesHandler', () => { diff --git a/packages/layout-engine/layout-bridge/test/tracked-changes-utils.test.ts b/packages/layout-engine/layout-bridge/test/tracked-changes-utils.test.ts index a57d867b19..f4bae5b3d0 100644 --- a/packages/layout-engine/layout-bridge/test/tracked-changes-utils.test.ts +++ b/packages/layout-engine/layout-bridge/test/tracked-changes-utils.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'bun:test'; import { hasTrackedChange, resolveTrackedChangesEnabled } from '../src/tracked-changes-utils'; import type { Run, TextRun, TabRun, TrackedChangeMeta, ParagraphBlock } from '@superdoc/contracts'; diff --git a/packages/layout-engine/layout-bridge/vitest.config.ts b/packages/layout-engine/layout-bridge/vitest.config.ts index 01c02b92b3..71b160bea3 100644 --- a/packages/layout-engine/layout-bridge/vitest.config.ts +++ b/packages/layout-engine/layout-bridge/vitest.config.ts @@ -3,11 +3,29 @@ import baseConfig from '../../../vitest.baseConfig'; const includeBench = process.env.VITEST_BENCH === 'true'; +// Files that must stay on Vitest (use fake timers, DOM, or have circular dependency issues) +const vitestFiles = [ + 'test/cursor-renderer.test.ts', + 'test/debounced-passes.test.ts', + 'test/dom-mapping.test.ts', + 'test/dom-reconciler.test.ts', + 'test/focus-watchdog.test.ts', + 'test/font-metrics-cache.test.ts', + 'test/headerFooterLayout.test.ts', + 'test/layout-epoch.test.ts', + 'test/layout-pipeline.test.ts', + 'test/layout-version-manager.test.ts', + 'test/pm-dom-fallback.test.ts', + 'test/resolveMeasurementConstraints.test.ts', + 'test/safety-net.test.ts', + 'test/table-handler.test.ts', +]; + export default defineConfig({ ...baseConfig, test: { environment: 'node', - include: includeBench ? ['test/**/performance*.test.ts'] : ['test/**/*.test.ts'], + include: includeBench ? ['test/**/performance*.test.ts'] : vitestFiles, exclude: includeBench ? [] : ['test/**/performance*.test.ts'], globals: true, },