diff --git a/example/generator/bundle.json b/example/generator/bundle.json
index a13bbdc8f8..cdb4736957 100644
--- a/example/generator/bundle.json
+++ b/example/generator/bundle.json
@@ -34,6 +34,10 @@
{
"key": "time",
"name": "Time"
+ },
+ {
+ "key": "yesterday",
+ "name": "Yesterday"
}
],
"ranges": [
@@ -61,4 +65,4 @@
}
]
}
-}
\ No newline at end of file
+}
diff --git a/example/generator/src/SinewaveTelemetrySeries.js b/example/generator/src/SinewaveTelemetrySeries.js
index 5b7914a867..1e84034766 100644
--- a/example/generator/src/SinewaveTelemetrySeries.js
+++ b/example/generator/src/SinewaveTelemetrySeries.js
@@ -29,23 +29,25 @@ define(
function () {
"use strict";
- var firstObservedTime = Math.floor(Date.now() / 1000);
+ var ONE_DAY = 60 * 60 * 24,
+ firstObservedTime = Math.floor(Date.now() / 1000) - ONE_DAY;
/**
*
* @constructor
*/
function SinewaveTelemetrySeries(request) {
- var latestObservedTime = Math.floor(Date.now() / 1000),
+ var timeOffset = (request.domain === 'yesterday') ? ONE_DAY : 0,
+ latestTime = Math.floor(Date.now() / 1000) - timeOffset,
+ firstTime = firstObservedTime - timeOffset,
endTime = (request.end !== undefined) ?
- Math.floor(request.end / 1000) : latestObservedTime,
- count =
- Math.min(endTime, latestObservedTime) - firstObservedTime,
- period = request.period || 30,
+ Math.floor(request.end / 1000) : latestTime,
+ count = Math.min(endTime, latestTime) - firstTime,
+ period = +request.period || 30,
generatorData = {},
- offset = (request.start !== undefined) ?
- Math.floor(request.start / 1000) - firstObservedTime :
- 0;
+ requestStart = (request.start === undefined) ? firstTime :
+ Math.max(Math.floor(request.start / 1000), firstTime),
+ offset = requestStart - firstTime;
if (request.size !== undefined) {
offset = Math.max(offset, count - request.size);
@@ -56,8 +58,8 @@ define(
};
generatorData.getDomainValue = function (i, domain) {
- return (i + offset) * 1000 +
- (domain !== 'delta' ? (firstObservedTime * 1000) : 0);
+ return (i + offset) * 1000 + firstTime * 1000 -
+ (domain === 'yesterday' ? ONE_DAY : 0);
};
generatorData.getRangeValue = function (i, range) {
diff --git a/platform/features/conductor/bundle.json b/platform/features/conductor/bundle.json
index 2e4a7c652f..de903cfb93 100644
--- a/platform/features/conductor/bundle.json
+++ b/platform/features/conductor/bundle.json
@@ -23,7 +23,23 @@
{
"key": "conductorService",
"implementation": "ConductorService.js",
- "depends": [ "now" ]
+ "depends": [ "now", "TIME_CONDUCTOR_DOMAINS" ]
+ }
+ ],
+ "templates": [
+ {
+ "key": "time-conductor",
+ "templateUrl": "templates/time-conductor.html"
+ }
+ ],
+ "constants": [
+ {
+ "key": "TIME_CONDUCTOR_DOMAINS",
+ "value": [
+ { "key": "time", "name": "Time" },
+ { "key": "yesterday", "name": "Yesterday" }
+ ],
+ "comment": "Placeholder; to be replaced by inspection of available domains."
}
]
}
diff --git a/platform/features/conductor/res/templates/time-conductor.html b/platform/features/conductor/res/templates/time-conductor.html
new file mode 100644
index 0000000000..4126652d5b
--- /dev/null
+++ b/platform/features/conductor/res/templates/time-conductor.html
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/platform/features/conductor/src/ConductorRepresenter.js b/platform/features/conductor/src/ConductorRepresenter.js
index 9f9c6a291f..c6d18c9266 100644
--- a/platform/features/conductor/src/ConductorRepresenter.js
+++ b/platform/features/conductor/src/ConductorRepresenter.js
@@ -28,7 +28,7 @@ define(
var CONDUCTOR_HEIGHT = "100px",
TEMPLATE = [
- "",
+ "",
""
].join(''),
THROTTLE_MS = 200,
@@ -78,7 +78,8 @@ define(
function bounds(start, end) {
return {
start: conductor.displayStart(),
- end: conductor.displayEnd()
+ end: conductor.displayEnd(),
+ domain: conductor.domain()
};
}
@@ -89,12 +90,30 @@ define(
}
function updateConductorInner() {
- conductor.displayStart(conductorScope.conductor.inner.start);
- conductor.displayEnd(conductorScope.conductor.inner.end);
+ var innerBounds = conductorScope.ngModel.conductor.inner;
+ conductor.displayStart(innerBounds.start);
+ conductor.displayEnd(innerBounds.end);
lastObservedBounds = lastObservedBounds || bounds();
broadcastBounds();
}
+ function updateDomain(value) {
+ conductor.domain(value);
+ repScope.$broadcast('telemetry:display:bounds', bounds(
+ conductor.displayStart(),
+ conductor.displayEnd(),
+ conductor.domain()
+ ));
+ }
+
+ // telemetry domain metadata -> option for a select control
+ function makeOption(domainOption) {
+ return {
+ name: domainOption.name,
+ value: domainOption.key
+ };
+ }
+
broadcastBounds = this.throttle(function () {
var newlyObservedBounds = bounds();
@@ -107,12 +126,19 @@ define(
}
}, THROTTLE_MS);
- conductorScope.conductor = { outer: bounds(), inner: bounds() };
+ conductorScope.ngModel = {};
+ conductorScope.ngModel.conductor =
+ { outer: bounds(), inner: bounds() };
+ conductorScope.ngModel.options =
+ conductor.domainOptions().map(makeOption);
+ conductorScope.ngModel.domain = conductor.domain();
conductorScope
- .$watch('conductor.inner.start', updateConductorInner);
+ .$watch('ngModel.conductor.inner.start', updateConductorInner);
conductorScope
- .$watch('conductor.inner.end', updateConductorInner);
+ .$watch('ngModel.conductor.inner.end', updateConductorInner);
+ conductorScope
+ .$watch('ngModel.domain', updateDomain);
repScope.$on('telemetry:view', updateConductorInner);
};
diff --git a/platform/features/conductor/src/ConductorService.js b/platform/features/conductor/src/ConductorService.js
index 59cfa95e3c..3e281d2c1d 100644
--- a/platform/features/conductor/src/ConductorService.js
+++ b/platform/features/conductor/src/ConductorService.js
@@ -39,12 +39,15 @@ define(
* @param {Function} now a function which returns the current time
* as a UNIX timestamp, in milliseconds
*/
- function ConductorService(now) {
+ function ConductorService(now, domains) {
var initialEnd =
Math.ceil(now() / SIX_HOURS_IN_MS) * SIX_HOURS_IN_MS;
- this.conductor =
- new TimeConductor(initialEnd - ONE_DAY_IN_MS, initialEnd);
+ this.conductor = new TimeConductor(
+ initialEnd - ONE_DAY_IN_MS,
+ initialEnd,
+ domains
+ );
}
/**
diff --git a/platform/features/conductor/src/ConductorTelemetryDecorator.js b/platform/features/conductor/src/ConductorTelemetryDecorator.js
index ed16db7d1b..ab2d958d7e 100644
--- a/platform/features/conductor/src/ConductorTelemetryDecorator.js
+++ b/platform/features/conductor/src/ConductorTelemetryDecorator.js
@@ -44,12 +44,14 @@ define(
ConductorTelemetryDecorator.prototype.amendRequests = function (requests) {
var conductor = this.conductorService.getConductor(),
start = conductor.displayStart(),
- end = conductor.displayEnd();
+ end = conductor.displayEnd(),
+ domain = conductor.domain();
function amendRequest(request) {
request = request || {};
request.start = start;
request.end = end;
+ request.domain = domain;
return request;
}
diff --git a/platform/features/conductor/src/TimeConductor.js b/platform/features/conductor/src/TimeConductor.js
index 394d9b01bb..0fa0403fd9 100644
--- a/platform/features/conductor/src/TimeConductor.js
+++ b/platform/features/conductor/src/TimeConductor.js
@@ -40,8 +40,10 @@ define(
* @param {number} start the initial start time
* @param {number} end the initial end time
*/
- function TimeConductor(start, end) {
+ function TimeConductor(start, end, domains) {
this.range = { start: start, end: end };
+ this.domains = domains;
+ this.activeDomain = domains[0].key;
}
/**
@@ -68,6 +70,34 @@ define(
return this.range.end;
};
+ /**
+ * Get available domain options which can be used to bound time
+ * selection.
+ * @returns {TelemetryDomain[]} available domains
+ */
+ TimeConductor.prototype.domainOptions = function () {
+ return this.domains;
+ };
+
+ /**
+ * Get or set (if called with an argument) the active domain.
+ * @param {string} [key] the key identifying the domain choice
+ * @returns {TelemetryDomain} the active telemetry domain
+ */
+ TimeConductor.prototype.domain = function (key) {
+ function matchesKey(domain) {
+ return domain.key === key;
+ }
+
+ if (arguments.length > 0) {
+ if (!this.domains.some(matchesKey)) {
+ throw new Error("Unknown domain " + key);
+ }
+ this.activeDomain = key;
+ }
+ return this.activeDomain;
+ };
+
return TimeConductor;
}
);
diff --git a/platform/features/conductor/test/ConductorRepresenterSpec.js b/platform/features/conductor/test/ConductorRepresenterSpec.js
index 59fae1b4ee..5d78c8a720 100644
--- a/platform/features/conductor/test/ConductorRepresenterSpec.js
+++ b/platform/features/conductor/test/ConductorRepresenterSpec.js
@@ -21,12 +21,9 @@
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,waitsFor,afterEach,jasmine*/
-/**
- * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015.
- */
define(
- ["../src/ConductorRepresenter"],
- function (ConductorRepresenter) {
+ ["../src/ConductorRepresenter", "./TestTimeConductor"],
+ function (ConductorRepresenter, TestTimeConductor) {
"use strict";
var SCOPE_METHODS = [
@@ -77,10 +74,7 @@ define(
testViews = [ { someKey: "some value" } ];
mockScope = jasmine.createSpyObj('scope', SCOPE_METHODS);
mockElement = jasmine.createSpyObj('element', ELEMENT_METHODS);
- mockConductor = jasmine.createSpyObj(
- 'conductor',
- [ 'displayStart', 'displayEnd' ]
- );
+ mockConductor = new TestTimeConductor();
mockCompiledTemplate = jasmine.createSpy('template');
mockNewScope = jasmine.createSpyObj('newScope', SCOPE_METHODS);
mockNewElement = jasmine.createSpyObj('newElement', ELEMENT_METHODS);
@@ -135,11 +129,12 @@ define(
it("exposes conductor state in scope", function () {
mockConductor.displayStart.andReturn(1977);
mockConductor.displayEnd.andReturn(1984);
+ mockConductor.domain.andReturn('d');
representer.represent(testViews[0], {});
- expect(mockNewScope.conductor).toEqual({
- inner: { start: 1977, end: 1984 },
- outer: { start: 1977, end: 1984 }
+ expect(mockNewScope.ngModel.conductor).toEqual({
+ inner: { start: 1977, end: 1984, domain: 'd' },
+ outer: { start: 1977, end: 1984, domain: 'd' }
});
});
@@ -151,17 +146,27 @@ define(
representer.represent(testViews[0], {});
- mockNewScope.conductor = testState;
+ mockNewScope.ngModel.conductor = testState;
- fireWatch(mockNewScope, 'conductor.inner.start', testState.inner.start);
+ fireWatch(
+ mockNewScope,
+ 'ngModel.conductor.inner.start',
+ testState.inner.start
+ );
expect(mockConductor.displayStart).toHaveBeenCalledWith(42);
- fireWatch(mockNewScope, 'conductor.inner.end', testState.inner.end);
+ fireWatch(
+ mockNewScope,
+ 'ngModel.conductor.inner.end',
+ testState.inner.end
+ );
expect(mockConductor.displayEnd).toHaveBeenCalledWith(1984);
});
describe("when bounds are changing", function () {
- var mockThrottledFn = jasmine.createSpy('throttledFn'),
+ var startWatch = "ngModel.conductor.inner.start",
+ endWatch = "ngModel.conductor.inner.end",
+ mockThrottledFn = jasmine.createSpy('throttledFn'),
testBounds;
function fireThrottledFn() {
@@ -172,7 +177,7 @@ define(
mockThrottle.andReturn(mockThrottledFn);
representer.represent(testViews[0], {});
testBounds = { start: 0, end: 1000 };
- mockNewScope.conductor.inner = testBounds;
+ mockNewScope.ngModel.conductor.inner = testBounds;
mockConductor.displayStart.andCallFake(function () {
return testBounds.start;
});
@@ -184,14 +189,14 @@ define(
it("does not broadcast while bounds are changing", function () {
expect(mockScope.$broadcast).not.toHaveBeenCalled();
testBounds.start = 100;
- fireWatch(mockNewScope, 'conductor.inner.start', testBounds.start);
+ fireWatch(mockNewScope, startWatch, testBounds.start);
testBounds.end = 500;
- fireWatch(mockNewScope, 'conductor.inner.end', testBounds.end);
+ fireWatch(mockNewScope, endWatch, testBounds.end);
fireThrottledFn();
testBounds.start = 200;
- fireWatch(mockNewScope, 'conductor.inner.start', testBounds.start);
+ fireWatch(mockNewScope, startWatch, testBounds.start);
testBounds.end = 400;
- fireWatch(mockNewScope, 'conductor.inner.end', testBounds.end);
+ fireWatch(mockNewScope, endWatch, testBounds.end);
fireThrottledFn();
expect(mockScope.$broadcast).not.toHaveBeenCalled();
});
@@ -199,17 +204,56 @@ define(
it("does broadcast when bounds have stabilized", function () {
expect(mockScope.$broadcast).not.toHaveBeenCalled();
testBounds.start = 100;
- fireWatch(mockNewScope, 'conductor.inner.start', testBounds.start);
+ fireWatch(mockNewScope, startWatch, testBounds.start);
testBounds.end = 500;
- fireWatch(mockNewScope, 'conductor.inner.end', testBounds.end);
+ fireWatch(mockNewScope, endWatch, testBounds.end);
fireThrottledFn();
- fireWatch(mockNewScope, 'conductor.inner.start', testBounds.start);
- fireWatch(mockNewScope, 'conductor.inner.end', testBounds.end);
+ fireWatch(mockNewScope, startWatch, testBounds.start);
+ fireWatch(mockNewScope, endWatch, testBounds.end);
fireThrottledFn();
expect(mockScope.$broadcast).toHaveBeenCalled();
});
});
+ it("exposes domain selection in scope", function () {
+ representer.represent(testViews[0], null);
+
+ expect(mockNewScope.ngModel.domain)
+ .toEqual(mockConductor.domain());
+ });
+
+ it("exposes domain options in scope", function () {
+ representer.represent(testViews[0], null);
+
+ mockConductor.domainOptions().forEach(function (option, i) {
+ expect(mockNewScope.ngModel.options[i].value)
+ .toEqual(option.key);
+ expect(mockNewScope.ngModel.options[i].name)
+ .toEqual(option.name);
+ });
+ });
+
+ it("updates domain selection from scope", function () {
+ var choice;
+ representer.represent(testViews[0], null);
+
+ // Choose a domain that isn't currently selected
+ mockNewScope.ngModel.options.forEach(function (option) {
+ if (option.value !== mockNewScope.ngModel.domain) {
+ choice = option.value;
+ }
+ });
+
+ expect(mockConductor.domain)
+ .not.toHaveBeenCalledWith(choice);
+
+ mockNewScope.ngModel.domain = choice;
+ fireWatch(mockNewScope, "ngModel.domain", choice);
+
+ expect(mockConductor.domain)
+ .toHaveBeenCalledWith(choice);
+ });
+
});
}
);
diff --git a/platform/features/conductor/test/ConductorServiceSpec.js b/platform/features/conductor/test/ConductorServiceSpec.js
index 640212540c..08080658a2 100644
--- a/platform/features/conductor/test/ConductorServiceSpec.js
+++ b/platform/features/conductor/test/ConductorServiceSpec.js
@@ -21,9 +21,6 @@
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/
-/**
- * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015.
- */
define(
["../src/ConductorService"],
function (ConductorService) {
@@ -38,7 +35,10 @@ define(
beforeEach(function () {
mockNow = jasmine.createSpy('now');
mockNow.andReturn(TEST_NOW);
- conductorService = new ConductorService(mockNow);
+ conductorService = new ConductorService(mockNow, [
+ { key: "d1", name: "Domain #1" },
+ { key: "d2", name: "Domain #2" }
+ ]);
});
it("initializes a time conductor around the current time", function () {
diff --git a/platform/features/conductor/test/ConductorTelemetryDecoratorSpec.js b/platform/features/conductor/test/ConductorTelemetryDecoratorSpec.js
index 9a5efc2448..6e768419c1 100644
--- a/platform/features/conductor/test/ConductorTelemetryDecoratorSpec.js
+++ b/platform/features/conductor/test/ConductorTelemetryDecoratorSpec.js
@@ -23,8 +23,8 @@
define(
- ["../src/ConductorTelemetryDecorator"],
- function (ConductorTelemetryDecorator) {
+ ["../src/ConductorTelemetryDecorator", "./TestTimeConductor"],
+ function (ConductorTelemetryDecorator, TestTimeConductor) {
"use strict";
describe("ConductorTelemetryDecorator", function () {
@@ -54,10 +54,7 @@ define(
'conductorService',
['getConductor']
);
- mockConductor = jasmine.createSpyObj(
- 'conductor',
- [ 'queryStart', 'queryEnd', 'displayStart', 'displayEnd' ]
- );
+ mockConductor = new TestTimeConductor();
mockPromise = jasmine.createSpyObj(
'promise',
['then']
@@ -78,10 +75,9 @@ define(
return j * j * j;
});
- mockConductor.queryStart.andReturn(-12321);
- mockConductor.queryEnd.andReturn(-12321);
mockConductor.displayStart.andReturn(42);
mockConductor.displayEnd.andReturn(1977);
+ mockConductor.domain.andReturn("testDomain");
decorator = new ConductorTelemetryDecorator(
mockConductorService,
@@ -89,24 +85,72 @@ define(
);
});
- it("adds display start/end times to historical requests", function () {
+
+ describe("decorates historical requests", function () {
+ var request;
+
+ beforeEach(function () {
+ decorator.requestTelemetry([{ someKey: "some value" }]);
+ request = mockTelemetryService.requestTelemetry
+ .mostRecentCall.args[0][0];
+ });
+
+ it("with start times", function () {
+ expect(request.start).toEqual(mockConductor.displayStart());
+ });
+
+ it("with end times", function () {
+ expect(request.end).toEqual(mockConductor.displayEnd());
+ });
+
+ it("with domain selection", function () {
+ expect(request.domain).toEqual(mockConductor.domain());
+ });
+ });
+
+ describe("decorates subscription requests", function () {
+ var request;
+
+ beforeEach(function () {
+ var mockCallback = jasmine.createSpy('callback');
+ decorator.subscribe(mockCallback, [{ someKey: "some value" }]);
+ request = mockTelemetryService.subscribe
+ .mostRecentCall.args[1][0];
+ });
+
+ it("with start times", function () {
+ expect(request.start).toEqual(mockConductor.displayStart());
+ });
+
+ it("with end times", function () {
+ expect(request.end).toEqual(mockConductor.displayEnd());
+ });
+
+ it("with domain selection", function () {
+ expect(request.domain).toEqual(mockConductor.domain());
+ });
+ });
+
+ it("adds display start/end times & domain selection to historical requests", function () {
decorator.requestTelemetry([{ someKey: "some value" }]);
expect(mockTelemetryService.requestTelemetry)
.toHaveBeenCalledWith([{
someKey: "some value",
start: mockConductor.displayStart(),
- end: mockConductor.displayEnd()
+ end: mockConductor.displayEnd(),
+ domain: jasmine.any(String)
}]);
});
- it("adds display start/end times to subscription requests", function () {
+ it("adds display start/end times & domain selection to subscription requests", function () {
var mockCallback = jasmine.createSpy('callback');
decorator.subscribe(mockCallback, [{ someKey: "some value" }]);
expect(mockTelemetryService.subscribe)
.toHaveBeenCalledWith(jasmine.any(Function), [{
someKey: "some value",
start: mockConductor.displayStart(),
- end: mockConductor.displayEnd()
+ end: mockConductor.displayEnd(),
+ domain: jasmine.any(String)
}]);
});
diff --git a/platform/features/conductor/test/TestTimeConductor.js b/platform/features/conductor/test/TestTimeConductor.js
new file mode 100644
index 0000000000..01fed0c8fd
--- /dev/null
+++ b/platform/features/conductor/test/TestTimeConductor.js
@@ -0,0 +1,50 @@
+/*****************************************************************************
+ * 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,describe,it,expect,beforeEach,waitsFor,jasmine,spyOn*/
+
+define(
+ ["../src/TimeConductor"],
+ function (TimeConductor) {
+ 'use strict';
+
+ function TestTimeConductor() {
+ var self = this;
+
+ TimeConductor.apply(this, [
+ 402514200000,
+ 444546000000,
+ [
+ { key: "domain0", name: "Domain #1" },
+ { key: "domain1", name: "Domain #2" }
+ ]
+ ]);
+
+ Object.keys(TimeConductor.prototype).forEach(function (method) {
+ spyOn(self, method).andCallThrough();
+ });
+ }
+
+ TestTimeConductor.prototype = TimeConductor.prototype;
+
+ return TestTimeConductor;
+ }
+);
diff --git a/platform/features/conductor/test/TimeConductorSpec.js b/platform/features/conductor/test/TimeConductorSpec.js
index 1e3859bf60..c9336a93b0 100644
--- a/platform/features/conductor/test/TimeConductorSpec.js
+++ b/platform/features/conductor/test/TimeConductorSpec.js
@@ -21,9 +21,6 @@
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/
-/**
- * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015.
- */
define(
["../src/TimeConductor"],
function (TimeConductor) {
@@ -32,12 +29,17 @@ define(
describe("TimeConductor", function () {
var testStart,
testEnd,
+ testDomains,
conductor;
beforeEach(function () {
testStart = 42;
testEnd = 12321;
- conductor = new TimeConductor(testStart, testEnd);
+ testDomains = [
+ { key: "d1", name: "Domain #1" },
+ { key: "d2", name: "Domain #2" }
+ ];
+ conductor = new TimeConductor(testStart, testEnd, testDomains);
});
it("provides accessors for query/display start/end times", function () {
@@ -52,6 +54,25 @@ define(
expect(conductor.displayEnd()).toEqual(4);
});
+ it("exposes domain options", function () {
+ expect(conductor.domainOptions()).toEqual(testDomains);
+ });
+
+ it("exposes the current domain choice", function () {
+ expect(conductor.domain()).toEqual(testDomains[0].key);
+ });
+
+ it("allows the domain choice to be changed", function () {
+ conductor.domain(testDomains[1].key);
+ expect(conductor.domain()).toEqual(testDomains[1].key);
+ });
+
+ it("throws an error on attempts to set an invalid domain", function () {
+ expect(function () {
+ conductor.domain("invalid-domain");
+ }).toThrow();
+ });
+
});
}
);
diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js
index f608f490f8..77c655e2cb 100644
--- a/platform/features/layout/src/FixedController.js
+++ b/platform/features/layout/src/FixedController.js
@@ -105,11 +105,13 @@ define(
index
);
- setDisplayedValue(
- telemetryObject,
- telemetrySeries.getRangeValue(index),
- limit && datum && limit.evaluate(datum)
- );
+ if (index >= 0) {
+ setDisplayedValue(
+ telemetryObject,
+ telemetrySeries.getRangeValue(index),
+ limit && datum && limit.evaluate(datum)
+ );
+ }
}
// Update the displayed value for this object
diff --git a/platform/telemetry/src/TelemetryHandle.js b/platform/telemetry/src/TelemetryHandle.js
index ae25fd9bfa..ff77d7b9e0 100644
--- a/platform/telemetry/src/TelemetryHandle.js
+++ b/platform/telemetry/src/TelemetryHandle.js
@@ -110,20 +110,23 @@ define(
* Get the latest telemetry datum for this domain object. This
* will be from real-time telemetry, unless an index is specified,
* in which case it will be pulled from the historical telemetry
- * series at the specified index.
+ * series at the specified index. If there is no latest available
+ * datum, this will return undefined.
*
* @param {DomainObject} domainObject the object of interest
* @param {number} [index] the index of the data of interest
* @returns {TelemetryDatum} the most recent datum
*/
self.getDatum = function (telemetryObject, index) {
+ function makeNewDatum(series) {
+ return series ?
+ subscription.makeDatum(telemetryObject, series, index) :
+ undefined;
+ }
+
return typeof index !== 'number' ?
subscription.getDatum(telemetryObject) :
- subscription.makeDatum(
- telemetryObject,
- this.getSeries(telemetryObject),
- index
- );
+ makeNewDatum(this.getSeries(telemetryObject));
};
return self;