UNPKG

@causalfoundry/js-sdk

Version:

Causal Foundry WEB SDK (JS/TS)

455 lines (402 loc) 12.6 kB
/** * @jest-environment jsdom */ import CfCore from "../../../core/CfCore"; import ECommerce from ".."; import { ECommerceTypes, ItemType, StockStatus, ItemProperties, ItemAction, } from "../typings"; import { CurrencyCode } from "../../../core/commonTypes"; import { ContentBlock } from "../../Navigation/typings"; let windowSpy; let mockSender; let mockImpressionManager = { on: () => {}, }; const device_id = "asdf"; describe("ECommerce", () => { beforeEach(() => { mockSender = { add() { return false; }, sendException() { return false; }, }; windowSpy = jest.spyOn(window, "window", "get"); }); afterEach(() => { // to remove the singleton instance (CfCore as any).instance = null; }); it('Should deliver a "Item" event', async () => { const senderSpy = jest.spyOn(mockSender, "add"); const cfCore = CfCore.createInstance( mockSender as any, mockImpressionManager as any, false, ContentBlock.Core, device_id, false ); const event: ItemProperties = { action: ItemAction.View, item: { id: "111", price: 90, type: ItemType.Drug, quantity: 1, promo_id: "11111", currency: CurrencyCode.EUR, stock_status: StockStatus.InStock, }, }; await ECommerce.logIngestEvent(ECommerceTypes.Item, event, true); expect(senderSpy).toHaveBeenCalledWith( expect.stringMatching(device_id), expect.stringMatching(device_id), expect.objectContaining({ name: ECommerceTypes.Item, ctx: expect.objectContaining({ // El item se transforma por getPayloadFromItem y serializeToFlatPrimitiveMap drug_id: "111", // Se agrega dinámicamente basado en el type price: 90, type: ItemType.Drug, quantity: 1, promo_id: "11111", currency: CurrencyCode.EUR, stock_status: StockStatus.InStock, }), }), true, expect.anything() ); }); it("Should throw exception and call sendException when quantity is negative", async () => { const addSpy = jest.spyOn(mockSender, "add"); const sendExceptionSpy = jest.spyOn(mockSender, "sendException"); const cfCore = CfCore.createInstance( mockSender as any, mockImpressionManager as any, false, ContentBlock.Core, device_id, false ); const event: ItemProperties = { action: ItemAction.View, item: { id: "111", price: 90, type: ItemType.Drug, quantity: -1, // Negative quantity promo_id: "11111", currency: CurrencyCode.EUR, stock_status: StockStatus.InStock, }, }; // The function should throw an exception due to negative quantity await expect( ECommerce.logIngestEvent(ECommerceTypes.Item, event, true) ).rejects.toThrow(); // add() should be called with an exception event when validation fails expect(addSpy).toHaveBeenCalledWith( expect.stringMatching(device_id), expect.stringMatching(device_id), expect.objectContaining({ name: "exception", property: "item", ctx: expect.objectContaining({ event_type: "item", exception_type: "Error", exception_source: "JS-SDK", }), }), false, false ); // sendException() should not be called (exceptions are logged via add) expect(sendExceptionSpy).not.toHaveBeenCalled(); }); it("Should throw exception and call sendException when price is negative", async () => { const addSpy = jest.spyOn(mockSender, "add"); const sendExceptionSpy = jest.spyOn(mockSender, "sendException"); const cfCore = CfCore.createInstance( mockSender as any, mockImpressionManager as any, false, ContentBlock.Core, device_id, false ); const event: ItemProperties = { action: ItemAction.View, item: { id: "111", price: -50, // Negative price type: ItemType.Drug, quantity: 1, promo_id: "11111", currency: CurrencyCode.EUR, stock_status: StockStatus.InStock, }, }; // The function should throw an exception due to negative price await expect( ECommerce.logIngestEvent(ECommerceTypes.Item, event, true) ).rejects.toThrow(); // add() should be called with an exception event when validation fails expect(addSpy).toHaveBeenCalledWith( expect.stringMatching(device_id), expect.stringMatching(device_id), expect.objectContaining({ name: "exception", property: "item", ctx: expect.objectContaining({ event_type: "item", exception_type: "Error", exception_source: "JS-SDK", }), }), false, false ); // sendException() should not be called (exceptions are logged via add) expect(sendExceptionSpy).not.toHaveBeenCalled(); }); it("Should throw exception and call sendException when id is missing", async () => { const addSpy = jest.spyOn(mockSender, "add"); const sendExceptionSpy = jest.spyOn(mockSender, "sendException"); const cfCore = CfCore.createInstance( mockSender as any, mockImpressionManager as any, false, ContentBlock.Core, device_id, false ); const event: ItemProperties = { action: ItemAction.View, item: { id: undefined as any, // Empty id price: 90, type: ItemType.Drug, quantity: 1, promo_id: "11111", currency: CurrencyCode.EUR, stock_status: StockStatus.InStock, }, }; // The function should throw an exception due to missing id await expect( ECommerce.logIngestEvent(ECommerceTypes.Item, event, true) ).rejects.toThrow(); // add() should be called with an exception event when validation fails expect(addSpy).toHaveBeenCalledWith( expect.stringMatching(device_id), expect.stringMatching(device_id), expect.objectContaining({ name: "exception", property: "item", ctx: expect.objectContaining({ event_type: "item", exception_type: "Error", exception_source: "JS-SDK", }), }), false, false ); // sendException() should not be called (exceptions are logged via add) expect(sendExceptionSpy).not.toHaveBeenCalled(); }); it("Should throw exception and call sendException when type is missing", async () => { const addSpy = jest.spyOn(mockSender, "add"); const sendExceptionSpy = jest.spyOn(mockSender, "sendException"); const cfCore = CfCore.createInstance( mockSender as any, mockImpressionManager as any, false, ContentBlock.Core, device_id, false ); const event: ItemProperties = { action: ItemAction.View, item: { id: "111", price: 90, type: undefined as any, // Missing type quantity: 1, promo_id: "11111", currency: CurrencyCode.EUR, stock_status: StockStatus.InStock, }, }; // The function should throw an exception due to missing type await expect( ECommerce.logIngestEvent(ECommerceTypes.Item, event, true) ).rejects.toThrow(); // add() should be called with an exception event when validation fails expect(addSpy).toHaveBeenCalledWith( expect.stringMatching(device_id), expect.stringMatching(device_id), expect.objectContaining({ name: "exception", property: "item", ctx: expect.objectContaining({ event_type: "item", exception_type: "Error", exception_source: "JS-SDK", }), }), false, false ); // sendException() should not be called (exceptions are logged via add) expect(sendExceptionSpy).not.toHaveBeenCalled(); }); it("Should throw exception and call sendException when currency is missing", async () => { const addSpy = jest.spyOn(mockSender, "add"); const sendExceptionSpy = jest.spyOn(mockSender, "sendException"); const cfCore = CfCore.createInstance( mockSender as any, mockImpressionManager as any, false, ContentBlock.Core, device_id, false ); const event: ItemProperties = { action: ItemAction.View, item: { id: "111", price: 90, type: ItemType.Drug, quantity: 1, promo_id: "11111", currency: undefined as any, // Missing currency stock_status: StockStatus.InStock, }, }; // The function should throw an exception due to missing currency await expect( ECommerce.logIngestEvent(ECommerceTypes.Item, event, true) ).rejects.toThrow(); // add() should be called with an exception event when validation fails expect(addSpy).toHaveBeenCalledWith( expect.stringMatching(device_id), expect.stringMatching(device_id), expect.objectContaining({ name: "exception", property: "item", ctx: expect.objectContaining({ event_type: "item", exception_type: "Error", exception_source: "JS-SDK", }), }), false, false ); // sendException() should not be called (exceptions are logged via add) expect(sendExceptionSpy).not.toHaveBeenCalled(); }); it("Should throw exception and call sendException when price is missing", async () => { const addSpy = jest.spyOn(mockSender, "add"); const sendExceptionSpy = jest.spyOn(mockSender, "sendException"); const cfCore = CfCore.createInstance( mockSender as any, mockImpressionManager as any, false, ContentBlock.Core, device_id, false ); const event: ItemProperties = { action: ItemAction.View, item: { id: "111", price: undefined as any, // Missing price type: ItemType.Drug, quantity: 1, promo_id: "11111", currency: CurrencyCode.EUR, stock_status: StockStatus.InStock, }, }; // The function should throw an exception due to missing price await expect( ECommerce.logIngestEvent(ECommerceTypes.Item, event, true) ).rejects.toThrow(); // add() should be called with an exception event when validation fails expect(addSpy).toHaveBeenCalledWith( expect.stringMatching(device_id), expect.stringMatching(device_id), expect.objectContaining({ name: "exception", property: "item", ctx: expect.objectContaining({ event_type: "item", exception_type: "Error", exception_source: "JS-SDK", }), }), false, false ); // sendException() should not be called (exceptions are logged via add) expect(sendExceptionSpy).not.toHaveBeenCalled(); }); it("Should throw exception and call sendException when quantity is missing", async () => { const addSpy = jest.spyOn(mockSender, "add"); const sendExceptionSpy = jest.spyOn(mockSender, "sendException"); const cfCore = CfCore.createInstance( mockSender as any, mockImpressionManager as any, false, ContentBlock.Core, device_id, false ); const event: ItemProperties = { action: ItemAction.View, item: { id: "111", price: 90, type: ItemType.Drug, quantity: undefined as any, // Missing quantity promo_id: "11111", currency: CurrencyCode.EUR, stock_status: StockStatus.InStock, }, }; // The function should throw an exception due to missing quantity await expect( ECommerce.logIngestEvent(ECommerceTypes.Item, event, true) ).rejects.toThrow(); // add() should be called with an exception event when validation fails expect(addSpy).toHaveBeenCalledWith( expect.stringMatching(device_id), expect.stringMatching(device_id), expect.objectContaining({ name: "exception", property: "item", ctx: expect.objectContaining({ event_type: "item", exception_type: "Error", exception_source: "JS-SDK", }), }), false, false ); // sendException() should not be called (exceptions are logged via add) expect(sendExceptionSpy).not.toHaveBeenCalled(); }); });