@benshi.ai/js-sdk
Version:
Benshi SDK
637 lines (543 loc) • 21.2 kB
text/typescript
/**
* @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
}
]
*/