import { Reporter } from '../../Reporter'; import { UA_REGEX, UUID_REGEX, UUID_REGEX_STRING } from '../../../../../tests/shared'; import { WebAdapter } from '../WebAdapter'; class TestReporter extends Reporter {} function getReporterAndInitialedAdapter() { const reporter = new TestReporter(); const adapter = new WebAdapter(); adapter.init(reporter); return { reporter, adapter }; } describe('WebAdapter', () => { beforeEach(() => { history.pushState({}, '', '/'); }); it("won't shut down when not init correctly", () => { const adapter = new WebAdapter(); expect(() => adapter.updateScopeInfo).not.toThrow(); expect(adapter.serializeLinkedData()).toBe(''); expect(adapter.envInfo).toEqual({}); }); it('updateScopeInfo correctly', () => { const { reporter, adapter } = getReporterAndInitialedAdapter(); adapter.updateScopeInfo(); expect(reporter.scopeContext).toStrictEqual({ clientHeight: 768, clientWidth: 1024, contextId: expect.stringMatching(UUID_REGEX), devicePixelRatio: 1, screenHeight: 0, screenWidth: 0, href: 'http://localhost/', }); }); it('readLinkedData correctly when all query params are provided', () => { const { reporter, adapter } = getReporterAndInitialedAdapter(); expect(reporter.scopeInfo.contextId).toMatch(UUID_REGEX); expect(reporter.scopeInfo.entranceId).toBeUndefined(); expect(reporter.scopeInfo.entranceInfo?.subEntranceid).toBeUndefined(); expect(reporter.scopeInfo.fromAccessId).toBeUndefined(); expect(reporter.scopeInfo.fromElementId).toBeUndefined(); history.pushState( {}, 'El Psy Congroo', 'http://localhost/home?a=1&context_id=el-psy-congroo&entrance_id=ei12312&sub_entranceid=se123&from_access_id=fa123&from_element_id=fe123&reddot_id=rd123', ); adapter.readLinkedData(); expect(reporter.scopeInfo.contextId).toBe('el-psy-congroo'); expect(reporter.scopeInfo.entranceId).toBe('ei12312'); expect(reporter.scopeInfo.entranceInfo?.subEntranceid).toBe('se123'); expect(reporter.scopeInfo.fromAccessId).toBe('fa123'); expect(reporter.scopeInfo.fromElementId).toBe('fe123'); expect(reporter.scopeInfo.redDotInfo?.id).toBe('rd123'); }); it('readLinkedData correctly when part of query params are provided', () => { const { reporter, adapter } = getReporterAndInitialedAdapter(); history.pushState({}, 'El Psy Congroo', 'http://localhost/home?a=1&context_id=el-psy-congroo&entrance_id=ei12312'); adapter.readLinkedData(); expect(reporter.scopeInfo.contextId).toBe('el-psy-congroo'); expect(reporter.scopeInfo.entranceId).toBe('ei12312'); expect(reporter.scopeInfo.entranceInfo?.subEntranceid).toBeUndefined(); expect(reporter.scopeInfo.fromAccessId).toBeUndefined(); expect(reporter.scopeInfo.fromElementId).toBeUndefined(); expect(reporter.scopeInfo.redDotInfo?.id).toBeUndefined(); }); it('readLinkedData correctly when no query param is provided', () => { const { reporter, adapter } = getReporterAndInitialedAdapter(); history.pushState({}, 'El Psy Congroo', 'http://localhost/home?a=1'); adapter.readLinkedData(); expect(reporter.scopeInfo.contextId).toMatch(UUID_REGEX); expect(reporter.scopeInfo.entranceId).toBeUndefined(); expect(reporter.scopeInfo.entranceInfo?.subEntranceid).toBeUndefined(); expect(reporter.scopeInfo.fromAccessId).toBeUndefined(); expect(reporter.scopeInfo.fromElementId).toBeUndefined(); expect(reporter.scopeInfo.redDotInfo?.id).toBeUndefined(); }); it('get linkedData correctly', () => { const { adapter } = getReporterAndInitialedAdapter(); expect(adapter.linkedData).toStrictEqual({ contextId: expect.stringMatching(UUID_REGEX), entranceId: undefined, subEntranceid: undefined, reddotId: undefined, }); history.pushState( {}, 'El Psy Congroo', 'http://localhost/home?a=1&context_id=el-psy-congroo&entrance_id=ei12312&from_access_id=fa123&from_element_id=fe123&reddot_id=rd123', ); adapter.readLinkedData(); expect(adapter.linkedData).toStrictEqual({ contextId: 'el-psy-congroo', entranceId: 'ei12312', subEntranceid: undefined, reddotId: 'rd123', }); }); it('serializeLinkedData correctly', () => { const { adapter } = getReporterAndInitialedAdapter(); expect(adapter.serializeLinkedData()).toMatch(new RegExp(`^context_id=${UUID_REGEX_STRING}$`)); history.pushState( {}, 'El Psy Congroo', 'http://localhost/home?a=1&context_id=el-psy-congroo&entrance_id=ei12312&from_access_id=fa123&from_element_id=fe123&reddot_id=rd123', ); adapter.readLinkedData(); expect(adapter.serializeLinkedData()).toMatchInlineSnapshot( `"context_id=el-psy-congroo&entrance_id=ei12312&reddot_id=rd123"`, ); }); it('serializeLinkedData correctly when extra params provided', () => { const { adapter } = getReporterAndInitialedAdapter(); expect( adapter.serializeLinkedData({ fromAccessId: 'Anya', }), ).toMatch(new RegExp(`^context_id=${UUID_REGEX_STRING}&from_access_id=Anya$`)); history.pushState( {}, 'El Psy Congroo', 'http://localhost/home?a=1&context_id=el-psy-congroo&entrance_id=ei12312&from_access_id=fa123&from_element_id=fe123', ); adapter.readLinkedData(); expect( adapter.serializeLinkedData({ fromAccessId: 'Anya', }), ).toMatchInlineSnapshot(`"context_id=el-psy-congroo&entrance_id=ei12312&from_access_id=Anya"`); }); it('getEnvInfo correctly', () => { const { adapter } = getReporterAndInitialedAdapter(); expect(adapter.envInfo).toStrictEqual({ userAgent: expect.stringMatching(UA_REGEX), }); }); }); describe('WebAdapter.storage', () => { beforeEach(() => { localStorage.clear(); }); it("won't setLocal with null or undefined value", () => { const localStorageSetItemSpy = jest.spyOn(global.localStorage.__proto__, 'setItem'); const adapter = new WebAdapter(); adapter.storage.setItem('test1', null); expect(localStorageSetItemSpy).not.toHaveBeenCalled(); expect(Object.keys(localStorage).length).toBe(0); adapter.storage.setItem('test2', undefined); expect(localStorageSetItemSpy).not.toHaveBeenCalled(); expect(Object.keys(localStorage).length).toBe(0); }); it('will setLocal with correctly stringified value', () => { const localStorageSetItemSpy = jest.spyOn(global.localStorage.__proto__, 'setItem'); const adapter = new WebAdapter(); adapter.storage.setItem('testNumber', 123); expect(localStorageSetItemSpy).toHaveBeenCalledWith('testNumber', '123'); expect(localStorage.getItem('testNumber')).toBe('123'); adapter.storage.setItem('testString', 'asd'); expect(localStorageSetItemSpy).toHaveBeenCalledWith('testString', '"asd"'); expect(localStorage.getItem('testString')).toBe('"asd"'); adapter.storage.setItem('testEmptyString', ''); expect(localStorageSetItemSpy).toHaveBeenCalledWith('testEmptyString', '""'); expect(localStorage.getItem('testEmptyString')).toBe('""'); adapter.storage.setItem('testBoolean', true); expect(localStorageSetItemSpy).toHaveBeenCalledWith('testBoolean', 'true'); expect(localStorage.getItem('testBoolean')).toBe('true'); adapter.storage.setItem('testObject', { a: 1, b: 2 }); expect(localStorageSetItemSpy).toHaveBeenCalledWith('testObject', '{"a":1,"b":2}'); expect(localStorage.getItem('testObject')).toBe('{"a":1,"b":2}'); adapter.storage.setItem('testNestedObject', { a: 1, b: { c: 'asd' } }); expect(localStorageSetItemSpy).toHaveBeenCalledWith('testNestedObject', '{"a":1,"b":{"c":"asd"}}'); expect(localStorage.getItem('testNestedObject')).toBe('{"a":1,"b":{"c":"asd"}}'); adapter.storage.setItem('testArray', [1, 2, 'asd', { a: 1, b: 2 }]); expect(localStorageSetItemSpy).toHaveBeenCalledWith('testArray', '[1,2,"asd",{"a":1,"b":2}]'); expect(localStorage.getItem('testArray')).toBe('[1,2,"asd",{"a":1,"b":2}]'); expect(localStorageSetItemSpy).toHaveBeenCalledTimes(7); }); it('removeLocal correctly', () => { const adapter = new WebAdapter(); localStorage.setItem('test', '123'); adapter.storage.removeItem('test'); expect(localStorage.getItem('test')).toBeNull(); expect(() => adapter.storage.removeItem('test')).not.toThrow(); }); it('getLocal with un-stringified value', async () => { const adapter = new WebAdapter(); localStorage.setItem('test', 123 as unknown as string); expect(await adapter.storage.getItem('test')).toBe(123); }); it('getLocal will return default value if get undefined or null', async () => { const adapter = new WebAdapter(); expect(await adapter.storage.getItem('test', 123)).toBe(123); expect(await adapter.storage.getItem('test', undefined)).toBeUndefined(); expect(await adapter.storage.getItem('test', null)).toBeNull(); localStorage.setItem('test', '123'); expect(await adapter.storage.getItem('test', 345)).toBe(123); }); it('getLocal correctly', async () => { const adapter = new WebAdapter(); adapter.storage.setItem('testNumber', 123); adapter.storage.setItem('testString', 'asd'); adapter.storage.setItem('testEmptyString', ''); adapter.storage.setItem('testBoolean', true); adapter.storage.setItem('testObject', { a: 1, b: 2 }); adapter.storage.setItem('testNestedObject', { a: 1, b: { c: 'asd' } }); adapter.storage.setItem('testArray', [1, 2, 'asd', { a: 1, b: 2 }]); expect(await adapter.storage.getItem('testNumber')).toBe(123); expect(await adapter.storage.getItem('testString')).toBe('asd'); expect(await adapter.storage.getItem('testEmptyString')).toBe(''); expect(await adapter.storage.getItem('testBoolean')).toBe(true); expect(await adapter.storage.getItem('testObject')).toEqual({ a: 1, b: 2 }); expect(await adapter.storage.getItem('testNestedObject')).toEqual({ a: 1, b: { c: 'asd' } }); expect(await adapter.storage.getItem('testArray')).toEqual([1, 2, 'asd', { a: 1, b: 2 }]); }); });