@apptus/esales-api
Version:
Library for making requests to Elevate 4 API v3
273 lines (201 loc) • 9.89 kB
text/typescript
import { describe, it, expect } from '#test';
import { localStorageBackedSession, LocalStorageSession, __sessionMetadataCache } from './session.ts';
const uuidv4 = /[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/;
const uuidStr = expect.stringMatching(uuidv4);
const suite = describe({
name: 'localStorageBackedSession()',
beforeEach() {
localStorage.clear();
__sessionMetadataCache.clear();
}
});
const jsonSuite = describe({
suite,
name: 'JSON parsing'
});
it(suite, 'should have empty cache and localStorage before reading session', () => {
localStorageBackedSession() satisfies LocalStorageSession;
expect(localStorage.length).toBe(0);
expect(__sessionMetadataCache.size).toBe(0);
});
it(suite, 'should return randomized uuid keys for empty storage', () => {
const session = localStorageBackedSession();
const result = session();
const { customerKey, sessionKey } = result;
expect(result).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('voyado.session')).toBe(`{"customerKey":"${customerKey}","sessionKey":"${sessionKey}"}`);
});
it(suite, 'should return the same cached value when retrieved multiple times', () => {
const session = localStorageBackedSession();
const data = session();
localStorage.clear();
expect(data).toBe(session());
expect(data).toBe(session());
});
it(suite, 'should return new random keys when cache and localStorage is cleared', () => {
const session = localStorageBackedSession();
const data = session();
localStorage.clear();
__sessionMetadataCache.clear();
expect(data).not.toEqual(session());
});
it(suite, 'should clear cache key when window storage event occurs', () => {
const session = localStorageBackedSession('storageEv');
const data = session();
const sizePriorDispatch = __sessionMetadataCache.size;
globalThis.dispatchEvent(new StorageEvent('storage', {
key: 'storageEv',
storageArea: localStorage
}));
expect(sizePriorDispatch).toBe(1);
expect(__sessionMetadataCache.size).toBe(0);
expect(data).not.toBe(session());
expect(data).toEqual(session());
});
it(suite, 'should NOT clear cache key when window storage event does not match', () => {
const session = localStorageBackedSession('nonStorageEv');
const data = session();
const sizePriorDispatch = __sessionMetadataCache.size;
globalThis.dispatchEvent(new StorageEvent('storage', {
key: '=== Non-match ===',
storageArea: localStorage
}));
globalThis.dispatchEvent(new StorageEvent('storage', {
key: 'nonStorageEv',
storageArea: sessionStorage
}));
globalThis.dispatchEvent(new Event('click'));
expect(sizePriorDispatch).toBe(1);
expect(__sessionMetadataCache.size).toBe(1);
expect(data).toBe(session());
});
it(suite, 'should return new randomized keys when clear is run', () => {
const session = localStorageBackedSession('reset');
const a = session();
session.reset();
const b = session();
expect(a).not.toEqual(b);
expect(b).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('reset')).toBe(`{"customerKey":"${b.customerKey}","sessionKey":"${b.sessionKey}"}`);
});
it(suite, 'should return the latest set customerKey', () => {
const session = localStorageBackedSession('update');
session.updateCustomerKey('Bruce Wayne 🦇');
const result = session();
expect(result).toEqual({ customerKey: 'Bruce Wayne 🦇', sessionKey: uuidStr });
expect(localStorage.getItem('update')).toBe(`{"customerKey":"Bruce Wayne 🦇","sessionKey":"${result.sessionKey}"}`);
});
it(jsonSuite, 'should return existing storage keys', () => {
const session = localStorageBackedSession('existing');
localStorage.setItem('existing', '{"customerKey":"foo","sessionKey":"bar"}');
const result = session();
expect(result).toEqual({ customerKey: 'foo', sessionKey: 'bar' });
expect(localStorage.getItem('existing')).toBe('{"customerKey":"foo","sessionKey":"bar"}');
});
it(jsonSuite, 'should return randomized uuid keys for invalid JSON', () => {
const session = localStorageBackedSession('invalid');
localStorage.setItem('invalid', 'not actually JSON! 😲');
const result = session();
const { customerKey, sessionKey } = result;
expect(result).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('invalid')).toBe(`{"customerKey":"${customerKey}","sessionKey":"${sessionKey}"}`);
});
it(jsonSuite, 'should reset data for stored boolean JSON data', () => {
const session = localStorageBackedSession('bool');
localStorage.setItem('bool', 'true');
const result = session();
const { customerKey, sessionKey } = result;
expect(result).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('bool')).toBe(`{"customerKey":"${customerKey}","sessionKey":"${sessionKey}"}`);
});
it(jsonSuite, 'should reset data for stored number JSON data', () => {
const session = localStorageBackedSession('num');
localStorage.setItem('num', '987.123');
const result = session();
const { customerKey, sessionKey } = result;
expect(result).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('num')).toBe(`{"customerKey":"${customerKey}","sessionKey":"${sessionKey}"}`);
});
it(jsonSuite, 'should reset data for stored string JSON data', () => {
const session = localStorageBackedSession('str');
localStorage.setItem('str', '"Hello there!"');
const result = session();
const { customerKey, sessionKey } = result;
expect(result).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('str')).toBe(`{"customerKey":"${customerKey}","sessionKey":"${sessionKey}"}`);
});
it(jsonSuite, 'should reset data for stored null JSON data', () => {
const session = localStorageBackedSession('nully');
localStorage.setItem('nully', 'null');
const result = session();
const { customerKey, sessionKey } = result;
expect(result).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('nully')).toBe(`{"customerKey":"${customerKey}","sessionKey":"${sessionKey}"}`);
});
it(jsonSuite, 'should reset data for stored array JSON data', () => {
const session = localStorageBackedSession('arr');
localStorage.setItem('arr', '["foo", "bar"]');
const result = session();
const { customerKey, sessionKey } = result;
expect(result).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('arr')).toBe(`{"customerKey":"${customerKey}","sessionKey":"${sessionKey}"}`);
});
it(jsonSuite, 'should repair broken stored empty metadata on read', () => {
const session = localStorageBackedSession('empty');
localStorage.setItem('empty', '{}');
const result = session();
const { customerKey, sessionKey } = result;
expect(result).toEqual({ customerKey: uuidStr, sessionKey: uuidStr });
expect(localStorage.getItem('empty')).toBe(`{"customerKey":"${customerKey}","sessionKey":"${sessionKey}"}`);
});
it(jsonSuite, 'should repair broken stored partial metadata on read', () => {
const session = localStorageBackedSession('repair');
localStorage.setItem('repair', '{"customerKey":"partial"}');
const result = session();
expect(result).toEqual({ customerKey: 'partial', sessionKey: uuidStr });
expect(localStorage.getItem('repair')).toBe(`{"customerKey":"partial","sessionKey":"${result.sessionKey}"}`);
});
it(jsonSuite, 'should repair invalid primitive type on "sessionKey"', () => {
const session = localStorageBackedSession('s-type');
localStorage.setItem('s-type', '{"customerKey":"abc","sessionKey":99}');
const result = session();
expect(result).toEqual({ customerKey: 'abc', sessionKey: uuidStr });
expect(localStorage.getItem('s-type')).toBe(`{"customerKey":"abc","sessionKey":"${result.sessionKey}"}`);
});
it(jsonSuite, 'should repair invalid object type on "sessionKey"', () => {
const session = localStorageBackedSession('s-type');
localStorage.setItem('s-type', '{"customerKey":"abc","sessionKey":{}}');
const result = session();
expect(result).toEqual({ customerKey: 'abc', sessionKey: uuidStr });
expect(localStorage.getItem('s-type')).toBe(`{"customerKey":"abc","sessionKey":"${result.sessionKey}"}`);
});
it(jsonSuite, 'should repair invalid primitive type on "customerKey"', () => {
const session = localStorageBackedSession('c-prim');
localStorage.setItem('c-prim', '{"customerKey":true,"sessionKey":"42"}');
const result = session();
expect(result).toEqual({ customerKey: uuidStr, sessionKey: '42' });
expect(localStorage.getItem('c-prim')).toBe(`{"customerKey":"${result.customerKey}","sessionKey":"42"}`);
});
it(jsonSuite, 'should repair invalid object type on "customerKey"', () => {
const session = localStorageBackedSession('c-obj');
localStorage.setItem('c-obj', '{"customerKey":{},"sessionKey":"42"}');
const result = session();
expect(result).toEqual({ customerKey: uuidStr, sessionKey: '42' });
expect(localStorage.getItem('c-obj')).toBe(`{"customerKey":"${result.customerKey}","sessionKey":"42"}`);
});
it(jsonSuite, 'should discard extraneous properties on stored metadata on read', () => {
const session = localStorageBackedSession('extraneous');
localStorage.setItem('extraneous', '{"foo":"foo","customerKey":"123","sessionKey":"321","bar":"bar"}');
const result = session();
expect(result).toEqual({ customerKey: '123', sessionKey: '321' });
expect(localStorage.getItem('extraneous')).toBe(`{"customerKey":"123","sessionKey":"321"}`);
});
class StorageEvent extends Event {
readonly key: string;
readonly storageArea: Storage;
constructor(type: string, eventInitDict: StorageEventInit) {
super(type, eventInitDict);
this.key = eventInitDict.key!;
this.storageArea = eventInitDict.storageArea!;
}
}