test(ui): проверить поздний фрагмент открытого потока

This commit is contained in:
Denozordec committed 2026-09-28 11:12:06 +07:00
1 parent 53bca894bb
commit 7318c5286b
3 files changed
+73 -3

No files matched your search

+63
View File
@@ -222,3 +222,66 @@ test('Flow: смена сервера отменяет старую SSE-подп
await expect(page.getByText('SSE текущего сервера', { exact: true }).filter({ visible: true })).toBeVisible()
await expect(page.getByLabel('Скорость потоков')).toContainText('7.00 Мбит/с')
})
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()
// Deliberately let the mock stream deliver a chunk after abort. This exercises
// the post-read guard, independently of the browser transport's cancellation.
await page.evaluate(() => {
const originalFetch = window.fetch.bind(window)
const state = { pending: false, aborted: false, delivered: false, release: () => {} }
Object.assign(window, { delayedFlowStream: state })
window.fetch = async (input, init) => {
const url = new URL(input instanceof Request ? input.url : String(input), location.href)
if (url.pathname !== '/api/traffic/flow/live') return originalFetch(input, init)
const old = url.searchParams.get('serverId') === '1'
const sample = (late = false) => ({
bpsNow: old ? (late ? 99000000 : 1000000) : 7000000,
bytes: 200, packets: 2, conversations: 1, uniqueSrc: 1, uniqueDst: 1,
topProto: 'TCP', topCategory: old ? (late ? 'Поздний фрагмент' : 'Открытый поток первого') : 'Открытый поток второго',
rxSeries: [1], txSeries: [2], applications: [], protocols: [], sources: [],
destinations: [], interfaces: [], conversationsList: [], ifaces: [], live: true,
})
const encode = (late = false) => new TextEncoder().encode('event: sample\ndata: ' + JSON.stringify(sample(late)) + '\n\n')
const stream = new ReadableStream<Uint8Array>({
start(controller) {
controller.enqueue(encode())
if (old) state.release = () => controller.enqueue(encode(true))
},
})
const response = new Response(stream, { headers: { 'Content-Type': 'text/event-stream' } })
if (old) {
init?.signal?.addEventListener('abort', () => { state.aborted = true })
const reader = stream.getReader()
const read = reader.read.bind(reader)
let calls = 0
reader.read = async () => {
const delayed = ++calls === 2
if (delayed) state.pending = true
const result = await read()
if (delayed) { state.pending = false; state.delivered = true }
return result
}
stream.getReader = (() => reader) as typeof stream.getReader
}
return response
}
})
await page.getByRole('button', { name: '5м', exact: true }).click()
await expect(page.getByText('Открытый поток первого', { exact: true }).filter({ visible: true })).toBeVisible()
const streamState = () => page.evaluate(() => {
const state = (window as unknown as { delayedFlowStream: { pending: boolean; aborted: boolean; delivered: boolean } }).delayedFlowStream
return { pending: state.pending, aborted: state.aborted, delivered: state.delivered }
})
await expect.poll(streamState).toEqual({ pending: true, aborted: false, delivered: false })
await page.getByRole('button').filter({ hasText: 'Экспортёр второй' }).click()
await expect(page.getByText('Открытый поток второго', { exact: true }).filter({ visible: true })).toBeVisible()
await expect.poll(streamState).toEqual({ pending: true, aborted: true, delivered: false })
await page.evaluate(() => (window as unknown as { delayedFlowStream: { release: () => void } }).delayedFlowStream.release())
await expect.poll(streamState).toEqual({ pending: false, aborted: true, delivered: true })
await expect(page.getByText('Поздний фрагмент', { exact: true })).toHaveCount(0)
await expect(page.getByText('Открытый поток второго', { exact: true }).filter({ visible: true })).toBeVisible()
await expect(page.getByLabel('Скорость потоков')).toContainText('7.00 Мбит/с')
})