Files
ITWorx Pulse release export bd774932d5
Public source validation / validate (push) Failing after 3m8s
Publish ITWorx Pulse source
2026-09-03 02:09:19 +02:00

70 lines
4.4 KiB
TypeScript

import { expect, test, type Page } from '@playwright/test';
import path from 'node:path';
const observedAt = new Date().toISOString();
async function mockResponsiveData(page: Page): Promise<void> {
await page.route('**/api/v1/**', async (route) => {
const pathname = new URL(route.request().url()).pathname;
const body = pathname === '/api/v1/system/status' ? {
version: '1', generatedAt: observedAt, overallState: 'degraded',
components: [
{ id: 'database', state: 'healthy', reason: 'ok' },
{ id: 'prometheus', state: 'unknown', reason: 'source_stale' },
],
backup: { state: 'disabled', reason: 'not_configured' },
sourceLag: [{ sourceId: 'prometheus', state: 'unknown', reason: 'source_stale', ageSeconds: 900 }],
} : pathname === '/api/v1/host' ? {
identity: { name: 'responsive-fixture' }, cpu: { totalPercent: 42, perCore: [42, 38] },
memory: { utilizationPercent: 61 }, source: { state: 'healthy', freshness: 'fresh' },
} : pathname === '/api/v1/containers' ? { source: { state: 'healthy', freshness: 'fresh' }, containers: [], total: 0 }
: pathname === '/api/v1/pools' ? { source: { state: 'healthy', freshness: 'fresh' }, pools: [], total: 0 }
: pathname === '/api/v1/services' ? { capabilityState: 'available', configurationState: 'not_configured', services: [], total: 0 }
: pathname === '/api/v1/incidents' ? { items: [] }
: {};
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(body) });
});
}
test.beforeEach(async ({ page }) => mockResponsiveData(page));
test('mobile primary navigation and operational reasons remain readable at 390px', async ({ page }, testInfo) => {
test.skip(testInfo.project.name !== 'mobile-chromium', 'Mobile evidence uses the supported 390px viewport.');
await page.goto('/');
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
const labels = page.locator('.mobile-primary-list .nav-link span:last-child');
await expect(labels).toHaveCount(4);
const metrics = await labels.evaluateAll((nodes) => nodes.map((node) => {
const box = node.getBoundingClientRect();
return { left: box.left, right: box.right, top: box.top, bottom: box.bottom, font: Number.parseFloat(getComputedStyle(node).fontSize) };
}));
for (let index = 1; index < metrics.length; index += 1) expect(metrics[index - 1].right).toBeLessThanOrEqual(metrics[index].left);
expect(metrics.every((metric) => metric.font >= 12 && metric.bottom - metric.top <= 16)).toBe(true);
const reason = page.locator('.action-queue small').first();
await expect(reason).toBeVisible();
await expect(reason).toHaveCSS('white-space', 'normal');
const overflow = await page.evaluate(() => [...document.querySelectorAll<HTMLElement>('body *')]
.map((element) => ({ tag: element.tagName, className: element.className, right: Math.round(element.getBoundingClientRect().right), scrollWidth: element.scrollWidth, clientWidth: element.clientWidth }))
.filter((item) => item.right > innerWidth + 1 || item.scrollWidth > item.clientWidth + 1)
.slice(0, 12));
expect(overflow).toEqual([]);
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBe(390);
if (process.env.PULSE_CAPTURE_VISUALS) await page.screenshot({ path: path.resolve('../../artifacts/evidence/M12-06/responsive-mobile-390.png'), fullPage: true });
});
test('tablet sidebar stays compact and content uses the remaining viewport', async ({ page }, testInfo) => {
test.skip(testInfo.project.name !== 'tablet-chromium', 'Tablet evidence uses the supported 1024px viewport.');
await page.goto('/');
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
const sidebar = await page.locator('.sidebar').boundingBox();
const workspace = await page.locator('.app-workspace').boundingBox();
const queue = await page.locator('.action-queue').boundingBox();
const dataPlane = await page.locator('.signal-path-panel').boundingBox();
expect(sidebar?.width).toBeLessThanOrEqual(208);
expect(workspace?.width).toBeGreaterThanOrEqual(816);
expect(queue?.width).toBeGreaterThan(300);
expect(dataPlane?.width).toBeGreaterThan(500);
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBe(1024);
if (process.env.PULSE_CAPTURE_VISUALS) await page.screenshot({ path: path.resolve('../../artifacts/evidence/M12-06/responsive-tablet-1024.png'), fullPage: true });
});