141 行
3.6 KiB
JavaScript
141 行
3.6 KiB
JavaScript
const Fastify = require('fastify');
|
|
|
|
const meRoutes = require('../../../src/routes/me');
|
|
const { AppError } = require('../../../src/utils/AppError');
|
|
|
|
function createPrismaState(overrides = {}) {
|
|
const auditEntries = [];
|
|
const employeeRecord = {
|
|
id: 'employee-1',
|
|
employee_no: 'E001',
|
|
name: '测试员工',
|
|
phone: '13800000000',
|
|
email: '[email protected]',
|
|
department_id: 'department-1',
|
|
direct_manager_id: 'manager-1',
|
|
status: 'active',
|
|
notification_push_enabled: true,
|
|
roles: [{ role_code: 'employee' }],
|
|
wecom_identity_binding: null,
|
|
...overrides,
|
|
};
|
|
|
|
return {
|
|
prisma: {
|
|
employee: {
|
|
findUnique: vi.fn().mockResolvedValue(employeeRecord),
|
|
update: vi.fn().mockImplementation(async ({ data }) => {
|
|
employeeRecord.notification_push_enabled = data.notification_push_enabled;
|
|
return {
|
|
id: employeeRecord.id,
|
|
notification_push_enabled: employeeRecord.notification_push_enabled,
|
|
};
|
|
}),
|
|
},
|
|
auditLog: {
|
|
create: vi.fn().mockImplementation(async ({ data }) => {
|
|
auditEntries.push(data);
|
|
return { id: `audit-${auditEntries.length}` };
|
|
}),
|
|
},
|
|
},
|
|
employeeRecord,
|
|
auditEntries,
|
|
};
|
|
}
|
|
|
|
async function buildApp(prisma) {
|
|
const app = Fastify();
|
|
app.decorate('prisma', prisma);
|
|
app.decorate('authenticate', async (request) => {
|
|
if (!request.headers.authorization) {
|
|
throw new AppError({
|
|
code: 'AUTH_001',
|
|
message: '未登录',
|
|
statusCode: 401,
|
|
});
|
|
}
|
|
|
|
request.employee = {
|
|
id: 'employee-1',
|
|
permissionCodes: [],
|
|
};
|
|
});
|
|
app.setErrorHandler((error, request, reply) => {
|
|
if (error instanceof AppError) {
|
|
return reply.status(error.statusCode).send({
|
|
requestId: request.id,
|
|
error: {
|
|
code: error.code,
|
|
message: error.message,
|
|
details: error.details ?? {},
|
|
},
|
|
});
|
|
}
|
|
|
|
return reply.status(500).send({
|
|
requestId: request.id,
|
|
error: {
|
|
code: 'SYS_001',
|
|
message: '服务器内部错误',
|
|
details: {},
|
|
},
|
|
});
|
|
});
|
|
|
|
await app.register(meRoutes, { prefix: '/api' });
|
|
return app;
|
|
}
|
|
|
|
describe('me routes', () => {
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('returns notificationPushEnabled in /me response', async () => {
|
|
const { prisma } = createPrismaState({ notification_push_enabled: false });
|
|
const app = await buildApp(prisma);
|
|
|
|
const response = await app.inject({
|
|
method: 'GET',
|
|
url: '/api/me',
|
|
headers: { authorization: 'Bearer test-token' },
|
|
});
|
|
|
|
expect(response.statusCode).toBe(200);
|
|
expect(response.json().data).toEqual(
|
|
expect.objectContaining({
|
|
id: 'employee-1',
|
|
notificationPushEnabled: false,
|
|
}),
|
|
);
|
|
|
|
await app.close();
|
|
});
|
|
|
|
it('updates notification preferences for current employee', async () => {
|
|
const { prisma, employeeRecord, auditEntries } = createPrismaState();
|
|
const app = await buildApp(prisma);
|
|
|
|
const response = await app.inject({
|
|
method: 'PATCH',
|
|
url: '/api/me/notification-preferences',
|
|
headers: { authorization: 'Bearer test-token' },
|
|
payload: {
|
|
notificationPushEnabled: false,
|
|
},
|
|
});
|
|
|
|
expect(response.statusCode).toBe(200);
|
|
expect(response.json().data).toEqual({ notificationPushEnabled: false });
|
|
expect(employeeRecord.notification_push_enabled).toBe(false);
|
|
expect(auditEntries[0]).toEqual(
|
|
expect.objectContaining({
|
|
action: 'EMPLOYEE_NOTIFICATION_PREFERENCE_UPDATED',
|
|
}),
|
|
);
|
|
|
|
await app.close();
|
|
});
|
|
});
|