@benshi.ai/js-sdk
Version:
Benshi SDK
345 lines (285 loc) • 10.2 kB
text/typescript
import BsSender from './BsSender'
import { ContentBlock, NavigationTypes } from '../modules/Navigation/typings';
import { AppAction } from '../modules/Navigation/typings';
import {AppInfoObject, DeviceInfoObject, EventMainObject} from "./typings";
jest.useFakeTimers();
jest.spyOn(global, 'setInterval');
const numberOfRetries = 3
const senderOptions = {
flushInterval: 10000,
flushMaxRetries: numberOfRetries,
baseUrl: 'www.base.url',
ingestPath: '/ingestPath',
currencyPath: '/currencyPath',
nudgeFetchPath: '/nudgePath',
catalogPath: '/catalog',
activateNudgeMechanism: true,
cacheEventsInLocalstorage: true,
cacheEventsKey: 'bslog',
debug: true
}
const deviceObject: DeviceInfoObject = {
id: 'device_id',
brand: "testBrand",
model: "testBrand",
os: 'linux',
os_ver: 'linux',
}
const appObject: AppInfoObject = {
id: "websiteURL",
min_sdk_version: 21,
target_sdk_version: 31,
version: "1.0.3 (3)",
version_code: 3,
version_name: "1.0.3",
}
describe('BsSender', () => {
it('Should send one event when flushing explicity', () => {
const mockBsNetwork = {
send: jest.fn( () => new Promise(r => r([]) )),
get: jest.fn()
}
const notificationSpy = jest.spyOn(mockBsNetwork, 'send')
const bsSender = new BsSender(mockBsNetwork, senderOptions)
const event = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:28Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 200
}
};
bsSender.add("userId", "deviceId", event)
bsSender.flush()
// [0][1] -> first call, parameter 1
expect(notificationSpy).toBeCalledWith(
expect.anything(),
{
data:
expect.arrayContaining([
expect.objectContaining({ ts: "2022-01-12T07:36:28Z" })
]),
app_info : expect.anything(),
d_info : expect.anything(),
dn : expect.anything(),
up : expect.anything(),
sdk : expect.anything(),
u_id : expect.anything(),
s_id : expect.anything(),
}
)
})
it('Should send one event when setting forceSend = true', () => {
const mockBsNetwork = {
send: jest.fn( () => new Promise(r => r([]) )),
get: jest.fn()
}
const notificationSpy = jest.spyOn(mockBsNetwork, 'send')
const bsSender = new BsSender(mockBsNetwork, senderOptions)
const event = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:28Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 112
}
};
bsSender.add("userId", "deviceId", event, true)
// [0][1] -> first call, parameter 1
expect(notificationSpy).toBeCalledWith(
expect.anything(),
{data:
expect.arrayContaining([
expect.objectContaining({ ts: "2022-01-12T07:36:28Z" })
]),
app_info : expect.anything(),
d_info : expect.anything(),
dn : expect.anything(),
up : expect.anything(),
sdk : expect.anything(),
u_id : expect.anything(),
s_id : expect.anything(),
}
)
})
it('Should NOT send the event immediately when not forced', () => {
const mockBsNetwork = {
send: jest.fn( () => new Promise(r => r([]) )),
get: jest.fn()
}
const networkSendSpy = jest.spyOn(mockBsNetwork, 'send')
const bsSender = new BsSender(mockBsNetwork, senderOptions)
const event = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:28Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 112
}
};
bsSender.add("userId", "deviceId", event, false)
// [0][1] -> first call, parameter 1
expect(networkSendSpy).toBeCalledTimes(0)
})
it('Should not sent the event after reaching the maximum number of retries', async() => {
const mockBsNetwork = {
send: jest
.fn()
.mockRejectedValueOnce(new Error('Async error'))
.mockRejectedValueOnce(new Error('Async error'))
.mockRejectedValueOnce(new Error('Async error'))
.mockResolvedValueOnce('first call'),
get: jest.fn()
}
const notificationSpy = jest.spyOn(mockBsNetwork, 'send')
const bsSender = new BsSender(mockBsNetwork, senderOptions)
const event = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:28Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 133
}
};
bsSender.add("userId", "deviceId", event)
await bsSender.flush()
await bsSender.flush()
await bsSender.flush()
await bsSender.flush()
await bsSender.flush()
await bsSender.flush()
await bsSender.flush()
await bsSender.flush()
expect(notificationSpy).toBeCalledTimes(numberOfRetries + 1)
})
it('Should release the queue when flushing explicity', async () => {
const mockBsNetwork = {
send: jest.fn(() => Promise.resolve()),
get: jest.fn()
}
const notificationSpy = jest.spyOn(mockBsNetwork, 'send')
const bsSender = new BsSender(mockBsNetwork, senderOptions)
const event = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:28Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 131
}
};
bsSender.add("userId", "deviceId", event)
await bsSender.flush()
await bsSender.flush()
// first "flush" will call it, but second one not, because the list
// is already empty
expect(notificationSpy).toHaveBeenCalledTimes(1)
})
it('Should enqueue event when there is a network error', async () => {
const mockBsNetwork = {
send: jest
.fn()
.mockRejectedValueOnce(new Error('Async error'))
.mockResolvedValueOnce('first call'),
get: jest.fn()
}
const notificationSpy = jest.spyOn(mockBsNetwork, 'send')
const bsSender = new BsSender(mockBsNetwork, senderOptions)
const event = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:28Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 131
}
};
bsSender.add("userId", "deviceId", event)
await bsSender.flush()
await bsSender.flush()
expect(notificationSpy).lastCalledWith(
expect.anything(),
{
data: expect.arrayContaining([
expect.objectContaining({ ts: "2022-01-12T07:36:28Z" })
]),
app_info : expect.anything(),
d_info : expect.anything(),
dn : expect.anything(),
up : expect.anything(),
sdk : expect.anything(),
u_id : expect.anything(),
s_id : expect.anything(),
}
)
})
it('Should send all events receive from last flushing explicity - explicit flush', async () => {
const mockBsNetwork = {
send: jest.fn(() => Promise.resolve()),
get: jest.fn()
}
const notificationSpy = jest.spyOn(mockBsNetwork, 'send')
const bsSender = new BsSender(mockBsNetwork, senderOptions)
const event1 = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:28Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 122
}
};
const event2 = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:29Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 122
}
};
const event3 = {
block: ContentBlock.Core,
ol: true,
ts: "2022-01-12T07:36:30Z",
type: NavigationTypes.App,
props: {
action: AppAction.Open,
start_time : 122
}
};
bsSender.add("userId", "deviceId", event1)
bsSender.add("userId", "deviceId", event2)
bsSender.add("userId", "deviceId", event3)
await bsSender.flush()
expect(notificationSpy).toHaveBeenCalledWith(
expect.anything(),
{
data: expect.arrayContaining([
expect.objectContaining({ ts: "2022-01-12T07:36:28Z" }),
expect.objectContaining({ ts: "2022-01-12T07:36:29Z" }),
expect.objectContaining({ ts: "2022-01-12T07:36:30Z" }),
]),
app_info : expect.anything(),
d_info : expect.anything(),
dn : expect.anything(),
up : expect.anything(),
sdk : expect.anything(),
u_id : expect.anything(),
s_id : expect.anything(),
}
)
})
})