import AxeBuilder from '@axe-core/playwright'; import { expect, test } from '@playwright/test'; const enabled = Boolean(process.env.PULSE_E2E_REAL_BASE_URL); test('storage map keeps physical identity and signal severities truthful', async ({ page }) => { test.skip(!enabled, 'Run against an isolated real stack with the M11-03 storage fixture.'); const login = await page.request.get('/auth/test-login'); expect(login.ok()).toBeTruthy(); const disks = await (await page.request.get('/api/v1/disks?limit=100')).json() as { disks: Array<{ id: string; state: string; capacitySeverity: string; thermalSeverity: string }> }; expect(disks.disks.find((disk) => disk.id === 'disk-10')).toMatchObject({ state: 'online', capacitySeverity: 'critical', thermalSeverity: 'normal' }); expect(disks.disks.find((disk) => disk.id === 'cache')).toMatchObject({ state: 'online', capacitySeverity: 'attention', thermalSeverity: 'critical' }); const pools = await (await page.request.get('/api/v1/pools?limit=100')).json() as { pools: Array<{ id: string; state: string; capacitySeverity: string }> }; expect(pools.pools.find((pool) => pool.id === 'cache')).toMatchObject({ state: 'healthy', capacitySeverity: 'attention' }); await page.goto('/storage'); await expect(page.getByRole('heading', { level: 1, name: 'Opslagoverzicht' })).toBeVisible(); const visualNodes = page.locator('.storage-map-node'); await expect(visualNodes).toHaveCount(3); await expect(visualNodes.filter({ hasText: 'disk10' })).toHaveCount(1); await expect(visualNodes.filter({ hasText: 'disk10' })).toContainText('capaciteit kritiek'); await expect(visualNodes.filter({ hasText: 'cache' })).toHaveCount(2); await expect(page.locator('.storage-heatmap-cell')).toHaveCount(2); await expect(page.locator('.storage-heatmap-cell--critical')).toHaveCount(1); const overflow = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth); expect(overflow).toBeLessThanOrEqual(1); const accessibility = await new AxeBuilder({ page }).analyze(); expect(accessibility.violations.filter((violation) => ['serious', 'critical'].includes(violation.impact ?? ''))).toEqual([]); });