UNPKG

@furystack/shades

Version:

Google Authentication Provider for FuryStack

133 lines (111 loc) 5.53 kB
import { TextDecoder, TextEncoder } from 'util' global.TextEncoder = TextEncoder global.TextDecoder = TextDecoder as any 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: any) => serializeToQueryString(value)) const customDeserializer = vi.fn((value: string) => 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: any) => serializeToQueryString(value)) const customDeserializer = vi.fn((value: string) => 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') }) }) }) })