MatchMaster/tools/coin-madness/check-api-preview.cjs

65 lines
4.6 KiB
JavaScript

const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright');
const assert = require('node:assert/strict');
const fs = require('node:fs');
(async () => {
const browser = await chromium.launch({ headless: true, channel: 'msedge' });
try {
const page = await browser.newPage({ viewport: { width: 450, height: 800 } });
const errors = []; page.on('pageerror', error => errors.push(error.message));
await page.goto('http://127.0.0.1:' + (process.env.PORT || 8765));
await page.waitForFunction(() => window.demo && demo.ready);
await page.evaluate(() => demo.open());
await page.evaluate(async () => {
const bundle = cc.assetManager.getBundle('coin_madness');
const prefab = await new Promise(resolve => bundle.load('prefab/CoinMadness', cc.Prefab, (error, asset) => resolve(asset)));
const node = cc.instantiate(prefab); cc.director.getScene().children[0].addChild(node);
node.zIndex = cc.macro.MAX_ZINDEX;
window.apiPanel = node.getComponent('CoinMadnessPanel');
window.apiCalls = []; window.toasts = [];
window.apiData = { serverNow: Date.now(), status: 'purchasable', state: {
config: { periodId: 'goldMiner:2026-09-17', startsAt: Date.now() - 1000, endsAt: Date.now() + 3600000,
priceCents: 600, stages: [0, 1, 2].map(i => ({ taskId: 'task-' + i, wins: (i + 1) * 2, coins: (i + 1) * 100, claimStatus: 'locked' })) },
paidAt: 0, totalWins: 6, claimed: [false, false, false], stage: 0, settled: false } };
apiPanel.initialize(null, { request: async (action, body) => {
apiCalls.push({ action, body });
if (action === 'claim') {
apiData.state.claimed[body.stage] = true;
apiData.state.config.stages[body.stage].claimStatus = 'claimed';
apiData.state.config.stages[body.stage + 1].claimStatus = 'claimable';
}
return { code: 1, data: JSON.parse(JSON.stringify(apiData)) };
}, close() { node.destroy(); }, openHelp() {}, toast: message => toasts.push(message), openSettlement() {} });
});
await page.waitForFunction(() => apiPanel.data && !apiPanel.busy);
assert.equal(await page.evaluate(() => apiPanel.debugTools.active), false);
assert.equal(await page.evaluate(() => apiPanel.priceDigits.text), '6.00');
assert.equal(await page.evaluate(() => apiPanel.purchaseButton.active), true);
assert.equal(await page.evaluate(() => apiPanel.content.children[0].getChildByName('Claim').active), false);
await page.evaluate(() => {
apiData.status = 'unlocked'; apiData.state.paidAt = 1;
apiData.state.config.stages[0].claimStatus = 'claimable'; apiPanel.render(apiData);
apiPanel.content.children[1].emit(cc.Node.EventType.TOUCH_END, { stopPropagation() {} });
});
assert.equal(await page.evaluate(() => apiCalls.filter(c => c.action === 'claim').length), 0);
assert.match(await page.evaluate(() => toasts[0]), /前一档/);
await page.evaluate(() => {
for (let i = 0; i < 2; i++) apiPanel.content.children[0].emit(cc.Node.EventType.TOUCH_END, { stopPropagation() {} });
});
await page.waitForFunction(() => !apiPanel.busy && apiPanel.data.state.claimed[0]);
assert.equal(await page.evaluate(() => apiCalls.filter(c => c.action === 'claim').length), 1);
assert.equal(await page.evaluate(() => apiPanel.purchaseButton.active), false);
assert.equal(await page.evaluate(() => apiPanel.content.children[1].getChildByName('Claim').active), true);
fs.mkdirSync('.codex_tmp/coinmadness-api', { recursive: true });
await page.screenshot({ path: '.codex_tmp/coinmadness-api/unlocked.png' });
await page.evaluate(() => {
apiData.status = 'unavailable'; apiData.state.paidAt = 0;
apiData.state.config.stages = []; apiData.state.config.endsAt = Date.now() - 1;
delete apiData.state.config.priceCents; apiPanel.render(apiData);
});
assert.equal(await page.evaluate(() => apiPanel.purchaseButton.active), false);
assert.equal(await page.evaluate(() => apiPanel.content.children.filter(c => c.active).length), 0);
assert.deepEqual(errors, []);
console.log('PASS: real asynchronous panel path, dynamic price, hidden debug tools, sequential claim gating, double tap and unavailable state.');
} finally { await browser.close(); }
})().catch(error => { console.error(error); process.exitCode = 1; });