From 4533910bce394e7a0ee6debfc05ca1221ee51899 Mon Sep 17 00:00:00 2001 From: victor Date: Sat, 24 Oct 2026 15:57:01 +0200 Subject: Astra! --- tests/test4.spec.ts | 118 ---------------------------------------------------- 1 file changed, 118 deletions(-) delete mode 100644 tests/test4.spec.ts (limited to 'tests/test4.spec.ts') diff --git a/tests/test4.spec.ts b/tests/test4.spec.ts deleted file mode 100644 index 3e6a3b5..0000000 --- a/tests/test4.spec.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { test, expect, type Page } from '@playwright/test'; - -async function read(page: Page, label: string) { - return Number((await page.getByLabel(label, { exact: true }).innerText()).replaceAll(',', '')); -} - -test('six original test questions have interactive scenes and every answer part', async ({ page }) => { - const errors: string[] = []; - page.on('pageerror', e => errors.push(e.message)); - await page.goto('/'); - const ids = ['work', 'conservation', 'central', 'assembly', 'uniform', 'dipole']; - const parts = [1, 1, 2, 2, 2, 3]; - await expect(page.getByRole('tab')).toHaveCount(6); - for (let i = 0; i < ids.length; i++) { - await page.getByRole('tab').nth(i).click(); - await expect(page).toHaveURL(new RegExp(`#test-${ids[i]}$`)); - await expect(page.locator('#test-question')).not.toBeEmpty(); - await expect(page.locator('#solution details')).toHaveCount(parts[i]); - await page.locator('#solution summary').first().click(); - await expect(page.locator('#solution details[open] .derivation')).toBeVisible(); - await expect(page.locator('#measurements')).not.toContainText('Undefined'); - await expect(page.locator('canvas').first()).toBeVisible(); - // Check actual rendered pixels, including scenes constructed after hash navigation. - await expect.poll(() => page.locator('#viewport > canvas').evaluate(canvas => new Promise(resolve => { - requestAnimationFrame(() => requestAnimationFrame(() => { - const small = document.createElement('canvas'); small.width = 80; small.height = 60; - const context = small.getContext('2d')!; - context.drawImage(canvas as HTMLCanvasElement, 0, 0, 80, 60); - const data = context.getImageData(0, 0, 80, 60).data; - const colours = new Set(); - for (let k = 0; k < data.length; k += 4) colours.add((data[k] << 16) | (data[k + 1] << 8) | data[k + 2]); - resolve(colours.size); - })); - }))).toBeGreaterThan(12); - } - expect(errors).toEqual([]); -}); - -test('path changes preserve work while signed charge and angle change it', async ({ page }) => { - await page.goto('/#test-work'); - const initial = await read(page, 'Field work a → b'); - await page.getByLabel('Path shape', { exact: true }).selectOption('curved'); - expect(await read(page, 'Field work a → b')).toBe(initial); - await page.getByRole('slider', { name: 'Moving charge q₀', exact: true }).fill('-2'); - expect(await read(page, 'Field work a → b')).toBe(-initial); - await page.goto('/#test-uniform'); - await page.getByRole('slider', { name: 'Displacement angle α', exact: true }).fill('90'); - expect(Math.abs(await read(page, 'Field work a → b'))).toBeLessThan(1e-10); -}); - -test('energy conservation, infinity and dipole equilibrium stay physically consistent', async ({ page }) => { - await page.goto('/#test-conservation'); - const total = await read(page, 'Total K + U'); - await page.getByRole('slider', { name: 'Journey progress', exact: true }).fill('100'); - expect(await read(page, 'Total K + U')).toBe(total); - expect(await read(page, 'Kinetic energy K')).toBeGreaterThan(0); - await page.goto('/#test-central'); - await page.getByLabel('Destination b', { exact: true }).selectOption('infinity'); - expect(await read(page, 'Potential energy Uᵦ')).toBe(0); - await expect(page.locator('#observation')).toContainText('infinity'); - await page.goto('/#test-dipole'); - await page.getByRole('slider', { name: 'Final angle θᵦ', exact: true }).fill('0'); - await page.getByRole('slider', { name: 'Rotation progress', exact: true }).fill('100'); - expect(await read(page, 'Potential energy U')).toBeLessThan(0); - expect(await read(page, 'Torque τz')).toBe(0); - await expect(page.locator('#observation')).toContainText('stable'); -}); - -test('assembly adds q₀ without double counting and the prediction can be revealed', async ({ page }) => { - await page.goto('/#test-assembly'); - await page.getByLabel('Assembly stage', { exact: true }).selectOption('3'); - const base = await read(page, 'Energy of current assembly'); - await page.getByLabel('Assembly stage', { exact: true }).selectOption('4'); - expect(await read(page, 'Energy of current assembly')).toBeCloseTo(base + await read(page, 'Additional energy ΔU₀'), 1); - await expect(page.locator('#prediction-answer')).toBeHidden(); - await page.getByRole('button', { name: 'Reveal explanation' }).click(); - await expect(page.locator('#prediction-answer')).toBeVisible(); -}); - -test('collection navigation retains settings, works with history, and fits mobile', async ({ page }) => { - await page.goto('/#test-dipole'); - await page.getByRole('slider', { name: 'Final angle θᵦ', exact: true }).fill('180'); - await page.getByRole('link', { name: 'All experiments', exact: true }).click(); - await expect(page.getByRole('tab')).toHaveCount(8); - await page.goBack(); - await expect(page.getByRole('slider', { name: 'Final angle θᵦ', exact: true })).toHaveValue('180'); - await page.getByRole('button', { name: 'Reset experiment' }).click(); - await expect(page.getByRole('slider', { name: 'Final angle θᵦ', exact: true })).toHaveValue('15'); - await page.setViewportSize({ width: 390, height: 844 }); - await expect(page.locator('canvas')).toBeVisible(); - expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true); -}); - -test('next question returns a mobile learner to the new heading', async ({ page }) => { - await page.setViewportSize({ width: 390, height: 844 }); - await page.goto('/#test-work'); - await page.getByRole('link', { name: 'Next question →', exact: true }).click(); - await expect(page).toHaveURL(/#test-conservation$/); - await expect(page.getByRole('heading', { name: 'Where does the energy go?' })).toBeInViewport(); - await expect(page.locator('#lesson-title')).toBeFocused(); -}); - -test('test answers and controls remain accessible without WebGL', async ({ page }) => { - await page.addInitScript(() => { - const original = HTMLCanvasElement.prototype.getContext; - HTMLCanvasElement.prototype.getContext = function (type: string, ...args: unknown[]) { - if (type.startsWith('webgl')) return null; - return original.call(this, type as '2d', ...args as []) as never; - } as typeof original; - }); - await page.goto('/#test-dipole'); - await expect(page.getByRole('alert')).toContainText('WebGL'); - await page.getByRole('slider', { name: 'Rotation progress', exact: true }).fill('100'); - expect(await read(page, 'Potential energy U')).toBeLessThan(0); - await page.locator('#solution summary').last().click(); - await expect(page.locator('#solution details[open] math').first()).toBeAttached(); - await expect(page.locator('#solution details[open] .katex-error')).toHaveCount(0); -}); -- cgit v1.2.3