diff --git a/src/__tests__/transferWebhook.spec.ts b/src/__tests__/transferWebhook.spec.ts new file mode 100644 index 000000000..e7fe7b951 --- /dev/null +++ b/src/__tests__/transferWebhook.spec.ts @@ -0,0 +1,35 @@ +import BankingWebhookHandler from "../notification/bankingWebhookHandler"; +import { EstimationTrackingData } from "../typings/transferWebhooks/estimationTrackingData"; + +describe("Transfer Webhook Serialization", (): void => { + it("should correctly deserialize union types in transfer webhooks", () => { + // Simplest possible webhook with just the fields we need to test + const webhookData = { + data: { + id: "test-transfer-id", + tracking: { + estimatedArrivalTime: "2025-04-23T22:30:00+02:00", + type: "estimation", + }, + }, + type: "balancePlatform.transfer.updated", + }; + + const jsonString = JSON.stringify(webhookData); + const bankingWebhookHandler = new BankingWebhookHandler(jsonString); + const transferNotification = + bankingWebhookHandler.getTransferNotificationRequest(); + + if (transferNotification.data.tracking?.type === "estimation") { + // Verify that the tracking object is properly deserialized to the correct type + expect(transferNotification.data.tracking).toBeInstanceOf( + EstimationTrackingData + ); + + // Verify that estimatedArrivalTime is properly converted to a Date object + expect( + transferNotification.data.tracking.estimatedArrivalTime + ).toBeInstanceOf(Date); + } + }); +}); diff --git a/src/typings/transferWebhooks/models.ts b/src/typings/transferWebhooks/models.ts index 3527dbef3..dd5962a6a 100644 --- a/src/typings/transferWebhooks/models.ts +++ b/src/typings/transferWebhooks/models.ts @@ -259,6 +259,25 @@ export class ObjectSerializer { return expectedType; } + // Handle union types + if (expectedType.includes(" | ")) { + const unionTypes = expectedType.split(" | ").map((t) => t.trim()); + + // For tracking field specifically, use the 'type' field to determine the actual type + if (data && data.type && unionTypes.some((t) => t.includes("TrackingData"))) { + if (data.type === "estimation") return "EstimationTrackingData"; + if (data.type === "confirmation") return "ConfirmationTrackingData"; + if (data.type === "internalReview") return "InternalReviewTrackingData"; + } + + // For other union types, return the first non-null type that exists in typeMap + for (const type of unionTypes) { + if (type !== "null" && typeMap[type]) { + return type; + } + } + } + if (!typeMap[expectedType]) { return expectedType; // w/e we don't know the type }