feat: add dedicated home page and automatic dark mode
Reference site / build (push) Canceled after 0s
Reference site / build (push) Canceled after 0s
This commit is contained in:
@@ -108,7 +108,7 @@ async function complete(page: import('@playwright/test').Page) {
|
||||
await expect(page.locator('html')).not.toHaveAttribute('data-landing');
|
||||
expect((await page.locator('.root-shape').boundingBox())!.height).toBeCloseTo(12.25, 4);
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true);
|
||||
await expect(page.getByRole('link', { name: 'Book', exact: true })).toBeVisible();
|
||||
await expect(page.locator('.site-header').getByRole('link', { name: 'Book', exact: true })).toBeVisible();
|
||||
}
|
||||
|
||||
test('only the resting slash shrinks; intro ink and tree dimensions stay unchanged', async ({ page }, testInfo) => {
|
||||
@@ -460,7 +460,7 @@ test('continuous motion overlaps growth, travel and reveal without intermediate
|
||||
await expect(root).toHaveCount(1);
|
||||
await expect(page.locator('.document-pane[data-reveal]')).not.toHaveAttribute('inert');
|
||||
await expect(page.locator('[data-glitching]')).toHaveCount(0);
|
||||
await expect(page.locator(selectedContent + ' h1')).toHaveText('1. コンセプト');
|
||||
await expect(page.locator(selectedContent).getByRole('heading', { level: 1, name: 'WIP', exact: true })).toBeVisible();
|
||||
await expect(page.locator('.branch-lines')).toHaveCount(0);
|
||||
await expect(page.locator('.demo-node')).toHaveCount(treeNodeCount);
|
||||
await expect(page.getByRole('treeitem')).toHaveCount(treeNodeCount);
|
||||
@@ -557,7 +557,7 @@ test('landing contains only the real filename tree and selected canonical conten
|
||||
await expect(page.getByRole('button', { name: '本文を読む' })).toHaveCount(0);
|
||||
await expect(page.getByRole('link', { name: 'Home', exact: true })).toHaveCount(0);
|
||||
await expect(page.locator('.site-header')).toContainText('WIP');
|
||||
await expect(page.getByRole('link', { name: 'Source', exact: true })).toBeVisible();
|
||||
await expect(page.locator('.site-header').getByRole('link', { name: 'Source', exact: true })).toBeVisible();
|
||||
await expect(page.locator('.demo-node')).toHaveCount(treeNodeCount);
|
||||
await expect(page.getByRole('treeitem')).toHaveCount(treeNodeCount);
|
||||
expect(await page.locator('.demo-node').evaluateAll((nodes) => nodes.map((node) => (node as HTMLElement).dataset.path))).toEqual(treePaths);
|
||||
@@ -609,10 +609,14 @@ test('landing contains only the real filename tree and selected canonical conten
|
||||
expect(folder).not.toHaveProperty('html');
|
||||
expect(folder.href).toBe(new URL(path === '/' ? './' : 'book/', testInfo.project.use.baseURL!).pathname);
|
||||
}
|
||||
await expect(page.locator(stage)).toHaveAttribute('data-current-path', initialPath);
|
||||
await expect(nodeAt(page, initialPath)).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(page.locator(stage)).toHaveAttribute('data-current-path', '/');
|
||||
await expect(nodeAt(page, '/')).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(nodeAt(page, '/')).toHaveAttribute('aria-current', 'page');
|
||||
await expect(nodeAt(page, initialPath)).toHaveAttribute('aria-selected', 'false');
|
||||
await expect(page.locator(selectedContent)).toBeVisible();
|
||||
await expect(page.locator(selectedContent + ' h1')).toHaveText('1. コンセプト');
|
||||
await expect(page.locator(selectedContent).getByRole('heading', { level: 1, name: 'WIP', exact: true })).toBeVisible();
|
||||
await expect(page.locator(selectedContent + ' .root-page[data-root-page]')).toHaveCount(1);
|
||||
await expect(page.locator(selectedContent)).not.toContainText('1. コンセプト');
|
||||
expect(await page.locator('.landing h1, .landing h2, .landing h3, .landing h4, .landing h5, .landing h6').evaluateAll((headings) => headings.every((heading) => heading.closest('[data-selected-content]')))).toBe(true);
|
||||
await checkGlyphRefs(page);
|
||||
});
|
||||
@@ -667,7 +671,10 @@ test('each file navigates to exactly its Book HTML and title, including links',
|
||||
documents.set(path, { html: await book.locator('article.prose').innerHTML(), title: await book.title() });
|
||||
}
|
||||
await book.close();
|
||||
expect(await page.locator(selectedContent).innerHTML()).toBe(documents.get(initialPath)!.html);
|
||||
expect(await page.locator(selectedContent).innerHTML()).not.toBe(documents.get(initialPath)!.html);
|
||||
await nodeAt(page, initialPath).click();
|
||||
await expect(page).toHaveURL(bookURL(initialPath, testInfo.project.use.baseURL!));
|
||||
await expect.poll(() => page.locator(selectedContent).innerHTML()).toBe(documents.get(initialPath)!.html);
|
||||
for (const path of documentPaths) {
|
||||
await nodeAt(page, path).click();
|
||||
await expect(page).toHaveURL(bookURL(path, testInfo.project.use.baseURL!));
|
||||
@@ -692,9 +699,15 @@ test('keyboard arrows only move focus or fold; Enter and Space activate route li
|
||||
const unchanged = async () => {
|
||||
expect(page.url()).toBe(originalURL);
|
||||
expect(await page.locator(selectedContent).innerHTML()).toBe(originalHTML);
|
||||
await expect(nodeAt(page, initialPath)).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(nodeAt(page, '/')).toHaveAttribute('aria-selected', 'true');
|
||||
};
|
||||
await expect(nodeAt(page, '/')).toBeFocused();
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await expect(nodeAt(page, '/book')).toBeFocused();
|
||||
await unchanged();
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await expect(nodeAt(page, initialPath)).toBeFocused();
|
||||
await unchanged();
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await expect(nodeAt(page, '/1.1-interaction-abstraction.md')).toBeFocused();
|
||||
await expect(nodeAt(page, '/1.1-interaction-abstraction.md')).toHaveAttribute('aria-selected', 'false');
|
||||
@@ -867,10 +880,19 @@ test.describe('glyph trunk regressions', () => {
|
||||
test.describe('JavaScript-free glyph tree', () => {
|
||||
test.use({ javaScriptEnabled: false });
|
||||
|
||||
test('initial canonical article and every file link remain usable without JavaScript', async ({ page }, testInfo) => {
|
||||
test('independent home article and every file link remain usable without JavaScript', async ({ page }, testInfo) => {
|
||||
await page.goto('./');
|
||||
await expect(page.locator(selectedContent)).toBeVisible();
|
||||
await expect(page.locator(selectedContent + ' h1')).toHaveText('1. コンセプト');
|
||||
await expect(page.locator(selectedContent).getByRole('heading', { level: 1, name: 'WIP', exact: true })).toBeVisible();
|
||||
await expect(page.locator(stage)).toHaveAttribute('data-current-path', '/');
|
||||
await expect(nodeAt(page, '/')).toHaveAttribute('aria-current', 'page');
|
||||
await expect(nodeAt(page, '/')).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(page.locator(selectedContent)).not.toContainText('1. コンセプト');
|
||||
const home = page.locator(selectedContent + ' .root-page[data-root-page]');
|
||||
await expect(home).toContainText('Worldspace Interface Protocol');
|
||||
const nav = home.getByRole('navigation', { name: 'ルートページのナビゲーション', exact: true });
|
||||
await expect(nav.getByRole('link', { name: /^Book(?:\s|$)/ })).toHaveAttribute('href', new URL('book/', testInfo.project.use.baseURL!).pathname);
|
||||
await expect(nav.getByRole('link', { name: /^Source(?:\s|$)/ })).toHaveAttribute('href', (await page.locator('.site-header').getByRole('link', { name: 'Source', exact: true }).getAttribute('href'))!);
|
||||
const initialHTML = await page.locator(selectedContent).innerHTML();
|
||||
await expect(page.locator('.static-guides, .guide-body, .ascii-panel')).toHaveCount(0);
|
||||
await expect(page.getByRole('treeitem')).toHaveCount(treeNodeCount);
|
||||
@@ -884,7 +906,10 @@ test.describe('JavaScript-free glyph tree', () => {
|
||||
await expect(page.locator('.demo-node')).toHaveCount(treeNodeCount);
|
||||
await expect(nodeAt(page, path)).toHaveAttribute('aria-current', 'page');
|
||||
await expect(page.locator(stage)).toHaveAttribute('data-current-path', path);
|
||||
if (path === initialPath) expect(await page.locator('article.prose').innerHTML()).toBe(initialHTML);
|
||||
if (path === initialPath) {
|
||||
await expect(page.locator('article.prose h1')).toHaveText('1. コンセプト');
|
||||
expect(await page.locator('article.prose').innerHTML()).not.toBe(initialHTML);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -904,7 +929,7 @@ test.describe('JavaScript-free glyph tree', () => {
|
||||
expect(Math.abs(trunk.axis)).toBeLessThan(.1);
|
||||
expect(trunk.gapRatio).toBeCloseTo(1 / 14, 5);
|
||||
await page.locator('.demo-tree').screenshot({ path: testInfo.outputPath('no-js-glyph-tree.png') });
|
||||
await page.getByRole('link', { name: 'Book', exact: true }).click();
|
||||
await page.getByRole('navigation', { name: 'ルートページのナビゲーション', exact: true }).getByRole('link', { name: /^Book(?:\s|$)/ }).click();
|
||||
await expect(page).toHaveURL(/\/book\/$/);
|
||||
await expect(nodeAt(page, '/book')).toHaveAttribute('aria-current', 'page');
|
||||
await expect(page.locator('.landing a[href$="/book/1-concept/"]').last()).toBeVisible();
|
||||
@@ -928,6 +953,12 @@ test('changing motion preference and resizing cannot strand the intro', async ({
|
||||
await expect(page.locator('html')).toHaveAttribute('data-landing', 'playing');
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
await complete(page);
|
||||
// The dedicated home is deliberately short; retain the mobile reading-scroll
|
||||
// regression on the long canonical chapter rather than requiring home filler.
|
||||
await nodeAt(page, initialPath).click();
|
||||
await expect(page.locator(selectedContent + ' h1')).toHaveText('1. コンセプト');
|
||||
// Keep the wheel outside the tree's overscroll-contained scroll viewport.
|
||||
await page.mouse.move(5, page.viewportSize()!.height / 2);
|
||||
await page.mouse.wheel(0, 650);
|
||||
await expect.poll(() => page.evaluate(() => scrollY)).toBeGreaterThan(0);
|
||||
});
|
||||
@@ -936,14 +967,14 @@ test('blocked animation module fails open to readable content', async ({ page })
|
||||
await page.route('**/*.js', (route) => route.abort());
|
||||
await page.goto('./');
|
||||
await expect(page.locator('html')).not.toHaveAttribute('data-landing', { timeout: 6000 });
|
||||
await expect(page.locator(selectedContent + ' h1')).toHaveText('1. コンセプト');
|
||||
await expect(page.locator(selectedContent).getByRole('heading', { level: 1, name: 'WIP', exact: true })).toBeVisible();
|
||||
await expect(page.locator(selectedContent)).toBeVisible();
|
||||
await nodeAt(page, '/2-core-model.md').click();
|
||||
await expect(page).toHaveURL(/\/book\/2-core-model\/$/);
|
||||
await expect(page.locator('article.prose h1')).toBeVisible();
|
||||
await page.goto('./');
|
||||
await expect(page.locator(selectedContent)).toBeVisible();
|
||||
await page.getByRole('link', { name: 'Book', exact: true }).click();
|
||||
await page.locator('.site-header').getByRole('link', { name: 'Book', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/book\/$/);
|
||||
await expect(nodeAt(page, '/book')).toHaveAttribute('aria-current', 'page');
|
||||
await expect(page.locator('.landing a[href$="/book/1-concept/"]').last()).toBeVisible();
|
||||
|
||||
Reference in New Issue
Block a user