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

fix(rules): only report errors for prefer-to-have-value on valid DTL queries #122

Merged
merged 5 commits into from
Dec 6, 2020

Conversation

juzerzarif
Copy link
Contributor

@juzerzarif juzerzarif commented Dec 6, 2020

What:
prefer-to-have-values only reports an error for expect(<something>.value).toEqual('foo') pattern if <something> is the result of a valid DTL query. Only auto fix for byRole('textbox') and byRole('dropdown') queries, suggest fix for rest.

Why:
So prefer-to-have-values doesn't report an error when the value property of non DOM element objects are queried in an assertion. Auto fix update to only auto fix for recommended queries.
Fixes #117

How:
Extracted existing logic for determining whether the value being queried in the assertion is a DOM element's value from the prefer-in-document rule.

Checklist:

  • Documentation N/A
  • Tests
  • Ready to be merged

@codecov
Copy link

codecov bot commented Dec 6, 2020

Codecov Report

Merging #122 (932bfda) into master (a912e68) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master      #122   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           14        15    +1     
  Lines          337       358   +21     
  Branches        52        59    +7     
=========================================
+ Hits           337       358   +21     
Impacted Files Coverage Δ
src/rules/prefer-to-have-class.js 100.00% <ø> (ø)
src/assignment-ast.js 100.00% <100.00%> (ø)
src/rules/prefer-in-document.js 100.00% <100.00%> (ø)
src/rules/prefer-to-have-value.js 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a912e68...932bfda. Read the comment docs.

return [
fixer.removeRange([
node.callee.object.arguments[0].object.range[1],
node.callee.object.arguments[0].property.range[0] - 1,
Copy link
Member

Choose a reason for hiding this comment

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

what is the -1 for? generally hardcoded values in fixers can be problematic, unless you're inserting an arg (which i'd love to find a better way).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If the object is wrapped in parentheses (like an inline await statement expect((await screen.findByRole('textbox')).value)), removing from the end of its range to the end of the property's range also gets rid of the closing wrapping parenthesis expect((await screen.findByRole('textbox')). It does feel kinda icky to use magical numbers but I couldn't find another way to get around that than to just assume that the . preceding value will be just one over in the vast majority of cases. Definitely open to other suggestions though.

Copy link
Member

Choose a reason for hiding this comment

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

@juzerzarif, i did some digging and i think I found a winner! you can use context.getSourceCode().getTokenBefore(node) or getTokenAfter(). I discovered this by changing .value to be . value which broke both the test for this use case as well as the ones i was using in to-have-class. By switching to these functions they're now completely immune to spacing issues. :) I hope you don't mind I just pushed it to your branch along w/ some other changes just extracting some variables out for readability.


const errors = [{ messageId: "use-to-have-value" }];
ruleTester.run("prefer-empty", rule, {
Copy link
Member

Choose a reason for hiding this comment

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

wow thanks, that's what I get for copy pasta. :)

valid: [
`expect(element).toHaveValue('foo')`,
`expect(element.value).toBeGreaterThan(2);`,
`expect(element.value).toBeLessThan(2);`,

`const element = document.getElementById('asdfasf');
Copy link
Member

Choose a reason for hiding this comment

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

for now this is fine, but it would be nice to at some point support document queries as well as RTL. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, my initial idea was to create a list of all the DOM api query functions but then it occurred to me that you can also get a reference to a dom element via a lot of other keys like first/lastElementChild, children etc. so I figured probably best to leave that to be implemented as its own piece

src/utils.js Outdated
: expression.type === "AwaitExpression"
? getInnerNodeFrom(expression.argument)
: expression;
}
Copy link
Member

Choose a reason for hiding this comment

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

this seems different than from what was in prefer-in-document:

function getAssignmentFrom(expression) {
    return expression.type === "TSAsExpression"
      ? getAssignmentFrom(expression.expression)
      : expression.type === "AwaitExpression"
      ? getAssignmentFrom(expression.argument)
      : expression.callee
      ? expression.callee
      : expression;
  }

is expression.callee no longer needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to make it return a slightly broader object because I needed access to the whole CallExpression in prefer-to-have-values to get access to its arguments as well as the callee. I've tweaked its consumption in prefer-in-document to maintain passivity here e77f6b9#diff-6eab9c599f2637bd770a8d963e5c787cfd559888fe0c7b71fbab69d5d2bfff4bR160

src/utils.js Outdated
@@ -0,0 +1,46 @@
/**
Copy link
Member

Choose a reason for hiding this comment

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

i'm a bit of a stickler, but utils has always bothered me. :) Can we rename this to assignment-ast.js to denote that its purpose is for finding assignment values. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense to me, renamed here 94aad94

@benmonro
Copy link
Member

benmonro commented Dec 6, 2020

Nice work @juzerzarif, a couple minor things then I think we're good to merge.

@all-contributors please add @juzerzarif for code, tests, bugs.

@allcontributors
Copy link
Contributor

@benmonro

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

@benmonro benmonro changed the title Only report errors for prefer-to-have-value on valid DTL queries fix(rules): only report errors for prefer-to-have-value on valid DTL queries Dec 6, 2020
Copy link
Member

@benmonro benmonro left a comment

Choose a reason for hiding this comment

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

looking super! just a couple minor things to tweak before merging.

@benmonro benmonro merged commit 56afe4f into testing-library:master Dec 6, 2020
@github-actions
Copy link

github-actions bot commented Dec 6, 2020

🎉 This PR is included in version 3.6.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Successfully merging this pull request may close these issues.

prefer-to-have-value having unintended effects
2 participants