mapillary-js
Version:
WebGL JavaScript library for displaying street level imagery from mapillary.com
1,116 lines (914 loc) • 41.8 kB
text/typescript
import {of as observableOf, throwError as observableThrowError, empty as observableEmpty, Observable, Subject} from "rxjs";
import {first} from "rxjs/operators";
import {NodeHelper} from "../helper/NodeHelper.spec";
import {StateServiceMockCreator} from "../helper/StateServiceMockCreator.spec";
import {
APIv3,
ICoreNode,
IKey,
IFullNode,
} from "../../src/API";
import {EdgeDirection} from "../../src/graph/edge/EdgeDirection";
import {AbortMapillaryError} from "../../src/Error";
import {
Graph,
GraphService,
ImageLoadingService,
Node,
} from "../../src/Graph";
import {
ICurrentState,
IFrame,
StateService,
State,
} from "../../src/State";
import {
CacheService,
LoadingService,
Navigator,
} from "../../src/Viewer";
let createState: () => ICurrentState = (): ICurrentState => {
return {
alpha: 0,
camera: null,
currentCamera: null,
currentIndex: 0,
currentNode: null,
currentTransform: null,
lastNode: null,
motionless: false,
nodesAhead: 0,
previousNode: null,
previousTransform: null,
reference: null,
state: State.Traversing,
trajectory: null,
zoom: 0,
};
};
describe("Navigator.ctor", () => {
it("should be defined without optional params", () => {
let navigator: Navigator = new Navigator("clientId", {});
expect(navigator).toBeDefined();
});
it("should be defined with optional params", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
expect(navigator).toBeDefined();
});
});
describe("Navigator.moveToKey$", () => {
it("should start loading", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
let loadingSpy: jasmine.Spy = spyOn(loadingService, "startLoading").and.stub();
spyOn(graphService, "cacheNode$").and.returnValue(observableEmpty());
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
let key: string = "key";
navigator.moveToKey$(key);
expect(loadingSpy.calls.count()).toBe(1);
expect(loadingSpy.calls.first().args[0]).toBe("navigator");
});
it("should stop loading when succeeding", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
spyOn(loadingService, "startLoading").and.stub();
let stopLoadingSpy: jasmine.Spy = spyOn(loadingService, "stopLoading").and.stub();
let key: string = "key";
let sequenceKey: string = "sequenceKey";
spyOn(graphService, "cacheNode$").and.returnValue(observableOf<Node>(
new Node({
cl: { lat: 0, lon: 0 },
key: key,
l: { lat: 0, lon: 0 },
sequence_key: sequenceKey,
})));
let stateSpy: jasmine.Spy = spyOn(stateService, "setNodes").and.stub();
let navigator: Navigator =
new Navigator(clientId, {}, undefined, apiV3, graphService, imageLoadingService, loadingService, stateService);
navigator.moveToKey$(key).subscribe(() => { /*noop*/ });
expect(stateSpy.calls.count()).toBe(1);
expect(stopLoadingSpy.calls.count()).toBe(1);
expect(stopLoadingSpy.calls.first().args[0]).toBe("navigator");
});
it("should stop loading when error is thrown", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
let stopLoadingSpy: jasmine.Spy = spyOn(loadingService, "stopLoading").and.stub();
spyOn(graphService, "cacheNode$").and.returnValue(observableThrowError(new Error()));
let stateSpy: jasmine.Spy = spyOn(stateService, "setNodes").and.stub();
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
let key: string = "key";
navigator.moveToKey$(key)
.subscribe(
(n: Node): void => { return; },
(e: Error): void => { return; });
expect(stateSpy.calls.count()).toBe(0);
expect(stopLoadingSpy.calls.count()).toBe(1);
expect(stopLoadingSpy.calls.first().args[0]).toBe("navigator");
});
it("should abort previous request when new request is done", (done: () => void) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
spyOn(graphService, "cacheNode$").and.returnValue(new Subject<Node>());
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.moveToKey$("key1")
.subscribe(
undefined,
(e: Error): void => {
expect(e).toBeDefined();
expect(e instanceof AbortMapillaryError);
done();
});
navigator.moveToKey$("key2");
});
it("should succeed when node is cached", (done: () => void) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
let key: string = "key";
let sequenceKey: string = "sequenceKey";
let node: Node = new Node({
cl: { lat: 0, lon: 0 },
key: key,
l: { lat: 0, lon: 0 },
sequence_key: sequenceKey,
});
spyOn(graphService, "cacheNode$").and.returnValue(observableOf<Node>(node));
spyOn(stateService, "setNodes").and.stub();
let navigator: Navigator =
new Navigator(clientId, {}, undefined, apiV3, graphService, imageLoadingService, loadingService, stateService);
navigator.moveToKey$(key)
.subscribe(
(n: Node) => {
expect(n.key).toBe(node.key);
done();
});
});
it("should succeed when node is not cached prior to call", (done: () => void) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
let key: string = "key";
let sequenceKey: string = "sequenceKey";
let cacheNodeSubject$: Subject<Node> = new Subject<Node>();
let node: Node = new Node({
cl: { lat: 0, lon: 0 },
key: key,
l: { lat: 0, lon: 0 },
sequence_key: sequenceKey,
});
spyOn(graphService, "cacheNode$").and.returnValue(cacheNodeSubject$);
spyOn(stateService, "setNodes").and.stub();
let navigator: Navigator =
new Navigator(clientId, {}, undefined, apiV3, graphService, imageLoadingService, loadingService, stateService);
navigator.moveToKey$(key)
.subscribe(
(n: Node) => {
expect(n.key).toBe(node.key);
done();
});
cacheNodeSubject$.next(node);
});
describe("Navigator.moveToKey$", () => {
it("should complete and not abort when another call is made in callback", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
let key: string = "key1";
let sequenceKey: string = "sequenceKey";
let cacheNodeSubject$: Subject<Node> = new Subject<Node>();
let node: Node = new Node({
cl: { lat: 0, lon: 0 },
key: key,
l: { lat: 0, lon: 0 },
sequence_key: sequenceKey,
});
spyOn(graphService, "cacheNode$").and.returnValue(cacheNodeSubject$);
spyOn(stateService, "setNodes").and.stub();
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
let successCount: number = 0;
let errorCount: number = 0;
let completeCount: number = 0;
navigator.moveToKey$(key)
.subscribe(
(): void => {
navigator.moveToKey$("key2").subscribe();
successCount++;
},
(): void => {
errorCount++;
},
(): void => {
completeCount++;
});
cacheNodeSubject$.next(node);
expect(successCount).toBe(1);
expect(errorCount).toBe(0);
expect(completeCount).toBe(1);
});
});
});
describe("Navigator.movedToKey$", () => {
it("should emit when move succeeds", (done: Function) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
let key: string = "key";
let sequenceKey: string = "sequenceKey";
spyOn(graphService, "cacheNode$").and.returnValue(observableOf<Node>(
new Node({
cl: { lat: 0, lon: 0 },
key: key,
l: { lat: 0, lon: 0 },
sequence_key: sequenceKey,
})));
spyOn(stateService, "setNodes").and.stub();
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.movedToKey$.pipe(
first(
(k: string): boolean => {
return k != null;
}))
.subscribe(
(k: string): void => {
expect(k).toBe(key);
done();
});
navigator.moveToKey$(key).subscribe(() => { /*noop*/ });
});
});
describe("Navigator.moveCloseTo$", () => {
it("should start loading", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
let startLoadingSpy: jasmine.Spy = spyOn(loadingService, "startLoading").and.stub();
spyOn(apiV3, "imageCloseTo$").and.returnValue(observableEmpty());
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
let lat: number = 0;
let lon: number = 0;
navigator.moveCloseTo$(lat, lon).subscribe(() => { /*noop*/ });
expect(startLoadingSpy.calls.count()).toBe(1);
expect(startLoadingSpy.calls.first().args[0]).toBe("navigator");
});
it("should call cacheNode$ when succeding", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
let key: string = "key";
spyOn(apiV3, "imageCloseTo$").and.returnValue(observableOf<IFullNode>(<IFullNode>{ key: key }));
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
let cacheSpy: jasmine.Spy = spyOn(graphService, "cacheNode$");
cacheSpy.and.returnValue(observableEmpty());
let lat: number = 0;
let lon: number = 0;
navigator.moveCloseTo$(lat, lon).subscribe(() => { /*noop*/ });
expect(cacheSpy.calls.count()).toBe(1);
expect(cacheSpy.calls.first().args[0]).toBe(key);
});
it("should stop loading and throw when failing", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
let stopLoadingSpy: jasmine.Spy = spyOn(loadingService, "stopLoading").and.stub();
spyOn(apiV3, "imageCloseTo$").and.returnValue(observableOf<IFullNode>(null));
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
let moveSpy: jasmine.Spy = spyOn(navigator, "moveToKey$");
moveSpy.and.returnValue(observableEmpty());
let lat: number = 0;
let lon: number = 0;
navigator.moveCloseTo$(lat, lon)
.subscribe(
(n: Node): void => { return; },
(e: Error): void => { return; });
expect(stopLoadingSpy.calls.count()).toBe(1);
expect(stopLoadingSpy.calls.first().args[0]).toBe("navigator");
expect(moveSpy.calls.count()).toBe(0);
});
it("should abort previous request when new request is done", (done: () => void) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
spyOn(apiV3, "imageCloseTo$").and.returnValue(new Subject<IFullNode>());
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
let lat: number = 0;
let lon: number = 0;
navigator.moveCloseTo$(lat, lon)
.subscribe(
undefined,
(e: Error): void => {
expect(e).toBeDefined();
expect(e instanceof AbortMapillaryError);
done();
});
navigator.moveCloseTo$(lat, lon);
});
});
class TestStateService extends StateService {
private _overridingCurrentState$: Subject<IFrame>;
constructor(currentState$: Subject<IFrame>) {
super();
this._overridingCurrentState$ = currentState$;
}
public get currentState$(): Subject<IFrame> {
return this._overridingCurrentState$;
}
}
describe("Navigator.setFilter$", () => {
let helper: NodeHelper;
beforeEach(() => {
helper = new NodeHelper();
});
it("should set filter when no key requested", (done: Function) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graph: Graph = new Graph(apiV3);
let graphService: GraphService = new GraphService(graph, imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
let clearNodesSpy: jasmine.Spy = spyOn(stateService, "clearNodes").and.stub();
let setFilterSubject$: Subject<Graph> = new Subject<Graph>();
let setFilterSpy: jasmine.Spy = spyOn(graphService, "setFilter$");
setFilterSpy.and.returnValue(setFilterSubject$);
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.setFilter$(["==", "key", "value"])
.subscribe(
(): void => {
expect(clearNodesSpy.calls.count()).toBe(1);
expect(setFilterSpy.calls.count()).toBe(1);
expect(setFilterSpy.calls.first().args.length).toBe(1);
expect(setFilterSpy.calls.first().args[0].length).toBe(3);
expect(setFilterSpy.calls.first().args[0][0]).toBe("==");
expect(setFilterSpy.calls.first().args[0][1]).toBe("key");
expect(setFilterSpy.calls.first().args[0][2]).toBe("value");
done();
});
setFilterSubject$.next(graph);
setFilterSubject$.complete();
});
it("should only set filter once when no key requested initially and key requested later", () => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graph: Graph = new Graph(apiV3);
let graphService: GraphService = new GraphService(graph, imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
let setFilterSpy: jasmine.Spy = spyOn(graphService, "setFilter$");
setFilterSpy.and.returnValue(new Subject<Graph>());
spyOn(stateService, "clearNodes").and.stub();
spyOn(loadingService, "startLoading").and.stub();
spyOn(graphService, "cacheNode$").and.returnValue(new Subject<Node>());
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.setFilter$(["==", "key", "value"]).subscribe();
// trigger key requested
navigator.moveToKey$("key").subscribe();
expect(setFilterSpy.calls.count()).toBe(1);
});
it("should set filter and cache requested when key requested but not moved to", (done: Function) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graph: Graph = new Graph(apiV3);
let graphService: GraphService = new GraphService(graph, imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
let setNodesSpy: jasmine.Spy = spyOn(stateService, "setNodes").and.stub();
let clearNodesSpy: jasmine.Spy = spyOn(stateService, "clearNodes").and.stub();
let setFilterSubject$: Subject<Graph> = new Subject<Graph>();
let setFilterSpy: jasmine.Spy = spyOn(graphService, "setFilter$");
setFilterSpy.and.returnValue(setFilterSubject$);
let cacheNodeSubject$: Subject<Node> = new Subject<Node>();
let cacheNodeSpy: jasmine.Spy = spyOn(graphService, "cacheNode$");
let firstEmit: boolean = true;
cacheNodeSpy.and.callFake(
(key: string): Observable<Node> => {
if (firstEmit) {
firstEmit = false;
return new Subject<Node>();
}
return cacheNodeSubject$;
});
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.moveToKey$("moveToKey").subscribe(() => { /*noop*/ });
navigator.setFilter$(["==", "key", "value"])
.subscribe(
(): void => {
expect(setNodesSpy.calls.count()).toBe(0);
expect(clearNodesSpy.calls.count()).toBe(1);
expect(setFilterSpy.calls.count()).toBe(1);
expect(cacheNodeSpy.calls.count()).toBe(2);
expect(cacheNodeSpy.calls.mostRecent().args.length).toBe(1);
expect(cacheNodeSpy.calls.mostRecent().args[0]).toBe("moveToKey");
done();
});
setFilterSubject$.next(graph);
setFilterSubject$.complete();
cacheNodeSubject$.next(null);
cacheNodeSubject$.complete();
});
it("should set filter and cache trajectory keys when moved to", (done: Function) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graph: Graph = new Graph(apiV3);
let graphService: GraphService = new GraphService(graph, imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let currentStateSubject$: Subject<IFrame> = new Subject<IFrame>();
let stateService: TestStateService = new TestStateService(currentStateSubject$);
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(cacheService, "start").and.stub();
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
let setNodesSpy: jasmine.Spy = spyOn(stateService, "setNodes").and.stub();
let clearNodesSpy: jasmine.Spy = spyOn(stateService, "clearNodes").and.stub();
let setFilterSubject$: Subject<Graph> = new Subject<Graph>();
let setFilterSpy: jasmine.Spy = spyOn(graphService, "setFilter$");
setFilterSpy.and.returnValue(setFilterSubject$);
let cacheNodeSubject1$: Subject<Node> = new Subject<Node>();
let cacheNodeSubject2$: Subject<Node> = new Subject<Node>();
let cacheNodeSpy: jasmine.Spy = spyOn(graphService, "cacheNode$");
let firstEmit: boolean = true;
cacheNodeSpy.and.callFake(
(key: string): Observable<Node> => {
if (firstEmit) {
firstEmit = false;
return cacheNodeSubject1$;
}
return cacheNodeSubject2$;
});
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.moveToKey$("key").subscribe(() => { /*noop*/ });
let coreNode0: ICoreNode = helper.createCoreNode();
coreNode0.key = "node0";
let node0: Node = new Node(coreNode0);
cacheNodeSubject1$.next(node0);
cacheNodeSubject1$.complete();
navigator.setFilter$(["==", "key", "value"])
.subscribe(
(): void => {
expect(setNodesSpy.calls.count()).toBe(1);
expect(clearNodesSpy.calls.count()).toBe(1);
expect(setFilterSpy.calls.count()).toBe(1);
expect(cacheNodeSpy.calls.count()).toBe(3);
expect(cacheNodeSpy.calls.argsFor(1)[0]).toBe("node1");
expect(cacheNodeSpy.calls.argsFor(2)[0]).toBe("node2");
done();
});
let coreNode1: ICoreNode = helper.createCoreNode();
coreNode1.key = "node1";
let node1: Node = new Node(coreNode1);
let coreNode2: ICoreNode = helper.createCoreNode();
coreNode2.key = "node2";
let node2: Node = new Node(coreNode2);
let state: ICurrentState = createState();
state.trajectory = [node1, node2];
currentStateSubject$.next({ fps: 60, id: 0, state: state });
currentStateSubject$.complete();
setFilterSubject$.next(graph);
setFilterSubject$.complete();
cacheNodeSubject2$.next(node1);
cacheNodeSubject2$.next(node2);
cacheNodeSubject2$.complete();
});
});
describe("Navigator.setToken$", () => {
let helper: NodeHelper;
beforeEach(() => {
helper = new NodeHelper();
});
it("should set token on api and reset when not moved to key", (done: Function) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graph: Graph = new Graph(apiV3);
let graphService: GraphService = new GraphService(graph, imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(cacheService, "start").and.stub();
let clearNodesSpy: jasmine.Spy = spyOn(stateService, "clearNodes").and.stub();
let setTokenSpy: jasmine.Spy = spyOn(apiV3, "setToken").and.stub();
let resetSubject$: Subject<Graph> = new Subject<Graph>();
let resetSpy: jasmine.Spy = spyOn(graphService, "reset$");
resetSpy.and.returnValue(resetSubject$);
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.setToken$("token")
.subscribe(
(): void => {
expect(clearNodesSpy.calls.count()).toBe(1);
expect(setTokenSpy.calls.count()).toBe(1);
expect(setTokenSpy.calls.first().args.length).toBe(1);
expect(setTokenSpy.calls.first().args[0]).toBe("token");
expect(resetSpy.calls.count()).toBe(1);
expect(resetSpy.calls.first().args.length).toBe(1);
expect(resetSpy.calls.first().args[0]).toEqual([]);
done();
});
resetSubject$.next(graph);
resetSubject$.complete();
});
it("should set token, reset and cache trajectory keys when moved to", (done: Function) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graph: Graph = new Graph(apiV3);
let graphService: GraphService = new GraphService(graph, imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let currentStateSubject$: Subject<IFrame> = new Subject<IFrame>();
let stateService: TestStateService = new TestStateService(currentStateSubject$);
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(cacheService, "start").and.stub();
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
spyOn(stateService, "setNodes").and.stub();
let clearNodesSpy: jasmine.Spy = spyOn(stateService, "clearNodes").and.stub();
let setTokenSpy: jasmine.Spy = spyOn(apiV3, "setToken").and.stub();
let resetSubject$: Subject<Graph> = new Subject<Graph>();
let resetSpy: jasmine.Spy = spyOn(graphService, "reset$");
resetSpy.and.returnValue(resetSubject$);
let cacheNodeSubject1$: Subject<Node> = new Subject<Node>();
let cacheNodeSubject2$: Subject<Node> = new Subject<Node>();
let cacheNodeSpy: jasmine.Spy = spyOn(graphService, "cacheNode$");
let firstEmit: boolean = true;
cacheNodeSpy.and.callFake(
(key: string): Observable<Node> => {
if (firstEmit) {
firstEmit = false;
return cacheNodeSubject1$;
}
return cacheNodeSubject2$;
});
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.moveToKey$("key").subscribe(() => { /*noop*/ });
let coreNode0: ICoreNode = helper.createCoreNode();
coreNode0.key = "node0";
let node0: Node = new Node(coreNode0);
cacheNodeSubject1$.next(node0);
cacheNodeSubject1$.complete();
navigator.setToken$("token")
.subscribe(
(): void => {
expect(clearNodesSpy.calls.count()).toBe(1);
expect(setTokenSpy.calls.count()).toBe(1);
expect(setTokenSpy.calls.first().args.length).toBe(1);
expect(setTokenSpy.calls.first().args[0]).toBe("token");
expect(resetSpy.calls.count()).toBe(1);
expect(resetSpy.calls.first().args.length).toBe(1);
expect(resetSpy.calls.first().args[0].length).toBe(2);
expect(resetSpy.calls.first().args[0][0]).toBe("node1");
expect(resetSpy.calls.first().args[0][1]).toBe("node2");
expect(cacheNodeSpy.calls.count()).toBe(3);
expect(cacheNodeSpy.calls.argsFor(1)[0]).toBe("node1");
expect(cacheNodeSpy.calls.argsFor(2)[0]).toBe("node2");
done();
});
let coreNode1: ICoreNode = helper.createCoreNode();
coreNode1.key = "node1";
let node1: Node = new Node(coreNode1);
let coreNode2: ICoreNode = helper.createCoreNode();
coreNode2.key = "node2";
let node2: Node = new Node(coreNode2);
let state: ICurrentState = createState();
state.trajectory = [node1, node2];
currentStateSubject$.next({ fps: 60, id: 0, state: state });
currentStateSubject$.complete();
resetSubject$.next(graph);
resetSubject$.complete();
cacheNodeSubject2$.next(node1);
cacheNodeSubject2$.next(node2);
cacheNodeSubject2$.complete();
});
it("should abort outstanding move to key request", (done: () => void) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
spyOn(graphService, "cacheNode$").and.returnValue(new Subject<Node>());
spyOn(apiV3, "imageCloseTo$").and.returnValue(new Subject<IFullNode>());
spyOn(stateService, "clearNodes").and.stub();
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.moveToKey$("key1")
.subscribe(
undefined,
(e: Error): void => {
expect(e).toBeDefined();
expect(e instanceof AbortMapillaryError);
done();
});
navigator.setToken$(undefined);
});
it("should abort outstanding move close to request", (done: () => void) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateService();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
spyOn(apiV3, "imageCloseTo$").and.returnValue(new Subject<IFullNode>());
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.moveCloseTo$(0, 0)
.subscribe(
undefined,
(e: Error): void => {
expect(e).toBeDefined();
expect(e instanceof AbortMapillaryError);
done();
});
navigator.setToken$(undefined);
});
it("should abort outstanding move dir request", (done: () => void) => {
let clientId: string = "clientId";
let apiV3: APIv3 = new APIv3(clientId);
let imageLoadingService: ImageLoadingService = new ImageLoadingService();
let graphService: GraphService = new GraphService(new Graph(apiV3), imageLoadingService);
let loadingService: LoadingService = new LoadingService();
let stateService: StateService = new StateServiceMockCreator().create();
let cacheService: CacheService = new CacheService(graphService, stateService);
spyOn(loadingService, "startLoading").and.stub();
spyOn(loadingService, "stopLoading").and.stub();
let navigator: Navigator =
new Navigator(
clientId,
{},
undefined,
apiV3,
graphService,
imageLoadingService,
loadingService,
stateService,
cacheService);
navigator.moveDir$(EdgeDirection.Next)
.subscribe(
undefined,
(e: Error): void => {
expect(e).toBeDefined();
expect(e instanceof AbortMapillaryError);
done();
});
navigator.setToken$(undefined);
});
});