Page, crawl, Playwright and Lighthouse coverage now include both pitch locales, and the contributor docs match the new route table and chrome. Co-authored-by: Cursor <cursoragent@cursor.com>
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
|
import { SITE_CONFIG } from '../src/app/core/content/site-config';
|
|
import { expectNoOverflow, pagePath } from './helpers';
|
|
|
|
const CHECKED = [
|
|
pagePath('home', 'de'),
|
|
pagePath('home', 'en'),
|
|
pagePath('pitch', 'de'),
|
|
pagePath('pitch', 'en'),
|
|
pagePath('projects', 'de'),
|
|
pagePath('projects', 'en'),
|
|
pagePath('servicesAi', 'de'),
|
|
pagePath('contact', 'de'),
|
|
pagePath('imprint', 'en'),
|
|
'/missing-route',
|
|
];
|
|
|
|
const VIEWPORTS = [320, 768, 1024, 1440] as const;
|
|
|
|
test.describe('layout and crawlability', () => {
|
|
test('does not overflow horizontally on checked routes', async ({ page }) => {
|
|
for (const width of VIEWPORTS) {
|
|
await page.setViewportSize({ width, height: 900 });
|
|
for (const path of CHECKED) {
|
|
await page.goto(path);
|
|
await expectNoOverflow(page, path, width);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('same-origin links and crawl files respond below 400', async ({ page, request }) => {
|
|
const seen = new Set<string>();
|
|
const queue = [pagePath('home', 'de'), pagePath('home', 'en')];
|
|
|
|
while (queue.length > 0) {
|
|
const path = queue.shift() as string;
|
|
if (seen.has(path)) {
|
|
continue;
|
|
}
|
|
seen.add(path);
|
|
|
|
await page.goto(path);
|
|
const { urls, baseURI } = await page.evaluate(() => {
|
|
const values = [
|
|
...Array.from(document.querySelectorAll('a[href]'), (node) => node.getAttribute('href')),
|
|
...Array.from(document.querySelectorAll('[src]'), (node) => node.getAttribute('src')),
|
|
];
|
|
return {
|
|
baseURI: document.baseURI,
|
|
urls: values.filter(
|
|
(value): value is string => typeof value === 'string' && value.length > 0,
|
|
),
|
|
};
|
|
});
|
|
|
|
for (const raw of urls) {
|
|
if (raw.startsWith('mailto:') || raw.startsWith('tel:') || raw.startsWith('#')) {
|
|
continue;
|
|
}
|
|
|
|
const resolved = new URL(raw, baseURI);
|
|
if (resolved.origin !== new URL(baseURI).origin) {
|
|
continue;
|
|
}
|
|
|
|
const next = `${resolved.pathname}${resolved.search}`;
|
|
const response = await request.get(next);
|
|
expect(response.status(), `${raw} from ${path}`).toBeLessThan(400);
|
|
|
|
if (!seen.has(next) && !next.includes('.')) {
|
|
queue.push(next);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const asset of ['/robots.txt', '/sitemap.xml', '/llms.txt', SITE_CONFIG.cvAssetPath]) {
|
|
const response = await request.get(asset);
|
|
expect(response.status(), asset).toBe(200);
|
|
}
|
|
});
|
|
});
|