92 lines
5.5 KiB
JavaScript
92 lines
5.5 KiB
JavaScript
const test = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
const vm = require('node:vm')
|
|
const ts = require('typescript')
|
|
function load(file, deps = {}) {
|
|
const exports = {}
|
|
vm.runInNewContext(ts.transpileModule(fs.readFileSync(path.join(__dirname, '..', file), 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 } }).outputText, { exports, require: id => deps[id], setTimeout, clearTimeout })
|
|
return exports
|
|
}
|
|
const ritual = load('src/utils/incenseRitual.ts')
|
|
const mock = load('src/utils/tiangongMock.ts', { './incenseRitual': ritual })
|
|
const { createTiangongStore } = load('src/utils/tiangongStore.ts', { './tiangongMock': mock, './incenseRitual': ritual })
|
|
const defer = () => { let resolve, reject; const promise = new Promise((ok, fail) => { resolve = ok; reject = fail }); return { promise, resolve, reject } }
|
|
function harness() {
|
|
let key = 'account-a', time = 1000, rows = [{ id: 81, name: '财神', holdingId: 726, active: true, incenseCount: 7, days: 3 }]
|
|
let loader = async () => rows, offer = async () => ({ id: 99 })
|
|
const calls = []
|
|
const store = createTiangongStore({ key: () => key, now: () => time, resolve: name => name === '财神' ? 'wealth' : undefined,
|
|
load: () => loader(), offer: (...args) => { calls.push(args); return offer(...args) }, dedicate: async (...args) => { calls.push(args); return { id: 100 } } })
|
|
return { store, calls, key: value => { key = value }, time: value => { time = value }, rows: value => { rows = value }, load: value => { loader = value }, offer: value => { offer = value } }
|
|
}
|
|
test('真实状态不预置财神,按后端持有ID提交,后端确认后才计数', async () => {
|
|
const h = harness()
|
|
assert.equal(h.store.snapshot().deities.wealth.unlocked, false)
|
|
await h.store.refresh()
|
|
const response = defer(); h.offer(() => response.promise)
|
|
const request = h.store.incense('wealth')
|
|
assert.equal(h.store.snapshot().deities.wealth.incenseCount, 7)
|
|
assert.equal(h.store.snapshot().deities.wealth.lit, false)
|
|
assert.equal(h.calls[0][0], 726); assert.equal(h.calls[0][1], 2)
|
|
response.resolve({ id: 10 }); await request
|
|
assert.equal(h.store.snapshot().deities.wealth.incenseCount, 8)
|
|
assert.equal(h.store.snapshot().deities.wealth.incenseUntil, 16000)
|
|
})
|
|
test('失败无计数无自动重试;晚到查询不覆盖已确认上香', async () => {
|
|
const h = harness(); await h.store.refresh()
|
|
h.offer(async () => { throw new Error('网络失败') })
|
|
await assert.rejects(h.store.incense('wealth'), /网络失败/)
|
|
assert.equal(h.calls.length, 1); assert.equal(h.store.snapshot().deities.wealth.incenseCount, 7)
|
|
const read = defer(); h.load(() => read.promise)
|
|
const refreshing = h.store.refresh(true)
|
|
h.offer(async () => ({ id: 1 })); await h.store.incense('wealth')
|
|
read.resolve([{ name: '财神', holdingId: 726, active: true, incenseCount: 7 }]); await refreshing
|
|
assert.equal(h.store.snapshot().deities.wealth.incenseCount, 8)
|
|
})
|
|
test('乱序并发响应逐次累计,不让旧点击缩短最后截止时间', async () => {
|
|
const h = harness(); await h.store.refresh()
|
|
const a = defer(), b = defer(); let count = 0
|
|
h.offer(() => (++count === 1 ? a : b).promise)
|
|
const first = h.store.incense('wealth'); h.time(4000); const second = h.store.incense('wealth')
|
|
b.resolve({ id: 2 }); assert.equal((await second).startsRound, true)
|
|
a.resolve({ id: 1 }); assert.equal((await first).startsRound, false)
|
|
assert.equal(h.store.snapshot().deities.wealth.incenseCount, 9)
|
|
assert.equal(h.store.snapshot().deities.wealth.incenseUntil, 19000)
|
|
h.time(19001); assert.equal(h.store.snapshot().deities.wealth.lit, false)
|
|
})
|
|
|
|
test('写入在途不采纳可能已包含该流水的GET,避免回包后再次加一', async () => {
|
|
const h = harness(); await h.store.refresh()
|
|
const response = defer(), read = defer()
|
|
h.load(() => read.promise)
|
|
const refreshing = h.store.refresh(true)
|
|
h.offer(() => response.promise); const sending = h.store.incense('wealth')
|
|
read.resolve([{ name: '财神', holdingId: 726, active: true, incenseCount: 8 }]); await refreshing
|
|
assert.equal(h.store.snapshot().deities.wealth.incenseCount, 7)
|
|
await h.store.refresh(true)
|
|
response.resolve({ id: 2 }); await sending
|
|
assert.equal(h.store.snapshot().deities.wealth.incenseCount, 8)
|
|
})
|
|
test('切换账号丢弃旧响应,不以Mock兜底;未绑定不可提交', async () => {
|
|
const h = harness(); await h.store.refresh()
|
|
const response = defer(); h.offer(() => response.promise)
|
|
const sending = h.store.incense('wealth')
|
|
h.key('account-b'); assert.equal(h.store.snapshot().deities.wealth.unlocked, false)
|
|
response.resolve({ id: 10 }); await assert.rejects(sending, /登录状态/)
|
|
h.rows([]); await h.store.refresh()
|
|
await assert.rejects(h.store.incense('wealth'), /绑定/)
|
|
h.load(async () => { throw new Error('未部署') }); await assert.rejects(h.store.refresh(true), /未部署/)
|
|
assert.equal(h.store.snapshot().deities.wealth.unlocked, false)
|
|
})
|
|
test('祈愿和任意姓名回向去空白提交,不携带功德或注册收件人ID', async () => {
|
|
const h = harness(); await h.store.refresh()
|
|
await h.store.wish('wealth', ' 愿顺遂 ')
|
|
await h.store.dedicate('wealth', ' 家人 ', ' 平安 ')
|
|
assert.deepEqual(h.calls, [[726, 3, '愿顺遂'], [726, '家人', '平安']])
|
|
await assert.rejects(h.store.wish('wealth', ' '), /愿望/)
|
|
await assert.rejects(h.store.dedicate('wealth', '', '祝愿'), /回向对象/)
|
|
assert.equal(h.calls.length, 2)
|
|
})
|