fix(search): harden authorized results and ordering
This commit is contained in:
@@ -125,6 +125,19 @@ test('FormData body leaves Content-Type unset so fetch provides the boundary', a
|
||||
assert.equal(requestInit.headers['Content-Type'], undefined)
|
||||
})
|
||||
|
||||
test('request forwards its AbortSignal to fetch', async () => {
|
||||
let requestInit
|
||||
const controller = new AbortController()
|
||||
globalThis.fetch = async (_url, init) => {
|
||||
requestInit = init
|
||||
return Response.json({ ok: true })
|
||||
}
|
||||
|
||||
await apiRequest('/search', { signal: controller.signal })
|
||||
|
||||
assert.equal(requestInit.signal, controller.signal)
|
||||
})
|
||||
|
||||
test('base URL normalizer trims whitespace and all trailing slashes', () => {
|
||||
assert.equal(normalizeBaseUrl(' https://host.example/// '), 'https://host.example')
|
||||
})
|
||||
|
||||
41
apps/web_v1/scripts/search-request-gate.test.mjs
Normal file
41
apps/web_v1/scripts/search-request-gate.test.mjs
Normal file
@@ -0,0 +1,41 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
import { createSearchRequestGate } from '../src/app/search-request-gate.ts'
|
||||
|
||||
test('starting a new request aborts and invalidates the previous request', () => {
|
||||
const gate = createSearchRequestGate()
|
||||
const first = gate.begin()
|
||||
const second = gate.begin()
|
||||
|
||||
assert.equal(first.signal.aborted, true)
|
||||
assert.equal(first.isCurrent(), false)
|
||||
assert.equal(second.signal.aborted, false)
|
||||
assert.equal(second.isCurrent(), true)
|
||||
})
|
||||
|
||||
test('session cleanup aborts the request and suppresses its stale error', async () => {
|
||||
const gate = createSearchRequestGate()
|
||||
const request = gate.begin()
|
||||
const surfacedErrors = []
|
||||
const oldSessionFailure = Promise.reject(new Error('旧会话搜索失败')).catch((error) => {
|
||||
if (request.isCurrent()) surfacedErrors.push(error.message)
|
||||
})
|
||||
|
||||
gate.invalidate()
|
||||
await oldSessionFailure
|
||||
|
||||
assert.equal(request.signal.aborted, true)
|
||||
assert.equal(request.isCurrent(), false)
|
||||
assert.deepEqual(surfacedErrors, [])
|
||||
})
|
||||
|
||||
test('a request after invalidation belongs to the new session generation', () => {
|
||||
const gate = createSearchRequestGate()
|
||||
const oldSessionRequest = gate.begin()
|
||||
gate.invalidate()
|
||||
const newSessionRequest = gate.begin()
|
||||
|
||||
assert.equal(oldSessionRequest.isCurrent(), false)
|
||||
assert.equal(newSessionRequest.isCurrent(), true)
|
||||
assert.equal(newSessionRequest.signal.aborted, false)
|
||||
})
|
||||
Reference in New Issue
Block a user