Skip to content

feat(prefer-in-document): add support for assigments #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 30, 2020
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ learn how: http://kcd.im/pull-request
Relevant code or config

```javascript

```

What you did:
Expand Down
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,19 @@ module.exports = {
🔧 indicates that a rule is fixable.

<!-- __BEGIN AUTOGENERATED TABLE__ -->
Name | 👍 | 🔧 | Description
----- | ----- | ----- | -----
[prefer-checked](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-checked.md) | 👍 | 🔧 | prefer toBeChecked over checking attributes
[prefer-empty](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-empty.md) | 👍 | 🔧 | Prefer toBeEmpty over checking innerHTML
[prefer-enabled-disabled](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-enabled-disabled.md) | 👍 | 🔧 | prefer toBeDisabled or toBeEnabled over checking attributes
[prefer-focus](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-focus.md) | 👍 | 🔧 | prefer toHaveFocus over checking document.activeElement
[prefer-in-document](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-in-document.md) | | 🔧 | Prefer .toBeInTheDocument() in favor of checking the length of the result using .toHaveLength(1)
[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-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

| Name | 👍 | 🔧 | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | --- | --- | ------------------------------------------------------------------------------------------------ |
| [prefer-checked](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-checked.md) | 👍 | 🔧 | prefer toBeChecked over checking attributes |
| [prefer-empty](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-empty.md) | 👍 | 🔧 | Prefer toBeEmpty over checking innerHTML |
| [prefer-enabled-disabled](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-enabled-disabled.md) | 👍 | 🔧 | prefer toBeDisabled or toBeEnabled over checking attributes |
| [prefer-focus](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-focus.md) | 👍 | 🔧 | prefer toHaveFocus over checking document.activeElement |
| [prefer-in-document](https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-in-document.md) | | 🔧 | Prefer .toBeInTheDocument() in favor of checking the length of the result using .toHaveLength(1) |
| [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-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 |

<!-- __END AUTOGENERATED TABLE__ -->

## Issues
Expand Down
25 changes: 20 additions & 5 deletions docs/rules/prefer-in-document.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,32 @@ expect(queryByText("foo")).toBeNull();
expect(queryByText("foo")).not.toBeNull();
expect(queryByText("foo")).toBeDefined();
expect(queryByText("foo")).not.toBeDefined();

const foo = screen.getByText("foo");
expect(foo).toHaveLength(1);

const bar = screen.queryByText("bar");
expect(bar).toHaveLength(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could include some async examples here now that it's properly supported?

```

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

```js
expect(screen.queryByText("foo")).toBeInTheDocument();
expect(screen.queryByText("foo")).toBeInTheDocument();
expect(queryByText("foo")).toBeInTheDocument()`;
expect(wrapper.queryAllByTestId('foo')).toBeInTheDocument()`;
expect(screen.getAllByLabel("foo-bar")).toHaveLength(2)`;
expect(notAQuery('foo-bar')).toHaveLength(1)`;
expect(await screen.findByText("foo")).toBeInTheDocument();
expect(queryByText("foo")).toBeInTheDocument();
expect(wrapper.queryAllByTestId("foo")).toBeInTheDocument();
expect(screen.getAllByLabel("foo-bar")).toHaveLength(2);
expect(notAQuery("foo-bar")).toHaveLength(1);

const foo = screen.getAllByText("foo");
expect(foo).toHaveLength(3);

const bar = screen.queryByText("bar");
expect(bar).not.toBeDefined();

const baz = await screen.findByText("baz");
expect(baz).toBeDefined()
```

## When Not To Use It
Expand Down
3 changes: 1 addition & 2 deletions other/MAINTAINING.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,4 @@ necessary by the git commit messages. With this in mind, **please brush up on

Thank you so much for helping to maintain this project!

[commit]:
https://github.com/conventional-changelog-archived-repos/conventional-changelog-angular/blob/ed32559941719a130bb0327f886d6a32a8cbc2ba/convention.md
[commit]: https://github.com/conventional-changelog-archived-repos/conventional-changelog-angular/blob/ed32559941719a130bb0327f886d6a32a8cbc2ba/convention.md
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
"rules": {
"babel/quotes": "off",
"max-lines-per-function": "off",
"testing-library/no-dom-import": "off"
"testing-library/no-dom-import": "off",
"consistent-return": "off"
}
},
"eslintIgnore": [
Expand Down
157 changes: 149 additions & 8 deletions src/__tests__/lib/rules/prefer-in-document.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
//------------------------------------------------------------------------------

import { RuleTester } from "eslint";
import { queries, queriesByVariant } from "../../../queries";
import * as rule from "../../../rules/prefer-in-document";

//------------------------------------------------------------------------------
Expand All @@ -28,17 +27,29 @@ function invalidCase(code, output) {
}

const valid = [
...queries.map((q) => [
...["getByText", "getByRole"].map((q) => [
`expect(screen.${q}('foo')).toBeInTheDocument()`,
`expect(${q}('foo')).toBeInTheDocument()`,
`expect(wrapper.${q}('foo')).toBeInTheDocument()`,
`let foo;
foo = screen.${q}('foo');
foo = somethingElse;
expect(foo).toHaveLength(1);`,
]),
`let foo;
foo = "bar";
expect(foo).toHaveLength(1);`,
`let foo;
foo = "bar";
expect(foo).toHaveLength(0);`,
`let foo;
expect(foo).toHaveLength(1);`,
`expect(screen.notAQuery('foo-bar')).toHaveLength(1)`,
`expect(screen.getByText('foo-bar')).toHaveLength(2)`,
`expect(screen.getAllByText('foo-bar')).toHaveLength(2)`,
];
const invalid = [
// Invalid cases that applies to all variants
...queries.map((q) => [
...["getByText", "getAllByRole"].map((q) => [
invalidCase(
`expect(screen.${q}('foo')).toHaveLength(1)`,
`expect(screen.${q}('foo')).toBeInTheDocument()`
Expand All @@ -51,9 +62,37 @@ const invalid = [
`expect(wrapper.${q}('foo')).toHaveLength(1)`,
`expect(wrapper.${q}('foo')).toBeInTheDocument()`
),
invalidCase(
`const foo = screen.${q}('foo');
expect(foo).toHaveLength(1);`,
`const foo = screen.${q}('foo');
expect(foo).toBeInTheDocument();`
),
invalidCase(
`const foo = ${q}('foo');
expect(foo).toHaveLength(1);`,
`const foo = ${q}('foo');
expect(foo).toBeInTheDocument();`
),
invalidCase(
`let foo;
foo = ${q}('foo');
expect(foo).toHaveLength(1);`,
`let foo;
foo = ${q}('foo');
expect(foo).toBeInTheDocument();`
),
invalidCase(
`let foo;
foo = screen.${q}('foo');
expect(foo).toHaveLength(1);`,
`let foo;
foo = screen.${q}('foo');
expect(foo).toBeInTheDocument();`
),
]),
// Invalid cases that applies to queryBy* and queryAllBy*
...queriesByVariant.query.map((q) => [
...["queryByText", "queryAllByText"].map((q) => [
invalidCase(
`expect(${q}('foo')).toHaveLength(0)`,
`expect(${q}('foo')).not.toBeInTheDocument()`
Expand All @@ -66,18 +105,120 @@ const invalid = [
`expect(${q}('foo')).not.toBeNull()`,
`expect(${q}('foo')).toBeInTheDocument()`
),
invalidCase(
`expect(${q}('foo')) .not .toBeNull()`,
`expect(${q}('foo')).toBeInTheDocument()`
),
invalidCase(
`expect(${q}('foo')).toBeDefined()`,
`expect(${q}('foo')).toBeInTheDocument()`
),
invalidCase(
`expect(${q}('foo')).not.toBeDefined()`,
`expect(${q}('foo')).not.toBeInTheDocument()`
`expect(${q}('foo')) .not .toBeDefined()`,
`expect(${q}('foo')) .not .toBeInTheDocument()`
),
invalidCase(
`let foo;
foo = screen.${q}('foo');
expect(foo).toHaveLength(0);`,
`let foo;
foo = screen.${q}('foo');
expect(foo).not.toBeInTheDocument();`
),
invalidCase(
`let foo;
foo = screen.${q}('foo');
expect(foo) .not.toBeNull();`,
`let foo;
foo = screen.${q}('foo');
expect(foo).toBeInTheDocument();`
),
invalidCase(
`let foo = screen.${q}('foo');
expect(foo).not.toBeNull();`,
`let foo = screen.${q}('foo');
expect(foo).toBeInTheDocument();`
),
]),
invalidCase(
`it("foo", async () => {
expect(await findByRole("button")).toBeDefined();
})`,
`it("foo", async () => {
expect(await findByRole("button")).toBeInTheDocument();
})`
),
invalidCase(
`it("foo", async () => {
expect(await findByRole("button")).not.toBeNull();
})`,
`it("foo", async () => {
expect(await findByRole("button")).toBeInTheDocument();
})`
),
invalidCase(
`it("foo", async () => {
expect(await screen.findByText(/Compressing video/)).toBeDefined();
})`,
`it("foo", async () => {
expect(await screen.findByText(/Compressing video/)).toBeInTheDocument();
})`
),
invalidCase(
`it("foo", async () => {
expect(await screen.findByText(/Compressing video/)).not.toBeDefined();
})`,
`it("foo", async () => {
expect(await screen.findByText(/Compressing video/)).not.toBeInTheDocument();
})`
),
invalidCase(
`it("foo", async () => {
const compressingFeedback = await screen.findByText(/Compressing video/);
expect(compressingFeedback).toBeDefined();
});`,
`it("foo", async () => {
const compressingFeedback = await screen.findByText(/Compressing video/);
expect(compressingFeedback).toBeInTheDocument();
});`
),
invalidCase(
`it("foo", async () => {
const compressingFeedback = await screen.findByText(/Compressing video/);
expect(compressingFeedback).not.toBeNull();
});`,
`it("foo", async () => {
const compressingFeedback = await screen.findByText(/Compressing video/);
expect(compressingFeedback).toBeInTheDocument();
});`
),
invalidCase(
`it("foo", async () => {
let compressingFeedback;
compressingFeedback = await screen.findByText(/Compressing video/);
expect(compressingFeedback).toBeDefined();
});`,
`it("foo", async () => {
let compressingFeedback;
compressingFeedback = await screen.findByText(/Compressing video/);
expect(compressingFeedback).toBeInTheDocument();
});`
),
invalidCase(
`it("foo", async () => {
let compressingFeedback;
compressingFeedback = await screen.findByText(/Compressing video/);
expect(compressingFeedback).not.toBeDefined();
});`,
`it("foo", async () => {
let compressingFeedback;
compressingFeedback = await screen.findByText(/Compressing video/);
expect(compressingFeedback).not.toBeInTheDocument();
});`
),
];

const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2017 } });
ruleTester.run("prefer-in-document", rule, {
valid: [].concat(...valid),
invalid: [].concat(...invalid),
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/lib/rules/prefer-to-have-style.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ ruleTester.run("prefer-to-have-style", rule, {
invalid: [
{
code: `expect(a.style).toHaveProperty('transform')`,
errors
errors,
},
{
code: `expect(el.style.foo).toBe("bar")`,
Expand Down
6 changes: 0 additions & 6 deletions src/queries.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
import { queries as allQueries } from "@testing-library/dom";

export const queries = Object.keys(allQueries);

export const queriesByVariant = {
query: queries.filter((q) => q.startsWith("query")),
get: queries.filter((q) => q.startsWith("get")),
find: queries.filter((q) => q.startsWith("find")),
};
Loading