90 lines
3.4 KiB
JavaScript
90 lines
3.4 KiB
JavaScript
const assert = require('node:assert/strict')
|
|
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
const test = require('node:test')
|
|
const ts = require('typescript')
|
|
|
|
const source = fs.readFileSync(path.join(__dirname, '../src/utils/im-chat-archive-trigger.ts'), 'utf8')
|
|
const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText
|
|
const mod = { exports: {} }
|
|
new Function('module', 'exports', compiled)(mod, mod.exports)
|
|
const { createImChatArchiveTrigger } = mod.exports
|
|
const deferred = () => {
|
|
let resolve, reject
|
|
const promise = new Promise((a, b) => { resolve = a; reject = b })
|
|
return { promise, resolve, reject }
|
|
}
|
|
|
|
test('all pages use server-owned current-doctor scope and carry the continuation token', async () => {
|
|
const calls = []
|
|
const sync = createImChatArchiveTrigger(async params => {
|
|
calls.push(params)
|
|
return { completed: calls.length === 3, sync_token: 'next-page' }
|
|
})
|
|
await sync(12116)
|
|
assert.deepEqual(calls, [
|
|
{ diagnosis_id: 12116, scope: 'current', sync_token: undefined },
|
|
{ diagnosis_id: 12116, scope: 'current', sync_token: 'next-page' },
|
|
{ diagnosis_id: 12116, scope: 'current', sync_token: 'next-page' }
|
|
])
|
|
})
|
|
|
|
test('many events while syncing coalesce, then perform one catch-up scan for new messages', async () => {
|
|
const page = deferred()
|
|
let calls = 0
|
|
const sync = createImChatArchiveTrigger(() => {
|
|
calls++
|
|
return calls === 1 ? page.promise : Promise.resolve({ completed: true })
|
|
})
|
|
const first = sync(10)
|
|
assert.equal(sync(10), first)
|
|
assert.equal(sync(10), first)
|
|
assert.equal(calls, 1)
|
|
page.resolve({ completed: true })
|
|
await first
|
|
assert.equal(calls, 2)
|
|
await sync(10)
|
|
assert.equal(calls, 3)
|
|
})
|
|
|
|
test('switching patients keeps in-flight requests bound to their original diagnosis', async () => {
|
|
const old = deferred(), calls = []
|
|
const sync = createImChatArchiveTrigger(params => {
|
|
calls.push(params)
|
|
if (params.diagnosis_id === 10 && !params.sync_token) return old.promise
|
|
return Promise.resolve({ completed: true })
|
|
})
|
|
const first = sync(10)
|
|
await sync(20)
|
|
old.resolve({ completed: false, sync_token: 'old-patient' })
|
|
await first
|
|
assert.deepEqual(calls.map(p => [p.diagnosis_id, p.sync_token]), [[10, undefined], [20, undefined], [10, 'old-patient']])
|
|
})
|
|
|
|
test('partial failure and network failure are reported and do not poison later retries', async () => {
|
|
const warnings = []
|
|
let count = 0
|
|
const sync = createImChatArchiveTrigger(async () => {
|
|
count++
|
|
if (count === 1) return { completed: true, errors: ['cloud unavailable'] }
|
|
if (count === 2) throw new Error('request timeout')
|
|
return { completed: true }
|
|
}, error => warnings.push(error.message))
|
|
await sync(10)
|
|
await sync(10)
|
|
await sync(10)
|
|
assert.deepEqual(warnings, ['cloud unavailable', 'request timeout'])
|
|
assert.equal(count, 3)
|
|
})
|
|
|
|
test('invalid IDs never request and missing progress stops a malformed response loop', async () => {
|
|
const warnings = []
|
|
let count = 0
|
|
const sync = createImChatArchiveTrigger(async () => { count++; return { completed: false } }, error => warnings.push(error.message))
|
|
for (const id of [0, -1, NaN, 1.5]) await sync(id)
|
|
assert.equal(count, 0)
|
|
await sync(10)
|
|
assert.equal(count, 1)
|
|
assert.match(warnings[0], /未返回进度/)
|
|
})
|