From 35c42ba43de5f1ee5348d686e8fd4d498ec42d00 Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Wed, 28 Sep 2022 17:13:41 -0700 Subject: [PATCH 1/8] Reviewer to smoke test PRs before merge (#5771) * Reviewer to smoke test PRs before merge * Update PULL_REQUEST_TEMPLATE.md * Update PULL_REQUEST_TEMPLATE.md * Update PULL_REQUEST_TEMPLATE.md Changes based on feedback * Update PULL_REQUEST_TEMPLATE.md Tweaking the language slightly for clarity. * Update PULL_REQUEST_TEMPLATE.md Co-authored-by: Jesse Mazzella --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a5525f4ce9..f6728a7d26 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -21,9 +21,9 @@ Closes -# Building Applications With Open MCT +# Developing Applications With Open MCT ## Scope and purpose of this document @@ -72,8 +72,7 @@ MCT, as well as addressing some common developer use cases. ## Building From Source The latest version of Open MCT is available from [our GitHub repository](https://github.com/nasa/openmct). -If you have `git`, and `node` installed, you can build Open MCT with the -commands +If you have `git`, and `node` installed, you can build Open MCT with the commands ```bash git clone https://github.com/nasa/openmct.git @@ -86,7 +85,7 @@ build a minified version that can be included in your application. The output of the build process is placed in a `dist` folder under the openmct source directory, which can be copied out to another location as needed. The contents of this folder will include a minified javascript file named `openmct.js` as -well as assets such as html, css, and images necessary for the UI. +well as assets such as html, css, and images necessary for the UI. ## Starting an Open MCT application diff --git a/Procfile b/Procfile deleted file mode 100644 index 1e13b4ae05..0000000000 --- a/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: node app.js --port $PORT diff --git a/README.md b/README.md index dc685fac11..463961d333 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ Building and running Open MCT in your local dev environment is very easy. Be sur Open MCT is now running, and can be accessed by pointing a web browser at [http://localhost:8080/](http://localhost:8080/) +Open MCT is built using [`npm`](http://npmjs.com/) and [`webpack`](https://webpack.js.org/). + ## Documentation Documentation is available on the [Open MCT website](https://nasa.github.io/openmct/documentation/). @@ -43,11 +45,9 @@ our documentation. We want Open MCT to be as easy to use, install, run, and develop for as possible, and your feedback will help us get there! Feedback can be provided via [GitHub issues](https://github.com/nasa/openmct/issues/new/choose), [Starting a GitHub Discussion](https://github.com/nasa/openmct/discussions), or by emailing us at [arc-dl-openmct@mail.nasa.gov](mailto:arc-dl-openmct@mail.nasa.gov). -## Building Applications With Open MCT +## Developing Applications With Open MCT -Open MCT is built using [`npm`](http://npmjs.com/) and [`webpack`](https://webpack.js.org/). - -See our documentation for a guide on [building Applications with Open MCT](https://github.com/nasa/openmct/blob/master/API.md#starting-an-open-mct-application). +For more on developing with Open MCT, see our documentation for a guide on [Developing Applications with Open MCT](./API.md#starting-an-open-mct-application). ## Compatibility @@ -64,7 +64,7 @@ that is intended to be added or removed as a single unit. As well as providing an extension mechanism, most of the core Open MCT codebase is also written as plugins. -For information on writing plugins, please see [our API documentation](https://github.com/nasa/openmct/blob/master/API.md#plugins). +For information on writing plugins, please see [our API documentation](./API.md#plugins). ## Tests diff --git a/app.js b/app.js deleted file mode 100644 index c7ecd9de3b..0000000000 --- a/app.js +++ /dev/null @@ -1,92 +0,0 @@ -/*global process*/ - -/** - * Usage: - * - * npm install minimist express - * node app.js [options] - */ - -const options = require('minimist')(process.argv.slice(2)); -const express = require('express'); -const app = express(); -const fs = require('fs'); -const request = require('request'); -const __DEV__ = !process.env.NODE_ENV || process.env.NODE_ENV === 'development'; - -// Defaults -options.port = options.port || options.p || 8080; -options.host = options.host || 'localhost'; -options.directory = options.directory || options.D || '.'; - -// Show command line options -if (options.help || options.h) { - console.log("\nUsage: node app.js [options]\n"); - console.log("Options:"); - console.log(" --help, -h Show this message."); - console.log(" --port, -p Specify port."); - console.log(" --directory, -D Serve files from specified directory."); - console.log(""); - process.exit(0); -} - -app.disable('x-powered-by'); - -app.use('/proxyUrl', function proxyRequest(req, res, next) { - console.log('Proxying request to: ', req.query.url); - req.pipe(request({ - url: req.query.url, - strictSSL: false - }).on('error', next)).pipe(res); -}); - -class WatchRunPlugin { - apply(compiler) { - compiler.hooks.emit.tapAsync('WatchRunPlugin', (compilation, callback) => { - console.log('Begin compile at ' + new Date()); - callback(); - }); - } -} - -const webpack = require('webpack'); -let webpackConfig; -if (__DEV__) { - webpackConfig = require('./webpack.dev'); - webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin()); - webpackConfig.entry.openmct = [ - 'webpack-hot-middleware/client?reload=true', - webpackConfig.entry.openmct - ]; - webpackConfig.plugins.push(new WatchRunPlugin()); -} else { - webpackConfig = require('./webpack.coverage'); -} - -const compiler = webpack(webpackConfig); - -app.use(require('webpack-dev-middleware')( - compiler, - { - publicPath: '/dist', - stats: 'errors-warnings' - } -)); - -if (__DEV__) { - app.use(require('webpack-hot-middleware')( - compiler, - {} - )); -} - -// Expose index.html for development users. -app.get('/', function (req, res) { - fs.createReadStream('index.html').pipe(res); -}); - -// Finally, open the HTTP server and log the instance to the console -app.listen(options.port, options.host, function () { - console.log('Open MCT application running at %s:%s', options.host, options.port); -}); - diff --git a/docs/footer.html b/docs/footer.html deleted file mode 100644 index a6878b0cac..0000000000 --- a/docs/footer.html +++ /dev/null @@ -1,3 +0,0 @@ -
- - diff --git a/docs/gendocs.js b/docs/gendocs.js deleted file mode 100644 index a5f3188e92..0000000000 --- a/docs/gendocs.js +++ /dev/null @@ -1,209 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2022, 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. - *****************************************************************************/ - -/*global require,process,__dirname,GLOBAL*/ -/*jslint nomen: false */ - - -// Usage: -// node gendocs.js --in --out - -var CONSTANTS = { - DIAGRAM_WIDTH: 800, - DIAGRAM_HEIGHT: 500 - }, - TOC_HEAD = "# Table of Contents"; - -GLOBAL.window = GLOBAL.window || GLOBAL; // nomnoml expects window to be defined -(function () { - "use strict"; - - var fs = require("fs"), - mkdirp = require("mkdirp"), - path = require("path"), - glob = require("glob"), - marked = require("marked"), - split = require("split"), - stream = require("stream"), - nomnoml = require('nomnoml'), - toc = require("markdown-toc"), - Canvas = require('canvas'), - header = fs.readFileSync(path.resolve(__dirname, 'header.html')), - footer = fs.readFileSync(path.resolve(__dirname, 'footer.html')), - options = require("minimist")(process.argv.slice(2)); - - // Convert from nomnoml source to a target PNG file. - function renderNomnoml(source, target) { - var canvas = - new Canvas(CONSTANTS.DIAGRAM_WIDTH, CONSTANTS.DIAGRAM_HEIGHT); - nomnoml.draw(canvas, source, 1.0); - canvas.pngStream().pipe(fs.createWriteStream(target)); - } - - // Stream transform. - // Pulls out nomnoml diagrams from fenced code blocks and renders them - // as PNG files in the output directory, prefixed with a provided name. - // The fenced code blocks will be replaced with Markdown in the - // output of this stream. - function nomnomlifier(outputDirectory, prefix) { - var transform = new stream.Transform({ objectMode: true }), - isBuilding = false, - counter = 1, - outputPath, - source = ""; - - transform._transform = function (chunk, encoding, done) { - if (!isBuilding) { - if (chunk.trim().indexOf("```nomnoml") === 0) { - var outputFilename = prefix + '-' + counter + '.png'; - outputPath = path.join(outputDirectory, outputFilename); - this.push([ - "\n![Diagram ", - counter, - "](", - outputFilename, - ")\n\n" - ].join("")); - isBuilding = true; - source = ""; - counter += 1; - } else { - // Otherwise, pass through - this.push(chunk + '\n'); - } - } else { - if (chunk.trim() === "```") { - // End nomnoml - renderNomnoml(source, outputPath); - isBuilding = false; - } else { - source += chunk + '\n'; - } - } - done(); - }; - - return transform; - } - - // Convert from Github-flavored Markdown to HTML - function gfmifier(renderTOC) { - var transform = new stream.Transform({ objectMode: true }), - markdown = ""; - transform._transform = function (chunk, encoding, done) { - markdown += chunk; - done(); - }; - transform._flush = function (done) { - if (renderTOC){ - // Prepend table of contents - markdown = - [ TOC_HEAD, toc(markdown).content, "", markdown ].join("\n"); - } - this.push(header); - this.push(marked(markdown)); - this.push(footer); - done(); - }; - return transform; - } - - // Custom renderer for marked; converts relative links from md to html, - // and makes headings linkable. - function CustomRenderer() { - var renderer = new marked.Renderer(), - customRenderer = Object.create(renderer); - customRenderer.heading = function (text, level) { - var escapedText = (text || "").trim().toLowerCase().replace(/\W/g, "-"), - aOpen = "", - aClose = ""; - return aOpen + renderer.heading.apply(renderer, arguments) + aClose; - }; - // Change links to .md files to .html - customRenderer.link = function (href, title, text) { - // ...but only if they look like relative paths - return (href || "").indexOf(":") === -1 && href[0] !== "/" ? - renderer.link(href.replace(/\.md/, ".html"), title, text) : - renderer.link.apply(renderer, arguments); - }; - return customRenderer; - } - - options['in'] = options['in'] || options.i; - options.out = options.out || options.o; - - marked.setOptions({ - renderer: new CustomRenderer(), - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: true, - smartLists: true, - smartypants: false - }); - - // Convert all markdown files. - // First, pull out nomnoml diagrams. - // Then, convert remaining Markdown to HTML. - glob(options['in'] + "/**/*.md", {}, function (err, files) { - files.forEach(function (file) { - var destination = file.replace(options['in'], options.out) - .replace(/md$/, "html"), - destPath = path.dirname(destination), - prefix = path.basename(destination).replace(/\.html$/, ""), - //Determine whether TOC should be rendered for this file based - //on regex provided as command line option - renderTOC = file.match(options['suppress-toc'] || "") === null; - - mkdirp(destPath, function (err) { - fs.createReadStream(file, { encoding: 'utf8' }) - .pipe(split()) - .pipe(nomnomlifier(destPath, prefix)) - .pipe(gfmifier(renderTOC)) - .pipe(fs.createWriteStream(destination, { - encoding: 'utf8' - })); - }); - }); - }); - - // Also copy over all HTML, CSS, or PNG files - glob(options['in'] + "/**/*.@(html|css|png)", {}, function (err, files) { - files.forEach(function (file) { - var destination = file.replace(options['in'], options.out), - destPath = path.dirname(destination), - streamOptions = {}; - if (file.match(/png$/)) { - streamOptions.encoding = null; - } else { - streamOptions.encoding = 'utf8'; - } - - mkdirp(destPath, function (err) { - fs.createReadStream(file, streamOptions) - .pipe(fs.createWriteStream(destination, streamOptions)); - }); - }); - }); - -}()); diff --git a/docs/header.html b/docs/header.html deleted file mode 100644 index c945996f4a..0000000000 --- a/docs/header.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/e2e/README.md b/e2e/README.md index 2ce8727107..6cfd604a20 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -151,7 +151,7 @@ Current list of test tags: - `@ipad` - Test case or test suite is compatible with Playwright's iPad support and Open MCT's read-only mobile view (i.e. no Create button). - `@gds` - Denotes a GDS Test Case used in the VIPER Mission. -- `@addInit` - Initializes the browser with an injected and artificial state. Useful for loading non-default plugins. Likely will not work outside of app.js. +- `@addInit` - Initializes the browser with an injected and artificial state. Useful for loading non-default plugins. Likely will not work outside of `npm start`. - `@localStorage` - Captures or generates session storage to manipulate browser state. Useful for excluding in tests which require a persistent backend (i.e. CouchDB). - `@snapshot` - Uses Playwright's snapshot functionality to record a copy of the DOM for direct comparison. Must be run inside of the playwright container. - `@unstable` - A new test or test which is known to be flaky. diff --git a/e2e/playwright-ci.config.js b/e2e/playwright-ci.config.js index aeff668823..cd8fd2e7e9 100644 --- a/e2e/playwright-ci.config.js +++ b/e2e/playwright-ci.config.js @@ -14,7 +14,7 @@ const config = { testIgnore: '**/*.perf.spec.js', //Ignore performance tests and define in playwright-perfromance.config.js timeout: 60 * 1000, webServer: { - command: 'cross-env NODE_ENV=test npm run start', + command: 'npm run start:coverage', url: 'http://localhost:8080/#', timeout: 200 * 1000, reuseExistingServer: false diff --git a/e2e/playwright-local.config.js b/e2e/playwright-local.config.js index 87365fee2b..845cf68124 100644 --- a/e2e/playwright-local.config.js +++ b/e2e/playwright-local.config.js @@ -12,10 +12,7 @@ const config = { testIgnore: '**/*.perf.spec.js', timeout: 30 * 1000, webServer: { - env: { - NODE_ENV: 'test' - }, - command: 'npm run start', + command: 'npm run start:coverage', url: 'http://localhost:8080/#', timeout: 120 * 1000, reuseExistingServer: true diff --git a/e2e/playwright-performance.config.js b/e2e/playwright-performance.config.js index de79304f11..7f4fae91c6 100644 --- a/e2e/playwright-performance.config.js +++ b/e2e/playwright-performance.config.js @@ -6,12 +6,12 @@ const CI = process.env.CI === 'true'; /** @type {import('@playwright/test').PlaywrightTestConfig} */ const config = { - retries: 1, //Only for debugging purposes because trace is enabled only on first retry + retries: 1, //Only for debugging purposes for trace: 'on-first-retry' testDir: 'tests/performance/', timeout: 60 * 1000, workers: 1, //Only run in serial with 1 worker webServer: { - command: 'cross-env NODE_ENV=test npm run start', + command: 'npm run start', //coverage not generated url: 'http://localhost:8080/#', timeout: 200 * 1000, reuseExistingServer: !CI diff --git a/e2e/playwright-visual.config.js b/e2e/playwright-visual.config.js index 1123de8087..34bc13d390 100644 --- a/e2e/playwright-visual.config.js +++ b/e2e/playwright-visual.config.js @@ -4,13 +4,13 @@ /** @type {import('@playwright/test').PlaywrightTestConfig<{ theme: string }>} */ const config = { - retries: 1, // visual tests should never retry due to snapshot comparison errors. Leaving as a shim + retries: 0, // Visual tests should never retry due to snapshot comparison errors. Leaving as a shim testDir: 'tests/visual', testMatch: '**/*.visual.spec.js', // only run visual tests timeout: 60 * 1000, workers: 1, //Lower stress on Circle CI Agent for Visual tests https://github.com/percy/cli/discussions/1067 webServer: { - command: 'cross-env NODE_ENV=test npm run start', + command: 'npm run start:coverage', url: 'http://localhost:8080/#', timeout: 200 * 1000, reuseExistingServer: !process.env.CI @@ -31,7 +31,7 @@ const config = { } }, { - name: 'chrome-snow-theme', + name: 'chrome-snow-theme', //Runs the same visual tests but with snow-theme enabled use: { browserName: 'chromium', theme: 'snow' diff --git a/e2e/tests/framework/baseFixtures.e2e.spec.js b/e2e/tests/framework/baseFixtures.e2e.spec.js index 86ae7c7d30..aa5bf744e5 100644 --- a/e2e/tests/framework/baseFixtures.e2e.spec.js +++ b/e2e/tests/framework/baseFixtures.e2e.spec.js @@ -23,7 +23,7 @@ /* This test suite is dedicated to testing our use of the playwright framework as it relates to how we've extended it (i.e. ./e2e/baseFixtures.js) and assumptions made in our dev environment -(app.js and ./e2e/webpack-dev-middleware.js) +(`npm start` and ./e2e/webpack-dev-middleware.js) */ const { test } = require('../../baseFixtures.js'); diff --git a/e2e/tests/visual/controlledClock.visual.spec.js b/e2e/tests/visual/controlledClock.visual.spec.js index c4d6b57679..0f5de10c63 100644 --- a/e2e/tests/visual/controlledClock.visual.spec.js +++ b/e2e/tests/visual/controlledClock.visual.spec.js @@ -22,7 +22,7 @@ /* Collection of Visual Tests set to run in a default context. The tests within this suite -are only meant to run against openmct's app.js started by `npm run start` within the +are only meant to run against openmct started by `npm start` within the `./e2e/playwright-visual.config.js` file. */ diff --git a/e2e/tests/visual/default.visual.spec.js b/e2e/tests/visual/default.visual.spec.js index b8c10b35f7..0a2a880055 100644 --- a/e2e/tests/visual/default.visual.spec.js +++ b/e2e/tests/visual/default.visual.spec.js @@ -22,7 +22,7 @@ /* Collection of Visual Tests set to run in a default context. The tests within this suite -are only meant to run against openmct's app.js started by `npm run start` within the +are only meant to run against openmct started by `npm start` within the `./e2e/playwright-visual.config.js` file. These should only use functional expect statements to verify assumptions about the state diff --git a/jsdoc.json b/jsdoc.json deleted file mode 100644 index ac485a5efa..0000000000 --- a/jsdoc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "source": { - "include": [ - "src/" - ], - "includePattern": "src/.+\\.js$", - "excludePattern": ".+\\Spec\\.js$|lib/.+" - }, - "plugins": [ - "plugins/markdown" - ] -} diff --git a/karma.conf.js b/karma.conf.js index a24f6d0f31..75a9c04fc5 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -23,14 +23,32 @@ /*global module,process*/ module.exports = (config) => { - const webpackConfig = require('./webpack.coverage.js'); + let webpackConfig; + let browsers; + let singleRun; + + if (process.env.KARMA_DEBUG) { + webpackConfig = require('./webpack.dev.js'); + browsers = ['ChromeDebugging']; + singleRun = false; + } else { + webpackConfig = require('./webpack.coverage.js'); + browsers = ['ChromeHeadless']; + singleRun = true; + } + delete webpackConfig.output; + // karma doesn't support webpack entry + delete webpackConfig.entry; config.set({ basePath: '', - frameworks: ['jasmine'], + frameworks: ['jasmine', 'webpack'], files: [ 'indexTest.js', + // included means: should the files be included in the browser using