MatchMaster/tools/coin-madness/check-expiry-sync.cjs

79 lines
4.5 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs');
const ts = require('typescript');
const code = ts.transpileModule(fs.readFileSync('assets/Script/coin_madness/CoinMadnessHost.ts', 'utf8'), {
compilerOptions: { target: ts.ScriptTarget.ES2017, module: ts.ModuleKind.CommonJS, experimentalDecorators: true }
}).outputText;
let now = 100, calls = 0;
const service = { info: { periodId: 'p1', startsAt: 50, endsAt: 200 },
get serverNow() { return now; }, settlementNotice: 0, refreshNeedsRetry: false,
async readForDisplay() { return {}; },
async refresh() { calls++; return {}; },
async retryRecovery() { calls++; return {}; } };
class Component {
constructor() { this.jobs = new Map(); }
schedule(fn, seconds) { this.jobs.set(fn, seconds); }
scheduleOnce(fn, seconds) { this.jobs.set(fn, seconds); }
unschedule(fn) { this.jobs.delete(fn); }
}
const cc = { isValid: () => true, Label: class {}, Button: class {}, Component, _decorator: { ccclass: value => value }, game: { on() {}, off() {} }, warn() {} };
const exportsHost = {};
new Function('require', 'exports', 'cc', code)(name => {
if (name.includes('GoldMinerService')) return { default: { current: () => service } };
return {};
}, exportsHost, cc);
const flush = () => new Promise(resolve => setImmediate(resolve));
(async () => {
const host = new exportsHost.default();
host.updateEntry = host.updateTestEntry = host.refreshCoinDisplay = () => {};
host.start(); await flush();
assert.equal(calls, 1);
assert.equal([...host.jobs.values()].includes(30), false, 'no recurring network poll');
for (let i = 0; i < 100; i++) host.refreshEntryBadge();
assert.equal(calls, 1, 'local ticks do not request');
now = 201; host.refreshEntryBadge(); await flush();
assert.equal(calls, 2, 'expiry requests once');
host.refreshEntryBadge(); await flush(); assert.equal(calls, 2);
service.refreshNeedsRetry = true;
host.resumeSync(); await flush();
for (const delay of [2, 3, 5, 7, 10, 15, 25, 30, 50]) {
assert.equal(host.jobs.get(host.retrySync), delay);
host.retrySync(); await flush();
}
assert.equal(host.jobs.has(host.retrySync), false, 'retry budget exhausted');
let opened = 0, switched = 0;
host.open = () => opened++;
host.openSettlement = () => switched++;
service.settlementNotice = 100;
host.showSettlementNotice(); assert.equal(opened, 1, 'ended before login can show notice');
host.panel = { getComponent: name => name === 'CoinMadnessPanel' ? {} : null };
host.showSettlementNotice(); assert.equal(switched, 1, 'open activity switches to settlement');
host.panel = { getComponent: () => null };
host.showSettlementNotice(); assert.equal(switched, 1, 'existing settlement is not replaced');
host.showSettlementNotice = () => {};
service.refreshNeedsRetry = false;
let animated = 0;
host.panel = { getComponent: () => ({ rewardSaved: () => animated++ }) };
service.request = async (action, body, saved) => { saved(100); return {code:1,data:{granted:100}}; };
await host.requestActivity(service,'claim',{});
assert.equal(animated, 1);
assert(host.isCoinDisplayHeld(), 'successful credit waits for animation');
host.rewardArrived(); assert.equal(host.isCoinDisplayHeld(),false);
service.request = async () => ({code:0});
await host.requestActivity(service,'claim',{});
assert.equal(host.isCoinDisplayHeld(),false,'failed claim does not hold the balance');
let loads = 0;
host.node = { getComponent: () => ({ openLoad: () => loads++, closeLoad: () => loads-- }) };
host.setEntryLoading(true); host.setEntryLoading(true); assert.equal(loads, 1);
host.setEntryLoading(false); host.setEntryLoading(false); assert.equal(loads, 0);
const label = { string: '' }, time = { active: true, getComponent: () => label }, bg = { active: true };
host.entry = { getComponent: () => null, getChildByName: name => name === 'time' ? time : name === 'timeBg' ? bg : null };
host.syncing = true;
service.info.endsAt = now + 90061000;
// Fixture serverNow and endsAt use milliseconds.
host.refreshEntryBadge(); assert.equal(label.string, '1天1时');
service.info.endsAt = now + 3661000; host.refreshEntryBadge(); assert.equal(label.string, '01:01:01');
service.info.endsAt = now; host.refreshEntryBadge(); assert.equal(label.string, ''); assert.equal(bg.active, false);
console.log('PASS: local countdown, expiry sync, bounded retries and settlement display');
})().catch(error => { console.error(error); process.exitCode = 1; });