文件
hyb-oa/server/tests/unit/routes/employees.profile.test.js
T

198 行
6.1 KiB
JavaScript

const employeesRoutes = require("../../../src/routes/employees");
const { buildEmployeeOrganization, buildEmployeeProfile } = employeesRoutes.__testables;
function buildEmployeeRow(overrides = {}) {
return {
id: "11111111-1111-4111-8111-111111111111",
employee_no: "E001",
name: "Alice",
title: "员工",
status: "active",
direct_manager_id: null,
department: {
id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
name: "行政部",
},
...overrides,
};
}
describe("employee profile organization", () => {
it("builds reporting chain from top to current employee and keeps direct reports scoped to one hop", async () => {
const currentEmployee = buildEmployeeRow({
id: "33333333-3333-4333-8333-333333333333",
employee_no: "E003",
name: "Carol",
title: "专员",
direct_manager_id: "22222222-2222-4222-8222-222222222222",
department: { id: "dept-3", name: "采购部" },
});
const manager = buildEmployeeRow({
id: "22222222-2222-4222-8222-222222222222",
employee_no: "E002",
name: "Bob",
title: "经理",
direct_manager_id: "11111111-1111-4111-8111-111111111111",
department: { id: "dept-2", name: "财务部" },
});
const director = buildEmployeeRow({
id: "11111111-1111-4111-8111-111111111111",
employee_no: "E001",
name: "Alice",
title: "总监",
department: { id: "dept-1", name: "管理层" },
});
const prisma = {
employee: {
findUnique: vi.fn(async ({ where }) => {
if (where.id === manager.id) return manager;
if (where.id === director.id) return director;
return null;
}),
findMany: vi.fn().mockResolvedValue([
buildEmployeeRow({
id: "44444444-4444-4444-8444-444444444444",
employee_no: "E004",
name: "David",
title: "专员",
status: "active",
department: { id: "dept-3", name: "采购部" },
}),
buildEmployeeRow({
id: "55555555-5555-4555-8555-555555555555",
employee_no: "E005",
name: "Eve",
title: "专员",
status: "archived",
department: { id: "dept-3", name: "采购部" },
}),
]),
},
};
const organization = await buildEmployeeOrganization(prisma, currentEmployee);
expect(organization.reportingChain.map((item) => item.id)).toEqual([
director.id,
manager.id,
currentEmployee.id,
]);
expect(organization.reportingChain.at(-1)).toMatchObject({
id: currentEmployee.id,
department: { id: "dept-3", name: "采购部" },
});
expect(organization.directReports.map((item) => item.id)).toEqual([
"44444444-4444-4444-8444-444444444444",
"55555555-5555-4555-8555-555555555555",
]);
expect(prisma.employee.findMany).toHaveBeenCalledWith({
where: { direct_manager_id: currentEmployee.id },
orderBy: [{ status: "asc" }, { name: "asc" }],
select: {
id: true,
employee_no: true,
name: true,
title: true,
status: true,
avatar_path: true,
department: { select: { id: true, name: true } },
},
});
});
it("stops on manager cycle and returns the partial reporting chain", async () => {
const currentEmployee = buildEmployeeRow({
id: "66666666-6666-4666-8666-666666666666",
employee_no: "E006",
name: "Frank",
title: "经理",
direct_manager_id: "77777777-7777-4777-8777-777777777777",
});
const cycleManager = buildEmployeeRow({
id: "77777777-7777-4777-8777-777777777777",
employee_no: "E007",
name: "Grace",
title: "总监",
direct_manager_id: currentEmployee.id,
});
const prisma = {
employee: {
findUnique: vi.fn(async ({ where }) => (where.id === cycleManager.id ? cycleManager : null)),
findMany: vi.fn().mockResolvedValue([]),
},
};
const organization = await buildEmployeeOrganization(prisma, currentEmployee);
expect(organization.reportingChain.map((item) => item.id)).toEqual([cycleManager.id, currentEmployee.id]);
expect(prisma.employee.findUnique).toHaveBeenCalledTimes(1);
});
it("embeds stable organization arrays into employee profile responses", async () => {
const currentEmployee = {
...buildEmployeeRow({
id: "88888888-8888-4888-8888-888888888888",
employee_no: "E008",
name: "Helen",
title: "主管",
}),
phone: "13800000000",
email: "[email protected]",
employment_status: "active",
department_id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
hire_date: new Date("2026-01-10T00:00:00.000Z"),
probation_end_date: null,
last_working_date: null,
work_location: "上海",
emergency_contact_name: "联系人",
emergency_contact_phone: "13900000000",
notes: "none",
archived_at: null,
roles: [{ role_code: "employee" }],
direct_manager: null,
};
const prisma = {
employee: {
findUnique: vi.fn(async ({ where }) => (where.id === currentEmployee.id ? currentEmployee : null)),
findMany: vi.fn().mockResolvedValue([]),
},
employeeChecklistTask: {
findMany: vi.fn().mockResolvedValue([]),
},
employeeLifecycleEvent: {
findMany: vi.fn().mockResolvedValue([]),
},
assetCard: {
findMany: vi.fn().mockResolvedValue([]),
count: vi.fn().mockResolvedValue(0),
},
workflowTask: {
count: vi.fn().mockResolvedValue(0),
},
};
const profile = await buildEmployeeProfile(prisma, currentEmployee.id);
expect(profile.organization.reportingChain).toEqual([
{
id: currentEmployee.id,
employeeNo: "E008",
name: "Helen",
title: "主管",
status: "active",
avatarUrl: null,
department: {
id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
name: "行政部",
},
},
]);
expect(profile.organization.directReports).toEqual([]);
expect(profile.assignedAssets).toEqual([]);
});
});