232 lines
6.6 KiB
JavaScript
232 lines
6.6 KiB
JavaScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { createRequire } from "node:module";
|
|
|
|
const require = createRequire(import.meta.url);
|
|
const mock = require("mock-require");
|
|
|
|
const graphClientModuleId = require.resolve("../graphql-client/graphql-client");
|
|
const queriesModuleId = require.resolve("../graphql-client/queries");
|
|
const emailQueueModuleId = require.resolve("./queues/emailQueue");
|
|
const appQueueModuleId = require.resolve("./queues/appQueue");
|
|
const fcmQueueModuleId = require.resolve("./queues/fcmQueue");
|
|
const dispatcherModuleId = require.resolve("./dispatchJobWatcherNotification");
|
|
|
|
const dispatchEmailsToQueueMock = vi.fn();
|
|
const dispatchAppsToQueueMock = vi.fn();
|
|
const dispatchFcmsToQueueMock = vi.fn();
|
|
|
|
const loadDispatcher = ({ requestMock }) => {
|
|
mock.stopAll();
|
|
dispatchEmailsToQueueMock.mockReset();
|
|
dispatchAppsToQueueMock.mockReset();
|
|
dispatchFcmsToQueueMock.mockReset();
|
|
|
|
mock(graphClientModuleId, { client: { request: requestMock } });
|
|
mock(queriesModuleId, {
|
|
GET_JOB_WATCHERS: "GET_JOB_WATCHERS",
|
|
GET_NOTIFICATION_ASSOCIATIONS: "GET_NOTIFICATION_ASSOCIATIONS"
|
|
});
|
|
mock(emailQueueModuleId, { dispatchEmailsToQueue: dispatchEmailsToQueueMock });
|
|
mock(appQueueModuleId, { dispatchAppsToQueue: dispatchAppsToQueueMock });
|
|
mock(fcmQueueModuleId, { dispatchFcmsToQueue: dispatchFcmsToQueueMock });
|
|
|
|
delete require.cache[dispatcherModuleId];
|
|
|
|
return require(dispatcherModuleId);
|
|
};
|
|
|
|
afterEach(() => {
|
|
mock.stopAll();
|
|
delete require.cache[dispatcherModuleId];
|
|
});
|
|
|
|
describe("dispatchJobWatcherNotification", () => {
|
|
it("dispatches queue payloads using watcher settings plus fallback defaults for extra recipients", async () => {
|
|
const requestMock = vi.fn(async (query) => {
|
|
if (query === "GET_JOB_WATCHERS") {
|
|
return {
|
|
job_watchers: [
|
|
{
|
|
user_email: "watcher@example.com",
|
|
user: {
|
|
employee: {
|
|
id: "emp-1",
|
|
first_name: "Pat",
|
|
last_name: "Lee"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
job: {
|
|
ro_number: "RO-123",
|
|
bodyshop: {
|
|
id: "shop-1",
|
|
shopname: "ImEX",
|
|
timezone: "America/Toronto"
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
if (query === "GET_NOTIFICATION_ASSOCIATIONS") {
|
|
return {
|
|
associations: [
|
|
{
|
|
id: "assoc-1",
|
|
useremail: "watcher@example.com",
|
|
notification_settings: {
|
|
"esign-document-opened": {
|
|
app: true,
|
|
email: false,
|
|
fcm: true
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: "assoc-2",
|
|
useremail: "creator@example.com",
|
|
notification_settings: {}
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
return {};
|
|
});
|
|
|
|
const { dispatchJobWatcherNotification } = loadDispatcher({ requestMock });
|
|
const logger = { log: vi.fn() };
|
|
|
|
const result = await dispatchJobWatcherNotification({
|
|
jobId: "job-1",
|
|
scenarioKey: "esign-document-opened",
|
|
key: "notifications.job.esignDocumentOpened",
|
|
body: '"Repair Authorization" has been opened.',
|
|
variables: { documentId: "123" },
|
|
extraRecipientEmails: ["creator@example.com"],
|
|
defaultChannelPreferences: {
|
|
app: true,
|
|
email: false,
|
|
fcm: false
|
|
},
|
|
logger
|
|
});
|
|
|
|
expect(result).toBe(true);
|
|
expect(requestMock).toHaveBeenCalledTimes(2);
|
|
|
|
expect(dispatchEmailsToQueueMock).not.toHaveBeenCalled();
|
|
|
|
expect(dispatchAppsToQueueMock).toHaveBeenCalledTimes(1);
|
|
expect(dispatchAppsToQueueMock.mock.calls[0][0]).toEqual({
|
|
appsToDispatch: [
|
|
expect.objectContaining({
|
|
jobId: "job-1",
|
|
jobRoNumber: "RO-123",
|
|
bodyShopId: "shop-1",
|
|
scenarioKey: "esign-document-opened",
|
|
key: "notifications.job.esignDocumentOpened",
|
|
recipients: [
|
|
{
|
|
user: "watcher@example.com",
|
|
bodyShopId: "shop-1",
|
|
employeeId: "emp-1",
|
|
associationId: "assoc-1"
|
|
},
|
|
{
|
|
user: "creator@example.com",
|
|
bodyShopId: "shop-1",
|
|
employeeId: null,
|
|
associationId: "assoc-2"
|
|
}
|
|
]
|
|
})
|
|
],
|
|
logger
|
|
});
|
|
|
|
expect(dispatchFcmsToQueueMock).toHaveBeenCalledTimes(1);
|
|
expect(dispatchFcmsToQueueMock.mock.calls[0][0]).toEqual({
|
|
fcmsToDispatch: [
|
|
expect.objectContaining({
|
|
jobId: "job-1",
|
|
scenarioKey: "esign-document-opened",
|
|
recipients: [
|
|
{
|
|
user: "watcher@example.com",
|
|
bodyShopId: "shop-1",
|
|
employeeId: "emp-1",
|
|
associationId: "assoc-1"
|
|
}
|
|
]
|
|
})
|
|
],
|
|
logger
|
|
});
|
|
});
|
|
|
|
it("returns false when no recipients have any enabled channels", async () => {
|
|
const requestMock = vi.fn(async (query) => {
|
|
if (query === "GET_JOB_WATCHERS") {
|
|
return {
|
|
job_watchers: [
|
|
{
|
|
user_email: "watcher@example.com",
|
|
user: {
|
|
employee: {
|
|
id: "emp-1",
|
|
first_name: "Pat",
|
|
last_name: "Lee"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
job: {
|
|
ro_number: "RO-123",
|
|
bodyshop: {
|
|
id: "shop-1",
|
|
shopname: "ImEX",
|
|
timezone: "America/Toronto"
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
if (query === "GET_NOTIFICATION_ASSOCIATIONS") {
|
|
return {
|
|
associations: [
|
|
{
|
|
id: "assoc-1",
|
|
useremail: "watcher@example.com",
|
|
notification_settings: {
|
|
"esign-document-opened": {
|
|
app: false,
|
|
email: false,
|
|
fcm: false
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
return {};
|
|
});
|
|
|
|
const { dispatchJobWatcherNotification } = loadDispatcher({ requestMock });
|
|
|
|
const result = await dispatchJobWatcherNotification({
|
|
jobId: "job-1",
|
|
scenarioKey: "esign-document-opened",
|
|
key: "notifications.job.esignDocumentOpened",
|
|
body: '"Repair Authorization" has been opened.',
|
|
logger: { log: vi.fn() }
|
|
});
|
|
|
|
expect(result).toBe(false);
|
|
expect(dispatchEmailsToQueueMock).not.toHaveBeenCalled();
|
|
expect(dispatchAppsToQueueMock).not.toHaveBeenCalled();
|
|
expect(dispatchFcmsToQueueMock).not.toHaveBeenCalled();
|
|
});
|
|
});
|