salsify-experiences-sdk
Version:
SDK to be used by commerce websites to implement product experiences.
135 lines (108 loc) • 5.08 kB
text/typescript
/**
* @jest-environment jsdom
*/
import { useConsoleLogger } from '../devTools'
import Transport from '../logger/log-service-transport'
import { createLogger } from '../logger'
import TimeOnPageTracker from '../time-on-page-tracker'
import { makeContext, makeSettings } from '../../__tests__/helpers'
import EnhancedContentApi, { EcRenderConfig } from '../../enhancedContent'
jest.mock('../devTools')
jest.mock('../logger/log-service-transport')
const log = jest.fn()
const ecApi = new EnhancedContentApi(makeSettings(), makeContext(), { log })
const lastEcRenderConfigSpy = jest.spyOn(ecApi, 'lastRenderConfig', 'get')
describe('time on page tracker', () => {
describe('log time on page event', () => {
beforeEach(() => {
;(Transport as jest.Mock).mockClear()
jest.useFakeTimers()
;(useConsoleLogger as jest.Mock).mockReturnValue(false)
})
test('should fire event on interval', () => {
const logger = createLogger(makeContext(), makeSettings())
const tracker = new TimeOnPageTracker(logger)
tracker.start()
jest.advanceTimersByTime(5000)
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(1)
jest.advanceTimersByTime(5000 * Math.pow(2, 2))
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(2)
jest.advanceTimersByTime(5000 * Math.pow(3, 2))
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(3)
})
test('should fire event on visibilitychange to hidden', () => {
const logger = createLogger(makeContext(), makeSettings())
const tracker = new TimeOnPageTracker(logger)
tracker.start()
jest.spyOn(document, 'visibilityState', 'get').mockReturnValue('hidden')
document.dispatchEvent(new Event('visibilitychange', { bubbles: true, cancelable: true }))
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(1)
})
test('should fire event on visibilitychange to visible', () => {
const logger = createLogger(makeContext(), makeSettings())
const tracker = new TimeOnPageTracker(logger)
tracker.start()
jest.spyOn(document, 'visibilityState', 'get').mockReturnValue('visible')
document.dispatchEvent(new Event('visibilitychange', { bubbles: true, cancelable: true }))
// No event fire when switch to visible, but it will start the timer
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(0)
jest.advanceTimersByTime(5000)
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(1)
})
test('stop will stop events', () => {
const logger = createLogger(makeContext(), makeSettings())
const tracker = new TimeOnPageTracker(logger)
tracker.start()
tracker.stop()
jest.advanceTimersByTime(5000)
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(0)
jest.spyOn(document, 'visibilityState', 'get').mockReturnValue('hidden')
document.dispatchEvent(new Event('visibilitychange', { bubbles: true, cancelable: true }))
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(0)
})
test('restart will restart events', () => {
const logger = createLogger(makeContext(), makeSettings())
const tracker = new TimeOnPageTracker(logger)
tracker.start()
jest.advanceTimersByTime(5000)
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(1)
tracker.restart()
// After restart, the first event will be sent after 5 seconds
jest.advanceTimersByTime(5000)
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(2)
})
test('should include last EC render after render', () => {
const logger = createLogger(makeContext(), makeSettings())
const tracker = new TimeOnPageTracker(logger, ecApi)
tracker.start()
jest.advanceTimersByTime(5000)
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(1)
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenLastCalledWith(
'time_on_page',
expect.objectContaining({
lastEcRenderConfig: undefined,
}),
expect.any(Object)
)
const lastEcRenderConfig: EcRenderConfig = {
productId: '1234',
idType: 'SKU',
content: [
{ source: 'foo.html', weight: 0.95 },
{ source: null, weight: 0.05 },
],
allContentExists: true,
source: 'foo.html',
sourceExists: true,
}
lastEcRenderConfigSpy.mockReturnValue(lastEcRenderConfig)
jest.advanceTimersByTime(5000 * Math.pow(2, 2))
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenCalledTimes(2)
expect((Transport as jest.Mock).mock.instances[0].log).toHaveBeenLastCalledWith(
'time_on_page',
expect.objectContaining({ lastEcRenderConfig }),
expect.any(Object)
)
})
})
})