diff --git a/platform/commonUI/inspect/src/gestures/InfoGesture.js b/platform/commonUI/inspect/src/gestures/InfoGesture.js index 4ad39fb4e6..d39e59745c 100644 --- a/platform/commonUI/inspect/src/gestures/InfoGesture.js +++ b/platform/commonUI/inspect/src/gestures/InfoGesture.js @@ -23,6 +23,12 @@ define( mousePosition, scopeOff; + function trackPosition(event) { + // Record mouse position, so bubble can be shown at latest + // mouse position (not just where the mouse entered) + mousePosition = [ event.clientX, event.clientY ]; + } + function hideBubble() { // If a bubble is showing, dismiss it if (dismissBubble) { @@ -33,6 +39,7 @@ define( // If a bubble will be shown on a timeout, cancel that if (pendingBubble) { $timeout.cancel(pendingBubble); + element.off('mousemove', trackPosition); pendingBubble = undefined; } // Also clear mouse position so we don't have a ton of tiny @@ -40,15 +47,12 @@ define( mousePosition = undefined; } - function trackPosition(event) { - // Record mouse position, so bubble can be shown at latest - // mouse position (not just where the mouse entered) - mousePosition = [ event.clientX, event.clientY ]; - } - function showBubble(event) { trackPosition(event); + // Also need to track position during hover + element.on('mousemove', trackPosition); + // Show the bubble, after a suitable delay (if mouse has // left before this time is up, this will be canceled.) pendingBubble = $timeout(function () { @@ -58,6 +62,7 @@ define( domainObject.useCapability('metadata'), mousePosition ); + element.off('mousemove', trackPosition); pendingBubble = undefined; }, DELAY); @@ -67,9 +72,6 @@ define( // Show bubble (on a timeout) on mouse over element.on('mouseenter', showBubble); - // Also need to track position during hover - element.on('mousemove', trackPosition); - // Also make sure we dismiss bubble if representation is destroyed // before the mouse actually leaves it scopeOff = element.scope().$on('$destroy', hideBubble); diff --git a/platform/commonUI/inspect/test/gestures/InfoGestureSpec.js b/platform/commonUI/inspect/test/gestures/InfoGestureSpec.js new file mode 100644 index 0000000000..4b72d6ba6b --- /dev/null +++ b/platform/commonUI/inspect/test/gestures/InfoGestureSpec.js @@ -0,0 +1,76 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-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. + *****************************************************************************/ +/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +define( + ['../../src/gestures/InfoGesture'], + function (InfoGesture) { + "use strict"; + + describe("The info gesture", function () { + var mockTimeout, + mockInfoService, + testDelay = 12321, + mockElement, + mockDomainObject, + mockScope, + mockOff, + gesture; + + beforeEach(function () { + mockTimeout = jasmine.createSpy('$timeout'); + mockInfoService = jasmine.createSpyObj( + 'infoService', + [ 'display' ] + ); + mockElement = jasmine.createSpyObj( + 'element', + [ 'on', 'off', 'scope', 'css' ] + ); + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getId', 'getCapability', 'useCapability', 'getModel' ] + ); + mockScope = jasmine.createSpyObj('$scope', [ '$on' ]); + mockOff = jasmine.createSpy('$off'); + + mockElement.scope.andReturn(mockScope); + mockScope.$on.andReturn(mockOff); + + gesture = new InfoGesture( + mockTimeout, + mockInfoService, + testDelay, + mockElement, + mockDomainObject + ); + }); + + it("listens for mouseenter on the representation", function () { + expect(mockElement.on) + .toHaveBeenCalledWith('mouseenter', jasmine.any(Function)); + }); + + + }); + } +); \ No newline at end of file diff --git a/platform/commonUI/inspect/test/services/InfoServiceSpec.js b/platform/commonUI/inspect/test/services/InfoServiceSpec.js new file mode 100644 index 0000000000..68d34e7fe8 --- /dev/null +++ b/platform/commonUI/inspect/test/services/InfoServiceSpec.js @@ -0,0 +1,80 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-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. + *****************************************************************************/ +/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +define( + ['../../src/services/InfoService'], + function (InfoService) { + "use strict"; + + describe("The info service", function () { + var mockCompile, + mockDocument, + testWindow, + mockRootScope, + mockCompiledTemplate, + testScope, + mockBody, + mockElement, + service; + + beforeEach(function () { + mockCompile = jasmine.createSpy('$compile'); + mockDocument = jasmine.createSpyObj('$document', ['find']); + testWindow = { innerWidth: 1000, innerHeight: 100 }; + mockRootScope = jasmine.createSpyObj('$rootScope', ['$new']); + mockCompiledTemplate = jasmine.createSpy('template'); + testScope = {}; + mockBody = jasmine.createSpyObj('body', ['append']); + mockElement = jasmine.createSpyObj('element', ['css', 'remove']); + + mockDocument.find.andCallFake(function (tag) { + return tag === 'body' ? mockBody : undefined; + }); + mockCompile.andReturn(mockCompiledTemplate); + mockCompiledTemplate.andReturn(mockElement); + mockRootScope.$new.andReturn(testScope); + + service = new InfoService( + mockCompile, + mockDocument, + testWindow, + mockRootScope + ); + }); + + it("creates elements and appends them to the body to display", function () { + service.display('', '', {}, [0, 0]); + expect(mockBody.append).toHaveBeenCalledWith(mockElement); + }); + + it("provides a function to remove displayed info bubbles", function () { + var fn = service.display('', '', {}, [0, 0]); + expect(mockElement.remove).not.toHaveBeenCalled(); + fn(); + expect(mockElement.remove).toHaveBeenCalled(); + }); + + + }); + } +); \ No newline at end of file diff --git a/platform/commonUI/inspect/test/suite.json b/platform/commonUI/inspect/test/suite.json new file mode 100644 index 0000000000..1d0805c9a9 --- /dev/null +++ b/platform/commonUI/inspect/test/suite.json @@ -0,0 +1,4 @@ +[ + "gestures/InfoGesture", + "services/InfoService" +] \ No newline at end of file