diff --git a/scripts/steiger-rules.ts b/scripts/steiger-rules.ts index 4cddfd8bb..a72a3731a 100644 --- a/scripts/steiger-rules.ts +++ b/scripts/steiger-rules.ts @@ -201,8 +201,8 @@ const strictTestFilePlacement = createFileRule('open-pencil/strict-test-file-pla if (sourceRel.startsWith('tests/engine/')) { if (sourceRel.endsWith('.test.ts')) return null if (sourceRel.endsWith('/helpers.ts') || sourceRel.endsWith('.bench.ts')) return null - if (path.basename(sourceRel).startsWith('visual-')) return null - return 'Engine/unit tests must live under tests/engine/** and use *.test.ts; helpers.ts, *.bench.ts, and visual-* support scripts are allowed.' + if (/\/visual\/[^/]+\.ts$/.test(sourceRel)) return null + return 'Engine/unit tests must live under tests/engine/** and use *.test.ts; helpers.ts, *.bench.ts, and domain visual support scripts are allowed.' } if (sourceRel.startsWith('tests/helpers/')) return null return 'Tests must live under tests/e2e/** (*.spec.ts), tests/engine/** (*.test.ts), or tests/helpers/**.' @@ -239,8 +239,13 @@ const noMisplacedEngineTestDomainPaths = createFileRule( 'open-pencil/no-misplaced-engine-test-domain-paths', (sourceRel) => { const redirect = ENGINE_TEST_DOMAIN_REDIRECTS.find(({ from }) => sourceRel.startsWith(from)) - if (!redirect) return null - return `Move tests from ${redirect.from} under ${redirect.to} to mirror ${redirect.source}.` + if (redirect) { + return `Move tests from ${redirect.from} under ${redirect.to} to mirror ${redirect.source}.` + } + if (/^tests\/engine\/[^/]+\.test\.ts$/.test(sourceRel)) { + return 'Move root-level engine tests under a domain folder that mirrors the source module under test.' + } + return null } ) diff --git a/tests/engine/color.test.ts b/tests/engine/color/basic.test.ts similarity index 100% rename from tests/engine/color.test.ts rename to tests/engine/color/basic.test.ts diff --git a/tests/engine/okhcl.test.ts b/tests/engine/color/okhcl/basic.test.ts similarity index 100% rename from tests/engine/okhcl.test.ts rename to tests/engine/color/okhcl/basic.test.ts diff --git a/tests/engine/geometry.test.ts b/tests/engine/geometry/basic.test.ts similarity index 100% rename from tests/engine/geometry.test.ts rename to tests/engine/geometry/basic.test.ts diff --git a/tests/engine/matrix.test.ts b/tests/engine/geometry/matrix.test.ts similarity index 100% rename from tests/engine/matrix.test.ts rename to tests/engine/geometry/matrix.test.ts diff --git a/tests/engine/iconify.test.ts b/tests/engine/icons/iconify.test.ts similarity index 100% rename from tests/engine/iconify.test.ts rename to tests/engine/icons/iconify.test.ts diff --git a/tests/engine/image.test.ts b/tests/engine/images/basic.test.ts similarity index 100% rename from tests/engine/image.test.ts rename to tests/engine/images/basic.test.ts diff --git a/tests/engine/lint.test.ts b/tests/engine/lint/basic.test.ts similarity index 100% rename from tests/engine/lint.test.ts rename to tests/engine/lint/basic.test.ts diff --git a/tests/engine/mcp.test.ts b/tests/engine/mcp/tools.test.ts similarity index 100% rename from tests/engine/mcp.test.ts rename to tests/engine/mcp/tools.test.ts diff --git a/tests/engine/profiler.test.ts b/tests/engine/profiler/basic.test.ts similarity index 100% rename from tests/engine/profiler.test.ts rename to tests/engine/profiler/basic.test.ts diff --git a/tests/engine/random.test.ts b/tests/engine/random/basic.test.ts similarity index 100% rename from tests/engine/random.test.ts rename to tests/engine/random/basic.test.ts diff --git a/tests/engine/render/canvas/silhouette-autopsy.test.ts b/tests/engine/render/canvas/silhouette-autopsy.test.ts index 097120a84..8162b57a4 100644 --- a/tests/engine/render/canvas/silhouette-autopsy.test.ts +++ b/tests/engine/render/canvas/silhouette-autopsy.test.ts @@ -291,8 +291,8 @@ describe('Doc 02 — Formula Deconstruction: Static Code Claims', () => { // ============================================================ describe('Doc 03 — Artifact Analysis: Static + Runtime Verification', () => { - test('C03-01: visual-inner-shadow-counter.ts exists and checks for right-edge shadow', () => { - const visualTestPath = repoTestPath('engine/visual-inner-shadow-counter.ts') + test('C03-01: render visual inner-shadow counter script exists and checks for right-edge shadow', () => { + const visualTestPath = repoTestPath('engine/render/canvas/visual/inner-shadow-counter.ts') const src = readFileSync(visualTestPath, 'utf-8') expect(src).toContain('hasShadowOnRightInnerEdge') expect(src).toContain("t.color === 'black'") diff --git a/tests/engine/visual-inner-shadow-counter.ts b/tests/engine/render/canvas/visual/inner-shadow-counter.ts similarity index 97% rename from tests/engine/visual-inner-shadow-counter.ts rename to tests/engine/render/canvas/visual/inner-shadow-counter.ts index 1ec48ee35..0d049d696 100644 --- a/tests/engine/visual-inner-shadow-counter.ts +++ b/tests/engine/render/canvas/visual/inner-shadow-counter.ts @@ -101,7 +101,7 @@ async function main() { } } - console.log('Transitions at centerY:', transitions) + console.warn('Transitions at centerY:', transitions) // Expected transitions for a physically correct inner shadow (light from left): // 1. blue -> black (left outer edge, shadow starts) @@ -120,7 +120,7 @@ async function main() { const data = image.encodeToBytes(ck.ImageFormat.PNG, 100) if (data) { await Bun.write('scratch/escher-trap-detected.png', data) - console.log('Saved scratch/escher-trap-detected.png') + console.warn('Saved scratch/escher-trap-detected.png') } surface.delete() @@ -131,7 +131,7 @@ async function main() { ) process.exit(1) } else { - console.log( + console.warn( '✅ PASSED: Physically accurate shadow detected on the right inner edge of the counter' ) process.exit(0) diff --git a/tests/engine/visual-sdf-test-matrix.ts b/tests/engine/render/canvas/visual/sdf-test-matrix.ts similarity index 97% rename from tests/engine/visual-sdf-test-matrix.ts rename to tests/engine/render/canvas/visual/sdf-test-matrix.ts index f305ea43b..965ed4fd4 100644 --- a/tests/engine/visual-sdf-test-matrix.ts +++ b/tests/engine/render/canvas/visual/sdf-test-matrix.ts @@ -160,7 +160,7 @@ async function main() { await mkdir(outputDir, { recursive: true }) const matrix = generateMatrix() - console.log(`Generated ${matrix.length} test cases`) + console.warn(`Generated ${matrix.length} test cases`) let generated = 0 let failed = 0 @@ -234,7 +234,7 @@ async function main() { renderer.destroy() } - console.log(`\nResult: ${generated} generated, ${failed} failed out of ${matrix.length}`) + console.warn(`\nResult: ${generated} generated, ${failed} failed out of ${matrix.length}`) } main() diff --git a/tests/engine/visual-verify-text-inner-shadow.ts b/tests/engine/render/canvas/visual/verify-text-inner-shadow.ts similarity index 87% rename from tests/engine/visual-verify-text-inner-shadow.ts rename to tests/engine/render/canvas/visual/verify-text-inner-shadow.ts index 383b1644f..fcf227708 100644 --- a/tests/engine/visual-verify-text-inner-shadow.ts +++ b/tests/engine/render/canvas/visual/verify-text-inner-shadow.ts @@ -19,7 +19,7 @@ async function main() { // Load Inter font from public dir const fontPath = join(process.cwd(), 'public/Inter-SemiBold.ttf') - console.log('Loading font from:', fontPath) + console.warn('Loading font from:', fontPath) const fontData = await readFile(fontPath) fontManager.markLoaded( 'Inter', @@ -62,9 +62,9 @@ async function main() { renderer.fontProvider = fontProvider renderer.fontsLoaded = true - console.log('Node created:', nodeId) - console.log('Font loaded for node:', renderer.isNodeFontLoaded(textNode)) - console.log('Absolute position:', graph.getAbsolutePosition(nodeId)) + console.warn('Node created:', nodeId) + console.warn('Font loaded for node:', renderer.isNodeFontLoaded(textNode)) + console.warn('Absolute position:', graph.getAbsolutePosition(nodeId)) // Render with scale 2 const data = renderNodesToImage(ck, renderer, graph, pageId, [nodeId], { @@ -75,7 +75,7 @@ async function main() { surface.delete() if (data && data.length > 2000) { - console.log(`✅ Generated scratch/text-inner-shadow-verification.png (${data.length} bytes)`) + console.warn(`✅ Generated scratch/text-inner-shadow-verification.png (${data.length} bytes)`) } else { console.error(`❌ Failed to generate useful image (size: ${data?.length ?? 0} bytes)`) if (data) { diff --git a/tests/engine/copy.test.ts b/tests/engine/scene-graph/copy.test.ts similarity index 100% rename from tests/engine/copy.test.ts rename to tests/engine/scene-graph/copy.test.ts diff --git a/tests/engine/mutation.test.ts b/tests/engine/scene-graph/mutation.test.ts similarity index 100% rename from tests/engine/mutation.test.ts rename to tests/engine/scene-graph/mutation.test.ts diff --git a/tests/engine/snap.test.ts b/tests/engine/snap/basic.test.ts similarity index 100% rename from tests/engine/snap.test.ts rename to tests/engine/snap/basic.test.ts diff --git a/tests/engine/xpath.test.ts b/tests/engine/tools/xpath/basic.test.ts similarity index 100% rename from tests/engine/xpath.test.ts rename to tests/engine/tools/xpath/basic.test.ts diff --git a/tests/engine/vector.test.ts b/tests/engine/vector/basic.test.ts similarity index 100% rename from tests/engine/vector.test.ts rename to tests/engine/vector/basic.test.ts diff --git a/tests/engine/centerline.test.ts b/tests/engine/vector/centerline.test.ts similarity index 100% rename from tests/engine/centerline.test.ts rename to tests/engine/vector/centerline.test.ts