/** * @jest-environment jest-fixed-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) ) }) }) })