mirror of
https://github.com/nasa/openmct.git
synced 2024-12-29 17:38:53 +00:00
Merge remote-tracking branch 'origin/open-master' into open1482c
Merge latest into topic branch for WTD-1482
This commit is contained in:
commit
bf417a14e0
@ -67,7 +67,7 @@ as described above.
|
|||||||
An example of this is expressed in `platform/framework`, which follows
|
An example of this is expressed in `platform/framework`, which follows
|
||||||
bundle conventions.
|
bundle conventions.
|
||||||
|
|
||||||
### Regression Testing
|
### Functional Testing
|
||||||
|
|
||||||
The tests described above are all at the unit-level; an additional
|
The tests described above are all at the unit-level; an additional
|
||||||
test suite using [Protractor](https://angular.github.io/protractor/)
|
test suite using [Protractor](https://angular.github.io/protractor/)
|
||||||
@ -76,9 +76,9 @@ us under development, in the `protractor` folder.
|
|||||||
To run:
|
To run:
|
||||||
|
|
||||||
* Install protractor following the instructions above.
|
* Install protractor following the instructions above.
|
||||||
* `webdriver-manager start`
|
* `cd protractor`
|
||||||
* `node app.js -p 1984 -x platform/persistence/elastic -i example/persistence
|
* `npm install`
|
||||||
* `protractor protractor/conf.js`
|
* `npm run all`
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
"platform/persistence/queue",
|
"platform/persistence/queue",
|
||||||
"platform/policy",
|
"platform/policy",
|
||||||
"platform/entanglement",
|
"platform/entanglement",
|
||||||
|
"platform/search",
|
||||||
|
|
||||||
"example/imagery",
|
"example/imagery",
|
||||||
"example/persistence",
|
"example/persistence",
|
||||||
|
@ -4,3 +4,7 @@ deployment:
|
|||||||
commands:
|
commands:
|
||||||
- ./build-docs.sh
|
- ./build-docs.sh
|
||||||
- git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master
|
- git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master
|
||||||
|
openmctweb-staging-un:
|
||||||
|
branch: search
|
||||||
|
heroku:
|
||||||
|
appname: openmctweb-staging-un
|
||||||
|
@ -92,7 +92,7 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/* line 5, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 5, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
html, body, div, span, applet, object, iframe,
|
html, body, div, span, applet, object, iframe,
|
||||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
a, abbr, acronym, address, big, cite, code,
|
a, abbr, acronym, address, big, cite, code,
|
||||||
@ -113,38 +113,38 @@ time, mark, audio, video {
|
|||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
vertical-align: baseline; }
|
vertical-align: baseline; }
|
||||||
|
|
||||||
/* line 22, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 22, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
html {
|
html {
|
||||||
line-height: 1; }
|
line-height: 1; }
|
||||||
|
|
||||||
/* line 24, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 24, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
ol, ul {
|
ol, ul {
|
||||||
list-style: none; }
|
list-style: none; }
|
||||||
|
|
||||||
/* line 26, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 26, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
border-spacing: 0; }
|
border-spacing: 0; }
|
||||||
|
|
||||||
/* line 28, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 28, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
caption, th, td {
|
caption, th, td {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
vertical-align: middle; }
|
vertical-align: middle; }
|
||||||
|
|
||||||
/* line 30, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 30, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
q, blockquote {
|
q, blockquote {
|
||||||
quotes: none; }
|
quotes: none; }
|
||||||
/* line 103, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 103, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
q:before, q:after, blockquote:before, blockquote:after {
|
q:before, q:after, blockquote:before, blockquote:after {
|
||||||
content: "";
|
content: "";
|
||||||
content: none; }
|
content: none; }
|
||||||
|
|
||||||
/* line 32, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 32, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
a img {
|
a img {
|
||||||
border: none; }
|
border: none; }
|
||||||
|
|
||||||
/* line 116, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
/* line 116, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
|
||||||
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary {
|
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary {
|
||||||
display: block; }
|
display: block; }
|
||||||
|
|
||||||
|
213
platform/persistence/elastic/src/ElasticsearchSearchProvider.js
Normal file
213
platform/persistence/elastic/src/ElasticsearchSearchProvider.js
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining ElasticsearchSearchProvider. Created by shale on 07/16/2015.
|
||||||
|
* This is not currently included in the bundle definition.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// JSLint doesn't like underscore-prefixed properties,
|
||||||
|
// so hide them here.
|
||||||
|
var ID = "_id",
|
||||||
|
SCORE = "_score",
|
||||||
|
DEFAULT_MAX_RESULTS = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A search service which searches through domain objects in
|
||||||
|
* the filetree using ElasticSearch.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param $http Angular's $http service, for working with urls.
|
||||||
|
* @param {ObjectService} objectService the service from which
|
||||||
|
* domain objects can be gotten.
|
||||||
|
* @param ROOT the constant ELASTIC_ROOT which allows us to
|
||||||
|
* interact with ElasticSearch.
|
||||||
|
*/
|
||||||
|
function ElasticsearchSearchProvider($http, objectService, ROOT) {
|
||||||
|
|
||||||
|
// Add the fuzziness operator to the search term
|
||||||
|
function addFuzziness(searchTerm, editDistance) {
|
||||||
|
if (!editDistance) {
|
||||||
|
editDistance = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchTerm.split(' ').map(function (s) {
|
||||||
|
// Don't add fuzziness for quoted strings
|
||||||
|
if (s.indexOf('"') !== -1) {
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
return s + '~' + editDistance;
|
||||||
|
}
|
||||||
|
}).join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently specific to elasticsearch
|
||||||
|
function processSearchTerm(searchTerm) {
|
||||||
|
var spaceIndex;
|
||||||
|
|
||||||
|
// Cut out any extra spaces
|
||||||
|
while (searchTerm.substr(0, 1) === ' ') {
|
||||||
|
searchTerm = searchTerm.substring(1, searchTerm.length);
|
||||||
|
}
|
||||||
|
while (searchTerm.substr(searchTerm.length - 1, 1) === ' ') {
|
||||||
|
searchTerm = searchTerm.substring(0, searchTerm.length - 1);
|
||||||
|
}
|
||||||
|
spaceIndex = searchTerm.indexOf(' ');
|
||||||
|
while (spaceIndex !== -1) {
|
||||||
|
searchTerm = searchTerm.substring(0, spaceIndex) +
|
||||||
|
searchTerm.substring(spaceIndex + 1, searchTerm.length);
|
||||||
|
spaceIndex = searchTerm.indexOf(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add fuzziness for completeness
|
||||||
|
searchTerm = addFuzziness(searchTerm);
|
||||||
|
|
||||||
|
return searchTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processes results from the format that elasticsearch returns to
|
||||||
|
// a list of searchResult objects, then returns a result object
|
||||||
|
// (See documentation for query for object descriptions)
|
||||||
|
function processResults(rawResults, timestamp) {
|
||||||
|
var results = rawResults.data.hits.hits,
|
||||||
|
resultsLength = results.length,
|
||||||
|
ids = [],
|
||||||
|
scores = {},
|
||||||
|
searchResults = [],
|
||||||
|
i;
|
||||||
|
|
||||||
|
// Get the result objects' IDs
|
||||||
|
for (i = 0; i < resultsLength; i += 1) {
|
||||||
|
ids.push(results[i][ID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the result objects' scores
|
||||||
|
for (i = 0; i < resultsLength; i += 1) {
|
||||||
|
scores[ids[i]] = results[i][SCORE];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the domain objects from their IDs
|
||||||
|
return objectService.getObjects(ids).then(function (objects) {
|
||||||
|
var j,
|
||||||
|
id;
|
||||||
|
|
||||||
|
for (j = 0; j < resultsLength; j += 1) {
|
||||||
|
id = ids[j];
|
||||||
|
|
||||||
|
// Include items we can get models for
|
||||||
|
if (objects[id].getModel) {
|
||||||
|
// Format the results as searchResult objects
|
||||||
|
searchResults.push({
|
||||||
|
id: id,
|
||||||
|
object: objects[id],
|
||||||
|
score: scores[id]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hits: searchResults,
|
||||||
|
total: rawResults.data.hits.total,
|
||||||
|
timedOut: rawResults.data.timed_out
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// For documentation, see query below.
|
||||||
|
function query(searchTerm, timestamp, maxResults, timeout) {
|
||||||
|
var esQuery;
|
||||||
|
|
||||||
|
// Check to see if the user provided a maximum
|
||||||
|
// number of results to display
|
||||||
|
if (!maxResults) {
|
||||||
|
// Else, we provide a default value.
|
||||||
|
maxResults = DEFAULT_MAX_RESULTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user input is empty, we want to have no search results.
|
||||||
|
if (searchTerm !== '' && searchTerm !== undefined) {
|
||||||
|
// Process the search term
|
||||||
|
searchTerm = processSearchTerm(searchTerm);
|
||||||
|
|
||||||
|
// Create the query to elasticsearch
|
||||||
|
esQuery = ROOT + "/_search/?q=" + searchTerm +
|
||||||
|
"&size=" + maxResults;
|
||||||
|
if (timeout) {
|
||||||
|
esQuery += "&timeout=" + timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the data...
|
||||||
|
return $http({
|
||||||
|
method: "GET",
|
||||||
|
url: esQuery
|
||||||
|
}).then(function (rawResults) {
|
||||||
|
// ...then process the data
|
||||||
|
return processResults(rawResults, timestamp);
|
||||||
|
}, function (err) {
|
||||||
|
// In case of error, return nothing. (To prevent
|
||||||
|
// infinite loading time.)
|
||||||
|
return {hits: [], total: 0};
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return {hits: [], total: 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Searches through the filetree for domain objects using a search
|
||||||
|
* term. This is done through querying elasticsearch. Returns a
|
||||||
|
* promise for a result object that has the format
|
||||||
|
* {hits: searchResult[], total: number, timedOut: boolean}
|
||||||
|
* where a searchResult has the format
|
||||||
|
* {id: string, object: domainObject, score: number}
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* * The order of the results is from highest to lowest score,
|
||||||
|
* as elsaticsearch determines them to be.
|
||||||
|
* * Uses the fuzziness operator to get more results.
|
||||||
|
* * More about this search's behavior at
|
||||||
|
* https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
|
||||||
|
*
|
||||||
|
* @param searchTerm The text input that is the query.
|
||||||
|
* @param timestamp The time at which this function was called.
|
||||||
|
* This timestamp is used as a unique identifier for this
|
||||||
|
* query and the corresponding results.
|
||||||
|
* @param maxResults (optional) The maximum number of results
|
||||||
|
* that this function should return.
|
||||||
|
* @param timeout (optional) The time after which the search should
|
||||||
|
* stop calculations and return partial results. Elasticsearch
|
||||||
|
* does not guarentee that this timeout will be strictly followed.
|
||||||
|
*/
|
||||||
|
query: query
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ElasticsearchSearchProvider;
|
||||||
|
}
|
||||||
|
);
|
@ -0,0 +1,115 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SearchSpec. Created by shale on 07/31/2015.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["../src/ElasticsearchSearchProvider"],
|
||||||
|
function (ElasticsearchSearchProvider) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// JSLint doesn't like underscore-prefixed properties,
|
||||||
|
// so hide them here.
|
||||||
|
var ID = "_id",
|
||||||
|
SCORE = "_score";
|
||||||
|
|
||||||
|
describe("The ElasticSearch search provider ", function () {
|
||||||
|
var mockHttp,
|
||||||
|
mockHttpPromise,
|
||||||
|
mockObjectPromise,
|
||||||
|
mockObjectService,
|
||||||
|
mockDomainObject,
|
||||||
|
provider,
|
||||||
|
mockProviderResults;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockHttp = jasmine.createSpy("$http");
|
||||||
|
mockHttpPromise = jasmine.createSpyObj(
|
||||||
|
"promise",
|
||||||
|
[ "then" ]
|
||||||
|
);
|
||||||
|
mockHttp.andReturn(mockHttpPromise);
|
||||||
|
// allow chaining of promise.then().catch();
|
||||||
|
mockHttpPromise.then.andReturn(mockHttpPromise);
|
||||||
|
|
||||||
|
mockObjectService = jasmine.createSpyObj(
|
||||||
|
"objectService",
|
||||||
|
[ "getObjects" ]
|
||||||
|
);
|
||||||
|
mockObjectPromise = jasmine.createSpyObj(
|
||||||
|
"promise",
|
||||||
|
[ "then" ]
|
||||||
|
);
|
||||||
|
mockObjectService.getObjects.andReturn(mockObjectPromise);
|
||||||
|
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
[ "getId", "getModel" ]
|
||||||
|
);
|
||||||
|
|
||||||
|
provider = new ElasticsearchSearchProvider(mockHttp, mockObjectService, "");
|
||||||
|
provider.query(' test "query" ', 0, undefined, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends a query to ElasticSearch", function () {
|
||||||
|
expect(mockHttp).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("gets data from ElasticSearch", function () {
|
||||||
|
var data = {
|
||||||
|
hits: {
|
||||||
|
hits: [
|
||||||
|
{},
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
timed_out: false
|
||||||
|
};
|
||||||
|
data.hits.hits[0][ID] = 1;
|
||||||
|
data.hits.hits[0][SCORE] = 1;
|
||||||
|
data.hits.hits[1][ID] = 2;
|
||||||
|
data.hits.hits[1][SCORE] = 2;
|
||||||
|
|
||||||
|
mockProviderResults = mockHttpPromise.then.mostRecentCall.args[0]({data: data});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
mockObjectPromise.then.mostRecentCall.args[0]({
|
||||||
|
1: mockDomainObject,
|
||||||
|
2: mockDomainObject
|
||||||
|
}).hits.length
|
||||||
|
).toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns nothing for an empty string query", function () {
|
||||||
|
expect(provider.query("").hits).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns something when there is an ElasticSearch error", function () {
|
||||||
|
mockProviderResults = mockHttpPromise.then.mostRecentCall.args[1]();
|
||||||
|
expect(mockProviderResults).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
@ -1,4 +1,5 @@
|
|||||||
[
|
[
|
||||||
"ElasticIndicator",
|
"ElasticIndicator",
|
||||||
"ElasticPersistenceProvider"
|
"ElasticPersistenceProvider",
|
||||||
|
"ElasticsearchSearchProvider"
|
||||||
]
|
]
|
||||||
|
33
platform/search/bundle.json
Normal file
33
platform/search/bundle.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "Search",
|
||||||
|
"description": "Allows the user to search through the file tree.",
|
||||||
|
"extensions": {
|
||||||
|
"constants": [
|
||||||
|
{
|
||||||
|
"key": "GENERIC_SEARCH_ROOTS",
|
||||||
|
"value": [ "ROOT" ],
|
||||||
|
"priority": "fallback"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"provides": "searchService",
|
||||||
|
"type": "provider",
|
||||||
|
"implementation": "GenericSearchProvider.js",
|
||||||
|
"depends": [ "$q", "$timeout", "objectService", "workerService", "GENERIC_SEARCH_ROOTS" ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"provides": "searchService",
|
||||||
|
"type": "aggregator",
|
||||||
|
"implementation": "SearchAggregator.js",
|
||||||
|
"depends": [ "$q" ]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"workers": [
|
||||||
|
{
|
||||||
|
"key": "genericSearchWorker",
|
||||||
|
"scriptUrl": "GenericSearchWorker.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
268
platform/search/src/GenericSearchProvider.js
Normal file
268
platform/search/src/GenericSearchProvider.js
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining GenericSearchProvider. Created by shale on 07/16/2015.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var DEFAULT_MAX_RESULTS = 100,
|
||||||
|
DEFAULT_TIMEOUT = 1000,
|
||||||
|
stopTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A search service which searches through domain objects in
|
||||||
|
* the filetree without using external search implementations.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param $q Angular's $q, for promise consolidation.
|
||||||
|
* @param $timeout Angular's $timeout, for delayed function execution.
|
||||||
|
* @param {ObjectService} objectService The service from which
|
||||||
|
* domain objects can be gotten.
|
||||||
|
* @param {WorkerService} workerService The service which allows
|
||||||
|
* more easy creation of web workers.
|
||||||
|
* @param {GENERIC_SEARCH_ROOTS} ROOTS An array of the root
|
||||||
|
* domain objects' IDs.
|
||||||
|
*/
|
||||||
|
function GenericSearchProvider($q, $timeout, objectService, workerService, ROOTS) {
|
||||||
|
var worker = workerService.run('genericSearchWorker'),
|
||||||
|
indexed = {},
|
||||||
|
pendingQueries = {};
|
||||||
|
// pendingQueries is a dictionary with the key value pairs st
|
||||||
|
// 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 indexItem(domainObject) {
|
||||||
|
var message;
|
||||||
|
|
||||||
|
// undefined check
|
||||||
|
if (domainObject && domainObject.getModel) {
|
||||||
|
// Using model instead of whole domain object because
|
||||||
|
// it's a JSON object.
|
||||||
|
message = {
|
||||||
|
request: 'index',
|
||||||
|
model: domainObject.getModel(),
|
||||||
|
id: domainObject.getId()
|
||||||
|
};
|
||||||
|
worker.postMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell the worker to search for items it has that match this searchInput.
|
||||||
|
// Takes the searchInput, as well as a max number of results (will return
|
||||||
|
// less than that if there are fewer matches).
|
||||||
|
function workerSearch(searchInput, maxResults, timestamp, timeout) {
|
||||||
|
var message = {
|
||||||
|
request: 'search',
|
||||||
|
input: searchInput,
|
||||||
|
maxNumber: maxResults,
|
||||||
|
timestamp: timestamp,
|
||||||
|
timeout: timeout
|
||||||
|
};
|
||||||
|
worker.postMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles responses from the web worker. Namely, the results of
|
||||||
|
// a search request.
|
||||||
|
function handleResponse(event) {
|
||||||
|
var ids = [],
|
||||||
|
id;
|
||||||
|
|
||||||
|
// If we have the results from a search
|
||||||
|
if (event.data.request === 'search') {
|
||||||
|
// Convert the ids given from the web worker into domain objects
|
||||||
|
for (id in event.data.results) {
|
||||||
|
ids.push(id);
|
||||||
|
}
|
||||||
|
objectService.getObjects(ids).then(function (objects) {
|
||||||
|
var searchResults = [],
|
||||||
|
id;
|
||||||
|
|
||||||
|
// Create searchResult objects
|
||||||
|
for (id in objects) {
|
||||||
|
searchResults.push({
|
||||||
|
object: objects[id],
|
||||||
|
id: id,
|
||||||
|
score: event.data.results[id]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resove the promise corresponding to this
|
||||||
|
pendingQueries[event.data.timestamp].resolve({
|
||||||
|
hits: searchResults,
|
||||||
|
total: event.data.total,
|
||||||
|
timedOut: event.data.timedOut
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.onmessage = handleResponse;
|
||||||
|
|
||||||
|
// Helper function for getItems(). Indexes the tree.
|
||||||
|
function indexItems(nodes) {
|
||||||
|
nodes.forEach(function (node) {
|
||||||
|
var id = node && node.getId && node.getId();
|
||||||
|
|
||||||
|
// If we have already indexed this item, stop here
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts the filetree into a list
|
||||||
|
function getItems() {
|
||||||
|
// Aquire root objects
|
||||||
|
objectService.getObjects(ROOTS).then(function (objectsById) {
|
||||||
|
var objects = [],
|
||||||
|
id;
|
||||||
|
|
||||||
|
// Get each of the domain objects in objectsById
|
||||||
|
for (id in objectsById) {
|
||||||
|
objects.push(objectsById[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index all of the roots' descendents
|
||||||
|
indexItems(objects);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// For documentation, see query below
|
||||||
|
function query(input, timestamp, maxResults, timeout) {
|
||||||
|
var terms = [],
|
||||||
|
searchResults = [],
|
||||||
|
defer = $q.defer();
|
||||||
|
|
||||||
|
// If the input is nonempty, do a search
|
||||||
|
if (input !== '' && input !== undefined) {
|
||||||
|
|
||||||
|
// Allow us to access this promise later to resolve it later
|
||||||
|
pendingQueries[timestamp] = defer;
|
||||||
|
|
||||||
|
// Check to see if the user provided a maximum
|
||||||
|
// number of results to display
|
||||||
|
if (!maxResults) {
|
||||||
|
// Else, we provide a default value
|
||||||
|
maxResults = DEFAULT_MAX_RESULTS;
|
||||||
|
}
|
||||||
|
// Similarly, check if timeout was provided
|
||||||
|
if (!timeout) {
|
||||||
|
timeout = DEFAULT_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the query to the worker
|
||||||
|
workerSearch(input, maxResults, timestamp, timeout);
|
||||||
|
|
||||||
|
return defer.promise;
|
||||||
|
} else {
|
||||||
|
// Otherwise return an empty result
|
||||||
|
return {hits: [], total: 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index the tree's contents once at the beginning
|
||||||
|
getItems();
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Searches through the filetree for domain objects which match
|
||||||
|
* the search term. This function is to be used as a fallback
|
||||||
|
* in the case where other search services are not avaliable.
|
||||||
|
* Returns a promise for a result object that has the format
|
||||||
|
* {hits: searchResult[], total: number, timedOut: boolean}
|
||||||
|
* where a searchResult has the format
|
||||||
|
* {id: string, object: domainObject, score: number}
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* * The order of the results is not guarenteed.
|
||||||
|
* * A domain object qualifies as a match for a search input if
|
||||||
|
* the object's name property contains any of the search terms
|
||||||
|
* (which are generated by splitting the input at spaces).
|
||||||
|
* * Scores are higher for matches that have more of the terms
|
||||||
|
* as substrings.
|
||||||
|
*
|
||||||
|
* @param input The text input that is the query.
|
||||||
|
* @param timestamp The time at which this function was called.
|
||||||
|
* This timestamp is used as a unique identifier for this
|
||||||
|
* query and the corresponding results.
|
||||||
|
* @param maxResults (optional) The maximum number of results
|
||||||
|
* that this function should return.
|
||||||
|
* @param timeout (optional) The time after which the search should
|
||||||
|
* stop calculations and return partial results.
|
||||||
|
*/
|
||||||
|
query: query
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return GenericSearchProvider;
|
||||||
|
}
|
||||||
|
);
|
185
platform/search/src/GenericSearchWorker.js
Normal file
185
platform/search/src/GenericSearchWorker.js
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 self*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining GenericSearchWorker. Created by shale on 07/21/2015.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// An array of objects composed of domain object IDs and models
|
||||||
|
// {id: domainObject's ID, model: domainObject's model}
|
||||||
|
var indexedItems = [];
|
||||||
|
|
||||||
|
// Helper function for index()
|
||||||
|
// Checks whether an item with this ID is already indexed
|
||||||
|
function conainsItem(id) {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < indexedItems.length; i += 1) {
|
||||||
|
if (indexedItems[i].id === id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indexes an item to indexedItems.
|
||||||
|
*
|
||||||
|
* @param data An object which contains:
|
||||||
|
* * model: The model of the domain object
|
||||||
|
* * id: The ID of the domain object
|
||||||
|
*/
|
||||||
|
function index(data) {
|
||||||
|
var message;
|
||||||
|
|
||||||
|
if (!conainsItem(data.id)) {
|
||||||
|
indexedItems.push({
|
||||||
|
id: data.id,
|
||||||
|
model: data.model
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for serach()
|
||||||
|
function convertToTerms(input) {
|
||||||
|
var terms = input;
|
||||||
|
// Shave any spaces off of the ends of the input
|
||||||
|
while (terms.substr(0, 1) === ' ') {
|
||||||
|
terms = terms.substring(1, terms.length);
|
||||||
|
}
|
||||||
|
while (terms.substr(terms.length - 1, 1) === ' ') {
|
||||||
|
terms = terms.substring(0, terms.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then split it at spaces and asterisks
|
||||||
|
terms = terms.split(/ |\*/);
|
||||||
|
|
||||||
|
// Remove any empty strings from the terms
|
||||||
|
while (terms.indexOf('') !== -1) {
|
||||||
|
terms.splice(terms.indexOf(''), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return terms;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for search()
|
||||||
|
function scoreItem(item, input, terms) {
|
||||||
|
var name = item.model.name.toLocaleLowerCase(),
|
||||||
|
weight = 0.65,
|
||||||
|
score = 0.0,
|
||||||
|
i;
|
||||||
|
|
||||||
|
// Make the score really big if the item name and
|
||||||
|
// the original search input are the same
|
||||||
|
if (name === input) {
|
||||||
|
score = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < terms.length; i += 1) {
|
||||||
|
// Increase the score if the term is in the item name
|
||||||
|
if (name.indexOf(terms[i]) !== -1) {
|
||||||
|
score += 1;
|
||||||
|
|
||||||
|
// Add extra to the score if the search term exists
|
||||||
|
// as its own term within the items
|
||||||
|
if (name.split(' ').indexOf(terms[i]) !== -1) {
|
||||||
|
score += 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets search results from the indexedItems based on provided search
|
||||||
|
* input. Returns matching results from indexedItems, as well as the
|
||||||
|
* timestamp that was passed to it.
|
||||||
|
*
|
||||||
|
* @param data An object which contains:
|
||||||
|
* * input: The original string which we are searching with
|
||||||
|
* * maxNumber: The maximum number of search results desired
|
||||||
|
* * timestamp: The time identifier from when the query was made
|
||||||
|
*/
|
||||||
|
function search(data) {
|
||||||
|
// This results dictionary will have domain object ID keys which
|
||||||
|
// point to the value the domain object's score.
|
||||||
|
var results = {},
|
||||||
|
input = data.input.toLocaleLowerCase(),
|
||||||
|
terms = convertToTerms(input),
|
||||||
|
message = {
|
||||||
|
request: 'search',
|
||||||
|
results: {},
|
||||||
|
total: 0,
|
||||||
|
timestamp: data.timestamp,
|
||||||
|
timedOut: false
|
||||||
|
},
|
||||||
|
score,
|
||||||
|
i,
|
||||||
|
id;
|
||||||
|
|
||||||
|
// If the user input is empty, we want to have no search results.
|
||||||
|
if (input !== '') {
|
||||||
|
for (i = 0; i < indexedItems.length; i += 1) {
|
||||||
|
// If this is taking too long, then stop
|
||||||
|
if (Date.now() > data.timestamp + data.timeout) {
|
||||||
|
message.timedOut = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Score and add items
|
||||||
|
score = scoreItem(indexedItems[i], input, terms);
|
||||||
|
if (score > 0) {
|
||||||
|
results[indexedItems[i].id] = score;
|
||||||
|
message.total += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate results if there are more than maxResults
|
||||||
|
if (message.total > data.maxResults) {
|
||||||
|
i = 0;
|
||||||
|
for (id in results) {
|
||||||
|
message.results[id] = results[id];
|
||||||
|
i += 1;
|
||||||
|
if (i >= data.maxResults) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: This seems inefficient.
|
||||||
|
} else {
|
||||||
|
message.results = results;
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.onmessage = function (event) {
|
||||||
|
if (event.data.request === 'index') {
|
||||||
|
index(event.data);
|
||||||
|
} else if (event.data.request === 'search') {
|
||||||
|
self.postMessage(search(event.data));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}());
|
146
platform/search/src/SearchAggregator.js
Normal file
146
platform/search/src/SearchAggregator.js
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining SearchAggregator. Created by shale on 07/16/2015.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var DEFUALT_TIMEOUT = 1000,
|
||||||
|
DEFAULT_MAX_RESULTS = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows multiple services which provide search functionality
|
||||||
|
* to be treated as one.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param $q Angular's $q, for promise consolidation.
|
||||||
|
* @param {SearchProvider[]} providers The search providers to be
|
||||||
|
* aggregated.
|
||||||
|
*/
|
||||||
|
function SearchAggregator($q, providers) {
|
||||||
|
|
||||||
|
// Remove duplicate objects that have the same ID. Modifies the passed
|
||||||
|
// array, and returns the number that were removed.
|
||||||
|
function filterDuplicates(results, total) {
|
||||||
|
var ids = {},
|
||||||
|
numRemoved = 0,
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 0; i < results.length; i += 1) {
|
||||||
|
if (ids[results[i].id]) {
|
||||||
|
// If this result's ID is already there, remove the object
|
||||||
|
results.splice(i, 1);
|
||||||
|
numRemoved += 1;
|
||||||
|
|
||||||
|
// Reduce loop index because we shortened the array
|
||||||
|
i -= 1;
|
||||||
|
} else {
|
||||||
|
// Otherwise add the ID to the list of the ones we have seen
|
||||||
|
ids[results[i].id] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return numRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Order the objects from highest to lowest score in the array.
|
||||||
|
// Modifies the passed array, as well as returns the modified array.
|
||||||
|
function orderByScore(results) {
|
||||||
|
results.sort(function (a, b) {
|
||||||
|
if (a.score > b.score) {
|
||||||
|
return -1;
|
||||||
|
} else if (b.score > a.score) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For documentation, see query below.
|
||||||
|
function queryAll(inputText, maxResults) {
|
||||||
|
var i,
|
||||||
|
timestamp = Date.now(),
|
||||||
|
resultPromises = [];
|
||||||
|
|
||||||
|
if (!maxResults) {
|
||||||
|
maxResults = DEFAULT_MAX_RESULTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the query to all the providers
|
||||||
|
for (i = 0; i < providers.length; i += 1) {
|
||||||
|
resultPromises.push(
|
||||||
|
providers[i].query(inputText, timestamp, maxResults, DEFUALT_TIMEOUT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get promises for results arrays
|
||||||
|
return $q.all(resultPromises).then(function (resultObjects) {
|
||||||
|
var results = [],
|
||||||
|
totalSum = 0,
|
||||||
|
i;
|
||||||
|
|
||||||
|
// Merge results
|
||||||
|
for (i = 0; i < resultObjects.length; i += 1) {
|
||||||
|
results = results.concat(resultObjects[i].hits);
|
||||||
|
totalSum += resultObjects[i].total;
|
||||||
|
}
|
||||||
|
// Order by score first, so that when removing repeats we keep the higher scored ones
|
||||||
|
orderByScore(results);
|
||||||
|
totalSum -= filterDuplicates(results, totalSum);
|
||||||
|
|
||||||
|
return {
|
||||||
|
hits: results,
|
||||||
|
total: totalSum,
|
||||||
|
timedOut: resultObjects.some(function (obj) {
|
||||||
|
return obj.timedOut;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Sends a query to each of the providers. Returns a promise for
|
||||||
|
* a result object that has the format
|
||||||
|
* {hits: searchResult[], total: number, timedOut: boolean}
|
||||||
|
* where a searchResult has the format
|
||||||
|
* {id: string, object: domainObject, score: number}
|
||||||
|
*
|
||||||
|
* @param inputText The text input that is the query.
|
||||||
|
* @param maxResults (optional) The maximum number of results
|
||||||
|
* that this function should return. If not provided, a
|
||||||
|
* default of 100 will be used.
|
||||||
|
*/
|
||||||
|
query: queryAll
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return SearchAggregator;
|
||||||
|
}
|
||||||
|
);
|
157
platform/search/test/GenericSearchProviderSpec.js
Normal file
157
platform/search/test/GenericSearchProviderSpec.js
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SearchSpec. Created by shale on 07/31/2015.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["../src/GenericSearchProvider"],
|
||||||
|
function (GenericSearchProvider) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("The generic search provider ", function () {
|
||||||
|
var mockQ,
|
||||||
|
mockTimeout,
|
||||||
|
mockDeferred,
|
||||||
|
mockObjectService,
|
||||||
|
mockObjectPromise,
|
||||||
|
mockDomainObjects,
|
||||||
|
mockCapability,
|
||||||
|
mockCapabilityPromise,
|
||||||
|
mockWorkerService,
|
||||||
|
mockWorker,
|
||||||
|
mockRoots = ['root1', 'root2'],
|
||||||
|
provider,
|
||||||
|
mockProviderResults;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
mockQ = jasmine.createSpyObj(
|
||||||
|
"$q",
|
||||||
|
[ "defer" ]
|
||||||
|
);
|
||||||
|
mockDeferred = jasmine.createSpyObj(
|
||||||
|
"deferred",
|
||||||
|
[ "resolve", "reject"]
|
||||||
|
);
|
||||||
|
mockDeferred.promise = "mock promise";
|
||||||
|
mockQ.defer.andReturn(mockDeferred);
|
||||||
|
|
||||||
|
mockTimeout = jasmine.createSpy("$timeout");
|
||||||
|
|
||||||
|
mockObjectService = jasmine.createSpyObj(
|
||||||
|
"objectService",
|
||||||
|
[ "getObjects" ]
|
||||||
|
);
|
||||||
|
mockObjectPromise = jasmine.createSpyObj(
|
||||||
|
"promise",
|
||||||
|
[ "then", "catch" ]
|
||||||
|
);
|
||||||
|
mockObjectService.getObjects.andReturn(mockObjectPromise);
|
||||||
|
|
||||||
|
|
||||||
|
mockWorkerService = jasmine.createSpyObj(
|
||||||
|
"workerService",
|
||||||
|
[ "run" ]
|
||||||
|
);
|
||||||
|
mockWorker = jasmine.createSpyObj(
|
||||||
|
"worker",
|
||||||
|
[ "postMessage" ]
|
||||||
|
);
|
||||||
|
mockWorkerService.run.andReturn(mockWorker);
|
||||||
|
|
||||||
|
mockDomainObjects = {};
|
||||||
|
for (i = 0; i < 4; i += 1) {
|
||||||
|
mockDomainObjects[i] = (
|
||||||
|
jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
[ "getId", "getModel", "hasCapability", "getCapability", "useCapability" ]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
mockDomainObjects[i].getId.andReturn(i);
|
||||||
|
mockDomainObjects[i].getCapability.andReturn(mockCapability);
|
||||||
|
}
|
||||||
|
// Give the first object children
|
||||||
|
mockDomainObjects[0].hasCapability.andReturn(true);
|
||||||
|
mockCapability = jasmine.createSpyObj(
|
||||||
|
"capability",
|
||||||
|
[ "invoke", "listen" ]
|
||||||
|
);
|
||||||
|
mockCapabilityPromise = jasmine.createSpyObj(
|
||||||
|
"promise",
|
||||||
|
[ "then", "catch" ]
|
||||||
|
);
|
||||||
|
mockCapability.invoke.andReturn(mockCapabilityPromise);
|
||||||
|
mockDomainObjects[0].getCapability.andReturn(mockCapability);
|
||||||
|
|
||||||
|
provider = new GenericSearchProvider(mockQ, mockTimeout, mockObjectService, mockWorkerService, mockRoots);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("indexes tree on initialization", function () {
|
||||||
|
expect(mockObjectService.getObjects).toHaveBeenCalled();
|
||||||
|
expect(mockObjectPromise.then).toHaveBeenCalled();
|
||||||
|
|
||||||
|
mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects);
|
||||||
|
|
||||||
|
//mockCapabilityPromise.then.mostRecentCall.args[0](mockDomainObjects[1]);
|
||||||
|
|
||||||
|
expect(mockWorker.postMessage).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends search queries to the worker", function () {
|
||||||
|
var timestamp = Date.now();
|
||||||
|
provider.query(' test "query" ', timestamp, 1, 2);
|
||||||
|
expect(mockWorker.postMessage).toHaveBeenCalledWith({
|
||||||
|
request: "search",
|
||||||
|
input: ' test "query" ',
|
||||||
|
timestamp: timestamp,
|
||||||
|
maxNumber: 1,
|
||||||
|
timeout: 2
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles responses from the worker", function () {
|
||||||
|
var timestamp = Date.now(),
|
||||||
|
event = {
|
||||||
|
data: {
|
||||||
|
request: "search",
|
||||||
|
results: {
|
||||||
|
1: 1,
|
||||||
|
2: 2
|
||||||
|
},
|
||||||
|
total: 2,
|
||||||
|
timedOut: false,
|
||||||
|
timestamp: timestamp
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
provider.query(' test "query" ', timestamp);
|
||||||
|
mockWorker.onmessage(event);
|
||||||
|
mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects);
|
||||||
|
expect(mockDeferred.resolve).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
132
platform/search/test/GenericSearchWorkerSpec.js
Normal file
132
platform/search/test/GenericSearchWorkerSpec.js
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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,runs,waitsFor,beforeEach,jasmine,Worker,require*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SearchSpec. Created by shale on 07/31/2015.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("The generic search worker ", function () {
|
||||||
|
// If this test fails, make sure this path is correct
|
||||||
|
var worker = new Worker(require.toUrl('platform/search/src/GenericSearchWorker.js')),
|
||||||
|
numObjects = 5;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < numObjects; i += 1) {
|
||||||
|
worker.postMessage(
|
||||||
|
{
|
||||||
|
request: "index",
|
||||||
|
id: i,
|
||||||
|
model: {
|
||||||
|
name: "object " + i,
|
||||||
|
id: i,
|
||||||
|
type: "something"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("searches can reach all objects", function () {
|
||||||
|
var flag = false,
|
||||||
|
workerOutput,
|
||||||
|
resultsLength = 0;
|
||||||
|
|
||||||
|
// Search something that should return all objects
|
||||||
|
runs(function () {
|
||||||
|
worker.postMessage(
|
||||||
|
{
|
||||||
|
request: "search",
|
||||||
|
input: "object",
|
||||||
|
maxNumber: 100,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
timeout: 1000
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
worker.onmessage = function (event) {
|
||||||
|
var id;
|
||||||
|
|
||||||
|
workerOutput = event.data;
|
||||||
|
for (id in workerOutput.results) {
|
||||||
|
resultsLength += 1;
|
||||||
|
}
|
||||||
|
flag = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
waitsFor(function () {
|
||||||
|
return flag;
|
||||||
|
}, "The worker should be searching", 1000);
|
||||||
|
|
||||||
|
runs(function () {
|
||||||
|
expect(workerOutput).toBeDefined();
|
||||||
|
expect(resultsLength).toEqual(numObjects);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("searches return only matches", function () {
|
||||||
|
var flag = false,
|
||||||
|
workerOutput,
|
||||||
|
resultsLength = 0;
|
||||||
|
|
||||||
|
// Search something that should return 1 object
|
||||||
|
runs(function () {
|
||||||
|
worker.postMessage(
|
||||||
|
{
|
||||||
|
request: "search",
|
||||||
|
input: "2",
|
||||||
|
maxNumber: 100,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
timeout: 1000
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
worker.onmessage = function (event) {
|
||||||
|
var id;
|
||||||
|
|
||||||
|
workerOutput = event.data;
|
||||||
|
for (id in workerOutput.results) {
|
||||||
|
resultsLength += 1;
|
||||||
|
}
|
||||||
|
flag = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
waitsFor(function () {
|
||||||
|
return flag;
|
||||||
|
}, "The worker should be searching", 1000);
|
||||||
|
|
||||||
|
runs(function () {
|
||||||
|
expect(workerOutput).toBeDefined();
|
||||||
|
expect(resultsLength).toEqual(1);
|
||||||
|
expect(workerOutput.results[2]).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
101
platform/search/test/SearchAggregatorSpec.js
Normal file
101
platform/search/test/SearchAggregatorSpec.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SearchSpec. Created by shale on 07/31/2015.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["../src/SearchAggregator"],
|
||||||
|
function (SearchAggregator) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("The search aggregator ", function () {
|
||||||
|
var mockQ,
|
||||||
|
mockPromise,
|
||||||
|
mockProviders = [],
|
||||||
|
aggregator,
|
||||||
|
mockProviderResults = [],
|
||||||
|
mockAggregatorResults,
|
||||||
|
i;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockQ = jasmine.createSpyObj(
|
||||||
|
"$q",
|
||||||
|
[ "all" ]
|
||||||
|
);
|
||||||
|
mockPromise = jasmine.createSpyObj(
|
||||||
|
"promise",
|
||||||
|
[ "then" ]
|
||||||
|
);
|
||||||
|
for (i = 0; i < 3; i += 1) {
|
||||||
|
mockProviders.push(
|
||||||
|
jasmine.createSpyObj(
|
||||||
|
"mockProvider" + i,
|
||||||
|
[ "query" ]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
mockProviders[i].query.andReturn(mockPromise);
|
||||||
|
}
|
||||||
|
mockQ.all.andReturn(mockPromise);
|
||||||
|
|
||||||
|
aggregator = new SearchAggregator(mockQ, mockProviders);
|
||||||
|
aggregator.query();
|
||||||
|
|
||||||
|
for (i = 0; i < mockProviders.length; i += 1) {
|
||||||
|
mockProviderResults.push({
|
||||||
|
hits: [
|
||||||
|
{
|
||||||
|
id: i,
|
||||||
|
score: 42 - i
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: i + 1,
|
||||||
|
score: 42 - (2 * i)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
mockAggregatorResults = mockPromise.then.mostRecentCall.args[0](mockProviderResults);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends queries to all providers", function () {
|
||||||
|
for (i = 0; i < mockProviders.length; i += 1) {
|
||||||
|
expect(mockProviders[i].query).toHaveBeenCalled();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("filters out duplicate objects", function () {
|
||||||
|
expect(mockAggregatorResults.hits.length).toEqual(mockProviders.length + 1);
|
||||||
|
expect(mockAggregatorResults.total).not.toBeLessThan(mockAggregatorResults.hits.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("orders results by score", function () {
|
||||||
|
for (i = 1; i < mockAggregatorResults.hits.length; i += 1) {
|
||||||
|
expect(mockAggregatorResults.hits[i].score)
|
||||||
|
.not.toBeGreaterThan(mockAggregatorResults.hits[i - 1].score);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
5
platform/search/test/suite.json
Normal file
5
platform/search/test/suite.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
"SearchAggregator",
|
||||||
|
"GenericSearchProvider",
|
||||||
|
"GenericSearchWorker"
|
||||||
|
]
|
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
|||||||
<groupId>gov.nasa.arc.wtd</groupId>
|
<groupId>gov.nasa.arc.wtd</groupId>
|
||||||
<artifactId>open-mct-web</artifactId>
|
<artifactId>open-mct-web</artifactId>
|
||||||
<name>Open MCT Web</name>
|
<name>Open MCT Web</name>
|
||||||
<version>0.8.0-SNAPSHOT</version>
|
<version>0.8.1-SNAPSHOT</version>
|
||||||
<packaging>war</packaging>
|
<packaging>war</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
69
protractor/README
Normal file
69
protractor/README
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
E2e Protractor Tests.
|
||||||
|
|
||||||
|
1. Instructions:
|
||||||
|
|
||||||
|
1. 3 Control Scripts located in bin/.
|
||||||
|
run.js : node script used to start tests
|
||||||
|
start.js: node script used to setup test(starts node,localstorage and webdriver)
|
||||||
|
stop.js : node script, kills the 3 process started in start.js.
|
||||||
|
clean.js: node script used to remove the node_module directory.(clean up directory).
|
||||||
|
|
||||||
|
2. Use npm(Node Package Mangager) to Run Scripts.
|
||||||
|
a. cd protractor;
|
||||||
|
b. npm install;
|
||||||
|
c. To Run:
|
||||||
|
-npm start : will start processes need by protractor
|
||||||
|
-npm stop : will stop the processes need by protractor
|
||||||
|
-npm run-script run : will execute Protractor Script
|
||||||
|
-npm run-script all : will execute "start", "run", and "stop" script
|
||||||
|
|
||||||
|
2. Directory Hierachy:
|
||||||
|
|
||||||
|
-protractor: base directory
|
||||||
|
-common: contains prototype javascript functions that all other tests use.
|
||||||
|
-Buttons: common prototype functions related to enter fullscreen
|
||||||
|
-CreateItem: common prototype functions related to creating an item
|
||||||
|
-drag: common functions to test drag and drop.
|
||||||
|
-editItem: common functions used to test edit functionality.
|
||||||
|
-Launch: common script used to navigate the specified website.
|
||||||
|
-RightMenu: common functions for right click menu(remove).
|
||||||
|
-create
|
||||||
|
-e2e tests that creates the specified object.
|
||||||
|
-delete
|
||||||
|
-e2e tests that removes the specified object
|
||||||
|
-logs
|
||||||
|
-ctrl.sh redirects console output of MMAP, webdriver and elastic search and pipes them to log files.
|
||||||
|
-UI
|
||||||
|
-Contains tests that test the UI(drag drop, fullscreen, info bubble)
|
||||||
|
-conf.js:
|
||||||
|
-protractor config file. Explained below
|
||||||
|
-stressTest:
|
||||||
|
Tests that are used to test for memory leaks. You can use the new tab option on WARP and then open the
|
||||||
|
timeline in the new tab during the browser.sleep(). Once the test is do the browser will pause and you
|
||||||
|
can look a the timeline results in the new tab.
|
||||||
|
|
||||||
|
NOTE: Cannot open chrome dev tools on same tab as the test are run on. Protractor uses the dev tools to
|
||||||
|
exectute the tests.
|
||||||
|
|
||||||
|
-StressTest will create and delete folders.
|
||||||
|
-StressTestBubble.js: creates manny bubbles.
|
||||||
|
(Delay variable in InfoGesture.js was changed to 0)
|
||||||
|
3. Conf.js
|
||||||
|
Conf.js is used by protractor to setup and execute the tests.
|
||||||
|
-allScriptsTimeout: gives more time for protractor to synchronize with the page.
|
||||||
|
-jasmineNodeOpts: Protractor uses jasmine for the tests and jasmine has a default time out 30 seconds
|
||||||
|
per "it" test. Changed to maximume allowed time 360000 ms
|
||||||
|
-seleniumAddress: Protractor uses a Selenium server as a "proxy" between the test scripts and the browser
|
||||||
|
driver. A stand a lone version comes with protractor and to run use "webdriver-manager"
|
||||||
|
default address is: http://localhost:4444/wd/hub.
|
||||||
|
-specs[]: Is an array of files. Each File should have a "describe, it" test to be executed by protractor.
|
||||||
|
-capabilities: Tells protractor what browser to use and any browser arguments.
|
||||||
|
|
||||||
|
4. bundle.json
|
||||||
|
bundle.json is used by npm to determine dependencies and location of script files.
|
||||||
|
-Dependencies:
|
||||||
|
"protractor": Contains protractor and webdriver package.
|
||||||
|
"psnode": Window/Unix Command, used for list/kill process.(ps aux)
|
||||||
|
"shelljs": Window/Unix Common JS Commands. eg rm,ls,exec
|
||||||
|
"sleep": Window/Unix Commands used to sleep the script
|
||||||
|
"string": Window/Unix Commands for string manipulation.
|
@ -22,7 +22,7 @@
|
|||||||
//TODO Add filter for duplications/
|
//TODO Add filter for duplications/
|
||||||
var fullScreenFile = require("../common/Buttons");
|
var fullScreenFile = require("../common/Buttons");
|
||||||
|
|
||||||
describe('Test Fullscreen', function() {
|
describe('Enable Fullscreen', function() {
|
||||||
var fullScreenClass = new fullScreenFile();
|
var fullScreenClass = new fullScreenFile();
|
||||||
|
|
||||||
beforeEach(require('../common/Launch'));
|
beforeEach(require('../common/Launch'));
|
||||||
|
@ -25,7 +25,7 @@ var itemEdit = require("../common/EditItem");
|
|||||||
var rightMenu = require("../common/RightMenu");
|
var rightMenu = require("../common/RightMenu");
|
||||||
var Drag = require("../common/drag");
|
var Drag = require("../common/drag");
|
||||||
|
|
||||||
describe('Test Info Bubble', function() {
|
describe('Info Bubble', function() {
|
||||||
var fullScreenClass = new fullScreenFile();
|
var fullScreenClass = new fullScreenFile();
|
||||||
var createClass = new createItem();
|
var createClass = new createItem();
|
||||||
var editItemClass = new itemEdit();
|
var editItemClass = new itemEdit();
|
||||||
|
@ -24,7 +24,7 @@ var createClassFile = require("../common/CreateItem")
|
|||||||
var itemEdit = require("../common/EditItem");
|
var itemEdit = require("../common/EditItem");
|
||||||
var rightMenu = require("../common/RightMenu.js");
|
var rightMenu = require("../common/RightMenu.js");
|
||||||
|
|
||||||
describe('Test New Window', function() {
|
describe('New Window', function() {
|
||||||
var fullScreenClass = new fullScreenFile();
|
var fullScreenClass = new fullScreenFile();
|
||||||
var createClass = new createClassFile();
|
var createClass = new createClassFile();
|
||||||
var editItemClass = new itemEdit();
|
var editItemClass = new itemEdit();
|
||||||
|
@ -21,28 +21,64 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
var right_click = require("../common/RightMenu.js");
|
var right_click = require("../common/RightMenu.js");
|
||||||
var Create = require("../common/CreateItem")
|
var Create = require("../common/CreateItem")
|
||||||
describe('Right Click Interations', function() {
|
var itemEdit = require("../common/EditItem");
|
||||||
|
|
||||||
|
describe('The Right Menu', function() {
|
||||||
var clickClass = new right_click();
|
var clickClass = new right_click();
|
||||||
var createClass = new Create();
|
var createClass = new Create();
|
||||||
|
var editItemClass = new itemEdit();
|
||||||
var ITEM_NAME = "Folder";
|
var ITEM_NAME = "Folder";
|
||||||
var ITEM_TYPE = "folder";
|
var ITEM_TYPE = "folder";
|
||||||
var ITEM_MENU_GLYPH = 'F\nFolder';
|
var ITEM_MENU_GLYPH = 'F\nFolder';
|
||||||
|
var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items';
|
||||||
|
|
||||||
beforeEach(require('../common/Launch'));
|
beforeEach(require('../common/Launch'));
|
||||||
|
|
||||||
it('should delete the specified object', function(){
|
it('should Dissapear After Delete', function(){
|
||||||
createClass.createButton().click();
|
browser.wait(function() {
|
||||||
var folder = createClass.selectNewItem(ITEM_TYPE);
|
createClass.createButton().click();
|
||||||
expect(folder.getText()).toEqual([ ITEM_MENU_GLYPH ]);
|
return true;
|
||||||
browser.sleep(1000);
|
}).then(function (){
|
||||||
folder.click()
|
var folder = createClass.selectNewItem(ITEM_TYPE);
|
||||||
browser.sleep(1000);
|
expect(folder.getText()).toEqual([ ITEM_MENU_GLYPH ]);
|
||||||
browser.wait(function () {
|
browser.sleep(1000);
|
||||||
return element.all(by.model('ngModel[field]')).isDisplayed();
|
folder.click()
|
||||||
|
}).then(function() {
|
||||||
|
browser.wait(function () {
|
||||||
|
return element.all(by.model('ngModel[field]')).isDisplayed();
|
||||||
|
})
|
||||||
|
createClass.fillFolderForum(ITEM_NAME, ITEM_TYPE).click();
|
||||||
|
browser.sleep(1000);
|
||||||
|
}).then(function (){
|
||||||
|
var item = editItemClass.SelectItem(ITEM_GRID_SELECT);
|
||||||
|
expect(item.count()).toBe(1);
|
||||||
|
browser.sleep(1000);
|
||||||
|
}).then(function () {
|
||||||
|
var MyItem = ">\nF\nMy Items"
|
||||||
|
element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
|
return ele.getText().then(function(text) {
|
||||||
|
return text === MyItem;
|
||||||
|
});
|
||||||
|
}).all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click();
|
||||||
|
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
|
return ele.getText().then(function(text) {
|
||||||
|
return text === ">\nF\nFolder";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
browser.sleep(1000)
|
||||||
|
browser.actions().mouseMove(object.get(0)).perform();
|
||||||
|
browser.actions().click(protractor.Button.RIGHT).perform();
|
||||||
|
browser.sleep(1000)
|
||||||
|
var menu = element.all(by.css('.ng-binding')).filter(function (ele){
|
||||||
|
return ele.getText().then(function (text) {
|
||||||
|
return text == "Z\nRemove";
|
||||||
|
})
|
||||||
|
})
|
||||||
|
menu.click();
|
||||||
|
browser.sleep(1000)
|
||||||
|
|
||||||
|
expect(menu.isDisplayed()).toBe(false);
|
||||||
})
|
})
|
||||||
createClass.fillFolderForum(ITEM_NAME, ITEM_TYPE).click();
|
|
||||||
clickClass.delete(ITEM_NAME);
|
|
||||||
browser.sleep(1000);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
15
protractor/bin/clean.js
Executable file
15
protractor/bin/clean.js
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
var shell = require("shelljs/global");
|
||||||
|
|
||||||
|
var startdir = process.cwd();
|
||||||
|
var command = "npm unlink";
|
||||||
|
|
||||||
|
console.log("Cleaning Directory")
|
||||||
|
exec(command, function(code, output) {
|
||||||
|
if(code != 0){
|
||||||
|
console.log('Exit code:', code);
|
||||||
|
console.log('Program output:', output);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("rm -rf node_modules")
|
||||||
|
rm('-rf', __dirname + "/../node_modules")
|
90
protractor/bin/ctrl.sh
Executable file
90
protractor/bin/ctrl.sh
Executable file
@ -0,0 +1,90 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
ARGUMENT=$1;
|
||||||
|
|
||||||
|
if [ $# != 1 ]; then
|
||||||
|
echo "Expected 1 Aurgument. Received " $# 1>&2;
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
#Start webdrive and http-server
|
||||||
|
if [ $ARGUMENT == start ]; then
|
||||||
|
echo "Creating Log Directory ..."
|
||||||
|
mkdir logs;
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
node app.js -p 1984 -x platform/persistence/elastic -i example/persistence > protractor/logs/nodeApp.log 2>&1 &
|
||||||
|
sleep 3;
|
||||||
|
if grep -iq "Error" protractor/logs/nodeApp.log; then
|
||||||
|
if grep -iq "minimist" protractor/logs/nodeApp.log; then
|
||||||
|
echo " Node Failed Because Minimist is not installed"
|
||||||
|
echo " Installng Minimist ..."
|
||||||
|
npm install minimist express > protractor/logs/minimist.log 2>&1 &
|
||||||
|
wait $!
|
||||||
|
if [ $? != 0 ]; then
|
||||||
|
echo " Error: minimist"
|
||||||
|
echo " Check Log file"
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo " Started: Minimist"
|
||||||
|
echo
|
||||||
|
node app.js -p 1984 -x platform/persistence/elastic -i example/persistence > protractor/logs/nodeApp.log 2>&1 &
|
||||||
|
if grep -iq "Error" protractor/logs/nodeApp.log; then
|
||||||
|
echo " Error: node app failed"
|
||||||
|
echo " Check Log file"
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo " Started: node app.js"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " Error: node app failed"
|
||||||
|
echo " Check Log file"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " Started: node app.js"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
echo "Starting webdriver ..."
|
||||||
|
|
||||||
|
cd protractor;
|
||||||
|
webdriver-manager start > logs/webdriver.log 2>&1 &
|
||||||
|
sleep 3;
|
||||||
|
if grep -iq "Exception" logs/webdriver.log; then
|
||||||
|
echo " Error: webdriver-manager"
|
||||||
|
echo " Check Log file"
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo " Started: webdriver-manager"
|
||||||
|
fi
|
||||||
|
echo "Starting Elastic Search..."
|
||||||
|
|
||||||
|
elasticsearch > logs/elasticSearch.log 2>&1 &
|
||||||
|
sleep 3;
|
||||||
|
if grep -iq "Exception" logs/elasticSearch.log; then
|
||||||
|
echo " Error: ElasticSearch"
|
||||||
|
echo " Check Log file"
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo " Started: ElasticSearch"
|
||||||
|
fi
|
||||||
|
#Runs Protractor tests
|
||||||
|
elif [ $ARGUMENT == run ]; then
|
||||||
|
protractor ./conf.js
|
||||||
|
#Kill Process
|
||||||
|
elif [ $ARGUMENT == stop ]; then
|
||||||
|
echo "Removing logs"
|
||||||
|
rm -rf logs
|
||||||
|
echo "Stopping Node"
|
||||||
|
kill $(ps aux | grep "[n]ode app.js"| awk '{print $2}');
|
||||||
|
|
||||||
|
echo "Stopping webdriver ..."
|
||||||
|
kill $(ps aux | grep "[p]rotractor" | awk '{print $2}');
|
||||||
|
kill $(ps aux | grep "[w]ebdriver-manager" | awk '{print $2}');
|
||||||
|
sleep 1;
|
||||||
|
echo "Stopping Elastic..."
|
||||||
|
kill $(ps aux | grep "[e]lastic" | awk '{print $2}');
|
||||||
|
sleep 1;
|
||||||
|
else
|
||||||
|
echo "Unkown: Command" $1;
|
||||||
|
fi
|
12
protractor/bin/run.js
Executable file
12
protractor/bin/run.js
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
var shell = require("shelljs/global");
|
||||||
|
var sleep = require('sleep');
|
||||||
|
|
||||||
|
var command = __dirname + "/../node_modules/protractor/bin/protractor " +__dirname + "/../conf.js";
|
||||||
|
console.log("Executing Protractor Test")
|
||||||
|
exec(command, function(code, output) {
|
||||||
|
if(code != 0){
|
||||||
|
console.log('Exit code:', code);
|
||||||
|
console.log('Program output:', output);
|
||||||
|
}
|
||||||
|
});
|
40
protractor/bin/start.js
Executable file
40
protractor/bin/start.js
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
var shell,sleep;
|
||||||
|
try {
|
||||||
|
shell = require("shelljs/global");
|
||||||
|
sleep = require('sleep');
|
||||||
|
}catch (e){
|
||||||
|
console.log("Dependencies Error");
|
||||||
|
console.log("Run npm install");
|
||||||
|
throw (e);
|
||||||
|
}
|
||||||
|
///Users/jsanderf/git/elastic/wtd/protractor/bin
|
||||||
|
var startdir = process.cwd();
|
||||||
|
var command;
|
||||||
|
mkdir(__dirname + '/../logs');
|
||||||
|
|
||||||
|
command = __dirname + "/../node_modules/protractor/bin/webdriver-manager update";
|
||||||
|
console.log("Installing Webdriver");
|
||||||
|
exec(command,{async:false});
|
||||||
|
sleep.sleep(1);
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
cd(__dirname + '/../../');
|
||||||
|
console.log('Installing Dependencies');
|
||||||
|
exec("npm install minimist express", {async:false});
|
||||||
|
console.log('Starting Node');
|
||||||
|
sleep.sleep(1);
|
||||||
|
exec("node app.js -p 1984 -x example/persistence -x platform/persistence/elastic -i example/localstorage > protractor/logs/nodeApp.log 2>&1 &", {async:false});
|
||||||
|
console.log(' Started Node');
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
console.log('Starting Webdriver');
|
||||||
|
sleep.sleep(1);
|
||||||
|
exec("protractor/node_modules/protractor/bin/webdriver-manager start --standalone> protractor/logs/webdriver.log 2>&1 &",{async:false});
|
||||||
|
if(error() == null){
|
||||||
|
console.log(" Webdriver Started");
|
||||||
|
}else{
|
||||||
|
console.log(" Error : ", error());
|
||||||
|
}
|
||||||
|
sleep.sleep(1);
|
||||||
|
cd(startdir);
|
44
protractor/bin/stop.js
Executable file
44
protractor/bin/stop.js
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
|
||||||
|
var shell = require("shelljs/global");
|
||||||
|
var ps = require('psnode');
|
||||||
|
var S = require('string');
|
||||||
|
var sleep = require('sleep');
|
||||||
|
|
||||||
|
// A simple pid lookup
|
||||||
|
ps.list(function(err, results) {
|
||||||
|
|
||||||
|
results.forEach(function( process ){
|
||||||
|
//Killing Node
|
||||||
|
if(S(process.command).contains("node app.js")) {
|
||||||
|
console.log();
|
||||||
|
console.log( 'Killing Node: %s', process.command);
|
||||||
|
ps.kill(process.pid, function(err, stdout) {
|
||||||
|
if (err) {
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
console.log(stdout);
|
||||||
|
});
|
||||||
|
}else if(S(process.command).contains("webdriver")) {
|
||||||
|
console.log();
|
||||||
|
console.log( 'Killing WebDriver: %s', process.command);
|
||||||
|
ps.kill(process.pid, function(err, stdout) {
|
||||||
|
if (err){
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
console.log(stdout);
|
||||||
|
});
|
||||||
|
}else if(S(process.command).contains("protractor")) {
|
||||||
|
console.log();
|
||||||
|
console.log( 'Killing Chrome Drive: %s', process.command);
|
||||||
|
ps.kill(process.pid, function(err, stdout) {
|
||||||
|
if (err){
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
console.log(stdout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -24,6 +24,6 @@
|
|||||||
module.exports = function launch() {
|
module.exports = function launch() {
|
||||||
'use strict';
|
'use strict';
|
||||||
browser.ignoreSynchronization = true;
|
browser.ignoreSynchronization = true;
|
||||||
browser.get('http://localhost:1984/');
|
browser.get('http://localhost:1984');
|
||||||
browser.sleep(2000); // 20 seconds
|
browser.sleep(2000); // 2 seconds
|
||||||
};
|
};
|
||||||
|
@ -24,18 +24,25 @@ var RightMenu = (function () {
|
|||||||
|
|
||||||
function RightMenu() {
|
function RightMenu() {
|
||||||
}
|
}
|
||||||
|
function carrotMyItem(){
|
||||||
|
var MyItem = ">\nF\nMy Items"
|
||||||
|
element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
|
return ele.getText().then(function(text) {
|
||||||
|
return text === MyItem;
|
||||||
|
});
|
||||||
|
}).all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click();
|
||||||
|
}
|
||||||
//RightMenu Click on Object
|
//RightMenu Click on Object
|
||||||
RightMenu.prototype.delete = function (name, flag) {
|
RightMenu.prototype.delete = function (name, flag) {
|
||||||
if(typeof flag === 'undefined'){
|
if(typeof flag === 'undefined'){
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
if(flag === true){
|
if(flag === true){
|
||||||
var carrot = element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).get(0).click();
|
carrotMyItem();
|
||||||
}
|
}
|
||||||
browser.sleep(1000)
|
browser.sleep(1000)
|
||||||
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
return ele.getText().then(function(text) {
|
return ele.getText().then(function(text) {
|
||||||
//expect(text).toEqual("3");
|
|
||||||
return text === name;
|
return text === name;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -43,7 +50,7 @@ var RightMenu = (function () {
|
|||||||
browser.actions().mouseMove(object.get(0)).perform();
|
browser.actions().mouseMove(object.get(0)).perform();
|
||||||
browser.actions().click(protractor.Button.RIGHT).perform();
|
browser.actions().click(protractor.Button.RIGHT).perform();
|
||||||
browser.sleep(1000)
|
browser.sleep(1000)
|
||||||
var remove = element.all(by.css('.ng-binding')).filter(function (ele){
|
element.all(by.css('.ng-binding')).filter(function (ele){
|
||||||
return ele.getText().then(function (text) {
|
return ele.getText().then(function (text) {
|
||||||
return text == "Z\nRemove";
|
return text == "Z\nRemove";
|
||||||
})
|
})
|
||||||
@ -58,11 +65,10 @@ var RightMenu = (function () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
RightMenu.prototype.reset = function (name) {
|
RightMenu.prototype.reset = function (name) {
|
||||||
var carrot = element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click();
|
carrotMyItem();
|
||||||
browser.sleep(1000)
|
browser.sleep(1000)
|
||||||
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
return ele.getText().then(function(text) {
|
return ele.getText().then(function(text) {
|
||||||
//expect(text).toEqual("3");
|
|
||||||
return text === name;
|
return text === name;
|
||||||
});
|
});
|
||||||
}).click();
|
}).click();
|
||||||
@ -75,19 +81,19 @@ var RightMenu = (function () {
|
|||||||
return text == "r\nRestart at 0";
|
return text == "r\nRestart at 0";
|
||||||
})
|
})
|
||||||
}).click();
|
}).click();
|
||||||
|
browser.sleep(1000)
|
||||||
};
|
};
|
||||||
|
//click '<', true==yes false==no
|
||||||
RightMenu.prototype.select = function(name, flag){
|
RightMenu.prototype.select = function(name, flag){
|
||||||
if(typeof flag == "undefined"){
|
if(typeof flag == "undefined"){
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
//click '<', true==yes false==no
|
|
||||||
if(flag == true){
|
if(flag == true){
|
||||||
var carrot = element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click();
|
carrotMyItem();
|
||||||
}
|
}
|
||||||
browser.sleep(1000)
|
browser.sleep(1000)
|
||||||
return element.all(by.repeater('child in composition')).filter(function (ele){
|
return element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
return ele.getText().then(function(text) {
|
return ele.getText().then(function(text) {
|
||||||
// expect(text).toEqual("3");
|
|
||||||
return text === name;
|
return text === name;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -96,7 +102,6 @@ var RightMenu = (function () {
|
|||||||
RightMenu.prototype.dragDrop = function(name){
|
RightMenu.prototype.dragDrop = function(name){
|
||||||
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
return ele.getText().then(function(text) {
|
return ele.getText().then(function(text) {
|
||||||
//expect(text).toEqual("3");
|
|
||||||
return text === name;
|
return text === name;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -24,34 +24,34 @@
|
|||||||
// conf.js
|
// conf.js
|
||||||
exports.config = {
|
exports.config = {
|
||||||
allScriptsTimeout: 500000,
|
allScriptsTimeout: 500000,
|
||||||
defaultTimeoutInterval: 60000,
|
jasmineNodeOpts: {defaultTimeoutInterval: 360000},
|
||||||
seleniumAddress: 'http://localhost:4444/wd/hub',
|
seleniumAddress: 'http://localhost:4444/wd/hub',
|
||||||
//specs: ['StressTest.js'],
|
//specs: ['StressTestCarrot.js'],
|
||||||
specs: [
|
specs: [
|
||||||
//'create/CreateActivity.js',
|
// 'create/CreateActivity.js',
|
||||||
//'delete/DeleteActivity.js',
|
// 'delete/DeleteActivity.js',
|
||||||
//'create/CreateActivityMode.js',
|
// 'create/CreateActivityMode.js',
|
||||||
//'delete/DeleteActivityMode.js',
|
// 'delete/DeleteActivityMode.js',
|
||||||
//'create/CreateActivityMode.js',
|
// 'create/CreateClock.js',
|
||||||
//'create/CreateClock.js',
|
// 'delete/DeleteClock.js',
|
||||||
//'delete/DeleteClock.js',
|
|
||||||
'create/CreateDisplay.js',
|
'create/CreateDisplay.js',
|
||||||
//'delete/DeleteDisplay.js',
|
'delete/DeleteDisplay.js',
|
||||||
'create/CreateFolder.js',
|
'create/CreateFolder.js',
|
||||||
//'delete/DeleteFolder.js',
|
'delete/DeleteFolder.js',
|
||||||
'create/CreateTelemetry.js',
|
// 'create/CreateTelemetry.js',
|
||||||
//'delete/DeleteTelemetry.js',
|
// 'delete/DeleteTelemetry.js',
|
||||||
//'create/CreateTimeline.js',
|
// 'create/CreateTimeline.js',
|
||||||
//'delete/DeleteTimeline.js',
|
// 'delete/DeleteTimeline.js',
|
||||||
//'create/CreateTimer.js',
|
// 'create/CreateTimer.js',
|
||||||
//'delete/DeleteTimer.js',
|
// 'delete/DeleteTimer.js',
|
||||||
'create/CreateWebPage.js',
|
'create/CreateWebPage.js',
|
||||||
//'delete/DeleteWebPage.js',
|
'delete/DeleteWebPage.js',
|
||||||
'UI/Fullscreen.js',
|
'UI/Fullscreen.js',
|
||||||
'create/CreateButton.js',
|
'create/CreateButton.js',
|
||||||
//"UI/DragDrop.js",
|
//"UI/DragDrop.js",
|
||||||
//"UI/NewWindow.js",
|
"UI/NewWindow.js"
|
||||||
'UI/InfoBubble.js'
|
//'UI/InfoBubble.js',
|
||||||
|
//'UI/RightClick.js'
|
||||||
],
|
],
|
||||||
capabilities: {
|
capabilities: {
|
||||||
'browserName': 'chrome', // or 'safari'
|
'browserName': 'chrome', // or 'safari'
|
||||||
@ -61,7 +61,7 @@ exports.config = {
|
|||||||
|
|
||||||
// Allow specifying binary location as an environment variable,
|
// Allow specifying binary location as an environment variable,
|
||||||
// for cases where Chrome is not installed in a usual location.
|
// for cases where Chrome is not installed in a usual location.
|
||||||
if (process.env.PROTRACTOR_CHROME_BINARY) {
|
if (process.env.CHROME_BIN) {
|
||||||
exports.config.capabilities.chromeOptions.binary =
|
exports.config.capabilities.chromeOptions.binary =
|
||||||
process.env.PROTRACTOR_CHROME_BINARY;
|
process.env.CHROME_BIN;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
var itemCreate = require("../common/CreateItem");
|
var itemCreate = require("../common/CreateItem");
|
||||||
var itemEdit = require("../common/EditItem");
|
var itemEdit = require("../common/EditItem");
|
||||||
|
|
||||||
describe('Create Web Page', function() {
|
describe('Create Activity Mode', function() {
|
||||||
var createClass = new itemCreate();
|
var createClass = new itemCreate();
|
||||||
var editItemClass = new itemEdit();
|
var editItemClass = new itemEdit();
|
||||||
var ITEM_NAME = "Activity Mode";
|
var ITEM_NAME = "Activity Mode";
|
||||||
|
@ -57,7 +57,7 @@ describe('Create Clock', function() {
|
|||||||
});
|
});
|
||||||
it('should check clock', function () {
|
it('should check clock', function () {
|
||||||
|
|
||||||
function getTime() {
|
function getTime(flag) {
|
||||||
function addZero(time){
|
function addZero(time){
|
||||||
if(time < 10){
|
if(time < 10){
|
||||||
return '0' + time;
|
return '0' + time;
|
||||||
@ -66,7 +66,6 @@ describe('Create Clock', function() {
|
|||||||
}
|
}
|
||||||
var currentdate = new Date();
|
var currentdate = new Date();
|
||||||
|
|
||||||
|
|
||||||
var month = currentdate.getMonth() + 1;
|
var month = currentdate.getMonth() + 1;
|
||||||
month = addZero(month);
|
month = addZero(month);
|
||||||
|
|
||||||
@ -77,6 +76,9 @@ describe('Create Clock', function() {
|
|||||||
hour = addZero(hour);
|
hour = addZero(hour);
|
||||||
|
|
||||||
var second = currentdate.getSeconds();
|
var second = currentdate.getSeconds();
|
||||||
|
if(flag == true) {
|
||||||
|
second = second + 1;
|
||||||
|
}
|
||||||
second = addZero(second);
|
second = addZero(second);
|
||||||
|
|
||||||
var minute = currentdate.getMinutes();
|
var minute = currentdate.getMinutes();
|
||||||
@ -85,17 +87,23 @@ describe('Create Clock', function() {
|
|||||||
return ("UTC " + currentdate.getFullYear() + "/" + (month) + "/" +
|
return ("UTC " + currentdate.getFullYear() + "/" + (month) + "/" +
|
||||||
day + " " + (hour) + ":" + minute + ":" + second + " PM");
|
day + " " + (hour) + ":" + minute + ":" + second + " PM");
|
||||||
}
|
}
|
||||||
|
this.addMatchers({
|
||||||
var current,clock;
|
toBeIn: function(expected){
|
||||||
rightClickClass.select(ITEM_MENU_GLYPH, true).click().then(function () {
|
var posibilities = Array.isArray(this.actual) ? this.actual : [this.actual];
|
||||||
browser.sleep(1000);
|
return posibilities.indexOf(expected) > -1;
|
||||||
current = browser.executeScript(getTime);
|
}
|
||||||
}).then(function () {
|
|
||||||
clock = element(by.css('.l-time-display.l-digital.l-clock.s-clock.ng-scope'));
|
|
||||||
clock.getText().then(function (time) {
|
|
||||||
expect(current).toEqual(time);
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
rightClickClass.select(ITEM_MENU_GLYPH, true).click().then(function () {
|
||||||
|
browser.sleep(1000);
|
||||||
|
browser.executeScript(getTime, false).then(function(current){
|
||||||
|
browser.executeScript(getTime, true).then(function(current1) {
|
||||||
|
var clock = element(by.css('.l-time-display.l-digital.l-clock.s-clock.ng-scope'));
|
||||||
|
clock.getText().then(function (ele) {
|
||||||
|
expect([current,current1]).toBeIn(ele);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -63,7 +63,11 @@ describe('Create Timer', function() {
|
|||||||
browser.sleep(1000)
|
browser.sleep(1000)
|
||||||
var timer = element(by.css('.value.ng-binding.active'))
|
var timer = element(by.css('.value.ng-binding.active'))
|
||||||
timer.getText().then(function (time) {
|
timer.getText().then(function (time) {
|
||||||
expect(time).toEqual("0D 00:00:01")
|
var timerChecker = false;
|
||||||
|
if(time == "0D 00:00:01" || time == "0D 00:00:02"){
|
||||||
|
timerChecker = true;
|
||||||
|
}
|
||||||
|
expect(timerChecker).toEqual(true)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
20
protractor/package.json
Normal file
20
protractor/package.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "ProtractorLauncher",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts" : {
|
||||||
|
"start" : "bin/start.js",
|
||||||
|
"protractor" : "bin/run.js",
|
||||||
|
"stop" : "bin/stop.js",
|
||||||
|
"all" : "bin/start.js; bin/run.js; bin/stop.js;",
|
||||||
|
"clean" : "bin/clean.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"protractor": "^2.1.0",
|
||||||
|
"psnode": "0.0.1",
|
||||||
|
"shelljs": "^0.5.2",
|
||||||
|
"sleep": "^3.0.0",
|
||||||
|
"string": "^3.3.1"
|
||||||
|
},
|
||||||
|
"description": "E2e Protractor Tests.",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
@ -19,10 +19,9 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
//TODO Add filter for duplications/
|
var itemCreate = require("../common/CreateItem");
|
||||||
var itemCreate = require("./common/CreateItem");
|
var itemEdit = require("../common/EditItem");
|
||||||
var itemEdit = require("./common/EditItem");
|
var right_click = require("../common/RightMenu.js");
|
||||||
var right_click = require("./common/RightMenu.js");
|
|
||||||
|
|
||||||
describe('Create Folder', function() {
|
describe('Create Folder', function() {
|
||||||
var clickClass = new right_click();
|
var clickClass = new right_click();
|
||||||
@ -41,31 +40,35 @@ describe('Create Folder', function() {
|
|||||||
});
|
});
|
||||||
it('should Create new Folder', function(){
|
it('should Create new Folder', function(){
|
||||||
browser.sleep(5000);
|
browser.sleep(5000);
|
||||||
for(var i=0; i < 50; i++){
|
for(var i=0; i < 25; i++){
|
||||||
browser.wait(function() {
|
browser.wait(function() {
|
||||||
createClass.createButton().click();
|
createClass.createButton().click();
|
||||||
return true;
|
return true;
|
||||||
}).then(function (){
|
}).then(function (){
|
||||||
var folder = createClass.selectNewItem(ITEM_TYPE);
|
var folder = createClass.selectNewItem(ITEM_TYPE);
|
||||||
expect(folder.getText()).toEqual([ ITEM_MENU_GLYPH ]);
|
expect(folder.getText()).toEqual([ ITEM_MENU_GLYPH ]);
|
||||||
browser.sleep(1000);
|
browser.sleep(500);
|
||||||
folder.click()
|
folder.click()
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
browser.wait(function () {
|
browser.wait(function () {
|
||||||
return element.all(by.model('ngModel[field]')).isDisplayed();
|
return element.all(by.model('ngModel[field]')).isDisplayed();
|
||||||
})
|
})
|
||||||
createClass.fillFolderForum(ITEM_NAME, ITEM_TYPE).click();
|
createClass.fillFolderForum(ITEM_NAME, ITEM_TYPE).click();
|
||||||
browser.sleep(1000);
|
browser.sleep(500);
|
||||||
}).then(function (){
|
}).then(function (){
|
||||||
browser.sleep(1000);
|
browser.sleep(500);
|
||||||
// if(i === 1){
|
clickClass.delete(ITEM_SIDE_SELECT, true);
|
||||||
clickClass.delete(ITEM_SIDE_SELECT, true);
|
//element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click();
|
||||||
element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click();
|
|
||||||
// }else{
|
|
||||||
browser.sleep(1000);
|
var MyItem = ">\nF\nMy Items"
|
||||||
|
element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
|
return ele.getText().then(function(text) {
|
||||||
|
//expect(text).toEqual(MyItem);
|
||||||
|
return text === MyItem;
|
||||||
|
});
|
||||||
|
}).all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click();
|
||||||
// clickClass.delete(ITEM_SIDE_SELECT, false);
|
// clickClass.delete(ITEM_SIDE_SELECT, false);
|
||||||
// }
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
browser.pause();
|
browser.pause();
|
59
protractor/stressTest/StressTestBubble.js
Normal file
59
protractor/stressTest/StressTestBubble.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/StressTestBubble.jsStressTestBubble.js
|
||||||
|
var itemCreate = require("../common/CreateItem");
|
||||||
|
var itemEdit = require("../common/EditItem");
|
||||||
|
var right_click = require("../common/RightMenu.js");
|
||||||
|
|
||||||
|
describe('Create Folder', function() {
|
||||||
|
var clickClass = new right_click();
|
||||||
|
var createClass = new itemCreate();
|
||||||
|
var editItemClass = new itemEdit();
|
||||||
|
var ITEM_NAME = "Folder";
|
||||||
|
var ITEM_TYPE = "folder";
|
||||||
|
var ITEM_MENU_GLYPH = 'F\nFolder';
|
||||||
|
var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items';
|
||||||
|
var ITEM_SIDE_SELECT = ">\nF\nFolder"
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.ignoreSynchronization = true;
|
||||||
|
browser.get('http://localhost:1984/warp/');
|
||||||
|
browser.sleep(2000); // 20 seconds
|
||||||
|
});
|
||||||
|
it('should Create new Folder', function(){
|
||||||
|
browser.sleep(10000);
|
||||||
|
for(var i=0; i < 1000; i++){
|
||||||
|
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
|
return ele.getText().then(function(text) {
|
||||||
|
return text === ">\nF\nMy Items";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//browser.sleep(1000)
|
||||||
|
browser.actions().mouseMove(object.get(0)).perform();
|
||||||
|
//browser.actions().click(protractor.Button.RIGHT).perform();
|
||||||
|
|
||||||
|
element.all(by.css('.items-holder.grid.abs.ng-scope')).click();
|
||||||
|
}
|
||||||
|
browser.pause();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
56
protractor/stressTest/StressTestCreateButton.js
Normal file
56
protractor/stressTest/StressTestCreateButton.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
var itemCreate = require("../common/CreateItem");
|
||||||
|
var itemEdit = require("../common/EditItem");
|
||||||
|
var right_click = require("../common/RightMenu.js");
|
||||||
|
|
||||||
|
describe('Create Folder', function() {
|
||||||
|
var clickClass = new right_click();
|
||||||
|
var createClass = new itemCreate();
|
||||||
|
var editItemClass = new itemEdit();
|
||||||
|
var ITEM_NAME = "Folder";
|
||||||
|
var ITEM_TYPE = "folder";
|
||||||
|
var ITEM_MENU_GLYPH = 'F\nFolder';
|
||||||
|
var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items';
|
||||||
|
var ITEM_SIDE_SELECT = ">\nF\nFolder"
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.ignoreSynchronization = true;
|
||||||
|
browser.get('http://localhost:1984/warp/');
|
||||||
|
browser.sleep(2000); // 20 seconds
|
||||||
|
});
|
||||||
|
it('should Create new Folder', function(){
|
||||||
|
browser.sleep(10000);
|
||||||
|
for(var i=0; i < 1000; i++){
|
||||||
|
createClass.createButton().click();
|
||||||
|
|
||||||
|
//browser.sleep(1000)
|
||||||
|
//browser.actions().mouseMove(object.get(0)).perform();
|
||||||
|
//browser.actions().click(protractor.Button.RIGHT).perform();
|
||||||
|
|
||||||
|
element.all(by.css('.items-holder.grid.abs.ng-scope')).click();
|
||||||
|
}
|
||||||
|
browser.pause();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
55
protractor/stressTest/StressTestMenu.js
Normal file
55
protractor/stressTest/StressTestMenu.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
var itemCreate = require("../common/CreateItem");
|
||||||
|
var itemEdit = require("../common/EditItem");
|
||||||
|
var right_click = require("../common/RightMenu.js");
|
||||||
|
|
||||||
|
describe('Create Folder', function() {
|
||||||
|
var clickClass = new right_click();
|
||||||
|
var createClass = new itemCreate();
|
||||||
|
var editItemClass = new itemEdit();
|
||||||
|
var ITEM_NAME = "Folder";
|
||||||
|
var ITEM_TYPE = "folder";
|
||||||
|
var ITEM_MENU_GLYPH = 'F\nFolder';
|
||||||
|
var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items';
|
||||||
|
var ITEM_SIDE_SELECT = ">\nF\nFolder"
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.ignoreSynchronization = true;
|
||||||
|
browser.get('http://localhost:1984/warp/');
|
||||||
|
browser.sleep(2000); // 20 seconds
|
||||||
|
});
|
||||||
|
it('should Create new Folder', function(){
|
||||||
|
browser.sleep(10000);
|
||||||
|
for(var i=0; i < 1000; i++){
|
||||||
|
browser.wait(function() {
|
||||||
|
createClass.createButton().click();
|
||||||
|
return true;
|
||||||
|
}).then(function (){
|
||||||
|
element.all(by.css('.items-holder.grid.abs.ng-scope')).click();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
browser.pause();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
61
protractor/stressTest/StressTestNewPage.js
Normal file
61
protractor/stressTest/StressTestNewPage.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
var itemCreate = require("../common/CreateItem");
|
||||||
|
var itemEdit = require("../common/EditItem");
|
||||||
|
var right_click = require("../common/RightMenu.js");
|
||||||
|
var fullScreenFile = require("../common/FullScreen");
|
||||||
|
|
||||||
|
describe('Create Folder', function() {
|
||||||
|
var clickClass = new right_click();
|
||||||
|
var createClass = new itemCreate();
|
||||||
|
var editItemClass = new itemEdit();
|
||||||
|
var fullScreenClass = new fullScreenFile();
|
||||||
|
|
||||||
|
var ITEM_NAME = "Folder";
|
||||||
|
var ITEM_TYPE = "folder";
|
||||||
|
var ITEM_MENU_GLYPH = 'F\nFolder';
|
||||||
|
var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items';
|
||||||
|
var ITEM_SIDE_SELECT = ">\nF\nFolder"
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.ignoreSynchronization = true;
|
||||||
|
browser.get('http://localhost:1984/warp/');
|
||||||
|
browser.sleep(2000); // 20 seconds
|
||||||
|
});
|
||||||
|
it('should Create new Folder', function(){
|
||||||
|
browser.sleep(15000);
|
||||||
|
for(var i=0; i < 1000; i++){
|
||||||
|
fullScreenClass.newWidnow().click();
|
||||||
|
|
||||||
|
browser.getAllWindowHandles().then(function (handles) {
|
||||||
|
//browser.driver.switchTo().window(handles[1]);
|
||||||
|
browser.sleep(1000);
|
||||||
|
browser.driver.close();
|
||||||
|
browser.sleep(1000);
|
||||||
|
// browser.driver.switchTo().window(handles[0]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
browser.pause();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
59
protractor/stressTest/StressTestRightClick.js
Normal file
59
protractor/stressTest/StressTestRightClick.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
var itemCreate = require("../common/CreateItem");
|
||||||
|
var itemEdit = require("../common/EditItem");
|
||||||
|
var right_click = require("../common/RightMenu.js");
|
||||||
|
|
||||||
|
describe('Create Folder', function() {
|
||||||
|
var clickClass = new right_click();
|
||||||
|
var createClass = new itemCreate();
|
||||||
|
var editItemClass = new itemEdit();
|
||||||
|
var ITEM_NAME = "Folder";
|
||||||
|
var ITEM_TYPE = "folder";
|
||||||
|
var ITEM_MENU_GLYPH = 'F\nFolder';
|
||||||
|
var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items';
|
||||||
|
var ITEM_SIDE_SELECT = ">\nF\nFolder"
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.ignoreSynchronization = true;
|
||||||
|
browser.get('http://localhost:1984/warp/');
|
||||||
|
browser.sleep(2000); // 20 seconds
|
||||||
|
});
|
||||||
|
it('should Create new Folder', function(){
|
||||||
|
browser.sleep(8000);
|
||||||
|
for(var i=0; i < 1000; i++){
|
||||||
|
var object = element.all(by.repeater('child in composition')).filter(function (ele){
|
||||||
|
return ele.getText().then(function(text) {
|
||||||
|
return text === ">\nF\nMy Items";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//browser.sleep(1000)
|
||||||
|
browser.actions().mouseMove(object.get(0)).perform();
|
||||||
|
browser.actions().click(protractor.Button.RIGHT).perform();
|
||||||
|
|
||||||
|
element.all(by.css('.items-holder.grid.abs.ng-scope')).click();
|
||||||
|
}
|
||||||
|
browser.pause();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user