This commit is contained in:
@@ -68,7 +68,7 @@ test('storyboard phases retain one root and ignore repeated triggers', async ({
|
||||
await page.mouse.wheel(0, 180);
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await page.mouse.click(20, 20);
|
||||
await page.clock.runFor(1080); // Scene 4: early trunk growth, before docking.
|
||||
await page.clock.runFor(1330); // Scene 4: early trunk growth, before docking.
|
||||
await expect(page.locator(stage)).toHaveAttribute('data-phase', 'extend');
|
||||
expect(await page.locator('#welcome-orbit').getAttribute('d')).toMatch(new RegExp(`^${circlePath} H`));
|
||||
const tangent = await page.locator('#welcome-orbit').evaluate((element, length) => {
|
||||
@@ -80,28 +80,60 @@ test('storyboard phases retain one root and ignore repeated triggers', async ({
|
||||
expect(tangent.dx).toBeCloseTo(40, 1);
|
||||
expect(tangent.dy).toBeCloseTo(0, 1);
|
||||
expect(tangent.y).toBeCloseTo(-180, 1);
|
||||
// The trunk must not cut through letters still on the bottom of the circle.
|
||||
expect(Number(await page.locator('.orbit textPath').getAttribute('startOffset'))).toBeGreaterThan(arcLength / 2 + 100);
|
||||
const earlyLength = await page.locator('.trunk-line').evaluate((path) => (path as SVGPathElement).getTotalLength());
|
||||
expect(earlyLength).toBeGreaterThan(10);
|
||||
await page.screenshot({ path: testInfo.outputPath('04-unfold.png') });
|
||||
await page.clock.runFor(950); // Let the horizontal line finish extending.
|
||||
await page.clock.runFor(700); // Let the downward trunk finish extending.
|
||||
await expect(page.locator(stage)).toHaveAttribute('data-phase', 'extend');
|
||||
const extendedLength = await page.locator('.trunk-line').evaluate((path) => (path as SVGPathElement).getTotalLength());
|
||||
expect(extendedLength).toBeGreaterThan(earlyLength * 1.4);
|
||||
expect(extendedLength).toBeGreaterThan(page.viewportSize()!.width * .18);
|
||||
expect(extendedLength).toBeGreaterThan(page.viewportSize()!.height * .18);
|
||||
await expect(page.locator('.trunk-line')).toHaveCSS('stroke-width', '10px');
|
||||
const extendedRoot = await root.boundingBox();
|
||||
expect(extendedRoot!.height).toBeCloseTo(initial!.height, 0);
|
||||
expect(extendedRoot!.y).toBeCloseTo(initial!.y, 0);
|
||||
await expect(page.locator('.demo-node:not(.root-mark)').first()).toHaveCSS('opacity', '0');
|
||||
const trunkGeometry = () => page.evaluate(() => {
|
||||
const path = document.querySelector<SVGPathElement>('.trunk-line')!;
|
||||
const start = path.getPointAtLength(0).matrixTransform(path.getScreenCTM()!);
|
||||
const tip = path.getPointAtLength(path.getTotalLength()).matrixTransform(path.getScreenCTM()!);
|
||||
const root = document.querySelector('.root-mark')!.getBoundingClientRect();
|
||||
return { dx: tip.x - start.x, dy: tip.y - start.y, axis: start.x - (root.left + root.width / 2), gap: start.y - root.bottom, bottom: tip.y };
|
||||
});
|
||||
const extended = await trunkGeometry();
|
||||
expect(Math.abs(extended.dx)).toBeLessThan(.1);
|
||||
expect(Math.abs(extended.axis)).toBeLessThan(.1);
|
||||
expect(extended.dy).toBeGreaterThan(0);
|
||||
expect(extended.gap).toBeCloseTo(8, 0);
|
||||
expect(extended.bottom).toBeLessThan(page.viewportSize()!.height * .91);
|
||||
await page.screenshot({ path: testInfo.outputPath('04-trunk.png') });
|
||||
await page.clock.runFor(1700); // SVG/box-drawing handoff, with neither removed.
|
||||
await page.clock.runFor(850);
|
||||
const docking = await trunkGeometry();
|
||||
expect(Math.abs(docking.dx)).toBeLessThan(.1);
|
||||
expect(Math.abs(docking.axis)).toBeLessThan(.1);
|
||||
expect(docking.gap).toBeGreaterThanOrEqual(0);
|
||||
await page.screenshot({ path: testInfo.outputPath('05-docking.png') });
|
||||
await page.clock.runFor(850); // SVG/box-drawing handoff, with neither removed.
|
||||
const handoff = await page.evaluate(() => {
|
||||
const path = document.querySelector<SVGPathElement>('.trunk-line')!;
|
||||
const start = path.getPointAtLength(0).matrixTransform(path.getScreenCTM()!);
|
||||
const tip = path.getPointAtLength(path.getTotalLength()).matrixTransform(path.getScreenCTM()!);
|
||||
const target = document.querySelector('.root-wire')!.getBoundingClientRect();
|
||||
return Math.hypot(tip.x - (target.right - target.width / 6), tip.y - (target.top + target.height / 2));
|
||||
const first = document.querySelector('.branch-spine')!.getBoundingClientRect();
|
||||
const last = [...document.querySelectorAll('.demo-node[aria-level="2"]')].at(-1)!.parentElement!.querySelector('.branch-spine')!.getBoundingClientRect();
|
||||
return {
|
||||
start: Math.hypot(start.x - (first.left + first.width / 2), start.y - first.top),
|
||||
end: Math.hypot(tip.x - (last.left + last.width / 2), tip.y - (last.top + last.height / 2)),
|
||||
spineOpacity: Number(getComputedStyle(document.querySelector('.branch-spine')!).opacity),
|
||||
trunkOpacity: Number(getComputedStyle(path).opacity),
|
||||
};
|
||||
});
|
||||
expect(handoff).toBeLessThan(1);
|
||||
expect(handoff.start).toBeLessThan(1);
|
||||
expect(handoff.end).toBeLessThan(1);
|
||||
expect(handoff.spineOpacity).toBeGreaterThan(0);
|
||||
expect(handoff.trunkOpacity).toBeGreaterThan(0);
|
||||
expect(handoff.spineOpacity + handoff.trunkOpacity).toBeCloseTo(1, 4);
|
||||
await page.clock.runFor(550);
|
||||
await expect(page.locator(stage)).toHaveAttribute('data-phase', 'tree');
|
||||
await page.screenshot({ path: testInfo.outputPath('05-tree.png') });
|
||||
@@ -127,13 +159,19 @@ test('storyboard phases retain one root and ignore repeated triggers', async ({
|
||||
'├── ', '│ ├── ', '│ └── ', '│ └── ',
|
||||
'├── ', '│ └── ', '└── ', ' └── ',
|
||||
]);
|
||||
await expect(page.locator('.root-wire')).toHaveCount(0);
|
||||
await expect(page.locator('.branch-spine')).toHaveText(['├', '│', '│', '│', '├', '│', '└', ' ']);
|
||||
const grid = await page.evaluate(() => {
|
||||
const root = document.querySelector('.root-mark')!.getBoundingClientRect();
|
||||
const spine = document.querySelector('.branch-spine')!.getBoundingClientRect();
|
||||
const prefix = document.querySelector<HTMLElement>('.branch-prefix')!;
|
||||
const cell = prefix.getBoundingClientRect().width / 4;
|
||||
const frame = document.querySelector('.landing-content')!.getBoundingClientRect();
|
||||
const rows = [...document.querySelectorAll<HTMLElement>('.node-row:not(.root-slot)')].map((row) => row.getBoundingClientRect());
|
||||
const nodes = [...document.querySelectorAll<HTMLElement>('.demo-node:not(.root-mark)')].map((node) => node.getBoundingClientRect());
|
||||
return {
|
||||
rootColumnError: Math.abs(root.left + root.width / 2 - spine.left - spine.width / 2),
|
||||
rootGap: Math.abs(root.bottom - spine.top),
|
||||
frameCells: frame.width / cell,
|
||||
rowHeights: rows.map((row) => row.height),
|
||||
nodeColumns: nodes.map((node) => (node.left - frame.left) / cell),
|
||||
@@ -141,6 +179,8 @@ test('storyboard phases retain one root and ignore repeated triggers', async ({
|
||||
font: getComputedStyle(prefix).fontFamily,
|
||||
};
|
||||
});
|
||||
expect(grid.rootColumnError).toBeLessThan(1);
|
||||
expect(grid.rootGap).toBeLessThan(1);
|
||||
expect(Math.abs(grid.frameCells / 4 - Math.round(grid.frameCells / 4))).toBeLessThan(.02);
|
||||
expect(grid.rowHeights.every((height) => height === 24)).toBe(true);
|
||||
expect(grid.nodeColumns.every((col) => Math.abs(col - Math.round(col)) < .02)).toBe(true);
|
||||
@@ -192,7 +232,10 @@ test('tree selection, collapse and call results are keyboard accessible', async
|
||||
await expect(page.getByRole('treeitem', { name: 'ルート /' })).toBeFocused();
|
||||
await page.keyboard.press('ArrowLeft');
|
||||
await expect(page.getByRole('treeitem')).toHaveCount(1);
|
||||
await expect(page.locator('.branch-spine').first()).toBeHidden();
|
||||
await page.keyboard.press('ArrowRight');
|
||||
await expect(page.locator('.branch-spine').first()).toBeVisible();
|
||||
await expect(page.locator('.branch-prefix').first()).toHaveText('├── ');
|
||||
await page.keyboard.press('End');
|
||||
await expect(page.getByRole('treeitem', { name: 'protocol', exact: true })).toBeFocused();
|
||||
await page.keyboard.press('Tab');
|
||||
|
||||
@@ -6,6 +6,13 @@ test('home and book are usable without client JavaScript', async ({ page }, test
|
||||
await page.goto('./');
|
||||
await expect(page.getByRole('heading', { level: 1 })).toContainText('探索できる世界へ');
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
|
||||
await expect(page.locator('.branch-prefix').first()).toHaveText('├── ');
|
||||
const root = await page.locator('.root-mark').boundingBox();
|
||||
const spine = await page.locator('.branch-spine').first().boundingBox();
|
||||
expect(root).not.toBeNull();
|
||||
expect(spine).not.toBeNull();
|
||||
expect(Math.abs(root!.x + root!.width / 2 - spine!.x - spine!.width / 2)).toBeLessThan(1);
|
||||
expect(Math.abs(root!.y + root!.height - spine!.y)).toBeLessThan(1);
|
||||
await page.screenshot({ path: testInfo.outputPath('home.png'), fullPage: true });
|
||||
await page.getByRole('link', { name: 'Book', exact: true }).click();
|
||||
await expect(page.getByRole('heading', { level: 1 })).toContainText('通信の約束まで');
|
||||
|
||||
Reference in New Issue
Block a user