diff --git a/config/suppliers/letter-variant/notify-standard-test1.json b/config/suppliers/letter-variant/notify-standard-test1.json index f69b59360..762356f1a 100644 --- a/config/suppliers/letter-variant/notify-standard-test1.json +++ b/config/suppliers/letter-variant/notify-standard-test1.json @@ -21,7 +21,8 @@ "id": "notify-standard-test1", "name": "Dev Happy Path", "packSpecificationIds": [ - "notify-c5" + "notify-c5", + "notify-c4" ], "priority": 50, "status": "PROD", diff --git a/config/suppliers/supplier-allocation/supplier1-volumeGroup-test3.json b/config/suppliers/supplier-allocation/supplier1-volumeGroup-test3.json index f08467c9f..299dc86c7 100644 --- a/config/suppliers/supplier-allocation/supplier1-volumeGroup-test3.json +++ b/config/suppliers/supplier-allocation/supplier1-volumeGroup-test3.json @@ -1,5 +1,5 @@ { - "allocationPercentage": 100, + "allocationPercentage": 50, "id": "supplier1-volumeGroup-test3", "status": "PROD", "supplier": "supplier1", diff --git a/config/suppliers/supplier-allocation/supplier2-volumeGroup-test3.json b/config/suppliers/supplier-allocation/supplier2-volumeGroup-test3.json new file mode 100644 index 000000000..3d8fa19cd --- /dev/null +++ b/config/suppliers/supplier-allocation/supplier2-volumeGroup-test3.json @@ -0,0 +1,7 @@ +{ + "allocationPercentage": 50, + "id": "supplier2-volumeGroup-test3", + "status": "PROD", + "supplier": "supplier2", + "volumeGroup": "volumeGroup-test3" +} diff --git a/config/suppliers/supplier-pack/supplier2-client1-campaign1.json b/config/suppliers/supplier-pack/supplier2-client1-campaign1.json new file mode 100644 index 000000000..fad6dec27 --- /dev/null +++ b/config/suppliers/supplier-pack/supplier2-client1-campaign1.json @@ -0,0 +1,7 @@ +{ + "approval": "APPROVED", + "id": "supplier2-client1-campaign1", + "packSpecificationId": "client1-campaign1", + "status": "PROD", + "supplierId": "supplier2" +} diff --git a/tests/component-tests/allocation-tests/letter-allocation.spec.ts b/tests/component-tests/allocation-tests/letter-allocation.spec.ts new file mode 100644 index 000000000..5a7264466 --- /dev/null +++ b/tests/component-tests/allocation-tests/letter-allocation.spec.ts @@ -0,0 +1,92 @@ +import { expect, test } from "@playwright/test"; +import { sendSnsEvent } from "tests/helpers/send-sns-event"; +import { createPreparedV1Event } from "tests/helpers/event-fixtures"; +import { randomUUID } from "node:crypto"; +import { logger } from "tests/helpers/pino-logger"; +import { + getAllocationLogForDomainId, + getVariantsForAllocation, +} from "tests/helpers/allocation-helper"; + +test.describe("Allocator Lambda Tests", () => { + test.setTimeout(180_000); // 3 minutes for long running polling + + test(`Verify that allocator successfully allocates a letter and emits PENDING event`, async () => { + const domainId = randomUUID(); + logger.info(`Testing event subscription with domainId: ${domainId}`); + + const letterVariant = getVariantsForAllocation(1); + const preparedEvent = createPreparedV1Event({ + domainId, + letterVariantId: letterVariant, + }); + + const response = await sendSnsEvent(preparedEvent); + + expect(response.MessageId).toBeTruthy(); + + const supplierAllocatorLog = await getAllocationLogForDomainId(domainId); + const supplierId = + supplierAllocatorLog.msg?.allocationDetails?.supplierSpec?.supplierId; + const specId = + supplierAllocatorLog.msg?.allocationDetails?.supplierSpec?.specId; + const billingId = + supplierAllocatorLog.msg?.allocationDetails?.supplierSpec?.billingId; + const allocationStatus = + supplierAllocatorLog.msg?.allocationDetails?.allocationStatus?.status; + + if (!supplierId) { + throw new Error("supplierId was not found in supplier allocator log"); + } + + expect(specId).toBeTruthy(); + expect(billingId).toBeTruthy(); + expect(allocationStatus).toBe("PENDING"); + }); + + test("Verify that unknown letter variant is marked as rejected allocation", async () => { + const domainId = randomUUID(); + logger.info(`Testing rejected allocation with domainId: ${domainId}`); + + const preparedEvent = createPreparedV1Event({ + domainId, + letterVariantId: `unknown-variant-${domainId}`, + }); + + const response = await sendSnsEvent(preparedEvent); + + expect(response.MessageId).toBeTruthy(); + + const supplierAllocatorLog = await getAllocationLogForDomainId(domainId); + const supplierId = + supplierAllocatorLog.msg?.allocationDetails?.supplierSpec?.supplierId; + const allocationStatus = + supplierAllocatorLog.msg?.allocationDetails?.allocationStatus?.status; + const reasonCode = + supplierAllocatorLog.msg?.allocationDetails?.allocationStatus?.reasonCode; + + expect(supplierId).toBe("unknown"); + expect(allocationStatus).toBe("REJECTED"); + expect(reasonCode).toBe("NO_SUPPLIERS_AVAILABLE"); + }); + + test("Verify that first eligible supplier is selected", async () => { + const letterVariant = getVariantsForAllocation(1); + const domainId = randomUUID(); + + const preparedEvent = createPreparedV1Event({ + domainId, + letterVariantId: letterVariant, + pageCount: 6, // pagecount that makes supplier1 ineligible and supplier2 eligible based on our config + }); + + const response = await sendSnsEvent(preparedEvent); + expect(response.MessageId).toBeTruthy(); + + const supplierAllocatorLog = await getAllocationLogForDomainId(domainId); + const supplierId = + supplierAllocatorLog.msg?.allocationDetails?.supplierSpec?.supplierId; + + expect(supplierId).toBe("supplier2"); + }); +}); diff --git a/tests/helpers/allocation-helper.ts b/tests/helpers/allocation-helper.ts new file mode 100644 index 000000000..0a6a03898 --- /dev/null +++ b/tests/helpers/allocation-helper.ts @@ -0,0 +1,49 @@ +import { pollSupplierAllocatorLogForResolvedSpec } from "./aws-cloudwatch-helper"; +import { logger } from "./pino-logger"; + +export const AllocationTestVariantMap: Record = { + "notify-standard-test1": 1, + "client1-campaign1": 2, +}; + +export function getVariantsForAllocation(testCase: number) { + const variants = Object.keys(AllocationTestVariantMap).filter( + // safe as comes from map's keys which are controlled by us + // eslint-disable-next-line security/detect-object-injection + (variant) => AllocationTestVariantMap[variant] === testCase, + ); + if (variants.length === 0) { + throw new Error(`No variants found with testCase ${testCase}`); + } + return variants[0]; +} + +export type SupplierAllocatorLog = { + msg?: { + allocationDetails?: { + supplierSpec?: { + supplierId?: string; + specId?: string; + billingId?: string; + }; + allocationStatus?: { + status?: "PENDING" | "REJECTED"; + reasonCode?: string; + }; + }; + }; +}; + +export async function getAllocationLogForDomainId( + domainId: string, +): Promise { + const message = await pollSupplierAllocatorLogForResolvedSpec(domainId); + const supplierAllocatorLog = JSON.parse(message) as SupplierAllocatorLog; + + logger.info({ + description: "Received supplier allocator log message", + message: supplierAllocatorLog, + }); + + return supplierAllocatorLog; +}