import { expect, test } from '../helpers/serve-dist'; import { environmentChunkPattern, installSceneInstrumentation, readSceneInstrumentation, } from '../helpers/scene-instrumentation'; test.beforeEach(async ({ page }) => installSceneInstrumentation(page)); test('falls back to one poster and no scene loop when the deferred scene chunk is unavailable', async ({ page, distUrl, }) => { const pageErrors: string[] = []; page.on('pageerror', (error) => pageErrors.push(error.message)); await page.route(environmentChunkPattern, (route) => route.abort('failed')); await page.goto(distUrl, { waitUntil: 'domcontentloaded' }); await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'failed'); await expect(page.locator('.journey-poster')).toHaveCount(1); await expect(page.locator('.journey-canvas')).toHaveCount(0); await expect(page.locator('main > section')).toHaveCount(8); await expect(page.locator('nav a[href="#contact"]')).toBeVisible(); await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible(); await expect.poll(async () => (await readSceneInstrumentation(page)).activeAnimationFrames).toBe(0); expect((await readSceneInstrumentation(page)).unhandledRejections).toEqual([]); expect(pageErrors).toEqual([]); }); test('contains a WebGL initialization failure without hiding the portfolio', async ({ page, distUrl }) => { const pageErrors: string[] = []; page.on('pageerror', (error) => pageErrors.push(error.message)); await page.addInitScript(() => { const nativeGetContext = HTMLCanvasElement.prototype.getContext; Object.defineProperty(HTMLCanvasElement.prototype, 'getContext', { configurable: true, value(this: HTMLCanvasElement, contextId: string, options?: unknown): RenderingContext | null { if (contextId === 'webgl' || contextId === 'webgl2' || contextId === 'experimental-webgl') return null; return Reflect.apply(nativeGetContext, this, [contextId, options]) as RenderingContext | null; }, }); }); await page.goto(distUrl, { waitUntil: 'domcontentloaded' }); await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'failed'); await expect(page.locator('.journey-poster')).toHaveCount(1); await expect(page.locator('.journey-canvas')).toHaveCount(0); await expect(page.locator('#portfolio-content')).toBeVisible(); await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible(); await expect.poll(async () => (await readSceneInstrumentation(page)).activeAnimationFrames).toBe(0); expect((await readSceneInstrumentation(page)).unhandledRejections).toEqual([]); expect(pageErrors).toEqual([]); }); test('allows an explicit Static visitor to re-enable motion when the system permits it', async ({ page, distUrl }) => { const requests: string[] = []; page.on('request', (request) => requests.push(request.url())); await page.goto(distUrl, { waitUntil: 'domcontentloaded' }); await page.getByLabel('Quality control').selectOption('static'); await expect(page.getByRole('button', { name: 'Enable motion' })).toBeVisible(); await expect(page.locator('.journey-canvas')).toHaveCount(0); await page.getByRole('button', { name: 'Enable motion' }).click(); await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'running'); await expect(page.locator('.journey-canvas')).toHaveCount(1); expect(requests.some((url) => environmentChunkPattern.test(url))).toBe(true); });