MatchMaster/server/laf-cloud/tests/wucai-client.test.mjs
2026-08-21 18:09:01 +08:00

154 lines
8.5 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
test("client stores migration state and exposes all transfer actions", async () => {
const [gameManager, gameConfig, utils, miniGameSdk] = await Promise.all([
readFile(new URL("../../../assets/Script/GameManager.ts", import.meta.url), "utf8"),
readFile(new URL("../../../assets/Script/module/Config/GameConfig.ts", import.meta.url), "utf8"),
readFile(new URL("../../../assets/Script/module/Pay/Utils.ts", import.meta.url), "utf8"),
readFile(new URL("../../../assets/Script/Sdk/MiniGameSdk.ts", import.meta.url), "utf8"),
]);
assert.match(gameConfig, /wucai_type:\s*number/);
assert.match(gameConfig, /wucai_type:\s*-1/);
assert.match(gameConfig, /wucai_preview:\s*any/);
assert.match(gameConfig, /wucai_reward_popup_pending:\s*boolean/);
assert.match(gameManager, /GM_INFO\.wucai_type\s*=\s*Number\.isInteger/);
assert.match(gameManager, /GM_INFO\.wucai_preview\s*=\s*data\.data\.wucai_preview \|\| null/);
assert.match(gameManager, /GM_INFO\.wucai_reward_popup_pending\s*=/);
assert.match(gameManager, /GM_INFO\.wucai_type === 1/);
assert.match(utils, /"claim_reward"\s*\|\s*"choose_wucai"\s*\|\s*"choose_current"\s*\|\s*"ack_reward_popup"/);
assert.match(utils, /Utils\.POST\("wucaiTransfer"/);
assert.match(utils, /action === "claim_reward"[\s\S]*GM_INFO\.coin = coinAmount/);
assert.match(utils, /StorageMessage\.setStorage\("coin"/);
assert.match(utils, /StorageMessage\.setStorage\("prop"/);
assert.match(utils, /action === "choose_wucai" \|\| action === "choose_current"[\s\S]*MiniGameSdk\.API\.reboot\(\)/);
assert.match(miniGameSdk, /userSet\(\{ transferred_from_wucai: transferred \}\)/);
});
test("Wucai transfer analytics report the final choice and both archive levels", async () => {
const [gameManager, utils, miniGameSdk] = await Promise.all([
readFile(new URL("../../../assets/Script/GameManager.ts", import.meta.url), "utf8"),
readFile(new URL("../../../assets/Script/module/Pay/Utils.ts", import.meta.url), "utf8"),
readFile(new URL("../../../assets/Script/Sdk/MiniGameSdk.ts", import.meta.url), "utf8"),
]);
assert.match(miniGameSdk, /shushu_Track\("transfer_from_wucai",\s*\{/);
assert.match(miniGameSdk, /already_xiaoxiao:\s*alreadyXiaoxiao/);
assert.match(miniGameSdk, /choose_xiaoxiao:\s*chooseXiaoxiao/);
assert.match(miniGameSdk, /wucai_level:\s*toCurrentLevel\(wucaiLevelAmount\)/);
assert.match(miniGameSdk, /xiaoxiao_level:\s*toCurrentLevel\(xiaoxiaoLevelAmount\)/);
assert.match(miniGameSdk, /levelAmount !== null[\s\S]*level \+ 1[\s\S]*-1/);
const updateIndex = gameManager.indexOf("update(dt)");
const loginIndex = gameManager.indexOf("this.loginShushuOnce();", updateIndex);
const pendingChoiceIndex = gameManager.indexOf("GM_INFO.wucai_type === 1", updateIndex);
assert.ok(updateIndex >= 0 && loginIndex > updateIndex && pendingChoiceIndex > loginIndex);
assert.match(gameManager, /loginShushuOnce\(\)[\s\S]*shushu_Login\(\)/);
assert.match(gameManager, /const transferred = wucaiType === 0 \|\| wucaiType === 2 \|\| wucaiType === 3/);
assert.match(gameManager, /shushu_userSetTransferredFromWucai\(transferred\)/);
assert.match(gameManager, /shushu_TrackWucaiTransfer\(0, 0, this\.autoWucaiLevelAmount, null\)/);
assert.match(utils, /action === "choose_current" \? 1 : 0/);
assert.match(utils, /res\.code === 1 && isProgressChoice && wasPendingChoice/);
assert.match(utils, /shushu_TrackWucaiTransfer\([\s\S]*wucaiLevelAmount,[\s\S]*xiaoxiaoLevelAmount/);
assert.match(utils, /shushu_userSetTransferredFromWucai\(true\)/);
});
test("new-user registration is independent of local cache and does not wait for analytics login", async () => {
const gameManager = await readFile(
new URL("../../../assets/Script/GameManager.ts", import.meta.url),
"utf8"
);
assert.doesNotMatch(gameManager, /pendingRegisterEvent/);
assert.match(gameManager, /if \(data\.data\.isFirst === true\)\s*\{[\s\S]*?this\.setFirstInfo\(\);\s*\}/);
assert.equal((gameManager.match(/this\.setFirstInfo\(\);/g) || []).length, 1);
const analyticsInitIndex = gameManager.indexOf("MiniGameSdk.API.shushu_Init();");
const loginRequestIndex = gameManager.indexOf("Utils.getUserInfo(", analyticsInitIndex);
const cacheBranchIndex = gameManager.indexOf("this.getUserDataToLocal(data.data);", loginRequestIndex);
const registerIndex = gameManager.indexOf("this.setFirstInfo();", cacheBranchIndex);
const loginMethodIndex = gameManager.indexOf("private loginShushuOnce()");
assert.ok(analyticsInitIndex >= 0);
assert.ok(loginRequestIndex > analyticsInitIndex);
assert.ok(cacheBranchIndex > loginRequestIndex);
assert.ok(registerIndex > cacheBranchIndex);
assert.ok(loginMethodIndex > registerIndex);
});
test("a completed progress choice shows the Home reward popup once after reboot", async () => {
const [transfer, home, gameManager] = await Promise.all([
readFile(new URL("../../../assets/Transfer/script/Transfer.ts", import.meta.url), "utf8"),
readFile(new URL("../../../assets/Script/JiaZai.ts", import.meta.url), "utf8"),
readFile(new URL("../../../assets/Script/GameManager.ts", import.meta.url), "utf8"),
]);
assert.match(gameManager, /wucai_reward_popup_pending\s*=\s*[\s\S]*data\.data\.wucai_reward_popup_pending === true/);
assert.match(home, /wucaiType === 0[\s\S]*wucai_reward_popup_pending === true/);
assert.match(transfer, /this\.submit\("ack_reward_popup"\)/);
assert.match(transfer, /action === "claim_reward" \|\| action === "ack_reward_popup"[\s\S]*this\.node\.active = false/);
assert.match(transfer, /action === "claim_reward"[\s\S]*home\.updateCoin\(\)/);
});
test("Home automatic popups wait until the Wucai Transfer popup closes", async () => {
const [transfer, home] = await Promise.all([
readFile(new URL("../../../assets/Transfer/script/Transfer.ts", import.meta.url), "utf8"),
readFile(new URL("../../../assets/Script/JiaZai.ts", import.meta.url), "utf8"),
]);
assert.match(home, /isWucaiTransferBlockingPopups\(\)/);
assert.match(home, /deferHomePopupWhileTransfer\("order"/);
assert.match(home, /deferHomePopupWhileTransfer\("monthlyReward"/);
assert.match(home, /deferHomePopupWhileTransfer\("monthlyCard"/);
assert.match(home, /deferHomePopupWhileTransfer\("starterPack"/);
assert.match(home, /deferHomePopupWhileTransfer\("share"/);
assert.match(home, /deferHomePopupWhileTransfer\("passCheck"/);
assert.match(home, /"jungleTreasure"[\s\S]*initializeJungleTreasureEntryFromLogin/);
assert.match(home, /resumeDeferredHomePopups\(\)/);
assert.match(transfer, /this\.node\.active = false;[\s\S]*this\.notifyHomeTransferClosed\(\)/);
assert.match(transfer, /home\.resumeDeferredHomePopups\(\)/);
});
test("Home Transfer reward glows rotate continuously", async () => {
const transfer = await readFile(
new URL("../../../assets/Transfer/script/Transfer.ts", import.meta.url),
"utf8"
);
for (const nodeName of ["coin_guang", "hammer_guang", "magic_guang", "ice_guang"]) {
assert.match(transfer, new RegExp(nodeName));
}
assert.match(transfer, /cc\.rotateBy\(5, 360\)\.repeatForever\(\)/);
assert.match(transfer, /this\.playHomePopupAnimation\(\)/);
assert.match(transfer, /homeRewardContent\.scale = 0\.8/);
assert.match(transfer, /scale: 1\.05[\s\S]*scale: 1/);
});
test("forcedUpdate is acknowledged only from the completed load gate", async () => {
const gameManager = await readFile(
new URL("../../../assets/Script/GameManager.ts", import.meta.url),
"utf8"
);
const updateIndex = gameManager.indexOf("update(dt)");
const clearIndex = gameManager.indexOf("Utils.setForcedUpdate(");
assert.ok(updateIndex >= 0);
assert.ok(clearIndex > updateIndex);
assert.match(gameManager, /data\.forcedUpdate === true[\s\S]*this\.applyForcedProgress\(data\)/);
assert.match(gameManager, /data\.data\.forcedUpdate === true[\s\S]*effectivePowerTime/);
assert.match(gameManager, /data\.data\.forcedUpdate === true[\s\S]*StorageMessage\.setStorage\("health"/);
assert.match(gameManager, /winStreak !== undefined && data\.data\.winStreak !== null/);
});
test("forcedUpdate backend requires a token and checks the update result", async () => {
const source = await readFile(
new URL("../functions/setForcedUpdate.ts", import.meta.url),
"utf8"
);
assert.match(source, /!res\.data \|\| !res\.data\.token \|\| !token1/);
assert.match(source, /res1\.ok !== false && res1\.updated !== 0/);
assert.doesNotMatch(source, /if \(res\.ok && res1\.updated/);
});