72 lines
4.8 KiB
TypeScript
72 lines
4.8 KiB
TypeScript
import { test, expect, type Page } from '@playwright/test'
|
|
import { statisticsDtoSchema } from '../../packages/contracts/src/statistics'
|
|
|
|
async function setup(page: Page, failure = 0) {
|
|
const control = { failure, empty: false, hold: false, release: () => {} }
|
|
const pending = new Promise<void>(resolve => { control.release = resolve })
|
|
await page.route('**/health', route => route.fulfill({ json: { ok: true } }))
|
|
await page.route('**/api/**', async route => {
|
|
const url = new URL(route.request().url())
|
|
if (url.pathname !== '/api/statistics') return route.fulfill({ json: url.pathname === '/api/auth/config' ? { required: false } : url.pathname === '/api/servers' ? [] : {} })
|
|
const from = url.searchParams.get('from')!
|
|
const fail = control.failure
|
|
if (control.hold && from === '2026-09-02') await pending
|
|
if (fail) return route.fulfill({ status: fail, json: { error: 'Статистика временно недоступна' } })
|
|
const n = control.empty ? 0 : 1
|
|
const dto = statisticsDtoSchema.parse({
|
|
from, to: url.searchParams.get('to'), grain: 'day',
|
|
kpis: { bytes: n * 1000, packets: n * 10, avgBps: n * 100, users: n, servers: n, ifaces: n, topCountry: '', topService: '' },
|
|
series: [], servers: [], interfaces: [], countries: [], services: [], asns: [],
|
|
users: n ? [{ id: from, label: `Данные ${from}`, bytes: 1000, packets: 10, bps: 100, percent: 100 }] : [],
|
|
})
|
|
await route.fulfill({ json: dto })
|
|
})
|
|
await page.goto('/statistics?from=2026-09-01&to=2026-09-03&dim=users')
|
|
return control
|
|
}
|
|
|
|
for (const status of [403, 500]) {
|
|
test(`Статистика: ${status} не подменяется нулём; повтор получает подтверждённый пустой ответ`, async ({ page }) => {
|
|
const control = await setup(page, status)
|
|
await expect(page.getByRole('alert').filter({ hasText: 'Ошибка загрузки' })).toContainText('Статистика временно недоступна')
|
|
await expect(page.getByText('Нет данных куба', { exact: true })).toHaveCount(0)
|
|
await expect(page.getByLabel('Сводка трафика')).toHaveCount(0)
|
|
control.failure = 0
|
|
control.empty = true
|
|
await page.getByRole('button', { name: 'Повторить загрузку', exact: true }).click()
|
|
await expect(page.getByText('Нет данных куба', { exact: true })).toBeVisible()
|
|
await expect(page.getByLabel('Сводка трафика')).toBeVisible()
|
|
await expect(page.getByText('Ошибка загрузки', { exact: true })).toHaveCount(0)
|
|
})
|
|
}
|
|
|
|
test('Статистика: смена периода скрывает старые строки и игнорирует поздний ответ', async ({ page }) => {
|
|
const control = await setup(page)
|
|
await expect(page.getByText('Данные 2026-09-01', { exact: true })).toBeVisible()
|
|
control.hold = true
|
|
const waiting = page.waitForRequest(r => r.url().includes('/api/statistics?') && r.url().includes('from=2026-09-02'))
|
|
await page.evaluate(() => window.history.pushState(null, '', '/statistics?from=2026-09-02&to=2026-09-03'))
|
|
await waiting
|
|
await expect(page.getByText('Загрузка статистики…', { exact: true })).toBeVisible()
|
|
await expect(page.getByText('Данные 2026-09-01', { exact: true })).toHaveCount(0)
|
|
await page.evaluate(() => window.history.pushState(null, '', '/statistics?from=2026-09-03&to=2026-09-03'))
|
|
await expect(page.getByText('Данные 2026-09-03', { exact: true })).toBeVisible()
|
|
const old = page.waitForResponse(r => r.url().includes('/api/statistics?') && r.url().includes('from=2026-09-02'))
|
|
control.release()
|
|
await old
|
|
await expect(page.getByText('Данные 2026-09-03', { exact: true })).toBeVisible()
|
|
await expect(page.getByText('Данные 2026-09-02', { exact: true })).toHaveCount(0)
|
|
})
|
|
|
|
test('Статистика: ошибка pivot не показывает метрики и строки прежнего отчёта', async ({ page }) => {
|
|
await setup(page)
|
|
await expect(page.getByText('Данные 2026-09-01', { exact: true })).toBeVisible()
|
|
await page.route('**/api/statistics/pivot?**', route => route.fulfill({ status: 500, json: { error: 'Сводка недоступна' } }))
|
|
await page.getByRole('button', { name: 'Сводка', exact: true }).click()
|
|
await expect(page.getByRole('alert').filter({ hasText: 'Ошибка загрузки' })).toContainText('Сводка недоступна')
|
|
await expect(page.getByLabel('Сводка трафика')).toHaveCount(0)
|
|
await expect(page.getByText('Нет данных куба', { exact: true })).toHaveCount(0)
|
|
await expect(page.getByText('Данные 2026-09-01', { exact: true })).toHaveCount(0)
|
|
await page.screenshot({ path: 'test-results/statistics-error.png', animations: 'disabled' })
|
|
})
|