import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' import { parse } from '@vue/compiler-sfc' import ts from 'typescript' function harness(arrange = false) { const script = parse(readFileSync(new URL('../src/components/business/pl-plan-quota-dialog/index.vue', import.meta.url), 'utf8')).descriptor.scriptSetup!.content const ast = ts.createSourceFile('quota.ts', script, ts.ScriptTarget.Latest, true) const method = ast.statements.find(n => ts.isFunctionDeclaration(n) && n.name?.text === 'accept')!.getText(ast) let finish!: () => void const pending = new Promise(r => { finish = r }) const callbacks: any[] = [] const state: any = { plan: { value: { planId: 'a' } }, busy: { value: false }, visible: { value: true }, forArrange: { value: arrange }, forSupplement: { value: false }, result: { value: { status: 'available' } }, preview: () => pending, payload: () => ({ purchaseCertIds: ['p'] }), planQuotaApi: { save: () => pending }, ElMessage: { success() {}, warning() {} } } const js = ts.transpileModule(`let epoch=0; let resolve=(v)=>callbacks.push(['old',v]);${method};return {run:accept,change:()=>{epoch++;plan.value={planId:'b'};busy.value=true;resolve=(v)=>callbacks.push(['new',v])}}`, {compilerOptions:{target:ts.ScriptTarget.ES2022}}).outputText const actions = new Function(...Object.keys(state), 'callbacks', js)(...Object.values(state), callbacks) return { ...actions, state, callbacks, finish } } for (const arrange of [false, true]) test(`stale ${arrange ? 'preview' : 'save'} cannot resolve or close the next session`, async () => { const h = harness(arrange), task = h.run() h.change(); h.finish(); await task assert.deepEqual(h.callbacks, []) assert.equal(h.state.visible.value, true) assert.equal(h.state.busy.value, true) })