diff --git a/Procfile b/Procfile
index aa6094edfe..1e13b4ae05 100644
--- a/Procfile
+++ b/Procfile
@@ -1 +1 @@
-web: node app.js --port $PORT --include example/localstorage
\ No newline at end of file
+web: node app.js --port $PORT
diff --git a/docs/gendocs.js b/docs/gendocs.js
index 329a9b607f..cd61b9a9bf 100644
--- a/docs/gendocs.js
+++ b/docs/gendocs.js
@@ -30,7 +30,8 @@
var CONSTANTS = {
DIAGRAM_WIDTH: 800,
DIAGRAM_HEIGHT: 500
- };
+ },
+ TOC_HEAD = "# Table of Contents";
GLOBAL.window = GLOBAL.window || GLOBAL; // nomnoml expects window to be defined
(function () {
@@ -44,6 +45,7 @@ GLOBAL.window = GLOBAL.window || GLOBAL; // nomnoml expects window to be define
split = require("split"),
stream = require("stream"),
nomnoml = require('nomnoml'),
+ toc = require("markdown-toc"),
Canvas = require('canvas'),
options = require("minimist")(process.argv.slice(2));
@@ -110,6 +112,9 @@ GLOBAL.window = GLOBAL.window || GLOBAL; // nomnoml expects window to be define
done();
};
transform._flush = function (done) {
+ // Prepend table of contents
+ markdown =
+ [ TOC_HEAD, toc(markdown).content, "", markdown ].join("\n");
this.push("
\n");
this.push(marked(markdown));
this.push("\n\n");
@@ -133,8 +138,8 @@ GLOBAL.window = GLOBAL.window || GLOBAL; // nomnoml expects window to be define
customRenderer.link = function (href, title, text) {
// ...but only if they look like relative paths
return (href || "").indexOf(":") === -1 && href[0] !== "/" ?
- renderer.link(href.replace(/\.md/, ".html"), title, text) :
- renderer.link.apply(renderer, arguments);
+ renderer.link(href.replace(/\.md/, ".html"), title, text) :
+ renderer.link.apply(renderer, arguments);
};
return customRenderer;
}
diff --git a/package.json b/package.json
index a1ac01f437..c96642129c 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,8 @@
"split": "^1.0.0",
"mkdirp": "^0.5.1",
"nomnoml": "^0.0.3",
- "canvas": "^1.2.7"
+ "canvas": "^1.2.7",
+ "markdown-toc": "^0.11.7"
},
"scripts": {
"start": "node app.js",
diff --git a/platform/commonUI/browse/bundle.json b/platform/commonUI/browse/bundle.json
index e3284d99b5..bc42a33c1f 100644
--- a/platform/commonUI/browse/bundle.json
+++ b/platform/commonUI/browse/bundle.json
@@ -1,4 +1,9 @@
{
+ "configuration": {
+ "paths": {
+ "uuid": "uuid"
+ }
+ },
"extensions": {
"routes": [
{
diff --git a/platform/commonUI/browse/src/creation/CreationService.js b/platform/commonUI/browse/src/creation/CreationService.js
index 667863ef20..2b059724b3 100644
--- a/platform/commonUI/browse/src/creation/CreationService.js
+++ b/platform/commonUI/browse/src/creation/CreationService.js
@@ -25,7 +25,7 @@
* Module defining CreateService. Created by vwoeltje on 11/10/14.
*/
define(
- ["../../lib/uuid"],
+ ["uuid"],
function (uuid) {
"use strict";
diff --git a/platform/commonUI/general/res/templates/controls/time-controller.html b/platform/commonUI/general/res/templates/controls/time-controller.html
index ff142ea189..300e56c381 100644
--- a/platform/commonUI/general/res/templates/controls/time-controller.html
+++ b/platform/commonUI/general/res/templates/controls/time-controller.html
@@ -19,84 +19,90 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
-
\ No newline at end of file
+
+
diff --git a/platform/commonUI/general/src/controllers/TimeRangeController.js b/platform/commonUI/general/src/controllers/TimeRangeController.js
index 55bddd712f..d4fb21be08 100644
--- a/platform/commonUI/general/src/controllers/TimeRangeController.js
+++ b/platform/commonUI/general/src/controllers/TimeRangeController.js
@@ -26,9 +26,8 @@ define(
function (moment) {
"use strict";
- var
- DATE_FORMAT = "YYYY-MM-DD HH:mm:ss",
- TICK_SPACING_PX = 150;
+ var DATE_FORMAT = "YYYY-MM-DD HH:mm:ss",
+ TICK_SPACING_PX = 150;
/**
* @memberof platform/commonUI/general
@@ -44,6 +43,15 @@ define(
return moment.utc(ts).format(DATE_FORMAT);
}
+ function parseTimestamp(text) {
+ var m = moment.utc(text, DATE_FORMAT);
+ if (m.isValid()) {
+ return m.valueOf();
+ } else {
+ throw new Error("Could not parse " + text);
+ }
+ }
+
// From 0.0-1.0 to "0%"-"1%"
function toPercent(p) {
return (100 * p) + "%";
@@ -93,6 +101,25 @@ define(
return { start: bounds.start, end: bounds.end };
}
+ function updateBoundsTextForProperty(ngModel, property) {
+ try {
+ if (!$scope.boundsModel[property] ||
+ parseTimestamp($scope.boundsModel[property]) !==
+ ngModel.outer[property]) {
+ $scope.boundsModel[property] =
+ formatTimestamp(ngModel.outer[property]);
+ }
+ } catch (e) {
+ // User-entered text is invalid, so leave it be
+ // until they fix it.
+ }
+ }
+
+ function updateBoundsText(ngModel) {
+ updateBoundsTextForProperty(ngModel, 'start');
+ updateBoundsTextForProperty(ngModel, 'end');
+ }
+
function updateViewFromModel(ngModel) {
var t = now();
@@ -101,8 +128,7 @@ define(
ngModel.inner = ngModel.inner || copyBounds(ngModel.outer);
// First, dates for the date pickers for outer bounds
- $scope.startOuterDate = new Date(ngModel.outer.start);
- $scope.endOuterDate = new Date(ngModel.outer.end);
+ updateBoundsText(ngModel);
// Then various updates for the inner span
updateViewForInnerSpanFromModel(ngModel);
@@ -178,6 +204,8 @@ define(
function updateOuterStart(t) {
var ngModel = $scope.ngModel;
+ ngModel.outer.start = t;
+
ngModel.outer.end = Math.max(
ngModel.outer.start + outerMinimumSpan,
ngModel.outer.end
@@ -190,14 +218,15 @@ define(
ngModel.inner.end
);
- $scope.startOuterText = formatTimestamp(t);
-
updateViewForInnerSpanFromModel(ngModel);
+ updateTicks();
}
function updateOuterEnd(t) {
var ngModel = $scope.ngModel;
+ ngModel.outer.end = t;
+
ngModel.outer.start = Math.min(
ngModel.outer.end - outerMinimumSpan,
ngModel.outer.start
@@ -210,9 +239,40 @@ define(
ngModel.inner.start
);
- $scope.endOuterText = formatTimestamp(t);
-
updateViewForInnerSpanFromModel(ngModel);
+ updateTicks();
+ }
+
+ function updateStartFromText(value) {
+ try {
+ updateOuterStart(parseTimestamp(value));
+ updateBoundsTextForProperty($scope.ngModel, 'end');
+ $scope.boundsModel.startValid = true;
+ } catch (e) {
+ $scope.boundsModel.startValid = false;
+ return;
+ }
+ }
+
+ function updateEndFromText(value) {
+ try {
+ updateOuterEnd(parseTimestamp(value));
+ updateBoundsTextForProperty($scope.ngModel, 'start');
+ $scope.boundsModel.endValid = true;
+ } catch (e) {
+ $scope.boundsModel.endValid = false;
+ return;
+ }
+ }
+
+ function updateStartFromPicker(value) {
+ updateOuterStart(value);
+ updateBoundsText($scope.ngModel);
+ }
+
+ function updateEndFromPicker(value) {
+ updateOuterEnd(value);
+ updateBoundsText($scope.ngModel);
}
$scope.startLeftDrag = startLeftDrag;
@@ -224,14 +284,17 @@ define(
$scope.state = false;
$scope.ticks = [];
+ $scope.boundsModel = {};
// Initialize scope to defaults
updateViewFromModel($scope.ngModel);
$scope.$watchCollection("ngModel", updateViewFromModel);
$scope.$watch("spanWidth", updateSpanWidth);
- $scope.$watch("ngModel.outer.start", updateOuterStart);
- $scope.$watch("ngModel.outer.end", updateOuterEnd);
+ $scope.$watch("ngModel.outer.start", updateStartFromPicker);
+ $scope.$watch("ngModel.outer.end", updateEndFromPicker);
+ $scope.$watch("boundsModel.start", updateStartFromText);
+ $scope.$watch("boundsModel.end", updateEndFromText);
}
return TimeConductorController;
diff --git a/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js b/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js
index 9d7a6a9f52..91d3ecb9db 100644
--- a/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js
+++ b/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js
@@ -22,8 +22,8 @@
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
define(
- ["../../src/controllers/TimeRangeController"],
- function (TimeRangeController) {
+ ["../../src/controllers/TimeRangeController", "moment"],
+ function (TimeRangeController, moment) {
"use strict";
var SEC = 1000,
@@ -166,8 +166,72 @@ define(
expect(mockScope.ngModel.inner.end)
.toBeGreaterThan(mockScope.ngModel.inner.start);
});
+
+ describe("by typing", function () {
+ it("updates models", function () {
+ var newStart = "1977-05-25 17:30:00",
+ newEnd = "2015-12-18 03:30:00";
+
+ mockScope.boundsModel.start = newStart;
+ fireWatch("boundsModel.start", newStart);
+ expect(mockScope.ngModel.outer.start)
+ .toEqual(moment.utc(newStart).valueOf());
+ expect(mockScope.boundsModel.startValid)
+ .toBeTruthy();
+
+ mockScope.boundsModel.end = newEnd;
+ fireWatch("boundsModel.end", newEnd);
+ expect(mockScope.ngModel.outer.end)
+ .toEqual(moment.utc(newEnd).valueOf());
+ expect(mockScope.boundsModel.endValid)
+ .toBeTruthy();
+ });
+
+ it("displays error state", function () {
+ var newStart = "Not a date",
+ newEnd = "Definitely not a date",
+ oldStart = mockScope.ngModel.outer.start,
+ oldEnd = mockScope.ngModel.outer.end;
+
+ mockScope.boundsModel.start = newStart;
+ fireWatch("boundsModel.start", newStart);
+ expect(mockScope.ngModel.outer.start)
+ .toEqual(oldStart);
+ expect(mockScope.boundsModel.startValid)
+ .toBeFalsy();
+
+ mockScope.boundsModel.end = newEnd;
+ fireWatch("boundsModel.end", newEnd);
+ expect(mockScope.ngModel.outer.end)
+ .toEqual(oldEnd);
+ expect(mockScope.boundsModel.endValid)
+ .toBeFalsy();
+ });
+
+ it("does not modify user input", function () {
+ // Don't want the controller "fixing" bad or
+ // irregularly-formatted input out from under
+ // the user's fingertips.
+ var newStart = "Not a date",
+ newEnd = "2015-3-3 01:02:04",
+ oldStart = mockScope.ngModel.outer.start,
+ oldEnd = mockScope.ngModel.outer.end;
+
+ mockScope.boundsModel.start = newStart;
+ fireWatch("boundsModel.start", newStart);
+ expect(mockScope.boundsModel.start)
+ .toEqual(newStart);
+
+ mockScope.boundsModel.end = newEnd;
+ fireWatch("boundsModel.end", newEnd);
+ expect(mockScope.boundsModel.end)
+ .toEqual(newEnd);
+ });
+ });
});
+
+
});
}
);
diff --git a/platform/entanglement/bundle.json b/platform/entanglement/bundle.json
index 61c3d90539..d8cde0ada6 100644
--- a/platform/entanglement/bundle.json
+++ b/platform/entanglement/bundle.json
@@ -30,6 +30,14 @@
"category": "contextual",
"implementation": "actions/LinkAction.js",
"depends": ["locationService", "linkService"]
+ },
+ {
+ "key": "follow",
+ "name": "Go To Original",
+ "description": "Go to the original, un-linked instance of this object.",
+ "glyph": "\u00F4",
+ "category": "contextual",
+ "implementation": "actions/GoToOriginalAction.js"
}
],
"components": [
@@ -52,7 +60,8 @@
"key": "location",
"name": "Location Capability",
"description": "Provides a capability for retrieving the location of an object based upon it's context.",
- "implementation": "capabilities/LocationCapability"
+ "implementation": "capabilities/LocationCapability",
+ "depends": [ "$q", "$injector" ]
}
],
"services": [
diff --git a/platform/entanglement/src/actions/GoToOriginalAction.js b/platform/entanglement/src/actions/GoToOriginalAction.js
new file mode 100644
index 0000000000..9722915ad6
--- /dev/null
+++ b/platform/entanglement/src/actions/GoToOriginalAction.js
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * 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 */
+define(
+ function () {
+ "use strict";
+
+ /**
+ * Implements the "Go To Original" action, which follows a link back
+ * to an original instance of an object.
+ *
+ * @implements {Action}
+ * @constructor
+ * @private
+ * @memberof platform/entanglement
+ * @param {ActionContext} context the context in which the action
+ * will be performed
+ */
+ function GoToOriginalAction(context) {
+ this.domainObject = context.domainObject;
+ }
+
+ GoToOriginalAction.prototype.perform = function () {
+ return this.domainObject.getCapability("location").getOriginal()
+ .then(function (originalObject) {
+ var actionCapability =
+ originalObject.getCapability("action");
+ return actionCapability &&
+ actionCapability.perform("navigate");
+ });
+ };
+
+ GoToOriginalAction.appliesTo = function (context) {
+ var domainObject = context.domainObject;
+ return domainObject && domainObject.hasCapability("location")
+ && domainObject.getCapability("location").isLink();
+ };
+
+ return GoToOriginalAction;
+ }
+);
+
diff --git a/platform/entanglement/src/capabilities/LocationCapability.js b/platform/entanglement/src/capabilities/LocationCapability.js
index 17d678f57e..27e1f74c74 100644
--- a/platform/entanglement/src/capabilities/LocationCapability.js
+++ b/platform/entanglement/src/capabilities/LocationCapability.js
@@ -1,3 +1,25 @@
+/*****************************************************************************
+ * 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 */
define(
@@ -12,11 +34,41 @@ define(
*
* @constructor
*/
- function LocationCapability(domainObject) {
+ function LocationCapability($q, $injector, domainObject) {
this.domainObject = domainObject;
+ this.$q = $q;
+ this.$injector = $injector;
return this;
}
+ /**
+ * Get an instance of this domain object in its original location.
+ *
+ * @returns {Promise.} a promise for the original
+ * instance of this domain object
+ */
+ LocationCapability.prototype.getOriginal = function () {
+ var id;
+
+ if (this.isOriginal()) {
+ return this.$q.when(this.domainObject);
+ }
+
+ id = this.domainObject.getId();
+
+ this.objectService =
+ this.objectService || this.$injector.get("objectService");
+
+ // Assume that an object will be correctly contextualized when
+ // loaded directly from the object service; this is true
+ // so long as LocatingObjectDecorator is present, and that
+ // decorator is also contained in this bundle.
+ return this.objectService.getObjects([id])
+ .then(function (objects) {
+ return objects[id];
+ });
+ };
+
/**
* Set the primary location (the parent id) of the current domain
* object.
@@ -78,10 +130,6 @@ define(
return !this.isLink();
};
- function createLocationCapability(domainObject) {
- return new LocationCapability(domainObject);
- }
-
- return createLocationCapability;
+ return LocationCapability;
}
);
diff --git a/platform/entanglement/test/actions/GoToOriginalActionSpec.js b/platform/entanglement/test/actions/GoToOriginalActionSpec.js
new file mode 100644
index 0000000000..40c2f213ce
--- /dev/null
+++ b/platform/entanglement/test/actions/GoToOriginalActionSpec.js
@@ -0,0 +1,95 @@
+/*****************************************************************************
+ * 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,beforeEach,it,jasmine,expect */
+
+define(
+ [
+ '../../src/actions/GoToOriginalAction',
+ '../DomainObjectFactory',
+ '../ControlledPromise'
+ ],
+ function (GoToOriginalAction, domainObjectFactory, ControlledPromise) {
+ 'use strict';
+
+ describe("The 'go to original' action", function () {
+ var testContext,
+ originalDomainObject,
+ mockLocationCapability,
+ mockOriginalActionCapability,
+ originalPromise,
+ action;
+
+ beforeEach(function () {
+ mockLocationCapability = jasmine.createSpyObj(
+ 'location',
+ [ 'isLink', 'isOriginal', 'getOriginal' ]
+ );
+ mockOriginalActionCapability = jasmine.createSpyObj(
+ 'action',
+ [ 'perform', 'getActions' ]
+ );
+ originalPromise = new ControlledPromise();
+ mockLocationCapability.getOriginal.andReturn(originalPromise);
+ mockLocationCapability.isLink.andReturn(true);
+ mockLocationCapability.isOriginal.andCallFake(function () {
+ return !mockLocationCapability.isLink();
+ });
+ testContext = {
+ domainObject: domainObjectFactory({
+ capabilities: {
+ location: mockLocationCapability
+ }
+ })
+ };
+ originalDomainObject = domainObjectFactory({
+ capabilities: {
+ action: mockOriginalActionCapability
+ }
+ });
+
+ action = new GoToOriginalAction(testContext);
+ });
+
+ it("is applicable to links", function () {
+ expect(GoToOriginalAction.appliesTo(testContext))
+ .toBeTruthy();
+ });
+
+ it("is not applicable to originals", function () {
+ mockLocationCapability.isLink.andReturn(false);
+ expect(GoToOriginalAction.appliesTo(testContext))
+ .toBeFalsy();
+ });
+
+ it("navigates to original objects when performed", function () {
+ expect(mockOriginalActionCapability.perform)
+ .not.toHaveBeenCalled();
+ action.perform();
+ originalPromise.resolve(originalDomainObject);
+ expect(mockOriginalActionCapability.perform)
+ .toHaveBeenCalledWith('navigate');
+ });
+
+ });
+ }
+);
diff --git a/platform/entanglement/test/capabilities/LocationCapabilitySpec.js b/platform/entanglement/test/capabilities/LocationCapabilitySpec.js
index 9cbfcc1bea..442bfe20aa 100644
--- a/platform/entanglement/test/capabilities/LocationCapabilitySpec.js
+++ b/platform/entanglement/test/capabilities/LocationCapabilitySpec.js
@@ -1,3 +1,25 @@
+/*****************************************************************************
+ * 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,jasmine */
define(
@@ -7,6 +29,7 @@ define(
'../ControlledPromise'
],
function (LocationCapability, domainObjectFactory, ControlledPromise) {
+ 'use strict';
describe("LocationCapability", function () {
@@ -14,13 +37,17 @@ define(
var locationCapability,
persistencePromise,
mutationPromise,
+ mockQ,
+ mockInjector,
+ mockObjectService,
domainObject;
beforeEach(function () {
domainObject = domainObjectFactory({
+ id: "testObject",
capabilities: {
context: {
- getParent: function() {
+ getParent: function () {
return domainObjectFactory({id: 'root'});
}
},
@@ -35,6 +62,11 @@ define(
}
});
+ mockQ = jasmine.createSpyObj("$q", ["when"]);
+ mockInjector = jasmine.createSpyObj("$injector", ["get"]);
+ mockObjectService =
+ jasmine.createSpyObj("objectService", ["getObjects"]);
+
persistencePromise = new ControlledPromise();
domainObject.capabilities.persistence.persist.andReturn(
persistencePromise
@@ -49,7 +81,11 @@ define(
}
);
- locationCapability = new LocationCapability(domainObject);
+ locationCapability = new LocationCapability(
+ mockQ,
+ mockInjector,
+ domainObject
+ );
});
it("returns contextual location", function () {
@@ -88,6 +124,57 @@ define(
expect(whenComplete).toHaveBeenCalled();
});
+ describe("when used to load an original instance", function () {
+ var objectPromise,
+ qPromise,
+ originalObjects,
+ mockCallback;
+
+ function resolvePromises() {
+ if (mockQ.when.calls.length > 0) {
+ qPromise.resolve(mockQ.when.mostRecentCall.args[0]);
+ }
+ if (mockObjectService.getObjects.calls.length > 0) {
+ objectPromise.resolve(originalObjects);
+ }
+ }
+
+ beforeEach(function () {
+ objectPromise = new ControlledPromise();
+ qPromise = new ControlledPromise();
+ originalObjects = {
+ testObject: domainObjectFactory()
+ };
+
+ mockInjector.get.andCallFake(function (key) {
+ return key === 'objectService' && mockObjectService;
+ });
+ mockObjectService.getObjects.andReturn(objectPromise);
+ mockQ.when.andReturn(qPromise);
+
+ mockCallback = jasmine.createSpy('callback');
+ });
+
+ it("provides originals directly", function () {
+ domainObject.model.location = 'root';
+ locationCapability.getOriginal().then(mockCallback);
+ expect(mockCallback).not.toHaveBeenCalled();
+ resolvePromises();
+ expect(mockCallback)
+ .toHaveBeenCalledWith(domainObject);
+ });
+
+ it("loads from the object service for links", function () {
+ domainObject.model.location = 'some-other-root';
+ locationCapability.getOriginal().then(mockCallback);
+ expect(mockCallback).not.toHaveBeenCalled();
+ resolvePromises();
+ expect(mockCallback)
+ .toHaveBeenCalledWith(originalObjects.testObject);
+ });
+ });
+
+
});
});
}
diff --git a/platform/entanglement/test/suite.json b/platform/entanglement/test/suite.json
index 12831b407a..89c082f9c8 100644
--- a/platform/entanglement/test/suite.json
+++ b/platform/entanglement/test/suite.json
@@ -1,5 +1,9 @@
[
"actions/AbstractComposeAction",
+ "actions/CopyAction",
+ "actions/GoToOriginalAction",
+ "actions/LinkAction",
+ "actions/MoveAction",
"services/CopyService",
"services/LinkService",
"services/MoveService",
diff --git a/platform/search/src/services/GenericSearchProvider.js b/platform/search/src/services/GenericSearchProvider.js
index 2b99abcae2..71dfe8c0ed 100644
--- a/platform/search/src/services/GenericSearchProvider.js
+++ b/platform/search/src/services/GenericSearchProvider.js
@@ -122,7 +122,7 @@ define([
mutationTopic.listen(function (mutatedObject) {
var id = mutatedObject.getId();
- provider.indexed[id] = false;
+ provider.indexedIds[id] = false;
provider.scheduleForIndexing(id);
});
};
diff --git a/platform/search/test/services/GenericSearchProviderSpec.js b/platform/search/test/services/GenericSearchProviderSpec.js
index 7b8e52274b..cc80e4210d 100644
--- a/platform/search/test/services/GenericSearchProviderSpec.js
+++ b/platform/search/test/services/GenericSearchProviderSpec.js
@@ -99,6 +99,14 @@ define([
.toHaveBeenCalledWith(jasmine.any(Function));
});
+ it('reschedules indexing when mutation occurs', function () {
+ var mockDomainObject =
+ jasmine.createSpyObj('domainObj', ['getId']);
+ mockDomainObject.getId.andReturn("some-id");
+ mutationTopic.listen.mostRecentCall.args[0](mockDomainObject);
+ expect(provider.scheduleForIndexing).toHaveBeenCalledWith('some-id');
+ });
+
it('starts indexing roots', function () {
expect(provider.scheduleForIndexing).toHaveBeenCalledWith('mine');
});
diff --git a/test-main.js b/test-main.js
index d3bbb1fcc3..77f6bb4d86 100644
--- a/test-main.js
+++ b/test-main.js
@@ -45,7 +45,8 @@ require.config({
paths: {
'es6-promise': 'platform/framework/lib/es6-promise-2.0.0.min',
'moment': 'platform/telemetry/lib/moment.min',
- 'moment-duration-format': 'platform/features/clock/lib/moment-duration-format'
+ 'moment-duration-format': 'platform/features/clock/lib/moment-duration-format',
+ 'uuid': 'platform/commonUI/browse/lib/uuid'
},
shim: {