文件
hyb-oa/server/tests/unit/scripts/repair-oa-only-smoke-accounts.test.js
T
wangsli ec68256588
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
实现(08-10-production-employee-smoke-break-glass-reset): 增加员工Smoke受控重置工具
2026-08-10 21:01:59 +08:00

142 行
5.2 KiB
JavaScript

const {
applyTarget,
isSafeOaOnlySmokeTarget,
isSmokeLikeValue,
normalizeRoleList,
parseArgs,
planForTarget,
} = require("../../../src/scripts/repair-oa-only-smoke-accounts");
function target(overrides = {}) {
return {
key: overrides.key ?? "admin",
identifier: overrides.identifier ?? "[email protected]",
maskedIdentifier: "sm***@***.com",
roles: overrides.roles ?? ["admin", "employee"],
};
}
function row(overrides = {}) {
return {
id: "11111111-1111-4111-8111-111111111111",
employeeNo: overrides.employeeNo ?? "T0001",
name: overrides.name ?? "OA试运行测试管理员",
email: overrides.email ?? "[email protected]",
phone: overrides.phone ?? "",
status: overrides.status ?? "archived",
employmentStatus: overrides.employmentStatus ?? "inactive",
archived: overrides.archived ?? true,
roles: overrides.roles ?? ["employee"],
loginFailedCount: overrides.loginFailedCount ?? 3,
hasLoginFailedFirstAt: overrides.hasLoginFailedFirstAt ?? true,
loginLocked: overrides.loginLocked ?? true,
activeAuthSessions: overrides.activeAuthSessions ?? 0,
};
}
describe("repair-oa-only-smoke-accounts", () => {
afterEach(() => {
delete process.env.OA_ONLY_SMOKE_REPAIR_APPLY;
});
it("recognizes only smoke-like identifiers as safe targets", () => {
expect(isSmokeLikeValue("[email protected]")).toBe(true);
expect(isSmokeLikeValue("SMOKE002")).toBe(true);
expect(isSmokeLikeValue("OA试运行测试管理员")).toBe(true);
expect(isSmokeLikeValue("[email protected]")).toBe(false);
});
it("blocks non-smoke employee matches before planning role repair", () => {
const plan = planForTarget(
target({ identifier: "[email protected]", roles: ["admin", "employee"] }),
row({
employeeNo: "HYD000100",
name: "真实员工",
email: "[email protected]",
status: "archived",
employmentStatus: "inactive",
archived: true,
}),
);
expect(isSafeOaOnlySmokeTarget(target({ identifier: "[email protected]" }), plan.before)).toBe(false);
expect(plan.status).toBe("BLOCKED");
expect(plan.reason).toBe("unsafe_non_smoke_target");
expect(plan.actions).toEqual([]);
});
it("plans only state, lock, and missing-role repairs for safe OA-only smoke rows", () => {
const plan = planForTarget(target(), row());
expect(plan.status).toBe("PLANNED");
expect(plan.actions).toEqual(["restore_active_employee", "clear_login_lock", "add_missing_roles"]);
expect(plan.missingRoles).toEqual(["admin"]);
expect(JSON.stringify(plan)).not.toContain("[email protected]");
});
it("normalizes roles and parses apply mode without enabling apply by itself", () => {
const options = parseArgs(["--apply", "--target=admin:[email protected]:admin+employee", "--format=json"]);
expect(options.mode).toBe("apply");
expect(options.targets[0]).toMatchObject({
key: "admin",
identifier: "[email protected]",
roles: ["admin", "employee"],
});
expect(normalizeRoleList(["admin", "admin", "invalid", "employee"])).toEqual(["admin", "employee"]);
expect(process.env.OA_ONLY_SMOKE_REPAIR_APPLY).toBeUndefined();
});
it("applies only lifecycle, login-lock, token, missing-role, and audit repairs", async () => {
const current = row({
status: "archived",
employmentStatus: "inactive",
archived: true,
roles: ["employee"],
});
const planned = planForTarget(target(), current);
const client = {
query: vi.fn(async (sql) => {
const text = String(sql);
if (text.includes("SELECT")) {
return {
rows: [
{
id: current.id,
employee_no: current.employeeNo,
name: current.name,
email: current.email,
phone: current.phone,
status: "active",
employment_status: "active",
archived: false,
login_failed_count: 0,
has_login_failed_first_at: false,
login_locked_until: null,
roles: ["admin", "employee"],
active_auth_sessions: 0,
},
],
};
}
return { rows: [] };
}),
};
await expect(
applyTarget(client, target(), planned, new Date("2026-08-10T00:00:00.000Z")),
).resolves.toMatchObject({ result: "applied" });
const sql = client.query.mock.calls.map(([statement]) => String(statement)).join("\n");
expect(sql).toContain("token_version = token_version + 1");
expect(sql).toContain("INSERT INTO employee_roles");
expect(sql).toContain("ON CONFLICT (employee_id, role_code) DO NOTHING");
expect(sql).toContain("INSERT INTO employee_lifecycle_events");
expect(sql).not.toContain("DELETE FROM employee_roles");
expect(sql).not.toContain("password_hash");
expect(sql).not.toMatch(/(?:UPDATE|INSERT\s+INTO|DELETE\s+FROM)\s+auth_sessions/iu);
expect(sql).not.toMatch(/(?:UPDATE|INSERT\s+INTO|DELETE\s+FROM)\s+password_reset_codes/iu);
expect(sql).not.toMatch(/(?:UPDATE|INSERT\s+INTO|DELETE\s+FROM)\s+email_login_codes/iu);
});
});