test(ui): проверить отмену потока при смене сервера

This commit is contained in:
Denozordec committed 2026-09-24 21:07:44 +07:00
1 parent c563583ccb
commit 2c2a3ef078
2 files changed
+39

No files matched your search

+7
View File
@@ -29,6 +29,13 @@
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Не начат |
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Не начат |
## Блок 8.4К — отмена SSE при смене сервера (2026-09-24)
- Добавлен браузерный сценарий: задержка SSE первого сервера до ответа, переход ко второму, подтверждение requestfailed для отменённой подписки, получение нового измерения и завершение старого обработчика. Старый sample не заменяет данные второго сервера.
- 3 профильных E2E прошли: закрытый SSE, поздний REST с интерфейсом первого сервера и новая проверка отмены SSE. Lint теста/diff-check чистые. Production-код не менялся; build не повторялся.
- Граница проверки: задержка перед получением ответа, не chunk внутри уже открытого ReadableStream. Далее: смена backend, задержка read внутри SSE, свежесть данных и приёмка этапа 8. Реальные IPFIX/RouterOS не проверены.
- Пятичасовое окно обновилось; использовано 10%, недельного — 94%. Локальный коммит без push.
## Блок 8.4И — интерфейс в контексте flow-сервера (2026-09-24)
- Выбор flow-интерфейса хранится вместе с контекстом backend, live/mock, раздела, источника и объекта. Чужой интерфейс не используется при первом рендере нового контекста. При выборе карточки фильтр сбрасывается; синхронный сброс через useEffect удалён.
+32
View File
@@ -190,3 +190,35 @@ test('Flow: интерфейс прежнего сервера не переда
await expect(page.getByText('Второй сервер', { exact: true }).filter({ visible: true })).toBeVisible()
await expect(page.getByText('Категория 15m', { exact: true })).toHaveCount(0)
})
test('Flow: смена сервера отменяет старую SSE-подписку', async ({ page }) => {
await setup(page)
await page.getByRole('button', { name: '15м', exact: true }).click()
await expect(page.getByText('Категория 15m', { exact: true }).filter({ visible: true })).toBeVisible()
let release = () => {}
const gate = new Promise<void>(resolve => { release = resolve })
let completed = () => {}
const delivered = new Promise<void>(resolve => { completed = resolve })
await page.route('**/api/traffic/flow/live?**', async route => {
const old = new URL(route.request().url()).searchParams.get('serverId') === '1'
if (old) await gate
const sample = { bpsNow: old ? 99000000 : 7000000, bytes: 200, packets: 2, conversations: 1, uniqueSrc: 1, uniqueDst: 1, topProto: 'TCP', topCategory: old ? 'SSE прежнего сервера' : 'SSE текущего сервера', rxSeries: [1], txSeries: [2], applications: [], protocols: [], sources: [], destinations: [], interfaces: [], conversationsList: [], ifaces: [], live: true }
try {
await route.fulfill({ contentType: 'text/event-stream', body: 'event: sample\ndata: ' + JSON.stringify(sample) + '\n\n' })
} finally {
if (old) completed()
}
})
const oldRequest = page.waitForRequest(r => r.url().includes('/flow/live?') && r.url().includes('serverId=1'))
await page.getByRole('button', { name: '5м', exact: true }).click()
await oldRequest
const aborted = page.waitForEvent('requestfailed', r => r.url().includes('/flow/live?') && r.url().includes('serverId=1'))
await page.getByRole('button').filter({ hasText: 'Экспортёр второй' }).click()
await aborted
await expect(page.getByText('SSE текущего сервера', { exact: true }).filter({ visible: true })).toBeVisible()
release()
await delivered
await expect(page.getByText('SSE прежнего сервера', { exact: true })).toHaveCount(0)
await expect(page.getByText('SSE текущего сервера', { exact: true }).filter({ visible: true })).toBeVisible()
await expect(page.getByLabel('Скорость потоков')).toContainText('7.00 Мбит/с')
})