122 lines
6.1 KiB
JavaScript
122 lines
6.1 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { registerHooks } from "node:module";
|
|
|
|
const configUrl = new URL("../functions/dailyTaskConfig.ts", import.meta.url);
|
|
const serviceUrl = new URL("../functions/dailyTaskService.ts", import.meta.url);
|
|
|
|
registerHooks({
|
|
resolve(specifier, context, nextResolve) {
|
|
if (specifier === "@/dailyTaskConfig") return { url: configUrl.href, shortCircuit: true };
|
|
return nextResolve(specifier, context);
|
|
},
|
|
});
|
|
|
|
const { getDayKey, getDayEndsAt, getWeekKey, getWeekEndsAt, refreshTaskData, mergeClientProgress, claimDaily, claimWeekly } = await import(serviceUrl);
|
|
|
|
test("uses Shanghai natural day and Monday week keys", () => {
|
|
assert.equal(getDayKey(Date.parse("2026-09-06T15:59:59Z")), "2026-09-06");
|
|
assert.equal(getDayKey(Date.parse("2026-09-06T16:00:00Z")), "2026-09-07");
|
|
assert.equal(getDayEndsAt(Date.parse("2026-09-06T16:00:00Z")), Date.parse("2026-09-08T00:00:00+08:00"));
|
|
assert.equal(getWeekKey(Date.parse("2026-09-06T16:00:00Z")), "2026-09-07");
|
|
assert.equal(getWeekEndsAt(Date.parse("2026-09-06T16:00:00Z")), Date.parse("2026-09-14T00:00:00+08:00"));
|
|
});
|
|
|
|
test("returns current server time and refreshes it on repeated reads", () => {
|
|
const firstNow = Date.parse("2026-09-07T04:00:00Z");
|
|
const secondNow = firstNow + 5000;
|
|
const first = refreshTaskData(null, "user-time", 20, firstNow).data;
|
|
const second = refreshTaskData(JSON.stringify(first), "user-time", 20, secondNow);
|
|
assert.equal(second.changed, false);
|
|
assert.equal(second.data.serverNow, secondNow);
|
|
assert.equal(second.data.dayEndsAt, Date.parse("2026-09-08T00:00:00+08:00"));
|
|
assert.equal(second.data.weekEndsAt, Date.parse("2026-09-14T00:00:00+08:00"));
|
|
});
|
|
|
|
test("migrates legacy tasks into five v2 stages totaling twenty stars", () => {
|
|
const legacy = JSON.stringify({ levelPass: { value: 3, state: 1 } });
|
|
const result = refreshTaskData(legacy, "user-1", 20, Date.parse("2026-09-04T04:00:00Z"));
|
|
assert.equal(result.changed, true);
|
|
assert.equal(result.data.version, 2);
|
|
assert.equal(result.data.dailyTasks.length, 5);
|
|
assert.equal(result.data.dailyTasks.reduce((sum, task) => sum + task.stars, 0), 20);
|
|
assert.deepEqual(result.data.dailyTasks.map(task => task.locked), [false, false, false, false, false]);
|
|
});
|
|
|
|
test("keeps the same selection during a day and avoids previous slot tasks next day", () => {
|
|
const first = refreshTaskData(null, "user-2", 20, Date.parse("2026-09-04T04:00:00Z")).data;
|
|
const same = refreshTaskData(JSON.stringify(first), "user-2", 20, Date.parse("2026-09-04T14:00:00Z"));
|
|
assert.equal(same.changed, false);
|
|
assert.deepEqual(same.data.dailyTasks.map(task => task.taskId), first.dailyTasks.map(task => task.taskId));
|
|
const next = refreshTaskData(JSON.stringify(first), "user-2", 20, Date.parse("2026-09-05T04:00:00Z")).data;
|
|
next.dailyTasks.forEach((task, index) => assert.notEqual(task.taskId, first.dailyTasks[index].taskId));
|
|
});
|
|
|
|
test("all daily tasks accumulate and can be claimed in any order", () => {
|
|
const data = refreshTaskData(null, "user-3", 20, Date.parse("2026-09-04T04:00:00Z")).data;
|
|
const submitted = structuredClone(data);
|
|
submitted.dailyTasks.forEach(task => task.value = task.target);
|
|
mergeClientProgress(data, submitted);
|
|
assert.ok(data.dailyTasks.every(task => task.state === 1 && !task.locked));
|
|
for (const task of [...data.dailyTasks].reverse()) {
|
|
assert.equal(claimDaily(data, task.taskId).ok, true);
|
|
assert.equal(claimDaily(data, task.taskId).ok, false);
|
|
}
|
|
assert.equal(data.weeklyStars, 20);
|
|
});
|
|
|
|
test("opens stored locked tasks immediately without resetting progress or rewards", () => {
|
|
const now = Date.parse("2026-09-04T04:00:00Z");
|
|
const stored = refreshTaskData(null, "existing-user", 20, now).data;
|
|
stored.dailyTasks.forEach((task, index) => task.locked = index > 0);
|
|
stored.dailyTasks[4].value = stored.dailyTasks[4].target;
|
|
stored.dailyTasks[4].state = 1;
|
|
const original = structuredClone(stored);
|
|
const result = refreshTaskData(JSON.stringify(stored), "existing-user", 20, now);
|
|
assert.equal(result.changed, true);
|
|
assert.deepEqual(result.data.dailyTasks, original.dailyTasks.map(task => ({ ...task, locked: false })));
|
|
assert.deepEqual(result.data.weeklyRewards, original.weeklyRewards);
|
|
assert.equal(result.data.weeklyStars, original.weeklyStars);
|
|
assert.equal(refreshTaskData(JSON.stringify(result.data), "existing-user", 20, now).changed, false);
|
|
assert.equal(claimDaily(result.data, result.data.dailyTasks[4].taskId).ok, true);
|
|
});
|
|
|
|
test("ignores legacy lock flags but still requires completion", () => {
|
|
const data = refreshTaskData(null, "legacy-flags", 20, Date.parse("2026-09-04T04:00:00Z")).data;
|
|
const task = data.dailyTasks[4];
|
|
task.locked = true;
|
|
task.value = 0;
|
|
task.state = 0;
|
|
assert.equal(claimDaily(data, task.taskId).ok, false);
|
|
task.value = task.target;
|
|
task.state = 1;
|
|
assert.equal(claimDaily(data, task.taskId).ok, true);
|
|
assert.ok(data.dailyTasks.every(item => !item.locked));
|
|
});
|
|
|
|
test("daily claims add stars once and weekly tiers claim independently", () => {
|
|
const data = refreshTaskData(null, "user-4", 20, Date.parse("2026-09-04T04:00:00Z")).data;
|
|
for (const task of data.dailyTasks) {
|
|
task.value = task.target;
|
|
task.state = 1;
|
|
task.locked = false;
|
|
assert.equal(claimDaily(data, task.taskId).ok, true);
|
|
}
|
|
assert.equal(data.weeklyStars, 20);
|
|
assert.equal(claimDaily(data, data.dailyTasks[0].taskId).ok, false);
|
|
data.weeklyStars = 140;
|
|
const high = claimWeekly(data, "weekly_140");
|
|
assert.equal(high.ok, true);
|
|
assert.equal(data.weeklyRewards.find(item => item.rewardId === "weekly_35").state, 0);
|
|
});
|
|
|
|
test("daily reset preserves stars while weekly reset clears them", () => {
|
|
const friday = refreshTaskData(null, "user-5", 20, Date.parse("2026-09-04T04:00:00Z")).data;
|
|
friday.weeklyStars = 70;
|
|
const saturday = refreshTaskData(JSON.stringify(friday), "user-5", 20, Date.parse("2026-09-05T04:00:00Z")).data;
|
|
assert.equal(saturday.weeklyStars, 70);
|
|
const monday = refreshTaskData(JSON.stringify(saturday), "user-5", 20, Date.parse("2026-09-07T04:00:00Z")).data;
|
|
assert.equal(monday.weeklyStars, 0);
|
|
assert.ok(monday.weeklyRewards.every(reward => reward.state === 0));
|
|
});
|