Second webServer builds fixtures/sparse (no sources) on 4379; third-party allow-list now derives from the configured servers; the embed test re-checks blocked requests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
63 lines
2.6 KiB
TypeScript
63 lines
2.6 KiB
TypeScript
import { expect, test, type Page } from '@playwright/test';
|
|
import { blockThirdParty } from './helpers.ts';
|
|
|
|
// fixtures/sparse: one project, no items, no issues, no external sources (see playwright.config.ts).
|
|
test.use({ baseURL: 'http://localhost:4379' });
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await blockThirdParty(page);
|
|
});
|
|
|
|
const PAGES = ['/', '/work/', '/off-the-clock/', '/off-the-clock/issues/', '/everything/', '/simple/'];
|
|
|
|
// Visible containers with neither text nor a link/image/svg/media/control inside.
|
|
async function emptyBoxes(page: Page): Promise<string[]> {
|
|
return page.evaluate(() => {
|
|
const out: string[] = [];
|
|
const sel = 'section, article, aside, nav, ul, ol, dl, [class*="card"], [class*="strip"], [class*="now"], [class*="wall"], [class*="box"]';
|
|
for (const el of document.querySelectorAll<HTMLElement>(sel)) {
|
|
if (el.closest('template, script, [hidden]') || !el.getClientRects().length) continue;
|
|
const cs = getComputedStyle(el);
|
|
if (cs.visibility === 'hidden' || cs.display === 'none') continue;
|
|
const text = (el.innerText ?? '').trim();
|
|
const content = el.querySelector('a, button, img, svg, canvas, video, audio, iframe, input, picture');
|
|
if (!text && !content) {
|
|
const id = el.id ? `#${el.id}` : '';
|
|
out.push(`${el.tagName.toLowerCase()}${id}.${el.className}`);
|
|
}
|
|
}
|
|
return out;
|
|
});
|
|
}
|
|
|
|
for (const path of PAGES) {
|
|
test(`${path} renders cleanly`, async ({ page }) => {
|
|
const res = await page.goto(path);
|
|
expect(res!.status()).toBe(200);
|
|
const text = await page.locator('body').innerText();
|
|
expect(text).not.toMatch(/\bundefined\b|\bnull\b|\bNaN\b|\[object/);
|
|
expect(await emptyBoxes(page)).toEqual([]);
|
|
await expect(page.locator('h1, h2').first()).toBeVisible();
|
|
});
|
|
}
|
|
|
|
test('personal side shows its warm empty line, with no cards or writing', async ({ page }) => {
|
|
await page.goto('/off-the-clock/');
|
|
await expect(page.locator('[data-wall-card]')).toHaveCount(0);
|
|
await expect(page.getByText('Nothing pinned up yet. The first few things are on their way.')).toBeVisible();
|
|
await expect(page.getByText(/Latest writing/i)).toHaveCount(0);
|
|
});
|
|
|
|
test('no writing boxes or "Latest writing" anywhere', async ({ page }) => {
|
|
for (const path of PAGES) {
|
|
await page.goto(path);
|
|
await expect(page.getByText(/Latest writing/i), path).toHaveCount(0);
|
|
await expect(page.locator('[class*="writing"]:visible'), path).toHaveCount(0);
|
|
}
|
|
});
|
|
|
|
test('the work side still shows its one project', async ({ page }) => {
|
|
await page.goto('/work/');
|
|
await expect(page.locator('a[href="/work/fixture-dashboard/"]').first()).toBeVisible();
|
|
});
|