Skip to content
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

feat(rule): prefer expect queryBy #22

Merged

Conversation

emmenko
Copy link
Contributor

@emmenko emmenko commented Oct 16, 2019

Closes #21

This a port of the implementation of the rule prefer-expect-query-by from this package.

As mentioned, we would like to eventually deprecate our own package in favor of this one, as it has more rules.

Let me know if the rule is "good enough" for now. We've already been using it in our apps and works great so far.

Copy link
Member

@Belco90 Belco90 left a comment

Choose a reason for hiding this comment

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

Looking good so far, the rule is even autofixable! I have requested few changes, let me know if you have questions or want to discuss something.

package-lock.json Show resolved Hide resolved
tests/lib/rules/prefer-expect-query-by.js Outdated Show resolved Hide resolved
tests/lib/rules/prefer-expect-query-by.js Outdated Show resolved Hide resolved
lib/index.js Show resolved Hide resolved
docs/rules/prefer-expect-query-by.md Outdated Show resolved Hide resolved
lib/rules/prefer-expect-query-by.js Show resolved Hide resolved
tests/lib/rules/prefer-expect-query-by.js Show resolved Hide resolved
errors: [{ messageId: 'expectQueryBy' }],
},
],
});
Copy link
Member

Choose a reason for hiding this comment

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

You also need to add some tests for autofixing feature, you can find some examples in tests/lib/rules/no-dom-import.js and again @thomlom can help you with it if you need something else.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah didn't know that. I added it now. Thanks

Copy link
Collaborator

Choose a reason for hiding this comment

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

Some tests are going to be needed for sure, something like that:

    {
      code: `
        const message = getByText('Hello')
        expect(message).toBeInTheDocument() 
      `,
      errors: [{ messageId: 'expectQueryBy' }],
      output: `
        const message = queryByText('Hello')
        expect(message).toBeInTheDocument()
      `,
    },

If auto-fixing is complex technically, I think we can leave it as an improvement.

Copy link
Member

Choose a reason for hiding this comment

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

@thomlom those specific tests for matched elements saved in a var are not necessary, but I found an issue with the current autofix so probably we need to leave it as an improvement.

@emmenko you are fixing the query used inside expect statement, but you also need to take care about if the query is imported or not.

Let's say I have this test:

const { getByText } = render(<Foo />);
// ...
expect(getByText('bar')).not.toBeInTheDocument();

would be replaced by

const { getByText } = render(<Foo />);
// ...
expect(queryByText('bar')).not.toBeInTheDocument();

but it's not 100% fixed as queryByText is not defined so you would have to destructure/get it from render (which could be harder than it seems as it should be get from destructured object or var declared by the user).

And another case:

const { getByText, queryByText } = render(<Foo />);
// ...
expect(getByText('bar')).not.toBeInTheDocument();

would be replaced by

const { getByText, queryByText } = render(<Foo />);
// ...
expect(queryByText('bar')).not.toBeInTheDocument();

so here queryByText is already defined and rule doesn't have to change anything related to this.

So here we have to 1) improve the fix function to take care of the new query being defined or not or 2) ignore fixing the rule for now. I'm happy with option 2 and leave the autofix for future improvement as implement the proper autofix here could take longer than expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixing rules do not need to account for other linting errors. As stated in the eslint docs

Since all rules are run again after the initial round of fixes is applied, it’s not necessary for a rule to check whether the code style of a fix will cause errors to be reported by another rule

image

So from my understanding, this is totally fine how the rule autofix is implemented regarding its concerns.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I understand what you mean, but even if it's explained in the rule info I don't want to leave this autofix with the possibility of breaking the code as it would harm the developer experience.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I totally get what you mean and I agree on the fact that fixing rules are only useful the first time.

But this plugin is new and the testing library's ecosystem is still growing. There are some best practices emerging but I think it's still not clear for newcomers to get how to make the most of Testing Library. My concern is that people will rely on this plugin to implement best practices for them automatically, possibly break their tests and have a bad experience with it.
Even if we state it in the docs, this rule will be in the recommended ones. And I'm pretty sure there will be people who will:

  1. Install the plugin (and don't care of the docs since they just want the recommended ones)
  2. Run eslint --fix
  3. See their tests break
  4. Remove the plugin
  5. Checkout the code

I prefer to have a limited experience that leaves you the manual work instead of a full experience that might cause your code to break.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So you want to remove/disable the autofix for now? It's fine by me, I just wanted to share my perspective on this topic before we decide on how to proceed.

Copy link
Member

Choose a reason for hiding this comment

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

Of course! This is not about what I want or something like that :) really happy to have your point of view here. Better to remove the fixing implementation (including the badge and the output in the tests, sorry about the last one as I asked that), and think about it in a future issue. For first rules we added to the plugin we also skipped the autofix for most of them as there are some cases we didn't know what to do or it took longer than expected to be implemented, so it's better to go bit by bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's disabled here: 0fd4a6c

I kept it commented out, so that we have a starting point in case we want to pick it up in the future.

@emmenko
Copy link
Contributor Author

emmenko commented Oct 16, 2019

Thanks for the feedback, I'll take a look at it later.

Copy link
Collaborator

@thomaslombart thomaslombart left a comment

Choose a reason for hiding this comment

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

Thanks a lot for this PR! 👍

There is still the case of assigning a getBy query that needs to be implemented but the rest LGTM.
If you need a hand to finish that, let me know!

tests/lib/rules/prefer-expect-query-by.js Show resolved Hide resolved
docs/rules/prefer-expect-query-by.md Outdated Show resolved Hide resolved
lib/rules/prefer-expect-query-by.js Show resolved Hide resolved
errors: [{ messageId: 'expectQueryBy' }],
},
],
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Some tests are going to be needed for sure, something like that:

    {
      code: `
        const message = getByText('Hello')
        expect(message).toBeInTheDocument() 
      `,
      errors: [{ messageId: 'expectQueryBy' }],
      output: `
        const message = queryByText('Hello')
        expect(message).toBeInTheDocument()
      `,
    },

If auto-fixing is complex technically, I think we can leave it as an improvement.

tests/lib/rules/prefer-expect-query-by.js Outdated Show resolved Hide resolved
errors: [{ messageId: 'expectQueryBy' }],
},
],
});
Copy link
Member

Choose a reason for hiding this comment

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

@thomlom those specific tests for matched elements saved in a var are not necessary, but I found an issue with the current autofix so probably we need to leave it as an improvement.

@emmenko you are fixing the query used inside expect statement, but you also need to take care about if the query is imported or not.

Let's say I have this test:

const { getByText } = render(<Foo />);
// ...
expect(getByText('bar')).not.toBeInTheDocument();

would be replaced by

const { getByText } = render(<Foo />);
// ...
expect(queryByText('bar')).not.toBeInTheDocument();

but it's not 100% fixed as queryByText is not defined so you would have to destructure/get it from render (which could be harder than it seems as it should be get from destructured object or var declared by the user).

And another case:

const { getByText, queryByText } = render(<Foo />);
// ...
expect(getByText('bar')).not.toBeInTheDocument();

would be replaced by

const { getByText, queryByText } = render(<Foo />);
// ...
expect(queryByText('bar')).not.toBeInTheDocument();

so here queryByText is already defined and rule doesn't have to change anything related to this.

So here we have to 1) improve the fix function to take care of the new query being defined or not or 2) ignore fixing the rule for now. I'm happy with option 2 and leave the autofix for future improvement as implement the proper autofix here could take longer than expected.

@emmenko
Copy link
Contributor Author

emmenko commented Oct 16, 2019

Alright, thanks a lot for all the feedback so far. I think this is ready for a final review.

thomaslombart
thomaslombart previously approved these changes Oct 16, 2019
Copy link
Collaborator

@thomaslombart thomaslombart left a comment

Choose a reason for hiding this comment

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

Last tiny fix, everything LGTM otherwise. Thanks again! 👍

},
schema: [],
type: 'suggestion',
fixable: 'code',
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
fixable: 'code',
fixable: null,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah thanks, I missed that

Copy link
Member

@Belco90 Belco90 left a comment

Choose a reason for hiding this comment

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

Awesome!

@Belco90 Belco90 merged commit 260f849 into testing-library:master Oct 16, 2019
@Belco90
Copy link
Member

Belco90 commented Oct 16, 2019

This PR is included in version 1.2.0 🎉

@emmenko emmenko deleted the nm-rule-prefer-expect-query-by branch October 16, 2019 14:04
@emmenko
Copy link
Contributor Author

emmenko commented Oct 16, 2019

Awesome, thanks a lot! 🚀

@Belco90
Copy link
Member

Belco90 commented Oct 18, 2019

@all-contributors please add @emmenko for code, test and docs

@allcontributors
Copy link
Contributor

@Belco90

I've put up a pull request to add @emmenko! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Avoid using throwing queries with expect: no-expect-get-by-query
3 participants