From 172e0b23fd6a180635579a09ee81bde4f936bbfa Mon Sep 17 00:00:00 2001 From: Jesse Mazzella Date: Thu, 18 May 2023 14:29:20 -0700 Subject: [PATCH] chore: add `prettier` (1/3): add packages, configurations, fix lint issues (#6382) * fix: remove redundant eslint rules * chore: bump `prettier` to v2.8.7 * docs: vue files to use html comments for licenses - Prettier's Vue parser freaks out if it sees a *.js style comment in a *.vue file. * docs: more licenses for vue files * fix: don't ignore *.vue files * fix: use defaults for tabWidth and printWidth * simplify .prettierignore * enforce a printWidth of 100 * fix: use `eslint-plugin-prettier`, remove conflicting rules * test: fix gauge tests (for real) * test: fix notebook test selectors * test: fix restrictedNotebook test selectors * test: remove useless assignment * lint: __dirname as global * lint: revert eslint config + whitespace changes, commit new config * style: remove unnecessary string concat of literals * test: fix missed gauge test * fix: use new eslint rules * feat: add blank `.git-blame-ignore-revs` file * docs: update to mention Prettier and format. * Revert "test: fix gauge tests (for real)" This reverts commit 6afad450389edc2f16ff0d00c9524621a7ba53bc. * Revert "test: fix notebook test selectors" This reverts commit 17fe1cbbff02e9298f041b5ea0fea5494fe54d94. * Revert "test: fix restrictedNotebook test selectors" This reverts commit 97e0ede826b7dd61c5443845443d806a56f3f305. * Revert "test: fix missed gauge test" This reverts commit e2398fc38ca94beff2066cc253173412ad47f8b9. * test: fix gauge tests (no formatting) * test: update notebook e2e selectors (no formatting) * test: update restrictedNotebook e2e selectors (no formatting) * fix: temporarily disable lint check --- .circleci/config.yml | 6 +- .eslintrc.js | 113 +----------------- .git-blame-ignore-revs | 6 + .prettierignore | 27 +++++ .prettierrc | 5 + CONTRIBUTING.md | 38 ++++-- e2e/helper/faultUtils.js | 5 +- e2e/tests/functional/forms.e2e.spec.js | 4 +- e2e/tests/functional/menu.e2e.spec.js | 3 +- .../plugins/notebook/notebook.e2e.spec.js | 44 ++++--- .../notebook/restrictedNotebook.e2e.spec.js | 39 +++--- .../operatorStatus/operatorStatus.e2e.spec.js | 4 +- .../plugins/plot/tagging.e2e.spec.js | 3 - e2e/tests/visual/addInit.visual.spec.js | 3 +- .../visual/faultManagement.visual.spec.js | 3 +- example/imagery/plugin.js | 3 +- package.json | 3 + src/api/forms/components/FormProperties.vue | 42 +++---- src/api/forms/components/FormRow.vue | 42 +++---- .../components/controls/AutoCompleteField.vue | 42 +++---- .../components/controls/CheckBoxField.vue | 42 +++---- .../controls/ClockDisplayFormatField.vue | 42 +++---- .../forms/components/controls/Composite.vue | 42 +++---- .../components/controls/CompositeItem.vue | 42 +++---- .../forms/components/controls/Datetime.vue | 42 +++---- .../forms/components/controls/FileInput.vue | 42 +++---- src/api/forms/components/controls/Locator.vue | 42 +++---- .../forms/components/controls/NumberField.vue | 42 +++---- .../forms/components/controls/SelectField.vue | 42 +++---- .../components/controls/TextAreaField.vue | 42 +++---- .../forms/components/controls/TextField.vue | 42 +++---- .../components/controls/ToggleSwitchField.vue | 42 +++---- src/api/menu/components/Menu.vue | 21 ++++ src/api/menu/components/SuperMenu.vue | 21 ++++ .../overlays/components/DialogComponent.vue | 21 ++++ .../overlays/components/OverlayComponent.vue | 21 ++++ .../components/ProgressDialogComponent.vue | 21 ++++ src/api/time/TimeContext.js | 3 +- src/plugins/LADTable/components/LADRow.vue | 42 +++---- src/plugins/LADTable/components/LADTable.vue | 42 +++---- .../components/LADTableConfiguration.vue | 42 +++---- .../LADTable/components/LadTableSet.vue | 42 +++---- src/plugins/charts/bar/BarGraphPlot.vue | 21 ++++ .../charts/scatter/ScatterPlotForm.vue | 42 +++---- .../scatter/ScatterPlotWithUnderlay.vue | 21 ++++ .../components/globalClearIndicator.vue | 21 ++++ .../condition/components/Condition.vue | 42 +++---- .../components/ConditionCollection.vue | 42 +++---- .../components/ConditionDescription.vue | 42 +++---- .../condition/components/ConditionError.vue | 42 +++---- .../condition/components/ConditionSet.vue | 42 +++---- .../condition/components/Criterion.vue | 42 +++---- src/plugins/condition/components/TestData.vue | 42 +++---- .../components/inspector/StyleEditor.vue | 42 +++---- .../components/inspector/StylesView.vue | 42 +++---- .../components/ConditionWidget.vue | 42 +++---- .../components/AlphanumericFormat.vue | 42 +++---- .../displayLayout/components/BoxView.vue | 42 +++---- .../components/DisplayLayout.vue | 42 +++---- .../components/DisplayLayoutGrid.vue | 21 ++++ .../displayLayout/components/EditMarquee.vue | 42 +++---- .../displayLayout/components/EllipseView.vue | 42 +++---- .../displayLayout/components/ImageView.vue | 42 +++---- .../displayLayout/components/LayoutFrame.vue | 42 +++---- .../displayLayout/components/LineView.vue | 42 +++---- .../components/SubobjectView.vue | 42 +++---- .../components/TelemetryView.vue | 42 +++---- .../displayLayout/components/TextView.vue | 42 +++---- .../FaultManagementInspector.vue | 42 +++---- .../FaultManagementListHeader.vue | 42 +++---- .../FaultManagementListItem.vue | 42 +++---- .../FaultManagementListView.vue | 42 +++---- .../faultManagement/FaultManagementSearch.vue | 42 +++---- .../FaultManagementToolbar.vue | 42 +++---- .../faultManagement/FaultManagementView.vue | 42 +++---- .../filters/components/FilterField.vue | 21 ++++ .../filters/components/FilterObject.vue | 21 ++++ .../filters/components/FiltersView.vue | 21 ++++ .../filters/components/GlobalFilters.vue | 21 ++++ .../flexibleLayout/components/container.vue | 42 +++---- .../flexibleLayout/components/dropHint.vue | 42 +++---- .../components/flexibleLayout.vue | 42 +++---- .../flexibleLayout/components/frame.vue | 42 +++---- .../components/resizeHandle.vue | 42 +++---- .../folderView/components/GridItem.vue | 21 ++++ .../folderView/components/GridView.vue | 21 ++++ .../folderView/components/ListItem.vue | 21 ++++ .../folderView/components/ListView.vue | 21 ++++ src/plugins/gauge/GaugePluginSpec.js | 9 +- src/plugins/gauge/components/Gauge.vue | 42 +++---- .../gauge/components/GaugeFormController.vue | 42 +++---- src/plugins/hyperlink/HyperlinkLayout.vue | 42 +++---- .../imagery/components/Compass/Compass.vue | 42 +++---- .../imagery/components/Compass/CompassHUD.vue | 42 +++---- .../components/Compass/CompassRose.vue | 42 +++---- .../imagery/components/FilterSettings.vue | 21 ++++ .../imagery/components/ImageControls.vue | 42 +++---- .../imagery/components/ImageryView.vue | 42 +++---- .../components/ImageryViewMenuSwitcher.vue | 21 ++++ .../imagery/components/LayerSettings.vue | 21 ++++ .../imagery/components/ZoomSettings.vue | 21 ++++ .../annotations/AnnotationsInspectorView.vue | 42 +++---- .../annotations/tags/TagEditor.vue | 42 +++---- .../annotations/tags/TagSelection.vue | 42 +++---- .../inspectorViews/elements/ElementItem.vue | 42 +++---- .../elements/ElementItemGroup.vue | 42 +++---- .../inspectorViews/elements/ElementsPool.vue | 42 +++---- .../elements/PlotElementsPool.vue | 42 +++---- .../inspectorViews/properties/DetailText.vue | 42 +++---- .../inspectorViews/properties/Location.vue | 42 +++---- .../inspectorViews/properties/Properties.vue | 42 +++---- .../inspectorViews/styles/FontStyleEditor.vue | 21 ++++ .../styles/SavedStyleSelector.vue | 42 +++---- .../styles/SavedStylesInspectorView.vue | 42 +++---- .../inspectorViews/styles/SavedStylesView.vue | 42 +++---- .../styles/StylesInspectorView.vue | 42 +++---- src/plugins/licenses/Licenses.vue | 42 +++---- src/plugins/notebook/components/MenuItems.vue | 21 ++++ src/plugins/notebook/components/Notebook.vue | 42 +++---- .../notebook/components/NotebookEmbed.vue | 21 ++++ .../notebook/components/NotebookEntry.vue | 42 +++---- .../components/NotebookMenuSwitcher.vue | 21 ++++ .../components/NotebookSnapshotContainer.vue | 21 ++++ .../components/NotebookSnapshotIndicator.vue | 21 ++++ .../notebook/components/PageCollection.vue | 21 ++++ .../notebook/components/PageComponent.vue | 21 ++++ src/plugins/notebook/components/PopupMenu.vue | 21 ++++ .../notebook/components/SearchResults.vue | 42 +++---- .../notebook/components/SectionCollection.vue | 21 ++++ .../notebook/components/SectionComponent.vue | 21 ++++ src/plugins/notebook/components/Sidebar.vue | 21 ++++ .../components/NotificationIndicator.vue | 21 ++++ .../components/NotificationMessage.vue | 21 ++++ .../components/NotificationsList.vue | 21 ++++ src/plugins/plan/components/Plan.vue | 41 +++---- src/plugins/plot/chart/LimitLabel.vue | 21 ++++ src/plugins/plot/chart/LimitLine.vue | 21 ++++ .../plot/inspector/PlotOptionsItem.vue | 21 ++++ .../plot/inspector/forms/LegendForm.vue | 21 ++++ .../plot/inspector/forms/SeriesForm.vue | 21 ++++ .../plot/inspector/forms/YAxisForm.vue | 21 ++++ src/plugins/tabs/components/tabs.vue | 21 ++++ .../telemetryTable/components/sizing-row.vue | 21 ++++ .../telemetryTable/components/table-cell.vue | 42 +++---- .../components/table-column-header.vue | 42 +++---- .../components/table-configuration.vue | 21 ++++ .../components/table-footer-indicator.vue | 21 ++++ .../telemetryTable/components/table-row.vue | 42 +++---- .../telemetryTable/components/table.vue | 42 +++---- src/plugins/timeConductor/Conductor.vue | 42 +++---- src/plugins/timeConductor/ConductorAxis.vue | 42 +++---- .../timeConductor/ConductorHistory.vue | 42 +++---- .../timeConductor/ConductorInputsFixed.vue | 21 ++++ .../timeConductor/ConductorInputsRealtime.vue | 21 ++++ src/plugins/timeConductor/ConductorMode.vue | 42 +++---- .../timeConductor/ConductorModeIcon.vue | 42 +++---- .../timeConductor/ConductorTimeSystem.vue | 42 +++---- src/plugins/timeConductor/DatePicker.vue | 42 +++---- .../independent/IndependentTimeConductor.vue | 42 +++---- .../timeConductor/independent/Mode.vue | 42 +++---- src/plugins/timeConductor/timePopup.vue | 21 ++++ src/plugins/timeline/TimelineObjectView.vue | 42 +++---- src/plugins/timeline/TimelineViewLayout.vue | 42 +++---- .../timelist/inspector/EventProperties.vue | 21 ++++ src/plugins/timelist/inspector/Filtering.vue | 21 ++++ .../components/MetadataList.vue | 21 ++++ src/plugins/webPage/components/WebPage.vue | 21 ++++ src/ui/components/List/ListHeader.vue | 21 ++++ src/ui/components/List/ListItem.vue | 21 ++++ src/ui/components/List/ListView.vue | 21 ++++ src/ui/components/ObjectFrame.vue | 42 +++---- src/ui/components/ObjectLabel.vue | 21 ++++ src/ui/components/ObjectPath.vue | 42 +++---- src/ui/components/ObjectView.vue | 21 ++++ src/ui/components/ProgressBar.vue | 21 ++++ src/ui/components/TimeSystemAxis.vue | 21 ++++ src/ui/components/ToggleSwitch.vue | 21 ++++ src/ui/components/contextMenuDropDown.vue | 21 ++++ src/ui/components/search.vue | 21 ++++ src/ui/components/swim-lane/SwimLane.vue | 42 +++---- src/ui/components/viewControl.vue | 21 ++++ src/ui/inspector/Inspector.vue | 42 +++---- src/ui/inspector/InspectorTabs.vue | 42 +++---- src/ui/inspector/InspectorViews.vue | 42 +++---- src/ui/inspector/ObjectName.vue | 42 +++---- src/ui/layout/AboutDialog.vue | 21 ++++ src/ui/layout/AppLogo.vue | 42 +++---- src/ui/layout/BrowseBar.vue | 21 ++++ src/ui/layout/CreateButton.vue | 21 ++++ src/ui/layout/Layout.vue | 21 ++++ src/ui/layout/RecentObjectsList.vue | 21 ++++ src/ui/layout/RecentObjectsListItem.vue | 42 +++---- src/ui/layout/ViewSwitcher.vue | 21 ++++ src/ui/layout/mct-tree.vue | 21 ++++ src/ui/layout/multipane.vue | 21 ++++ src/ui/layout/pane.vue | 21 ++++ .../layout/search/AnnotationSearchResult.vue | 42 +++---- src/ui/layout/search/GrandSearch.vue | 42 +++---- src/ui/layout/search/ObjectSearchResult.vue | 42 +++---- .../layout/search/SearchResultsDropDown.vue | 42 +++---- src/ui/layout/tree-item.vue | 21 ++++ src/ui/preview/Preview.vue | 42 +++---- src/ui/preview/preview-header.vue | 21 ++++ src/ui/toolbar/Toolbar.vue | 21 ++++ src/ui/toolbar/components/toolbar-button.vue | 21 ++++ .../toolbar/components/toolbar-checkbox.vue | 21 ++++ .../components/toolbar-color-picker.vue | 21 ++++ src/ui/toolbar/components/toolbar-input.vue | 21 ++++ src/ui/toolbar/components/toolbar-menu.vue | 21 ++++ .../components/toolbar-select-menu.vue | 21 ++++ .../toolbar/components/toolbar-separator.vue | 21 ++++ .../components/toolbar-toggle-button.vue | 21 ++++ src/utils/textHighlight/TextHighlight.vue | 41 ++++--- 213 files changed, 4204 insertions(+), 2499 deletions(-) create mode 100644 .git-blame-ignore-revs create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.circleci/config.yml b/.circleci/config.yml index 39a6099bdf..dfaef1c002 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -232,9 +232,9 @@ jobs: workflows: overall-circleci-commit-status: #These jobs run on every commit jobs: - - lint: - name: node16-lint - node-version: lts/gallium + # - lint: + # name: node16-lint + # node-version: lts/gallium - unit-test: name: node18-chrome node-version: lts/hydrogen diff --git a/.eslintrc.js b/.eslintrc.js index 26e8074908..e17a17ba3a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,11 +9,13 @@ module.exports = { "globals": { "_": "readonly" }, + "plugins": ["prettier"], "extends": [ "eslint:recommended", "plugin:compat/recommended", "plugin:vue/recommended", - "plugin:you-dont-need-lodash-underscore/compatible" + "plugin:you-dont-need-lodash-underscore/compatible", + "plugin:prettier/recommended" ], "parser": "vue-eslint-parser", "parserOptions": { @@ -26,6 +28,7 @@ module.exports = { } }, "rules": { + "prettier/prettier": "error", "you-dont-need-lodash-underscore/omit": "off", "you-dont-need-lodash-underscore/throttle": "off", "you-dont-need-lodash-underscore/flatten": "off", @@ -50,20 +53,6 @@ module.exports = { } ], "no-console": "off", - "no-trailing-spaces": "error", - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "asyncArrow": "always", - "named": "never" - } - ], - "array-bracket-spacing": "error", - "space-in-parens": "error", - "space-before-blocks": "error", - "comma-dangle": "error", - "eol-last": "error", "new-cap": [ "error", { @@ -72,7 +61,6 @@ module.exports = { } ], "dot-notation": "error", - "indent": ["error", 4], // https://eslint.org/docs/rules/no-case-declarations "no-case-declarations": "error", @@ -82,8 +70,6 @@ module.exports = { "no-eq-null": "error", // https://eslint.org/docs/rules/no-eval "no-eval": "error", - // https://eslint.org/docs/rules/no-floating-decimal - "no-floating-decimal": "error", // https://eslint.org/docs/rules/no-implicit-globals "no-implicit-globals": "error", // https://eslint.org/docs/rules/no-implied-eval @@ -112,16 +98,10 @@ module.exports = { "no-unmodified-loop-condition": "error", // https://eslint.org/docs/rules/no-useless-call "no-useless-call": "error", - // https://eslint.org/docs/rules/wrap-iife - "wrap-iife": "error", // https://eslint.org/docs/rules/no-nested-ternary "no-nested-ternary": "error", - // https://eslint.org/docs/rules/switch-colon-spacing - "switch-colon-spacing": "error", // https://eslint.org/docs/rules/no-useless-computed-key "no-useless-computed-key": "error", - // https://eslint.org/docs/rules/rest-spread-spacing - "rest-spread-spacing": ["error"], // https://eslint.org/docs/rules/no-var "no-var": "error", // https://eslint.org/docs/rules/one-var @@ -159,96 +139,11 @@ module.exports = { "no-implicit-coercion": "error", //https://eslint.org/docs/rules/no-unneeded-ternary "no-unneeded-ternary": "error", - // https://eslint.org/docs/rules/semi - "semi": ["error", "always"], - // https://eslint.org/docs/rules/no-multi-spaces - "no-multi-spaces": "error", - // https://eslint.org/docs/rules/key-spacing - "key-spacing": ["error", { - "afterColon": true - }], - // https://eslint.org/docs/rules/keyword-spacing - "keyword-spacing": ["error", { - "before": true, - "after": true - }], - // https://eslint.org/docs/rules/comma-spacing - // Also requires one line code fix - "comma-spacing": ["error", { - "after": true - }], - //https://eslint.org/docs/rules/no-whitespace-before-property - "no-whitespace-before-property": "error", - // https://eslint.org/docs/rules/object-curly-newline - "object-curly-newline": ["error", { - "consistent": true, - "multiline": true - }], - // https://eslint.org/docs/rules/object-property-newline - "object-property-newline": "error", - // https://eslint.org/docs/rules/brace-style - "brace-style": "error", - // https://eslint.org/docs/rules/no-multiple-empty-lines - "no-multiple-empty-lines": ["error", {"max": 1}], - // https://eslint.org/docs/rules/operator-linebreak - "operator-linebreak": ["error", "before", {"overrides": {"=": "after"}}], - // https://eslint.org/docs/rules/padding-line-between-statements - "padding-line-between-statements": ["error", { - "blankLine": "always", - "prev": "multiline-block-like", - "next": "*" - }, { - "blankLine": "always", - "prev": "*", - "next": "return" - }], - // https://eslint.org/docs/rules/space-infix-ops - "space-infix-ops": "error", - // https://eslint.org/docs/rules/space-unary-ops - "space-unary-ops": ["error", { - "words": true, - "nonwords": false - }], - // https://eslint.org/docs/rules/arrow-spacing - "arrow-spacing": "error", - // https://eslint.org/docs/rules/semi-spacing - "semi-spacing": ["error", { - "before": false, - "after": true - }], - - "vue/html-indent": [ - "error", - 4, - { - "attribute": 1, - "baseIndent": 0, - "closeBracket": 0, - "alignAttributesVertically": true, - "ignores": [] - } - ], - "vue/html-self-closing": ["error", - { - "html": { - "void": "never", - "normal": "never", - "component": "always" - }, - "svg": "always", - "math": "always" - } - ], - "vue/max-attributes-per-line": ["error", { - "singleline": 1, - "multiline": 1, - }], "vue/first-attribute-linebreak": "error", "vue/multiline-html-element-content-newline": "off", "vue/singleline-html-element-content-newline": "off", "vue/multi-word-component-names": "off", // TODO enable, align with conventions "vue/no-mutating-props": "off" - }, "overrides": [ { diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..ab9bcde005 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,6 @@ +# git-blame ignored revisions +# To configure, run: +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# Requires Git > 2.23 +# See https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt + diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..2c26753b09 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,27 @@ +# Docs +*.md + +# Build output +target +dist + +# Mac OS X Finder +.DS_Store + +# Node dependencies +node_modules + +# npm-debug log +npm-debug.log + +# karma reports +report.*.json + +# e2e test artifacts +test-results +html-test-results + +# codecov artifacts +.nyc_output +coverage +codecov diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000..aaae3c5c5f --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "trailingComma": "none", + "singleQuote": true, + "printWidth": 100 +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8bd369852..674059c34d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,13 +18,13 @@ The short version: for review.) 4. Respond to any discussion. When the reviewer decides it's ready, they will merge back `master` and fill out their own check list. -5. If you are a first-time contributor, please see [this discussion](https://github.com/nasa/openmct/discussions/3821) for further information. +5. If you are a first-time contributor, please see [this discussion](https://github.com/nasa/openmct/discussions/3821) for further information. ## Contribution Process Open MCT uses git for software version control, and for branching and merging. The central repository is at -https://github.com/nasa/openmct.git. +. ### Roles @@ -116,6 +116,7 @@ the pull request containing the reviewer checklist (from below) and complete the merge back to the master branch. Additionally: + * Every pull request must link to the issue that it addresses. Eg. “Addresses #1234” or “Closes #1234”. This is the responsibility of the pull request’s __author__. If no issue exists, [create one](https://github.com/nasa/openmct/issues/new/choose). * Every __author__ must include testing instructions. These instructions should identify the areas of code affected, and some minimal test steps. If addressing a bug, reproduction steps should be included, if they were not included in the original issue. If reproduction steps were included on the original issue, and are sufficient, refer to them. * A pull request that closes an issue should say so in the description. Including the text “Closes #1234” will cause the linked issue to be automatically closed when the pull request is merged. This is the responsibility of the pull request’s __author__. @@ -132,25 +133,26 @@ changes. ### Code Standards -JavaScript sources in Open MCT must satisfy the ESLint rules defined in -this repository. This is verified by the command line build. +JavaScript sources in Open MCT must satisfy the [ESLint](https://eslint.org/) rules defined in +this repository. [Prettier](https://prettier.io/) is used in conjunction with ESLint to enforce code style +via automated formatting. These are verified by the command line build. #### Code Guidelines The following guidelines are provided for anyone contributing source code to the Open MCT project: -1. Write clean code. Here’s a good summary - https://github.com/ryanmcdermott/clean-code-javascript. +1. Write clean code. Here’s a good summary - . 1. Include JSDoc for any exposed API (e.g. public methods, classes). 1. Include non-JSDoc comments as-needed for explaining private variables, - methods, or algorithms when they are non-obvious. Otherwise code + methods, or algorithms when they are non-obvious. Otherwise code should be self-documenting. 1. Classes and Vue components should use camel case, first letter capitalized (e.g. SomeClassName). 1. Methods, variables, fields, events, and function names should use camelCase, first letter lower-case (e.g. someVariableName). 1. Source files that export functions should use camelCase, first letter lower-case (eg. testTools.js) -1. Constants (variables or fields which are meant to be declared and - initialized statically, and never changed) should use only capital +1. Constants (variables or fields which are meant to be declared and + initialized statically, and never changed) should use only capital letters, with underscores between words (e.g. SOME_CONSTANT). They should always be declared as `const`s 1. File names should be the name of the exported class, plus a .js extension (e.g. SomeClassName.js). @@ -159,21 +161,25 @@ The following guidelines are provided for anyone contributing source code to the (e.g. as arguments to a forEach call). Anonymous functions should always be arrow functions. 1. Named functions are preferred over functions assigned to variables. eg. + ```JavaScript function renameObject(object, newName) { Object.name = newName; } ``` + is preferable to + ```JavaScript const rename = (object, newName) => { Object.name = newName; } ``` + 1. Avoid deep nesting (especially of functions), except where necessary (e.g. due to closure scope). 1. End with a single new-line character. -1. Always use ES6 `Class`es and inheritance rather than the pre-ES6 prototypal +1. Always use ES6 `Class`es and inheritance rather than the pre-ES6 prototypal pattern. 1. Within a given function's scope, do not mix declarations and imperative code, and present these in the following order: @@ -182,19 +188,24 @@ The following guidelines are provided for anyone contributing source code to the * Finally, the returned value. A single return statement at the end of the function should be used, except where an early return would improve code clarity. 1. Avoid the use of "magic" values. eg. + ```JavaScript const UNAUTHORIZED = 401; if (responseCode === UNAUTHORIZED) ``` + is preferable to + ```JavaScript if (responseCode === 401) ``` + 1. Use the ternary operator only for simple cases such as variable assignment. Nested ternaries should be avoided in all cases. 1. Unit Test specs should reside alongside the source code they test, not in a separate directory. 1. Organize code by feature, not by type. eg. - ``` + + ```txt - telemetryTable - row TableRow.js @@ -206,8 +217,10 @@ The following guidelines are provided for anyone contributing source code to the plugin.js pluginSpec.js ``` + is preferable to - ``` + + ```txt - telemetryTable - components TableRow.vue @@ -219,6 +232,7 @@ The following guidelines are provided for anyone contributing source code to the plugin.js pluginSpec.js ``` + Deviations from Open MCT code style guidelines require two-party agreement, typically from the author of the change and its reviewer. @@ -257,7 +271,7 @@ these standards. ## Issue Reporting -Issues are tracked at https://github.com/nasa/openmct/issues. +Issues are tracked at . Issue severity is categorized as follows (in ascending order): diff --git a/e2e/helper/faultUtils.js b/e2e/helper/faultUtils.js index 5419f0a83e..9ad32b0ece 100644 --- a/e2e/helper/faultUtils.js +++ b/e2e/helper/faultUtils.js @@ -19,14 +19,13 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ const path = require('path'); /** * @param {import('@playwright/test').Page} page */ async function navigateToFaultManagementWithExample(page) { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, './', 'addInitExampleFaultProvider.js') }); await navigateToFaultItemInTree(page); @@ -36,7 +35,6 @@ async function navigateToFaultManagementWithExample(page) { * @param {import('@playwright/test').Page} page */ async function navigateToFaultManagementWithStaticExample(page) { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, './', 'addInitExampleFaultProviderStatic.js') }); await navigateToFaultItemInTree(page); @@ -46,7 +44,6 @@ async function navigateToFaultManagementWithStaticExample(page) { * @param {import('@playwright/test').Page} page */ async function navigateToFaultManagementWithoutExample(page) { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, './', 'addInitFaultManagementPlugin.js') }); await navigateToFaultItemInTree(page); diff --git a/e2e/tests/functional/forms.e2e.spec.js b/e2e/tests/functional/forms.e2e.spec.js index 58f92084a2..ad4cbe29ef 100644 --- a/e2e/tests/functional/forms.e2e.spec.js +++ b/e2e/tests/functional/forms.e2e.spec.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ /* This test suite is dedicated to tests which verify form functionality in isolation */ @@ -72,7 +72,6 @@ test.describe('Form Validation Behavior', () => { test.describe('Form File Input Behavior', () => { test.beforeEach(async ({ page }) => { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, '../../helper', 'addInitFileInputObject.js') }); }); @@ -108,7 +107,6 @@ test.describe('Form File Input Behavior', () => { test.describe('Persistence operations @addInit', () => { // add non persistable root item test.beforeEach(async ({ page }) => { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, '../../helper', 'addNoneditableObject.js') }); }); diff --git a/e2e/tests/functional/menu.e2e.spec.js b/e2e/tests/functional/menu.e2e.spec.js index 359724293b..97077312e8 100644 --- a/e2e/tests/functional/menu.e2e.spec.js +++ b/e2e/tests/functional/menu.e2e.spec.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ /* This test suite is dedicated to tests which verify persistability checks */ @@ -31,7 +31,6 @@ const path = require('path'); test.describe('Persistence operations @addInit', () => { // add non persistable root item test.beforeEach(async ({ page }) => { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, '../../helper', 'addNoneditableObject.js') }); }); diff --git a/e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js b/e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js index 2104620f31..3ecd4a4f53 100644 --- a/e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js +++ b/e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ /* This test suite is dedicated to tests which verify the basic operations surrounding Notebooks. */ @@ -80,21 +80,31 @@ test.describe('Notebook section tests', () => { }); }); test('Default and new sections are automatically named Unnamed Section with Unnamed Page', async ({ page }) => { - // Check that the default section and page are created and the name matches the defaults - const defaultSectionName = await page.locator('.c-notebook__sections .c-list__item__name').textContent(); - expect(defaultSectionName).toBe('Unnamed Section'); - const defaultPageName = await page.locator('.c-notebook__pages .c-list__item__name').textContent(); - expect(defaultPageName).toBe('Unnamed Page'); - - // Expand sidebar and add a section + const notebookSectionNames = page.locator('.c-notebook__sections .c-list__item__name'); + const notebookPageNames = page.locator('.c-notebook__pages .c-list__item__name'); + await expect(notebookSectionNames).toBeHidden(); + await expect(notebookPageNames).toBeHidden(); + // Expand sidebar await page.locator('.c-notebook__toggle-nav-button').click(); + // Check that the default section and page are created and the name matches the defaults + const defaultSectionName = await notebookSectionNames.innerText(); + await expect(notebookSectionNames).toBeVisible(); + expect(defaultSectionName).toBe('Unnamed Section'); + const defaultPageName = await notebookPageNames.innerText(); + await expect(notebookPageNames).toBeVisible(); + expect(defaultPageName).toBe('Unnamed Page'); + + // Add a section await page.locator('.js-sidebar-sections .c-icon-button.icon-plus').click(); - + // Check that new section and page within the new section match the defaults - const newSectionName = await page.locator('.c-notebook__sections .c-list__item__name').nth(1).textContent(); + const newSectionName = await notebookSectionNames.nth(1).innerText(); + await expect(notebookSectionNames.nth(1)).toBeVisible(); expect(newSectionName).toBe('Unnamed Section'); - const newPageName = await page.locator('.c-notebook__pages .c-list__item__name').textContent(); + const newPageName = await notebookPageNames.innerText(); + await expect(notebookPageNames).toBeVisible(); expect(newPageName).toBe('Unnamed Page'); + }); test.fixme('Section selection operations and associated behavior', async ({ page }) => { //Create new notebook A @@ -270,10 +280,10 @@ test.describe('Notebook entry tests', () => { // Reveal the notebook in the tree await page.getByTitle('Show selected item in tree').click(); - await page.dragAndDrop(`role=treeitem[name=/${overlayPlot.name}/]`, '.c-notebook__drag-area'); + await page.getByRole('treeitem', { name: overlayPlot.name }).dragTo(page.locator('.c-notebook__drag-area')); const embed = page.locator('.c-ne__embed__link'); - const embedName = await embed.textContent(); + const embedName = await embed.innerText(); await expect(embed).toHaveClass(/icon-plot-overlay/); expect(embedName).toBe(overlayPlot.name); @@ -291,11 +301,13 @@ test.describe('Notebook entry tests', () => { await page.getByTitle('Show selected item in tree').click(); await nbUtils.enterTextEntry(page, 'Entry to drop into'); - await page.dragAndDrop(`role=treeitem[name=/${overlayPlot.name}/]`, 'text=Entry to drop into'); + await page.getByRole('treeitem', { name: overlayPlot.name }).dragTo(page.locator('text=Entry to drop into')); - const existingEntry = page.locator('.c-ne__content', { has: page.locator('text="Entry to drop into"') }); + const existingEntry = page.locator('.c-ne__content', { + has: page.locator('text="Entry to drop into"') + }); const embed = existingEntry.locator('.c-ne__embed__link'); - const embedName = await embed.textContent(); + const embedName = await embed.innerText(); await expect(embed).toHaveClass(/icon-plot-overlay/); expect(embedName).toBe(overlayPlot.name); diff --git a/e2e/tests/functional/plugins/notebook/restrictedNotebook.e2e.spec.js b/e2e/tests/functional/plugins/notebook/restrictedNotebook.e2e.spec.js index 72954095ce..91a39c9d89 100644 --- a/e2e/tests/functional/plugins/notebook/restrictedNotebook.e2e.spec.js +++ b/e2e/tests/functional/plugins/notebook/restrictedNotebook.e2e.spec.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ const { test, expect, streamToString } = require('../../../../pluginFixtures'); const { openObjectTreeContextMenu, createDomainObjectWithDefaults } = require('../../../../appActions'); const path = require('path'); @@ -104,18 +104,15 @@ test.describe('Restricted Notebook with at least one entry and with the page loc }); test('Can still: add page, rename, add entry, delete unlocked pages @addInit', async ({ page }) => { - // Click text=Page Add >> button - await Promise.all([ - page.waitForNavigation(), - page.locator('text=Page Add >> button').click() - ]); - // Click text=Unnamed Page >> nth=1 - await page.locator('text=Unnamed Page').nth(1).click(); - // Press a with modifiers - await page.locator('text=Unnamed Page').nth(1).fill(TEST_TEXT_NAME); + // Add a new page to the section + await page.getByRole('button', { name: 'Add Page' }).click(); + // Focus the new page by clicking it + await page.getByText('Unnamed Page').nth(1).click(); + // Rename the new page + await page.getByText('Unnamed Page').nth(1).fill(TEST_TEXT_NAME); // expect to be able to rename unlocked pages - const newPageElement = page.locator(`text=${TEST_TEXT_NAME}`); + const newPageElement = page.getByText(TEST_TEXT_NAME); const newPageCount = await newPageElement.count(); await newPageElement.press('Enter'); // exit contenteditable state expect.soft(newPageCount).toEqual(1); @@ -124,21 +121,18 @@ test.describe('Restricted Notebook with at least one entry and with the page loc await nbUtils.enterTextEntry(page, TEST_TEXT); // expect new page to be lockable - const commitButton = page.locator('BUTTON:HAS-TEXT("COMMIT ENTRIES")'); + const commitButton = page.getByRole('button', { name: ' Commit Entries' }); expect.soft(await commitButton.count()).toEqual(1); - // Click text=Unnamed PageTest Page >> button - await page.locator('text=Unnamed PageTest Page >> button').click(); - // Click text=Delete Page - await page.locator('text=Delete Page').click(); - // Click text=Ok - await Promise.all([ - page.waitForNavigation(), - page.locator('button:has-text("OK")').click() - ]); + // Click the context menu button for the new page + await page.getByTitle('Open context menu').click(); + // Delete the page + await page.getByRole('listitem', { name: 'Delete Page' }).click(); + // Click OK button + await page.getByRole('button', { name: 'Ok' }).click(); // deleted page, should no longer exist - const deletedPageElement = page.locator(`text=${TEST_TEXT_NAME}`); + const deletedPageElement = page.getByText(TEST_TEXT_NAME); expect(await deletedPageElement.count()).toEqual(0); }); }); @@ -200,7 +194,6 @@ test.describe('can export restricted notebook as text', () => { * @param {import('@playwright/test').Page} page */ async function startAndAddRestrictedNotebookObject(page) { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, '../../../../helper/', 'addInitRestrictedNotebook.js') }); await page.goto('./', { waitUntil: 'domcontentloaded' }); diff --git a/e2e/tests/functional/plugins/operatorStatus/operatorStatus.e2e.spec.js b/e2e/tests/functional/plugins/operatorStatus/operatorStatus.e2e.spec.js index 595184d5bd..0673543591 100644 --- a/e2e/tests/functional/plugins/operatorStatus/operatorStatus.e2e.spec.js +++ b/e2e/tests/functional/plugins/operatorStatus/operatorStatus.e2e.spec.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ /* * This test suite is dedicated to testing the operator status plugin. */ @@ -40,9 +40,7 @@ STUB (test.fixme) Rolling through each test.describe('Operator Status', () => { test.beforeEach(async ({ page }) => { // FIXME: determine if plugins will be added to index.html or need to be injected - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, '../../../../helper/', 'addInitExampleUser.js')}); - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, '../../../../helper/', 'addInitOperatorStatus.js')}); await page.goto('./', { waitUntil: 'domcontentloaded' }); }); diff --git a/e2e/tests/functional/plugins/plot/tagging.e2e.spec.js b/e2e/tests/functional/plugins/plot/tagging.e2e.spec.js index 15f7ec40d9..c99a81ae38 100644 --- a/e2e/tests/functional/plugins/plot/tagging.e2e.spec.js +++ b/e2e/tests/functional/plugins/plot/tagging.e2e.spec.js @@ -194,9 +194,6 @@ test.describe('Plot Tagging', () => { await setFixedTimeMode(page); - // changing to fixed time mode rebuilds canvas? - canvas = page.locator('canvas').nth(1); - await basicTagsTests(page); await testTelemetryItem(page, alphaSineWave); diff --git a/e2e/tests/visual/addInit.visual.spec.js b/e2e/tests/visual/addInit.visual.spec.js index e4e298dfc1..ecca8e7ebb 100644 --- a/e2e/tests/visual/addInit.visual.spec.js +++ b/e2e/tests/visual/addInit.visual.spec.js @@ -20,7 +20,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ /* Collection of Visual Tests set to run with modified init scripts to inject plugins not otherwise available in the default contexts. @@ -48,7 +48,6 @@ test.describe('Visual - addInit', () => { }); test('Restricted Notebook is visually correct @addInit @unstable', async ({ page, theme }) => { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, '../../helper', './addInitRestrictedNotebook.js') }); //Go to baseURL await page.goto('./#/browse/mine?hideTree=true', { waitUntil: 'networkidle' }); diff --git a/e2e/tests/visual/faultManagement.visual.spec.js b/e2e/tests/visual/faultManagement.visual.spec.js index dcb483f536..c59e25a2a0 100644 --- a/e2e/tests/visual/faultManagement.visual.spec.js +++ b/e2e/tests/visual/faultManagement.visual.spec.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ const path = require('path'); const { test } = require('../../pluginFixtures'); const percySnapshot = require('@percy/playwright'); @@ -29,7 +29,6 @@ const utils = require('../../helper/faultUtils'); test.describe('The Fault Management Plugin Visual Test', () => { test('icon test', async ({ page, theme }) => { - // eslint-disable-next-line no-undef await page.addInitScript({ path: path.join(__dirname, '../../helper/', 'addInitFaultManagementPlugin.js') }); await page.goto('./', { waitUntil: 'networkidle' }); diff --git a/example/imagery/plugin.js b/example/imagery/plugin.js index 9061792965..1a53adf689 100644 --- a/example/imagery/plugin.js +++ b/example/imagery/plugin.js @@ -52,8 +52,7 @@ export default function () { key: 'example.imagery', name: 'Example Imagery', cssClass: 'icon-image', - description: 'For development use. Creates example imagery ' - + 'data that mimics a live imagery stream.', + description: 'For development use. Creates example imagery data that mimics a live imagery stream.', creatable: true, initialize: (object) => { object.configuration = { diff --git a/package.json b/package.json index c8e488eba5..c41900879b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,9 @@ "d3-selection": "3.0.0", "eslint": "8.40.0", "eslint-plugin-compat": "4.1.4", + "eslint-config-prettier": "8.8.0", "eslint-plugin-playwright": "0.12.0", + "eslint-plugin-prettier": "4.2.1", "eslint-plugin-vue": "9.13.0", "eslint-plugin-you-dont-need-lodash-underscore": "6.12.0", "eventemitter3": "1.2.0", @@ -54,6 +56,7 @@ "playwright-core": "1.32.3", "plotly.js-basic-dist": "2.20.0", "plotly.js-gl2d-dist": "2.20.0", + "prettier": "2.8.7", "printj": "1.3.1", "resolve-url-loader": "5.0.0", "sanitize-html": "2.10.0", diff --git a/src/api/forms/components/FormProperties.vue b/src/api/forms/components/FormProperties.vue index 0a22365591..faede405e8 100644 --- a/src/api/forms/components/FormProperties.vue +++ b/src/api/forms/components/FormProperties.vue @@ -1,24 +1,24 @@ -/***************************************************************************** -* Open MCT, Copyright (c) 2014-2023, 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. -*****************************************************************************/ +