diff --git a/deploy/saneUrl/util.js b/deploy/saneUrl/util.js index 249ec333d9ccc2d84cbba295425ebd55fb8c7b89..949025cdc76bbf6b8794222bc67e2995ae1da482 100644 --- a/deploy/saneUrl/util.js +++ b/deploy/saneUrl/util.js @@ -41,14 +41,25 @@ class ProxyStore { const NotExactlyPromiseAny = async arg => { const errs = [] - for (const pr of arg) { - try{ - return await pr - } catch (e) { - errs.push(e) + let resolvedFlag = false + return await new Promise((rs, rj) => { + let totalCounter = 0 + for (const pr of arg) { + totalCounter ++ + pr.then(val => { + if (!resolvedFlag) { + resolvedFlag = true + rs(val) + } + }).catch(e => { + errs.push(e) + totalCounter -- + if (totalCounter <= 0) { + rj(new NotFoundError(errs)) + } + }) } - } - throw new NotFoundError(errs) + }) } module.exports = { diff --git a/deploy/saneUrl/util.spec.js b/deploy/saneUrl/util.spec.js index 4df3074ddb228a48480ecd1ad8e6622964255878..f19d8cc92e23f79d42384389a6232c6e0a1d6443 100644 --- a/deploy/saneUrl/util.spec.js +++ b/deploy/saneUrl/util.spec.js @@ -188,7 +188,7 @@ describe('> saneUrl/util.js', () => { }) }) describe('> something resolves', () => { - it('> returns the first in list order', async () => { + it('> returns the first to resolve', async () => { try { const result = await NotExactlyPromiseAny([ @@ -196,7 +196,7 @@ describe('> saneUrl/util.js', () => { new Promise(rs => setTimeout(() => rs('hello world'), 100)), Promise.resolve('foo-bar') ]) - assert(result == 'hello world', 'expecting first in list to resolve successfully') + assert(result == 'foo-bar', 'expecting first to resolve') } catch (e) { assert(false, 'not expecting to throw') } diff --git a/src/atlasComponents/userAnnotations/routedAnnotation.service.spec.ts b/src/atlasComponents/userAnnotations/routedAnnotation.service.spec.ts index ffd4636c75a4b6132e7f0b16d2edf59205ca720b..7aecdd3d4a043e42699d2a8d2279c568bf48191c 100644 --- a/src/atlasComponents/userAnnotations/routedAnnotation.service.spec.ts +++ b/src/atlasComponents/userAnnotations/routedAnnotation.service.spec.ts @@ -1,5 +1,5 @@ import { fakeAsync, TestBed, tick } from "@angular/core/testing" -import { of, Subject } from "rxjs" +import { BehaviorSubject, of } from "rxjs" import { RouterService } from "src/routerModule/router.service" import { SaneUrlSvc } from "src/share/saneUrl/saneUrl.service" import { ModularUserAnnotationToolService } from "./tools/service" @@ -8,15 +8,11 @@ import { userAnnotationRouteKey } from "./constants" describe('> routedannotation.service.ts', () => { describe('> RoutedAnnotationService', () => { - const customRouteSub = new Subject() + const customRouteSub = new BehaviorSubject(null) const spyRService = { customRoute$: customRouteSub.asObservable() } - let spyRSvcCstmRoute: jasmine.Spy - const spySaneUrlSvc = { - getKeyVal: jasmine.createSpy('getKeyVal') - } const spyAnnSvc = { switchAnnotationMode: jasmine.createSpy('switchAnnotationMode'), parseAnnotationObject: jasmine.createSpy('parseAnnotationObject'), @@ -31,7 +27,13 @@ describe('> routedannotation.service.ts', () => { useValue: spyRService }, { provide: SaneUrlSvc, - useValue: spySaneUrlSvc + useFactory: () => { + return { + getKeyVal: jasmine.createSpy('getKeyVal').and.returnValue( + of({}) + ) + } + } }, { provide: ModularUserAnnotationToolService, useValue: spyAnnSvc @@ -40,8 +42,6 @@ describe('> routedannotation.service.ts', () => { }) }) afterEach(() => { - if (spyRSvcCstmRoute) spyRSvcCstmRoute.calls.reset() - spySaneUrlSvc.getKeyVal.calls.reset() spyAnnSvc.switchAnnotationMode.calls.reset() spyAnnSvc.parseAnnotationObject.calls.reset() spyAnnSvc.importAnnotation.calls.reset() @@ -68,6 +68,7 @@ describe('> routedannotation.service.ts', () => { }] beforeEach(() => { + const spySaneUrlSvc = TestBed.inject(SaneUrlSvc) as any spySaneUrlSvc.getKeyVal.and.returnValue( of(getKeyValReturn) ) @@ -75,30 +76,31 @@ describe('> routedannotation.service.ts', () => { }) it('> getKeyVal called after at least 160ms', fakeAsync(() => { - const svc = TestBed.inject(RoutedAnnotationService) customRouteSub.next({ [userAnnotationRouteKey]: mockVal }) - tick(160) + const svc = TestBed.inject(RoutedAnnotationService) + tick(200) + const spySaneUrlSvc = TestBed.inject(SaneUrlSvc) as any expect(spySaneUrlSvc.getKeyVal).toHaveBeenCalled() expect(spySaneUrlSvc.getKeyVal).toHaveBeenCalledWith(mockVal) })) it('> switchannotation mode is called with "on"', fakeAsync(() => { - const svc = TestBed.inject(RoutedAnnotationService) customRouteSub.next({ [userAnnotationRouteKey]: mockVal }) - tick(160) + const svc = TestBed.inject(RoutedAnnotationService) + tick(200) expect(spyAnnSvc.switchAnnotationMode).toHaveBeenCalledOnceWith('on') })) it('> parseAnnotationObject is called expected number of times', fakeAsync(() => { - const svc = TestBed.inject(RoutedAnnotationService) customRouteSub.next({ [userAnnotationRouteKey]: mockVal }) - tick(160) + const svc = TestBed.inject(RoutedAnnotationService) + tick(200) const userAnn = getKeyValReturn[userAnnotationRouteKey] expect(spyAnnSvc.parseAnnotationObject).toHaveBeenCalledTimes(userAnn.length) @@ -108,11 +110,11 @@ describe('> routedannotation.service.ts', () => { })) it('> importAnnotation is called expected number of times', fakeAsync(() => { - const svc = TestBed.inject(RoutedAnnotationService) customRouteSub.next({ [userAnnotationRouteKey]: mockVal }) - tick(160) + const svc = TestBed.inject(RoutedAnnotationService) + tick(200) expect(spyAnnSvc.importAnnotation).toHaveBeenCalledTimes(parseAnnObjReturn.length) for (const obj of parseAnnObjReturn) { expect(spyAnnSvc.importAnnotation).toHaveBeenCalledWith(obj) @@ -125,32 +127,35 @@ describe('> routedannotation.service.ts', () => { const mockVal = 'foo-bar' it('> getKeyVal should only be called once', fakeAsync(() => { - const svc = TestBed.inject(RoutedAnnotationService) customRouteSub.next({ [userAnnotationRouteKey]: mockVal }) + const svc = TestBed.inject(RoutedAnnotationService) tick(200) customRouteSub.next({ [userAnnotationRouteKey]: 'hello world' }) - tick(160) + tick(200) + const spySaneUrlSvc = TestBed.inject(SaneUrlSvc) as any expect(spySaneUrlSvc.getKeyVal).toHaveBeenCalledOnceWith(mockVal) })) }) describe('> routerSvc.customRoute$ does not emit valid key', () => { it('> does not call getKeyVal', fakeAsync(() => { - const svc = TestBed.inject(RoutedAnnotationService) customRouteSub.next({ 'hello-world': 'foo-bar' }) - tick(160) + const svc = TestBed.inject(RoutedAnnotationService) + tick(200) + const spySaneUrlSvc = TestBed.inject(SaneUrlSvc) as any expect(spySaneUrlSvc.getKeyVal).not.toHaveBeenCalled() })) }) describe('> getKeyVal returns invalid key', () => { it('> does not call switchAnnotationMode', fakeAsync(() => { + const spySaneUrlSvc = TestBed.inject(SaneUrlSvc) as any spySaneUrlSvc.getKeyVal.and.returnValue( of({ 'hello-world': [{ @@ -159,10 +164,11 @@ describe('> routedannotation.service.ts', () => { }] }) ) - const svc = TestBed.inject(RoutedAnnotationService) customRouteSub.next({ [userAnnotationRouteKey]: 'foo-bar' }) + const svc = TestBed.inject(RoutedAnnotationService) + tick(320) expect(spyAnnSvc.switchAnnotationMode).not.toHaveBeenCalled() })) diff --git a/src/atlasComponents/userAnnotations/routedAnnotation.service.ts b/src/atlasComponents/userAnnotations/routedAnnotation.service.ts index fac5afe94a0fcd91dc0408a99f73750a5e2104d9..11a28a8fe6548ede886ab3b0c0ca1f09125aa918 100644 --- a/src/atlasComponents/userAnnotations/routedAnnotation.service.ts +++ b/src/atlasComponents/userAnnotations/routedAnnotation.service.ts @@ -20,9 +20,7 @@ export class RoutedAnnotationService{ routerSvc.customRoute$.pipe( debounceTime(160), take(1), - map(obj => { - return obj[userAnnotationRouteKey] - }), + map(obj => obj[userAnnotationRouteKey]), switchMap( saneUrlKey => { return saneUrlKey