import { Subject } from "rxjs"; import { ContainerMockCreator } from "../../helper/ContainerMockCreator"; import { EventHelper } from "../../helper/EventHelper"; import { MockCreator } from "../../helper/MockCreator"; import { NavigatorMockCreator } from "../../helper/NavigatorMockCreator"; import { ImageHelper } from "../../helper/ImageHelper"; import { Navigator } from "../../../src/viewer/Navigator"; import { Image } from "../../../src/graph/Image"; import { Component } from "../../../src/component/Component"; import { ComponentConfiguration } from "../../../src/component/interfaces/ComponentConfiguration"; import { KeyPlayHandler } from "../../../src/component/keyboard/KeyPlayHandler"; import { NavigationEdgeStatus } from "../../../src/graph/interfaces/NavigationEdgeStatus"; import { State } from "../../../src/state/State"; import { Container } from "../../../src/viewer/Container"; import { NavigationDirection } from "../../../src/graph/edge/NavigationDirection"; interface TestConfiguration extends ComponentConfiguration { test: boolean; } class TestComponent extends Component { constructor(name: string, container: Container, navigator: Navigator) { super(name, container, navigator); } protected _activate(): void { /* noop */ } protected _deactivate(): void { /* noop */ } protected _getDefaultConfiguration(): TestConfiguration { return { test: false }; } } describe("KeyPlayHandler.ctor", () => { it("should be defined", () => { const containerMock: Container = new ContainerMockCreator().create(); const navigatorMock: Navigator = new NavigatorMockCreator().create(); const handler: KeyPlayHandler = new KeyPlayHandler( new TestComponent("test", containerMock, navigatorMock), containerMock, navigatorMock); expect(handler).toBeDefined(); }); }); describe("KeyPlayHandler.disable", () => { it("should disable correctly", () => { const containerMock: Container = new ContainerMockCreator().create(); const navigatorMock: Navigator = new NavigatorMockCreator().create(); const testComponent: TestComponent = new TestComponent("test", containerMock, navigatorMock); const handler: KeyPlayHandler = new KeyPlayHandler( testComponent, containerMock, navigatorMock); testComponent.activate(); handler.enable(); expect(handler.isEnabled).toBe(true); handler.disable(); expect(handler.isEnabled).toBe(false); }); }); describe("KeyPlayHandler.enable", () => { let imageHelper: ImageHelper; let containerMock: Container; let navigatorMock: Navigator; let testComponent: TestComponent; let handler: KeyPlayHandler; beforeEach(() => { imageHelper = new ImageHelper(); containerMock = new ContainerMockCreator().create(); navigatorMock = new NavigatorMockCreator().create(); testComponent = new TestComponent("test", containerMock, navigatorMock); handler = new KeyPlayHandler( testComponent, containerMock, navigatorMock); testComponent.activate(); handler.enable(); }); it("should not prevent default if modifier key is pressed", () => { (>navigatorMock.playService.playing$).next(true); (>navigatorMock.playService.direction$).next(NavigationDirection.Next); (>navigatorMock.playService.speed$).next(0.5); (>navigatorMock.stateService.state$).next(State.Traversing); const image: Image = imageHelper.createImage(); const sequenceEdgesSubject: Subject = new Subject(); new MockCreator().mockProperty(image, "sequenceEdges$", sequenceEdgesSubject); (>navigatorMock.stateService.currentImage$).next(image); sequenceEdgesSubject.next({ cached: false, edges: [] }); let keyboardEvent: KeyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: " ", ctrlKey: true }); const preventDefaultSpyCtrl: jasmine.Spy = spyOn(keyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(keyboardEvent); expect(preventDefaultSpyCtrl.calls.count()).toBe(0); keyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: " ", altKey: true }); const preventDefaultSpyAlt: jasmine.Spy = spyOn(keyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(keyboardEvent); expect(preventDefaultSpyAlt.calls.count()).toBe(0); keyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: " ", metaKey: true }); const preventDefaultSpyMeta: jasmine.Spy = spyOn(keyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(keyboardEvent); expect(preventDefaultSpyMeta.calls.count()).toBe(0); keyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: " ", shiftKey: true }); const preventDefaultSpyShift: jasmine.Spy = spyOn(keyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(keyboardEvent); expect(preventDefaultSpyShift.calls.count()).toBe(0); keyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: " " }); const preventDefaultSpy: jasmine.Spy = spyOn(keyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(keyboardEvent); expect(preventDefaultSpy.calls.count()).toBe(1); }); it("should change speed if `>` or `<` is pressed", () => { (>navigatorMock.playService.playing$).next(true); (>navigatorMock.playService.direction$).next(NavigationDirection.Next); (>navigatorMock.playService.speed$).next(0.5); (>navigatorMock.stateService.state$).next(State.Traversing); const image: Image = imageHelper.createImage(); const sequenceEdgesSubject: Subject = new Subject(); new MockCreator().mockProperty(image, "sequenceEdges$", sequenceEdgesSubject); (>navigatorMock.stateService.currentImage$).next(image); sequenceEdgesSubject.next({ cached: false, edges: [] }); const setSpeedSpy: jasmine.Spy = navigatorMock.playService.setSpeed; const increaseKeyboardEvent: KeyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: ">" }); const increasePreventDefaultSpy: jasmine.Spy = spyOn(increaseKeyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(increaseKeyboardEvent); expect(increasePreventDefaultSpy.calls.count()).toBe(1); expect(setSpeedSpy.calls.count()).toBe(1); expect(setSpeedSpy.calls.argsFor(0)[0]).toBeGreaterThan(0.5); const decreaseKeyboardEvent: KeyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: "<" }); const decreasePreventDefaultSpy: jasmine.Spy = spyOn(decreaseKeyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(decreaseKeyboardEvent); expect(decreasePreventDefaultSpy.calls.count()).toBe(1); expect(setSpeedSpy.calls.count()).toBe(2); expect(setSpeedSpy.calls.argsFor(1)[0]).toBeLessThan(0.5); }); it("should change direction when not playing", () => { (>navigatorMock.playService.playing$).next(true); (>navigatorMock.playService.direction$).next(NavigationDirection.Next); (>navigatorMock.playService.speed$).next(0.5); (>navigatorMock.stateService.state$).next(State.Traversing); const image: Image = imageHelper.createImage(); const sequenceEdgesSubject: Subject = new Subject(); new MockCreator().mockProperty(image, "sequenceEdges$", sequenceEdgesSubject); (>navigatorMock.stateService.currentImage$).next(image); sequenceEdgesSubject.next({ cached: false, edges: [] }); const setDirectionSpy: jasmine.Spy = navigatorMock.playService.setDirection; const shiftKeyboardEvent: KeyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: "D", shiftKey: true }); const shiftPreventDefaultSpy: jasmine.Spy = spyOn(shiftKeyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(shiftKeyboardEvent); expect(shiftPreventDefaultSpy.calls.count()).toBe(1); expect(setDirectionSpy.calls.count()).toBe(0); (>navigatorMock.playService.playing$).next(false); (>navigatorMock.playService.direction$).next(NavigationDirection.Next); (>containerMock.keyboardService.keyDown$).next(shiftKeyboardEvent); expect(shiftPreventDefaultSpy.calls.count()).toBe(2); expect(setDirectionSpy.calls.count()).toBe(1); expect(setDirectionSpy.calls.argsFor(0)[0]).toBe(NavigationDirection.Prev); (>navigatorMock.playService.playing$).next(false); (>navigatorMock.playService.direction$).next(NavigationDirection.Prev); (>containerMock.keyboardService.keyDown$).next(shiftKeyboardEvent); expect(shiftPreventDefaultSpy.calls.count()).toBe(3); expect(setDirectionSpy.calls.count()).toBe(2); expect(setDirectionSpy.calls.argsFor(1)[0]).toBe(NavigationDirection.Next); }); it("should play when stopped edge direction exist and stop when playing", () => { const playSpy: jasmine.Spy = navigatorMock.playService.play; const stopSpy: jasmine.Spy = navigatorMock.playService.stop; (>navigatorMock.stateService.state$).next(State.Traversing); const image: Image = imageHelper.createImage(); const sequenceEdgesSubject: Subject = new Subject(); new MockCreator().mockProperty(image, "sequenceEdges$", sequenceEdgesSubject); (>navigatorMock.stateService.currentImage$).next(image); sequenceEdgesSubject.next({ cached: false, edges: [] }); (>navigatorMock.playService.playing$).next(false); (>navigatorMock.playService.direction$).next(NavigationDirection.Next); (>navigatorMock.playService.speed$).next(0.5); const spacebarKeyboardEvent: KeyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: " " }); const spacebarPreventDefaultSpy: jasmine.Spy = spyOn(spacebarKeyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(spacebarKeyboardEvent); expect(spacebarPreventDefaultSpy.calls.count()).toBe(1); expect(playSpy.calls.count()).toBe(0); expect(stopSpy.calls.count()).toBe(0); (>navigatorMock.playService.direction$).next(NavigationDirection.Next); sequenceEdgesSubject.next({ cached: true, edges: [{ data: { direction: NavigationDirection.Next, worldMotionAzimuth: 0 }, source: image.id, target: "toKey", }], }); (>containerMock.keyboardService.keyDown$).next(spacebarKeyboardEvent); expect(spacebarPreventDefaultSpy.calls.count()).toBe(2); expect(playSpy.calls.count()).toBe(1); expect(stopSpy.calls.count()).toBe(0); sequenceEdgesSubject.next({ cached: false, edges: [] }); (>navigatorMock.playService.playing$).next(true); (>containerMock.keyboardService.keyDown$).next(spacebarKeyboardEvent); expect(spacebarPreventDefaultSpy.calls.count()).toBe(3); expect(playSpy.calls.count()).toBe(1); expect(stopSpy.calls.count()).toBe(1); }); it("should not start play when in earth mode", () => { const playSpy: jasmine.Spy = navigatorMock.playService.play; const stopSpy: jasmine.Spy = navigatorMock.playService.stop; (>navigatorMock.stateService.state$).next(State.Earth); const image: Image = imageHelper.createImage(); const sequenceEdgesSubject: Subject = new Subject(); new MockCreator().mockProperty(image, "sequenceEdges$", sequenceEdgesSubject); (>navigatorMock.stateService.currentImage$).next(image); sequenceEdgesSubject.next({ cached: false, edges: [] }); (>navigatorMock.playService.playing$).next(false); (>navigatorMock.playService.direction$).next(NavigationDirection.Next); (>navigatorMock.playService.speed$).next(0.5); const spacebarKeyboardEvent: KeyboardEvent = EventHelper.createKeyboardEvent("keyDown", { key: " " }); const spacebarPreventDefaultSpy: jasmine.Spy = spyOn(spacebarKeyboardEvent, "preventDefault").and.stub(); (>containerMock.keyboardService.keyDown$).next(spacebarKeyboardEvent); expect(spacebarPreventDefaultSpy.calls.count()).toBe(1); expect(playSpy.calls.count()).toBe(0); expect(stopSpy.calls.count()).toBe(0); (>navigatorMock.playService.direction$).next(NavigationDirection.Next); sequenceEdgesSubject.next({ cached: true, edges: [{ data: { direction: NavigationDirection.Next, worldMotionAzimuth: 0 }, source: image.id, target: "toKey", }], }); (>containerMock.keyboardService.keyDown$).next(spacebarKeyboardEvent); expect(spacebarPreventDefaultSpy.calls.count()).toBe(2); expect(playSpy.calls.count()).toBe(0); expect(stopSpy.calls.count()).toBe(0); sequenceEdgesSubject.next({ cached: false, edges: [] }); (>navigatorMock.playService.playing$).next(true); (>containerMock.keyboardService.keyDown$).next(spacebarKeyboardEvent); expect(spacebarPreventDefaultSpy.calls.count()).toBe(3); expect(playSpy.calls.count()).toBe(0); expect(stopSpy.calls.count()).toBe(0); }); });