MatchMaster/server/laf-cloud/tests/monthly-card-renewal.test.mjs
2026-08-13 20:08:01 +08:00

159 lines
5.1 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { registerHooks } from "node:module";
const monthlyCardUrl = new URL("../functions/monthlyCard.ts", import.meta.url);
const MONTH_CARD_DURATION = 30 * 24 * 60 * 60 * 1000;
const NOW = 1_800_000_000_000;
const state = { user: null, orders: [] };
globalThis.__monthlyCardCloudMock = {
database() {
return {
collection(name) {
return {
where(query) {
return {
async getOne() {
if (name === "order") {
return { data: state.orders.find((order) => matches(order, query)) || null };
}
return { data: state.user && matches(state.user, query) ? state.user : null };
},
async update(payload) {
if (name === "order") {
const orders = state.orders.filter((order) => matches(order, query));
orders.forEach((order) => Object.assign(order, payload));
return { updated: orders.length };
}
if (state.user && matches(state.user, query)) {
Object.assign(state.user, payload);
return { updated: 1 };
}
return { updated: 0 };
},
};
},
};
},
};
},
};
globalThis.__monthlyCardUtilsMock = {
checkToken(received, expected) {
return received === expected;
},
};
registerHooks({
resolve(specifier, context, nextResolve) {
if (specifier === "@lafjs/cloud") {
return { url: "data:text/javascript,export default globalThis.__monthlyCardCloudMock", shortCircuit: true };
}
if (specifier === "@/Utils") {
return { url: "data:text/javascript,export default globalThis.__monthlyCardUtilsMock", shortCircuit: true };
}
return nextResolve(specifier, context);
},
});
const { default: monthlyCard } = await import(monthlyCardUrl);
const realDateNow = Date.now;
Date.now = () => NOW;
test.after(() => { Date.now = realDateNow; });
function matches(target, query) {
return Object.entries(query || {}).every(([key, value]) => target?.[key] === value);
}
function reset({ monthCardTime = 0, monthCardReward = 0, granted = false } = {}) {
state.user = { _id: "user-1", openid: "openid-1", monthCardTime, monthCardReward };
state.orders = [{
outTradeNo: "order-1",
openid: "openid-1",
itemid: "month_Card",
state: 1,
monthCardGranted: granted,
}];
}
function save(outTradeNo = "order-1") {
return monthlyCard({ body: { action: "save", uid: "user-1", outTradeNo } });
}
test("first purchase starts a 30-day month card", async () => {
reset();
const result = await save();
assert.equal(result.code, 1);
assert.equal(state.user.monthCardTime, NOW + MONTH_CARD_DURATION);
assert.equal(state.user.monthCardReward, 0);
assert.equal(state.orders[0].state, 2);
assert.equal(state.orders[0].monthCardGranted, true);
});
test("renewal extends from the existing expiry and preserves today's claim state", async () => {
const currentExpiry = NOW + 12 * 24 * 60 * 60 * 1000;
const rewardTime = NOW - 60_000;
reset({ monthCardTime: currentExpiry, monthCardReward: rewardTime });
await save();
assert.equal(state.user.monthCardTime, currentExpiry + MONTH_CARD_DURATION);
assert.equal(state.user.monthCardReward, rewardTime);
});
test("three different paid orders accumulate 30, 60, then 90 days", async () => {
reset();
await save("order-1");
assert.equal(state.user.monthCardTime, NOW + MONTH_CARD_DURATION);
for (const [outTradeNo, days] of [["order-2", 60], ["order-3", 90]]) {
state.orders.push({
outTradeNo,
openid: "openid-1",
itemid: "month_Card",
state: 1,
monthCardGranted: false,
});
await save(outTradeNo);
assert.equal(state.user.monthCardTime, NOW + days * 24 * 60 * 60 * 1000);
}
});
test("expired card restarts from now and resets the claim state", async () => {
reset({ monthCardTime: NOW - 1, monthCardReward: NOW - 60_000 });
await save();
assert.equal(state.user.monthCardTime, NOW + MONTH_CARD_DURATION);
assert.equal(state.user.monthCardReward, 0);
});
test("the same paid order cannot extend the card twice", async () => {
reset();
await save();
const firstExpiry = state.user.monthCardTime;
const result = await save();
assert.equal(result.code, 1);
assert.equal(result.data.alreadyGranted, true);
assert.equal(state.user.monthCardTime, firstExpiry);
});
test("a legacy completed order without a grant marker cannot be replayed", async () => {
reset({ monthCardTime: NOW + MONTH_CARD_DURATION });
state.orders[0].state = 2;
delete state.orders[0].monthCardGranted;
const expiry = state.user.monthCardTime;
const result = await save();
assert.equal(result.code, 1);
assert.equal(result.data.alreadyGranted, true);
assert.equal(state.user.monthCardTime, expiry);
});
test("saving without a paid order number is rejected", async () => {
reset();
const result = await save("");
assert.equal(result.code, 0);
assert.match(result.msg, /订单号/);
assert.equal(state.user.monthCardTime, 0);
});