Repository: ember-cli/ember-cli
Pull request #9391 (2020-11-30 04:00:26)

Add prettier to blueprint
Implements this RFC: https://github.com/emberjs/rfcs/blob/master/text/0628-prettier.md (https://github.com/emberjs/rfcs/pull/628)

Changes included:
* Installs prettier dev dependencies (package.json)
* Updates lint scripts (package.json)
* Adds `plugin:prettier/recommended` to .eslintrc.js
* Creates new file `.prettierrc.js`
* Adds `.prettierrc.js` to Node files override in .eslintrc.js
* Adds `.eslintcache` to .eslintiginore
* Creates new file `.prettierignore` (duplicate of .eslintignore)
* Fixes prettier violations in blueprints and test fixtures

TODO:

- [x] update tests
- [x] manually test this
- [x] ensure ember-cli generated code has no prettier violations
- [ ] update `ember generate` to run `lint:fix`  to fix prettier violations in external blueprints? ([RFC section](https://github.com/emberjs/rfcs/blob/master/text/0628-prettier.md#blueprint-changes))


Patch:
diff --git a/blueprints/addon/files/addon-config/ember-try.js b/blueprints/addon/files/addon-config/ember-try.js
index e4e8973d6..657373b20 100644
--- a/blueprints/addon/files/addon-config/ember-try.js
+++ b/blueprints/addon/files/addon-config/ember-try.js
@@ -2,7 +2,7 @@
 
 const getChannelURL = require('ember-source-channel-url');
 
-module.exports = async function() {
+module.exports = async function () {
   return {
     <% if (yarn) { %>useYarn: true,
     <% } %>scenarios: [
@@ -10,54 +10,54 @@ module.exports = async function() {
         name: 'ember-lts-3.16',
         npm: {
           devDependencies: {
-            'ember-source': '~3.16.0'
-          }
-        }
+            'ember-source': '~3.16.0',
+          },
+        },
       },
       {
         name: 'ember-lts-3.20',
         npm: {
           devDependencies: {
-            'ember-source': '~3.20.5'
-          }
-        }
+            'ember-source': '~3.20.5',
+          },
+        },
       },
       {
         name: 'ember-release',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('release')
-          }
-        }
+            'ember-source': await getChannelURL('release'),
+          },
+        },
       },
       {
         name: 'ember-beta',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('beta')
-          }
-        }
+            'ember-source': await getChannelURL('beta'),
+          },
+        },
       },
       {
         name: 'ember-canary',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('canary')
-          }
-        }
+            'ember-source': await getChannelURL('canary'),
+          },
+        },
       },
       {
         name: 'ember-default-with-jquery',
         env: {
           EMBER_OPTIONAL_FEATURES: JSON.stringify({
-            'jquery-integration': true
-          })
+            'jquery-integration': true,
+          }),
         },
         npm: {
           devDependencies: {
-            '@ember/jquery': '^1.1.0'
-          }
-        }
+            '@ember/jquery': '^1.1.0',
+          },
+        },
       },
       {
         name: 'ember-classic',
@@ -65,15 +65,15 @@ module.exports = async function() {
           EMBER_OPTIONAL_FEATURES: JSON.stringify({
             'application-template-wrapper': true,
             'default-async-observers': false,
-            'template-only-glimmer-components': false
-          })
+            'template-only-glimmer-components': false,
+          }),
         },
         npm: {
           ember: {
-            edition: 'classic'
-          }
-        }
-      }
-    ]
+            edition: 'classic',
+          },
+        },
+      },
+    ],
   };
 };
diff --git a/blueprints/addon/files/addon-config/environment.js b/blueprints/addon/files/addon-config/environment.js
index 0dfaed472..331ab30df 100644
--- a/blueprints/addon/files/addon-config/environment.js
+++ b/blueprints/addon/files/addon-config/environment.js
@@ -1,5 +1,5 @@
 'use strict';
 
-module.exports = function(/* environment, appConfig */) {
-  return { };
+module.exports = function (/* environment, appConfig */) {
+  return {};
 };
diff --git a/blueprints/addon/files/ember-cli-build.js b/blueprints/addon/files/ember-cli-build.js
index dc5a39e1b..ba0649dc9 100644
--- a/blueprints/addon/files/ember-cli-build.js
+++ b/blueprints/addon/files/ember-cli-build.js
@@ -2,7 +2,7 @@
 
 const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
   let app = new EmberAddon(defaults, {
     // Add options here
   });
diff --git a/blueprints/addon/files/index.js b/blueprints/addon/files/index.js
index 2e1d1d8d5..0ca063d42 100644
--- a/blueprints/addon/files/index.js
+++ b/blueprints/addon/files/index.js
@@ -1,5 +1,5 @@
 'use strict';
 
 module.exports = {
-  name: require('./package').name
+  name: require('./package').name,
 };
diff --git a/blueprints/app/files/.eslintignore b/blueprints/app/files/.eslintignore
index 72df37307..922165552 100644
--- a/blueprints/app/files/.eslintignore
+++ b/blueprints/app/files/.eslintignore
@@ -13,6 +13,7 @@
 # misc
 /coverage/
 !.*
+.eslintcache
 
 # ember-try
 /.node_modules.ember-try/
diff --git a/blueprints/app/files/.eslintrc.js b/blueprints/app/files/.eslintrc.js
index 11a44f2eb..256132080 100644
--- a/blueprints/app/files/.eslintrc.js
+++ b/blueprints/app/files/.eslintrc.js
@@ -7,18 +7,17 @@ module.exports = {
     ecmaVersion: 2018,
     sourceType: 'module',
     ecmaFeatures: {
-      legacyDecorators: true
-    }
+      legacyDecorators: true,
+    },
   },
-  plugins: [
-    'ember'
-  ],
+  plugins: ['ember'],
   extends: [
     'eslint:recommended',
-    'plugin:ember/recommended'
+    'plugin:ember/recommended',
+    'plugin:prettier/recommended',
   ],
   env: {
-    browser: true
+    browser: true,
   },
   rules: {},
   overrides: [
@@ -26,36 +25,37 @@ module.exports = {
     {
       files: [
         '.eslintrc.js',
+        '.prettierrc.js',
         '.template-lintrc.js',
         'ember-cli-build.js',<% if (blueprint !== 'app') { %>
         'index.js',<% } %>
         'testem.js',
         'blueprints/*/index.js',
-        'config/**/*.js'<% if (blueprint === 'app') { %>,
+        'config/**/*.js',<% if (blueprint === 'app') { %>
         'lib/*/index.js',
-        'server/**/*.js'<% } else { %>,
-        'tests/dummy/config/**/*.js'<% } %>
+        'server/**/*.js',<% } else { %>
+        'tests/dummy/config/**/*.js',<% } %>
       ],<% if (blueprint !== 'app') { %>
       excludedFiles: [
         'addon/**',
         'addon-test-support/**',
         'app/**',
-        'tests/dummy/app/**'
+        'tests/dummy/app/**',
       ],<% } %>
       parserOptions: {
-        sourceType: 'script'
+        sourceType: 'script',
       },
       env: {
         browser: false,
-        node: true
+        node: true,
       },
       plugins: ['node'],
-      extends: ['plugin:node/recommended']<% if (blueprint === 'app') {%>,
+      extends: ['plugin:node/recommended'],<% if (blueprint === 'app') {%>
       rules: {
         // this can be removed once the following is fixed
         // https://github.com/mysticatea/eslint-plugin-node/issues/77
-        'node/no-unpublished-require': 'off'
-      }<% } %>
-    }
-  ]
+        'node/no-unpublished-require': 'off',
+      },<% } %>
+    },
+  ],
 };
diff --git a/blueprints/app/files/.prettierignore b/blueprints/app/files/.prettierignore
new file mode 100644
index 000000000..922165552
--- /dev/null
+++ b/blueprints/app/files/.prettierignore
@@ -0,0 +1,21 @@
+# unconventional js
+/blueprints/*/files/
+/vendor/
+
+# compiled output
+/dist/
+/tmp/
+
+# dependencies
+/bower_components/
+/node_modules/
+
+# misc
+/coverage/
+!.*
+.eslintcache
+
+# ember-try
+/.node_modules.ember-try/
+/bower.json.ember-try
+/package.json.ember-try
diff --git a/blueprints/app/files/.prettierrc.js b/blueprints/app/files/.prettierrc.js
new file mode 100644
index 000000000..534e6d35a
--- /dev/null
+++ b/blueprints/app/files/.prettierrc.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = {
+  singleQuote: true,
+};
diff --git a/blueprints/app/files/.template-lintrc.js b/blueprints/app/files/.template-lintrc.js
index f38737001..3b0b9af95 100644
--- a/blueprints/app/files/.template-lintrc.js
+++ b/blueprints/app/files/.template-lintrc.js
@@ -1,5 +1,5 @@
 'use strict';
 
 module.exports = {
-  extends: 'octane'
+  extends: 'octane',
 };
diff --git a/blueprints/app/files/app/router.js b/blueprints/app/files/app/router.js
index 8ab5dca38..9d2bbff52 100644
--- a/blueprints/app/files/app/router.js
+++ b/blueprints/app/files/app/router.js
@@ -6,5 +6,4 @@ export default class Router extends EmberRouter {
   rootURL = config.rootURL;
 }
 
-Router.map(function() {
-});
+Router.map(function () {});
diff --git a/blueprints/app/files/config/environment.js b/blueprints/app/files/config/environment.js
index 19ed23445..25cbe0b0f 100644
--- a/blueprints/app/files/config/environment.js
+++ b/blueprints/app/files/config/environment.js
@@ -1,6 +1,6 @@
 'use strict';
 
-module.exports = function(environment) {
+module.exports = function (environment) {
   let ENV = {
     modulePrefix: '<%= modulePrefix %>',
     environment,
@@ -13,14 +13,14 @@ module.exports = function(environment) {
       },
       EXTEND_PROTOTYPES: {
         // Prevent Ember Data from overriding Date.parse.
-        Date: false
-      }
+        Date: false,
+      },
     },
 
     APP: {
       // Here you can pass flags/options to your application instance
       // when it is created
-    }
+    },
   };
 
   if (environment === 'development') {
diff --git a/blueprints/app/files/config/targets.js b/blueprints/app/files/config/targets.js
index 228a07898..4b33327e8 100644
--- a/blueprints/app/files/config/targets.js
+++ b/blueprints/app/files/config/targets.js
@@ -3,7 +3,7 @@
 const browsers = [
   'last 1 Chrome versions',
   'last 1 Firefox versions',
-  'last 1 Safari versions'
+  'last 1 Safari versions',
 ];
 
 const isCI = Boolean(process.env.CI);
@@ -14,5 +14,5 @@ if (isCI || isProduction) {
 }
 
 module.exports = {
-  browsers
+  browsers,
 };
diff --git a/blueprints/app/files/ember-cli-build.js b/blueprints/app/files/ember-cli-build.js
index 64cae47d2..e12881816 100644
--- a/blueprints/app/files/ember-cli-build.js
+++ b/blueprints/app/files/ember-cli-build.js
@@ -2,7 +2,7 @@
 
 const EmberApp = require('ember-cli/lib/broccoli/ember-app');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
   let app = new EmberApp(defaults, {
     // Add options here
   });
diff --git a/blueprints/app/files/package.json b/blueprints/app/files/package.json
index 8c9a82fb8..1a4d58609 100644
--- a/blueprints/app/files/package.json
+++ b/blueprints/app/files/package.json
@@ -12,9 +12,12 @@
   },
   "scripts": {
     "build": "ember build --environment=production",
-    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+    "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
     "lint:hbs": "ember-template-lint .",
-    "lint:js": "eslint .",
+    "lint:hbs:fix": "ember-template-lint . --fix",
+    "lint:js": "eslint . --cache",
+    "lint:js:fix": "eslint . --fix",
     "start": "ember serve",
     "test": "npm-run-all lint:* test:*",
     "test:ember": "ember test"
@@ -50,10 +53,13 @@
     "ember-template-lint": "^2.14.0<% if (welcome) { %>",
     "ember-welcome-page": "^4.0.0<% } %>",
     "eslint": "^7.11.0",
+    "eslint-config-prettier": "^6.15.0",
     "eslint-plugin-ember": "^10.0.1",
     "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "loader.js": "^4.7.0",
     "npm-run-all": "^4.1.5",
+    "prettier": "^2.2.1",
     "qunit": "^2.11.0",
     "qunit-dom": "^1.6.0-beta.1"
   },
diff --git a/docs/brocfile-transition.md b/docs/brocfile-transition.md
index dd4863acb..c542f23c8 100644
--- a/docs/brocfile-transition.md
+++ b/docs/brocfile-transition.md
@@ -33,7 +33,7 @@ module.exports = app.toTree();
 ```
 var EmberApp = require('ember-cli/lib/broccoli/ember-app');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
     var app = new EmberApp(defaults, {
         // Any other options
     });
diff --git a/lib/models/blueprint.js b/lib/models/blueprint.js
index 8c3c8d896..0736c9753 100644
--- a/lib/models/blueprint.js
+++ b/lib/models/blueprint.js
@@ -1161,13 +1161,13 @@ let Blueprint = CoreObject.extend({
     Example:
     ```
     // app/router.js
-    Router.map(function() {
+    Router.map(function () {
     });
     ```
 
     ```
     insertIntoFile('app/router.js', '  this.route("admin");', {
-      after: 'Router.map(function() {' + EOL
+      after: 'Router.map(function () {' + EOL
     }).then(function() {
       // file has been inserted into!
     });
@@ -1177,7 +1177,7 @@ let Blueprint = CoreObject.extend({
 
     ```
     // app/router.js
-    Router.map(function() {
+    Router.map(function () {
       this.route("admin");
     });
     ```
diff --git a/lib/utilities/insert-into-file.js b/lib/utilities/insert-into-file.js
index 27d280f08..dff87ddd1 100644
--- a/lib/utilities/insert-into-file.js
+++ b/lib/utilities/insert-into-file.js
@@ -24,19 +24,19 @@ const EOL = require('os').EOL;
 
   ```
   // app/router.js
-  Router.map(function() {
+  Router.map(function () {
   });
   ```
 
   ```
   insertIntoFile('app/router.js', '  this.route("admin");', {
-    after: 'Router.map(function() {' + EOL
+    after: 'Router.map(function () {' + EOL
   });
   ```
 
   ```
   // app/router.js
-  Router.map(function() {
+  Router.map(function () {
     this.route("admin");
   });
   ```


Test patch:
diff --git a/blueprints/app/files/testem.js b/blueprints/app/files/testem.js
index 49f53feed..ed2f37124 100644
--- a/blueprints/app/files/testem.js
+++ b/blueprints/app/files/testem.js
@@ -3,12 +3,8 @@
 module.exports = {
   test_page: 'tests/index.html?hidepassed',
   disable_watching: true,
-  launch_in_ci: [
-    'Chrome'
-  ],
-  launch_in_dev: [
-    'Chrome'
-  ],
+  launch_in_ci: ['Chrome'],
+  launch_in_dev: ['Chrome'],
   browser_start_timeout: 120,
   browser_args: {
     Chrome: {
@@ -20,8 +16,8 @@ module.exports = {
         '--disable-software-rasterizer',
         '--mute-audio',
         '--remote-debugging-port=0',
-        '--window-size=1440,900'
-      ].filter(Boolean)
-    }
-  }
+        '--window-size=1440,900',
+      ].filter(Boolean),
+    },
+  },
 };
diff --git a/tests/fixtures/addon/.eslintrc.js b/tests/fixtures/addon/.eslintrc.js
index 928585995..2504063f6 100644
--- a/tests/fixtures/addon/.eslintrc.js
+++ b/tests/fixtures/addon/.eslintrc.js
@@ -7,18 +7,17 @@ module.exports = {
     ecmaVersion: 2018,
     sourceType: 'module',
     ecmaFeatures: {
-      legacyDecorators: true
-    }
+      legacyDecorators: true,
+    },
   },
-  plugins: [
-    'ember'
-  ],
+  plugins: ['ember'],
   extends: [
     'eslint:recommended',
-    'plugin:ember/recommended'
+    'plugin:ember/recommended',
+    'plugin:prettier/recommended',
   ],
   env: {
-    browser: true
+    browser: true,
   },
   rules: {},
   overrides: [
@@ -26,29 +25,30 @@ module.exports = {
     {
       files: [
         '.eslintrc.js',
+        '.prettierrc.js',
         '.template-lintrc.js',
         'ember-cli-build.js',
         'index.js',
         'testem.js',
         'blueprints/*/index.js',
         'config/**/*.js',
-        'tests/dummy/config/**/*.js'
+        'tests/dummy/config/**/*.js',
       ],
       excludedFiles: [
         'addon/**',
         'addon-test-support/**',
         'app/**',
-        'tests/dummy/app/**'
+        'tests/dummy/app/**',
       ],
       parserOptions: {
-        sourceType: 'script'
+        sourceType: 'script',
       },
       env: {
         browser: false,
-        node: true
+        node: true,
       },
       plugins: ['node'],
-      extends: ['plugin:node/recommended']
-    }
-  ]
+      extends: ['plugin:node/recommended'],
+    },
+  ],
 };
diff --git a/tests/fixtures/addon/defaults/config/ember-try.js b/tests/fixtures/addon/defaults/config/ember-try.js
index a68252d8c..e59f91b33 100644
--- a/tests/fixtures/addon/defaults/config/ember-try.js
+++ b/tests/fixtures/addon/defaults/config/ember-try.js
@@ -2,61 +2,61 @@
 
 const getChannelURL = require('ember-source-channel-url');
 
-module.exports = async function() {
+module.exports = async function () {
   return {
     scenarios: [
       {
         name: 'ember-lts-3.16',
         npm: {
           devDependencies: {
-            'ember-source': '~3.16.0'
-          }
-        }
+            'ember-source': '~3.16.0',
+          },
+        },
       },
       {
         name: 'ember-lts-3.20',
         npm: {
           devDependencies: {
-            'ember-source': '~3.20.5'
-          }
-        }
+            'ember-source': '~3.20.5',
+          },
+        },
       },
       {
         name: 'ember-release',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('release')
-          }
-        }
+            'ember-source': await getChannelURL('release'),
+          },
+        },
       },
       {
         name: 'ember-beta',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('beta')
-          }
-        }
+            'ember-source': await getChannelURL('beta'),
+          },
+        },
       },
       {
         name: 'ember-canary',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('canary')
-          }
-        }
+            'ember-source': await getChannelURL('canary'),
+          },
+        },
       },
       {
         name: 'ember-default-with-jquery',
         env: {
           EMBER_OPTIONAL_FEATURES: JSON.stringify({
-            'jquery-integration': true
-          })
+            'jquery-integration': true,
+          }),
         },
         npm: {
           devDependencies: {
-            '@ember/jquery': '^1.1.0'
-          }
-        }
+            '@ember/jquery': '^1.1.0',
+          },
+        },
       },
       {
         name: 'ember-classic',
@@ -64,15 +64,15 @@ module.exports = async function() {
           EMBER_OPTIONAL_FEATURES: JSON.stringify({
             'application-template-wrapper': true,
             'default-async-observers': false,
-            'template-only-glimmer-components': false
-          })
+            'template-only-glimmer-components': false,
+          }),
         },
         npm: {
           ember: {
-            edition: 'classic'
-          }
-        }
-      }
-    ]
+            edition: 'classic',
+          },
+        },
+      },
+    ],
   };
 };
diff --git a/tests/fixtures/addon/defaults/package.json b/tests/fixtures/addon/defaults/package.json
index 73bb63d53..427ac66ff 100644
--- a/tests/fixtures/addon/defaults/package.json
+++ b/tests/fixtures/addon/defaults/package.json
@@ -14,9 +14,12 @@
   },
   "scripts": {
     "build": "ember build --environment=production",
-    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+    "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
     "lint:hbs": "ember-template-lint .",
-    "lint:js": "eslint .",
+    "lint:hbs:fix": "ember-template-lint . --fix",
+    "lint:js": "eslint . --cache",
+    "lint:js:fix": "eslint . --fix",
     "start": "ember serve",
     "test": "npm-run-all lint:* test:*",
     "test:ember": "ember test",
@@ -51,10 +54,13 @@
     "ember-template-lint": "^2.14.0",
     "ember-try": "^1.4.0",
     "eslint": "^7.11.0",
+    "eslint-config-prettier": "^6.15.0",
     "eslint-plugin-ember": "^10.0.1",
     "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "loader.js": "^4.7.0",
     "npm-run-all": "^4.1.5",
+    "prettier": "^2.2.1",
     "qunit": "^2.11.0",
     "qunit-dom": "^1.6.0-beta.1"
   },
diff --git a/tests/fixtures/addon/yarn/config/ember-try.js b/tests/fixtures/addon/yarn/config/ember-try.js
index 779a4f9a2..f14ac7f50 100644
--- a/tests/fixtures/addon/yarn/config/ember-try.js
+++ b/tests/fixtures/addon/yarn/config/ember-try.js
@@ -2,7 +2,7 @@
 
 const getChannelURL = require('ember-source-channel-url');
 
-module.exports = async function() {
+module.exports = async function () {
   return {
     useYarn: true,
     scenarios: [
@@ -10,54 +10,54 @@ module.exports = async function() {
         name: 'ember-lts-3.16',
         npm: {
           devDependencies: {
-            'ember-source': '~3.16.0'
-          }
-        }
+            'ember-source': '~3.16.0',
+          },
+        },
       },
       {
         name: 'ember-lts-3.20',
         npm: {
           devDependencies: {
-            'ember-source': '~3.20.5'
-          }
-        }
+            'ember-source': '~3.20.5',
+          },
+        },
       },
       {
         name: 'ember-release',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('release')
-          }
-        }
+            'ember-source': await getChannelURL('release'),
+          },
+        },
       },
       {
         name: 'ember-beta',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('beta')
-          }
-        }
+            'ember-source': await getChannelURL('beta'),
+          },
+        },
       },
       {
         name: 'ember-canary',
         npm: {
           devDependencies: {
-            'ember-source': await getChannelURL('canary')
-          }
-        }
+            'ember-source': await getChannelURL('canary'),
+          },
+        },
       },
       {
         name: 'ember-default-with-jquery',
         env: {
           EMBER_OPTIONAL_FEATURES: JSON.stringify({
-            'jquery-integration': true
-          })
+            'jquery-integration': true,
+          }),
         },
         npm: {
           devDependencies: {
-            '@ember/jquery': '^1.1.0'
-          }
-        }
+            '@ember/jquery': '^1.1.0',
+          },
+        },
       },
       {
         name: 'ember-classic',
@@ -65,15 +65,15 @@ module.exports = async function() {
           EMBER_OPTIONAL_FEATURES: JSON.stringify({
             'application-template-wrapper': true,
             'default-async-observers': false,
-            'template-only-glimmer-components': false
-          })
+            'template-only-glimmer-components': false,
+          }),
         },
         npm: {
           ember: {
-            edition: 'classic'
-          }
-        }
-      }
-    ]
+            edition: 'classic',
+          },
+        },
+      },
+    ],
   };
 };
diff --git a/tests/fixtures/addon/yarn/package.json b/tests/fixtures/addon/yarn/package.json
index 206ccf935..dd9c9ae09 100644
--- a/tests/fixtures/addon/yarn/package.json
+++ b/tests/fixtures/addon/yarn/package.json
@@ -14,9 +14,12 @@
   },
   "scripts": {
     "build": "ember build --environment=production",
-    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+    "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
     "lint:hbs": "ember-template-lint .",
-    "lint:js": "eslint .",
+    "lint:hbs:fix": "ember-template-lint . --fix",
+    "lint:js": "eslint . --cache",
+    "lint:js:fix": "eslint . --fix",
     "start": "ember serve",
     "test": "npm-run-all lint:* test:*",
     "test:ember": "ember test",
@@ -52,10 +55,13 @@
     "ember-try": "^1.4.0",
     "ember-welcome-page": "^4.0.0",
     "eslint": "^7.11.0",
+    "eslint-config-prettier": "^6.15.0",
     "eslint-plugin-ember": "^10.0.1",
     "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "loader.js": "^4.7.0",
     "npm-run-all": "^4.1.5",
+    "prettier": "^2.2.1",
     "qunit": "^2.11.0",
     "qunit-dom": "^1.6.0-beta.1"
   },
diff --git a/tests/fixtures/app/.eslintrc.js b/tests/fixtures/app/.eslintrc.js
index 26d707835..da079e309 100644
--- a/tests/fixtures/app/.eslintrc.js
+++ b/tests/fixtures/app/.eslintrc.js
@@ -7,18 +7,17 @@ module.exports = {
     ecmaVersion: 2018,
     sourceType: 'module',
     ecmaFeatures: {
-      legacyDecorators: true
-    }
+      legacyDecorators: true,
+    },
   },
-  plugins: [
-    'ember'
-  ],
+  plugins: ['ember'],
   extends: [
     'eslint:recommended',
-    'plugin:ember/recommended'
+    'plugin:ember/recommended',
+    'plugin:prettier/recommended',
   ],
   env: {
-    browser: true
+    browser: true,
   },
   rules: {},
   overrides: [
@@ -26,28 +25,29 @@ module.exports = {
     {
       files: [
         '.eslintrc.js',
+        '.prettierrc.js',
         '.template-lintrc.js',
         'ember-cli-build.js',
         'testem.js',
         'blueprints/*/index.js',
         'config/**/*.js',
         'lib/*/index.js',
-        'server/**/*.js'
+        'server/**/*.js',
       ],
       parserOptions: {
-        sourceType: 'script'
+        sourceType: 'script',
       },
       env: {
         browser: false,
-        node: true
+        node: true,
       },
       plugins: ['node'],
       extends: ['plugin:node/recommended'],
       rules: {
         // this can be removed once the following is fixed
         // https://github.com/mysticatea/eslint-plugin-node/issues/77
-        'node/no-unpublished-require': 'off'
-      }
-    }
-  ]
+        'node/no-unpublished-require': 'off',
+      },
+    },
+  ],
 };
diff --git a/tests/fixtures/app/defaults/ember-cli-build.js b/tests/fixtures/app/defaults/ember-cli-build.js
index d690a2531..48e94e9e4 100644
--- a/tests/fixtures/app/defaults/ember-cli-build.js
+++ b/tests/fixtures/app/defaults/ember-cli-build.js
@@ -2,7 +2,7 @@
 
 const EmberApp = require('ember-cli/lib/broccoli/ember-app');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
   let app = new EmberApp(defaults, {
     // Add options here
   });
diff --git a/tests/fixtures/app/defaults/package.json b/tests/fixtures/app/defaults/package.json
index f4f5ba210..efb74c42c 100644
--- a/tests/fixtures/app/defaults/package.json
+++ b/tests/fixtures/app/defaults/package.json
@@ -12,9 +12,12 @@
   },
   "scripts": {
     "build": "ember build --environment=production",
-    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+    "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
     "lint:hbs": "ember-template-lint .",
-    "lint:js": "eslint .",
+    "lint:hbs:fix": "ember-template-lint . --fix",
+    "lint:js": "eslint . --cache",
+    "lint:js:fix": "eslint . --fix",
     "start": "ember serve",
     "test": "npm-run-all lint:* test:*",
     "test:ember": "ember test"
@@ -47,10 +50,13 @@
     "ember-template-lint": "^2.14.0",
     "ember-welcome-page": "^4.0.0",
     "eslint": "^7.11.0",
+    "eslint-config-prettier": "^6.15.0",
     "eslint-plugin-ember": "^10.0.1",
     "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "loader.js": "^4.7.0",
     "npm-run-all": "^4.1.5",
+    "prettier": "^2.2.1",
     "qunit": "^2.11.0",
     "qunit-dom": "^1.6.0-beta.1"
   },
diff --git a/tests/fixtures/app/embroider-no-welcome/package.json b/tests/fixtures/app/embroider-no-welcome/package.json
index d242f0029..9d5fb8ae3 100644
--- a/tests/fixtures/app/embroider-no-welcome/package.json
+++ b/tests/fixtures/app/embroider-no-welcome/package.json
@@ -12,9 +12,12 @@
   },
   "scripts": {
     "build": "ember build --environment=production",
-    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+    "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
     "lint:hbs": "ember-template-lint .",
-    "lint:js": "eslint .",
+    "lint:hbs:fix": "ember-template-lint . --fix",
+    "lint:js": "eslint . --cache",
+    "lint:js:fix": "eslint . --fix",
     "start": "ember serve",
     "test": "npm-run-all lint:* test:*",
     "test:ember": "ember test"
@@ -49,10 +52,13 @@
     "ember-source": "~3.23.0-beta.1",
     "ember-template-lint": "^2.14.0",
     "eslint": "^7.11.0",
+    "eslint-config-prettier": "^6.15.0",
     "eslint-plugin-ember": "^10.0.1",
     "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "loader.js": "^4.7.0",
     "npm-run-all": "^4.1.5",
+    "prettier": "^2.2.1",
     "qunit": "^2.11.0",
     "qunit-dom": "^1.6.0-beta.1"
   },
diff --git a/tests/fixtures/app/embroider/ember-cli-build.js b/tests/fixtures/app/embroider/ember-cli-build.js
index 8433a1242..35d9cc416 100644
--- a/tests/fixtures/app/embroider/ember-cli-build.js
+++ b/tests/fixtures/app/embroider/ember-cli-build.js
@@ -2,7 +2,7 @@
 
 const EmberApp = require('ember-cli/lib/broccoli/ember-app');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
   let app = new EmberApp(defaults, {
     // Add options here
   });
diff --git a/tests/fixtures/app/embroider/package.json b/tests/fixtures/app/embroider/package.json
index 9e3d71f20..ff4c2e436 100644
--- a/tests/fixtures/app/embroider/package.json
+++ b/tests/fixtures/app/embroider/package.json
@@ -12,9 +12,12 @@
   },
   "scripts": {
     "build": "ember build --environment=production",
-    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+    "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
     "lint:hbs": "ember-template-lint .",
-    "lint:js": "eslint .",
+    "lint:hbs:fix": "ember-template-lint . --fix",
+    "lint:js": "eslint . --cache",
+    "lint:js:fix": "eslint . --fix",
     "start": "ember serve",
     "test": "npm-run-all lint:* test:*",
     "test:ember": "ember test"
@@ -50,10 +53,13 @@
     "ember-template-lint": "^2.14.0",
     "ember-welcome-page": "^4.0.0",
     "eslint": "^7.11.0",
+    "eslint-config-prettier": "^6.15.0",
     "eslint-plugin-ember": "^10.0.1",
     "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "loader.js": "^4.7.0",
     "npm-run-all": "^4.1.5",
+    "prettier": "^2.2.1",
     "qunit": "^2.11.0",
     "qunit-dom": "^1.6.0-beta.1"
   },
diff --git a/tests/fixtures/app/npm/package.json b/tests/fixtures/app/npm/package.json
index 32ca58ebe..76fe17a15 100644
--- a/tests/fixtures/app/npm/package.json
+++ b/tests/fixtures/app/npm/package.json
@@ -12,9 +12,12 @@
   },
   "scripts": {
     "build": "ember build --environment=production",
-    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+    "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
     "lint:hbs": "ember-template-lint .",
-    "lint:js": "eslint .",
+    "lint:hbs:fix": "ember-template-lint . --fix",
+    "lint:js": "eslint . --cache",
+    "lint:js:fix": "eslint . --fix",
     "start": "ember serve",
     "test": "npm-run-all lint:* test:*",
     "test:ember": "ember test"
@@ -46,10 +49,13 @@
     "ember-source": "~3.23.0-beta.1",
     "ember-template-lint": "^2.14.0",
     "eslint": "^7.11.0",
+    "eslint-config-prettier": "^6.15.0",
     "eslint-plugin-ember": "^10.0.1",
     "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "loader.js": "^4.7.0",
     "npm-run-all": "^4.1.5",
+    "prettier": "^2.2.1",
     "qunit": "^2.11.0",
     "qunit-dom": "^1.6.0-beta.1"
   },
diff --git a/tests/fixtures/app/yarn/package.json b/tests/fixtures/app/yarn/package.json
index f4f5ba210..efb74c42c 100644
--- a/tests/fixtures/app/yarn/package.json
+++ b/tests/fixtures/app/yarn/package.json
@@ -12,9 +12,12 @@
   },
   "scripts": {
     "build": "ember build --environment=production",
-    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+    "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+    "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
     "lint:hbs": "ember-template-lint .",
-    "lint:js": "eslint .",
+    "lint:hbs:fix": "ember-template-lint . --fix",
+    "lint:js": "eslint . --cache",
+    "lint:js:fix": "eslint . --fix",
     "start": "ember serve",
     "test": "npm-run-all lint:* test:*",
     "test:ember": "ember test"
@@ -47,10 +50,13 @@
     "ember-template-lint": "^2.14.0",
     "ember-welcome-page": "^4.0.0",
     "eslint": "^7.11.0",
+    "eslint-config-prettier": "^6.15.0",
     "eslint-plugin-ember": "^10.0.1",
     "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "loader.js": "^4.7.0",
     "npm-run-all": "^4.1.5",
+    "prettier": "^2.2.1",
     "qunit": "^2.11.0",
     "qunit-dom": "^1.6.0-beta.1"
   },
diff --git a/tests/fixtures/brocfile-tests/auto-run-false/ember-cli-build.js b/tests/fixtures/brocfile-tests/auto-run-false/ember-cli-build.js
index 9826d0a55..29d08305c 100644
--- a/tests/fixtures/brocfile-tests/auto-run-false/ember-cli-build.js
+++ b/tests/fixtures/brocfile-tests/auto-run-false/ember-cli-build.js
@@ -1,6 +1,6 @@
 const EmberApp = require('ember-cli/lib/broccoli/ember-app');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
   var app = new EmberApp(defaults, {
     autoRun: false
   });
diff --git a/tests/fixtures/brocfile-tests/auto-run-true/ember-cli-build.js b/tests/fixtures/brocfile-tests/auto-run-true/ember-cli-build.js
index 6a34d1ab7..6f4025190 100644
--- a/tests/fixtures/brocfile-tests/auto-run-true/ember-cli-build.js
+++ b/tests/fixtures/brocfile-tests/auto-run-true/ember-cli-build.js
@@ -1,6 +1,6 @@
 const EmberApp = require('ember-cli/lib/broccoli/ember-app');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
   var app = new EmberApp(defaults, {
     autoRun: true
   });
diff --git a/tests/fixtures/brocfile-tests/custom-environment-config/ember-cli-build.js b/tests/fixtures/brocfile-tests/custom-environment-config/ember-cli-build.js
index 85f5e3064..bfc9e28ad 100644
--- a/tests/fixtures/brocfile-tests/custom-environment-config/ember-cli-build.js
+++ b/tests/fixtures/brocfile-tests/custom-environment-config/ember-cli-build.js
@@ -1,6 +1,6 @@
 const EmberApp = require('ember-cli/lib/broccoli/ember-app');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
   var app = new EmberApp(defaults, {
     configPath: 'config/something-else'
   });
diff --git a/tests/fixtures/brocfile-tests/jshint-addon/lib/ember-random-thing/index.js b/tests/fixtures/brocfile-tests/jshint-addon/lib/ember-random-thing/index.js
index e54cf2e76..bd29a4e19 100644
--- a/tests/fixtures/brocfile-tests/jshint-addon/lib/ember-random-thing/index.js
+++ b/tests/fixtures/brocfile-tests/jshint-addon/lib/ember-random-thing/index.js
@@ -1,5 +1,5 @@
 'use strict';
 
 module.exports = {
-  name: require('./package').name
+  name: require('./package').name,
 }
diff --git a/tests/fixtures/brocfile-tests/multiple-sass-files/ember-cli-build.js b/tests/fixtures/brocfile-tests/multiple-sass-files/ember-cli-build.js
index b49e14016..96618a02d 100644
--- a/tests/fixtures/brocfile-tests/multiple-sass-files/ember-cli-build.js
+++ b/tests/fixtures/brocfile-tests/multiple-sass-files/ember-cli-build.js
@@ -1,6 +1,6 @@
 const EmberApp = require('ember-cli/lib/broccoli/ember-app');
 
-module.exports = function(defaults) {
+module.exports = function (defaults) {
   var app = new EmberApp(defaults, {
     name: require('./package.json').name,
     outputPaths: { app: { css: { 'main': '/assets/main.css', 'theme/a': '/assets/theme/a.css' } } }
diff --git a/tests/fixtures/missing-before-addon/lib/sample-addon/index.js b/tests/fixtures/missing-before-addon/lib/sample-addon/index.js
index 149ef39fa..3a77c77d6 100644
--- a/tests/fixtures/missing-before-addon/lib/sample-addon/index.js
+++ b/tests/fixtures/missing-before-addon/lib/sample-addon/index.js
@@ -1,3 +1,3 @@
 module.exports = {
-  name: require('./package').name
+  name: require('./package').name,
 };
diff --git a/tests/fixtures/smoke-tests/js-testem-config/testem.js b/tests/fixtures/smoke-tests/js-testem-config/testem.js
index a2f44c434..e60c6e041 100644
--- a/tests/fixtures/smoke-tests/js-testem-config/testem.js
+++ b/tests/fixtures/smoke-tests/js-testem-config/testem.js
@@ -4,12 +4,8 @@ module.exports = {
   "framework": "qunit",
   "test_page": "tests/index.html?hidepassed",
   "disable_watching": true,
-  "launch_in_ci": [
-    "Chrome"
-  ],
-  "launch_in_dev": [
-    "Chrome"
-  ],
+  "launch_in_ci": ["Chrome"],
+  "launch_in_dev": ["Chrome"],
   "browser_args": {
     "Chrome": [
       // --no-sandbox is needed when running Chrome inside a container
@@ -17,7 +13,7 @@ module.exports = {
 
       "--headless",
       "--remote-debugging-port=0",
-      "--window-size=1440,900"
+      "--window-size=1440,900",
     ].filter(Boolean),
-  }
+  },
 };