197 行
6.3 KiB
JavaScript
197 行
6.3 KiB
JavaScript
const workflowRoutes = require("../../../src/routes/workflow");
|
|
|
|
describe("Workflow Route Permissions", () => {
|
|
const {
|
|
buildWorkflowEntityVisibilityWhere,
|
|
canViewWorkflowEntityType,
|
|
employeeHasBusinessApproveRole,
|
|
listAllowedActionsForTask,
|
|
parseTaskListQuery,
|
|
} = workflowRoutes.__testables;
|
|
|
|
it.each(["admin", "system_admin"])(
|
|
"does not treat %s as a business approval role even with broad runtime permissions",
|
|
(roleCode) => {
|
|
expect(employeeHasBusinessApproveRole({
|
|
roleCodes: [roleCode],
|
|
permissionCodes: ["*", "expense.approve"],
|
|
}, "reimbursement")).toBe(false);
|
|
},
|
|
);
|
|
|
|
it("allows leave approvers to act on leave tasks", () => {
|
|
const actions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["leave.approve"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "leave" },
|
|
},
|
|
true,
|
|
);
|
|
|
|
expect(actions).toEqual(["approve", "reject", "return"]);
|
|
});
|
|
|
|
it("exposes return instead of reject for reimbursement tasks", () => {
|
|
const actions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["expense.approve"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "reimbursement" },
|
|
},
|
|
true,
|
|
);
|
|
|
|
expect(actions).toEqual(["approve", "return"]);
|
|
});
|
|
|
|
it("does not allow expense approvers to act on leave tasks without leave.approve", () => {
|
|
const actions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["expense.approve"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "leave" },
|
|
},
|
|
true,
|
|
);
|
|
|
|
expect(actions).toEqual([]);
|
|
});
|
|
|
|
it("allows procurement approvers to act on purchase tasks", () => {
|
|
const actions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["procurement.approve"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "purchase_request" },
|
|
},
|
|
true,
|
|
);
|
|
|
|
expect(actions).toEqual(["approve", "reject", "return"]);
|
|
});
|
|
|
|
it("allows travel approvers to act on travel tasks", () => {
|
|
const actions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["travel.approve"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "travel_request" },
|
|
},
|
|
true,
|
|
);
|
|
|
|
expect(actions).toEqual(["approve", "reject", "return"]);
|
|
});
|
|
|
|
it("allows attendance approvers to approve/reject attendance corrections without return action", () => {
|
|
const actions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["attendance.approve"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "attendance_correction" },
|
|
},
|
|
true,
|
|
);
|
|
|
|
expect(actions).toEqual(["approve", "reject"]);
|
|
});
|
|
|
|
it("allows transfer on approval tasks when actor also has expense.transfer", () => {
|
|
const reimbursementActions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["expense.approve", "expense.transfer"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "reimbursement" },
|
|
},
|
|
true,
|
|
);
|
|
const leaveActions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["leave.approve", "expense.transfer"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "leave" },
|
|
},
|
|
true,
|
|
);
|
|
const purchaseActions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["procurement.approve", "expense.transfer"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "purchase_request" },
|
|
},
|
|
true,
|
|
);
|
|
const travelActions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["travel.approve", "expense.transfer"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "travel_request" },
|
|
},
|
|
true,
|
|
);
|
|
const attendanceActions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["attendance.approve", "expense.transfer"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "attendance_correction" },
|
|
},
|
|
true,
|
|
);
|
|
|
|
expect(reimbursementActions).toEqual(["approve", "return", "transfer"]);
|
|
expect(leaveActions).toEqual(["approve", "reject", "return", "transfer"]);
|
|
expect(purchaseActions).toEqual(["approve", "reject", "return", "transfer"]);
|
|
expect(travelActions).toEqual(["approve", "reject", "return", "transfer"]);
|
|
expect(attendanceActions).toEqual(["approve", "reject", "transfer"]);
|
|
});
|
|
|
|
it("does not allow transfer without matching approve permission", () => {
|
|
const actions = listAllowedActionsForTask(
|
|
{ employee: { permissionCodes: ["expense.transfer"] } },
|
|
{
|
|
status: "pending",
|
|
workflow_instance: { entity_type: "leave" },
|
|
},
|
|
true,
|
|
);
|
|
|
|
expect(actions).toEqual([]);
|
|
});
|
|
|
|
it("parses optional workflow entityType filter for PC approval center", () => {
|
|
expect(parseTaskListQuery({ status: "pending", entityType: "attendance_correction", page: "2" })).toMatchObject({
|
|
status: "pending",
|
|
entityType: "attendance_correction",
|
|
page: 2,
|
|
pageSize: 20,
|
|
});
|
|
});
|
|
|
|
it("rejects unsupported workflow entityType filters", () => {
|
|
expect(() => parseTaskListQuery({ entityType: "invoice_pool" })).toThrow("参数校验失败");
|
|
});
|
|
|
|
it("hides travel workflow entities when travel is frozen for the actor", () => {
|
|
const request = { employee: { permissionCodes: [] } };
|
|
|
|
expect(canViewWorkflowEntityType(request, "travel_request")).toBe(false);
|
|
expect(buildWorkflowEntityVisibilityWhere(request)).toEqual({
|
|
entity_type: { notIn: ["travel_request"] },
|
|
});
|
|
expect(buildWorkflowEntityVisibilityWhere(request, "travel_request")).toEqual({
|
|
entity_type: "__forbidden__",
|
|
});
|
|
});
|
|
|
|
it("keeps travel workflow entities visible only for system settings holders", () => {
|
|
const request = { employee: { permissionCodes: ["system.settings"] } };
|
|
|
|
expect(canViewWorkflowEntityType(request, "travel_request")).toBe(true);
|
|
expect(buildWorkflowEntityVisibilityWhere(request)).toEqual({});
|
|
expect(buildWorkflowEntityVisibilityWhere(request, "travel_request")).toEqual({
|
|
entity_type: "travel_request",
|
|
});
|
|
});
|
|
});
|