const { NOTIFICATION_DOMAIN_SCOPES, NOTIFICATION_TYPES, } = require("../../../src/constants/notificationTypes"); const { isImChannelTypeSupported, matchesNotificationChannel, normalizeChannelType, normalizeRouting, } = require("../../../src/services/notifications/imRouting"); describe("IM routing", () => { it("normalizes wechat_work alias to wecom", () => { expect(normalizeChannelType("wechat_work")).toBe("wecom"); expect(isImChannelTypeSupported("wecom")).toBe(true); expect(isImChannelTypeSupported("dingtalk")).toBe(false); }); it("normalizes routing arrays and drops empty values", () => { expect( normalizeRouting({ routing: { roleCodes: ["manager", "manager", ""], domainScopes: ["workflow", "workflow"], allowedTypes: ["workflow.task_assigned", ""], }, }), ).toEqual({ roleCodes: ["manager"], domainScopes: ["workflow"], allowedTypes: ["workflow.task_assigned"], }); }); it("matches channel when role scope type all hit", () => { const matched = matchesNotificationChannel( { enabled: true, channel_type: "wecom", config_json: { routing: { roleCodes: ["manager"], domainScopes: ["workflow"], allowedTypes: ["workflow.task_assigned"], }, }, }, { notificationType: "workflow.task_assigned", domainScope: "workflow", recipientRoleCodes: ["manager", "finance_mgr"], }, ); expect(matched).toBe(true); }); it("rejects channel when any routing dimension does not match", () => { const baseChannel = { enabled: true, channel_type: "wecom", config_json: { routing: { roleCodes: ["manager"], domainScopes: ["workflow"], allowedTypes: ["workflow.task_assigned"], }, }, }; expect( matchesNotificationChannel(baseChannel, { notificationType: "workflow.task_assigned", domainScope: "procurement", recipientRoleCodes: ["manager"], }), ).toBe(false); expect( matchesNotificationChannel(baseChannel, { notificationType: "workflow.task_assigned", domainScope: "workflow", recipientRoleCodes: ["finance_mgr"], }), ).toBe(false); expect( matchesNotificationChannel(baseChannel, { notificationType: "leave.approved", domainScope: "workflow", recipientRoleCodes: ["manager"], }), ).toBe(false); }); it.each([ [NOTIFICATION_TYPES.leaveReturned, NOTIFICATION_DOMAIN_SCOPES.leave], [NOTIFICATION_TYPES.purchaseRequestReturned, NOTIFICATION_DOMAIN_SCOPES.procurement], [NOTIFICATION_TYPES.travelRequestReturned, NOTIFICATION_DOMAIN_SCOPES.travel], ])("requires both the allowed type and domain for %s", (notificationType, domainScope) => { const buildChannel = (routing) => ({ enabled: true, channel_type: "wecom", config_json: { routing }, }); const context = { notificationType, domainScope, recipientRoleCodes: ["employee"], }; expect(matchesNotificationChannel(buildChannel({ roleCodes: [], domainScopes: [domainScope], allowedTypes: [notificationType], }), context)).toBe(true); expect(matchesNotificationChannel(buildChannel({ roleCodes: [], domainScopes: [NOTIFICATION_DOMAIN_SCOPES.workflow], allowedTypes: [notificationType], }), context)).toBe(false); expect(matchesNotificationChannel(buildChannel({ roleCodes: [], domainScopes: [domainScope], allowedTypes: [NOTIFICATION_TYPES.workflowTaskAssigned], }), context)).toBe(false); }); });