/***************************************************************************** * Open MCT Web, Copyright (c) 2009-2015, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * Open MCT Web is licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * * Open MCT Web includes source code licensed under additional open source * licenses. See the Open Source Licenses file (LICENSES.md) included with * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ define( ['../../../src/controllers/drag/TimelineMoveHandle', '../../../src/TimelineConstants'], function (TimelineMoveHandle, TimelineConstants) { describe("A Timeline move drag handle", function () { var mockDragHandler, mockSnapHandler, mockZoomController, handle; beforeEach(function () { mockDragHandler = jasmine.createSpyObj( 'dragHandler', ['start', 'duration', 'end', 'move', 'persist'] ); mockSnapHandler = jasmine.createSpyObj( 'snapHandler', ['snap'] ); mockZoomController = jasmine.createSpyObj( 'zoom', ['toMillis', 'toPixels'] ); mockDragHandler.start.andReturn(12321); mockDragHandler.duration.andReturn(4200); mockDragHandler.end.andReturn(12321 + 4200); // Echo back the value from snapper for most tests mockSnapHandler.snap.andCallFake(function (ts) { return ts; }); // Double pixels to get millis, for test purposes mockZoomController.toMillis.andCallFake(function (px) { return px * 2; }); mockZoomController.toPixels.andCallFake(function (ms) { return ms / 2; }); handle = new TimelineMoveHandle( 'test-id', mockDragHandler, mockSnapHandler ); }); it("provides a style for templates", function () { var w = TimelineConstants.HANDLE_WIDTH; expect(handle.style(mockZoomController)).toEqual({ // Left should be adjusted by zoom controller left: (12321 / 2) + w + 'px', // Width should be duration minus end points width: 2100 - (w * 2) + 'px' }); }); it("forwards drags to the drag handler", function () { handle.begin(); handle.drag(100, mockZoomController); // Should have been interpreted as a +200 ms change expect(mockDragHandler.move).toHaveBeenCalledWith( "test-id", 200 ); }); it("tracks drags incrementally", function () { handle.begin(); handle.drag(100, mockZoomController); // Should have been interpreted as a +200 ms change... expect(mockDragHandler.move).toHaveBeenCalledWith( "test-id", 200 ); // Reflect the change from the drag handler mockDragHandler.start.andReturn(12521); mockDragHandler.end.andReturn(12521 + 4200); // ....followed by a +100 ms change. handle.drag(150, mockZoomController); expect(mockDragHandler.move).toHaveBeenCalledWith( "test-id", 100 ); }); it("snaps drags to other end points", function () { mockSnapHandler.snap.andCallFake(function (ts) { return ts + 10; }); handle.begin(); handle.drag(100, mockZoomController); // Should have used snap-to timestamp, which was 10 // ms greater than the provided one expect(mockDragHandler.move).toHaveBeenCalledWith( "test-id", 210 ); }); it("considers snaps for both endpoints", function () { handle.begin(); expect(mockSnapHandler.snap).not.toHaveBeenCalled(); handle.drag(100, mockZoomController); expect(mockSnapHandler.snap.calls.length).toEqual(2); }); it("chooses the closest snap-to location", function () { // Use a toggle to give snapped timestamps that are // different distances away from the original. // The move handle needs to choose the closest snap-to, // regardless of whether it is the start/end (which // will vary based on the initial state of this toggle.) var toggle = false; mockSnapHandler.snap.andCallFake(function (ts) { toggle = !toggle; return ts + (toggle ? -5 : 10); }); handle.begin(); handle.drag(100, mockZoomController); expect(mockDragHandler.move).toHaveBeenCalledWith( "test-id", 195 // Chose the -5 ); // Reflect the change from the drag handler mockDragHandler.start.andReturn(12521 - 5); mockDragHandler.end.andReturn(12521 + 4200 - 5); toggle = true; // Change going-in state handle.drag(300, mockZoomController); // Note that the -5 offset is shown in the current state, // so snapping to the -5 implies that the full 400ms will // be moved (again, relative to dragHandler's reported state) expect(mockDragHandler.move).toHaveBeenCalledWith( "test-id", 400 // Still chose the -5 ); }); it("persists when a move is complete", function () { // Simulate normal drag cycle handle.begin(); handle.drag(100, mockZoomController); // Should not have persisted yet expect(mockDragHandler.persist).not.toHaveBeenCalled(); // Finish the drag handle.finish(); // Now it should have persisted expect(mockDragHandler.persist).toHaveBeenCalled(); }); }); } );