Merge branch 'main' of https://git.sparkus.cn/yangzhao/server
This commit is contained in:
@@ -46,7 +46,8 @@ export default async function (ctx: FunctionContext) {
|
||||
}
|
||||
//console.log(data);
|
||||
let res2 = await db.collection(dbname).where({ _id: uid }).update(data);
|
||||
if (res2.ok && res2.updated == 1) {
|
||||
// 同值保存不会增加 updated;匹配到用户且操作成功也属于保存成功。
|
||||
if (res2.ok && (res2.updated == 1 || res2.matched == 1)) {
|
||||
return { code: 1, data: null, msg: "用户数据更新成功" }
|
||||
} else {
|
||||
return { code: 0, data: null, msg: "用户数据更新失败" }
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
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 }]);
|
||||
});
|
||||
Reference in New Issue
Block a user