Files
kra-new/web/src/utils/latestRequest.test.js
T

78 lines
2.9 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import http from 'node:http'
import axios from 'axios'
import { createLatestRequest } from './latestRequest.js'
test('replacing and closing a query aborts it and invalidates late callbacks', () => {
const scope = createLatestRequest()
const first = scope.start()
let aborted = 0
first.signal.addEventListener('abort', () => aborted++)
const second = scope.start()
assert.equal(aborted, 1)
assert.equal(first.isCurrent(), false)
assert.equal(second.isCurrent(), true)
scope.cancel()
scope.cancel()
assert.equal(second.signal.aborted, true)
assert.equal(second.isCurrent(), false)
const reopened = scope.start()
assert.equal(reopened.signal.aborted, false)
assert.equal(reopened.isCurrent(), true)
})
test('a late response or finally callback cannot overwrite the newly opened query', async () => {
const scope = createLatestRequest()
let resolveOld, resolveNew
const oldResponse = new Promise(resolve => { resolveOld = resolve })
const newResponse = new Promise(resolve => { resolveNew = resolve })
let data = null, loading = false
const load = async response => {
const request = scope.start()
loading = true
try {
const result = await response
if (request.isCurrent()) data = result
} finally { if (request.isCurrent()) loading = false }
}
const old = load(oldResponse)
scope.cancel()
const current = load(newResponse)
resolveOld('old channel')
await old
assert.equal(data, null)
assert.equal(loading, true)
resolveNew('new channel')
await current
assert.equal(data, 'new channel')
assert.equal(loading, false)
})
test('axios cancellation releases the slow HTTP request without cancelling another query', async t => {
const pending = new Map()
let ready
const bothConnected = new Promise(resolve => { ready = resolve })
const server = http.createServer((req, res) => {
pending.set(req.url, res)
if (pending.size === 2) ready()
})
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve))
t.after(() => { server.closeAllConnections(); server.close() })
const firstScope = createLatestRequest(), secondScope = createLatestRequest()
const first = firstScope.start(), second = secondScope.start()
const base = `http://127.0.0.1:${server.address().port}`
const cancelled = axios.get(`${base}/slow`, { signal: first.signal })
const cancellation = assert.rejects(cancelled, error => axios.isCancel(error) && !error.response)
const completed = axios.get(`${base}/other`, { signal: second.signal })
await bothConnected
const disconnected = new Promise(resolve => pending.get('/slow').on('close', resolve))
firstScope.cancel()
await cancellation
await disconnected
assert.equal(second.isCurrent(), true)
assert.equal(second.signal.aborted, false)
pending.get('/other').end('other query finished')
assert.equal((await completed).data, 'other query finished')
})