abedaniels's picture
feat: make the landing page just the header and the about card
ee13518
Raw History Blame Contribute Delete
6.93 kB
// Check the built guide against the local app, without allocating a GPU.
const { chromium } = require('playwright');
const assert = require('node:assert/strict');
const { mkdir } = require('node:fs/promises');
const path = require('node:path');
(async () => {
const base = process.env.LLMON_TEST_URL || 'http://127.0.0.1:7860';
const browser = await chromium.launch({ executablePath: process.env.LLMON_CHROMIUM_PATH });
try {
const page = await browser.newPage();
// Pin the theme so the palette assertions see the dark palette (the
// redesigned pages follow the stored theme, which defaults to light).
await page.addInitScript(() => localStorage.setItem('llmon_theme', 'dark'));
const errors = [];
const apiCalls = [];
page.on('pageerror', error => errors.push(error.message));
page.on('request', request => {
if (/\/(api|gradio_api)\//.test(new URL(request.url()).pathname)) apiCalls.push(request.url());
});
for (const width of [1440, 390, 320]) {
await page.setViewportSize({ width, height: 1000 });
const response = await page.goto(base + '/how-it-works/index.html', { waitUntil: 'networkidle' });
assert.equal(response.status(), 200);
assert(!/Mamba|hatched/i.test(await page.locator('body').innerText()));
await page.getByRole('heading', { name: 'The point of LLMON: follow the selected task', exact: true }).waitFor();
await page.getByText('Yes, the model sees the selection rule too.', { exact: false }).waitFor();
const guide = page.getByRole('link', { name: 'How it works', exact: true });
const box = await guide.boundingBox();
assert(box && box.x >= 0 && box.x + box.width <= width, 'Guide entry must be visible at the top left on mobile');
await page.getByRole('button', { name: '2. Find the targets', exact: true }).focus();
await page.keyboard.press('Enter');
await page.getByText('Target instruction · selected', { exact: true }).waitFor();
await page.getByText('Target data · selected', { exact: true }).waitFor();
assert.equal(await page.locator('[data-guide-category="data_t"]').evaluate(el => getComputedStyle(el).borderLeftColor), 'rgb(69, 137, 255)');
const distractor = page.locator('[data-sketch-category="instr_d1"]');
assert.equal(await distractor.evaluate(el => getComputedStyle(el).borderLeftColor), 'rgb(218, 30, 40)');
await page.getByRole('button', { name: 'CB', exact: true }).click();
assert.equal(await distractor.evaluate(el => getComputedStyle(el).borderLeftColor), 'rgb(230, 159, 0)');
await page.getByRole('button', { name: 'CB', exact: true }).click();
assert.equal(await distractor.evaluate(el => getComputedStyle(el).borderLeftColor), 'rgb(218, 30, 40)');
await page.getByRole('button', { name: '3. Check the answer', exact: true }).click();
await page.getByLabel('Expected answer: 12', { exact: true }).waitFor();
await page.getByRole('button', { name: '1. Read the prompt', exact: true }).click();
assert.equal(await page.getByLabel('Expected answer: 12', { exact: true }).count(), 0);
const next = page.getByRole('button', { name: 'Next piece →', exact: true });
const previous = page.getByRole('button', { name: '← Previous', exact: true });
assert(await previous.isDisabled());
assert.equal(await page.locator('[data-sketch-curve="generated"]').count(), 0, 'No earlier output before the first piece');
await next.click();
assert.equal(await page.locator('[data-sketch-curve="generated"]').count(), 1);
for (let step = 1; step < 4; step++) await next.click();
assert(await next.isDisabled());
await page.getByText('Output piece 5 of 5', { exact: true }).waitFor();
await previous.click();
await page.getByText('Output piece 4 of 5', { exact: true }).waitFor();
await page.getByRole('button', { name: 'Show piece 1: The', exact: true }).click();
assert(await previous.isDisabled());
for (const details of await page.locator('details').all()) {
await details.locator('summary').focus();
await page.keyboard.press('Enter');
assert(await details.evaluate(element => element.open));
}
assert(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1), `Overflow at ${width}px`);
assert.equal(await page.getByRole('navigation', { name: 'Visualizations' }).getByRole('link').count(), 2);
assert.equal(await page.locator("a[href='/experiment_1/index.html'], a[href='/experiment_3/index.html']").count(), 0);
assert.equal(await page.locator("main a[href='/experiment_2/index.html?example=2']").count(), 1);
if (process.env.LLMON_GUIDE_SCREENSHOTS) {
await mkdir(process.env.LLMON_GUIDE_SCREENSHOTS, { recursive: true });
await page.evaluate(() => scrollTo(0, 0));
await page.screenshot({ path: path.join(process.env.LLMON_GUIDE_SCREENSHOTS, `guide-${width}.png`), fullPage: true });
}
console.log(`Guide passed: ${width}px; keyboard, example, tokens, layer explanation, no horizontal overflow.`);
}
assert.deepEqual(apiCalls, [], 'The introduction and its illustrations must work without model or inference requests.');
assert.deepEqual(errors, []);
await page.getByRole('link', { name: 'Open Generation Flow' }).click();
await page.waitForURL('**/experiment_2/index.html?example=2');
await page.getByRole('link', { name: 'How it works', exact: true }).click();
await page.waitForURL('**/how-it-works/index.html');
await page.getByRole('heading', { name: 'How it works', exact: true }).waitFor();
for (const width of [1440, 390, 320]) {
await page.setViewportSize({ width, height: 900 });
await page.goto(base + '/', { waitUntil: 'networkidle' });
// The landing links the two views from its header (kebab menu and the
// pill button) and from the about card's two view cards.
const guideCards = page.locator('a[href="./how-it-works/index.html"]');
const flowLinks = page.locator('a[href="./experiment_2/index.html"]');
assert.equal(await guideCards.count(), 1, 'Guide card in the about card');
assert.equal(await flowLinks.count(), 2, 'Pill button and the about card');
await page.getByRole('button', { name: 'More options' }).click();
await page.getByRole('menuitem', { name: 'How it works' }).waitFor();
await page.keyboard.press('Escape');
await page.mouse.move(0, 0);
await page.waitForTimeout(220);
await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1 ? null : (() => { throw new Error('overflow'); })());
}
assert.deepEqual(errors, []);
console.log('Navigation from the guide to a live view and back passed.');
} finally {
await browser.close();
}
})().catch(error => { console.error(error); process.exit(1); });