Repository: ember-cli/eslint-plugin-ember
Pull request #778 (2020-04-14 04:45:02)

Add new rule `no-test-this-render`
Ember's `this.render` method and [`@ember/test-helpers`](https://github.com/emberjs/ember-test-helpers)'s `render` method are equivalent, but using `test-helpers`' `render` method is the recommended approach.

The rule invites users to call `@ember/test-helpers`' `render` method instead of `this.render` in tests.


Patch:
diff --git a/README.md b/README.md
index 973d9654..124b26d1 100644
--- a/README.md
+++ b/README.md
@@ -186,6 +186,7 @@ Rules are grouped by category to help you understand their purpose. Each rule ha
 | :white_check_mark: | [no-test-and-then](./docs/rules/no-test-and-then.md) | disallow usage of the `andThen` test wait helper |
 | :white_check_mark: | [no-test-import-export](./docs/rules/no-test-import-export.md) | disallow importing of "-test.js" in a test file and exporting from a test file |
 | :white_check_mark: | [no-test-module-for](./docs/rules/no-test-module-for.md) | disallow usage of `moduleFor`, `moduleForComponent`, etc |
+|  | [no-test-this-render](./docs/rules/no-test-this-render.md) | disallow usage of the `this.render` in tests, recommending to use @ember/test-helpers' `render` instead. |
 
 <!--RULES_TABLE_END-->
 
diff --git a/lib/index.js b/lib/index.js
index 432ddd61..cede51e0 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -52,6 +52,7 @@ module.exports = {
     'no-test-and-then': require('./rules/no-test-and-then'),
     'no-test-import-export': require('./rules/no-test-import-export'),
     'no-test-module-for': require('./rules/no-test-module-for'),
+    'no-test-this-render': require('./rules/no-test-this-render'),
     'no-unnecessary-index-route': require('./rules/no-unnecessary-index-route'),
     'no-unnecessary-route-path-option': require('./rules/no-unnecessary-route-path-option'),
     'no-unnecessary-service-injection-argument': require('./rules/no-unnecessary-service-injection-argument'),


Test patch:
diff --git a/docs/rules/no-test-this-render.md b/docs/rules/no-test-this-render.md
new file mode 100644
index 00000000..b1e16b0d
--- /dev/null
+++ b/docs/rules/no-test-this-render.md
@@ -0,0 +1,45 @@
+# no-test-this-render
+
+Ember's `this.render`/`this.clearRender` method and [`@ember/test-helpers`](https://github.com/emberjs/ember-test-helpers)'s `render`/`clearRender` method are equivalent, but using `@ember/test-helpers`' `render`/`clearRender` method is the recommended approach.
+
+## Rule Details
+
+The rule invites users to call `@ember/test-helpers`' `render`/`clearRender` method instead of `this.render`/`this.clearRender` in tests.
+
+## Examples
+
+Examples of **incorrect** code for this rule:
+
+```js
+test('baz', function (assert) {
+  this.render();
+});
+```
+
+```js
+test('baz', function (assert) {
+  this.clearRender();
+});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+import { render } from '@ember/test-helpers';
+
+test('baz', function (assert) {
+  render();
+});
+```
+
+```js
+import { clearRender } from '@ember/test-helpers';
+
+test('baz', function (assert) {
+  clearRender();
+});
+```
+
+## References
+
+* [Rendering Helpers on `@ember/test-helpers`](https://github.com/emberjs/ember-test-helpers/blob/master/API.md#rendering-helpers).
diff --git a/lib/rules/no-test-this-render.js b/lib/rules/no-test-this-render.js
new file mode 100644
index 00000000..43d3ca06
--- /dev/null
+++ b/lib/rules/no-test-this-render.js
@@ -0,0 +1,51 @@
+'use strict';
+
+const emberUtils = require('../utils/ember');
+const types = require('../utils/types');
+
+const ERROR_MESSAGE =
+  'Do not use `this.render()` or `this.clearRender()`. Prefer `render` or `clearRender` from `@ember/test-helpers` instead.';
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description:
+        "disallow usage of the `this.render` in tests, recommending to use @ember/test-helpers' `render` instead.",
+      category: 'Testing',
+      url:
+        'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/no-test-this-render.md',
+    },
+    fixable: null,
+    schema: [],
+  },
+
+  ERROR_MESSAGE,
+
+  create(context) {
+    if (!emberUtils.isTestFile(context.getFilename())) {
+      return {};
+    }
+
+    return {
+      CallExpression(node) {
+        const { callee } = node;
+
+        if (
+          types.isThisExpression(callee.object) &&
+          types.isIdentifier(callee.property) &&
+          (callee.property.name === 'render' || callee.property.name === 'clearRender')
+        ) {
+          context.report({
+            node,
+            message: ERROR_MESSAGE,
+          });
+        }
+      },
+    };
+  },
+};
diff --git a/tests/lib/rules/no-test-this-render.js b/tests/lib/rules/no-test-this-render.js
new file mode 100644
index 00000000..48025cea
--- /dev/null
+++ b/tests/lib/rules/no-test-this-render.js
@@ -0,0 +1,74 @@
+'use strict';
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require('../../../lib/rules/no-test-this-render');
+const RuleTester = require('eslint').RuleTester;
+
+const { ERROR_MESSAGE } = rule;
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const TEST_FILE_NAME = 'some-test.js';
+
+const ruleTester = new RuleTester({
+  parserOptions: {
+    ecmaVersion: 2018,
+    sourceType: 'module',
+  },
+});
+
+ruleTester.run('no-test-this-render', rule, {
+  valid: [
+    {
+      filename: TEST_FILE_NAME,
+      code: "run(() => { console.log('Hello World.'); });",
+    },
+    {
+      filename: TEST_FILE_NAME,
+      code: 'myCustomClass.render(myFunction);',
+    },
+    {
+      filename: TEST_FILE_NAME,
+      code: 'myCustomClass.clearRender(myFunction);',
+    },
+    {
+      filename: TEST_FILE_NAME,
+      code: 'render.otherFunction(myFunction);',
+    },
+    {
+      filename: TEST_FILE_NAME,
+      code: 'clearRender.otherFunction(myFunction);',
+    },
+    {
+      filename: 'not-a-test-file.js',
+      code: 'async () => { await this.render(); }',
+    },
+    {
+      filename: TEST_FILE_NAME,
+      code: 'this.render.otherFunction()',
+    },
+    {
+      filename: 'not-a-test-file.js',
+      code: 'async () => { await this.clearRender(); }',
+    },
+  ],
+  invalid: [
+    {
+      filename: TEST_FILE_NAME,
+      code: 'async () => { await this.render(); }',
+      output: null,
+      errors: [{ message: ERROR_MESSAGE, type: 'CallExpression' }],
+    },
+    {
+      filename: TEST_FILE_NAME,
+      code: 'async () => { await this.clearRender(); }',
+      output: null,
+      errors: [{ message: ERROR_MESSAGE, type: 'CallExpression' }],
+    },
+  ],
+});