mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-30 09:21:52 +00:00
112 lines
5.5 KiB
JavaScript
112 lines
5.5 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { once } from 'node:events';
|
|
import test from 'node:test';
|
|
import { chromium } from '@playwright/test';
|
|
import { createConsoleServer } from '../../src/console/server.mjs';
|
|
|
|
const views = [
|
|
['overview', 'Overview'],
|
|
['owner-briefing', 'Briefing'],
|
|
['flow-watch', 'Flow watch'],
|
|
['work', 'Work'],
|
|
['initiative-progress', 'Progress'],
|
|
['fleet', 'Fleet'],
|
|
['communications', 'Conversations'],
|
|
['organization', 'Organization'],
|
|
['evidence', 'Evidence'],
|
|
['delivery', 'Release gates'],
|
|
];
|
|
|
|
async function openDemo(t, viewport) {
|
|
const server = createConsoleServer();
|
|
server.listen(0, '127.0.0.1');
|
|
await once(server, 'listening');
|
|
let browser;
|
|
t.after(async () => {
|
|
await browser?.close();
|
|
await new Promise((resolve) => server.close(resolve));
|
|
});
|
|
browser = await chromium.launch({ headless: true });
|
|
const context = await browser.newContext({ viewport });
|
|
const page = await context.newPage();
|
|
await page.clock.install({ time: new Date('2026-10-01T12:00:00.000Z') });
|
|
await page.goto(`http://127.0.0.1:${server.address().port}/console?demo=1#work`);
|
|
await page.locator('#live-refresh-status[data-generation="1"]').waitFor();
|
|
return { page, context };
|
|
}
|
|
|
|
async function assertSelectedView(page, route, title) {
|
|
const selected = await page.locator('.console-workspace > [data-console-view]:not([hidden])').evaluateAll((sections) =>
|
|
[...new Set(sections.map((section) => section.dataset.consoleView))]);
|
|
assert.deepEqual(selected, [route], `only the ${route} view should be visible`);
|
|
assert.equal(await page.title(), `${title} | TORCH Local Fleet Console`);
|
|
assert.equal(await page.locator(`.console-rail a[aria-current="page"][href="#${route}"]`).count(), 1);
|
|
assert.equal(await page.locator('#project-name').isVisible(), true);
|
|
assert.equal(await page.locator('#snapshot-time').isVisible(), true);
|
|
}
|
|
|
|
test('SCN-console-view-navigation: fragments, direct loads, Back and Forward select one addressable view', async (t) => {
|
|
const { page } = await openDemo(t, { width: 1280, height: 900 });
|
|
await assertSelectedView(page, 'work', 'Work');
|
|
|
|
await page.locator('.console-rail a[href="#fleet"]').click();
|
|
await assertSelectedView(page, 'fleet', 'Fleet');
|
|
await page.locator('.console-rail a[href="#evidence"]').click();
|
|
await assertSelectedView(page, 'evidence', 'Evidence');
|
|
await page.goBack();
|
|
await assertSelectedView(page, 'fleet', 'Fleet');
|
|
await page.goForward();
|
|
await assertSelectedView(page, 'evidence', 'Evidence');
|
|
|
|
await page.goto(`http://127.0.0.1:${new URL(page.url()).port}/console?demo=1#approval-request-list`);
|
|
await page.locator('#live-refresh-status[data-generation="1"]').waitFor();
|
|
await assertSelectedView(page, 'flow-watch', 'Flow watch');
|
|
});
|
|
|
|
test('SCN-console-mobile-navigation: every destination is visible at 390x844 without horizontal hunting', async (t) => {
|
|
const { page } = await openDemo(t, { width: 390, height: 844 });
|
|
assert.equal(await page.locator('.console-rail a').count(), views.length);
|
|
|
|
for (const [route, title] of views) {
|
|
const link = page.locator(`.console-rail a[href="#${route}"]`);
|
|
assert.equal(await link.isVisible(), true, `${title} navigation must remain visible`);
|
|
await link.click();
|
|
await assertSelectedView(page, route, title);
|
|
const widths = await page.evaluate(() => ({
|
|
viewport: innerWidth,
|
|
document: document.documentElement.scrollWidth,
|
|
navigation: document.querySelector('.console-rail').scrollWidth,
|
|
navigationClient: document.querySelector('.console-rail').clientWidth,
|
|
}));
|
|
assert.ok(widths.document <= widths.viewport, `document overflows horizontally: ${JSON.stringify(widths)}`);
|
|
assert.ok(widths.navigation <= widths.navigationClient, `navigation requires horizontal scrolling: ${JSON.stringify(widths)}`);
|
|
}
|
|
});
|
|
|
|
test('SCN-console-view-drafts: navigation and refresh retain unsent edits and the explicit owner preview boundary', async (t) => {
|
|
const { page } = await openDemo(t, { width: 1280, height: 900 });
|
|
const titleInput = page.locator('#task-create-form [name="title"]');
|
|
await page.locator('.task-create-panel > summary').click();
|
|
await titleInput.fill('Unsent route-change draft');
|
|
await page.locator('.console-rail a[href="#flow-watch"]').click();
|
|
const approval = page.locator('.approval-decision-form').first();
|
|
await approval.locator('[name="decision"]').selectOption('approved');
|
|
await approval.locator('[name="note"]').fill('Review remains explicit after navigation.');
|
|
await approval.locator('[data-approval-preview]').click();
|
|
await approval.locator('[data-approval-confirm]:visible').waitFor();
|
|
const previewToken = await approval.getAttribute('data-preview-token');
|
|
|
|
await page.locator('.console-rail a[href="#work"]').click();
|
|
await page.locator('#refresh-console').click();
|
|
await page.locator('#live-refresh-status[data-generation="2"]').waitFor();
|
|
assert.equal(await titleInput.inputValue(), 'Unsent route-change draft');
|
|
|
|
await page.locator('.console-rail a[href="#flow-watch"]').click();
|
|
assert.equal(await approval.getAttribute('data-preview-token'), previewToken);
|
|
assert.equal(await approval.locator('[data-approval-confirm]').isVisible(), true);
|
|
assert.equal(await approval.locator('[name="decision"]').isDisabled(), true);
|
|
assert.equal(await approval.locator('[data-approval-edit]').isVisible(), true);
|
|
assert.match(await approval.locator('.approval-decision-status').innerText(), /bound to this request revision/);
|
|
assert.equal(await page.locator('#approval-request-count').innerText(), '1 open');
|
|
});
|