Compare commits
	
		
			23 Commits
		
	
	
		
			tc-nav-abo
			...
			couchdb-te
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | a5c61ec1b7 | ||
|   | f6ecabb053 | ||
|   | 831f207b10 | ||
|   | 42e474ca60 | ||
|   | d767932be2 | ||
|   | 0238a86be5 | ||
|   | 7abbd7cb20 | ||
|   | 6e2b12b00d | ||
|   | 6a2520f39b | ||
|   | 5b7a011069 | ||
|   | d216117b30 | ||
|   | 5c520bfce9 | ||
|   | cba9670823 | ||
|   | 27651e9eaa | ||
|   | f096d54dd0 | ||
|   | 8258f21f7b | ||
|   | 44bfcf33ef | ||
|   | 669415d362 | ||
|   | 8601ec441f | ||
|   | 9a57a20404 | ||
|   | 1a3bff9813 | ||
|   | baa5f21640 | ||
|   | af9dceee3c | 
| @@ -23,7 +23,7 @@ | ||||
| /*global module,process*/ | ||||
|  | ||||
| const devMode = process.env.NODE_ENV !== 'production'; | ||||
| const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'FirefoxHeadless']; | ||||
| const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless']; | ||||
| const coverageEnabled = process.env.COVERAGE === 'true'; | ||||
| const reporters = ['progress', 'html']; | ||||
|  | ||||
| @@ -70,7 +70,7 @@ module.exports = (config) => { | ||||
|             } | ||||
|         }, | ||||
|         colors: true, | ||||
|         logLevel: config.LOG_INFO, | ||||
|         logLevel: config.LOG_DEBUG, | ||||
|         autoWatch: true, | ||||
|         // HTML test reporting. | ||||
|         htmlReporter: { | ||||
|   | ||||
| @@ -79,12 +79,6 @@ function ( | ||||
|         return this.objectService; | ||||
|     }; | ||||
|  | ||||
|     function resolveWith(object) { | ||||
|         return function () { | ||||
|             return object; | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|          * Save changes and conclude editing. | ||||
|          * | ||||
| @@ -102,7 +96,6 @@ function ( | ||||
|     SaveAsAction.prototype.save = function () { | ||||
|         var self = this, | ||||
|             domainObject = this.domainObject, | ||||
|             copyService = this.copyService, | ||||
|             dialog = new SaveInProgressDialog(this.dialogService), | ||||
|             toUndirty = []; | ||||
|  | ||||
| @@ -139,19 +132,22 @@ function ( | ||||
|             return fetchObject(object.getModel().location); | ||||
|         } | ||||
|  | ||||
|         function allowClone(objectToClone) { | ||||
|             var allowed = | ||||
|                     (objectToClone.getId() === domainObject.getId()) | ||||
|                         || objectToClone.getCapability('location').isOriginal(); | ||||
|             if (allowed) { | ||||
|                 toUndirty.push(objectToClone); | ||||
|             } | ||||
|  | ||||
|             return allowed; | ||||
|         function saveObject(parent) { | ||||
|             return this.openmct.editor.save().then(() => { | ||||
|                 // Force mutation for search indexing | ||||
|                 return parent; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         function cloneIntoParent(parent) { | ||||
|             return copyService.perform(domainObject, parent, allowClone); | ||||
|         function addSavedObjectToParent(parent) { | ||||
|             return parent.getCapability("composition") | ||||
|                 .add(domainObject) | ||||
|                 .then(function (addedObject) { | ||||
|                     return parent.getCapability("persistence").persist() | ||||
|                         .then(function () { | ||||
|                             return addedObject; | ||||
|                         }); | ||||
|                 }); | ||||
|         } | ||||
|  | ||||
|         function undirty(object) { | ||||
| @@ -160,26 +156,17 @@ function ( | ||||
|  | ||||
|         function undirtyOriginals(object) { | ||||
|             return Promise.all(toUndirty.map(undirty)) | ||||
|                 .then(resolveWith(object)); | ||||
|                 .then(() => { | ||||
|                     return object; | ||||
|                 }); | ||||
|         } | ||||
|  | ||||
|         function saveAfterClone(clonedObject) { | ||||
|             return this.openmct.editor.save().then(() => { | ||||
|                 // Force mutation for search indexing | ||||
|                 return clonedObject; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         function finishEditing(clonedObject) { | ||||
|             return fetchObject(clonedObject.getId()); | ||||
|         } | ||||
|  | ||||
|         function indexForSearch(savedObject) { | ||||
|             savedObject.useCapability('mutation', (model) => { | ||||
|         function indexForSearch(addedObject) { | ||||
|             addedObject.useCapability('mutation', (model) => { | ||||
|                 return model; | ||||
|             }); | ||||
|  | ||||
|             return savedObject; | ||||
|             return addedObject; | ||||
|         } | ||||
|  | ||||
|         function onSuccess(object) { | ||||
| @@ -201,10 +188,12 @@ function ( | ||||
|             .then(doWizardSave) | ||||
|             .then(showBlockingDialog) | ||||
|             .then(getParent) | ||||
|             .then(cloneIntoParent) | ||||
|             .then(saveObject) | ||||
|             .then(addSavedObjectToParent) | ||||
|             .then(undirtyOriginals) | ||||
|             .then(saveAfterClone) | ||||
|             .then(finishEditing) | ||||
|             .then((addedObject) => { | ||||
|                 return fetchObject(addedObject.getId()); | ||||
|             }) | ||||
|             .then(indexForSearch) | ||||
|             .then(hideBlockingDialog) | ||||
|             .then(onSuccess) | ||||
|   | ||||
| @@ -422,7 +422,10 @@ define([ | ||||
|  | ||||
|                 this.router.start(); | ||||
|                 this.emit('start'); | ||||
|             }.bind(this)); | ||||
|             }.bind(this), function () { | ||||
|                 console.log('startPromise failed'); | ||||
|                 this.emit('start'); | ||||
|             }); | ||||
|     }; | ||||
|  | ||||
|     MCT.prototype.startHeadless = function () { | ||||
|   | ||||
| @@ -35,7 +35,8 @@ define([ | ||||
|     './services/LegacyObjectAPIInterceptor', | ||||
|     './views/installLegacyViews', | ||||
|     './policies/LegacyCompositionPolicyAdapter', | ||||
|     './actions/LegacyActionAdapter' | ||||
|     './actions/LegacyActionAdapter', | ||||
|     './services/LegacyPersistenceAdapter' | ||||
| ], function ( | ||||
|     ActionDialogDecorator, | ||||
|     AdapterCapability, | ||||
| @@ -51,7 +52,8 @@ define([ | ||||
|     LegacyObjectAPIInterceptor, | ||||
|     installLegacyViews, | ||||
|     legacyCompositionPolicyAdapter, | ||||
|     LegacyActionAdapter | ||||
|     LegacyActionAdapter, | ||||
|     LegacyPersistenceAdapter | ||||
| ) { | ||||
|     return { | ||||
|         name: 'src/adapter', | ||||
| @@ -114,6 +116,13 @@ define([ | ||||
|                             "instantiate", | ||||
|                             "topic" | ||||
|                         ] | ||||
|                     }, | ||||
|                     { | ||||
|                         provides: "persistenceService", | ||||
|                         type: "provider", | ||||
|                         priority: "fallback", | ||||
|                         implementation: LegacyPersistenceAdapter.default, | ||||
|                         depends: ["openmct"] | ||||
|                     } | ||||
|                 ], | ||||
|                 policies: [ | ||||
|   | ||||
							
								
								
									
										29
									
								
								src/adapter/services/LegacyPersistenceAdapter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/adapter/services/LegacyPersistenceAdapter.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| import objectUtils from 'objectUtils'; | ||||
|  | ||||
| function LegacyPersistenceProvider(openmct) { | ||||
|     this.openmct = openmct; | ||||
| } | ||||
|  | ||||
| LegacyPersistenceProvider.prototype.listObjects = function () { | ||||
|     return Promise.resolve([]); | ||||
| }; | ||||
|  | ||||
| LegacyPersistenceProvider.prototype.listSpaces = function () { | ||||
|     return Promise.resolve(Object.keys(this.openmct.objects.providers)); | ||||
| }; | ||||
|  | ||||
| LegacyPersistenceProvider.prototype.updateObject = function (legacyDomainObject) { | ||||
|     return this.openmct.objects.save(legacyDomainObject.useCapability('adapter')); | ||||
| }; | ||||
|  | ||||
| LegacyPersistenceProvider.prototype.updateObject = function (legacyDomainObject) { | ||||
|     return this.openmct.objects.save(legacyDomainObject.useCapability('adapter')); | ||||
| }; | ||||
|  | ||||
| LegacyPersistenceProvider.prototype.readObject = function (keystring) { | ||||
|     let identifier = objectUtils.parseKeyString(keystring); | ||||
|  | ||||
|     return this.openmct.legacyObject(this.openmct.objects.get(identifier)); | ||||
| }; | ||||
|  | ||||
| export default LegacyPersistenceProvider; | ||||
| @@ -81,17 +81,17 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|             expect(window.location.hash.includes('tc.mode=fixed')).toBe(false); | ||||
|         }); | ||||
|         describe("when set in the url", () => { | ||||
|             it("will change from fixed to realtime mode when the mode changes", () => { | ||||
|             it("will change from fixed to realtime mode when the mode changes", (done) => { | ||||
|                 expectLocationToBeInFixedMode(); | ||||
|  | ||||
|                 return switchToRealtimeMode().then(() => { | ||||
|                     let clock = openmct.time.clock(); | ||||
|  | ||||
|                     expect(clock).toBeDefined(); | ||||
|                     expect(clock.key).toBe('local'); | ||||
|                     done(); | ||||
|                 }); | ||||
|             }); | ||||
|             it("the clock is correctly set in the API from the URL parameters", () => { | ||||
|             it("the clock is correctly set in the API from the URL parameters", (done) => { | ||||
|                 return switchToRealtimeMode().then(() => { | ||||
|                     let resolveFunction; | ||||
|  | ||||
| @@ -109,10 +109,11 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|                         expect(clock).toBeDefined(); | ||||
|                         expect(clock.key).toBe('test-clock'); | ||||
|                         openmct.time.off('clock', resolveFunction); | ||||
|                         done(); | ||||
|                     }); | ||||
|                 }); | ||||
|             }); | ||||
|             it("the clock offsets are correctly set in the API from the URL parameters", () => { | ||||
|             it("the clock offsets are correctly set in the API from the URL parameters", (done) => { | ||||
|                 return switchToRealtimeMode().then(() => { | ||||
|                     let resolveFunction; | ||||
|  | ||||
| @@ -131,10 +132,11 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|                         expect(clockOffsets.start).toBe(-2000); | ||||
|                         expect(clockOffsets.end).toBe(200); | ||||
|                         openmct.time.off('clockOffsets', resolveFunction); | ||||
|                         done(); | ||||
|                     }); | ||||
|                 }); | ||||
|             }); | ||||
|             it("the time system is correctly set in the API from the URL parameters", () => { | ||||
|             it("the time system is correctly set in the API from the URL parameters", (done) => { | ||||
|                 return switchToRealtimeMode().then(() => { | ||||
|                     let resolveFunction; | ||||
|  | ||||
| @@ -152,6 +154,7 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|                         expect(timeSystem).toBeDefined(); | ||||
|                         expect(timeSystem.key).toBe('local'); | ||||
|                         openmct.time.off('timeSystem', resolveFunction); | ||||
|                         done(); | ||||
|                     }); | ||||
|                 }); | ||||
|             }); | ||||
| @@ -199,7 +202,7 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|             expect(window.location.hash.includes('tc.timeSystem=utc')).toBe(false); | ||||
|         }); | ||||
|         describe("when set in the url", () => { | ||||
|             it("time system changes are reflected in the API", () => { | ||||
|             it("time system changes are reflected in the API", (done) => { | ||||
|                 let resolveFunction; | ||||
|  | ||||
|                 return new Promise((resolve) => { | ||||
| @@ -215,9 +218,10 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|                     expect(timeSystem.key).toBe('local'); | ||||
|  | ||||
|                     openmct.time.off('timeSystem', resolveFunction); | ||||
|                     done(); | ||||
|                 }); | ||||
|             }); | ||||
|             it("mode can be changed from realtime to fixed", () => { | ||||
|             it("mode can be changed from realtime to fixed", (done) => { | ||||
|                 return switchToRealtimeMode().then(() => { | ||||
|                     expectLocationToBeInRealtimeMode(); | ||||
|  | ||||
| @@ -225,9 +229,10 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|                 }).then(switchToFixedMode).then(() => { | ||||
|                     let clock = openmct.time.clock(); | ||||
|                     expect(clock).not.toBeDefined(); | ||||
|                     done(); | ||||
|                 }); | ||||
|             }); | ||||
|             it("bounds are correctly set in the API from the URL parameters", () => { | ||||
|             it("bounds are correctly set in the API from the URL parameters", (done) => { | ||||
|                 let resolveFunction; | ||||
|  | ||||
|                 expectLocationToBeInFixedMode(); | ||||
| @@ -245,9 +250,10 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|                     expect(bounds).toBeDefined(); | ||||
|                     expect(bounds.start).toBe(222); | ||||
|                     expect(bounds.end).toBe(333); | ||||
|                     done(); | ||||
|                 }); | ||||
|             }); | ||||
|             it("bounds are correctly set in the API from the URL parameters where only the end bound changes", () => { | ||||
|             it("bounds are correctly set in the API from the URL parameters where only the end bound changes", (done) => { | ||||
|                 let resolveFunction; | ||||
|  | ||||
|                 expectLocationToBeInFixedMode(); | ||||
| @@ -264,6 +270,7 @@ describe("The URLTimeSettingsSynchronizer", () => { | ||||
|                     expect(bounds).toBeDefined(); | ||||
|                     expect(bounds.start).toBe(0); | ||||
|                     expect(bounds.end).toBe(333); | ||||
|                     done(); | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|   | ||||
							
								
								
									
										53
									
								
								src/plugins/persistence/couch/CouchDocument.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/plugins/persistence/couch/CouchDocument.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2018, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT 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 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /** | ||||
|  * A CouchDocument describes domain object model in a format | ||||
|  * which is easily read-written to CouchDB. This includes | ||||
|  * Couch's _id and _rev fields, as well as a separate | ||||
|  * metadata field which contains a subset of information found | ||||
|  * in the model itself (to support search optimization with | ||||
|  * CouchDB views.) | ||||
|  * @memberof platform/persistence/couch | ||||
|  * @constructor | ||||
|  * @param {string} id the id under which to store this mode | ||||
|  * @param {object} model the model to store | ||||
|  * @param {string} rev the revision to include (or undefined, | ||||
|  *        if no revision should be noted for couch) | ||||
|  * @param {boolean} whether or not to mark this document as | ||||
|  *        deleted (see CouchDB docs for _deleted) | ||||
|  */ | ||||
| export default function CouchDocument(id, model, rev, markDeleted) { | ||||
|     return { | ||||
|         "_id": id, | ||||
|         "_rev": rev, | ||||
|         "_deleted": markDeleted, | ||||
|         "metadata": { | ||||
|             "category": "domain object", | ||||
|             "type": model.type, | ||||
|             "owner": "admin", | ||||
|             "name": model.name, | ||||
|             "created": Date.now() | ||||
|         }, | ||||
|         "model": model | ||||
|     }; | ||||
| } | ||||
							
								
								
									
										134
									
								
								src/plugins/persistence/couch/CouchObjectProvider.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								src/plugins/persistence/couch/CouchObjectProvider.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| import CouchDocument from "./CouchDocument"; | ||||
| import CouchObjectQueue from "./CouchObjectQueue"; | ||||
|  | ||||
| const REV = "_rev"; | ||||
| const ID = "_id"; | ||||
|  | ||||
| export default class CouchObjectProvider { | ||||
|     constructor(openmct, url, namespace) { | ||||
|         this.openmct = openmct; | ||||
|         this.url = url; | ||||
|         this.namespace = namespace; | ||||
|         this.objectQueue = {}; | ||||
|     } | ||||
|  | ||||
|     request(subPath, method, value) { | ||||
|         return fetch(this.url + '/' + subPath, { | ||||
|             method: method, | ||||
|             body: JSON.stringify(value) | ||||
|         }).then(response => response.json()) | ||||
|             .then(function (response) { | ||||
|                 return response; | ||||
|             }, function () { | ||||
|                 return undefined; | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     // Check the response to a create/update/delete request; | ||||
|     // track the rev if it's valid, otherwise return false to | ||||
|     // indicate that the request failed. | ||||
|     // persist any queued objects | ||||
|     checkResponse(response, intermediateResponse) { | ||||
|         let requestSuccess = false; | ||||
|         const id = response.id; | ||||
|         let rev; | ||||
|         if (response && response.ok) { | ||||
|             rev = response.rev; | ||||
|             requestSuccess = true; | ||||
|         } | ||||
|  | ||||
|         intermediateResponse.resolve(requestSuccess); | ||||
|  | ||||
|         if (id) { | ||||
|             if (!this.objectQueue[id]) { | ||||
|                 this.objectQueue[id] = new CouchObjectQueue(undefined, rev); | ||||
|             } | ||||
|  | ||||
|             this.objectQueue[id].updateRevision(rev); | ||||
|             this.objectQueue[id].pending = false; | ||||
|             if (this.objectQueue[id].hasNext()) { | ||||
|                 this.updateQueued(id); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     getModel(response) { | ||||
|         if (response && response.model) { | ||||
|             let key = response[ID]; | ||||
|             let object = response.model; | ||||
|             object.identifier = { | ||||
|                 namespace: this.namespace, | ||||
|                 key: key | ||||
|             }; | ||||
|             if (!this.objectQueue[key]) { | ||||
|                 this.objectQueue[key] = new CouchObjectQueue(undefined, response[REV]); | ||||
|             } | ||||
|  | ||||
|             this.objectQueue[key].updateRevision(response[REV]); | ||||
|  | ||||
|             return object; | ||||
|         } else { | ||||
|             return undefined; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     get(identifier) { | ||||
|         return this.request(identifier.key, "GET").then(this.getModel.bind(this)); | ||||
|     } | ||||
|  | ||||
|     getIntermediateResponse() { | ||||
|         let intermediateResponse = {}; | ||||
|         intermediateResponse.promise = new Promise(function (resolve, reject) { | ||||
|             intermediateResponse.resolve = resolve; | ||||
|             intermediateResponse.reject = reject; | ||||
|         }); | ||||
|  | ||||
|         return intermediateResponse; | ||||
|     } | ||||
|  | ||||
|     enqueueObject(key, model, intermediateResponse) { | ||||
|         if (this.objectQueue[key]) { | ||||
|             this.objectQueue[key].enqueue({ | ||||
|                 model, | ||||
|                 intermediateResponse | ||||
|             }); | ||||
|         } else { | ||||
|             this.objectQueue[key] = new CouchObjectQueue({ | ||||
|                 model, | ||||
|                 intermediateResponse | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     create(model) { | ||||
|         let intermediateResponse = this.getIntermediateResponse(); | ||||
|         const key = model.identifier.key; | ||||
|         this.enqueueObject(key, model, intermediateResponse); | ||||
|         this.objectQueue[key].pending = true; | ||||
|         const queued = this.objectQueue[key].dequeue(); | ||||
|         this.request(key, "PUT", new CouchDocument(key, queued.model)).then((response) => { | ||||
|             this.checkResponse(response, queued.intermediateResponse); | ||||
|         }); | ||||
|  | ||||
|         return intermediateResponse.promise; | ||||
|     } | ||||
|  | ||||
|     updateQueued(key) { | ||||
|         if (!this.objectQueue[key].pending) { | ||||
|             this.objectQueue[key].pending = true; | ||||
|             const queued = this.objectQueue[key].dequeue(); | ||||
|             this.request(key, "PUT", new CouchDocument(key, queued.model, this.objectQueue[key].rev)).then((response) => { | ||||
|                 this.checkResponse(response, queued.intermediateResponse); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     update(model) { | ||||
|         let intermediateResponse = this.getIntermediateResponse(); | ||||
|         const key = model.identifier.key; | ||||
|         this.enqueueObject(key, model, intermediateResponse); | ||||
|         this.updateQueued(key); | ||||
|  | ||||
|         return intermediateResponse.promise; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/plugins/persistence/couch/CouchObjectQueue.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/plugins/persistence/couch/CouchObjectQueue.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| //TODO: should we limit the queue size? | ||||
| //const MAX_QUEUE_SIZE = 10; | ||||
|  | ||||
| export default class CouchObjectQueue { | ||||
|     constructor(object, rev) { | ||||
|         this.rev = rev; | ||||
|         this.objects = object ? [object] : []; | ||||
|         this.pending = false; | ||||
|     } | ||||
|  | ||||
|     updateRevision(rev) { | ||||
|         this.rev = rev; | ||||
|     } | ||||
|  | ||||
|     hasNext() { | ||||
|         return this.objects.length; | ||||
|     } | ||||
|  | ||||
|     enqueue(item) { | ||||
|         this.objects.push(item); | ||||
|     } | ||||
|  | ||||
|     dequeue() { | ||||
|         return this.objects.shift(); | ||||
|     } | ||||
|  | ||||
|     clear() { | ||||
|         this.rev = undefined; | ||||
|         this.objects = []; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/plugins/persistence/couch/plugin.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/plugins/persistence/couch/plugin.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| import CouchObjectProvider from './CouchObjectProvider'; | ||||
| const NAMESPACE = ''; | ||||
|  | ||||
| export default function CouchPlugin(url) { | ||||
|     return function install(openmct) { | ||||
|         openmct.objects.addProvider(NAMESPACE, new CouchObjectProvider(openmct, url, NAMESPACE)); | ||||
|     }; | ||||
| } | ||||
							
								
								
									
										102
									
								
								src/plugins/persistence/couch/pluginSpec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/plugins/persistence/couch/pluginSpec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2020, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT 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 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. | ||||
|  *****************************************************************************/ | ||||
| import CouchPlugin from './plugin.js'; | ||||
| import { | ||||
|     createOpenMct, | ||||
|     resetApplicationState | ||||
| } from 'utils/testing'; | ||||
| import CouchObjectProvider from "@/plugins/persistence/couch/CouchObjectProvider"; | ||||
| import CouchObjectQueue from "@/plugins/persistence/couch/CouchObjectQueue"; | ||||
|  | ||||
| describe("the plugin", () => { | ||||
|     let openmct; | ||||
|     let element; | ||||
|     let child; | ||||
|     let provider; | ||||
|     let testSpace = "testSpace"; | ||||
|     let testPath = "/test/db"; | ||||
|     let mockDomainObject = { | ||||
|         identifier: { | ||||
|             namespace: '', | ||||
|             key: "some-value" | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     beforeEach((done) => { | ||||
|         openmct = createOpenMct(false); | ||||
|         openmct.install(new CouchPlugin(testSpace, testPath)); | ||||
|  | ||||
|         element = document.createElement('div'); | ||||
|         child = document.createElement('div'); | ||||
|         element.appendChild(child); | ||||
|  | ||||
|         openmct.on('start', done); | ||||
|         openmct.startHeadless(); | ||||
|  | ||||
|         provider = openmct.objects.getProvider(mockDomainObject.identifier); | ||||
|     }); | ||||
|  | ||||
|     it('registers a provider for objects', () => { | ||||
|         expect(provider).toBeDefined(); | ||||
|     }); | ||||
|  | ||||
|     it('gets an object', () => { | ||||
|         openmct.objects.get(mockDomainObject.identifier).then((result) => { | ||||
|             expect(provider.get).toHaveBeenCalled(); | ||||
|             expect(result).toBeDefined(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('creates an object', () => { | ||||
|         openmct.objects.save(mockDomainObject).then((result) => { | ||||
|             expect(provider.create).toHaveBeenCalled(); | ||||
|             expect(result).toBeDefined(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('updates an object', () => { | ||||
|         openmct.objects.save(mockDomainObject).then((result) => { | ||||
|             expect(provider.create).toHaveBeenCalled(); | ||||
|             openmct.objects.save(mockDomainObject).then((updatedResult) => { | ||||
|                 expect(provider.update).toHaveBeenCalled(); | ||||
|                 expect(updatedResult).toBeDefined(); | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('updates queued objects', () => { | ||||
|         let couchProvider = new CouchObjectProvider(openmct, 'http://localhost', ''); | ||||
|         let intermediateResponse = couchProvider.getIntermediateResponse(); | ||||
|         spyOn(couchProvider, 'updateQueued'); | ||||
|         couchProvider.enqueueObject(mockDomainObject.identifier.key, mockDomainObject, intermediateResponse); | ||||
|         couchProvider.objectQueue[mockDomainObject.identifier.key].updateRevision(1); | ||||
|         couchProvider.update(mockDomainObject); | ||||
|         expect(couchProvider.objectQueue[mockDomainObject.identifier.key].hasNext()).toBe(2); | ||||
|         couchProvider.checkResponse({ | ||||
|             ok: true, | ||||
|             rev: 2, | ||||
|             id: mockDomainObject.identifier.key | ||||
|         }, intermediateResponse); | ||||
|  | ||||
|         expect(couchProvider.updateQueued).toHaveBeenCalledTimes(2); | ||||
|     }); | ||||
| }); | ||||
| @@ -54,7 +54,8 @@ define([ | ||||
|     './themes/snow', | ||||
|     './URLTimeSettingsSynchronizer/plugin', | ||||
|     './notificationIndicator/plugin', | ||||
|     './newFolderAction/plugin' | ||||
|     './newFolderAction/plugin', | ||||
|     './persistence/couch/plugin' | ||||
| ], function ( | ||||
|     _, | ||||
|     UTCTimeSystem, | ||||
| @@ -89,12 +90,12 @@ define([ | ||||
|     Snow, | ||||
|     URLTimeSettingsSynchronizer, | ||||
|     NotificationIndicator, | ||||
|     NewFolderAction | ||||
|     NewFolderAction, | ||||
|     CouchDBPlugin | ||||
| ) { | ||||
|     var bundleMap = { | ||||
|         LocalStorage: 'platform/persistence/local', | ||||
|         MyItems: 'platform/features/my-items', | ||||
|         CouchDB: 'platform/persistence/couch', | ||||
|         Elasticsearch: 'platform/persistence/elastic' | ||||
|     }; | ||||
|  | ||||
| @@ -126,27 +127,7 @@ define([ | ||||
|  | ||||
|     plugins.Conductor = TimeConductorPlugin.default; | ||||
|  | ||||
|     plugins.CouchDB = function (url) { | ||||
|         return function (openmct) { | ||||
|             if (url) { | ||||
|                 var bundleName = "config/couch"; | ||||
|                 openmct.legacyRegistry.register(bundleName, { | ||||
|                     "extensions": { | ||||
|                         "constants": [ | ||||
|                             { | ||||
|                                 "key": "COUCHDB_PATH", | ||||
|                                 "value": url, | ||||
|                                 "priority": "mandatory" | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 }); | ||||
|                 openmct.legacyRegistry.enable(bundleName); | ||||
|             } | ||||
|  | ||||
|             openmct.legacyRegistry.enable(bundleMap.CouchDB); | ||||
|         }; | ||||
|     }; | ||||
|     plugins.CouchDB = CouchDBPlugin.default; | ||||
|  | ||||
|     plugins.Elasticsearch = function (url) { | ||||
|         return function (openmct) { | ||||
|   | ||||
| @@ -178,7 +178,7 @@ describe("the plugin", () => { | ||||
|  | ||||
|         it("Renders a row for every telemetry datum returned", () => { | ||||
|             let rows = element.querySelectorAll('table.c-telemetry-table__body tr'); | ||||
|             expect(rows.length).toBe(3); | ||||
|             expect(rows.length).toBe(1); | ||||
|         }); | ||||
|  | ||||
|         it("Renders a column for every item in telemetry metadata", () => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user