diff --git a/lint/plugin.js b/lint/plugin.js index 4a53289ca..479c20e4e 100644 --- a/lint/plugin.js +++ b/lint/plugin.js @@ -384,7 +384,7 @@ const noStaleViteAppPaths = { } } -function createParentRelativeImportRule({ description, applies, message }) { +function createParentRelativeImportRule({ description, applies, message, minDepth = 1 }) { return { meta: { docs: { description } @@ -395,6 +395,8 @@ function createParentRelativeImportRule({ description, applies, message }) { function reportSource(node, source) { if (!source?.startsWith('../')) return + const depth = source.match(/^(?:\.\.\/)+/)?.[0].split('../').length - 1 + if ((depth ?? 0) < minDepth) return if (/^(?:\.\.\/)+package\.json$/.test(source)) return context.report({ node, message }) } @@ -415,6 +417,13 @@ function createParentRelativeImportRule({ description, applies, message }) { } } +const noDeepParentRelativeImports = createParentRelativeImportRule({ + description: 'Disallow deep parent-relative imports — use package/test aliases instead', + applies: () => true, + message: 'Use an import alias instead of path drilling with ../.. imports.', + minDepth: 2 +}) + const noCoreParentRelativeImports = createParentRelativeImportRule({ description: 'Disallow parent-relative imports in core internals — use #core/* aliases', applies: (file) => @@ -1371,6 +1380,7 @@ const plugin = { 'no-legacy-app-imports': noLegacyAppImports, 'no-vue-self-package-imports': noVueSelfPackageImports, 'no-cross-package-source-imports': noCrossPackageSourceImports, + 'no-deep-parent-relative-imports': noDeepParentRelativeImports, 'no-core-parent-relative-imports': noCoreParentRelativeImports, 'no-mcp-parent-relative-imports': noMcpParentRelativeImports, 'no-vue-parent-relative-imports': noVueParentRelativeImports, diff --git a/oxlint.json b/oxlint.json index 045648dc7..154637f72 100644 --- a/oxlint.json +++ b/oxlint.json @@ -8,11 +8,21 @@ }, "rules": { "no-unused-vars": "warn", - "no-console": ["warn", { "allow": ["warn", "error", "debug", "time", "timeEnd"] }], - "eqeqeq": ["error", "always", { "null": "ignore" }], + "no-console": [ + "warn", + { + "allow": ["warn", "error", "debug", "time", "timeEnd"] + } + ], + "eqeqeq": [ + "error", + "always", + { + "null": "ignore" + } + ], "prefer-const": "error", "radix": "error", - "no-restricted-imports": [ "error", { @@ -110,6 +120,7 @@ "open-pencil/no-core-framework-imports": "error", "open-pencil/no-direct-storage-access": "error", "open-pencil/no-legacy-shim-files": "error", + "open-pencil/no-deep-parent-relative-imports": "error", "open-pencil/no-broad-double-cast": "error", "open-pencil/no-unknown-record-double-cast": "error", "open-pencil/no-ts-suppression-comments": "error", @@ -117,7 +128,37 @@ "open-pencil/no-reflect-delete-global-this-outside-tests": "error", "open-pencil/no-core-browser-globals": "error", "open-pencil/no-function-alias-imports": "error", - "open-pencil/max-composition-root-lines": ["error", { "max": 260 }] + "open-pencil/max-composition-root-lines": [ + "error", + { + "max": 260 + } + ], + "open-pencil/no-core-parent-relative-imports": "error", + "open-pencil/no-mcp-parent-relative-imports": "error", + "open-pencil/no-vue-parent-relative-imports": "error", + "open-pencil/no-stale-vite-app-paths": "error", + "open-pencil/no-cli-parent-relative-imports": "error", + "open-pencil/no-root-demo-module": "error", + "open-pencil/no-mcp-core-barrel-imports": "error", + "open-pencil/no-cli-core-barrel-imports": "error", + "open-pencil/no-script-core-barrel-imports": "error", + "open-pencil/no-core-self-package-imports": "error", + "open-pencil/no-inline-prompt-constants": "error", + "open-pencil/no-legacy-app-support-imports": "error", + "open-pencil/no-app-vue-core-barrel-imports": "error", + "open-pencil/no-legacy-test-app-imports": "error", + "open-pencil/no-test-core-source-imports": "error", + "open-pencil/no-direct-graph-emitter-subscriptions": "error", + "open-pencil/no-on-unmounted-in-composition-roots": "error", + "open-pencil/no-composable-state-wrappers": "error", + "open-pencil/prefer-vueuse-intervals": "error", + "open-pencil/prefer-vueuse-timeouts": "error", + "open-pencil/vue-component-file-pascal-case": "error", + "open-pencil/component-namespace-pascal-case": "error", + "open-pencil/non-component-source-directories-kebab-case": "error", + "open-pencil/no-component-root-sibling-folder": "error", + "open-pencil/no-flat-kiwi-modules": "error" }, "overrides": [ { @@ -127,10 +168,21 @@ } }, { - "files": ["**/*.test.ts", "**/*.test.tsx"], + "files": ["tests/**/*.ts", "tests/**/*.tsx"], "rules": { "typescript/no-non-null-assertion": "off", - "open-pencil/no-silent-catch": "off" + "open-pencil/no-silent-catch": "off", + "no-unused-vars": "off", + "no-empty-function": "off", + "unicorn/no-nested-ternary": "off", + "typescript/consistent-type-imports": "off", + "open-pencil/no-inline-named-types": "off", + "no-console": "off", + "max-lines": "off", + "complexity": "off", + "radix": "off", + "prefer-const": "off", + "import/no-duplicates": "off" } }, { @@ -161,6 +213,45 @@ "rules": { "open-pencil/no-raw-console-format": "error" } + }, + { + "files": [ + "tests/engine/copy.test.ts", + "tests/engine/editor/selection/**/*.test.ts", + "tests/engine/fig/**/*.test.ts", + "tests/engine/font-normalize-export.test.ts", + "tests/engine/matrix.test.ts", + "tests/engine/mcp-stdio.test.ts", + "tests/engine/nudge.test.ts", + "tests/engine/okhcl-toggle-conversion.test.ts", + "tests/engine/okhcl-ui-logic.test.ts", + "tests/engine/plugin-data.test.ts", + "tests/engine/render-cache.test.ts", + "tests/engine/render/jsx/**/*.test.ts", + "tests/engine/text-edit-undo.test.ts" + ], + "rules": { + "typescript/no-non-null-assertion": "error" + } + }, + { + "files": ["tests/**/*.spec.ts"], + "rules": { + "typescript/no-non-null-assertion": "off", + "open-pencil/no-silent-catch": "off", + "no-unused-vars": "off", + "no-empty-function": "off", + "unicorn/no-nested-ternary": "off" + } + }, + { + "files": ["scripts/**/*.ts"], + "rules": { + "no-console": "off", + "typescript/no-non-null-assertion": "off", + "open-pencil/no-hand-rolled-color": "off", + "radix": "off" + } } ], "ignorePatterns": ["node_modules", "dist", "desktop", "*.config.*"] diff --git a/oxlint.structure.json b/oxlint.structure.json deleted file mode 100644 index a45edd079..000000000 --- a/oxlint.structure.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "$schema": "./node_modules/oxlint/configuration_schema.json", - "jsPlugins": ["./lint/plugin.js"], - "env": { - "browser": true, - "es2024": true - }, - "overrides": [ - { - "files": ["tests/**/*.ts"], - "rules": { - "no-unused-vars": "off" - } - }, - { - "files": ["packages/core/src/kiwi/kiwi-schema/**"], - "rules": { - "typescript/no-explicit-any": "off" - } - }, - { - "files": [ - "tests/engine/copy.test.ts", - "tests/engine/editor/selection/**/*.test.ts", - "tests/engine/fig/**/*.test.ts", - "tests/engine/font-normalize-export.test.ts", - "tests/engine/matrix.test.ts", - "tests/engine/mcp-stdio.test.ts", - "tests/engine/nudge.test.ts", - "tests/engine/okhcl-toggle-conversion.test.ts", - "tests/engine/okhcl-ui-logic.test.ts", - "tests/engine/plugin-data.test.ts", - "tests/engine/render-cache.test.ts", - "tests/engine/render/jsx/**/*.test.ts", - "tests/engine/text-edit-undo.test.ts" - ], - "rules": { - "typescript/no-non-null-assertion": "error" - } - } - ], - "rules": { - "open-pencil/no-legacy-app-imports": "error", - "open-pencil/no-vue-self-package-imports": "error", - "open-pencil/no-cross-package-source-imports": "error", - "open-pencil/no-core-parent-relative-imports": "error", - "open-pencil/no-mcp-parent-relative-imports": "error", - "open-pencil/no-vue-parent-relative-imports": "error", - "open-pencil/no-stale-vite-app-paths": "error", - "open-pencil/no-cli-parent-relative-imports": "error", - "open-pencil/no-root-demo-module": "error", - "open-pencil/no-mcp-core-barrel-imports": "error", - "open-pencil/no-cli-core-barrel-imports": "error", - "open-pencil/no-script-core-barrel-imports": "error", - "open-pencil/no-core-self-package-imports": "error", - "open-pencil/no-inline-prompt-constants": "error", - "open-pencil/no-legacy-app-support-imports": "error", - "open-pencil/no-app-vue-core-barrel-imports": "error", - "open-pencil/no-app-imports-in-packages": "error", - "open-pencil/no-core-framework-imports": "error", - "open-pencil/no-direct-storage-access": "error", - "open-pencil/no-legacy-shim-files": "error", - "open-pencil/no-legacy-test-app-imports": "error", - "open-pencil/no-test-core-source-imports": "error", - "open-pencil/no-broad-double-cast": "error", - "open-pencil/no-unknown-record-double-cast": "error", - "open-pencil/no-ts-suppression-comments": "error", - "open-pencil/no-function-type": "error", - "open-pencil/no-reflect-delete-global-this-outside-tests": "error", - "typescript/no-explicit-any": "error", - "open-pencil/no-core-browser-globals": "error", - "open-pencil/no-direct-graph-emitter-subscriptions": "error", - "open-pencil/no-on-unmounted-in-composition-roots": "error", - "open-pencil/no-composable-state-wrappers": "error", - "open-pencil/prefer-vueuse-intervals": "error", - "open-pencil/prefer-vueuse-timeouts": "error", - "open-pencil/max-composition-root-lines": ["error", { "max": 260 }], - "open-pencil/vue-component-file-pascal-case": "error", - "open-pencil/component-namespace-pascal-case": "error", - "open-pencil/non-component-source-directories-kebab-case": "error", - "open-pencil/no-component-root-sibling-folder": "error", - "open-pencil/no-flat-kiwi-modules": "error" - }, - "ignorePatterns": ["node_modules", "dist", "desktop"] -} diff --git a/package.json b/package.json index fb1861326..72da397d3 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "preview": "vite preview", "tauri": "tauri", "lint": "bun run lint:structure && oxlint -c oxlint.json --type-aware --type-check src/ packages/core/src/ packages/vue/src/ packages/cli/src/ packages/mcp/src/", - "lint:structure": "oxlint -c oxlint.structure.json vite.config.ts vite/ src/ packages/core/src/ packages/vue/src/ packages/cli/src/ packages/mcp/src/ tests/ scripts/", + "lint:structure": "oxlint -c oxlint.json vite.config.ts vite/ src/ packages/core/src/ packages/vue/src/ packages/cli/src/ packages/mcp/src/ tests/ scripts/", "format": "oxfmt --write src/ packages/core/src/ packages/cli/src/ packages/mcp/src/ packages/vue/src/ tests", "check": "bun run lint && tsgo --noEmit && bun run check:vue", "check:vue": "vue-tsc --noEmit -p tsconfig.json && vue-tsc --noEmit -p packages/vue/tsconfig.json", diff --git a/tests/e2e/app-menu.spec.ts b/tests/e2e/app-menu.spec.ts index 7d248fa37..261a7d60f 100644 --- a/tests/e2e/app-menu.spec.ts +++ b/tests/e2e/app-menu.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/auto-layout.spec.ts b/tests/e2e/auto-layout.spec.ts index b6e37a1b8..caaba798f 100644 --- a/tests/e2e/auto-layout.spec.ts +++ b/tests/e2e/auto-layout.spec.ts @@ -1,8 +1,7 @@ +import { CanvasHelper } from '#tests/helpers/canvas' +import { getSelectedNode, getNodeById } from '#tests/helpers/store' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' -import { getSelectedNode, getNodeById } from '../helpers/store' - let page: Page let canvas: CanvasHelper let frameId: string diff --git a/tests/e2e/autosave.spec.ts b/tests/e2e/autosave.spec.ts index 7b39cc17b..85a38fbf9 100644 --- a/tests/e2e/autosave.spec.ts +++ b/tests/e2e/autosave.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/canvas-manipulation.spec.ts b/tests/e2e/canvas-manipulation.spec.ts index e52b65c37..843e81d20 100644 --- a/tests/e2e/canvas-manipulation.spec.ts +++ b/tests/e2e/canvas-manipulation.spec.ts @@ -1,8 +1,7 @@ +import { CanvasHelper } from '#tests/helpers/canvas' +import { getSelectedIds, getPageChildren, getSelectedNode, getNodeById } from '#tests/helpers/store' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' -import { getSelectedIds, getPageChildren, getSelectedNode, getNodeById } from '../helpers/store' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/chat-panel.spec.ts b/tests/e2e/chat-panel.spec.ts index 8e21dca73..69650c427 100644 --- a/tests/e2e/chat-panel.spec.ts +++ b/tests/e2e/chat-panel.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - const USE_REAL_LLM = process.env.TEST_REAL_LLM === '1' const OPENROUTER_KEY = process.env.OPENROUTER_API_KEY ?? '' diff --git a/tests/e2e/code-panel.spec.ts b/tests/e2e/code-panel.spec.ts index 32dc83fb0..d1282ca97 100644 --- a/tests/e2e/code-panel.spec.ts +++ b/tests/e2e/code-panel.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/color-picker-demo-card.spec.ts b/tests/e2e/color-picker-demo-card.spec.ts index 36904348f..06f7e47a7 100644 --- a/tests/e2e/color-picker-demo-card.spec.ts +++ b/tests/e2e/color-picker-demo-card.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - async function dragSlider( page: Parameters[0]['page'], canvas: CanvasHelper, diff --git a/tests/e2e/color-picker.spec.ts b/tests/e2e/color-picker.spec.ts index 4a09dceda..decfef89c 100644 --- a/tests/e2e/color-picker.spec.ts +++ b/tests/e2e/color-picker.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/components.spec.ts b/tests/e2e/components.spec.ts index 683d5e1ae..34ca4180a 100644 --- a/tests/e2e/components.spec.ts +++ b/tests/e2e/components.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/context-menu.spec.ts b/tests/e2e/context-menu.spec.ts index 471ac2900..40d3d98ab 100644 --- a/tests/e2e/context-menu.spec.ts +++ b/tests/e2e/context-menu.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/copy-paste.spec.ts b/tests/e2e/copy-paste.spec.ts index 8300914cc..4e548d552 100644 --- a/tests/e2e/copy-paste.spec.ts +++ b/tests/e2e/copy-paste.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/corner-stroke-toggles.spec.ts b/tests/e2e/corner-stroke-toggles.spec.ts index 6f4be97ce..063e239c3 100644 --- a/tests/e2e/corner-stroke-toggles.spec.ts +++ b/tests/e2e/corner-stroke-toggles.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/create-shapes.spec.ts b/tests/e2e/create-shapes.spec.ts index 8a6391dc7..be542e77d 100644 --- a/tests/e2e/create-shapes.spec.ts +++ b/tests/e2e/create-shapes.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/design-panel.spec.ts b/tests/e2e/design-panel.spec.ts index 4e8c511b4..6b75e6273 100644 --- a/tests/e2e/design-panel.spec.ts +++ b/tests/e2e/design-panel.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/duplicate-undo.spec.ts b/tests/e2e/duplicate-undo.spec.ts index b2d3416c1..292cc0c93 100644 --- a/tests/e2e/duplicate-undo.spec.ts +++ b/tests/e2e/duplicate-undo.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/effects.spec.ts b/tests/e2e/effects.spec.ts index bed090d88..548d7e467 100644 --- a/tests/e2e/effects.spec.ts +++ b/tests/e2e/effects.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/export.spec.ts b/tests/e2e/export.spec.ts index 47a652f2b..00019673c 100644 --- a/tests/e2e/export.spec.ts +++ b/tests/e2e/export.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/font-settings.spec.ts b/tests/e2e/font-settings.spec.ts index c9f82b5cb..82beb830d 100644 --- a/tests/e2e/font-settings.spec.ts +++ b/tests/e2e/font-settings.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - test('font settings popover is available from typography panel', async ({ page }) => { await page.goto('/') const canvas = new CanvasHelper(page) diff --git a/tests/e2e/frame-overlays.spec.ts b/tests/e2e/frame-overlays.spec.ts index ce6f2c26e..3f4dc7380 100644 --- a/tests/e2e/frame-overlays.spec.ts +++ b/tests/e2e/frame-overlays.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/keyboard-shortcuts.spec.ts b/tests/e2e/keyboard-shortcuts.spec.ts index d12521c94..01722de63 100644 --- a/tests/e2e/keyboard-shortcuts.spec.ts +++ b/tests/e2e/keyboard-shortcuts.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/layers-panel.spec.ts b/tests/e2e/layers-panel.spec.ts index d6a30291e..9123fcaa9 100644 --- a/tests/e2e/layers-panel.spec.ts +++ b/tests/e2e/layers-panel.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/multi-page.spec.ts b/tests/e2e/multi-page.spec.ts index 8cbefc5e8..67baac679 100644 --- a/tests/e2e/multi-page.spec.ts +++ b/tests/e2e/multi-page.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/panels.spec.ts b/tests/e2e/panels.spec.ts index 2244f3066..44f035a0b 100644 --- a/tests/e2e/panels.spec.ts +++ b/tests/e2e/panels.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/perf.spec.ts b/tests/e2e/perf.spec.ts index 48effef0a..7aa861c17 100644 --- a/tests/e2e/perf.spec.ts +++ b/tests/e2e/perf.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - const NODE_COUNT = 500 const ITERATIONS = 200 diff --git a/tests/e2e/properties-panel.spec.ts b/tests/e2e/properties-panel.spec.ts index 21d8c3f45..4b275d9d7 100644 --- a/tests/e2e/properties-panel.spec.ts +++ b/tests/e2e/properties-panel.spec.ts @@ -1,8 +1,7 @@ +import { CanvasHelper } from '#tests/helpers/canvas' +import { getSelectedNode, getPageChildren } from '#tests/helpers/store' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' -import { getSelectedNode, getPageChildren } from '../helpers/store' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/property-visibility.spec.ts b/tests/e2e/property-visibility.spec.ts index 740537dab..4bab3286e 100644 --- a/tests/e2e/property-visibility.spec.ts +++ b/tests/e2e/property-visibility.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/scene-cache.spec.ts b/tests/e2e/scene-cache.spec.ts index 0673f42c0..eaae6ec50 100644 --- a/tests/e2e/scene-cache.spec.ts +++ b/tests/e2e/scene-cache.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - test.describe('SkPicture scene caching', () => { let helper: CanvasHelper diff --git a/tests/e2e/section-tool.spec.ts b/tests/e2e/section-tool.spec.ts index e7ea76339..3ad8839f0 100644 --- a/tests/e2e/section-tool.spec.ts +++ b/tests/e2e/section-tool.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/snap-guides.spec.ts b/tests/e2e/snap-guides.spec.ts index 0037fcb7d..32c2b1402 100644 --- a/tests/e2e/snap-guides.spec.ts +++ b/tests/e2e/snap-guides.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/stroke-picker.spec.ts b/tests/e2e/stroke-picker.spec.ts index 0ad8eda4d..81b389db3 100644 --- a/tests/e2e/stroke-picker.spec.ts +++ b/tests/e2e/stroke-picker.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - async function dragSlider(page: Page, canvas: CanvasHelper, testId: string, ratio: number) { const slider = page.locator(`[data-test-id="${testId}"] input[type="range"]`) const box = await slider.boundingBox() diff --git a/tests/e2e/text-editing.spec.ts b/tests/e2e/text-editing.spec.ts index 7be98ad36..203ae11c6 100644 --- a/tests/e2e/text-editing.spec.ts +++ b/tests/e2e/text-editing.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { expect, test, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/text-formatting.spec.ts b/tests/e2e/text-formatting.spec.ts index 2a5026ae1..b5ae351d7 100644 --- a/tests/e2e/text-formatting.spec.ts +++ b/tests/e2e/text-formatting.spec.ts @@ -1,8 +1,7 @@ +import { CanvasHelper } from '#tests/helpers/canvas' +import { getSelectedNode, getEditingTextId, getNodeById } from '#tests/helpers/store' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' -import { getSelectedNode, getEditingTextId, getNodeById } from '../helpers/store' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/toolbar.spec.ts b/tests/e2e/toolbar.spec.ts index 346a57986..7b398228b 100644 --- a/tests/e2e/toolbar.spec.ts +++ b/tests/e2e/toolbar.spec.ts @@ -1,8 +1,7 @@ +import { CanvasHelper } from '#tests/helpers/canvas' +import { getPageChildren } from '#tests/helpers/store' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' -import { getPageChildren } from '../helpers/store' - let page: Page let canvas: CanvasHelper diff --git a/tests/e2e/variables-dialog.spec.ts b/tests/e2e/variables-dialog.spec.ts index 0abd71525..8b3c01576 100644 --- a/tests/e2e/variables-dialog.spec.ts +++ b/tests/e2e/variables-dialog.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect, type Page } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - let page: Page let canvas: CanvasHelper @@ -63,15 +62,21 @@ test('add variable menu creates non-color variable types', async () => { await page.locator('[data-test-id="variables-add-variable"]').click() await page.locator('[data-test-id="variables-add-float"]').click() - await expect(page.locator('[data-test-id="variable-row"]').filter({ hasText: 'New number' })).toHaveCount(1) + await expect( + page.locator('[data-test-id="variable-row"]').filter({ hasText: 'New number' }) + ).toHaveCount(1) await page.locator('[data-test-id="variables-add-variable"]').click() await page.locator('[data-test-id="variables-add-string"]').click() - await expect(page.locator('[data-test-id="variable-row"]').filter({ hasText: 'New text' })).toHaveCount(1) + await expect( + page.locator('[data-test-id="variable-row"]').filter({ hasText: 'New text' }) + ).toHaveCount(1) await page.locator('[data-test-id="variables-add-variable"]').click() await page.locator('[data-test-id="variables-add-boolean"]').click() - await expect(page.locator('[data-test-id="variable-row"]').filter({ hasText: 'New boolean' })).toHaveCount(1) + await expect( + page.locator('[data-test-id="variable-row"]').filter({ hasText: 'New boolean' }) + ).toHaveCount(1) canvas.assertNoErrors() }) diff --git a/tests/e2e/zoom-pan.spec.ts b/tests/e2e/zoom-pan.spec.ts index a4d4ad270..1c4525d74 100644 --- a/tests/e2e/zoom-pan.spec.ts +++ b/tests/e2e/zoom-pan.spec.ts @@ -1,7 +1,6 @@ +import { CanvasHelper } from '#tests/helpers/canvas' import { test, expect } from '@playwright/test' -import { CanvasHelper } from '../helpers/canvas' - const NODE_COUNT = 200 test.describe('Zoom and pan', () => { diff --git a/tests/engine/acp-permission.test.ts b/tests/engine/acp-permission.test.ts index 2ea9c8b80..7d1eb6e76 100644 --- a/tests/engine/acp-permission.test.ts +++ b/tests/engine/acp-permission.test.ts @@ -6,7 +6,7 @@ import { requestPermissionFromUser, respondToPermission, rejectCurrentPermission -} from '../../src/app/ai/acp/permission' +} from '@/app/ai/acp/permission' import type { RequestPermissionRequest } from '@agentclientprotocol/sdk' diff --git a/tests/engine/acp-transport.test.ts b/tests/engine/acp-transport.test.ts index ba7de2987..bf7649ef0 100644 --- a/tests/engine/acp-transport.test.ts +++ b/tests/engine/acp-transport.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from 'bun:test' -import { mapUpdate } from '../../src/app/ai/acp/map-update' -import { formatConnectionError, buildCrashChunks } from '../../src/app/ai/acp/transport' +import { mapUpdate } from '@/app/ai/acp/map-update' +import { formatConnectionError, buildCrashChunks } from '@/app/ai/acp/transport' import type { SessionUpdate } from '@agentclientprotocol/sdk' diff --git a/tests/engine/copy.test.ts b/tests/engine/copy.test.ts index 583163671..43926b05a 100644 --- a/tests/engine/copy.test.ts +++ b/tests/engine/copy.test.ts @@ -8,8 +8,7 @@ import { copyStyleRun, copyGeometryPaths } from '#core/scene-graph/copy' - -import { expectDefined } from '../helpers/assert' +import { expectDefined } from '#tests/helpers/assert' import type { Fill, Stroke, Effect, StyleRun, GeometryPath } from '@open-pencil/core' diff --git a/tests/engine/editor-store-path.test.ts b/tests/engine/editor-store-path.test.ts index 2d8f8d4ad..e82485e06 100644 --- a/tests/engine/editor-store-path.test.ts +++ b/tests/engine/editor-store-path.test.ts @@ -1,6 +1,6 @@ import { describe, test, expect } from 'bun:test' -import { createEditorStore } from '../../src/app/editor/session' +import { createEditorStore } from '@/app/editor/session' describe('setPlannedFilePath', () => { test('sets document name from file path', () => { diff --git a/tests/engine/editor/clipboard/import-nodes.test.ts b/tests/engine/editor/clipboard/import-nodes.test.ts index 58ce3cfb3..8b5b26e52 100644 --- a/tests/engine/editor/clipboard/import-nodes.test.ts +++ b/tests/engine/editor/clipboard/import-nodes.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it } from 'bun:test' -import { importClipboardNodes } from '@open-pencil/core' +import { createClipboardGraph } from '#tests/helpers/clipboard' -import { createClipboardGraph } from '../../../helpers/clipboard' +import { importClipboardNodes } from '@open-pencil/core' import type { NodeChange, SceneNode } from '@open-pencil/core' diff --git a/tests/engine/editor/selection/alignment.test.ts b/tests/engine/editor/selection/alignment.test.ts index aa8321c79..996c755cc 100644 --- a/tests/engine/editor/selection/alignment.test.ts +++ b/tests/engine/editor/selection/alignment.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from 'bun:test' -import { SceneGraph } from '@open-pencil/core' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' +import { createRect, firstPageId } from '#tests/helpers/scene' -import { expectDefined, getNodeOrThrow } from '../../../helpers/assert' -import { createRect, firstPageId } from '../../../helpers/scene' +import { SceneGraph } from '@open-pencil/core' describe('single-node alignment to parent', () => { function setup() { diff --git a/tests/engine/editor/selection/flip.test.ts b/tests/engine/editor/selection/flip.test.ts index 8f93ba50d..c10785887 100644 --- a/tests/engine/editor/selection/flip.test.ts +++ b/tests/engine/editor/selection/flip.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from 'bun:test' -import { SceneGraph } from '@open-pencil/core' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' +import { createRect, firstPageId } from '#tests/helpers/scene' -import { expectDefined, getNodeOrThrow } from '../../../helpers/assert' -import { createRect, firstPageId } from '../../../helpers/scene' +import { SceneGraph } from '@open-pencil/core' describe('flip', () => { test('flipX defaults to false', () => { diff --git a/tests/engine/editor/selection/properties.test.ts b/tests/engine/editor/selection/properties.test.ts index db4488044..36b3d2ce1 100644 --- a/tests/engine/editor/selection/properties.test.ts +++ b/tests/engine/editor/selection/properties.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from 'bun:test' -import { SceneGraph } from '@open-pencil/core' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' +import { createRect, firstPageId } from '#tests/helpers/scene' -import { expectDefined, getNodeOrThrow } from '../../../helpers/assert' -import { createRect, firstPageId } from '../../../helpers/scene' +import { SceneGraph } from '@open-pencil/core' describe('multi-node property merging', () => { test('same values merge to single value', () => { diff --git a/tests/engine/eval-cli.test.ts b/tests/engine/eval-cli.test.ts index 35fc01c24..11b92e28d 100644 --- a/tests/engine/eval-cli.test.ts +++ b/tests/engine/eval-cli.test.ts @@ -3,12 +3,13 @@ import { randomUUID } from 'crypto' import { tmpdir } from 'os' import { join } from 'path' -import { heavy } from '../helpers/test-utils' +import { cliSourcePath, repoPath } from '#tests/helpers/paths' +import { heavy } from '#tests/helpers/test-utils' setDefaultTimeout(30_000) -const CLI = join(import.meta.dir, '../../packages/cli/src/index.ts') -const FIXTURE = join(import.meta.dir, '../fixtures/gold-preview.fig') +const CLI = cliSourcePath('index.ts') +const FIXTURE = repoPath('tests/fixtures/gold-preview.fig') async function run( args: string[], diff --git a/tests/engine/external-link.test.ts b/tests/engine/external-link.test.ts index c2d8b3cad..9ac1d80a7 100644 --- a/tests/engine/external-link.test.ts +++ b/tests/engine/external-link.test.ts @@ -1,8 +1,8 @@ import { describe, test, expect, vi, beforeEach, afterEach } from 'bun:test' -import { openExternalLink } from '@/app/shell/ui' +import { clearTauriMocks, mockTauriIPC } from '#tests/helpers/tauri-mocks' -import { clearTauriMocks, mockTauriIPC } from '../helpers/tauri-mocks' +import { openExternalLink } from '@/app/shell/ui' /** * Tests for the browser (window.open) path only. diff --git a/tests/engine/fig-export-worker.test.ts b/tests/engine/fig-export-worker.test.ts index 37b42731d..c65d930bf 100644 --- a/tests/engine/fig-export-worker.test.ts +++ b/tests/engine/fig-export-worker.test.ts @@ -2,6 +2,8 @@ import { describe, test, expect, beforeAll, setDefaultTimeout } from 'bun:test' import { readFileSync } from 'fs' import { resolve } from 'path' +import { heavy } from '#tests/helpers/test-utils' + import { parseFigFile, exportFigFile, @@ -10,8 +12,6 @@ import { SceneGraph } from '@open-pencil/core' -import { heavy } from '../helpers/test-utils' - setDefaultTimeout(30_000) const FIXTURES = resolve(import.meta.dir, '../fixtures') diff --git a/tests/engine/fig/export/text.test.ts b/tests/engine/fig/export/text.test.ts index 9492b30c1..c6000f183 100644 --- a/tests/engine/fig/export/text.test.ts +++ b/tests/engine/fig/export/text.test.ts @@ -1,6 +1,21 @@ import { beforeAll, describe, expect, setDefaultTimeout, test } from 'bun:test' import { computeContentBounds } from '#core/io/formats/raster/render' +import { expectDefined } from '#tests/helpers/assert' +import { + FIXTURES, + parseFixture, + parseGoldPreviewFixture, + VALID_NODE_TYPES +} from '#tests/helpers/fig-fixtures' +import { + childMatching, + childNamed, + collectAllNodes, + countByType, + previewChild +} from '#tests/helpers/fig-traversal' +import { heavy } from '#tests/helpers/test-utils' import { parseFigFile, @@ -14,22 +29,6 @@ import { type Fill } from '@open-pencil/core' -import { expectDefined } from '../../../helpers/assert' -import { - FIXTURES, - parseFixture, - parseGoldPreviewFixture, - VALID_NODE_TYPES -} from '../../../helpers/fig-fixtures' -import { - childMatching, - childNamed, - collectAllNodes, - countByType, - previewChild -} from '../../../helpers/fig-traversal' -import { heavy } from '../../../helpers/test-utils' - setDefaultTimeout(60_000) describe('text node export', () => { @@ -86,8 +85,7 @@ describe('text node export', () => { await initCodec() const { unzipSync, inflateSync } = await import('fflate') - const { decodeBinarySchema, compileSchema, ByteBuffer } = - await import('../../../../packages/core/src/kiwi/kiwi-schema') + const { decodeBinarySchema, compileSchema, ByteBuffer } = await import('#core/kiwi/kiwi-schema') const { parseFigKiwiChunks } = await import('@open-pencil/core') const graph = new SceneGraph() @@ -146,8 +144,7 @@ describe('text node export', () => { await initCodec() const { unzipSync, inflateSync } = await import('fflate') - const { decodeBinarySchema, compileSchema, ByteBuffer } = - await import('../../../../packages/core/src/kiwi/kiwi-schema') + const { decodeBinarySchema, compileSchema, ByteBuffer } = await import('#core/kiwi/kiwi-schema') const { parseFigKiwiChunks } = await import('@open-pencil/core') const graph = new SceneGraph() diff --git a/tests/engine/fig/heavy/fixtures.test.ts b/tests/engine/fig/heavy/fixtures.test.ts index 7e62bfe11..9119f2d55 100644 --- a/tests/engine/fig/heavy/fixtures.test.ts +++ b/tests/engine/fig/heavy/fixtures.test.ts @@ -1,6 +1,20 @@ import { beforeAll, describe, expect, setDefaultTimeout, test } from 'bun:test' import { computeContentBounds } from '#core/io/formats/raster/render' +import { expectDefined } from '#tests/helpers/assert' +import { + parseFixture, + parseGoldPreviewFixture, + VALID_NODE_TYPES +} from '#tests/helpers/fig-fixtures' +import { + childMatching, + childNamed, + collectAllNodes, + countByType, + previewChild +} from '#tests/helpers/fig-traversal' +import { heavy } from '#tests/helpers/test-utils' import { parseFigFile, @@ -14,21 +28,6 @@ import { type Fill } from '@open-pencil/core' -import { expectDefined } from '../../../helpers/assert' -import { - parseFixture, - parseGoldPreviewFixture, - VALID_NODE_TYPES -} from '../../../helpers/fig-fixtures' -import { - childMatching, - childNamed, - collectAllNodes, - countByType, - previewChild -} from '../../../helpers/fig-traversal' -import { heavy } from '../../../helpers/test-utils' - setDefaultTimeout(60_000) heavy('parse heavy .fig files', () => { diff --git a/tests/engine/fig/import/basic.test.ts b/tests/engine/fig/import/basic.test.ts index 162e2e39d..30d389a7d 100644 --- a/tests/engine/fig/import/basic.test.ts +++ b/tests/engine/fig/import/basic.test.ts @@ -1,6 +1,21 @@ import { beforeAll, describe, expect, setDefaultTimeout, test } from 'bun:test' import { computeContentBounds } from '#core/io/formats/raster/render' +import { expectDefined } from '#tests/helpers/assert' +import { + FIXTURES, + parseFixture, + parseGoldPreviewFixture, + VALID_NODE_TYPES +} from '#tests/helpers/fig-fixtures' +import { + childMatching, + childNamed, + collectAllNodes, + countByType, + previewChild +} from '#tests/helpers/fig-traversal' +import { heavy } from '#tests/helpers/test-utils' import { parseFigFile, @@ -14,22 +29,6 @@ import { type Fill } from '@open-pencil/core' -import { expectDefined } from '../../../helpers/assert' -import { - FIXTURES, - parseFixture, - parseGoldPreviewFixture, - VALID_NODE_TYPES -} from '../../../helpers/fig-fixtures' -import { - childMatching, - childNamed, - collectAllNodes, - countByType, - previewChild -} from '../../../helpers/fig-traversal' -import { heavy } from '../../../helpers/test-utils' - setDefaultTimeout(60_000) let parsed: SceneGraph diff --git a/tests/engine/fig/import/edge-cases.test.ts b/tests/engine/fig/import/edge-cases.test.ts index 68b602dfc..3bb448154 100644 --- a/tests/engine/fig/import/edge-cases.test.ts +++ b/tests/engine/fig/import/edge-cases.test.ts @@ -1,6 +1,21 @@ import { beforeAll, describe, expect, setDefaultTimeout, test } from 'bun:test' import { computeContentBounds } from '#core/io/formats/raster/render' +import { expectDefined } from '#tests/helpers/assert' +import { + FIXTURES, + parseFixture, + parseGoldPreviewFixture, + VALID_NODE_TYPES +} from '#tests/helpers/fig-fixtures' +import { + childMatching, + childNamed, + collectAllNodes, + countByType, + previewChild +} from '#tests/helpers/fig-traversal' +import { heavy } from '#tests/helpers/test-utils' import { parseFigFile, @@ -14,22 +29,6 @@ import { type Fill } from '@open-pencil/core' -import { expectDefined } from '../../../helpers/assert' -import { - FIXTURES, - parseFixture, - parseGoldPreviewFixture, - VALID_NODE_TYPES -} from '../../../helpers/fig-fixtures' -import { - childMatching, - childNamed, - collectAllNodes, - countByType, - previewChild -} from '../../../helpers/fig-traversal' -import { heavy } from '../../../helpers/test-utils' - setDefaultTimeout(60_000) describe('edge cases', () => { diff --git a/tests/engine/fig/import/instance-regressions.test.ts b/tests/engine/fig/import/instance-regressions.test.ts index 063678454..d0fecf202 100644 --- a/tests/engine/fig/import/instance-regressions.test.ts +++ b/tests/engine/fig/import/instance-regressions.test.ts @@ -1,6 +1,21 @@ import { beforeAll, describe, expect, setDefaultTimeout, test } from 'bun:test' import { computeContentBounds } from '#core/io/formats/raster/render' +import { expectDefined } from '#tests/helpers/assert' +import { + FIXTURES, + parseFixture, + parseGoldPreviewFixture, + VALID_NODE_TYPES +} from '#tests/helpers/fig-fixtures' +import { + childMatching, + childNamed, + collectAllNodes, + countByType, + previewChild +} from '#tests/helpers/fig-traversal' +import { heavy } from '#tests/helpers/test-utils' import { parseFigFile, @@ -14,22 +29,6 @@ import { type Fill } from '@open-pencil/core' -import { expectDefined } from '../../../helpers/assert' -import { - FIXTURES, - parseFixture, - parseGoldPreviewFixture, - VALID_NODE_TYPES -} from '../../../helpers/fig-fixtures' -import { - childMatching, - childNamed, - collectAllNodes, - countByType, - previewChild -} from '../../../helpers/fig-traversal' -import { heavy } from '../../../helpers/test-utils' - setDefaultTimeout(60_000) let parsed: SceneGraph diff --git a/tests/engine/fig/import/property-integrity.test.ts b/tests/engine/fig/import/property-integrity.test.ts index cdcafd7f0..120d54347 100644 --- a/tests/engine/fig/import/property-integrity.test.ts +++ b/tests/engine/fig/import/property-integrity.test.ts @@ -1,6 +1,20 @@ import { beforeAll, describe, expect, setDefaultTimeout, test } from 'bun:test' import { computeContentBounds } from '#core/io/formats/raster/render' +import { expectDefined } from '#tests/helpers/assert' +import { + parseFixture, + parseGoldPreviewFixture, + VALID_NODE_TYPES +} from '#tests/helpers/fig-fixtures' +import { + childMatching, + childNamed, + collectAllNodes, + countByType, + previewChild +} from '#tests/helpers/fig-traversal' +import { heavy } from '#tests/helpers/test-utils' import { parseFigFile, @@ -14,21 +28,6 @@ import { type Fill } from '@open-pencil/core' -import { expectDefined } from '../../../helpers/assert' -import { - parseFixture, - parseGoldPreviewFixture, - VALID_NODE_TYPES -} from '../../../helpers/fig-fixtures' -import { - childMatching, - childNamed, - collectAllNodes, - countByType, - previewChild -} from '../../../helpers/fig-traversal' -import { heavy } from '../../../helpers/test-utils' - setDefaultTimeout(60_000) let parsed: SceneGraph diff --git a/tests/engine/fig/roundtrip/basic.test.ts b/tests/engine/fig/roundtrip/basic.test.ts index 172d25b99..f8fc4fb9b 100644 --- a/tests/engine/fig/roundtrip/basic.test.ts +++ b/tests/engine/fig/roundtrip/basic.test.ts @@ -1,6 +1,21 @@ import { beforeAll, describe, expect, setDefaultTimeout, test } from 'bun:test' import { computeContentBounds } from '#core/io/formats/raster/render' +import { expectDefined } from '#tests/helpers/assert' +import { + FIXTURES, + parseFixture, + parseGoldPreviewFixture, + VALID_NODE_TYPES +} from '#tests/helpers/fig-fixtures' +import { + childMatching, + childNamed, + collectAllNodes, + countByType, + previewChild +} from '#tests/helpers/fig-traversal' +import { heavy } from '#tests/helpers/test-utils' import { parseFigFile, @@ -14,22 +29,6 @@ import { type Fill } from '@open-pencil/core' -import { expectDefined } from '../../../helpers/assert' -import { - FIXTURES, - parseFixture, - parseGoldPreviewFixture, - VALID_NODE_TYPES -} from '../../../helpers/fig-fixtures' -import { - childMatching, - childNamed, - collectAllNodes, - countByType, - previewChild -} from '../../../helpers/fig-traversal' -import { heavy } from '../../../helpers/test-utils' - setDefaultTimeout(60_000) describe('roundtrip: export → re-import', () => { diff --git a/tests/engine/fig/roundtrip/variables.test.ts b/tests/engine/fig/roundtrip/variables.test.ts index dd74601a7..a5c3fa0a1 100644 --- a/tests/engine/fig/roundtrip/variables.test.ts +++ b/tests/engine/fig/roundtrip/variables.test.ts @@ -1,6 +1,21 @@ import { beforeAll, describe, expect, setDefaultTimeout, test } from 'bun:test' import { computeContentBounds } from '#core/io/formats/raster/render' +import { expectDefined } from '#tests/helpers/assert' +import { + FIXTURES, + parseFixture, + parseGoldPreviewFixture, + VALID_NODE_TYPES +} from '#tests/helpers/fig-fixtures' +import { + childMatching, + childNamed, + collectAllNodes, + countByType, + previewChild +} from '#tests/helpers/fig-traversal' +import { heavy } from '#tests/helpers/test-utils' import { parseFigFile, @@ -14,22 +29,6 @@ import { type Fill } from '@open-pencil/core' -import { expectDefined } from '../../../helpers/assert' -import { - FIXTURES, - parseFixture, - parseGoldPreviewFixture, - VALID_NODE_TYPES -} from '../../../helpers/fig-fixtures' -import { - childMatching, - childNamed, - collectAllNodes, - countByType, - previewChild -} from '../../../helpers/fig-traversal' -import { heavy } from '../../../helpers/test-utils' - setDefaultTimeout(60_000) describe('variable roundtrip', () => { diff --git a/tests/engine/font-normalize-export.test.ts b/tests/engine/font-normalize-export.test.ts index 4e9a39b68..ff5ca38f9 100644 --- a/tests/engine/font-normalize-export.test.ts +++ b/tests/engine/font-normalize-export.test.ts @@ -1,8 +1,8 @@ import { describe, test, expect, beforeAll } from 'bun:test' -import { exportFigFile, parseFigFile, initCodec, SceneGraph } from '@open-pencil/core' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' -import { expectDefined, getNodeOrThrow } from '../helpers/assert' +import { exportFigFile, parseFigFile, initCodec, SceneGraph } from '@open-pencil/core' beforeAll(async () => { await initCodec() diff --git a/tests/engine/fonts.test.ts b/tests/engine/fonts.test.ts index 0af267478..b190a28f6 100644 --- a/tests/engine/fonts.test.ts +++ b/tests/engine/fonts.test.ts @@ -13,6 +13,7 @@ import { fontFallbackEntry, fontFallbackManifest } from '@open-pencil/core' + import type { CanvasKit, TypefaceFontProvider } from 'canvaskit-wasm' function pageId(graph: SceneGraph) { diff --git a/tests/engine/layout/auto-layout.test.ts b/tests/engine/layout/auto-layout.test.ts index 74b39c8f8..4243ea4ce 100644 --- a/tests/engine/layout/auto-layout.test.ts +++ b/tests/engine/layout/auto-layout.test.ts @@ -1,5 +1,7 @@ import { describe, expect, test } from 'bun:test' +import { autoFrame, loadFixtureGraph, pageId, rect } from '#tests/helpers/layout' + import { createEditorStore } from '@/app/editor/session' import { computeLayout, @@ -10,8 +12,6 @@ import { setTextMeasurer } from '@open-pencil/core' -import { autoFrame, loadFixtureGraph, pageId, rect } from '../../helpers/layout' - describe('Auto Layout', () => { describe('horizontal basic', () => { test('positions children left-to-right', () => { diff --git a/tests/engine/layout/grid-layout.test.ts b/tests/engine/layout/grid-layout.test.ts index be869af6b..496ae7570 100644 --- a/tests/engine/layout/grid-layout.test.ts +++ b/tests/engine/layout/grid-layout.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from 'bun:test' -import { computeLayout, computeAllLayouts, FigmaAPI, SceneGraph } from '@open-pencil/core' +import { autoFrame, fixed, fr, gridFrame, pageId, rect } from '#tests/helpers/layout' -import { autoFrame, fixed, fr, gridFrame, pageId, rect } from '../../helpers/layout' +import { computeLayout, computeAllLayouts, FigmaAPI, SceneGraph } from '@open-pencil/core' describe('Grid Layout', () => { describe('basic grid', () => { diff --git a/tests/engine/matrix.test.ts b/tests/engine/matrix.test.ts index a06a678ba..a33a8c02b 100644 --- a/tests/engine/matrix.test.ts +++ b/tests/engine/matrix.test.ts @@ -7,9 +7,9 @@ */ import { describe, test, expect } from 'bun:test' -import { TransformMatrix } from '@open-pencil/core' +import { expectDefined } from '#tests/helpers/assert' -import { expectDefined } from '../helpers/assert' +import { TransformMatrix } from '@open-pencil/core' describe('TransformMatrix.identity', () => { test('produces a 3x3 identity matrix', () => { diff --git a/tests/engine/mcp-stdio.test.ts b/tests/engine/mcp-stdio.test.ts index cac326c9e..b65c440a7 100644 --- a/tests/engine/mcp-stdio.test.ts +++ b/tests/engine/mcp-stdio.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test, beforeEach, afterEach } from 'bun:test' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' import { WebSocketServer, type WebSocket } from 'ws' import { @@ -10,8 +11,6 @@ import { executeRpcCommand } from '@open-pencil/core' -import { expectDefined, getNodeOrThrow } from '../helpers/assert' - import type { Client } from '@modelcontextprotocol/sdk/client/index.js' import type { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js' import type { AddressInfo } from 'node:net' diff --git a/tests/engine/nudge.test.ts b/tests/engine/nudge.test.ts index 6b01d1952..b23bceac4 100644 --- a/tests/engine/nudge.test.ts +++ b/tests/engine/nudge.test.ts @@ -1,8 +1,8 @@ import { describe, test, expect } from 'bun:test' -import { createEditor } from '@open-pencil/core/editor' +import { getNodeOrThrow } from '#tests/helpers/assert' -import { getNodeOrThrow } from '../helpers/assert' +import { createEditor } from '@open-pencil/core/editor' describe('nudgeSelected', () => { function setup() { diff --git a/tests/engine/okhcl-toggle-conversion.test.ts b/tests/engine/okhcl-toggle-conversion.test.ts index 5dcaec96d..3ce7b6488 100644 --- a/tests/engine/okhcl-toggle-conversion.test.ts +++ b/tests/engine/okhcl-toggle-conversion.test.ts @@ -1,5 +1,7 @@ import { describe, expect, test } from 'bun:test' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' + import { clearNodeFillOkHCL, colorDistance, @@ -9,8 +11,6 @@ import { setNodeFillOkHCL } from '@open-pencil/core' -import { expectDefined, getNodeOrThrow } from '../helpers/assert' - describe('OkHCL toggle conversion', () => { test('enabling OkHCL from an existing rgba fill preserves the visible color closely', () => { const graph = new SceneGraph() diff --git a/tests/engine/okhcl-ui-logic.test.ts b/tests/engine/okhcl-ui-logic.test.ts index 4fcba5a1b..e8d6aad35 100644 --- a/tests/engine/okhcl-ui-logic.test.ts +++ b/tests/engine/okhcl-ui-logic.test.ts @@ -1,5 +1,7 @@ import { describe, expect, test } from 'bun:test' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' + import { clearNodeFillOkHCL, clearNodeStrokeOkHCL, @@ -10,8 +12,6 @@ import { setNodeStrokeOkHCL } from '@open-pencil/core' -import { expectDefined, getNodeOrThrow } from '../helpers/assert' - describe('OkHCL metadata toggling', () => { test('can disable fill OkHCL metadata', () => { const graph = new SceneGraph() diff --git a/tests/engine/plugin-data.test.ts b/tests/engine/plugin-data.test.ts index 31ce04bcf..0c7d1fb33 100644 --- a/tests/engine/plugin-data.test.ts +++ b/tests/engine/plugin-data.test.ts @@ -1,6 +1,7 @@ import { describe, expect, test } from 'bun:test' import { deduplicateNodeChangePluginData } from '#core/kiwi' +import { expectDefined } from '#tests/helpers/assert' import { exportFigFile, @@ -12,8 +13,6 @@ import { type NodeChange } from '@open-pencil/core' -import { expectDefined } from '../helpers/assert' - function doc(): NodeChange { return { guid: { sessionID: 0, localID: 0 }, diff --git a/tests/engine/render-cache.test.ts b/tests/engine/render-cache.test.ts index 19bbaec85..c0531729a 100644 --- a/tests/engine/render-cache.test.ts +++ b/tests/engine/render-cache.test.ts @@ -3,6 +3,7 @@ import { readFileSync } from 'fs' import { resolve } from 'path' import { initCanvasKit } from '#cli/headless' +import { expectDefined } from '#tests/helpers/assert' import { computeAllLayouts, @@ -14,8 +15,6 @@ import { type SceneNode } from '@open-pencil/core' -import { expectDefined } from '../helpers/assert' - let graph: SceneGraph let movingNodeId: string let ck: Awaited> diff --git a/tests/engine/render-text.test.ts b/tests/engine/render-text.test.ts index c20fdf230..e9e742f1d 100644 --- a/tests/engine/render-text.test.ts +++ b/tests/engine/render-text.test.ts @@ -3,6 +3,7 @@ import { describe, test, expect, mock } from 'bun:test' import { initCanvasKit } from '#cli/headless' import { renderText } from '#core/canvas/scene' import { fontManager } from '#core/text/fonts' +import { repoPath } from '#tests/helpers/paths' import { SceneGraph, SkiaRenderer as SkiaRendererClass } from '@open-pencil/core' import { detectTextDirection, resolveTextDirection } from '@open-pencil/core' @@ -161,8 +162,7 @@ describe('renderText headless visual', () => { fontProvider.registerFont(interData, 'Inter') fontManager.markLoaded('Inter', 'Regular', interData) - const notoPath = new URL('../../tests/fixtures/fonts/NotoSansSC-Regular.ttf', import.meta.url) - .pathname + const notoPath = repoPath('tests/fixtures/fonts/NotoSansSC-Regular.ttf') const notoData = await Bun.file(notoPath).arrayBuffer() fontProvider.registerFont(notoData, 'Noto Sans SC') fontManager.setCJKFallbackFamily('Noto Sans SC') diff --git a/tests/engine/render/jsx/builders.test.ts b/tests/engine/render/jsx/builders.test.ts index 035b80b47..be82aa4d3 100644 --- a/tests/engine/render/jsx/builders.test.ts +++ b/tests/engine/render/jsx/builders.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it } from 'bun:test' -import { Frame, Text, Rectangle, isTreeNode, node } from '@open-pencil/core' +import { expectDefined } from '#tests/helpers/assert' -import { expectDefined } from '../../../helpers/assert' +import { Frame, Text, Rectangle, isTreeNode, node } from '@open-pencil/core' describe('TreeNode builders', () => { it('creates Frame tree node', () => { diff --git a/tests/engine/render/jsx/grid-layout.test.ts b/tests/engine/render/jsx/grid-layout.test.ts index 0740cf65a..11c725e5e 100644 --- a/tests/engine/render/jsx/grid-layout.test.ts +++ b/tests/engine/render/jsx/grid-layout.test.ts @@ -1,5 +1,8 @@ import { describe, expect, it } from 'bun:test' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' +import { makeSceneGraph } from '#tests/helpers/scene' + import { renderTree, renderJSX, @@ -9,9 +12,6 @@ import { Rectangle } from '@open-pencil/core' -import { expectDefined, getNodeOrThrow } from '../../../helpers/assert' -import { makeSceneGraph } from '../../../helpers/scene' - describe('grid layout rendering', () => { it('creates grid frame with template columns', async () => { const g = makeSceneGraph() diff --git a/tests/engine/render/jsx/render-tree.test.ts b/tests/engine/render/jsx/render-tree.test.ts index edc3ad952..d7be462a1 100644 --- a/tests/engine/render/jsx/render-tree.test.ts +++ b/tests/engine/render/jsx/render-tree.test.ts @@ -1,5 +1,8 @@ import { describe, expect, it } from 'bun:test' +import { expectDefined, getNodeOrThrow, childIdAt } from '#tests/helpers/assert' +import { makeSceneGraph } from '#tests/helpers/scene' + import { renderTree, renderJSX, @@ -14,9 +17,6 @@ import { Section } from '@open-pencil/core' -import { expectDefined, getNodeOrThrow, childIdAt } from '../../../helpers/assert' -import { makeSceneGraph } from '../../../helpers/scene' - describe('renderTree', () => { it('renders a simple frame', async () => { const g = makeSceneGraph() diff --git a/tests/engine/render/jsx/text-props.test.ts b/tests/engine/render/jsx/text-props.test.ts index 3951492bd..81f7f780d 100644 --- a/tests/engine/render/jsx/text-props.test.ts +++ b/tests/engine/render/jsx/text-props.test.ts @@ -1,9 +1,9 @@ import { describe, expect, it } from 'bun:test' -import { renderJSX, sceneNodeToJSX } from '@open-pencil/core' +import { getNodeOrThrow, childIdAt } from '#tests/helpers/assert' +import { makeSceneGraph } from '#tests/helpers/scene' -import { getNodeOrThrow, childIdAt } from '../../../helpers/assert' -import { makeSceneGraph } from '../../../helpers/scene' +import { renderJSX, sceneNodeToJSX } from '@open-pencil/core' describe('text props round-trip', () => { it('lineHeight renders and exports', async () => { diff --git a/tests/engine/tauri-document-io.test.ts b/tests/engine/tauri-document-io.test.ts index 9dd290997..94b32bce4 100644 --- a/tests/engine/tauri-document-io.test.ts +++ b/tests/engine/tauri-document-io.test.ts @@ -1,11 +1,11 @@ import { afterEach, describe, expect, test } from 'bun:test' +import { clearTauriMocks, mockTauriIPC } from '#tests/helpers/tauri-mocks' + import { readReloadSource } from '@/app/document/io/reload-source' import { chooseTauriFigSavePath } from '@/app/document/io/save-targets' import { createDocumentWriter } from '@/app/document/io/write' -import { clearTauriMocks, mockTauriIPC } from '../helpers/tauri-mocks' - afterEach(async () => { await clearTauriMocks() Reflect.deleteProperty(globalThis, 'window') diff --git a/tests/engine/tauri-file-actions.test.ts b/tests/engine/tauri-file-actions.test.ts index d5c9df618..73b81b290 100644 --- a/tests/engine/tauri-file-actions.test.ts +++ b/tests/engine/tauri-file-actions.test.ts @@ -1,11 +1,11 @@ import { afterEach, describe, expect, test } from 'bun:test' +import { clearTauriMocks, mockTauriIPC } from '#tests/helpers/tauri-mocks' + import { saveExportedFile } from '@/app/document/export/files' import { watchTauriFile } from '@/app/document/io/watch-targets' import { chooseTauriOpenPath, readTauriDesignFile } from '@/app/shell/menu/files' -import { clearTauriMocks, mockTauriIPC } from '../helpers/tauri-mocks' - afterEach(async () => { await clearTauriMocks() Reflect.deleteProperty(globalThis, 'window') diff --git a/tests/engine/tauri-font-cache.test.ts b/tests/engine/tauri-font-cache.test.ts index 9a27aeb52..0a5e7140b 100644 --- a/tests/engine/tauri-font-cache.test.ts +++ b/tests/engine/tauri-font-cache.test.ts @@ -1,7 +1,8 @@ import { afterEach, describe, expect, test } from 'bun:test' +import { clearTauriMocks, mockTauriIPC } from '#tests/helpers/tauri-mocks' + import { clearDownloadedFontCache, downloadedFontCacheSummary } from '@/app/editor/fonts/cache' -import { clearTauriMocks, mockTauriIPC } from '../helpers/tauri-mocks' const encoder = new TextEncoder() @@ -14,27 +15,31 @@ describe('Tauri downloaded font cache helpers', () => { await mockTauriIPC((cmd, args) => { expect(cmd).toBe('plugin:fs|read_file') expect(args).toMatchObject({ path: 'font-cache/v1/manifest.json' }) - return [...encoder.encode(JSON.stringify({ - version: 1, - entries: { - one: { - family: 'Noto Sans SC', - style: 'Regular', - file: 'one.ttf', - byteLength: 10, - sha256: 'a', - updatedAt: 100 - }, - two: { - family: 'Noto Naskh Arabic', - style: 'Regular', - file: 'two.ttf', - byteLength: 25, - sha256: 'b', - updatedAt: 250 - } - } - }))] + return [ + ...encoder.encode( + JSON.stringify({ + version: 1, + entries: { + one: { + family: 'Noto Sans SC', + style: 'Regular', + file: 'one.ttf', + byteLength: 10, + sha256: 'a', + updatedAt: 100 + }, + two: { + family: 'Noto Naskh Arabic', + style: 'Regular', + file: 'two.ttf', + byteLength: 25, + sha256: 'b', + updatedAt: 250 + } + } + }) + ) + ] }) await expect(downloadedFontCacheSummary()).resolves.toEqual({ diff --git a/tests/engine/tauri-fonts.test.ts b/tests/engine/tauri-fonts.test.ts index affc7f00a..7a6d07772 100644 --- a/tests/engine/tauri-fonts.test.ts +++ b/tests/engine/tauri-fonts.test.ts @@ -1,8 +1,8 @@ import { afterEach, describe, expect, test, vi } from 'bun:test' -import { fontManager } from '@open-pencil/core/text' +import { clearTauriMocks, mockTauriIPC } from '#tests/helpers/tauri-mocks' -import { clearTauriMocks, mockTauriIPC } from '../helpers/tauri-mocks' +import { fontManager } from '@open-pencil/core/text' class MockFontFace { family: string diff --git a/tests/engine/tauri-processes.test.ts b/tests/engine/tauri-processes.test.ts index eda46029d..b41c09c2f 100644 --- a/tests/engine/tauri-processes.test.ts +++ b/tests/engine/tauri-processes.test.ts @@ -1,12 +1,11 @@ import { afterEach, describe, expect, test, vi } from 'bun:test' +import { clearTauriMocks, mockTauriIPC } from '#tests/helpers/tauri-mocks' import { ref } from 'vue' import { spawnAcpProcess } from '@/app/ai/acp/process' import { checkForAppUpdate } from '@/app/shell/updater' -import { clearTauriMocks, mockTauriIPC } from '../helpers/tauri-mocks' - afterEach(async () => { await clearTauriMocks() vi.restoreAllMocks() diff --git a/tests/engine/tauri-remaining-integrations.test.ts b/tests/engine/tauri-remaining-integrations.test.ts index 98bf76fff..8684b28c9 100644 --- a/tests/engine/tauri-remaining-integrations.test.ts +++ b/tests/engine/tauri-remaining-integrations.test.ts @@ -1,11 +1,11 @@ import { afterEach, describe, expect, test, vi } from 'bun:test' +import { clearTauriMocks, installTauriMockWindow, mockTauriIPC } from '#tests/helpers/tauri-mocks' + import { createACPTransport } from '@/app/ai/chat/transports' import { ensureTauriParentDirectory } from '@/app/automation/bridge/file-handlers' import { spawnMCPIfNeeded } from '@/app/automation/mcp/spawn' -import { clearTauriMocks, installTauriMockWindow, mockTauriIPC } from '../helpers/tauri-mocks' - import type { ACPChatTransport } from '@/app/ai/acp/transport' afterEach(async () => { diff --git a/tests/engine/text-edit-undo.test.ts b/tests/engine/text-edit-undo.test.ts index 2e6ab864c..e70c31c63 100644 --- a/tests/engine/text-edit-undo.test.ts +++ b/tests/engine/text-edit-undo.test.ts @@ -1,10 +1,10 @@ import { describe, test, expect } from 'bun:test' +import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert' + import { SceneGraph, TextEditor, UndoManager } from '@open-pencil/core' import { createTextActions } from '@open-pencil/core/editor' -import { expectDefined, getNodeOrThrow } from '../helpers/assert' - import type { StyleRun } from '@open-pencil/core' import type { EditorContext, EditorState } from '@open-pencil/core/editor' import type { CanvasKit } from 'canvaskit-wasm' diff --git a/tests/engine/tools-cli.test.ts b/tests/engine/tools-cli.test.ts index 8c335d6e9..b1d6fc841 100644 --- a/tests/engine/tools-cli.test.ts +++ b/tests/engine/tools-cli.test.ts @@ -1,12 +1,13 @@ import { describe, expect, test, setDefaultTimeout } from 'bun:test' import { join } from 'path' -import { heavy } from '../helpers/test-utils' +import { cliSourcePath, repoPath } from '#tests/helpers/paths' +import { heavy } from '#tests/helpers/test-utils' setDefaultTimeout(30_000) -const CLI = join(import.meta.dir, '../../packages/cli/src/index.ts') -const FIXTURE = join(import.meta.dir, '../fixtures/gold-preview.fig') +const CLI = cliSourcePath('index.ts') +const FIXTURE = repoPath('tests/fixtures/gold-preview.fig') async function evalCode( code: string diff --git a/tests/engine/tools/create.test.ts b/tests/engine/tools/create.test.ts index 160b1455d..46fb1e53a 100644 --- a/tests/engine/tools/create.test.ts +++ b/tests/engine/tools/create.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'bun:test' -import { getTool, setupToolTest, type ToolResult } from '../../helpers/tools' +import { getTool, setupToolTest, type ToolResult } from '#tests/helpers/tools' describe('create_shape', () => { test('creates a frame', () => { diff --git a/tests/engine/tools/modify.test.ts b/tests/engine/tools/modify.test.ts index 45ac7bccd..5fba10650 100644 --- a/tests/engine/tools/modify.test.ts +++ b/tests/engine/tools/modify.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from 'bun:test' -import { computeAllLayouts } from '@open-pencil/core' +import { ALL_TOOLS, getTool, setupToolTest, type ToolResult } from '#tests/helpers/tools' -import { ALL_TOOLS, getTool, setupToolTest, type ToolResult } from '../../helpers/tools' +import { computeAllLayouts } from '@open-pencil/core' describe('set_fill', () => { test('sets solid fill', () => { diff --git a/tests/engine/tools/read.test.ts b/tests/engine/tools/read.test.ts index ceeddb2dc..4dbba4177 100644 --- a/tests/engine/tools/read.test.ts +++ b/tests/engine/tools/read.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from 'bun:test' -import { FigmaAPI } from '@open-pencil/core' +import { ALL_TOOLS, getTool, setupToolTest, type ToolResult } from '#tests/helpers/tools' -import { ALL_TOOLS, getTool, setupToolTest, type ToolResult } from '../../helpers/tools' +import { FigmaAPI } from '@open-pencil/core' describe('find_nodes', () => { test('finds by name', () => { diff --git a/tests/engine/tools/registry.test.ts b/tests/engine/tools/registry.test.ts index adc385391..ba8a9bf61 100644 --- a/tests/engine/tools/registry.test.ts +++ b/tests/engine/tools/registry.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'bun:test' -import { ALL_TOOLS } from '../../helpers/tools' +import { ALL_TOOLS } from '#tests/helpers/tools' describe('tool definitions', () => { test('all tools have unique names', () => { diff --git a/tests/engine/tools/structure.test.ts b/tests/engine/tools/structure.test.ts index 111f27d2e..3eada397f 100644 --- a/tests/engine/tools/structure.test.ts +++ b/tests/engine/tools/structure.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'bun:test' -import { getTool, setupToolTest, type ToolResult } from '../../helpers/tools' +import { getTool, setupToolTest, type ToolResult } from '#tests/helpers/tools' describe('delete_node', () => { test('removes a node', () => { diff --git a/tests/engine/undo-batch-idle.test.ts b/tests/engine/undo-batch-idle.test.ts index d10e91702..787f50503 100644 --- a/tests/engine/undo-batch-idle.test.ts +++ b/tests/engine/undo-batch-idle.test.ts @@ -1,6 +1,6 @@ import { describe, test, expect } from 'bun:test' -import { createUndoManager, noop, undoEntry } from '../helpers/undo' +import { createUndoManager, noop, undoEntry } from '#tests/helpers/undo' describe('UndoManager idle-timer batching', () => { test('rapid pushes inside a batch produce a single undo entry', () => { diff --git a/tests/engine/undo-redo-sequence.test.ts b/tests/engine/undo-redo-sequence.test.ts index ec6c211f8..cb4ed3b13 100644 --- a/tests/engine/undo-redo-sequence.test.ts +++ b/tests/engine/undo-redo-sequence.test.ts @@ -1,6 +1,6 @@ import { describe, test, expect } from 'bun:test' -import { createHistoryFrame, setupEditorPage } from '../helpers/editor-history' +import { createHistoryFrame, setupEditorPage } from '#tests/helpers/editor-history' describe('undo/redo multi-step sequences', () => { test('create → move → duplicate → move copy → undo all → redo all', () => { diff --git a/tests/engine/undo.test.ts b/tests/engine/undo.test.ts index 28945bd8a..bc24571a7 100644 --- a/tests/engine/undo.test.ts +++ b/tests/engine/undo.test.ts @@ -1,6 +1,6 @@ import { describe, test, expect } from 'bun:test' -import { createUndoManager, undoEntry } from '../helpers/undo' +import { createUndoManager, undoEntry } from '#tests/helpers/undo' describe('UndoManager', () => { test('initial state', () => { diff --git a/tests/engine/variables-editor.test.ts b/tests/engine/variables-editor.test.ts index c95603323..da72e0845 100644 --- a/tests/engine/variables-editor.test.ts +++ b/tests/engine/variables-editor.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from 'bun:test' -import { ref } from 'vue' import { createVariableCollectionActions, createVariableValueActions } from '#vue/variables/helpers' +import { ref } from 'vue' import type { Editor } from '@open-pencil/core/editor' import type { Variable, VariableCollection } from '@open-pencil/core/scene-graph' diff --git a/tests/engine/vector.test.ts b/tests/engine/vector.test.ts index 59bd23204..a54a593a4 100644 --- a/tests/engine/vector.test.ts +++ b/tests/engine/vector.test.ts @@ -1,5 +1,13 @@ import { describe, test, expect } from 'bun:test' +import { + lineNetwork, + triangleNetwork, + vectorNetwork, + vectorSegment, + vectorVertex +} from '#tests/helpers/vector-network' + import { encodeVectorNetworkBlob, decodeVectorNetworkBlob, @@ -9,14 +17,6 @@ import { type VectorNetwork } from '@open-pencil/core' -import { - lineNetwork, - triangleNetwork, - vectorNetwork, - vectorSegment, - vectorVertex -} from '../helpers/vector-network' - describe('vectorNetworkBlob round-trip', () => { test('empty network', () => { const network: VectorNetwork = { vertices: [], segments: [], regions: [] } diff --git a/tests/engine/verify-silhouette-autopsy.test.ts b/tests/engine/verify-silhouette-autopsy.test.ts index c1f15a04d..24b714336 100644 --- a/tests/engine/verify-silhouette-autopsy.test.ts +++ b/tests/engine/verify-silhouette-autopsy.test.ts @@ -13,31 +13,28 @@ */ import { beforeAll, describe, expect, test } from 'bun:test' import { readFileSync } from 'node:fs' -import { join } from 'node:path' import { initCanvasKit } from '#cli/headless' import { SkiaRenderer } from '#core/canvas' import { SceneGraph } from '#core/scene-graph' import { fontManager } from '#core/text' +import { cliSourcePath, coreSourcePath, publicPath, testPath } from '#tests/helpers/paths' // === CLAIM EXTRACTION === // Each claim is: [doc_section, claim_text, verification_strategy] // We load the relevant source files to verify the claims by static analysis // AND runtime behavior where applicable. -const shadowsPath = join(import.meta.dir, '../../packages/core/src/canvas/shadows.ts') -const effectsPath = join(import.meta.dir, '../../packages/core/src/canvas/effects.ts') -const scenePath = join(import.meta.dir, '../../packages/core/src/canvas/scene.ts') -const rendererPath = join(import.meta.dir, '../../packages/core/src/canvas/renderer.ts') -const sgTypesPath = join(import.meta.dir, '../../packages/core/src/scene-graph/types.ts') -const nodeExportPath = join( - import.meta.dir, - '../../packages/core/src/kiwi/node-change/export-node.ts' -) -const convertPath = join(import.meta.dir, '../../packages/core/src/kiwi/node-change/paint.ts') -const schemaPath = join(import.meta.dir, '../../packages/core/src/kiwi/binary/schema.ts') -const codecPath = join(import.meta.dir, '../../packages/core/src/kiwi/binary/codec.ts') -const lifecyclePath = join(import.meta.dir, '../../packages/core/src/canvas/renderer/lifecycle.ts') +const shadowsPath = coreSourcePath('canvas/shadows.ts') +const effectsPath = coreSourcePath('canvas/effects.ts') +const scenePath = coreSourcePath('canvas/scene.ts') +const rendererPath = coreSourcePath('canvas/renderer.ts') +const sgTypesPath = coreSourcePath('scene-graph/types.ts') +const nodeExportPath = coreSourcePath('kiwi/node-change/export-node.ts') +const convertPath = coreSourcePath('kiwi/node-change/paint.ts') +const schemaPath = coreSourcePath('kiwi/binary/schema.ts') +const codecPath = coreSourcePath('kiwi/binary/codec.ts') +const lifecyclePath = coreSourcePath('canvas/renderer/lifecycle.ts') function readSource(path: string): string { return readFileSync(path, 'utf-8') @@ -293,7 +290,7 @@ 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 testPath = join(import.meta.dir, '../../tests/engine/visual-inner-shadow-counter.ts') + const testPath = testPath('engine/visual-inner-shadow-counter.ts') const src = readFileSync(testPath, 'utf-8') expect(src).toContain('hasShadowOnRightInnerEdge') expect(src).toContain("t.color === 'black'") @@ -344,7 +341,7 @@ describe('Doc 01/03 — Runtime Behavior Verification', () => { fontManager.attachProvider(ck, fontProvider) // Load Inter font for text tests - const fontPath = join(import.meta.dir, '../../public/Inter-SemiBold.ttf') + const fontPath = publicPath('Inter-SemiBold.ttf') try { const fontData = readFileSync(fontPath) fontManager.markLoaded( diff --git a/tests/figma/create-shapes.spec.ts b/tests/figma/create-shapes.spec.ts index ab03e22c1..f0a5e4980 100644 --- a/tests/figma/create-shapes.spec.ts +++ b/tests/figma/create-shapes.spec.ts @@ -1,7 +1,6 @@ +import { FigmaHelper } from '#tests/helpers/figma' import { test, expect } from '@playwright/test' -import { FigmaHelper } from '../helpers/figma' - test.describe('figma reference: create shapes', () => { let figma: FigmaHelper diff --git a/tests/helpers/paths.ts b/tests/helpers/paths.ts new file mode 100644 index 000000000..cd33e27af --- /dev/null +++ b/tests/helpers/paths.ts @@ -0,0 +1,23 @@ +import { join } from 'node:path' + +const repoRoot = join(import.meta.dir, '..', '..') + +export function repoPath(...segments: string[]): string { + return join(repoRoot, ...segments) +} + +export function coreSourcePath(...segments: string[]): string { + return repoPath('packages/core/src', ...segments) +} + +export function cliSourcePath(...segments: string[]): string { + return repoPath('packages/cli/src', ...segments) +} + +export function testPath(...segments: string[]): string { + return repoPath('tests', ...segments) +} + +export function publicPath(...segments: string[]): string { + return repoPath('public', ...segments) +} diff --git a/tests/helpers/tauri-mocks.ts b/tests/helpers/tauri-mocks.ts index cf233ff2d..1d0001e62 100644 --- a/tests/helpers/tauri-mocks.ts +++ b/tests/helpers/tauri-mocks.ts @@ -13,7 +13,9 @@ export async function mockTauriIPC( const { mockIPC } = await import('@tauri-apps/api/mocks') mockIPC(handler) const windowLike = window as typeof window & { - __TAURI_INTERNALS__: { invoke: (cmd: string, args: unknown, options?: unknown) => Promise } + __TAURI_INTERNALS__: { + invoke: (cmd: string, args: unknown, options?: unknown) => Promise + } } windowLike.__TAURI_INTERNALS__.invoke = async (cmd, args, options) => handler(cmd, args, options) } diff --git a/tsconfig.json b/tsconfig.json index 126f7f58a..e58c215bc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,6 +21,7 @@ "#core/*": ["./packages/core/src/*"], "#cli/*": ["./packages/cli/src/*"], "#mcp/*": ["./packages/mcp/src/*"], + "#tests/*": ["./tests/*"], "tinykeys": ["./node_modules/tinykeys/dist/tinykeys.d.ts"], "@open-pencil/vue": ["./packages/vue/src/index.ts"], "@open-pencil/core": ["./packages/core/src/index.ts"], diff --git a/vite/canvaskit-assets.ts b/vite/canvaskit-assets.ts index dfaffc578..c53137d13 100644 --- a/vite/canvaskit-assets.ts +++ b/vite/canvaskit-assets.ts @@ -1,8 +1,7 @@ import { copyFileSync, createReadStream, existsSync, mkdirSync } from 'fs' import { dirname, resolve } from 'node:path' -import type { Connect, ResolvedConfig } from 'vite' -import type { Plugin } from 'vite' +import type { Connect, Plugin, ResolvedConfig } from 'vite' function syncWasmFromNodeModules(root: string, source: string, destination: string) { const sourcePath = resolve(root, source) @@ -51,7 +50,11 @@ export function copyCanvasKitAssetsPlugin(): Plugin { root = config.root }, buildStart() { - syncWasmFromNodeModules(root, 'node_modules/canvaskit-wasm/bin/canvaskit.wasm', 'public/canvaskit.wasm') + syncWasmFromNodeModules( + root, + 'node_modules/canvaskit-wasm/bin/canvaskit.wasm', + 'public/canvaskit.wasm' + ) syncWasmFromNodeModules( root, 'packages/core/vendor/canvaskit-webgpu/canvaskit.wasm',