import AxeBuilder from '@axe-core/playwright'; import { expect, test } from '@playwright/test'; import path from 'node:path'; const rule = { id: '20000000-0000-4000-8000-000000000001', schemaVersion: 1, name: 'Hoge hostbelasting', enabled: true, severity: 'critical', scope: {}, condition: { inputType: 'metric', metric: 'host.cpu.utilization', operator: '>', threshold: 90, recoveryThreshold: 80, aggregation: 'avg', windowSeconds: 60 }, evaluationIntervalSeconds: 30, pendingSeconds: 60, resolveSeconds: 120, cooldownSeconds: 300, unknownBehavior: 'retain-firing-as-unknown', groupBy: [], suppressWhen: ['host.unreachable'], message: { titleKey: 'alerts.rule.title', bodyKey: 'alerts.rule.body' }, revision: 1, currentVersion: 1, }; test.beforeEach(async ({ page }) => { await page.route('**/api/v1/system/status', (route) => route.fulfill({ contentType: 'application/json', body: JSON.stringify({ version: 'test', generatedAt: new Date().toISOString(), overallState: 'healthy', components: [], backup: { state: 'disabled', reason: 'not_configured' }, sourceLag: [] }) })); await page.route('**/api/v1/alert-rules?**', (route) => route.fulfill({ contentType: 'application/json', body: JSON.stringify({ items: [rule] }) })); await page.route('**/api/v1/metrics/catalog', (route) => route.fulfill({ contentType: 'application/json', body: JSON.stringify({ metrics: [{ semanticName: 'host.cpu.utilization', unit: 'percent', defaultAggregation: 'avg' }] }) })); await page.route('**/api/v1/alert-silences**', (route) => route.fulfill({ contentType: 'application/json', body: JSON.stringify({ items: [] }) })); await page.route('**/api/v1/maintenance-windows**', (route) => route.fulfill({ contentType: 'application/json', body: JSON.stringify({ items: [] }) })); await page.route('**/api/v1/alerts?**', (route) => route.fulfill({ contentType: 'application/json', body: JSON.stringify({ items: [] }) })); }); test('alert editor uses Dutch guided choices and rejects an invalid draft', async ({ page }, testInfo) => { test.skip(testInfo.project.name === 'wallboard-chromium', 'De alert-editor is geen wallboardroute.'); await page.goto('/alerts'); await expect(page.getByRole('heading', { name: 'Meldingen en incidenten' })).toBeVisible(); await page.getByRole('button', { name: /Alertregels Detectie en drempels/ }).click(); await expect(page.getByText('Kritiek ยท v1')).toBeVisible(); await expect(page.getByRole('combobox', { name: /Meting/ })).toHaveValue('host.cpu.utilization'); await expect(page.getByRole('option', { name: 'CPU-gebruik van de host (%)' })).toBeAttached(); await expect(page.getByText('host.cpu.utilization')).toHaveCount(0); await expect(page.getByText('host.unreachable')).not.toBeVisible(); await page.getByRole('button', { name: 'Nieuwe regel' }).click(); const save = page.getByRole('button', { name: 'Regel opslaan' }); await expect(save).toBeDisabled(); await page.locator('#alert-rule-name').fill('CPU-waarschuwing'); await page.getByRole('combobox', { name: /Meting/ }).selectOption('host.cpu.utilization'); await expect(save).toBeEnabled(); await page.locator('#alert-rule-recovery-threshold').fill('90'); await expect(save).toBeDisabled(); await page.getByRole('combobox', { name: /Signaalbron/ }).selectOption('event'); await expect(page.getByRole('combobox', { name: /Meting/ })).toHaveCount(0); await expect(page.locator('#alert-rule-threshold')).toHaveValue('3'); await expect(save).toBeEnabled(); await page.getByRole('button', { name: /Stiltes en onderhoud Tijdelijke uitzonderingen/ }).click(); await expect(page.locator('#silence-matcher')).toHaveValue('critical'); await expect(page.locator('#silence-matcher')).toContainText('Kritiek'); await expect(page.locator('#maintenance-selector')).toContainText('Host'); expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth + 1)).toBe(true); const axe = await new AxeBuilder({ page }).analyze(); expect(axe.violations.filter((item) => item.impact === 'serious' || item.impact === 'critical')).toEqual([]); if (process.env.PULSE_CAPTURE_VISUALS) await page.screenshot({ path: path.resolve('../../artifacts/evidence/M11-09', `alert-editor-${testInfo.project.name}.png`), fullPage: true }); });