Skip to content

Commit

Permalink
tests and ironing out the final logic
Browse files Browse the repository at this point in the history
  • Loading branch information
engelhartrueben committed Dec 13, 2024
1 parent df04c67 commit c347bb5
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 74 deletions.
196 changes: 126 additions & 70 deletions __test__/extensions/message-handlers/ngpvan-optout.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Config = require("../../../src/server/api/lib/config");
const Van = require("../../../src/extensions/message-handlers/ngpvan-optout");
const VanAction = require("../../../src/extensions/action-handlers/ngpvan-action");
const VanOptOut = require("../../../src/extensions/message-handlers/ngpvan-optout");
const VanUtil = require("../../../src/extensions/contact-loaders/ngpvan/util");
const HttpRequest = require("../../../src/server/lib/http-request");

describe("extensions.message-handlers.ngpvan-optout", () => {
afterEach(async () => {
Expand All @@ -12,17 +12,12 @@ describe("extensions.message-handlers.ngpvan-optout", () => {
let contact;
let organization;
let handlerContext;
let body;

beforeEach(async () => {
message = {
is_from_contact: false
};

contact = {
message_status: "needsMessage",
custom_fields: '{"vanid": 12345}',
cell: "123-456-7891"
campaign_contact_id: "1234",
contact_number: "(123)-456-7890",
is_from_contact: true
};

organization = {
Expand All @@ -33,111 +28,172 @@ describe("extensions.message-handlers.ngpvan-optout", () => {
autoOptOutReason: "stop"
}

// Custom body for this call - this is the expected structure
body = {
"canvassContext": {
"inputTypeId": 11, // API input
"phone": {
"dialingPrefix": "1",
"phoneNumber": "123-456-7891",
"smsOptInStatus": "O" // opt out status
}
},
"resultCodeId": 130
};
jest.spyOn(VanOptOut, "available").mockReturnValue(true);
jest.spyOn(VanOptOut, "dbQuery").mockReturnValue([{custom_fields: '{"VanID": 1234}'}]);

jest.spyOn(Config, "getConfig").mockReturnValue(undefined);
jest.spyOn(Van, "available").mockReturnValue(true);
jest.spyOn(VanUtil.default, "getAuth").mockReturnValue("*****");

jest.spyOn(VanAction, "postCanvassResponse").mockResolvedValue(null);
jest.spyOn(HttpRequest, "default").mockReturnValue(null);
});

it("delegates to its dependencies and DOES call postCanvassResponse", async () => {
const result = await Van.postMessageSave({
contact,
it("delegates to its dependencies and DOES post to NGP VAN", async () => {
const result = await VanOptOut.postMessageSave({
handlerContext,
organization
organization,
message
});

expect(result).toEqual({});

// This also verifies that postCanvassResponse was only called once
expect(VanAction.postCanvassResponse.mock.calls).toEqual([
expect(HttpRequest.default.mock.calls).toEqual(
[
contact,
organization,
body
[
"https://api.securevan.com/v4/people/1234/canvassResponses",
{
"method": "POST",
"retries": 1,
"timeout": 32000,
"headers": {
"Authorization": "*****",
"accept": "text/plain",
"Content-Type": "application/json"
},
"body": `{"canvassContext":{"inputTypeId":11,"phone":{"dialingPrefix":"1"`+
`,"phoneNumber":"123-456-7890","smsOptInStatus":"O"}},"resultCodeId":130}`,
"validStatuses": [204],
"compress": false
}
]
]
]);
);
});

describe("when the handler is not available", () => {
beforeEach(async () => {
Van.available.mockReturnValue(false);
VanOptOut.available.mockReturnValue(false);
});

it("returns an empty object and DOES NOT call postCanvassResponse", async () => {
const result = await Van.postMessageSave({
message,
contact,
organization
it("returns an empty object and DOES NOT post to NGP VAN", async () => {
const result = await VanOptOut.postMessageSave({
handlerContext,
organization,
message
});

expect(result).toEqual({});
expect(VanAction.postCanvassResponse.mock.calls).toHaveLength(0);
expect(HttpRequest.default.mock.calls).toHaveLength(0);
});
});

describe("when contact is null or undefined", () => {
it("returns an empty object and DOES NOT call postCanvassResponse", async () => {
const result = await Van.postMessageSave({
message,
organization
describe("when message is null or undefined", () => {
beforeEach(async () => {
handlerContext = {}
});

it("returns an empty object and DOES NOT post to NGP VAN", async () => {
const result = await VanOptOut.postMessageSave({
handlerContext,
organization,
message
});

expect(result).toEqual({});
expect(VanAction.postCanvassResponse.mock.calls).toHaveLength(0);
expect(HttpRequest.default.mock.calls).toHaveLength(0);
});
});

describe("when no VAN Id is inclued", () => {
beforeEach(async () => {
contact = {
...contact,
custom_fields: '{}'
};
VanOptOut.dbQuery.mockReturnValue({});
});

it("returns an empty object and DOES NOT call postCanvassResponse", async () => {
const result = await Van.postMessageSave({
message,
contact,
it("returns an empty object and DOES NOT post to NGP VAN", async () => {
const result = await VanOptOut.postMessageSave({
handlerContext,
organization,
handlerContext
message
});

expect(result).toEqual({});
expect(VanAction.postCanvassResponse.mock.calls).toHaveLength(0);
expect(HttpRequest.default.mock.calls).toHaveLength(0);
})
})

describe("when alternate VAN ID is included", () => {
beforeEach(async () => {
contact = {
...contact,
customFields: '{"VanID": 54321}'
};
VanOptOut.dbQuery.mockReturnValue([{custom_fields: '{"vanid": 1234}'}])
});

it("still works and DOES call postCanvassResponse", async () => {
const result = await Van.postMessageSave({
message,
contact,
it("still works and DOES post to NGP VAN", async () => {
const result = await VanOptOut.postMessageSave({
handlerContext,
organization,
handlerContext
message
});

expect(result).toEqual({});
expect(VanAction.postCanvassResponse.mock.calls).toHaveLength(1);
expect(HttpRequest.default.mock.calls).toEqual(
[
[
"https://api.securevan.com/v4/people/1234/canvassResponses",
{
"method": "POST",
"retries": 1,
"timeout": 32000,
"headers": {
"Authorization": "*****",
"accept": "text/plain",
"Content-Type": "application/json"
},
"body": `{"canvassContext":{"inputTypeId":11,"phone":{"dialingPrefix":"1"`+
`,"phoneNumber":"123-456-7890","smsOptInStatus":"O"}},"resultCodeId":130}`,
"validStatuses": [204],
"compress": false
}
]
]
);
})
})
});

describe("when no contact number is included in the message object", () => {
beforeEach(async () => {
message = {
...message,
contact_number: ""
};
});

it("returns an object and DOES NOT post to NGP VAN", async () => {
const result = await VanOptOut.postMessageSave({
handlerContext,
organization,
message
});

expect(result).toEqual({});
expect(HttpRequest.default.mock.calls).toHaveLength(0);
});
});

describe("when the message is not from the contact", () => {
beforeEach(async () => {
message = {
...message,
is_from_contact: false
};
});

it("returns and empty obejct and DOES NOT post to NGP VAN", async () => {
const result = await VanOptOut.postMessageSave({
handlerContext,
organization,
message
});

expect(result).toEqual({});
expect(HttpRequest.default.mock.calls).toHaveLength(0);
});
});
});
});
13 changes: 9 additions & 4 deletions src/extensions/message-handlers/ngpvan-optout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const serverAdministratorInstructions = () => {
};
}

const dbQuery = async (campaignContactId) => {
export const dbQuery = async campaignContactId => {
return await r
.knex("campaign_contact")
.select("custom_fields")
Expand Down Expand Up @@ -60,12 +60,13 @@ export const postMessageSave = async ({
// If no message or optOut, return
if (
!message ||
!message.is_from_contact ||
!handlerContext.autoOptOutReason
) return {};


try {
query = await dbQuery(message.campaign_contact_id);
query = await exports.dbQuery(message.campaign_contact_id);
customField = JSON.parse(query[0]["custom_fields"] || "{}");

vanId = customField["VanID"] || customField["vanid"];
Expand Down Expand Up @@ -100,10 +101,12 @@ export const postMessageSave = async ({
"resultCodeId": 130
};

return httpRequest(url, {
console.log(`ngpvan-optout.postMessageSave VAN ID : ${vanId}`);

await httpRequest(url, {
method: "POST",
retries: 1,
timeout: Van.getVanTimeout(organization),
timeout: Van.getNgpVanTimeout(organization),
headers: {
Authorization: await Van.getAuth(organization),
"accept": "text/plain",
Expand All @@ -113,6 +116,8 @@ export const postMessageSave = async ({
validStatuses: [204],
compress: false
})

return {};
}


0 comments on commit c347bb5

Please sign in to comment.