mirror of
https://github.com/nasa/openmct.git
synced 2024-12-30 09:58:52 +00:00
Merge remote-tracking branch 'github-open/open141' into open141-integration
This commit is contained in:
commit
fc0bfa77db
@ -4,6 +4,10 @@
|
|||||||
{
|
{
|
||||||
"implementation": "WatchIndicator.js",
|
"implementation": "WatchIndicator.js",
|
||||||
"depends": ["$interval", "$rootScope"]
|
"depends": ["$interval", "$rootScope"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"implementation": "DigestIndicator.js",
|
||||||
|
"depends": ["$interval", "$rootScope"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
77
example/profiling/src/DigestIndicator.js
Normal file
77
example/profiling/src/DigestIndicator.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the number of digests that have occurred since the
|
||||||
|
* indicator was first instantiated.
|
||||||
|
* @constructor
|
||||||
|
* @param $interval Angular's $interval
|
||||||
|
* @implements {Indicator}
|
||||||
|
*/
|
||||||
|
function DigestIndicator($interval, $rootScope) {
|
||||||
|
var digests = 0,
|
||||||
|
displayed = 0,
|
||||||
|
start = Date.now();
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var secs = (Date.now() - start) / 1000;
|
||||||
|
displayed = Math.round(digests / secs);
|
||||||
|
}
|
||||||
|
|
||||||
|
function increment() {
|
||||||
|
digests += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.$watch(increment);
|
||||||
|
|
||||||
|
// Update state every second
|
||||||
|
$interval(update, 1000);
|
||||||
|
|
||||||
|
// Provide initial state, too
|
||||||
|
update();
|
||||||
|
|
||||||
|
return {
|
||||||
|
getGlyph: function () {
|
||||||
|
return ".";
|
||||||
|
},
|
||||||
|
getGlyphClass: function () {
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
getText: function () {
|
||||||
|
return displayed + " digests/sec";
|
||||||
|
},
|
||||||
|
getDescription: function () {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return DigestIndicator;
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
@ -29,7 +29,8 @@ define(
|
|||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var TOPIC_PREFIX = "mutation:";
|
var GENERAL_TOPIC = "mutation",
|
||||||
|
TOPIC_PREFIX = "mutation:";
|
||||||
|
|
||||||
// Utility function to overwrite a destination object
|
// Utility function to overwrite a destination object
|
||||||
// with the contents of a source object.
|
// with the contents of a source object.
|
||||||
@ -78,7 +79,11 @@ define(
|
|||||||
* @implements {Capability}
|
* @implements {Capability}
|
||||||
*/
|
*/
|
||||||
function MutationCapability(topic, now, domainObject) {
|
function MutationCapability(topic, now, domainObject) {
|
||||||
this.mutationTopic = topic(TOPIC_PREFIX + domainObject.getId());
|
this.generalMutationTopic =
|
||||||
|
topic(GENERAL_TOPIC);
|
||||||
|
this.specificMutationTopic =
|
||||||
|
topic(TOPIC_PREFIX + domainObject.getId());
|
||||||
|
|
||||||
this.now = now;
|
this.now = now;
|
||||||
this.domainObject = domainObject;
|
this.domainObject = domainObject;
|
||||||
}
|
}
|
||||||
@ -115,11 +120,17 @@ define(
|
|||||||
// mutator function has a temporary copy to work with.
|
// mutator function has a temporary copy to work with.
|
||||||
var domainObject = this.domainObject,
|
var domainObject = this.domainObject,
|
||||||
now = this.now,
|
now = this.now,
|
||||||
t = this.mutationTopic,
|
generalTopic = this.generalMutationTopic,
|
||||||
|
specificTopic = this.specificMutationTopic,
|
||||||
model = domainObject.getModel(),
|
model = domainObject.getModel(),
|
||||||
clone = JSON.parse(JSON.stringify(model)),
|
clone = JSON.parse(JSON.stringify(model)),
|
||||||
useTimestamp = arguments.length > 1;
|
useTimestamp = arguments.length > 1;
|
||||||
|
|
||||||
|
function notifyListeners(model) {
|
||||||
|
generalTopic.notify(domainObject);
|
||||||
|
specificTopic.notify(model);
|
||||||
|
}
|
||||||
|
|
||||||
// Function to handle copying values to the actual
|
// Function to handle copying values to the actual
|
||||||
function handleMutation(mutationResult) {
|
function handleMutation(mutationResult) {
|
||||||
// If mutation result was undefined, just use
|
// If mutation result was undefined, just use
|
||||||
@ -136,7 +147,7 @@ define(
|
|||||||
copyValues(model, result);
|
copyValues(model, result);
|
||||||
}
|
}
|
||||||
model.modified = useTimestamp ? timestamp : now();
|
model.modified = useTimestamp ? timestamp : now();
|
||||||
t.notify(model);
|
notifyListeners(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report the result of the mutation
|
// Report the result of the mutation
|
||||||
@ -158,7 +169,7 @@ define(
|
|||||||
* @memberof platform/core.MutationCapability#
|
* @memberof platform/core.MutationCapability#
|
||||||
*/
|
*/
|
||||||
MutationCapability.prototype.listen = function (listener) {
|
MutationCapability.prototype.listen = function (listener) {
|
||||||
return this.mutationTopic.listen(listener);
|
return this.specificMutationTopic.listen(listener);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,7 +61,7 @@ define(
|
|||||||
* @memberof platform/core.Throttle#
|
* @memberof platform/core.Throttle#
|
||||||
*/
|
*/
|
||||||
return function (fn, delay, apply) {
|
return function (fn, delay, apply) {
|
||||||
var promise, // Promise for the result of throttled function
|
var promise,
|
||||||
args = [];
|
args = [];
|
||||||
|
|
||||||
function invoke() {
|
function invoke() {
|
||||||
|
@ -45,7 +45,15 @@
|
|||||||
"provides": "searchService",
|
"provides": "searchService",
|
||||||
"type": "provider",
|
"type": "provider",
|
||||||
"implementation": "services/GenericSearchProvider.js",
|
"implementation": "services/GenericSearchProvider.js",
|
||||||
"depends": [ "$q", "$timeout", "objectService", "workerService", "GENERIC_SEARCH_ROOTS" ]
|
"depends": [
|
||||||
|
"$q",
|
||||||
|
"$log",
|
||||||
|
"throttle",
|
||||||
|
"objectService",
|
||||||
|
"workerService",
|
||||||
|
"topic",
|
||||||
|
"GENERIC_SEARCH_ROOTS"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"provides": "searchService",
|
"provides": "searchService",
|
||||||
|
@ -31,6 +31,8 @@ define(
|
|||||||
|
|
||||||
var DEFAULT_MAX_RESULTS = 100,
|
var DEFAULT_MAX_RESULTS = 100,
|
||||||
DEFAULT_TIMEOUT = 1000,
|
DEFAULT_TIMEOUT = 1000,
|
||||||
|
MAX_CONCURRENT_REQUESTS = 100,
|
||||||
|
FLUSH_INTERVAL = 0,
|
||||||
stopTime;
|
stopTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,7 +41,8 @@ define(
|
|||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param $q Angular's $q, for promise consolidation.
|
* @param $q Angular's $q, for promise consolidation.
|
||||||
* @param $timeout Angular's $timeout, for delayed function execution.
|
* @param $log Anglar's $log, for logging.
|
||||||
|
* @param {Function} throttle a function to throttle function invocations
|
||||||
* @param {ObjectService} objectService The service from which
|
* @param {ObjectService} objectService The service from which
|
||||||
* domain objects can be gotten.
|
* domain objects can be gotten.
|
||||||
* @param {WorkerService} workerService The service which allows
|
* @param {WorkerService} workerService The service which allows
|
||||||
@ -47,10 +50,16 @@ define(
|
|||||||
* @param {GENERIC_SEARCH_ROOTS} ROOTS An array of the root
|
* @param {GENERIC_SEARCH_ROOTS} ROOTS An array of the root
|
||||||
* domain objects' IDs.
|
* domain objects' IDs.
|
||||||
*/
|
*/
|
||||||
function GenericSearchProvider($q, $timeout, objectService, workerService, ROOTS) {
|
function GenericSearchProvider($q, $log, throttle, objectService, workerService, topic, ROOTS) {
|
||||||
var indexed = {},
|
var indexed = {},
|
||||||
|
pendingIndex = {},
|
||||||
pendingQueries = {},
|
pendingQueries = {},
|
||||||
worker = workerService.run('genericSearchWorker');
|
toRequest = [],
|
||||||
|
worker = workerService.run('genericSearchWorker'),
|
||||||
|
mutationTopic = topic("mutation"),
|
||||||
|
indexingStarted = Date.now(),
|
||||||
|
pendingRequests = 0,
|
||||||
|
scheduleFlush;
|
||||||
|
|
||||||
this.worker = worker;
|
this.worker = worker;
|
||||||
this.pendingQueries = pendingQueries;
|
this.pendingQueries = pendingQueries;
|
||||||
@ -58,23 +67,31 @@ define(
|
|||||||
// pendingQueries is a dictionary with the key value pairs st
|
// pendingQueries is a dictionary with the key value pairs st
|
||||||
// the key is the timestamp and the value is the promise
|
// the key is the timestamp and the value is the promise
|
||||||
|
|
||||||
// Tell the web worker to add a domain object's model to its list of items.
|
function scheduleIdsForIndexing(ids) {
|
||||||
function indexItem(domainObject) {
|
ids.forEach(function (id) {
|
||||||
var message;
|
if (!indexed[id] && !pendingIndex[id]) {
|
||||||
|
indexed[id] = true;
|
||||||
// undefined check
|
pendingIndex[id] = true;
|
||||||
if (domainObject && domainObject.getModel) {
|
toRequest.push(id);
|
||||||
// Using model instead of whole domain object because
|
}
|
||||||
// it's a JSON object.
|
});
|
||||||
message = {
|
scheduleFlush();
|
||||||
request: 'index',
|
|
||||||
model: domainObject.getModel(),
|
|
||||||
id: domainObject.getId()
|
|
||||||
};
|
|
||||||
worker.postMessage(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tell the web worker to add a domain object's model to its list of items.
|
||||||
|
function indexItem(domainObject) {
|
||||||
|
var model = domainObject.getModel();
|
||||||
|
|
||||||
|
worker.postMessage({
|
||||||
|
request: 'index',
|
||||||
|
model: model,
|
||||||
|
id: domainObject.getId()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Array.isArray(model.composition)) {
|
||||||
|
scheduleIdsForIndexing(model.composition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handles responses from the web worker. Namely, the results of
|
// Handles responses from the web worker. Namely, the results of
|
||||||
// a search request.
|
// a search request.
|
||||||
@ -111,82 +128,48 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for getItems(). Indexes the tree.
|
function requestAndIndex(id) {
|
||||||
function indexItems(nodes) {
|
pendingRequests += 1;
|
||||||
nodes.forEach(function (node) {
|
objectService.getObjects([id]).then(function (objects) {
|
||||||
var id = node && node.getId && node.getId();
|
delete pendingIndex[id];
|
||||||
|
if (objects[id]) {
|
||||||
// If we have already indexed this item, stop here
|
indexItem(objects[id]);
|
||||||
if (indexed[id]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Index each item with the web worker
|
|
||||||
indexItem(node);
|
|
||||||
indexed[id] = true;
|
|
||||||
|
|
||||||
|
|
||||||
// If this node has children, index those
|
|
||||||
if (node && node.hasCapability && node.hasCapability('composition')) {
|
|
||||||
// Make sure that this is async, so doesn't block up page
|
|
||||||
$timeout(function () {
|
|
||||||
// Get the children...
|
|
||||||
node.useCapability('composition').then(function (children) {
|
|
||||||
$timeout(function () {
|
|
||||||
// ... then index the children
|
|
||||||
if (children.constructor === Array) {
|
|
||||||
indexItems(children);
|
|
||||||
} else {
|
|
||||||
indexItems([children]);
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
});
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch for changes to this item, in case it gets new children
|
|
||||||
if (node && node.hasCapability && node.hasCapability('mutation')) {
|
|
||||||
node.getCapability('mutation').listen(function (listener) {
|
|
||||||
if (listener && listener.composition) {
|
|
||||||
// If the node was mutated to have children, get the child domain objects
|
|
||||||
objectService.getObjects(listener.composition).then(function (objectsById) {
|
|
||||||
var objects = [],
|
|
||||||
id;
|
|
||||||
|
|
||||||
// Get each of the domain objects in objectsById
|
|
||||||
for (id in objectsById) {
|
|
||||||
objects.push(objectsById[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
indexItems(objects);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}, function () {
|
||||||
|
$log.warn("Failed to index domain object " + id);
|
||||||
|
}).then(function () {
|
||||||
|
pendingRequests -= 1;
|
||||||
|
scheduleFlush();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts the filetree into a list
|
scheduleFlush = throttle(function flush() {
|
||||||
function getItems() {
|
var batchSize =
|
||||||
// Aquire root objects
|
Math.max(MAX_CONCURRENT_REQUESTS - pendingRequests, 0);
|
||||||
objectService.getObjects(ROOTS).then(function (objectsById) {
|
|
||||||
var objects = [],
|
|
||||||
id;
|
|
||||||
|
|
||||||
// Get each of the domain objects in objectsById
|
if (toRequest.length + pendingRequests < 1) {
|
||||||
for (id in objectsById) {
|
$log.info([
|
||||||
objects.push(objectsById[id]);
|
'GenericSearch finished indexing after ',
|
||||||
}
|
((Date.now() - indexingStarted) / 1000).toFixed(2),
|
||||||
|
' seconds.'
|
||||||
// Index all of the roots' descendents
|
].join(''));
|
||||||
indexItems(objects);
|
} else {
|
||||||
});
|
toRequest.splice(-batchSize, batchSize)
|
||||||
}
|
.forEach(requestAndIndex);
|
||||||
|
}
|
||||||
|
}, FLUSH_INTERVAL);
|
||||||
|
|
||||||
worker.onmessage = handleResponse;
|
worker.onmessage = handleResponse;
|
||||||
|
|
||||||
// Index the tree's contents once at the beginning
|
// Index the tree's contents once at the beginning
|
||||||
getItems();
|
scheduleIdsForIndexing(ROOTS);
|
||||||
|
|
||||||
|
// Re-index items when they are mutated
|
||||||
|
mutationTopic.listen(function (domainObject) {
|
||||||
|
var id = domainObject.getId();
|
||||||
|
indexed[id] = false;
|
||||||
|
scheduleIdsForIndexing([id]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,26 +31,56 @@ define(
|
|||||||
|
|
||||||
describe("The generic search provider ", function () {
|
describe("The generic search provider ", function () {
|
||||||
var mockQ,
|
var mockQ,
|
||||||
mockTimeout,
|
mockLog,
|
||||||
|
mockThrottle,
|
||||||
mockDeferred,
|
mockDeferred,
|
||||||
mockObjectService,
|
mockObjectService,
|
||||||
mockObjectPromise,
|
mockObjectPromise,
|
||||||
|
mockChainedPromise,
|
||||||
mockDomainObjects,
|
mockDomainObjects,
|
||||||
mockCapability,
|
mockCapability,
|
||||||
mockCapabilityPromise,
|
mockCapabilityPromise,
|
||||||
mockWorkerService,
|
mockWorkerService,
|
||||||
mockWorker,
|
mockWorker,
|
||||||
|
mockTopic,
|
||||||
|
mockMutationTopic,
|
||||||
mockRoots = ['root1', 'root2'],
|
mockRoots = ['root1', 'root2'],
|
||||||
|
mockThrottledFn,
|
||||||
|
throttledCallCount,
|
||||||
provider,
|
provider,
|
||||||
mockProviderResults;
|
mockProviderResults;
|
||||||
|
|
||||||
beforeEach(function () {
|
function resolveObjectPromises() {
|
||||||
var i;
|
var i;
|
||||||
|
for (i = 0; i < mockObjectPromise.then.calls.length; i += 1) {
|
||||||
|
mockChainedPromise.then.calls[i].args[0](
|
||||||
|
mockObjectPromise.then.calls[i]
|
||||||
|
.args[0](mockDomainObjects)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveThrottledFn() {
|
||||||
|
if (mockThrottledFn.calls.length > throttledCallCount) {
|
||||||
|
mockThrottle.mostRecentCall.args[0]();
|
||||||
|
throttledCallCount = mockThrottledFn.calls.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveAsyncTasks() {
|
||||||
|
resolveThrottledFn();
|
||||||
|
resolveObjectPromises();
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
mockQ = jasmine.createSpyObj(
|
mockQ = jasmine.createSpyObj(
|
||||||
"$q",
|
"$q",
|
||||||
[ "defer" ]
|
[ "defer" ]
|
||||||
);
|
);
|
||||||
|
mockLog = jasmine.createSpyObj(
|
||||||
|
"$log",
|
||||||
|
[ "error", "warn", "info", "debug" ]
|
||||||
|
);
|
||||||
mockDeferred = jasmine.createSpyObj(
|
mockDeferred = jasmine.createSpyObj(
|
||||||
"deferred",
|
"deferred",
|
||||||
[ "resolve", "reject"]
|
[ "resolve", "reject"]
|
||||||
@ -58,7 +88,9 @@ define(
|
|||||||
mockDeferred.promise = "mock promise";
|
mockDeferred.promise = "mock promise";
|
||||||
mockQ.defer.andReturn(mockDeferred);
|
mockQ.defer.andReturn(mockDeferred);
|
||||||
|
|
||||||
mockTimeout = jasmine.createSpy("$timeout");
|
mockThrottle = jasmine.createSpy("throttle");
|
||||||
|
mockThrottledFn = jasmine.createSpy("throttledFn");
|
||||||
|
throttledCallCount = 0;
|
||||||
|
|
||||||
mockObjectService = jasmine.createSpyObj(
|
mockObjectService = jasmine.createSpyObj(
|
||||||
"objectService",
|
"objectService",
|
||||||
@ -68,8 +100,13 @@ define(
|
|||||||
"promise",
|
"promise",
|
||||||
[ "then", "catch" ]
|
[ "then", "catch" ]
|
||||||
);
|
);
|
||||||
|
mockChainedPromise = jasmine.createSpyObj(
|
||||||
|
"chainedPromise",
|
||||||
|
[ "then" ]
|
||||||
|
);
|
||||||
mockObjectService.getObjects.andReturn(mockObjectPromise);
|
mockObjectService.getObjects.andReturn(mockObjectPromise);
|
||||||
|
|
||||||
|
mockTopic = jasmine.createSpy('topic');
|
||||||
|
|
||||||
mockWorkerService = jasmine.createSpyObj(
|
mockWorkerService = jasmine.createSpyObj(
|
||||||
"workerService",
|
"workerService",
|
||||||
@ -87,59 +124,100 @@ define(
|
|||||||
);
|
);
|
||||||
|
|
||||||
mockDomainObjects = {};
|
mockDomainObjects = {};
|
||||||
for (i = 0; i < 4; i += 1) {
|
['a', 'root1', 'root2'].forEach(function (id) {
|
||||||
mockDomainObjects[i] = (
|
mockDomainObjects[id] = (
|
||||||
jasmine.createSpyObj(
|
jasmine.createSpyObj(
|
||||||
"domainObject",
|
"domainObject",
|
||||||
[ "getId", "getModel", "hasCapability", "getCapability", "useCapability" ]
|
[
|
||||||
|
"getId",
|
||||||
|
"getModel",
|
||||||
|
"hasCapability",
|
||||||
|
"getCapability",
|
||||||
|
"useCapability"
|
||||||
|
]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
mockDomainObjects[i].getId.andReturn(i);
|
mockDomainObjects[id].getId.andReturn(id);
|
||||||
mockDomainObjects[i].getCapability.andReturn(mockCapability);
|
mockDomainObjects[id].getCapability.andReturn(mockCapability);
|
||||||
mockDomainObjects[i].useCapability.andReturn(mockCapabilityPromise);
|
mockDomainObjects[id].useCapability.andReturn(mockCapabilityPromise);
|
||||||
}
|
mockDomainObjects[id].getModel.andReturn({});
|
||||||
// Give the first object children
|
});
|
||||||
mockDomainObjects[0].hasCapability.andReturn(true);
|
|
||||||
mockCapability = jasmine.createSpyObj(
|
mockCapability = jasmine.createSpyObj(
|
||||||
"capability",
|
"capability",
|
||||||
[ "invoke", "listen" ]
|
[ "invoke", "listen" ]
|
||||||
);
|
);
|
||||||
mockCapability.invoke.andReturn(mockCapabilityPromise);
|
mockCapability.invoke.andReturn(mockCapabilityPromise);
|
||||||
mockDomainObjects[0].getCapability.andReturn(mockCapability);
|
mockDomainObjects.a.getCapability.andReturn(mockCapability);
|
||||||
|
mockMutationTopic = jasmine.createSpyObj(
|
||||||
|
'mutationTopic',
|
||||||
|
[ 'listen' ]
|
||||||
|
);
|
||||||
|
mockTopic.andCallFake(function (key) {
|
||||||
|
return key === 'mutation' && mockMutationTopic;
|
||||||
|
});
|
||||||
|
mockThrottle.andReturn(mockThrottledFn);
|
||||||
|
mockObjectPromise.then.andReturn(mockChainedPromise);
|
||||||
|
|
||||||
provider = new GenericSearchProvider(mockQ, mockTimeout, mockObjectService, mockWorkerService, mockRoots);
|
provider = new GenericSearchProvider(
|
||||||
|
mockQ,
|
||||||
|
mockLog,
|
||||||
|
mockThrottle,
|
||||||
|
mockObjectService,
|
||||||
|
mockWorkerService,
|
||||||
|
mockTopic,
|
||||||
|
mockRoots
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("indexes tree on initialization", function () {
|
it("indexes tree on initialization", function () {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
resolveThrottledFn();
|
||||||
|
|
||||||
expect(mockObjectService.getObjects).toHaveBeenCalled();
|
expect(mockObjectService.getObjects).toHaveBeenCalled();
|
||||||
expect(mockObjectPromise.then).toHaveBeenCalled();
|
expect(mockObjectPromise.then).toHaveBeenCalled();
|
||||||
|
|
||||||
// Call through the root-getting part
|
// Call through the root-getting part
|
||||||
mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects);
|
resolveObjectPromises();
|
||||||
|
|
||||||
// Call through the children-getting part
|
mockRoots.forEach(function (id) {
|
||||||
mockTimeout.mostRecentCall.args[0]();
|
expect(mockWorker.postMessage).toHaveBeenCalledWith({
|
||||||
// Array argument indicates multiple children
|
request: 'index',
|
||||||
mockCapabilityPromise.then.mostRecentCall.args[0]([]);
|
model: mockDomainObjects[id].getModel(),
|
||||||
mockTimeout.mostRecentCall.args[0]();
|
id: id
|
||||||
// Call again, but for single child
|
});
|
||||||
mockCapabilityPromise.then.mostRecentCall.args[0]({});
|
});
|
||||||
mockTimeout.mostRecentCall.args[0]();
|
|
||||||
|
|
||||||
expect(mockWorker.postMessage).toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("when indexing, listens for composition changes", function () {
|
it("indexes members of composition", function () {
|
||||||
var mockListener = {composition: {}};
|
mockDomainObjects.root1.getModel.andReturn({
|
||||||
|
composition: ['a']
|
||||||
|
});
|
||||||
|
|
||||||
// Call indexItems
|
resolveAsyncTasks();
|
||||||
mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects);
|
resolveAsyncTasks();
|
||||||
|
|
||||||
// Call through listening for changes
|
expect(mockWorker.postMessage).toHaveBeenCalledWith({
|
||||||
expect(mockCapability.listen).toHaveBeenCalled();
|
request: 'index',
|
||||||
mockCapability.listen.mostRecentCall.args[0](mockListener);
|
model: mockDomainObjects.a.getModel(),
|
||||||
expect(mockObjectService.getObjects).toHaveBeenCalled();
|
id: 'a'
|
||||||
mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects);
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("listens for changes to mutation", function () {
|
||||||
|
expect(mockMutationTopic.listen)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
mockMutationTopic.listen.mostRecentCall
|
||||||
|
.args[0](mockDomainObjects.a);
|
||||||
|
|
||||||
|
resolveAsyncTasks();
|
||||||
|
|
||||||
|
expect(mockWorker.postMessage).toHaveBeenCalledWith({
|
||||||
|
request: 'index',
|
||||||
|
model: mockDomainObjects.a.getModel(),
|
||||||
|
id: mockDomainObjects.a.getId()
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sends search queries to the worker", function () {
|
it("sends search queries to the worker", function () {
|
||||||
@ -188,6 +266,28 @@ define(
|
|||||||
expect(mockDeferred.resolve).toHaveBeenCalled();
|
expect(mockDeferred.resolve).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("warns when objects are unavailable", function () {
|
||||||
|
resolveAsyncTasks();
|
||||||
|
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||||
|
mockChainedPromise.then.mostRecentCall.args[0](
|
||||||
|
mockObjectPromise.then.mostRecentCall.args[1]()
|
||||||
|
);
|
||||||
|
expect(mockLog.warn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throttles the loading of objects to index", function () {
|
||||||
|
expect(mockObjectService.getObjects).not.toHaveBeenCalled();
|
||||||
|
resolveThrottledFn();
|
||||||
|
expect(mockObjectService.getObjects).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("logs when all objects have been processed", function () {
|
||||||
|
expect(mockLog.info).not.toHaveBeenCalled();
|
||||||
|
resolveAsyncTasks();
|
||||||
|
resolveThrottledFn();
|
||||||
|
expect(mockLog.info).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
Loading…
Reference in New Issue
Block a user