import { observedTrafficFixturePayload } from "./traffic-observation-fixture" import { test, expect } from '@playwright/test' for (const variant of ['missing-sessions', 'negative-series', 'monthly-missing', 'monthly-mismatch'] as const) { test(`Потоки: некорректный HTTP DTO ${variant} даёт ошибку и повтор без потери контекста`, async ({ page }) => { let bad = true const errors: string[] = [] const queries: Array<{ range: string | null; month: string | null; serverId: string | null }> = [] const monthlyCase = variant.startsWith('monthly') const stats = { bpsNow: 1000000, bytes: 200, packets: 2, conversations: 1, uniqueSrc: 1, uniqueDst: 1, topProto: 'TCP', topCategory: 'Восстановлено', rxSeries: [1], txSeries: [2], applications: [], protocols: [], sources: [], destinations: [], interfaces: [], conversationsList: [], ifaces: [], live: false } const card = { id: '1', name: 'Экспортёр DTO', subtitle: '', site: 'TEST', country: 'RU', status: 'online', rxNow: 2, txNow: 3, sessions: 1, bytes: 200, rxSeries: [1], txSeries: [2] } page.on('pageerror', error => errors.push(error.message)) await page.route('**/health', route => route.fulfill({ json: observedTrafficFixturePayload({ ok: true }) })) await page.route('**/api/**', route => { const url = new URL(route.request().url()), path = url.pathname if (path === '/api/traffic/flow/analytics' || path === '/api/traffic/flow/monthly') { if (path.endsWith(monthlyCase ? '/monthly' : '/analytics')) queries.push({ range: url.searchParams.get('range'), month: url.searchParams.get('month'), serverId: url.searchParams.get('serverId') }) if (path.endsWith('/monthly')) { const month = url.searchParams.get('month')! const data = bad && variant === 'monthly-missing' ? { month, bytes: 1500 } : { month: bad && variant === 'monthly-mismatch' ? (month === '2026-01' ? '2026-02' : '2026-01') : month, bytes: 1500, countries: [], services: [], asns: [] } return route.fulfill({ json: observedTrafficFixturePayload(data) }) } const data = bad && variant === 'missing-sessions' ? { ...stats, conversationsList: undefined } : bad && variant === 'negative-series' ? { ...stats, rxSeries: [-1] } : stats return route.fulfill({ json: observedTrafficFixturePayload(data) }) } if (path.endsWith('/live')) return route.fulfill({ status: 503, json: observedTrafficFixturePayload({}) }) const json = path === '/api/auth/config' ? { required: false } : path === '/api/traffic/flow/exporters' ? { exporters: [card] } : path === '/api/traffic/flows' ? { exportersOnline: 1, bytesPerMin: 200, uniqueSrc: 1, uniqueDst: 1, topProto: 'TCP', talkers: [], listenerBound: true } : path === '/api/traffic/servers' ? { servers: [] } : path === '/api/traffic/users' ? { users: [] } : path === '/api/traffic/flow/clients' ? { clients: [] } : path.endsWith('/interfaces') ? { interfaces: [] } : path === '/api/servers' ? [{ id: 1, name: card.name, host: '127.0.0.1', port: 80, useSsl: false, verifySsl: false, username: 'admin', password: '', type: 'jump-host', site: 'TEST', country: 'RU', asn: '', comment: '', enabled: true, lanSubnet: '', wanUplinks: [], createdAt: '', updatedAt: '', status: null, latency: null, os: null, model: null, uptime: null, cpuLoad: null, freeMemory: null, totalMemory: null, identityName: null, sessions: 0, polledAt: null }] : {} return route.fulfill({ json: observedTrafficFixturePayload(json) }) }) await page.goto('/traffic') await page.getByRole('group', { name: 'Разделы трафика' }).getByRole('button', { name: 'Потоки', exact: true }).click() if (monthlyCase) await page.getByRole('button', { name: 'Месяц', exact: true }).click() const alert = page.getByRole('alert').filter({ hasText: 'Аналитика недоступна' }) await expect(alert).toBeVisible() await expect(alert).toContainText(variant === 'monthly-mismatch' ? 'данные другого месяца' : 'некорректный ответ сервера') await expect(page.getByLabel('Скорость потоков')).toHaveCount(0) const selected = queries.at(-1)! expect(selected.serverId).toBe('1') bad = false await page.getByRole('button', { name: 'Повторить аналитику', exact: true }).click() await expect(alert).toHaveCount(0) expect(queries.at(-1)).toEqual(selected) if (!monthlyCase) await expect(page.getByLabel('Скорость потоков')).toBeVisible() expect(errors).toEqual([]) }) }