fix: keep large approval batches observable
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
This commit is contained in:
@@ -329,6 +329,59 @@ test("Xft OpenAPI derives empId server-side and validates ownership before and a
|
||||
assert.equal(actionBodies[0]?.empId, "EMP-1");
|
||||
});
|
||||
|
||||
test("Xft approval batches revalidate each write and share one post-write todo scan", async () => {
|
||||
const billIds = Array.from({ length: 20 }, (_, index) => String(10_000_000_100 + index));
|
||||
const pending = new Set(billIds);
|
||||
let todoQueries = 0;
|
||||
let actionCalls = 0;
|
||||
const client = new XftOpenApiClient(config(), async (input, init) => {
|
||||
const path = new URL(String(input)).pathname;
|
||||
const body = init?.body ? decodedBody(init) : {};
|
||||
if (path.includes("user-mapping")) {
|
||||
return encrypted({ code: "0", data: { records: [{ thirdStaffId: "ding-u1", enterpriseUserId: "EMP-1" }] } });
|
||||
}
|
||||
if (path.endsWith("todo-task/page/by-user")) {
|
||||
todoQueries += 1;
|
||||
return encrypted({ code: "0", data: { records: [...pending].map((billId) => ({
|
||||
todoTaskId: `TD-${billId}`, groupId: billId, appCode: "xft-itrip",
|
||||
})) } });
|
||||
}
|
||||
if (path.endsWith("todo-task/detail/by-ids")) {
|
||||
const taskIds = Array.isArray(body.todoTaskIds) ? body.todoTaskIds : [];
|
||||
return encrypted({ code: "0", data: taskIds.map((taskId) => ({
|
||||
todoTaskId: taskId, businessId: String(taskId).replace(/^TD-/, ""), appCode: "xft-itrip",
|
||||
})) });
|
||||
}
|
||||
if (path.endsWith("bill-list")) {
|
||||
const ids = Array.isArray(body.billIds) ? body.billIds.map(String) : [];
|
||||
return encrypted({ code: "0", data: { list: ids.map((billId) => ({ billId, eventType: "COMMON_REIM" })) } });
|
||||
}
|
||||
if (path.endsWith("approve/pass")) {
|
||||
actionCalls += 1;
|
||||
const businessList = Array.isArray(body.businessList) ? body.businessList : [];
|
||||
const businessId = businessList[0] && typeof businessList[0] === "object"
|
||||
? String((businessList[0] as Record<string, unknown>).businessId)
|
||||
: "";
|
||||
pending.delete(businessId);
|
||||
return encrypted({ code: "0", data: {} });
|
||||
}
|
||||
throw new Error(`unexpected ${path}`);
|
||||
});
|
||||
|
||||
const result = await client.processApprovalBatch(
|
||||
{ userId: "ding-u1" },
|
||||
"agree",
|
||||
"同意",
|
||||
billIds.map((billId) => ({ billId })),
|
||||
);
|
||||
|
||||
assert.equal(result.succeeded, 20);
|
||||
assert.equal(result.failed, 0);
|
||||
assert.equal(actionCalls, 20);
|
||||
assert.equal(todoQueries, 21, "each write needs a live ownership scan, followed by one shared post-write scan");
|
||||
assert.deepEqual(result.results.map((item) => item.billId), billIds);
|
||||
});
|
||||
|
||||
test("Xft submission discovers live templates and derives protected create fields server-side", async () => {
|
||||
const createBodies: Record<string, unknown>[] = [];
|
||||
const fakeFetch: typeof fetch = async (input, init) => {
|
||||
|
||||
Reference in New Issue
Block a user