From ee3dcdacf27ab735d4be659f94af6f2acb671dd0 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Thu, 24 Sep 2026 21:09:39 +0700 Subject: [PATCH] =?UTF-8?q?test(ui):=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=B8=D1=82=D1=8C=20=D1=82=D1=80=D0=B0=D1=84=D0=B8=D0=BA?= =?UTF-8?q?=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D1=81=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=8B=20=D0=B8=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ux-ui-progress.md | 6 ++++ tests/e2e/backend-switch.e2e.ts | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index dbfa1196..aeee8db7 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -29,6 +29,12 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Не начат | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | Не начат | +## Блок 8.4Л — смена backend трафика (2026-09-24) + +- Добавлен E2E реального пользовательского пути через настройки: задержанное обновление списка старого backend, смена адреса, возврат к трафику, ответ старого источника, повторное обновление нового. Старый список не применяется, обновление отправляется только новому backend. +- Все 3 сценария playwright.backend.config.ts прошли (два прежних Ping 200/500 и новый трафик). Lint теста/diff-check чистые. Production-код не менялся, build не повторялся. +- Граница: переход через настройки размонтирует экран. Это не проверка смены provider без размонтирования и не отдельный flow-backend/SSE сценарий. Далее: задержка внутри открытого SSE, свежесть данных и общая приёмка этапа 8. Реальные IPFIX/RouterOS не проверены. Локальный коммит без push. + ## Блок 8.4К — отмена SSE при смене сервера (2026-09-24) - Добавлен браузерный сценарий: задержка SSE первого сервера до ответа, переход ко второму, подтверждение requestfailed для отменённой подписки, получение нового измерения и завершение старого обработчика. Старый sample не заменяет данные второго сервера. diff --git a/tests/e2e/backend-switch.e2e.ts b/tests/e2e/backend-switch.e2e.ts index 2cf758dc..0e2069b0 100644 --- a/tests/e2e/backend-switch.e2e.ts +++ b/tests/e2e/backend-switch.e2e.ts @@ -54,3 +54,52 @@ for (const status of [200, 500]) { await expect(page.getByRole('button', { name: 'Новая проба', exact: true })).toBeEnabled() }) } + +test('смена backend: поздний список трафика не заменяет новый источник', async ({ page }) => { + let hold = false + let release!: () => void + const gate = new Promise(resolve => { release = resolve }) + const refreshOrigins: string[] = [] + await page.route('**/health', route => route.fulfill({ json: { ok: true } })) + await page.route('**/api/**', async route => { + const url = new URL(route.request().url()) + const isNew = url.port === '8999' + const server = { id: '1', name: isNew ? 'Новый трафик' : 'Старый трафик', site: 'TEST', country: 'RU', status: 'online', rxNow: 2, txNow: 3, rxPeak: 4, txPeak: 5, rxTotal: 100, txTotal: 200, sessions: 1, rxSeries: [1, 2], txSeries: [2, 3] } + if (url.pathname === '/api/traffic/servers') { + if (hold) { + refreshOrigins.push(url.origin) + if (!isNew) await gate + } + return route.fulfill({ json: { servers: [server] } }) + } + const json = url.pathname === '/api/auth/config' ? { required: false } + : url.pathname === '/api/traffic/servers/1' ? { server } + : url.pathname.endsWith('/interfaces') || url.pathname === '/api/traffic/bound-interfaces' ? { interfaces: [] } + : url.pathname === '/api/traffic/users' ? { users: [] } + : url.pathname === '/api/servers' ? [] : {} + if (url.pathname.endsWith('/live')) return route.fulfill({ status: 503, json: {} }) + return route.fulfill({ json }) + }) + await page.goto('/traffic') + await expect(page.getByRole('heading', { name: 'Старый трафик', exact: true })).toBeVisible() + hold = true + const started = page.waitForRequest(r => r.url().includes(':8000/api/traffic/servers?')) + await page.getByRole('button', { name: 'Обновить', exact: true }).click() + await started + await page.locator('a[href="/settings"]').first().click() + const backend = page.getByPlaceholder('http://localhost:8000', { exact: true }) + await backend.fill('http://127.0.0.1:8999') + await backend.press('Enter') + await page.goBack() + await expect(page.getByRole('heading', { name: 'Новый трафик', exact: true })).toBeVisible() + const late = page.waitForResponse(r => r.url().includes(':8000/api/traffic/servers?')) + release() + await late + await expect(page.getByRole('heading', { name: 'Новый трафик', exact: true })).toBeVisible() + await expect(page.getByRole('button').filter({ hasText: 'Старый трафик' })).toHaveCount(0) + const beforeRefresh = refreshOrigins.length + const fresh = page.waitForResponse(r => r.url().includes(':8999/api/traffic/servers?')) + await page.getByRole('button', { name: 'Обновить', exact: true }).click() + await fresh + expect(refreshOrigins.slice(beforeRefresh)).toEqual(['http://127.0.0.1:8999']) +})