import test from "node:test"; import assert from "node:assert/strict"; import { registerHooks } from "node:module"; const state = { user: null, failUpdate: false, loseMatch: false, legacyResult: false, results: [] }; const profile = { useravatar: "2", username: "player", useravatarIcon: "1", userCat: "3" }; globalThis.__userDataSaveCloudMock = { database() { return { collection() { return { where(query) { return { async getOne() { return { data: state.user?._id === query._id ? structuredClone(state.user) : null }; }, async update(payload) { if (state.loseMatch) state.user = null; const matched = state.user?._id === query._id ? 1 : 0; const updated = !state.failUpdate && matched && Object.entries(payload).some(([key, value]) => state.user[key] !== value) ? 1 : 0; if (updated) Object.assign(state.user, payload); const result = { ok: !state.failUpdate, updated, ...(!state.legacyResult ? { matched } : {}) }; state.results.push(result); return result; }, }; }, }; }, }; }, }; globalThis.__userDataSaveUtilsMock = { checkToken(received, expected) { return received === expected; }, }; registerHooks({ resolve(specifier, context, nextResolve) { if (specifier === "@lafjs/cloud") { return { url: "data:text/javascript,export default globalThis.__userDataSaveCloudMock", shortCircuit: true }; } if (specifier === "@/Utils") { return { url: "data:text/javascript,export default globalThis.__userDataSaveUtilsMock", shortCircuit: true }; } return nextResolve(specifier, context); }, }); const { default: userData } = await import(new URL("../functions/userData.ts", import.meta.url)); function reset() { state.user = { _id: "user-1", token: "token-1", useravatar: "0", username: "user", useravatarIcon: "0", userCat: "1" }; state.failUpdate = false; state.loseMatch = false; state.legacyResult = false; state.results = []; } function save(extra = {}) { return userData({ body: { uid: "user-1", token: "token-1", action: "save", userData: JSON.stringify(profile), ...extra, } }); } test("saving changed and then identical profile data both succeeds", async () => { reset(); const first = await save(); const repeated = await save(); assert.deepEqual(state.results, [ { ok: true, matched: 1, updated: 1 }, { ok: true, matched: 1, updated: 0 }, ]); assert.equal(first.code, 1); assert.equal(repeated.code, 1); assert.deepEqual(state.user, { _id: "user-1", token: "token-1", ...profile }); }); test("a missing uid is rejected without updating", async () => { reset(); assert.equal((await save({ uid: undefined })).code, 0); assert.equal(state.results.length, 0); }); test("an unknown user is not mistaken for an unchanged successful save", async () => { reset(); const before = structuredClone(state.user); assert.equal((await save({ uid: "missing-user" })).code, 0); assert.deepEqual(state.user, before); }); test("losing the matching user during the update remains a failure", async () => { reset(); state.loseMatch = true; assert.equal((await save()).code, 0); assert.deepEqual(state.results, [{ ok: true, matched: 0, updated: 0 }]); }); test("an explicitly failed database update remains a failure", async () => { reset(); state.failUpdate = true; const before = structuredClone(state.user); assert.equal((await save()).code, 0); assert.deepEqual(state.results, [{ ok: false, matched: 1, updated: 0 }]); assert.deepEqual(state.user, before); }); test("an invalid token prevents all writes", async () => { reset(); assert.equal((await save({ token: "wrong-token" })).code, 0); assert.equal(state.results.length, 0); }); test("legacy update results with only ok and updated still succeed", async () => { reset(); state.legacyResult = true; assert.equal((await save()).code, 1); assert.deepEqual(state.results, [{ ok: true, updated: 1 }]); });