UNPKG

ohayolibs

Version:

Ohayo is a set of essential modules for ohayojp.

359 lines (340 loc) 11.7 kB
// tslint:disable:no-string-literal import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { Type } from '@angular/core'; import { fakeAsync, TestBed, tick } from '@angular/core/testing'; import { OhayoThemeModule, _HttpClient } from '@ohayo/theme'; import { OhayoCacheConfig, OHAYO_CONFIG } from '@ohayo/util'; import { NzSafeAny } from 'ng-zorro-antd/core/types'; import { Observable, of } from 'rxjs'; import { filter } from 'rxjs/operators'; import { OhayoCacheModule } from './cache.module'; import { CacheService } from './cache.service'; import { ICache } from './interface'; describe('cache: service', () => { let srv: CacheService; const KEY = 'a'; function getHTC(): HttpTestingController { return TestBed.inject(HttpTestingController as Type<HttpTestingController>); } beforeEach(() => { let data: any = {}; spyOn(localStorage, 'getItem').and.callFake((key: string): string => { return data[key] || null; }); spyOn(localStorage, 'removeItem').and.callFake((key: string): void => { delete data[key]; }); spyOn(localStorage, 'setItem').and.callFake((key: string, value: string): string => { return (data[key] = value as string); }); spyOn(localStorage, 'clear').and.callFake(() => { data = {}; }); }); function genModule(options?: OhayoCacheConfig): void { const providers: any[] = []; if (options) { providers.push({ provide: OHAYO_CONFIG, useValue: { cache: options } }); } TestBed.configureTestingModule({ imports: [HttpClientTestingModule, OhayoThemeModule.forRoot(), OhayoCacheModule], providers, }); srv = TestBed.inject<CacheService>(CacheService); } it('should be specify a global config', () => { genModule({ expire: 100, type: 'm' }); const saveSpy = spyOn(srv as any, 'save'); srv.set(KEY, 'a'); const args = saveSpy.calls.first().args; expect(args[0]).toBe('m'); }); describe('[property]', () => { beforeEach(() => genModule()); afterEach(() => srv.ngOnDestroy()); describe('#set', () => { it('should be set number', () => { srv.set(KEY, 1); expect(srv.getNone(KEY)).toBe(1); }); it('should be set array', () => { srv.set(KEY, [1, 2]); const ret = srv.getNone(KEY) as number[]; expect(ret.length).toBe(2); expect(ret[0]).toBe(1); expect(ret[1]).toBe(2); }); it('should be set Observable', (done: () => void) => { srv.set(KEY, of(10)).subscribe(res => { expect(res).toBe(10); expect(srv.getNone(KEY)).toBe(10); done(); }); }); it('should be set string vis memory', () => { srv.set(KEY, 'a', { type: 'm' }); expect(localStorage.setItem).not.toHaveBeenCalled(); }); it('should be set string vis storage', () => { srv.set(KEY, 'a', { type: 's' }); expect(localStorage.setItem).toHaveBeenCalled(); expect(srv.has(KEY)).toBe(true); const meta = JSON.parse(localStorage.getItem('__cache_meta')!) as ICache; expect(meta).not.toBeNaN(); expect(meta.v.indexOf(KEY)).not.toBe(-1); }); it('should be set string and expires vis memory', () => { srv.set(KEY, 'a', { type: 'm', expire: 60 * 60 }); expect(srv.getNone(KEY)).toBe('a'); }); it('should be set string and expires vis storage', () => { srv.set(KEY, 'a', { type: 's', expire: 10 }); expect(localStorage.setItem).toHaveBeenCalled(); const org = JSON.parse(localStorage.getItem(KEY)!) as ICache; expect(org.e).toBeGreaterThan(1000); }); it('should be overwirte key', () => { srv.set(KEY, 1); expect(srv.getNone(KEY)).toBe(1); srv.set(KEY, 2); expect(srv.getNone(KEY)).toBe(2); }); }); describe('#get', () => { it('should be return number', () => { srv.set(KEY, 1); expect(srv.getNone(KEY)).toBe(1); }); it('should be return array', () => { srv.set(KEY, [1, 2]); const ret = srv.getNone(KEY) as number[]; expect(ret.length).toBe(2); expect(ret[0]).toBe(1); expect(ret[1]).toBe(2); }); it('should be return null if invalid KEY', () => { expect(srv.getNone('aaa')).toBeNull(); }); it('should be return null if expired', () => { localStorage.setItem( KEY, JSON.stringify({ e: 1000, v: 1, } as ICache), ); expect(srv.getNone(KEY)).toBeNull(); }); it('should be return number via promise mode', (done: () => void) => { const k = '/data/1'; srv.get(k).subscribe(res => { expect(res).toBe('ok!'); expect(srv.getNone(k)).toBe('ok!'); done(); }); getHTC().expectOne(k).flush('ok!'); }); it('should be specify sotre type via promise mode', (done: () => void) => { const k = '/data/1'; const setSpy = spyOn(srv, 'set'); srv.get(k, { mode: 'promise', type: 'm' }).subscribe(() => { const data = setSpy.calls.mostRecent().args[2]; expect(data.type).toBe('m'); done(); }); getHTC().expectOne(k).flush('ok!'); }); it('reproduce-issues-40', () => { const url = `/test`; const firstGet = srv.get(url); expect(firstGet instanceof Observable).toBe(true); firstGet.subscribe(); getHTC().expectOne(url).flush('ok!'); const secondGet = srv.get(url); expect(secondGet instanceof Observable).toBe(true); }); }); describe('#tryGet', () => { it('should be return number if not exists KEY', () => { const ret = srv.tryGet(KEY, 1); expect(ret).toBe(1); }); it('should be return number via Observable if not exists KEY', (done: () => void) => { srv.tryGet(KEY, of(10)).subscribe(ret => { expect(ret).toBe(10); done(); }); }); it('should be return Observable when valid key', (done: () => void) => { srv.set(KEY, 10); srv.tryGet(KEY, of(10)).subscribe(ret => { expect(ret).toBe(10); done(); }); }); it('should be return value via memory', (done: () => void) => { srv.tryGet(KEY, of(10), { type: 'm' }).subscribe((ret: NzSafeAny) => { expect(ret).toBe(10); done(); }); }); it('should be return value via http request', fakeAsync(() => { const http = TestBed.inject(_HttpClient); const get$ = srv.tryGet(KEY, http.get('/')); expect(http.loading).toBeFalsy(); get$.subscribe(); tick(); expect(http.loading).toBeTruthy(); })); }); describe('#has', () => { it('shoule be return true if key exists', () => { srv.set(KEY, 10); expect(srv.has(KEY)).toBe(true); }); it('shoule be return true if key not exists', () => { expect(srv.has(KEY)).toBe(false); }); }); describe('#remove', () => { it('shoule be return null because has removed', () => { srv.set(KEY, 10); expect(srv.getNone(KEY)).toBe(10); srv.remove(KEY); expect(srv.getNone(KEY)).toBeNull(); }); it('shoule be return null because has removed in memory', () => { srv.set(KEY, 10, { type: 'm' }); expect(srv.getNone(KEY)).toBe(10); srv.remove(KEY); expect(srv.getNone(KEY)).toBeNull(); }); it('should be remove invalid key', () => { const key = 'test'; expect(srv.getNone(key)).toBeNull(); srv.remove(key); expect(srv.getNone(key)).toBeNull(); }); }); describe('#clear', () => { it('shoule be return null', () => { srv.set(KEY, 10, { type: 'm' }); srv.set(KEY + '1', 100); expect(srv.getNone(KEY)).toBe(10); expect(srv.getNone(KEY + '1')).toBe(100); srv.clear(); expect(srv.getNone(KEY)).toBeNull(); expect(srv.getNone(KEY + '1')).toBeNull(); }); it('should be notify a remove event', (done: () => void) => { srv .notify(KEY) .pipe(filter(w => w !== null && w.type === 'remove')) .subscribe(res => { expect(res.type).toBe('remove'); done(); }); srv.freq = 10; srv.set(KEY, 1, { expire: 1 }); srv.clear(); }); }); describe('#deepGet', () => { const tree = { responsne: { list: [], total: 10, }, status: 'ok', }; it('should be get [status]', () => { expect(srv['deepGet'](tree, ['status'])).toBe(tree.status); }); it('should be get [responsne.totle]', () => { expect(srv['deepGet'](tree, ['responsne', 'total'])).toBe(tree.responsne.total); }); it('should be return default value when not exist deep key', () => { const def = 'aa'; const res = srv['deepGet'](tree, ['responsne', 'totala'], def); expect(res).toBe(def); }); it('should be return default value when not exist key', () => { const def = 'aa'; expect(srv['deepGet'](tree, ['status11'], def)).toBe(def); }); it('should be return default value when source object is null', () => { const def = 'aa'; expect(srv['deepGet'](null, ['status11'], def)).toBe(def); }); }); describe('#notify', () => { it('should notify set', (done: () => void) => { srv .notify(KEY) .pipe(filter(w => w !== null)) .subscribe(res => { expect(res.type).toBe('set'); expect(res.value).toBe(1); done(); }); srv.notify(KEY).subscribe(); srv.set(KEY, 1); }); it('should notify remove', (done: () => void) => { srv .notify(KEY) .pipe(filter(w => w !== null)) .subscribe(res => { expect(res.type).toBe('remove'); done(); }); srv.remove(KEY); }); it('should notify expired', (done: () => void) => { srv .notify(KEY) .pipe(filter(w => w !== null && w.type === 'expire')) .subscribe(res => { expect(res.type).toBe('expire'); done(); }); srv.freq = 10; srv.set(KEY, 1, { expire: 1 }); }); it('should be cancel notify', () => { expect(srv.hasNotify(KEY)).toBe(false); srv.notify(KEY).subscribe(); expect(srv.hasNotify(KEY)).toBe(true); srv.cancelNotify(KEY); expect(srv.hasNotify(KEY)).toBe(false); }); it('shoulb be call cancel notify when is invalid key', () => { expect(srv.hasNotify(KEY)).toBe(false); srv.cancelNotify(KEY); expect(srv.hasNotify(KEY)).toBe(false); }); it('should be clear notify', () => { expect(srv.hasNotify(KEY)).toBe(false); srv.notify(KEY).subscribe(); expect(srv.hasNotify(KEY)).toBe(true); srv.clearNotify(); expect(srv.hasNotify(KEY)).toBe(false); }); }); }); describe('[meta]', () => { const meta_key = '__cache_meta'; beforeEach(() => { localStorage.setItem( meta_key, JSON.stringify({ v: [KEY], }), ); }); beforeEach(() => genModule()); it('should be loaded history keys', () => { expect(srv.getMeta().has(KEY)).toBe(true); }); }); });