Skip to content

Commit

Permalink
feat(rules): added rule for prefer-to-have-class (#118)
Browse files Browse the repository at this point in the history
* feat(rules): added rule prefer-to-have-class

* more tests

* fixed typeo

* covg

* Apply suggestions from code review

Co-authored-by: Anton Niklasson <[email protected]>

* classList

Co-authored-by: Anton Niklasson <[email protected]>
  • Loading branch information
benmonro and AntonNiklasson authored Dec 3, 2020
1 parent 043e7bf commit 00b65fa
Show file tree
Hide file tree
Showing 5 changed files with 430 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ module.exports = {
| [prefer-in-document](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-in-document.md) | 👍 | 🔧 | Prefer .toBeInTheDocument() for asserting the existence of a DOM node |
| [prefer-required](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-required.md) | 👍 | 🔧 | prefer toBeRequired over checking properties |
| [prefer-to-have-attribute](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-attribute.md) | 👍 | 🔧 | prefer toHaveAttribute over checking getAttribute/hasAttribute |
| [prefer-to-have-class](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-class.md) | 👍 | 🔧 | prefer toHaveClass over checking element className |
| [prefer-to-have-style](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-style.md) | 👍 | 🔧 | prefer toHaveStyle over checking element style |
| [prefer-to-have-text-content](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-text-content.md) | 👍 | 🔧 | Prefer toHaveTextContent over checking element.textContent |
| [prefer-to-have-value](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-value.md) | 👍 | 🔧 | prefer toHaveValue over checking element.value |
Expand Down
40 changes: 40 additions & 0 deletions docs/rules/prefer-to-have-class.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# prefer toHaveClass over checking element.class (prefer-to-have-class)

This rule is an autofixable rule that reports usages of checking element className or classList in expect statements in preference of using the jest-dom
`toHaveClass` matcher.

## Rule Details

Examples of **incorrect** code for this rule:

```js
expect(el.className).toBe("bar");
expect(el.className).not.toBe("bar");
expect(el.className).toHaveProperty("class", "foo");
expect(screen.getByTestId("foo").className).toBe("foo");
expect(el.className).toContain("bar");
expect(el.className).not.toContain("baz");
expect(el).toHaveAttribute("class", "qux");

expect(el.classList[0]).toBe("foo");
expect(el.classList[0]).toBe("bar");
```

Examples of **correct** code for this rule:

```js
expect(el).toHaveClass("bar");
expect(el).toHaveStyle({ foo: "bar" });
expect(el.class).toMatchSnapshot();
expect(el.class).toEqual(foo);
```

## When Not To Use It

If you don't care about using built in matchers for checking class on dom
elements.

## Further Reading

- [jest-dom toHaveStyle](https://github.com/testing-library/jest-dom#tohaveclass)
- [ElementCSSInlineStyle.class](https://developer.mozilla.org/en-US/docs/Web/API/ElementCSSInlineStyle/class)
2 changes: 1 addition & 1 deletion docs/rules/prefer-to-have-style.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# prefer toHaveProperty over checking element.style (prefer-to-have-style)
# prefer toHaveStyle over checking element.style (prefer-to-have-style)

This rule is an autofixable rule that reports usages of checking element.style in expect statements in preference of using the jest-dom
`toHaveStyle` matcher.
Expand Down
137 changes: 137 additions & 0 deletions src/__tests__/lib/rules/prefer-prefer-to-have-class.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { RuleTester } from "eslint";
import * as rule from "../../../rules/prefer-to-have-class";

const errors = [{ messageId: "use-to-have-class" }];
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
ruleTester.run("prefer-to-have-class", rule, {
valid: [
`expect(el).toHaveClass("bar")`,
`expect(el.class).toEqual(foo)`,
`expect(el).toHaveAttribute("class")`,
`expect(el).toHaveAttribute("className", "bar")`,
`expect(el).toHaveAttribute("clazz", "bar")`,
`expect(el).not.toHaveAttribute("clazz", "bar")`,
`expect(el).not.toHaveAttribute("clazz", expect.stringContaining("bar"))`,
`expect(el).toHaveAttribute("clazz", expect.stringContaining("bar"))`,
`expect(el).toHaveProperty("class", "foo")`,
`expect(el).toHaveProperty("clazz", "foo")`,
`expect(el).not.toHaveProperty("clazz", "foo")`,
`expect(el).toHaveProperty("clazz", expect.stringContaining("bar"))`,
`expect(el).not.toHaveProperty("clazz", expect.stringContaining("bar"))`,
`expect(closeButton).toHaveAttribute("class", expect.stringMatching("bar"));`,
],
invalid: [
{
code: `expect(screen.getByRole("button").className).toBe("foo")`,
errors,
output: `expect(screen.getByRole("button")).toHaveClass("foo", { exact: true })`,
},
{
code: `expect(screen.getByRole("button").className).not.toBe("foo")`,
errors,
output: `expect(screen.getByRole("button")).not.toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el).toHaveProperty("className", "foo")`,
errors,
output: `expect(el).toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el).toHaveAttribute("class", "foo")`,
errors,
output: `expect(el).toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el).toHaveAttribute(\`class\`, "foo")`,
errors,
output: `expect(el).toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el).toHaveAttribute("class", expect.stringContaining("bar"))`,
errors,
output: `expect(el).toHaveClass("bar")`,
},
{
code: `expect(el).toHaveAttribute(\`class\`, expect.stringContaining("bar"))`,
errors,
output: `expect(el).toHaveClass("bar")`,
},
{
code: `expect(el).not.toHaveProperty("className", "foo")`,
errors,
output: `expect(el).not.toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el).not.toHaveAttribute("class", "foo")`,
errors,
output: `expect(el).not.toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el.className).toContain("foo")`,
errors,
output: `expect(el).toHaveClass("foo")`,
},
{
code: `expect(el.className).not.toContain("foo")`,
errors,
output: `expect(el).not.toHaveClass("foo")`,
},
{
code: `expect(el.className).toBe("foo")`,
errors,
output: `expect(el).toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el.className).toEqual("foo")`,
errors,
output: `expect(el).toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el.className).toStrictEqual("foo")`,
errors,
output: `expect(el).toHaveClass("foo", { exact: true })`,
},
{
code: `expect(el.className).toEqual(expect.stringContaining("foo"))`,
errors,
output: `expect(el).toHaveClass("foo")`,
},
{
code: `expect(el.className).toEqual(expect.stringContaining(\`foo\`))`,
errors,
output: `expect(el).toHaveClass(\`foo\`)`,
},
{
code: `expect(el.className).toStrictEqual(expect.stringContaining("foo"))`,
errors,
output: `expect(el).toHaveClass("foo")`,
},
{
code: `expect(el.className).toEqual(expect.stringContaining("bar"))`,
errors,
output: `expect(el).toHaveClass("bar")`,
},
{
code: `expect(el.classList).toContain("bar")`,
errors,
output: `expect(el).toHaveClass("bar")`,
},
{
code: `expect(el.classList).toBe("bar")`,
errors,
},
{
code: `expect(el.classList[0]).toBe("bar")`,
errors,
output: `expect(el).toHaveClass("bar")`,
},
{
code: `expect(el.classList[0]).not.toBe("bar")`,
errors,
},
{
code: `expect(el.classList[0]).toContain(("fo"))`,
errors,
},
],
});
Loading

0 comments on commit 00b65fa

Please sign in to comment.