feat: add protocol explorer with catalogs and live playground
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { expect, test, type Page } from '@playwright/test';
|
||||
import { load } from 'cheerio';
|
||||
import { bookURL, documentPaths, draftPaths, treeNodeCount, treePaths } from './documents';
|
||||
import { bookURL, documentPaths, draftPaths, treeNodeCount, treePaths, routeURL } from './documents';
|
||||
|
||||
test.use({ javaScriptEnabled: true });
|
||||
|
||||
@@ -8,8 +8,7 @@ const stage = '[data-landing-stage]';
|
||||
const article = 'article.selected-content.prose[data-selected-content]';
|
||||
const nodeAt = (page: Page, path: string) => page.locator(`.demo-node[data-path="${path}"]`);
|
||||
const toggle = (page: Page) => page.locator('button.node-toggle[data-toggle-path="/book"]');
|
||||
const urlFor = (path: string, base: string) => path === '/' ? new URL('./', base).href
|
||||
: path === '/book' ? new URL('book/', base).href : bookURL(path, base);
|
||||
const urlFor = routeURL;
|
||||
|
||||
async function settled(page: Page, path: string) {
|
||||
await expect(page.locator(stage)).toHaveAttribute('data-current-path', path);
|
||||
@@ -82,11 +81,10 @@ test('home response contains independent root content and the unchanged public t
|
||||
expect(copy).toMatch(/インタフェース/);
|
||||
const nav = home.find('nav[aria-label="ルートページのナビゲーション"]');
|
||||
expect(nav.length).toBe(1);
|
||||
expect(nav.find('a').length).toBe(2);
|
||||
expect(nav.find('a').length).toBe(3);
|
||||
expect(nav.find('a').filter((_, el) => $(el).text().includes('Book')).attr('href')).toBe(new URL('book/', base).pathname);
|
||||
const source = $('.site-header a').filter((_, el) => $(el).text().includes('Source')).attr('href');
|
||||
expect(source).toMatch(/^https:\/\//);
|
||||
expect(nav.find('a').filter((_, el) => $(el).text().includes('Source')).attr('href')).toBe(source);
|
||||
expect(nav.find('a').filter((_, el) => $(el).text().includes('Sources')).attr('href')).toBe(new URL('sources/', base).pathname);
|
||||
expect(nav.find('a').filter((_, el) => $(el).text().includes('Packages')).attr('href')).toBe(new URL('packages/', base).pathname);
|
||||
expect($(article).html()).not.toBe(chapter(article).html());
|
||||
expect($(article).text()).not.toContain('1. コンセプト');
|
||||
const chapterCopy = chapter(article).find('p').filter((_, el) => Boolean(chapter(el).text().trim())).first().text().trim();
|
||||
@@ -131,11 +129,10 @@ test('root content navigation works without changing the tree or overflowing nar
|
||||
await expect(home.locator('p').filter({ hasText: 'Worldspace Interface Protocol' })).toBeVisible();
|
||||
await expect(page.locator(article)).not.toContainText('1. コンセプト');
|
||||
const nav = home.getByRole('navigation', { name: 'ルートページのナビゲーション', exact: true });
|
||||
await expect(nav.getByRole('link')).toHaveCount(2);
|
||||
await expect(nav.getByRole('link')).toHaveCount(3);
|
||||
await expect(nav.getByRole('link', { name: /^Book(?:\s|$)/ })).toHaveAttribute('href', new URL('book/', base).pathname);
|
||||
const source = await page.locator('.site-header').getByRole('link', { name: 'Source', exact: true }).getAttribute('href');
|
||||
expect(source).toMatch(/^https:\/\//);
|
||||
await expect(nav.getByRole('link', { name: /^Source(?:\s|$)/ })).toHaveAttribute('href', source!);
|
||||
await expect(nav.getByRole('link', { name: /^Sources(?:\s|$)/ })).toHaveAttribute('href', new URL('sources/', base).pathname);
|
||||
await expect(nav.getByRole('link', { name: /^Packages(?:\s|$)/ })).toHaveAttribute('href', new URL('packages/', base).pathname);
|
||||
if (testInfo.project.name === 'mobile') {
|
||||
for (const width of [320, 360, 390]) {
|
||||
await page.setViewportSize({ width, height: 740 });
|
||||
@@ -155,7 +152,7 @@ test('root content navigation works without changing the tree or overflowing nar
|
||||
|
||||
test('all 14 document responses contain the current article and metadata-only public tree', async ({ request }, testInfo) => {
|
||||
expect(documentPaths).toHaveLength(14);
|
||||
expect(treeNodeCount).toBe(16);
|
||||
expect(treeNodeCount).toBe(19);
|
||||
for (const path of documentPaths) {
|
||||
const url = bookURL(path, testInfo.project.use.baseURL!);
|
||||
const response = await request.get(url);
|
||||
@@ -370,6 +367,7 @@ test('directory anchors navigate independently from the sibling plus/minus toggl
|
||||
const html = await page.locator(article).innerHTML();
|
||||
const title = await page.title();
|
||||
await expect(nodeAt(page, '/book')).toHaveAttribute('href', new URL('book/', base).pathname);
|
||||
await nodeAt(page, '/book').locator('..').hover();
|
||||
await toggle(page).click();
|
||||
await expect(toggle(page)).toHaveText('+');
|
||||
await expect(nodeAt(page, '/book')).toHaveAttribute('aria-expanded', 'false');
|
||||
@@ -378,6 +376,7 @@ test('directory anchors navigate independently from the sibling plus/minus toggl
|
||||
expect(await page.locator(article).innerHTML()).toBe(html);
|
||||
await expect(page).toHaveTitle(title);
|
||||
await expect(nodeAt(page, path)).toHaveAttribute('aria-selected', 'true');
|
||||
await nodeAt(page, '/book').locator('..').hover();
|
||||
await toggle(page).click();
|
||||
await expect(toggle(page)).toHaveText('−');
|
||||
await expect(nodeAt(page, path)).toBeVisible();
|
||||
@@ -404,6 +403,7 @@ test('persisted tree retains scroll and collapse, expanding only an ancestor nee
|
||||
const pane = await page.locator('.tree-pane').elementHandle();
|
||||
const viewport = await page.locator('.tree-viewport').elementHandle();
|
||||
const root = await nodeAt(page, '/').elementHandle();
|
||||
await nodeAt(page, '/4-client.md').locator('..').hover();
|
||||
await page.locator('.node-toggle[data-toggle-path="/4-client.md"]').click();
|
||||
await page.locator('.tree-viewport').evaluate((el) => {
|
||||
(el as HTMLElement).style.height = '120px';
|
||||
@@ -451,7 +451,9 @@ test('home preserves a collapsed root until selecting a child requires expansion
|
||||
await page.goto(bookURL(path, base));
|
||||
await settled(page, path);
|
||||
const pane = await page.locator('.tree-pane').elementHandle();
|
||||
await nodeAt(page, '/4-client.md').locator('..').hover();
|
||||
await page.locator('.node-toggle[data-toggle-path="/4-client.md"]').click();
|
||||
await nodeAt(page, '/book').locator('..').hover();
|
||||
await toggle(page).click();
|
||||
await expect(nodeAt(page, '/book')).toHaveAttribute('aria-expanded', 'false');
|
||||
await nodeAt(page, '/').focus();
|
||||
@@ -573,9 +575,11 @@ test('rapid navigation settles on the last file and repeated swaps do not duplic
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await expect(nodeAt(page, '/1.1-interaction-abstraction.md')).toBeFocused();
|
||||
expect(page.url()).toBe(currentURL);
|
||||
await nodeAt(page, '/book').locator('..').hover();
|
||||
await toggle(page).click();
|
||||
await expect(nodeAt(page, '/book')).toHaveAttribute('aria-expanded', 'false');
|
||||
await expect(toggle(page)).toHaveText('+');
|
||||
await nodeAt(page, '/book').locator('..').hover();
|
||||
await toggle(page).click();
|
||||
await expect(nodeAt(page, '/book')).toHaveAttribute('aria-expanded', 'true');
|
||||
await expect(toggle(page)).toHaveText('−');
|
||||
|
||||
Reference in New Issue
Block a user