/* * Copyright (C) 2018, 2019 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ import {TestBed} from '@angular/core/testing'; import {Client} from '@openstapps/api/lib/client'; import {SCDish, SCMessage, SCSaveableThing, SCSearchQuery, SCSearchResponse, SCSearchValueFilter, SCThing, SCThingOriginType, SCThings, SCThingType} from '@openstapps/core'; import {sampleThingsMap} from '../../_helpers/data/sampleThings'; import {StorageProvider} from '../storage/storage.provider'; import {DataModule} from './data.module'; import {DataProvider, DataScope} from './data.provider'; import {StAppsWebHttpClient} from './stapps-web-http-client.provider'; describe('DataProvider', () => { let dataProvider: DataProvider; let storageProvider: StorageProvider; const sampleThing: SCMessage = sampleThingsMap.message[0] as SCMessage; const sampleResponse: SCSearchResponse = { data: sampleThingsMap.dish as SCDish[], facets: [ { buckets: [], field: 'foo', }, ], pagination: { count: 0, offset: 0, total: 0, }, stats: { time: 123, }, }; const sampleFilter: SCSearchValueFilter = { arguments: { field: 'type', value: 'dish', }, type: 'value', }; const sampleQuery: SCSearchQuery = { filter: sampleFilter, }; const sampleSavable: SCSaveableThing = { data: sampleThing, name: sampleThing.name, origin: { created: new Date().toISOString(), type: SCThingOriginType.User, }, type: SCThingType.Message, uid: sampleThing.uid, }; const otherSampleThing: SCMessage = {...sampleThing, uid: 'message-456', name: 'bar'}; beforeEach(async () => { TestBed.configureTestingModule({ imports: [DataModule], providers: [ DataProvider, StAppsWebHttpClient, ], }); storageProvider = TestBed.get(StorageProvider); dataProvider = TestBed.get(DataProvider); await storageProvider.deleteAll(); }); it('should generate data key', async () => { dataProvider.storagePrefix = 'foo.data'; expect(dataProvider.getDataKey('123')).toBe('foo.data.123'); }); it('should provide backend data items using search query', async () => { spyOn(Client.prototype, 'search').and.callFake(() => { return { then: (callback: any) => { return callback(sampleResponse); }, }; }); const response = await dataProvider.search(sampleQuery); expect(response).toEqual(sampleResponse); }); it('should put an data item into the local database (storage)', async () => { let providedThing: SCSaveableThing; spyOn(storageProvider, 'put').and.callFake((_id: any, thing: any) => { providedThing = thing; providedThing.origin.created = sampleSavable.origin.created; }); expect(storageProvider.put).not.toHaveBeenCalled(); expect(providedThing!).not.toBeDefined(); await dataProvider.put(sampleThing); expect(providedThing!).toBeDefined(); expect(providedThing!).toEqual(sampleSavable); }); it('should correctly set and get single data item from the local database (storage)', async () => { await dataProvider.put(sampleThing); spyOn(storageProvider, 'get').and.callThrough(); expect(storageProvider.get).not.toHaveBeenCalled(); const providedThing = await dataProvider.get(sampleThing.uid, DataScope.Local); providedThing.origin.created = sampleSavable.origin.created; expect(storageProvider.get).toHaveBeenCalledWith(dataProvider.getDataKey(sampleThing.uid)); expect(providedThing).toEqual(sampleSavable); }); it('should provide all data items from the local database (storage)', async () => { await dataProvider.put(sampleThing); await dataProvider.put(otherSampleThing); const result = await dataProvider.getAll(); expect(Array.from(result.keys()).sort()).toEqual([ dataProvider.getDataKey(sampleThing.uid), dataProvider.getDataKey(otherSampleThing.uid), ]); expect(result.get(dataProvider.getDataKey(sampleThing.uid))!.data).toEqual(sampleThing); expect(result.get(dataProvider.getDataKey(otherSampleThing.uid))!.data).toEqual(otherSampleThing); }); it('should provide single data from the backend', async () => { spyOn(Client.prototype, 'getThing').and.callFake(() => { return { then: (callback: any) => { return callback(sampleThing); }, }; }); expect(Client.prototype.getThing).not.toHaveBeenCalled(); const providedThing = await dataProvider.get(sampleThing.uid, DataScope.Remote); expect(Client.prototype.getThing).toHaveBeenCalledWith(sampleThing.uid); expect(providedThing).toBe(sampleThing); }); it('should get an item from both local and remote database', async () => { spyOn(Client.prototype, 'getThing').and.callFake(() => { return { then: (callback: any) => { return callback(sampleThing); }, }; }); spyOn(storageProvider, 'get').and.callFake(() => { return { then: (callback: any) => { return callback(sampleSavable); }, }; }); const result = await dataProvider.get(sampleThing.uid); expect(result.get(DataScope.Local)).toEqual(sampleSavable); expect(result.get(DataScope.Remote)).toEqual(sampleThing); }); it('should properly delete a data item from the local database (storage)', async () => { spyOn(storageProvider, 'delete').and.callThrough(); await dataProvider.put(sampleThing); expect(await storageProvider.length()).toBe(1); await dataProvider.delete(sampleThing.uid); expect(storageProvider.delete).toHaveBeenCalledWith(dataProvider.getDataKey(sampleThing.uid)); expect(await storageProvider.length()).toBe(0); }); it('should properly delete all the data items from the local database (storage)', async () => { spyOn(storageProvider, 'delete').and.callThrough(); await dataProvider.put(sampleThing); await dataProvider.put(otherSampleThing); await storageProvider.put('some-uid', {some: 'thing'}); expect(await storageProvider.length()).toBe(3); await dataProvider.deleteAll(); expect(storageProvider.delete).toHaveBeenCalledWith( dataProvider.getDataKey(sampleThing.uid), dataProvider.getDataKey(otherSampleThing.uid), ); const result = await storageProvider.getAll(); expect(Array.from(result.keys())).toEqual(['some-uid']); }); it('should properly check if a data item has already been saved', async () => { expect(await dataProvider.isSaved(sampleThing.uid)).toBeFalsy(); await dataProvider.put(sampleThing); expect(await dataProvider.isSaved(sampleThing.uid)).toBeTruthy(); }); });