@furystack/shades
Version:
Google Authentication Provider for FuryStack
107 lines • 6.07 kB
JavaScript
import { Injector } from '@furystack/inject';
import { deserializeQueryString, serializeToQueryString, serializeValue } from '@furystack/rest';
import { usingAsync } from '@furystack/utils';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { LocationService, useCustomSearchStateSerializer } from './location-service.js';
describe('LocationService', () => {
beforeEach(() => {
document.body.innerHTML = '<div id="root"></div>';
});
afterEach(() => {
document.body.innerHTML = '';
});
it('Shuld be constructed', async () => {
await usingAsync(new Injector(), async (i) => {
const s = i.getInstance(LocationService);
expect(s).toBeInstanceOf(LocationService);
});
});
it('Shuld update state on events', async () => {
await usingAsync(new Injector(), async (i) => {
const onLocaionChanged = vi.fn();
const s = i.getInstance(LocationService);
s.onLocationPathChanged.subscribe(onLocaionChanged);
expect(onLocaionChanged).toBeCalledTimes(0);
history.pushState(null, '', '/loc1');
expect(onLocaionChanged).toBeCalledTimes(1);
history.replaceState(null, '', '/loc2');
expect(onLocaionChanged).toBeCalledTimes(2);
// TODO: Figure out testing hashchange and popstate subscriptions
// window.dispatchEvent(new HashChangeEvent('hashchange', { newURL: '/loc3' }))
// expect(onLocaionChanged).toBeCalledTimes(3)
// window.dispatchEvent(new PopStateEvent('popstate', {}))
// expect(onLocaionChanged).toBeCalledTimes(4)
});
});
describe('useSearchParam', () => {
it('Should create observables lazily', async () => {
await usingAsync(new Injector(), async (i) => {
const service = i.getInstance(LocationService);
const observables = service.searchParamObservables;
const testSearchParam = service.useSearchParam('test', null);
expect(observables.size).toBe(1);
const testSearchParam2 = service.useSearchParam('test', null);
expect(observables.size).toBe(1);
expect(testSearchParam).toBe(testSearchParam2);
const testSearchParam3 = service.useSearchParam('test2', undefined);
expect(observables.size).toBe(2);
expect(testSearchParam3).not.toBe(testSearchParam2);
});
});
it('Should return the default value, if not present in the query string', async () => {
await usingAsync(new Injector(), async (i) => {
const service = i.getInstance(LocationService);
const testSearchParam = service.useSearchParam('test', { value: 'foo' });
expect(testSearchParam.getValue()).toEqual({ value: 'foo' });
});
});
it('Should return the value from the query string', async () => {
await usingAsync(new Injector(), async (i) => {
const service = i.getInstance(LocationService);
history.pushState(null, '', `/loc1?test=${serializeValue(1)}`);
const testSearchParam = service.useSearchParam('test', 123);
expect(testSearchParam.getValue()).toBe(1);
});
});
it('should update the observable value on push / replace states', async () => {
await usingAsync(new Injector(), async (i) => {
const service = i.getInstance(LocationService);
history.pushState(null, '', `/loc1?test=${serializeValue(1)}`);
const testSearchParam = service.useSearchParam('test', 234);
expect(testSearchParam.getValue()).toBe(1);
history.replaceState(null, '', `/loc1?test=${serializeValue('2')}`);
expect(testSearchParam.getValue()).toBe('2');
});
});
it('Should update the URL based on search value change', async () => {
await usingAsync(new Injector(), async (i) => {
const service = i.getInstance(LocationService);
history.pushState(null, '', `/loc1?test=${serializeValue('2')}`);
const testSearchParam = service.useSearchParam('test', '');
testSearchParam.setValue('2');
expect(location.search).toBe('?test=IjIi');
});
});
it('Should throw an error when trying to use a custom serializer after LocationService has been instantiated', async () => {
await usingAsync(new Injector(), async (i) => {
const customSerializer = vi.fn((value) => serializeToQueryString(value));
const customDeserializer = vi.fn((value) => deserializeQueryString(value));
i.getInstance(LocationService);
expect(() => useCustomSearchStateSerializer(i, customSerializer, customDeserializer)).toThrowError('useCustomSearchStateSerializer must be called before the LocationService is instantiated');
});
});
it('Should use custom serializer and deserializer', async () => {
await usingAsync(new Injector(), async (i) => {
const customSerializer = vi.fn((value) => serializeToQueryString(value));
const customDeserializer = vi.fn((value) => deserializeQueryString(value));
useCustomSearchStateSerializer(i, customSerializer, customDeserializer);
const locationService = i.getInstance(LocationService);
const testSearchParam = locationService.useSearchParam('test', { value: 'foo' });
testSearchParam.setValue({ value: 'bar' });
expect(customSerializer).toBeCalledWith({ test: { value: 'bar' } });
expect(customDeserializer).toBeCalledWith('?test=eyJ2YWx1ZSI6ImJhciJ9');
});
});
});
});
//# sourceMappingURL=location-service.spec.js.map