W1-W3 实现企业微信个人应用消息通知
这个提交包含在:
@@ -262,6 +262,9 @@ function createPrismaState({ channels = [], deliveries = [], notifications = []
|
||||
return { id: `audit-${auditEntries.length}` };
|
||||
}),
|
||||
},
|
||||
wecomIdentityBinding: {
|
||||
findMany: vi.fn().mockResolvedValue([]),
|
||||
},
|
||||
$transaction: vi.fn().mockImplementation(async (callback) => callback(transactionClient)),
|
||||
},
|
||||
stateChannels,
|
||||
@@ -423,6 +426,48 @@ describe('notifications channel routes', () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it('creates wecom app message channel without webhook or secret', async () => {
|
||||
const { prisma, stateChannels } = createPrismaState();
|
||||
const app = await buildApp({
|
||||
prisma,
|
||||
config: { fieldEncryptionKey: validFieldEncryptionKey },
|
||||
});
|
||||
|
||||
const response = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/notifications/channels',
|
||||
headers: { authorization: 'Bearer test-token' },
|
||||
payload: {
|
||||
channelType: 'wecom',
|
||||
name: '企微个人应用消息',
|
||||
enabled: true,
|
||||
configJson: {
|
||||
mode: 'wecom_app_message',
|
||||
timeoutMs: 800,
|
||||
routing: {
|
||||
roleCodes: ['manager'],
|
||||
domainScopes: ['workflow'],
|
||||
allowedTypes: ['workflow.task_assigned'],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data.channel.configJson).toEqual(
|
||||
expect.objectContaining({
|
||||
mode: 'wecom_app_message',
|
||||
webhookUrl: null,
|
||||
secretConfigured: false,
|
||||
secretMasked: null,
|
||||
}),
|
||||
);
|
||||
expect(stateChannels[0].config_json.secretEncrypted).toBeUndefined();
|
||||
expect(stateChannels[0].config_json.webhookUrl).toBeNull();
|
||||
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it('rejects secret write when FIELD_ENCRYPTION_KEY is missing', async () => {
|
||||
const { prisma } = createPrismaState();
|
||||
const app = await buildApp({ prisma, config: { fieldEncryptionKey: '' } });
|
||||
@@ -585,6 +630,44 @@ describe('notifications channel routes', () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it('tests wecom app message channel against current bound admin when available', async () => {
|
||||
const { prisma } = createPrismaState({
|
||||
channels: [
|
||||
buildChannelRecord({
|
||||
config_json: {
|
||||
mode: 'wecom_app_message',
|
||||
webhookUrl: null,
|
||||
timeoutMs: 800,
|
||||
routing: {},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
const app = await buildApp({ prisma });
|
||||
|
||||
const response = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/notifications/channels/11111111-1111-4111-8111-111111111111/test',
|
||||
headers: { authorization: 'Bearer test-token' },
|
||||
payload: {},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data.testResult).toEqual(
|
||||
expect.objectContaining({
|
||||
ok: true,
|
||||
code: 'wecom_app_no_bound_recipients',
|
||||
}),
|
||||
);
|
||||
expect(prisma.wecomIdentityBinding.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: { employee_id: { in: ['employee-1'] } },
|
||||
}),
|
||||
);
|
||||
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it('lists grouped delivery summaries with latest status and attempt count', async () => {
|
||||
const notification = buildNotificationRecord({
|
||||
id: '55555555-5555-4555-8555-555555555555',
|
||||
|
||||
在新工单中引用
屏蔽一个用户