From 26a7fee86945a556badb44df2976ff360b545956 Mon Sep 17 00:00:00 2001 From: Pete Richards Date: Mon, 22 May 2017 14:40:35 -0700 Subject: [PATCH 01/12] Convert example imagery to plugin --- example/imagery/bundle.js | 80 ------------ .../{src/ImageTelemetry.js => plugin.js} | 97 +++++++++------ example/imagery/src/ImageTelemetryProvider.js | 115 ------------------ index.html | 2 +- src/defaultRegistry.js | 1 - src/plugins/plugins.js | 8 +- 6 files changed, 70 insertions(+), 233 deletions(-) delete mode 100644 example/imagery/bundle.js rename example/imagery/{src/ImageTelemetry.js => plugin.js} (53%) delete mode 100644 example/imagery/src/ImageTelemetryProvider.js diff --git a/example/imagery/bundle.js b/example/imagery/bundle.js deleted file mode 100644 index 7dba959bf5..0000000000 --- a/example/imagery/bundle.js +++ /dev/null @@ -1,80 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2017, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT 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 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*/ - -define([ - "./src/ImageTelemetryProvider", - 'legacyRegistry' -], function ( - ImageTelemetryProvider, - legacyRegistry -) { - "use strict"; - - legacyRegistry.register("example/imagery", { - "name": "Imagery", - "description": "Example of a component that produces image telemetry.", - "extensions": { - "components": [ - { - "implementation": ImageTelemetryProvider, - "type": "provider", - "provides": "telemetryService", - "depends": [ - "$q", - "$timeout" - ] - } - ], - "types": [ - { - "key": "imagery", - "name": "Example Imagery", - "cssClass": "icon-image", - "features": "creation", - "description": "For development use. Creates example imagery data that mimics a live imagery stream.", - "priority": 10, - "model": { - "telemetry": {} - }, - "telemetry": { - "source": "imagery", - "domains": [ - { - "name": "Time", - "key": "time", - "format": "utc" - } - ], - "ranges": [ - { - "name": "Image", - "key": "url", - "format": "imageUrl" - } - ] - } - } - ] - } - }); -}); diff --git a/example/imagery/src/ImageTelemetry.js b/example/imagery/plugin.js similarity index 53% rename from example/imagery/src/ImageTelemetry.js rename to example/imagery/plugin.js index c854e66bf6..4c4f41d75b 100644 --- a/example/imagery/src/ImageTelemetry.js +++ b/example/imagery/plugin.js @@ -19,18 +19,15 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*global define,Promise*/ -/** - * Module defining ImageTelemetry. Created by vwoeltje on 06/22/15. - */ -define( - [], - function () { - "use strict"; +define([ - var firstObservedTime = Date.now(), - images = [ +], function( + +) { + function ImageryPlugin() { + + var IMAGE_SAMPLES = [ "https://www.hq.nasa.gov/alsj/a16/AS16-117-18731.jpg", "https://www.hq.nasa.gov/alsj/a16/AS16-117-18732.jpg", "https://www.hq.nasa.gov/alsj/a16/AS16-117-18733.jpg", @@ -49,33 +46,65 @@ define( "https://www.hq.nasa.gov/alsj/a16/AS16-117-18746.jpg", "https://www.hq.nasa.gov/alsj/a16/AS16-117-18747.jpg", "https://www.hq.nasa.gov/alsj/a16/AS16-117-18748.jpg" + ]; - ].map(function (url, index) { - return { - timestamp: firstObservedTime + 1000 * index, - url: url - }; + return function install(openmct) { + openmct.types.addType('example.imagery', { + key: 'example.imagery', + name: 'Example Imagery', + cssClass: 'icon-image', + description: 'For development use. Creates example imagery ' + + 'data that mimics a live imagery stream.', + creatable: true, + initialize: function (object) { + object.telemetry = { + values: [ + { + name: 'Time', + key: 'time', + format: 'utc', + hints: { + domain: 1 + } + }, + { + name: 'Image', + key: 'url', + format: 'image', + hints: {} + } + ] + } + } }); + openmct.telemetry.addProvider({ + supportsSubscribe: function (domainObject) { + return domainObject.type === 'example.imagery'; + }, + subscribe: function (domainObject, callback) { + var index = 0, + end = IMAGE_SAMPLES.length, + interval; - /** - * - * @constructor - */ - function ImageTelemetry() { - return { - getPointCount: function () { - return Math.floor((Date.now() - firstObservedTime) / 1000); - }, - getDomainValue: function (i, domain) { - return images[i % images.length].timestamp; - }, - getRangeValue: function (i, range) { - return images[i % images.length].url; + interval = setInterval(function () { + if (index >= end) { + index = 0; + } + callback({ + time: Date.now(), + url: IMAGE_SAMPLES[index] + }); + index += 1; + }, 1000); + + return function (interval) { + clearInterval(interval); + }; } - }; - } - - return ImageTelemetry; + }); + }; } -); + + return ImageryPlugin; +}); diff --git a/example/imagery/src/ImageTelemetryProvider.js b/example/imagery/src/ImageTelemetryProvider.js deleted file mode 100644 index 3232441ef7..0000000000 --- a/example/imagery/src/ImageTelemetryProvider.js +++ /dev/null @@ -1,115 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2017, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT 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 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*/ - -/** - * Module defining ImageTelemetryProvider. Created by vwoeltje on 06/22/15. - */ -define( - ["./ImageTelemetry"], - function (ImageTelemetry) { - "use strict"; - - /** - * - * @constructor - */ - function ImageTelemetryProvider($q, $timeout) { - var subscriptions = []; - - // - function matchesSource(request) { - return request.source === "imagery"; - } - - // Used internally; this will be repacked by doPackage - function generateData(request) { - return { - key: request.key, - telemetry: new ImageTelemetry() - }; - } - - // - function doPackage(results) { - var packaged = {}; - results.forEach(function (result) { - packaged[result.key] = result.telemetry; - }); - // Format as expected (sources -> keys -> telemetry) - return { imagery: packaged }; - } - - function requestTelemetry(requests) { - return $timeout(function () { - return doPackage(requests.filter(matchesSource).map(generateData)); - }, 0); - } - - function handleSubscriptions() { - subscriptions.forEach(function (subscription) { - var requests = subscription.requests; - subscription.callback(doPackage( - requests.filter(matchesSource).map(generateData) - )); - }); - } - - function startGenerating() { - $timeout(function () { - handleSubscriptions(); - if (subscriptions.length > 0) { - startGenerating(); - } - }, 1000); - } - - function subscribe(callback, requests) { - var subscription = { - callback: callback, - requests: requests - }; - - function unsubscribe() { - subscriptions = subscriptions.filter(function (s) { - return s !== subscription; - }); - } - - subscriptions.push(subscription); - - if (subscriptions.length === 1) { - startGenerating(); - } - - return unsubscribe; - } - - return { - requestTelemetry: requestTelemetry, - subscribe: subscribe - }; - } - - return ImageTelemetryProvider; - } -); diff --git a/index.html b/index.html index 9b6f732346..71a5f8df18 100644 --- a/index.html +++ b/index.html @@ -32,7 +32,6 @@ require(['openmct'], function (openmct) { [ - 'example/imagery', 'example/eventGenerator', 'example/styleguide' ].forEach( @@ -42,6 +41,7 @@ openmct.install(openmct.plugins.LocalStorage()); openmct.install(openmct.plugins.Espresso()); openmct.install(openmct.plugins.Generator()); + openmct.install(openmct.plugins.ExampleImagery()); openmct.install(openmct.plugins.UTCTimeSystem()); openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0}); openmct.time.timeSystem('utc'); diff --git a/src/defaultRegistry.js b/src/defaultRegistry.js index 1259efe17e..c2808fad0d 100644 --- a/src/defaultRegistry.js +++ b/src/defaultRegistry.js @@ -34,7 +34,6 @@ define([ '../example/extensions/bundle', '../example/forms/bundle', '../example/identity/bundle', - '../example/imagery/bundle', '../example/mobile/bundle', '../example/msl/bundle', '../example/notifications/bundle', diff --git a/src/plugins/plugins.js b/src/plugins/plugins.js index 5c671fa79c..ee3cbe42c7 100644 --- a/src/plugins/plugins.js +++ b/src/plugins/plugins.js @@ -25,13 +25,15 @@ define([ './utcTimeSystem/plugin', '../../example/generator/plugin', '../../platform/features/autoflow/plugin', - './timeConductor/plugin' + './timeConductor/plugin', + '../../example/imagery/plugin' ], function ( _, UTCTimeSystem, GeneratorPlugin, AutoflowPlugin, - TimeConductorPlugin + TimeConductorPlugin, + ExampleImagery ) { var bundleMap = { CouchDB: 'platform/persistence/couch', @@ -113,5 +115,7 @@ define([ return GeneratorPlugin; }; + plugins.ExampleImagery = ExampleImagery; + return plugins; }); From b60eb6d6ae2334217ea3b3c2135a002ebbc323ab Mon Sep 17 00:00:00 2001 From: Pete Richards Date: Mon, 22 May 2017 18:30:01 -0700 Subject: [PATCH 02/12] WIP refactor for new telem api --- example/imagery/plugin.js | 8 +- platform/features/imagery/bundle.js | 7 +- .../imagery/res/templates/imagery.html | 4 +- .../src/controllers/ImageryController.js | 118 ++++++++---------- .../imagery/src/policies/ImageryViewPolicy.js | 31 ++--- .../test/controllers/ImageryControllerSpec.js | 63 +++++----- 6 files changed, 109 insertions(+), 122 deletions(-) diff --git a/example/imagery/plugin.js b/example/imagery/plugin.js index 4c4f41d75b..9866514dbd 100644 --- a/example/imagery/plugin.js +++ b/example/imagery/plugin.js @@ -61,7 +61,7 @@ define([ values: [ { name: 'Time', - key: 'time', + key: 'utc', format: 'utc', hints: { domain: 1 @@ -71,7 +71,9 @@ define([ name: 'Image', key: 'url', format: 'image', - hints: {} + hints: { + image: 1 + } } ] } @@ -92,7 +94,7 @@ define([ index = 0; } callback({ - time: Date.now(), + utc: Date.now(), url: IMAGE_SAMPLES[index] }); index += 1; diff --git a/platform/features/imagery/bundle.js b/platform/features/imagery/bundle.js index 107de8ed6a..85aba508ff 100644 --- a/platform/features/imagery/bundle.js +++ b/platform/features/imagery/bundle.js @@ -53,7 +53,10 @@ define([ "policies": [ { "category": "view", - "implementation": ImageryViewPolicy + "implementation": ImageryViewPolicy, + "depends": [ + "openmct" + ] } ], "controllers": [ @@ -62,7 +65,7 @@ define([ "implementation": ImageryController, "depends": [ "$scope", - "telemetryHandler" + "openmct" ] } ], diff --git a/platform/features/imagery/res/templates/imagery.html b/platform/features/imagery/res/templates/imagery.html index 542ef66e56..1b2b1c3e53 100644 --- a/platform/features/imagery/res/templates/imagery.html +++ b/platform/features/imagery/res/templates/imagery.html @@ -34,10 +34,8 @@
- {{imagery.getZone()}} + ng-click="showThumbsBubble = (showThumbsBubble) ? false:true"> {{imagery.getTime()}} - {{imagery.getDate()}}
0 && state !== this.isPaused) { this.isPaused = state; - // Switch to latest image - this.updateValues(); + this.updateValues(this.nextValue); + delete this.nextValue; } return this.isPaused; }; diff --git a/platform/features/imagery/src/policies/ImageryViewPolicy.js b/platform/features/imagery/src/policies/ImageryViewPolicy.js index ecc1505f36..75e43a0015 100644 --- a/platform/features/imagery/src/policies/ImageryViewPolicy.js +++ b/platform/features/imagery/src/policies/ImageryViewPolicy.js @@ -20,8 +20,11 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define( - function () { +define([ + '../../../../../src/api/objects/object-utils' +], function ( + objectUtils +) { /** * Policy preventing the Imagery view from being made available for @@ -29,24 +32,24 @@ define( * @implements {Policy.} * @constructor */ - function ImageryViewPolicy() { + function ImageryViewPolicy(openmct) { + this.openmct = openmct; } - function hasImageTelemetry(domainObject) { - var telemetry = domainObject && - domainObject.getCapability('telemetry'), - metadata = telemetry ? telemetry.getMetadata() : {}, - ranges = metadata.ranges || []; + ImageryViewPolicy.prototype.hasImageTelemetry = function (domainObject) { + var newDO = objectUtils.toNewFormat( + domainObject.getModel(), + domainObject.getId() + ); - return ranges.some(function (range) { - return range.format === 'imageUrl' || - range.format === 'image'; - }); - } + var metadata = this.openmct.telemetry.getMetadata(newDO); + var values = metadata.valuesForHints(['image']); + return values.length >= 1; + }; ImageryViewPolicy.prototype.allow = function (view, domainObject) { if (view.key === 'imagery') { - return hasImageTelemetry(domainObject); + return this.hasImageTelemetry(domainObject); } return true; diff --git a/platform/features/imagery/test/controllers/ImageryControllerSpec.js b/platform/features/imagery/test/controllers/ImageryControllerSpec.js index 3d3c3c00b1..d81becec51 100644 --- a/platform/features/imagery/test/controllers/ImageryControllerSpec.js +++ b/platform/features/imagery/test/controllers/ImageryControllerSpec.js @@ -25,48 +25,45 @@ define( function (ImageryController) { describe("The Imagery controller", function () { - var mockScope, - mockTelemetryHandler, - mockHandle, - mockDomainObject, + var $scope, + openmct, + oldDomainObject, + newDomainObject, + unsubscribe, + callback, controller; - function invokeWatch(expr, value) { - mockScope.$watch.calls.forEach(function (call) { - if (call.args[0] === expr) { - call.args[1](value); - } - }); - } - beforeEach(function () { - mockScope = jasmine.createSpyObj('$scope', ['$on', '$watch']); - mockTelemetryHandler = jasmine.createSpyObj( - 'telemetryHandler', - ['handle'] - ); - mockHandle = jasmine.createSpyObj( - 'handle', - [ - 'getDomainValue', - 'getRangeValue', - 'getTelemetryObjects', - 'unsubscribe' - ] - ); - mockDomainObject = jasmine.createSpyObj( + $scope = jasmine.createSpyObj('$scope', ['$on', '$watch']); + oldDomainObject = jasmine.createSpyObj( 'domainObject', - ['getId', 'getModel', 'getCapability'] + ['getId'] ); - mockTelemetryHandler.handle.andReturn(mockHandle); - mockHandle.getTelemetryObjects.andReturn([mockDomainObject]); + oldDomainObject.getId.andReturn('testID'); + openmct = { + objects: jasmine.createSpyObj('objectAPI', [ + 'get' + ]), + time: jasmine.createSpyObj('timeAPI', [ + 'timeSystem' + ]), + telemetry: jasmine.createSpyObj('telemetryAPI', [ + 'subscribe' + ]); + }; + unsubscribe = jasmine.createSpy('unsubscribe'); + openmct.telemetry.subscribe.andReturn(unsubcribe); + openmct.time.timeSystem.andReturn({ + key: 'testKey' + }); + openmct.objects.get.andReturn(Promise.resolve(newDomainObject)); controller = new ImageryController( - mockScope, - mockTelemetryHandler + $scope, + openmct ); - invokeWatch('domainObject', mockDomainObject); + }); it("unsubscribes when scope is destroyed", function () { From 8c7e8dab8e99fe936174018b3be2cacd72ef4f71 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 31 May 2017 15:52:15 -0700 Subject: [PATCH 03/12] [Imagery] Use consistent field name --- .../features/imagery/src/controllers/ImageryController.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/features/imagery/src/controllers/ImageryController.js b/platform/features/imagery/src/controllers/ImageryController.js index 978df8a4bb..3cbf940647 100644 --- a/platform/features/imagery/src/controllers/ImageryController.js +++ b/platform/features/imagery/src/controllers/ImageryController.js @@ -96,7 +96,7 @@ define( return; } this.time = this.timeFormat.format(datum); - this.image = this.imageFormat.format(datum); + this.imageUrl = this.imageFormat.format(datum); }; /** @@ -113,7 +113,7 @@ define( * @returns {string} URL for telemetry image */ ImageryController.prototype.getImageUrl = function () { - return this.image; + return this.imageUrl; }; /** From 95188f6ce67c8570dba059175f26b44245ba9be6 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 31 May 2017 15:57:20 -0700 Subject: [PATCH 04/12] [Documentation] Document image hint --- API.md | 1 + 1 file changed, 1 insertion(+) diff --git a/API.md b/API.md index 882c80b946..c9823d5ebf 100644 --- a/API.md +++ b/API.md @@ -372,6 +372,7 @@ Known hints: * `domain`: Indicates that the value represents the "input" of a datum. Values with a `domain` hint will be used for the x-axis of a plot, and tables will render columns for these values first. * `range`: Indicates that the value is the "output" of a datum. Values with a `range` hint will be used as the y-axis on a plot, and tables will render columns for these values after the `domain` values. +* `image`: Indicates that the value may be interpreted as the URL to an image file, in which case appropriate views will be made available. ##### The Time Conductor and Telemetry From 53cecb89099a9bb147099b02fe7240781a451ce9 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 31 May 2017 16:02:12 -0700 Subject: [PATCH 05/12] [Imagery] Add missing semicolon, remove unused vars --- .../features/imagery/src/controllers/ImageryController.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platform/features/imagery/src/controllers/ImageryController.js b/platform/features/imagery/src/controllers/ImageryController.js index 3cbf940647..7661136a1c 100644 --- a/platform/features/imagery/src/controllers/ImageryController.js +++ b/platform/features/imagery/src/controllers/ImageryController.js @@ -28,9 +28,6 @@ define( ['moment'], function (moment) { - var DATE_FORMAT = "YYYY-MM-DD", - TIME_FORMAT = "HH:mm:ss.SSS"; - /** * Controller for the "Imagery" view of a domain object which * provides image telemetry. @@ -87,7 +84,7 @@ define( this.unsubscribe(); delete this.unsubscribe; } - } + }; // Update displayable values to reflect latest image telemetry ImageryController.prototype.updateValues = function (datum) { From f6cd35a6315c05f2a6322b97321fa776d4c12953 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 31 May 2017 16:04:56 -0700 Subject: [PATCH 06/12] [Imagery] Fix code style issues in spec --- .../features/imagery/test/controllers/ImageryControllerSpec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/features/imagery/test/controllers/ImageryControllerSpec.js b/platform/features/imagery/test/controllers/ImageryControllerSpec.js index d81becec51..da84634690 100644 --- a/platform/features/imagery/test/controllers/ImageryControllerSpec.js +++ b/platform/features/imagery/test/controllers/ImageryControllerSpec.js @@ -30,7 +30,6 @@ define( oldDomainObject, newDomainObject, unsubscribe, - callback, controller; beforeEach(function () { @@ -50,7 +49,7 @@ define( ]), telemetry: jasmine.createSpyObj('telemetryAPI', [ 'subscribe' - ]); + ]) }; unsubscribe = jasmine.createSpy('unsubscribe'); openmct.telemetry.subscribe.andReturn(unsubcribe); From e300b49c9562c53e30253f1afbddda85175bb4d8 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 31 May 2017 16:05:57 -0700 Subject: [PATCH 07/12] [Imagery] Normalize whitespace in policy --- .../imagery/src/policies/ImageryViewPolicy.js | 56 +++++++++---------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/platform/features/imagery/src/policies/ImageryViewPolicy.js b/platform/features/imagery/src/policies/ImageryViewPolicy.js index 75e43a0015..4811f1e55a 100644 --- a/platform/features/imagery/src/policies/ImageryViewPolicy.js +++ b/platform/features/imagery/src/policies/ImageryViewPolicy.js @@ -25,37 +25,35 @@ define([ ], function ( objectUtils ) { + /** + * Policy preventing the Imagery view from being made available for + * domain objects which do not have associated image telemetry. + * @implements {Policy.} + * @constructor + */ + function ImageryViewPolicy(openmct) { + this.openmct = openmct; + } - /** - * Policy preventing the Imagery view from being made available for - * domain objects which do not have associated image telemetry. - * @implements {Policy.} - * @constructor - */ - function ImageryViewPolicy(openmct) { - this.openmct = openmct; + ImageryViewPolicy.prototype.hasImageTelemetry = function (domainObject) { + var newDO = objectUtils.toNewFormat( + domainObject.getModel(), + domainObject.getId() + ); + + var metadata = this.openmct.telemetry.getMetadata(newDO); + var values = metadata.valuesForHints(['image']); + return values.length >= 1; + }; + + ImageryViewPolicy.prototype.allow = function (view, domainObject) { + if (view.key === 'imagery') { + return this.hasImageTelemetry(domainObject); } - ImageryViewPolicy.prototype.hasImageTelemetry = function (domainObject) { - var newDO = objectUtils.toNewFormat( - domainObject.getModel(), - domainObject.getId() - ); + return true; + }; - var metadata = this.openmct.telemetry.getMetadata(newDO); - var values = metadata.valuesForHints(['image']); - return values.length >= 1; - }; - - ImageryViewPolicy.prototype.allow = function (view, domainObject) { - if (view.key === 'imagery') { - return this.hasImageTelemetry(domainObject); - } - - return true; - }; - - return ImageryViewPolicy; - } -); + return ImageryViewPolicy; +}); From 1c9230029da4dbbda307b9a8fd9243b072c0104b Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 1 Jun 2017 15:46:58 -0700 Subject: [PATCH 08/12] [Imagery] Begin updating spec --- .../test/controllers/ImageryControllerSpec.js | 59 +++++++++---------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/platform/features/imagery/test/controllers/ImageryControllerSpec.js b/platform/features/imagery/test/controllers/ImageryControllerSpec.js index da84634690..6a5f9cca47 100644 --- a/platform/features/imagery/test/controllers/ImageryControllerSpec.js +++ b/platform/features/imagery/test/controllers/ImageryControllerSpec.js @@ -30,6 +30,7 @@ define( oldDomainObject, newDomainObject, unsubscribe, + callback, controller; beforeEach(function () { @@ -38,6 +39,7 @@ define( 'domainObject', ['getId'] ); + newDomainObject = { name: 'foo' }; oldDomainObject.getId.andReturn('testID'); openmct = { @@ -52,10 +54,11 @@ define( ]) }; unsubscribe = jasmine.createSpy('unsubscribe'); - openmct.telemetry.subscribe.andReturn(unsubcribe); + openmct.telemetry.subscribe.andReturn(unsubscribe); openmct.time.timeSystem.andReturn({ key: 'testKey' }); + $scope.domainObject = oldDomainObject; openmct.objects.get.andReturn(Promise.resolve(newDomainObject)); controller = new ImageryController( @@ -63,18 +66,33 @@ define( openmct ); + +// runs(function () { +// callback = +// openmct.telemetry.subscribe.mostRecentCall.args[1]; +// }); + }); + + it("subscribes to telemetry", function () { + waitsFor(function () { + return !!(openmct.telemetry.subscribe.mostRecentCall); + }); + expect(openmct.telemetry.subscribe).toHaveBeenCalledWith( + newDomainObject, + jasmine.any(Function) + ); }); it("unsubscribes when scope is destroyed", function () { - expect(mockHandle.unsubscribe).not.toHaveBeenCalled(); + expect(unsubscribe).not.toHaveBeenCalled(); // Find the $destroy listener and call it - mockScope.$on.calls.forEach(function (call) { + $scope.$on.calls.forEach(function (call) { if (call.args[0] === '$destroy') { call.args[1](); } }); - expect(mockHandle.unsubscribe).toHaveBeenCalled(); + expect(unsubscribe).toHaveBeenCalled(); }); it("exposes the latest telemetry values", function () { @@ -84,20 +102,15 @@ define( nextTimestamp = 1434600259456, // 4:05.456 nextUrl = "some/other/url"; - mockHandle.getDomainValue.andReturn(testTimestamp); - mockHandle.getRangeValue.andReturn(testUrl); - - // Call the subscription listener - mockTelemetryHandler.handle.mostRecentCall.args[1](); + // Call back with telemetry data + callback({ timestamp: testTimestamp, value: testUrl }); expect(controller.getTime()).toEqual("04:04:18.123"); expect(controller.getDate()).toEqual("2015-06-18"); expect(controller.getZone()).toEqual("UTC"); expect(controller.getImageUrl()).toEqual(testUrl); - mockHandle.getDomainValue.andReturn(nextTimestamp); - mockHandle.getRangeValue.andReturn(nextUrl); - mockTelemetryHandler.handle.mostRecentCall.args[1](); + callback({ timestamp: nextTimestamp, value: nextUrl }); expect(controller.getTime()).toEqual("04:04:19.456"); expect(controller.getDate()).toEqual("2015-06-18"); @@ -112,14 +125,8 @@ define( nextTimestamp = 1434600259456, // 4:05.456 nextUrl = "some/other/url"; - // As above, but pause in between. Expect details - // not to change this time - - mockHandle.getDomainValue.andReturn(testTimestamp); - mockHandle.getRangeValue.andReturn(testUrl); - - // Call the subscription listener - mockTelemetryHandler.handle.mostRecentCall.args[1](); + // Call back with telemetry data + callback({ timestamp: testTimestamp, value: testUrl }); expect(controller.getTime()).toEqual("04:04:18.123"); expect(controller.getDate()).toEqual("2015-06-18"); @@ -130,9 +137,7 @@ define( controller.paused(true); // Pause! expect(controller.paused()).toBeTruthy(); - mockHandle.getDomainValue.andReturn(nextTimestamp); - mockHandle.getRangeValue.andReturn(nextUrl); - mockTelemetryHandler.handle.mostRecentCall.args[1](); + callback({ timestamp: nextTimestamp, value: nextUrl }); expect(controller.getTime()).toEqual("04:04:18.123"); expect(controller.getDate()).toEqual("2015-06-18"); @@ -141,13 +146,7 @@ define( }); it("initially shows an empty string for date/time", function () { - // Call the subscription listener while domain/range - // values are still undefined - mockHandle.getDomainValue.andReturn(undefined); - mockHandle.getRangeValue.andReturn(undefined); - mockTelemetryHandler.handle.mostRecentCall.args[1](); - - // Should have empty strings for date/time/zone + // Do not invoke callback... expect(controller.getTime()).toEqual(""); expect(controller.getDate()).toEqual(""); expect(controller.getZone()).toEqual(""); From cb9231f4533cd7ca30fb17868c37bd1d9b572b33 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 1 Jun 2017 18:16:15 -0700 Subject: [PATCH 09/12] [Imagery] Set up test mocks --- .../test/controllers/ImageryControllerSpec.js | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/platform/features/imagery/test/controllers/ImageryControllerSpec.js b/platform/features/imagery/test/controllers/ImageryControllerSpec.js index 6a5f9cca47..1fecdba105 100644 --- a/platform/features/imagery/test/controllers/ImageryControllerSpec.js +++ b/platform/features/imagery/test/controllers/ImageryControllerSpec.js @@ -31,6 +31,7 @@ define( newDomainObject, unsubscribe, callback, + metadata, controller; beforeEach(function () { @@ -50,9 +51,15 @@ define( 'timeSystem' ]), telemetry: jasmine.createSpyObj('telemetryAPI', [ - 'subscribe' + 'subscribe', + 'getValueFormatter', + 'getMetadata' ]) }; + metadata = jasmine.createSpyObj('metadata', [ + 'value', + 'valuesForHints' + ]); unsubscribe = jasmine.createSpy('unsubscribe'); openmct.telemetry.subscribe.andReturn(unsubscribe); openmct.time.timeSystem.andReturn({ @@ -60,23 +67,22 @@ define( }); $scope.domainObject = oldDomainObject; openmct.objects.get.andReturn(Promise.resolve(newDomainObject)); + openmct.telemetry.getMetadata.andReturn(metadata); + metadata.valuesForHints.andReturn([]); - controller = new ImageryController( - $scope, - openmct - ); + controller = new ImageryController($scope, openmct); + waitsFor(function () { + return openmct.telemetry.subscribe.calls.length > 0; + }, 100); -// runs(function () { -// callback = -// openmct.telemetry.subscribe.mostRecentCall.args[1]; -// }); + runs(function () { + callback = + openmct.telemetry.subscribe.mostRecentCall.args[1]; + }); }); it("subscribes to telemetry", function () { - waitsFor(function () { - return !!(openmct.telemetry.subscribe.mostRecentCall); - }); expect(openmct.telemetry.subscribe).toHaveBeenCalledWith( newDomainObject, jasmine.any(Function) From 7513f24ff380fda8756d47bda62c1177b5adae88 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 1 Jun 2017 18:34:26 -0700 Subject: [PATCH 10/12] [Imagery] Update value testing in spec --- .../test/controllers/ImageryControllerSpec.js | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/platform/features/imagery/test/controllers/ImageryControllerSpec.js b/platform/features/imagery/test/controllers/ImageryControllerSpec.js index 1fecdba105..2fc146353f 100644 --- a/platform/features/imagery/test/controllers/ImageryControllerSpec.js +++ b/platform/features/imagery/test/controllers/ImageryControllerSpec.js @@ -32,6 +32,7 @@ define( unsubscribe, callback, metadata, + prefix, controller; beforeEach(function () { @@ -60,6 +61,7 @@ define( 'value', 'valuesForHints' ]); + prefix = "formatted "; unsubscribe = jasmine.createSpy('unsubscribe'); openmct.telemetry.subscribe.andReturn(unsubscribe); openmct.time.timeSystem.andReturn({ @@ -68,7 +70,17 @@ define( $scope.domainObject = oldDomainObject; openmct.objects.get.andReturn(Promise.resolve(newDomainObject)); openmct.telemetry.getMetadata.andReturn(metadata); - metadata.valuesForHints.andReturn([]); + openmct.telemetry.getValueFormatter.andCallFake(function (property) { + var formatter = + jasmine.createSpyObj("formatter-" + property, ['format']); + var isTime = (property === "timestamp"); + formatter.format.andCallFake(function (datum) { + return (isTime ? prefix : "") + datum[property]; + }); + return formatter; + }); + metadata.value.andReturn("timestamp"); + metadata.valuesForHints.andReturn(["value"]); controller = new ImageryController($scope, openmct); @@ -111,16 +123,12 @@ define( // Call back with telemetry data callback({ timestamp: testTimestamp, value: testUrl }); - expect(controller.getTime()).toEqual("04:04:18.123"); - expect(controller.getDate()).toEqual("2015-06-18"); - expect(controller.getZone()).toEqual("UTC"); + expect(controller.getTime()).toEqual(prefix + testTimestamp); expect(controller.getImageUrl()).toEqual(testUrl); callback({ timestamp: nextTimestamp, value: nextUrl }); - expect(controller.getTime()).toEqual("04:04:19.456"); - expect(controller.getDate()).toEqual("2015-06-18"); - expect(controller.getZone()).toEqual("UTC"); + expect(controller.getTime()).toEqual(prefix + nextTimestamp); expect(controller.getImageUrl()).toEqual(nextUrl); }); @@ -134,9 +142,7 @@ define( // Call back with telemetry data callback({ timestamp: testTimestamp, value: testUrl }); - expect(controller.getTime()).toEqual("04:04:18.123"); - expect(controller.getDate()).toEqual("2015-06-18"); - expect(controller.getZone()).toEqual("UTC"); + expect(controller.getTime()).toEqual(prefix + testTimestamp); expect(controller.getImageUrl()).toEqual(testUrl); expect(controller.paused()).toBeFalsy(); @@ -145,18 +151,14 @@ define( callback({ timestamp: nextTimestamp, value: nextUrl }); - expect(controller.getTime()).toEqual("04:04:18.123"); - expect(controller.getDate()).toEqual("2015-06-18"); - expect(controller.getZone()).toEqual("UTC"); + expect(controller.getTime()).toEqual(prefix + testTimestamp); expect(controller.getImageUrl()).toEqual(testUrl); }); it("initially shows an empty string for date/time", function () { // Do not invoke callback... expect(controller.getTime()).toEqual(""); - expect(controller.getDate()).toEqual(""); - expect(controller.getZone()).toEqual(""); - expect(controller.getImageUrl()).toBeUndefined(); + expect(controller.getImageUrl()).toEqual(""); }); }); } From b2333d83d2cafc0a5c4d080cf093e151638c9744 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 1 Jun 2017 18:46:22 -0700 Subject: [PATCH 11/12] [Imagery] Update policy spec Fixes #1591 --- .../test/policies/ImageryViewPolicySpec.js | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/platform/features/imagery/test/policies/ImageryViewPolicySpec.js b/platform/features/imagery/test/policies/ImageryViewPolicySpec.js index 5e69cb331c..1e317c6e55 100644 --- a/platform/features/imagery/test/policies/ImageryViewPolicySpec.js +++ b/platform/features/imagery/test/policies/ImageryViewPolicySpec.js @@ -26,14 +26,17 @@ define( describe("Imagery view policy", function () { var testView, + openmct, mockDomainObject, mockTelemetry, - testMetadata, + mockMetadata, policy; beforeEach(function () { testView = { key: "imagery" }; - testMetadata = {}; + mockMetadata = jasmine.createSpyObj('metadata', [ + "valuesForHints" + ]); mockDomainObject = jasmine.createSpyObj( 'domainObject', ['getId', 'getModel', 'getCapability'] @@ -45,30 +48,33 @@ define( mockDomainObject.getCapability.andCallFake(function (c) { return c === 'telemetry' ? mockTelemetry : undefined; }); - mockTelemetry.getMetadata.andReturn(testMetadata); + mockDomainObject.getId.andReturn("some-id"); + mockDomainObject.getModel.andReturn({ name: "foo" }); + mockTelemetry.getMetadata.andReturn(mockMetadata); + mockMetadata.valuesForHints.andReturn(["bar"]); - policy = new ImageryViewPolicy(); + openmct = { telemetry: mockTelemetry }; + + policy = new ImageryViewPolicy(openmct); + }); + + it("checks for hints indicating image telemetry", function () { + policy.allow(testView, mockDomainObject); + expect(mockMetadata.valuesForHints) + .toHaveBeenCalledWith(["image"]); }); it("allows the imagery view for domain objects with image telemetry", function () { - testMetadata.ranges = [{ key: "foo", format: "imageUrl" }]; expect(policy.allow(testView, mockDomainObject)).toBeTruthy(); }); it("disallows the imagery view for domain objects without image telemetry", function () { - testMetadata.ranges = [{ key: "foo", format: "somethingElse" }]; - expect(policy.allow(testView, mockDomainObject)).toBeFalsy(); - }); - - it("disallows the imagery view for domain objects without telemetry", function () { - testMetadata.ranges = [{ key: "foo", format: "imageUrl" }]; - mockDomainObject.getCapability.andReturn(undefined); + mockMetadata.valuesForHints.andReturn([]); expect(policy.allow(testView, mockDomainObject)).toBeFalsy(); }); it("allows other views", function () { testView.key = "somethingElse"; - testMetadata.ranges = [{ key: "foo", format: "somethingElse" }]; expect(policy.allow(testView, mockDomainObject)).toBeTruthy(); }); From 1c9a9baf7712f5bff364a7648a8af32c6f5b6fb2 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 13 Jun 2017 14:16:47 -0700 Subject: [PATCH 12/12] [Imagery] Check for pending updates when unpausing https://github.com/nasa/openmct/pull/1600#discussion_r119931468 --- .../features/imagery/src/controllers/ImageryController.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/features/imagery/src/controllers/ImageryController.js b/platform/features/imagery/src/controllers/ImageryController.js index 7661136a1c..d9ea5c8478 100644 --- a/platform/features/imagery/src/controllers/ImageryController.js +++ b/platform/features/imagery/src/controllers/ImageryController.js @@ -89,7 +89,7 @@ define( // Update displayable values to reflect latest image telemetry ImageryController.prototype.updateValues = function (datum) { if (this.isPaused) { - this.nextValue = datum; + this.nextDatum = datum; return; } this.time = this.timeFormat.format(datum); @@ -122,8 +122,10 @@ define( ImageryController.prototype.paused = function (state) { if (arguments.length > 0 && state !== this.isPaused) { this.isPaused = state; - this.updateValues(this.nextValue); - delete this.nextValue; + if (this.nextDatum) { + this.updateValues(this.nextDatum); + delete this.nextDatum; + } } return this.isPaused; };