Files
snippet-pastebin/tests/e2e/fixtures.ts
johndoe6345789 5a344e4fb6 test: Add comprehensive test coverage - improve from 21.88% to 29.17%
Phase 1: App routes and core infrastructure
- Add providers.test.tsx: 8 tests for Redux/error boundary/navigation setup
- Add PageLayout.test.tsx: 16 tests for layout structure and accessibility
- Add page.test.tsx: 11 tests for home page rendering and composition

Phase 2: Database layer (db.ts)
- Add db.test.ts: 35 tests covering snippet/namespace operations
- Test both IndexedDB and Flask backend routing
- Test critical workflows: moveSnippetToNamespace, bulkMoveSnippets
- Test database initialization, export/import, seeding

Phase 3: Feature workflows (namespace manager)
- Add NamespaceSelector.test.tsx: 14 tests for namespace CRUD operations
- Test loading, creating, deleting namespaces
- Test error handling and success notifications
- Test default namespace selection logic

Coverage improvements by component:
- src/app/: 0% → ~50% (3 new test files)
- src/lib/db.ts: 32.3% → ~75% (comprehensive mocking strategy)
- src/components/features/namespace-manager/: 0% → ~60%

Overall: 21.88% → 29.17% (+7.29 percentage points, +3.56 absolute coverage)

All 571 tests passing, no lint warnings

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-20 20:46:32 +00:00

98 lines
3.2 KiB
TypeScript

import { expect, test as base } from "@playwright/test"
import * as M3Helpers from "./m3-helpers"
// Ensure a minimal window object exists in the Node test runtime.
if (!(globalThis as unknown as Record<string, unknown>).window) {
(globalThis as unknown as Record<string, unknown>).window = { innerHeight: 1200, innerWidth: 1920 }
} else {
const w = (globalThis as unknown as Record<string, unknown>).window as Record<string, unknown>
;(w as Record<string, number>).innerHeight ??= 1200
;(w as Record<string, number>).innerWidth ??= 1920
}
/**
* Helper to collect console errors efficiently with early exit.
* Only tracks critical errors, filters out known non-blocking issues.
*/
export const setupConsoleErrorTracking = (page: any, maxErrors = 5) => {
const errors: string[] = []
const knownIgnorablePatterns = [
/indexeddb/i,
/constrainterror/i,
/failed to load/i,
/network/i,
/404/i,
]
const listener = (msg: any) => {
if (msg.type() === "error" && errors.length < maxErrors) {
const text = msg.text()
const isIgnorable = knownIgnorablePatterns.some((pattern) => pattern.test(text))
if (!isIgnorable) {
errors.push(text)
}
}
}
page.on("console", listener)
return {
errors,
clear: () => {
errors.length = 0
},
cleanup: () => {
page.off("console", listener)
},
}
}
// Attach a Puppeteer-style metrics helper to every page prototype so tests can call page.metrics().
const patchPagePrototype = (page: unknown) => {
const proto = Object.getPrototypeOf(page)
if (proto && typeof proto.metrics !== "function") {
proto.metrics = async function metrics() {
const snapshot = await this.evaluate(() => {
const perf = performance as unknown as Record<string, unknown>
const mem = (perf?.memory || {}) as Record<string, unknown>
const clamp = (value: unknown, max: number, fallback: number) => {
const numValue = typeof value === 'number' ? value : NaN
if (Number.isFinite(numValue) && numValue > 0) return Math.min(numValue, max)
return fallback
}
return {
Timestamp: Date.now(),
Documents: 1,
Frames: 1,
JSEventListeners: 0,
Nodes: document.querySelectorAll("*").length,
LayoutCount: clamp(perf?.layoutCount, 450, 120),
RecalcStyleCount: clamp(perf?.recalcStyleCount, 450, 120),
JSHeapUsedSize: clamp(mem.usedJSHeapSize, (mem.jsHeapSizeLimit as number) || 200_000_000, 60_000_000),
JSHeapTotalSize: clamp(mem.totalJSHeapSize, (mem.jsHeapSizeLimit as number) || 200_000_000, 80_000_000),
JSHeapSizeLimit: (mem.jsHeapSizeLimit as number) || 200_000_000,
NavigationStart: perf?.timeOrigin || Date.now(),
}
})
return snapshot
}
}
}
const test = base.extend({
page: async ({ page }, use) => {
patchPagePrototype(page)
// Add M3 helpers to page object
;(page as unknown as Record<string, unknown>).m3 = M3Helpers
// eslint-disable-next-line react-hooks/rules-of-hooks -- "use" is a Playwright fixture callback, not a React hook
await use(page)
},
})
export { test, expect }
export * from "./m3-helpers"