diff --git a/.lintstagedrc.json b/.lintstagedrc.json index 5f81e94..d72cb1d 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -2,13 +2,13 @@ "*.{ts,tsx}": [ "biome check --write --no-errors-on-unmatched", "biome format --write --no-errors-on-unmatched", - "eslint --fix --max-warnings 0", + "eslint --fix --max-warnings 0 --no-warn-ignored", "cspell --no-progress --no-must-find-files" ], "*.{js,cjs,mjs}": [ "biome check --write --no-errors-on-unmatched", "biome format --write --no-errors-on-unmatched", - "eslint --fix --max-warnings 0" + "eslint --fix --max-warnings 0 --no-warn-ignored" ], "*.{json,jsonc}": ["biome format --write --no-errors-on-unmatched"], "*.css": ["biome format --write --no-errors-on-unmatched"], diff --git a/playwright.config.ts b/playwright.config.ts index 227f611..c42d06d 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -7,11 +7,11 @@ export default defineConfig({ snapshotPathTemplate: '{snapshotDir}/{testFilePath}/{testName}/{projectName}{ext}', fullyParallel: true, - forbidOnly: !!process.env['CI'], - retries: process.env['CI'] ? 2 : 0, - workers: process.env['CI'] ? 1 : 2, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : 2, - reporter: process.env['CI'] ? 'github' : 'html', + reporter: process.env.CI ? 'github' : 'html', use: { baseURL: 'http://localhost:5174', @@ -35,7 +35,7 @@ export default defineConfig({ webServer: { command: 'pnpm exec vite serve tests/visual/fixtures --port 5174', port: 5174, - reuseExistingServer: !process.env['CI'], + reuseExistingServer: !process.env.CI, timeout: 30_000, }, }); diff --git a/tests/visual/__snapshots__/primitives.spec.ts/Primitive-Rendering-should-render-known-primitive-patterns/chromium-webgpu.png b/tests/visual/__snapshots__/primitives.spec.ts/Primitive-Rendering-should-render-known-primitive-patterns/chromium-webgpu.png new file mode 100644 index 0000000000000000000000000000000000000000..97f6a85cc9c1b09c726e7bc607da28820691bb60 GIT binary patch literal 1044 zcmeAS@N?(olHy`uVBq!ia0y~yV02($VEDkn#K6Gt&tJ=ifr0s?r;B4q#hf>HJ@f7u zh%j8d-}t`%soykCq227hI?wm6-6EhO=IFrk!_eW{afV2yHUmcI84Zd)2L#j-ID`#a zI3*6T@Femx?K^*`Eq2d;z4zaD9?3nuegCV4`^$dk9scQf;MLRG)mJw?o3p7`)dZ>> z)s)*}AI$$4{_9w)yCx<2fSYm5DIqD4p{T0hcHt7{`%&ipYNIqZ=Yg~o&-h(m@#F4I zIhLCJ_w&Coeq=lROvHZQzCWw)?XDCF`}+8ytW;a7EnkHR&+00z2Nw-=UfyhQKfGa{ zIFlUj;iNe33KJgfN=uN$pkgZtrv ziM1eoqGcd`%WoS$xM(mZ`#DHr(O;0hNIuRA6Q1Q3Ae&^~9{@>gNCrtv zqJhlgB_N50&mg1j`SDhm@a(p-esIy?&GROZ6DDVaB;@o!cFc~I{E#8BZKuV9iv~Fb zwFed_R$Lci>~DLhyPCyDs_nWi$c1rR!ax#7i$D^Y+H5vbZO?V2K4eJD+mHv6NO{@d ze)z-Et00FwX96h_?gfeH&jgXvgAOcC{1L44;G)5wXJ+`)11P|;B$H8L%&bGDFxfDl qfq~)w|D7&+-3$y2Y@kfd%+MdTJdXdF!43un1_n=8KbLh*2~7Z{nQp59 literal 0 HcmV?d00001 diff --git a/tests/visual/fixtures/primitives.html b/tests/visual/fixtures/primitives.html new file mode 100644 index 0000000..38c8b32 --- /dev/null +++ b/tests/visual/fixtures/primitives.html @@ -0,0 +1,70 @@ + + + + + Visual Test: Primitives + + + +
+ +
+ + + diff --git a/tests/visual/fixtures/vite.config.ts b/tests/visual/fixtures/vite.config.ts new file mode 100644 index 0000000..077c4c2 --- /dev/null +++ b/tests/visual/fixtures/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite'; + +export default defineConfig({ + root: '.', + resolve: { + alias: { + 'blit-tech': '/Users/vancura/Repos/_BLIT_TECH_/blit-tech/src/BlitTech.ts', + }, + }, +}); diff --git a/tests/visual/primitives.spec.ts b/tests/visual/primitives.spec.ts new file mode 100644 index 0000000..ca5fb8e --- /dev/null +++ b/tests/visual/primitives.spec.ts @@ -0,0 +1,31 @@ +import { expect, test } from '@playwright/test'; + +test.describe('Primitive Rendering', () => { + test('should render known primitive patterns', async ({ page }) => { + await page.goto('/primitives.html'); + + // Wait for either render completion or initialization failure. + await page.waitForFunction( + () => { + const w = window as unknown as Record; + return w.__RENDER_COMPLETE__ || w.__INIT_FAILED__; + }, + { timeout: 10_000 }, + ); + + // Check if WebGPU initialization failed (hardware-dependent). + const initFailed = await page.evaluate(() => (window as unknown as Record).__INIT_FAILED__); + + if (initFailed) { + test.skip(true, 'WebGPU not available in this environment'); + return; + } + + // Small delay for GPU present. + await page.waitForTimeout(100); + + await expect(page.locator('canvas')).toHaveScreenshot('primitives.png', { + maxDiffPixelRatio: 0.01, + }); + }); +}); -- 2.51.2 From 657dd5d9de3f130f40f1c8efeb2dcb09a17e6aa8 Mon Sep 17 00:00:00 2001 From: Vaclav Vancura Date: Wed, 25 Mar 2026 16:04:48 +0100 Subject: [PATCH 2/2] test(ci): make visual test fixture path resolution portable Replace the hardcoded absolute path in vite.config.ts with a path.resolve(__dirname, ...) relative path so the fixture server works correctly on any machine and in CI. Pass --config explicitly to playwright.config.ts so Vite picks up the fixture config. Also extract the GPU present delay into a GPU_PRESENT_DELAY env var for easier CI tuning. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Vaclav Vancura --- playwright.config.ts | 2 +- tests/visual/fixtures/vite.config.ts | 6 +++++- tests/visual/primitives.spec.ts | 8 ++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index c42d06d..d2f2d60 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -33,7 +33,7 @@ export default defineConfig({ ], webServer: { - command: 'pnpm exec vite serve tests/visual/fixtures --port 5174', + command: 'pnpm exec vite serve tests/visual/fixtures --config tests/visual/fixtures/vite.config.ts --port 5174', port: 5174, reuseExistingServer: !process.env.CI, timeout: 30_000, diff --git a/tests/visual/fixtures/vite.config.ts b/tests/visual/fixtures/vite.config.ts index 077c4c2..ed60b9b 100644 --- a/tests/visual/fixtures/vite.config.ts +++ b/tests/visual/fixtures/vite.config.ts @@ -1,10 +1,14 @@ +import path from 'path'; +import { fileURLToPath } from 'url'; import { defineConfig } from 'vite'; +const __dirname = fileURLToPath(new URL('.', import.meta.url)); + export default defineConfig({ root: '.', resolve: { alias: { - 'blit-tech': '/Users/vancura/Repos/_BLIT_TECH_/blit-tech/src/BlitTech.ts', + 'blit-tech': path.resolve(__dirname, '../../../src/BlitTech.ts'), }, }, }); diff --git a/tests/visual/primitives.spec.ts b/tests/visual/primitives.spec.ts index ca5fb8e..2952b71 100644 --- a/tests/visual/primitives.spec.ts +++ b/tests/visual/primitives.spec.ts @@ -1,5 +1,9 @@ import { expect, test } from '@playwright/test'; +// Delay after render-complete signal before taking a screenshot, to allow the +// GPU to present the frame. Override via GPU_PRESENT_DELAY env var for CI tuning. +const GPU_PRESENT_DELAY = Number(process.env.GPU_PRESENT_DELAY ?? 100); + test.describe('Primitive Rendering', () => { test('should render known primitive patterns', async ({ page }) => { await page.goto('/primitives.html'); @@ -21,8 +25,8 @@ test.describe('Primitive Rendering', () => { return; } - // Small delay for GPU present. - await page.waitForTimeout(100); + // Wait for the GPU to present the rendered frame before capturing. + await page.waitForTimeout(GPU_PRESENT_DELAY); await expect(page.locator('canvas')).toHaveScreenshot('primitives.png', { maxDiffPixelRatio: 0.01,