Compare commits
9 Commits
remove-dep
...
memory-lea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ac37a481c | ||
|
|
d6474045c3 | ||
|
|
23c10d40a8 | ||
|
|
cc37a5f899 | ||
|
|
177dbec0c5 | ||
|
|
38952b8eb3 | ||
|
|
f19c5699a6 | ||
|
|
cc017e879c | ||
|
|
93172eb180 |
10
app.js
10
app.js
@@ -42,11 +42,11 @@ app.use('/proxyUrl', function proxyRequest(req, res, next) {
|
||||
|
||||
const webpack = require('webpack');
|
||||
const webpackConfig = require('./webpack.config.js');
|
||||
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||
webpackConfig.plugins.push(function() { this.plugin('watch-run', function(watching, callback) { console.log('Begin compile at ' + new Date()); callback(); }) });
|
||||
//webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||
//webpackConfig.plugins.push(function() { this.plugin('watch-run', function(watching, callback) { console.log('Begin compile at ' + new Date()); callback(); }) });
|
||||
|
||||
webpackConfig.entry.openmct = [
|
||||
'webpack-hot-middleware/client?reload=true',
|
||||
// 'webpack-hot-middleware/client?reload=true',
|
||||
webpackConfig.entry.openmct
|
||||
];
|
||||
|
||||
@@ -60,12 +60,12 @@ app.use(require('webpack-dev-middleware')(
|
||||
}
|
||||
));
|
||||
|
||||
app.use(require('webpack-hot-middleware')(
|
||||
/*app.use(require('webpack-hot-middleware')(
|
||||
compiler,
|
||||
{
|
||||
|
||||
}
|
||||
));
|
||||
));*/
|
||||
|
||||
// Expose index.html for development users.
|
||||
app.get('/', function (req, res) {
|
||||
|
||||
@@ -41,11 +41,6 @@ define([
|
||||
"$scope"
|
||||
]
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"templateUrl": "templates/exampleForm.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
47
index.html
47
index.html
@@ -66,6 +66,7 @@
|
||||
<body>
|
||||
</body>
|
||||
<script>
|
||||
(function() {
|
||||
const THIRTY_SECONDS = 30 * 1000;
|
||||
const ONE_MINUTE = THIRTY_SECONDS * 2;
|
||||
const FIVE_MINUTES = ONE_MINUTE * 5;
|
||||
@@ -75,27 +76,30 @@
|
||||
const TWO_HOURS = ONE_HOUR * 2;
|
||||
const ONE_DAY = ONE_HOUR * 24;
|
||||
|
||||
let app = new openmct();
|
||||
|
||||
[
|
||||
'example/eventGenerator'
|
||||
].forEach(
|
||||
openmct.legacyRegistry.enable.bind(openmct.legacyRegistry)
|
||||
app.legacyRegistry.enable.bind(app.legacyRegistry)
|
||||
);
|
||||
|
||||
openmct.install(openmct.plugins.LocalStorage());
|
||||
openmct.install(openmct.plugins.Espresso());
|
||||
openmct.install(openmct.plugins.MyItems());
|
||||
openmct.install(openmct.plugins.Generator());
|
||||
openmct.install(openmct.plugins.ExampleImagery());
|
||||
openmct.install(openmct.plugins.PlanLayout());
|
||||
openmct.install(openmct.plugins.Timeline());
|
||||
openmct.install(openmct.plugins.UTCTimeSystem());
|
||||
openmct.install(openmct.plugins.AutoflowView({
|
||||
app.install(app.plugins.LocalStorage());
|
||||
app.install(app.plugins.Espresso());
|
||||
app.install(app.plugins.MyItems());
|
||||
//app.install(app.plugins.Generator());
|
||||
app.install(app.plugins.ExampleImagery());
|
||||
app.install(app.plugins.PlanLayout());
|
||||
app.install(app.plugins.Timeline());
|
||||
//app.install(app.plugins.Hyperlink());
|
||||
app.install(app.plugins.UTCTimeSystem());
|
||||
app.install(app.plugins.AutoflowView({
|
||||
type: "telemetry.panel"
|
||||
}));
|
||||
openmct.install(openmct.plugins.DisplayLayout({
|
||||
app.install(app.plugins.DisplayLayout({
|
||||
showAsView: ['summary-widget', 'example.imagery']
|
||||
}));
|
||||
openmct.install(openmct.plugins.Conductor({
|
||||
app.install(app.plugins.Conductor({
|
||||
menuOptions: [
|
||||
{
|
||||
name: "Fixed",
|
||||
@@ -185,15 +189,20 @@
|
||||
}
|
||||
]
|
||||
}));
|
||||
openmct.install(openmct.plugins.SummaryWidget());
|
||||
openmct.install(openmct.plugins.Notebook());
|
||||
openmct.install(openmct.plugins.LADTable());
|
||||
openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay']));
|
||||
openmct.install(openmct.plugins.ObjectMigration());
|
||||
openmct.install(openmct.plugins.ClearData(
|
||||
app.install(app.plugins.SummaryWidget());
|
||||
app.install(app.plugins.Notebook());
|
||||
app.install(app.plugins.LADTable());
|
||||
app.install(app.plugins.Filters(['table', 'telemetry.plot.overlay']));
|
||||
app.install(app.plugins.ObjectMigration());
|
||||
app.install(app.plugins.ClearData(
|
||||
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
|
||||
{indicator: true}
|
||||
));
|
||||
openmct.start();
|
||||
app.start();
|
||||
|
||||
setTimeout(() => {
|
||||
app.destroy();
|
||||
}, 5000)
|
||||
})();
|
||||
</script>
|
||||
</html>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
const testsContext = require.context('.', true, /\/(src|platform)\/.*Spec.js$/);
|
||||
import MemoryLeaksReporter from "./src/utils/testing/MemoryLeaksReporter";
|
||||
|
||||
jasmine.getEnv().addReporter(new MemoryLeaksReporter());
|
||||
|
||||
const testsContext = require.context('.', true, /\/(src|platform)\/.*Spec.js$/);
|
||||
testsContext.keys().forEach(testsContext);
|
||||
console.error("Done running tests?");
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
/*global module,process*/
|
||||
|
||||
const devMode = process.env.NODE_ENV !== 'production';
|
||||
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless'];
|
||||
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeMemory'];
|
||||
const coverageEnabled = process.env.COVERAGE === 'true';
|
||||
const reporters = ['progress', 'html', 'junit'];
|
||||
|
||||
@@ -64,7 +64,11 @@ module.exports = (config) => {
|
||||
}
|
||||
},
|
||||
customLaunchers: {
|
||||
ChromeDebugging: {
|
||||
ChromeMemory: {
|
||||
base: 'ChromeHeadless',
|
||||
flags: ['--enable-precise-memory-info', '--js-flags="--expose-gc --nocrankshaft --noopt"']
|
||||
}
|
||||
/* ChromeDebugging: {
|
||||
base: 'Chrome',
|
||||
flags: ['--remote-debugging-port=9222'],
|
||||
debug: true
|
||||
@@ -72,7 +76,7 @@ module.exports = (config) => {
|
||||
FirefoxESR: {
|
||||
base: 'FirefoxHeadless',
|
||||
name: 'FirefoxESR'
|
||||
}
|
||||
}*/
|
||||
},
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
@@ -32,6 +32,6 @@ if (document.currentScript) {
|
||||
|
||||
const MCT = require('./src/MCT');
|
||||
|
||||
const openmct = new MCT();
|
||||
//const openmct = new MCT();
|
||||
|
||||
module.exports = openmct;
|
||||
module.exports = MCT;
|
||||
|
||||
10
package.json
10
package.json
@@ -2,8 +2,11 @@
|
||||
"name": "openmct",
|
||||
"version": "1.7.6-SNAPSHOT",
|
||||
"description": "The Open MCT core platform",
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"http-server": "^0.12.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@webpack-cli/serve": "^1.5.1",
|
||||
"angular": ">=1.8.0",
|
||||
"angular-route": "1.4.14",
|
||||
"babel-eslint": "10.0.3",
|
||||
@@ -41,13 +44,13 @@
|
||||
"jsdoc": "^3.3.2",
|
||||
"karma": "6.3.4",
|
||||
"karma-chrome-launcher": "3.1.0",
|
||||
"karma-firefox-launcher": "2.1.0",
|
||||
"karma-cli": "2.0.0",
|
||||
"karma-coverage": "2.0.3",
|
||||
"karma-coverage-istanbul-reporter": "3.0.3",
|
||||
"karma-junit-reporter": "2.0.1",
|
||||
"karma-firefox-launcher": "2.1.0",
|
||||
"karma-html-reporter": "0.2.7",
|
||||
"karma-jasmine": "4.0.1",
|
||||
"karma-junit-reporter": "2.0.1",
|
||||
"karma-sourcemap-loader": "0.3.8",
|
||||
"karma-webpack": "4.0.2",
|
||||
"location-bar": "^3.0.1",
|
||||
@@ -75,6 +78,7 @@
|
||||
"webpack": "^4.16.2",
|
||||
"webpack-cli": "^3.1.0",
|
||||
"webpack-dev-middleware": "^3.1.3",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"webpack-hot-middleware": "^2.22.3",
|
||||
"zepto": "^1.2.0"
|
||||
},
|
||||
|
||||
@@ -164,16 +164,6 @@ define([
|
||||
"license": "license-apache",
|
||||
"link": "http://logging.apache.org/log4net/license.html"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"when": "/licenses",
|
||||
"template": licensesTemplate
|
||||
},
|
||||
{
|
||||
"when": "/licenses-md",
|
||||
"template": licensesExportMdTemplate
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,6 @@ define([
|
||||
name: "platform/commonUI/browse",
|
||||
definition: {
|
||||
"extensions": {
|
||||
"routes": [
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
"key": "DEFAULT_PATH",
|
||||
|
||||
@@ -40,8 +40,8 @@ define(
|
||||
this.checks = [];
|
||||
this.$window = $window;
|
||||
|
||||
this.oldUnload = $window.onbeforeunload;
|
||||
$window.onbeforeunload = this.onBeforeUnload.bind(this);
|
||||
/* this.oldUnload = $window.onbeforeunload;
|
||||
$window.onbeforeunload = this.onBeforeUnload.bind(this);*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,7 +89,8 @@ define([
|
||||
"implementation": TickerService,
|
||||
"depends": [
|
||||
"$timeout",
|
||||
"now"
|
||||
"now",
|
||||
"$rootScope"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -32,8 +32,13 @@ define(
|
||||
* @param $timeout Angular's $timeout
|
||||
* @param {Function} now function to provide the current time in ms
|
||||
*/
|
||||
function TickerService($timeout, now) {
|
||||
function TickerService($timeout, now, $rootScope) {
|
||||
var self = this;
|
||||
var timeoutId;
|
||||
|
||||
$rootScope.$on('$destroy', function () {
|
||||
$timeout.cancel(timeoutId);
|
||||
});
|
||||
|
||||
function tick() {
|
||||
var timestamp = now(),
|
||||
@@ -48,7 +53,7 @@ define(
|
||||
}
|
||||
|
||||
// Try to update at exactly the next second
|
||||
$timeout(tick, 1000 - millis, true);
|
||||
timeoutId = $timeout(tick, 1000 - millis, true);
|
||||
}
|
||||
|
||||
tick();
|
||||
|
||||
@@ -58,7 +58,7 @@ define([
|
||||
) {
|
||||
var $http = this.$http,
|
||||
$log = this.$log,
|
||||
app = angular.module(Constants.MODULE_NAME, ["ngRoute"]),
|
||||
app = angular.module(Constants.MODULE_NAME, []),
|
||||
loader = new BundleLoader($http, $log, openmct.legacyRegistry),
|
||||
resolver = new BundleResolver(
|
||||
new ExtensionResolver(
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
define(
|
||||
[
|
||||
'./FrameworkLayer',
|
||||
'angular',
|
||||
'angular-route'
|
||||
'angular'
|
||||
],
|
||||
function (
|
||||
FrameworkLayer,
|
||||
|
||||
@@ -57,7 +57,6 @@ define(
|
||||
$log = this.$log;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
$log.info("Bootstrapping application " + (app || {}).name);
|
||||
angular.element(document).ready(function () {
|
||||
angular.bootstrap(document, [app.name], { strictDi: true });
|
||||
resolve(angular);
|
||||
|
||||
@@ -138,34 +138,6 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
// Custom registration function for extensions of category "route"
|
||||
function registerRoute(extension) {
|
||||
var app = this.app,
|
||||
$log = this.$log,
|
||||
route = Object.create(extension);
|
||||
|
||||
// Adjust path for bundle
|
||||
if (route.templateUrl) {
|
||||
route.templateUrl = [
|
||||
route.bundle.path,
|
||||
route.bundle.resources,
|
||||
route.templateUrl
|
||||
].join(Constants.SEPARATOR);
|
||||
}
|
||||
|
||||
// Log the registration
|
||||
$log.info("Registering route: " + (route.key || route.when));
|
||||
|
||||
// Register the route with Angular
|
||||
app.config(['$routeProvider', function ($routeProvider) {
|
||||
if (route.when) {
|
||||
$routeProvider.when(route.when, route);
|
||||
} else {
|
||||
$routeProvider.otherwise(route);
|
||||
}
|
||||
}]);
|
||||
}
|
||||
|
||||
// Handle service compositing
|
||||
function registerComponents(components) {
|
||||
var app = this.app,
|
||||
@@ -194,13 +166,6 @@ define(
|
||||
CustomRegistrars.prototype.constants =
|
||||
mapUpon(registerConstant);
|
||||
|
||||
/**
|
||||
* Register Angular routes.
|
||||
* @param {Array} extensions the resolved extensions
|
||||
*/
|
||||
CustomRegistrars.prototype.routes =
|
||||
mapUpon(registerRoute);
|
||||
|
||||
/**
|
||||
* Register Angular directives.
|
||||
* @param {Array} extensions the resolved extensions
|
||||
|
||||
@@ -57,7 +57,6 @@ define(
|
||||
expect(customRegistrars.directives).toBeTruthy();
|
||||
expect(customRegistrars.controllers).toBeTruthy();
|
||||
expect(customRegistrars.services).toBeTruthy();
|
||||
expect(customRegistrars.routes).toBeTruthy();
|
||||
expect(customRegistrars.constants).toBeTruthy();
|
||||
expect(customRegistrars.runs).toBeTruthy();
|
||||
});
|
||||
@@ -139,47 +138,6 @@ define(
|
||||
expect(mockLog.warn.calls.count()).toEqual(0);
|
||||
});
|
||||
|
||||
it("allows routes to be registered", function () {
|
||||
var mockRouteProvider = jasmine.createSpyObj(
|
||||
"$routeProvider",
|
||||
["when", "otherwise"]
|
||||
),
|
||||
bundle = {
|
||||
path: "test/bundle",
|
||||
resources: "res"
|
||||
},
|
||||
routes = [
|
||||
{
|
||||
when: "foo",
|
||||
templateUrl: "templates/test.html",
|
||||
bundle: bundle
|
||||
},
|
||||
{
|
||||
templateUrl: "templates/default.html",
|
||||
bundle: bundle
|
||||
}
|
||||
];
|
||||
|
||||
customRegistrars.routes(routes);
|
||||
|
||||
// Give it the route provider based on its config call
|
||||
mockApp.config.calls.all().forEach(function (call) {
|
||||
// Invoke the provided callback
|
||||
call.args[0][1](mockRouteProvider);
|
||||
});
|
||||
|
||||
// The "when" clause should have been mapped to the when method...
|
||||
expect(mockRouteProvider.when).toHaveBeenCalled();
|
||||
expect(mockRouteProvider.when.calls.mostRecent().args[0]).toEqual("foo");
|
||||
expect(mockRouteProvider.when.calls.mostRecent().args[1].templateUrl)
|
||||
.toEqual("test/bundle/res/templates/test.html");
|
||||
|
||||
// ...while the other should have been treated as a default route
|
||||
expect(mockRouteProvider.otherwise).toHaveBeenCalled();
|
||||
expect(mockRouteProvider.otherwise.calls.mostRecent().args[0].templateUrl)
|
||||
.toEqual("test/bundle/res/templates/default.html");
|
||||
});
|
||||
|
||||
it("accepts components for service compositing", function () {
|
||||
// Most relevant code will be exercised in service compositor spec
|
||||
expect(customRegistrars.components).toBeTruthy();
|
||||
|
||||
@@ -30,8 +30,8 @@ define([
|
||||
|
||||
return function ImportExportPlugin() {
|
||||
return function (openmct) {
|
||||
ExportAsJSONAction.appliesTo = function (context) {
|
||||
return openmct.$injector.get('policyService')
|
||||
ExportAsJSONAction.prototype.appliesTo = function (context) {
|
||||
return this.openmct.$injector.get('policyService')
|
||||
.allow("creation", context.domainObject.getCapability("type")
|
||||
);
|
||||
};
|
||||
|
||||
@@ -110,8 +110,15 @@ define([
|
||||
worker = workerService.run('bareBonesSearchWorker');
|
||||
}
|
||||
|
||||
worker.addEventListener('message', function (messageEvent) {
|
||||
function handleWorkerMessage(messageEvent) {
|
||||
provider.onWorkerMessage(messageEvent);
|
||||
}
|
||||
|
||||
worker.addEventListener('message', handleWorkerMessage);
|
||||
|
||||
this.openmct.once('destroy', () => {
|
||||
worker.removeEventListener('message', handleWorkerMessage);
|
||||
worker.terminate();
|
||||
});
|
||||
|
||||
return worker;
|
||||
|
||||
34
src/MCT.js
34
src/MCT.js
@@ -31,7 +31,6 @@ define([
|
||||
'objectUtils',
|
||||
'./plugins/plugins',
|
||||
'./adapter/indicators/legacy-indicators-plugin',
|
||||
'./plugins/buildInfo/plugin',
|
||||
'./ui/registries/ViewRegistry',
|
||||
'./plugins/imagery/plugin',
|
||||
'./ui/registries/InspectorViewRegistry',
|
||||
@@ -40,6 +39,7 @@ define([
|
||||
'./ui/router/Browse',
|
||||
'../platform/framework/src/Main',
|
||||
'./ui/layout/Layout.vue',
|
||||
'./ui/inspector/styles/StylesManager',
|
||||
'../platform/core/src/objects/DomainObjectImpl',
|
||||
'../platform/core/src/capabilities/ContextualDomainObject',
|
||||
'./ui/preview/plugin',
|
||||
@@ -60,7 +60,6 @@ define([
|
||||
objectUtils,
|
||||
plugins,
|
||||
LegacyIndicatorsPlugin,
|
||||
buildInfoPlugin,
|
||||
ViewRegistry,
|
||||
ImageryPlugin,
|
||||
InspectorViewRegistry,
|
||||
@@ -69,6 +68,7 @@ define([
|
||||
Browse,
|
||||
Main,
|
||||
Layout,
|
||||
stylesManager,
|
||||
DomainObjectImpl,
|
||||
ContextualDomainObject,
|
||||
PreviewPlugin,
|
||||
@@ -374,6 +374,7 @@ define([
|
||||
* MCT; if undefined, MCT will be run in the body of the document
|
||||
*/
|
||||
MCT.prototype.start = function (domElement = document.body, isHeadlessMode = false) {
|
||||
|
||||
if (this.types.get('layout') === undefined) {
|
||||
this.install(this.plugins.DisplayLayout({
|
||||
showAsView: ['summary-widget']
|
||||
@@ -432,6 +433,9 @@ define([
|
||||
domElement.appendChild(appLayout.$mount().$el);
|
||||
|
||||
this.layout = appLayout.$refs.layout;
|
||||
this.once('destroy', () => {
|
||||
this.layout.$destroy();
|
||||
});
|
||||
Browse(this);
|
||||
}
|
||||
|
||||
@@ -459,7 +463,31 @@ define([
|
||||
|
||||
MCT.prototype.destroy = function () {
|
||||
this.emit('destroy');
|
||||
this.router.destroy();
|
||||
this.removeAllListeners();
|
||||
|
||||
if (this.$injector) {
|
||||
this.$injector.get('$rootScope').$destroy();
|
||||
this.$injector = null;
|
||||
}
|
||||
|
||||
if (this.$angular) {
|
||||
this.$angular.element(this.element).off().removeData();
|
||||
this.$angular.element(this.element).empty();
|
||||
this.$angular = null;
|
||||
}
|
||||
|
||||
this.overlays.destroy();
|
||||
|
||||
if (this.element) {
|
||||
this.element.remove();
|
||||
}
|
||||
|
||||
stylesManager.default.removeAllListeners();
|
||||
|
||||
window.angular = null;
|
||||
window.openmct = null;
|
||||
|
||||
Object.keys(require.cache).forEach(key => delete require.cache[key]);
|
||||
};
|
||||
|
||||
MCT.prototype.plugins = plugins;
|
||||
|
||||
@@ -26,80 +26,93 @@ define([
|
||||
'utils/testing'
|
||||
], function (plugins, legacyRegistry, testUtils) {
|
||||
describe("MCT", function () {
|
||||
let openmct;
|
||||
let mockPlugin;
|
||||
let mockPlugin2;
|
||||
let mockListener;
|
||||
let oldBundles;
|
||||
|
||||
beforeEach(function () {
|
||||
mockPlugin = jasmine.createSpy('plugin');
|
||||
mockPlugin2 = jasmine.createSpy('plugin2');
|
||||
mockListener = jasmine.createSpy('listener');
|
||||
oldBundles = legacyRegistry.list();
|
||||
this.mockPlugin = jasmine.createSpy('plugin');
|
||||
this.mockPlugin2 = jasmine.createSpy('plugin2');
|
||||
this.mockListener = jasmine.createSpy('listener');
|
||||
this.oldBundles = legacyRegistry.list();
|
||||
|
||||
openmct = testUtils.createOpenMct();
|
||||
this.openmct = testUtils.createOpenMct();
|
||||
|
||||
openmct.install(mockPlugin);
|
||||
openmct.install(mockPlugin2);
|
||||
openmct.on('start', mockListener);
|
||||
this.openmct.install(this.mockPlugin);
|
||||
this.openmct.install(this.mockPlugin2);
|
||||
this.openmct.once('start', this.mockListener);
|
||||
});
|
||||
|
||||
// Clean up the dirty singleton.
|
||||
afterEach(function () {
|
||||
legacyRegistry.list().forEach(function (bundle) {
|
||||
if (oldBundles.indexOf(bundle) === -1) {
|
||||
if (this.oldBundles.indexOf(bundle) === -1) {
|
||||
legacyRegistry.delete(bundle);
|
||||
}
|
||||
});
|
||||
|
||||
return testUtils.resetApplicationState(openmct);
|
||||
return testUtils.resetApplicationState(this.openmct)
|
||||
.then(() => {
|
||||
this.openmct = null;
|
||||
this.mockPlugin = null;
|
||||
this.mockPlugin2 = null;
|
||||
this.mockListener = null;
|
||||
this.oldBundles = null;
|
||||
console.error('Done clearing test variables');
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes plugins", function () {
|
||||
expect(openmct.plugins).toEqual(plugins);
|
||||
expect(this.openmct.plugins).toEqual(plugins);
|
||||
});
|
||||
|
||||
it("does not issue a start event before started", function () {
|
||||
expect(mockListener).not.toHaveBeenCalled();
|
||||
expect(this.mockListener).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("start", function () {
|
||||
let appHolder;
|
||||
beforeEach(function (done) {
|
||||
appHolder = document.createElement("div");
|
||||
openmct.on('start', done);
|
||||
openmct.start(appHolder);
|
||||
beforeEach(function () {
|
||||
this.appHolder = document.createElement("div");
|
||||
|
||||
const startPromise = new Promise(resolve => {
|
||||
this.openmct.once('start', resolve);
|
||||
});
|
||||
|
||||
this.openmct.startHeadless();
|
||||
|
||||
return startPromise;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
//this.appHolder.remove();
|
||||
this.appHolder = null;
|
||||
});
|
||||
|
||||
it("calls plugins for configuration", function () {
|
||||
expect(mockPlugin).toHaveBeenCalledWith(openmct);
|
||||
expect(mockPlugin2).toHaveBeenCalledWith(openmct);
|
||||
expect(this.mockPlugin).toHaveBeenCalledWith(this.openmct);
|
||||
expect(this.mockPlugin2).toHaveBeenCalledWith(this.openmct);
|
||||
});
|
||||
|
||||
it("emits a start event", function () {
|
||||
expect(mockListener).toHaveBeenCalled();
|
||||
expect(this.mockListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Renders the application into the provided container element", function () {
|
||||
let openMctShellElements = appHolder.querySelectorAll('div.l-shell');
|
||||
let openMctShellElements = this.appHolder.querySelectorAll('div.l-shell');
|
||||
expect(openMctShellElements.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("startHeadless", function () {
|
||||
beforeEach(function (done) {
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
console.error('HERE');
|
||||
this.openmct.on('start', done);
|
||||
this.openmct.startHeadless();
|
||||
});
|
||||
|
||||
it("calls plugins for configuration", function () {
|
||||
expect(mockPlugin).toHaveBeenCalledWith(openmct);
|
||||
expect(mockPlugin2).toHaveBeenCalledWith(openmct);
|
||||
expect(this.mockPlugin).toHaveBeenCalledWith(this.openmct);
|
||||
expect(this.mockPlugin2).toHaveBeenCalledWith(this.openmct);
|
||||
});
|
||||
|
||||
it("emits a start event", function () {
|
||||
expect(mockListener).toHaveBeenCalled();
|
||||
expect(this.mockListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Does not render Open MCT", function () {
|
||||
@@ -112,19 +125,19 @@ define([
|
||||
let testAssetPath;
|
||||
|
||||
beforeEach(function () {
|
||||
openmct.legacyExtension = jasmine.createSpy('legacyExtension');
|
||||
this.openmct.legacyExtension = jasmine.createSpy('legacyExtension');
|
||||
});
|
||||
|
||||
it("configures the path for assets", function () {
|
||||
testAssetPath = "some/path/";
|
||||
openmct.setAssetPath(testAssetPath);
|
||||
expect(openmct.getAssetPath()).toBe(testAssetPath);
|
||||
this.openmct.setAssetPath(testAssetPath);
|
||||
expect(this.openmct.getAssetPath()).toBe(testAssetPath);
|
||||
});
|
||||
|
||||
it("adds a trailing /", function () {
|
||||
testAssetPath = "some/path";
|
||||
openmct.setAssetPath(testAssetPath);
|
||||
expect(openmct.getAssetPath()).toBe(testAssetPath + "/");
|
||||
this.openmct.setAssetPath(testAssetPath);
|
||||
expect(this.openmct.getAssetPath()).toBe(testAssetPath + "/");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,6 +32,10 @@ define([
|
||||
// cannot be injected.
|
||||
function AlternateCompositionInitializer(openmct) {
|
||||
AlternateCompositionCapability.appliesTo = function (model, id) {
|
||||
openmct.once('destroy', () => {
|
||||
delete AlternateCompositionCapability.appliesTo;
|
||||
});
|
||||
|
||||
model = objectUtils.toNewFormat(model, id || '');
|
||||
|
||||
return Boolean(openmct.composition.get(model));
|
||||
|
||||
@@ -28,6 +28,10 @@ export default class Editor extends EventEmitter {
|
||||
super();
|
||||
this.editing = false;
|
||||
this.openmct = openmct;
|
||||
|
||||
openmct.once('destroy', () => {
|
||||
this.removeAllListeners();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,11 +17,7 @@ class OverlayAPI {
|
||||
|
||||
this.dismissLastOverlay = this.dismissLastOverlay.bind(this);
|
||||
|
||||
document.addEventListener('keyup', (event) => {
|
||||
if (event.key === 'Escape') {
|
||||
this.dismissLastOverlay();
|
||||
}
|
||||
});
|
||||
document.addEventListener('keyup', this.dismissLastOverlay);
|
||||
|
||||
}
|
||||
|
||||
@@ -49,12 +45,14 @@ class OverlayAPI {
|
||||
/**
|
||||
* private
|
||||
*/
|
||||
dismissLastOverlay() {
|
||||
dismissLastOverlay(event) {
|
||||
if (event.key === 'Escape') {
|
||||
let lastOverlay = this.activeOverlays[this.activeOverlays.length - 1];
|
||||
if (lastOverlay && lastOverlay.dismissable) {
|
||||
lastOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of option properties that can be passed into the overlay
|
||||
@@ -129,6 +127,10 @@ class OverlayAPI {
|
||||
return progressDialog;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
document.removeEventListener('keyup', this.dismissLastOverlay);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default OverlayAPI;
|
||||
|
||||
@@ -32,6 +32,10 @@ export default class StatusAPI extends EventEmitter {
|
||||
this.get = this.get.bind(this);
|
||||
this.set = this.set.bind(this);
|
||||
this.observe = this.observe.bind(this);
|
||||
|
||||
openmct.once('destroy', () => {
|
||||
this.removeAllListeners();
|
||||
});
|
||||
}
|
||||
|
||||
get(identifier) {
|
||||
|
||||
@@ -42,7 +42,7 @@ const DEFAULTS = [
|
||||
'platform/forms',
|
||||
'platform/identity',
|
||||
'platform/persistence/aggregator',
|
||||
'platform/persistence/queue',
|
||||
//'platform/persistence/queue',
|
||||
'platform/policy',
|
||||
'platform/entanglement',
|
||||
'platform/search',
|
||||
@@ -90,7 +90,7 @@ define([
|
||||
'../platform/persistence/aggregator/bundle',
|
||||
'../platform/persistence/elastic/bundle',
|
||||
'../platform/persistence/local/bundle',
|
||||
'../platform/persistence/queue/bundle',
|
||||
//'../platform/persistence/queue/bundle',
|
||||
'../platform/policy/bundle',
|
||||
'../platform/representation/bundle',
|
||||
'../platform/search/bundle',
|
||||
|
||||
@@ -117,6 +117,10 @@ export default function NotebookPlugin() {
|
||||
key: 'notebook-snapshot-indicator'
|
||||
};
|
||||
|
||||
openmct.once('destroy', () => {
|
||||
snapshotContainer.destroy();
|
||||
});
|
||||
|
||||
openmct.indicators.add(indicator);
|
||||
|
||||
openmct.objectViews.addProvider({
|
||||
|
||||
@@ -80,4 +80,8 @@ export default class SnapshotContainer extends EventEmitter {
|
||||
|
||||
return this.saveSnapshots(updatedSnapshots);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
delete SnapshotContainer.instance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,10 @@ export default {
|
||||
|
||||
//Respond to changes in conductor
|
||||
this.openmct.time.on("timeSystem", this.setViewFromTimeSystem);
|
||||
setInterval(this.resize, RESIZE_POLL_INTERVAL);
|
||||
this.resizeTimer = setInterval(this.resize, RESIZE_POLL_INTERVAL);
|
||||
},
|
||||
destroyed() {
|
||||
clearInterval(this.resizeTimer);
|
||||
},
|
||||
methods: {
|
||||
setAxisDimensions() {
|
||||
|
||||
@@ -38,6 +38,10 @@ define(
|
||||
|
||||
this.openmct = openmct;
|
||||
this.selected = [];
|
||||
|
||||
this.openmct.once('destroy', () => {
|
||||
this.removeAllListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Selection.prototype = Object.create(EventEmitter.prototype);
|
||||
|
||||
@@ -253,7 +253,7 @@ export default {
|
||||
}
|
||||
|
||||
document.removeEventListener('click', this.closeViewAndSaveMenu);
|
||||
window.removeEventListener('click', this.promptUserbeforeNavigatingAway);
|
||||
window.removeEventListener('beforeunload', this.promptUserbeforeNavigatingAway);
|
||||
},
|
||||
methods: {
|
||||
toggleSaveMenu() {
|
||||
|
||||
@@ -49,6 +49,10 @@ class ApplicationRouter extends EventEmitter {
|
||||
this.routes = [];
|
||||
this.started = false;
|
||||
|
||||
openmct.once('destroy', () => {
|
||||
this.destroy();
|
||||
});
|
||||
|
||||
this.setHash = _.debounce(this.setHash.bind(this), 300);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,12 @@ import MCT from 'MCT';
|
||||
let nativeFunctions = [];
|
||||
let mockObjects = setMockObjects();
|
||||
|
||||
const activeInstance = {
|
||||
activeSpec: undefined,
|
||||
specToInstanceMap: new WeakMap()
|
||||
};
|
||||
export {activeInstance};
|
||||
|
||||
export function createOpenMct() {
|
||||
const openmct = new MCT();
|
||||
openmct.install(openmct.plugins.LocalStorage());
|
||||
@@ -33,6 +39,7 @@ export function createOpenMct() {
|
||||
start: 0,
|
||||
end: 1
|
||||
});
|
||||
activeInstance.specToInstanceMap.set(activeInstance.activeSpec, openmct);
|
||||
|
||||
return openmct;
|
||||
}
|
||||
@@ -88,7 +95,11 @@ export function resetApplicationState(openmct) {
|
||||
promise = Promise.resolve();
|
||||
}
|
||||
|
||||
return promise;
|
||||
openmct = null;
|
||||
|
||||
return promise.then(() => {
|
||||
window.gc();
|
||||
});
|
||||
}
|
||||
|
||||
// required: key
|
||||
|
||||
66
src/utils/testing/MemoryLeaksReporter.js
Normal file
66
src/utils/testing/MemoryLeaksReporter.js
Normal file
@@ -0,0 +1,66 @@
|
||||
//'Possible memory leaks in 205 specs'
|
||||
//'Possible memory leaks in 214 specs'
|
||||
//'Possible memory leaks in 207 specs'
|
||||
//'Possible memory leaks in 212 specs'
|
||||
//'Possible memory leaks in 204 specs'
|
||||
|
||||
// Note: specDone will run when it THINKS the spec is done. It's possible that it's not actually done yet, the promise could have been resolved or the done function could have been invoked prematurely.
|
||||
|
||||
import {activeInstance} from '../testing.js';
|
||||
|
||||
function toMegabytes(bytes) {
|
||||
return `${Math.round(bytes / 1024 / 1024)}MB`;
|
||||
}
|
||||
|
||||
function toKilobytes(bytes) {
|
||||
return `${Math.round(bytes / 1024)}KB`;
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
const memoryLeaks = new Set();
|
||||
|
||||
const FR = new FinalizationRegistry((specName) => {
|
||||
memoryLeaks.delete(specName);
|
||||
console.error(`Spec cleaned up after itself: ${specName}. Good spec.`);
|
||||
});
|
||||
|
||||
export default class MemoryLeaksReporter {
|
||||
specStarted(spec) {
|
||||
window.gc();
|
||||
//this.usedJSHeapSizeStart = performance.memory.usedJSHeapSize;
|
||||
activeInstance.activeSpec = spec;
|
||||
}
|
||||
specDone(spec) {
|
||||
let instance = activeInstance.specToInstanceMap.get(activeInstance.activeSpec);
|
||||
|
||||
if (instance !== undefined) {
|
||||
memoryLeaks.add(spec.fullName);
|
||||
FR.register(instance, spec.fullName);
|
||||
}
|
||||
/*
|
||||
const usedJSHeapSizeEnd = performance.memory.usedJSHeapSize;
|
||||
const memoryDelta = usedJSHeapSizeEnd - this.usedJSHeapSizeStart;
|
||||
if (memoryDelta > 0) {
|
||||
count++;
|
||||
}*/
|
||||
}
|
||||
|
||||
async jasmineDone() {
|
||||
window.gc();
|
||||
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
window.gc();
|
||||
if (memoryLeaks.size > 0) {
|
||||
console.error("\r\n");
|
||||
console.error("##############################################");
|
||||
console.error(`${memoryLeaks.size} test spec(s) contain memory leaks: `);
|
||||
for (const specName of memoryLeaks) {
|
||||
console.error(`- ${specName}`);
|
||||
}
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user