UNPKG

@benshi.ai/js-sdk

Version:

Benshi SDK

637 lines (543 loc) 21.2 kB
/** * @jest-environment jsdom */ import NudgeManager from "./BsNudgeManager"; import { DateTime } from 'luxon' import { CTAType, INudgesRepository } from "./repositories/nudges/typings"; import NudgeRepository from "./repositories/nudges/NudgeRepository"; import { NudgeManagerAction } from "./BsNudgeManager.typings"; describe('BsNudgeManager', () => { afterEach(() => { jest.clearAllMocks() }) it('Should do not do something when retrieving an empty list of nudges', (done) => { const mockBsNotification = { show() { return false }, on() { } } const mockNudgeRepository = { getNudges: jest.fn().mockResolvedValue([]), haveBeenAlreadyShown: jest.fn().mockReturnValue(false), markNudgeAsShown: jest.fn() } const notificationSpy = jest.spyOn(mockBsNotification, 'show') const nudgeManager = new NudgeManager( 'userId', mockBsNotification, mockNudgeRepository as INudgesRepository, ) setTimeout(() => { expect(notificationSpy).not.toHaveBeenCalled() done() }, 1000) }) it('Should show the notification for the given nudge', (done) => { const nudgeDate = DateTime.local().plus(20).toJSDate().toISOString() const nudgeExpiryDate = DateTime.local().plus({ seconds: 45 }).toJSDate().toISOString() const mockBsNotification = { show: jest.fn(), on: jest.fn() } const notificationSpy = jest.spyOn(mockBsNotification, 'show') const nudgeTitle = 'nudge-title' const nudgeBody = 'nudge-body' const nudgeId = 15501 const mockNudgeRepository = { getNudges: jest.fn().mockResolvedValue([{ id: nudgeId, dispatched_at: nudgeDate, expire_at: nudgeExpiryDate, action: { definition: { title: nudgeTitle, body: nudgeBody } } }]), haveBeenAlreadyShown: jest.fn().mockReturnValue(false), markNudgeAsShown: jest.fn() } const nudgeManager = new NudgeManager( 'userId', mockBsNotification, mockNudgeRepository as INudgesRepository, ) setTimeout(() => { // this timeout waits for the setTimeout inside the BsNudgeManager, which // should trigger in one second expect(notificationSpy).toBeCalledWith(nudgeTitle, nudgeBody, nudgeId) done() }, 100) }) it('Should show the notification for the given nudge even if its date has already passed, but not expired', (done) => { const nudgeDate = DateTime.local().plus({ seconds: -1 }).toJSDate().toISOString() const nudgeExpiryDate = DateTime.local().plus({ seconds: 45 }).toJSDate().toISOString() const mockBsNotification = { show: jest.fn(), on: jest.fn() } const notificationSpy = jest.spyOn(mockBsNotification, 'show') const nudgeTitle = 'nudge-title' const nudgeBody = 'nudge-body' const nudgeId = 15501 const mockNudgeRepository = { getNudges: jest.fn().mockResolvedValue([{ id: nudgeId, dispatched_at: nudgeDate, expire_at: nudgeExpiryDate, action: { definition: { title: nudgeTitle, body: nudgeBody } } }]), haveBeenAlreadyShown: jest.fn().mockReturnValue(false), markNudgeAsShown: jest.fn() } const nudgeManager = new NudgeManager( 'userId', mockBsNotification, mockNudgeRepository as INudgesRepository, ) setTimeout(() => { // this timeout waits for the setTimeout inside the BsNudgeManager, which // should trigger in one second expect(notificationSpy).toBeCalledWith(nudgeTitle, nudgeBody, nudgeId) done() }, 20) }) it('Should discard expired nudges', (done) => { const nudgeDate = DateTime.local().plus({ seconds: 20 }).toJSDate().toISOString() const nudgeExpiryDate = DateTime.local().plus({ seconds: 3 }).toJSDate().toISOString() const mockBsNotification = { show: jest.fn(), on: jest.fn() } const notificationSpy = jest.spyOn(mockBsNotification, 'show') const nudgeTitle = 'nudge-title' const nudgeBody = 'nudge-body' const nudgeId = 15501 const mockNudgeRepository = { getNudges: jest.fn().mockResolvedValue([{ id: nudgeId, dispatched_at: nudgeDate, expire_at: nudgeExpiryDate, action: { definition: { title: nudgeTitle, body: nudgeBody } } }]), haveBeenAlreadyShown: jest.fn().mockReturnValue(false), markNudgeAsShown: jest.fn() } const nudgeManager = new NudgeManager( 'userId', mockBsNotification, mockNudgeRepository as INudgesRepository ) setTimeout(() => { // this timeout waits for the setTimeout inside the BsNudgeManager, which // should trigger in one second expect(notificationSpy).not.toBeCalled() done() }, 200) }) it('Should discard nudges with the same ID (show only a notification regardless many fetches with repeated nudges)', (done) => { const nudgeDate = DateTime.local().plus({ seconds: -1 }).toJSDate().toISOString() const nudgeExpiryDate = DateTime.local().plus({ seconds: 45 }).toJSDate().toISOString() const mockBsNotification = { show: jest.fn(), on: jest.fn() } let saveValue = null const mockStorage = { save(key, value) { saveValue = value }, get() { return saveValue } } const notificationSpy = jest.spyOn(mockBsNotification, 'show') const nudgeTitle = 'nudge-title' const nudgeBody = 'nudge-body' const nudgeId = 15501 const mockBsNetwork = { get: jest.fn(() => new Promise(r => r( [ { "id": nudgeId, "action": { "id": nudgeId, "org_proj": "demo_demo", "name": "See what others are up to in {{app}}! ", "description": "", "tags": ["Intrigue"], "type": "push_notification", "target_cohort_ids": null, "definition": { "body": nudgeBody, "language": "en", "linkTo": "", "saveToLibrary": [""], "tags": ["Intrigue"], "title": nudgeTitle }, "created_by": "benshi", "created_at": "2022-01-26T09:04:56.383983Z" }, "expire_at": nudgeExpiryDate, "dispatched_at": nudgeDate } ]))), send: jest.fn() } const nudgesRepository = new NudgeRepository('fake-url', mockBsNetwork, mockStorage) const nudgeManager = new NudgeManager( 'userId', mockBsNotification, nudgesRepository, 20 ) setTimeout(() => { // this timeout waits for the setTimeout inside the BsNudgeManager, which // should trigger in one second expect(notificationSpy).toBeCalledTimes(1) done() }, 100) }) it('Should discard nudges with the same ID (show only a notification regardless many fetches with repeated nudges) - new nudges in second request', (done) => { const nudgeDate = DateTime.local().plus({ seconds: -1 }).toJSDate().toISOString() const nudgeExpiryDate = DateTime.local().plus({ seconds: 45 }).toJSDate().toISOString() const mockBsNotification = { show: jest.fn(), on: jest.fn() } let saveValue = null const mockStorage = { save(key, value) { saveValue = value }, get() { return saveValue } } const notificationSpy = jest.spyOn(mockBsNotification, 'show') const nudgeTitle = 'nudge-title' const nudgeBody = 'nudge-body' const nudgeId_1 = 15501 const nudgeId_2 = 15502 const mockBsNetwork = { get: jest.fn() .mockReturnValueOnce(new Promise(r => r( [ { "id": nudgeId_1, "action": { "id": nudgeId_1, "org_proj": "demo_demo", "name": "See what others are up to in {{app}}! ", "description": "", "tags": ["Intrigue"], "type": "push_notification", "target_cohort_ids": null, "definition": { "body": nudgeBody, "language": "en", "linkTo": "", "saveToLibrary": [""], "tags": ["Intrigue"], "title": nudgeTitle }, "created_by": "benshi", "created_at": "2022-01-26T09:04:56.383983Z" }, "expire_at": nudgeExpiryDate, "dispatched_at": nudgeDate } ]))) .mockReturnValue(new Promise(r => r( [{ "id": nudgeId_1, "action": { "id": nudgeId_1, "org_proj": "demo_demo", "name": "See what others are up to in {{app}}! ", "description": "", "tags": ["Intrigue"], "type": "push_notification", "target_cohort_ids": null, "definition": { "body": nudgeBody, "language": "en", "linkTo": "", "saveToLibrary": [""], "tags": ["Intrigue"], "title": nudgeTitle }, "created_by": "benshi", "created_at": "2022-01-26T09:04:56.383983Z" }, "expire_at": nudgeExpiryDate, "dispatched_at": nudgeDate }, { "id": nudgeId_2, "action": { "id": nudgeId_2, "org_proj": "demo_demo", "name": "See what others are up to in {{app}}! ", "description": "", "tags": ["Intrigue"], "type": "push_notification", "target_cohort_ids": null, "definition": { "body": nudgeBody, "language": "en", "linkTo": "", "saveToLibrary": [""], "tags": ["Intrigue"], "title": nudgeTitle }, "created_by": "benshi", "created_at": "2022-01-26T09:04:56.383983Z" }, "expire_at": nudgeExpiryDate, "dispatched_at": nudgeDate } ]))), send: jest.fn() } const nudgesRepository = new NudgeRepository('fake-url', mockBsNetwork, mockStorage) const nudgeManager = new NudgeManager( 'userId', mockBsNotification, nudgesRepository, 20 ) setTimeout(() => { // this timeout waits for the setTimeout inside the BsNudgeManager, which // should trigger in one second expect(notificationSpy).toBeCalledTimes(2) done() }, 60) }) it('Should emit an event on call_to_action to open itemId ', async () => { const mockBsNotification = { show: jest.fn(), on: (eventName, clb) => { if (eventName !== 'open') { return } setTimeout(() => { clb(111) }, 100) } } const fetchedNudgeData = [{ id: 111, dispatched_at: DateTime.local().plus(10).toJSDate().toISOString(), expire_at: DateTime.local().plus(150).toJSDate().toISOString(), action: { call_to_action: { type: CTAType.Redirect, cta_resource: { type: '', id: '45' } }, definition: { title: 'title-1', body: 'body-1' } } }] const mockNudgeRepository = { getNudges: jest.fn() .mockResolvedValue(fetchedNudgeData), haveBeenAlreadyShown: jest.fn().mockReturnValue(false), markNudgeAsShown: jest.fn() } const nudgeManager = new NudgeManager( 'userId', mockBsNotification, mockNudgeRepository as INudgesRepository, 200 ) const actionCallback = jest.fn() nudgeManager.on(NudgeManagerAction.Action, actionCallback) await new Promise((r) => setTimeout(r, 300)); expect(actionCallback).toBeCalled() }) it('Should NOT emit an event on call_to_action if the action is not redirect ', async () => { const mockBsNotification = { show: jest.fn(), on: (eventName, clb) => { if (eventName !== 'open') { return } setTimeout(() => { clb(111) }, 100) console.log('called method on: ', eventName) } } const fetchedNudgeData = [{ id: 111, dispatched_at: DateTime.local().plus(10).toJSDate().toISOString(), expire_at: DateTime.local().plus(150).toJSDate().toISOString(), action: { call_to_action: { type: CTAType.None, cta_resource: { type: '', id: '45' } }, definition: { title: 'title-1', body: 'body-1' } } }] const mockNudgeRepository = { getNudges: jest.fn() .mockResolvedValue(fetchedNudgeData), haveBeenAlreadyShown: jest.fn().mockReturnValue(false), markNudgeAsShown: jest.fn() } const nudgeManager = new NudgeManager( 'userId', mockBsNotification, mockNudgeRepository as INudgesRepository, 200 ) const actionCallback = jest.fn() nudgeManager.on(NudgeManagerAction.Action, actionCallback) await new Promise((r) => setTimeout(r, 300)); expect(actionCallback).not.toBeCalled() }) it('Should NOT emit an event on call_to_action if the id is missing ', async () => { const mockBsNotification = { show: jest.fn(), on: (eventName, clb) => { if (eventName !== 'open') { return } setTimeout(() => { clb(111) }, 100) console.log('called method on: ', eventName) } } const fetchedNudgeData = [{ id: 111, dispatched_at: DateTime.local().plus(10).toJSDate().toISOString(), expire_at: DateTime.local().plus(150).toJSDate().toISOString(), action: { call_to_action: { type: CTAType.Redirect, cta_resource: { type: '', id: '' } }, definition: { title: 'title-1', body: 'body-1' } } }] const mockNudgeRepository = { getNudges: jest.fn() .mockResolvedValue(fetchedNudgeData), haveBeenAlreadyShown: jest.fn().mockReturnValue(false), markNudgeAsShown: jest.fn() } const nudgeManager = new NudgeManager( 'userId', mockBsNotification, mockNudgeRepository as INudgesRepository, 200 ) const actionCallback = jest.fn() nudgeManager.on(NudgeManagerAction.Action, actionCallback) await new Promise((r) => setTimeout(r, 300)); expect(actionCallback).not.toBeCalled() }) it.skip('Should show nudges from differents fetchs', async () => { const mockBsNotification = { show: jest.fn(), on: jest.fn() } const notificationSpy = jest.spyOn(mockBsNotification, 'show') const firstFetch = [{ id: 111, dispatched_at: DateTime.local().plus(10).toJSDate().toISOString(), expire_at: DateTime.local().plus(150).toJSDate().toISOString(), title: 'title-1', body: 'body-1' }] const secondFetch = [{ id: 222, dispatched_at: DateTime.local().plus(20).toJSDate().toISOString(), title: 'title-2', body: 'body-2' }] const mockNudgeRepository = { getNudges: jest.fn() .mockResolvedValueOnce(firstFetch) .mockResolvedValue(secondFetch), haveBeenAlreadyShown: jest.fn().mockReturnValue(false), markNudgeAsShown: jest.fn() } const nudgeManager = new NudgeManager( 'userId', mockBsNotification, mockNudgeRepository as INudgesRepository, 200 ) await new Promise((r) => setTimeout(r, 300)); // expect(notificationSpy.mock.calls[0][0]).toEqual(firstFetch[0].title) // expect(notificationSpy.mock.calls[1][0]).toEqual(secondFetch[0].title) }) }) function BsNudgeEvents(BsNudgeEvents: any) { throw new Error("Function not implemented."); } /* // REAL NUDGE RESPONSE const response = [ { "id": nudgeId, "action": { "id": 121, "org_proj": "demo_demo", "name": "See what others are up to in {{app}}! ", "description": "", "tags": ["Intrigue"], "type": "push_notification", "target_cohort_ids": null, "definition": { "body": nudgeBody, "language": "en", "linkTo": "", "saveToLibrary": [""], "tags": ["Intrigue"], "title": nudgeTitle }, "created_by": "benshi", "created_at": "2022-01-26T09:04:56.383983Z" }, "dispatched_at": nudgeDate } ] */