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. --> -
-
- C - - - - {{startOuterText}} - - -
- - -
-
-
-
+
+ C + + + + + + + +
+ + +
+
+
+
- to + to - - - - {{endOuterText}} - - -
- - -
-
-
  -
-
+ + + + + + + + +
+ + +
+
+
  +
+
-
-
-
-
-
{{startInnerText}}
-
-
-
{{endInnerText}}
-
-
-
-
-
-
-
-
-
+
+
+
+
+
{{startInnerText}}
+
+
+
{{endInnerText}}
+
+
+
+
+
+
+
+
+
-
-
-
- {{tick}} -
-
-
-
\ No newline at end of file +
+
+
+ {{tick}} +
+
+
+ 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: {