UNPKG

voluptasmollitia

Version:
264 lines (216 loc) 8.08 kB
/** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { expect, use } from 'chai'; import * as sinon from 'sinon'; import * as sinonChai from 'sinon-chai'; import { testAuth, testUser } from '../../../test/helpers/mock_auth'; import { PersistedBlob, PersistenceInternal, PersistenceType } from '../../core/persistence'; import { _getInstance } from '../../core/util/instantiator'; import { browserLocalPersistence, _POLLING_INTERVAL_MS } from './local_storage'; use(sinonChai); describe('platform_browser/persistence/local_storage', () => { const persistence: PersistenceInternal = _getInstance( browserLocalPersistence ); beforeEach(() => { localStorage.clear(); }); afterEach(() => sinon.restore()); it('should work with persistence type', async () => { const key = 'my-super-special-persistence-type'; const value = PersistenceType.LOCAL; expect(await persistence._get(key)).to.be.null; await persistence._set(key, value); expect(await persistence._get(key)).to.be.eq(value); expect(await persistence._get('other-key')).to.be.null; await persistence._remove(key); expect(await persistence._get(key)).to.be.null; }); it('should return persistedblob from user', async () => { const key = 'my-super-special-user'; const auth = await testAuth(); const value = testUser(auth, 'some-uid'); expect(await persistence._get(key)).to.be.null; await persistence._set(key, value.toJSON()); const out = await persistence._get<PersistedBlob>(key); expect(out!['uid']).to.eql(value.uid); await persistence._remove(key); expect(await persistence._get(key)).to.be.null; }); describe('#isAvailable', () => { it('should emit false if localStorage setItem throws', async () => { sinon.stub(localStorage, 'setItem').throws(new Error('nope')); expect(await persistence._isAvailable()).to.be.false; }); it('should emit false if localStorage removeItem throws', async () => { sinon.stub(localStorage, 'removeItem').throws(new Error('nope')); expect(await persistence._isAvailable()).to.be.false; }); it('should emit true if everything works properly', async () => { expect(await persistence._isAvailable()).to.be.true; }); }); describe('#addEventListener', () => { const key = 'my-key'; const newValue = 'new-value'; let callback: sinon.SinonSpy; beforeEach(() => { callback = sinon.spy(); }); context('with events', () => { beforeEach(() => { persistence._addListener(key, callback); }); afterEach(() => { persistence._removeListener(key, callback); }); context('with multiple listeners', () => { let otherCallback: sinon.SinonSpy; beforeEach(() => { otherCallback = sinon.spy(); persistence._addListener(key, otherCallback); localStorage.setItem(key, JSON.stringify(newValue)); }); afterEach(() => { persistence._removeListener(key, otherCallback); }); it('should trigger both listeners if multiple listeners are registered', () => { window.dispatchEvent( new StorageEvent('storage', { key, oldValue: null, newValue: JSON.stringify(newValue) }) ); expect(callback).to.have.been.calledWith(newValue); expect(otherCallback).to.have.been.calledWith(newValue); }); }); context('with a change in the underlying storage', () => { beforeEach(() => { localStorage.setItem(key, JSON.stringify(newValue)); }); it('should trigger on storage event for the same key', () => { window.dispatchEvent( new StorageEvent('storage', { key, oldValue: null, newValue: JSON.stringify(newValue) }) ); expect(callback).to.have.been.calledWith(newValue); }); it('should not trigger after unsubscribe', () => { persistence._removeListener(key, callback); window.dispatchEvent( new StorageEvent('storage', { key, oldValue: null, newValue: JSON.stringify(newValue) }) ); expect(callback).not.to.have.been.called; }); it('should trigger even if the event had no key', () => { window.dispatchEvent(new StorageEvent('storage', {})); expect(callback).to.have.been.calledWith(newValue); }); }); context('without a change in the underlying storage', () => { it('should not trigger', () => { window.dispatchEvent( new StorageEvent('storage', { key, oldValue: null, newValue: JSON.stringify(newValue) }) ); expect(callback).not.to.have.been.called; }); it('should not trigger on storage event for a different key', () => { localStorage.setItem('other-key', JSON.stringify(newValue)); window.dispatchEvent( new StorageEvent('storage', { key: 'other-key', oldValue: null, newValue: JSON.stringify(newValue) }) ); expect(callback).not.to.have.been.called; }); it('should not trigger if the listener was added after the storage was updated', () => { const otherCallback = sinon.spy(); persistence._addListener(key, otherCallback); window.dispatchEvent( new StorageEvent('storage', { key, oldValue: null, newValue: JSON.stringify(newValue) }) ); expect(otherCallback).not.to.have.been.called; persistence._removeListener(key, otherCallback); }); }); }); context('with polling (mobile browsers)', () => { let clock: sinon.SinonFakeTimers; beforeEach(() => { clock = sinon.useFakeTimers(); (persistence as any)['fallbackToPolling'] = true; persistence._addListener(key, callback); }); afterEach(() => { persistence._removeListener(key, callback); clock.restore(); }); it('should catch persistence changes', async () => { localStorage.setItem(key, JSON.stringify(newValue)); clock.tick(_POLLING_INTERVAL_MS + 1); expect(callback).to.have.been.calledWith(newValue); }); it('should not trigger twice if event still occurs after poll', async () => { localStorage.setItem(key, JSON.stringify(newValue)); clock.tick(_POLLING_INTERVAL_MS + 1); window.dispatchEvent( new StorageEvent('storage', { key, oldValue: null, newValue: JSON.stringify(newValue) }) ); expect(callback).to.have.been.calledOnceWith(newValue); }); it('should not trigger twice if poll occurs after event', async () => { localStorage.setItem(key, JSON.stringify(newValue)); window.dispatchEvent( new StorageEvent('storage', { key, oldValue: null, newValue: JSON.stringify(newValue) }) ); clock.tick(_POLLING_INTERVAL_MS + 1); expect(callback).to.have.been.calledOnceWith(newValue); }); }); }); });