-
Notifications
You must be signed in to change notification settings - Fork 236
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: resolve expect
based on scope
#1173
Conversation
c15b40a
to
407bc9c
Compare
I toyed around with adding some helpers to the parsed jest call e.g. I might add them in the future if we get some more rules that would benefit from them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exciting stuff!
@@ -70,7 +70,7 @@ ruleTester.run('no-restricted-matchers', rule, { | |||
], | |||
}, | |||
{ | |||
code: 'expect(a).not', | |||
code: 'expect(a).not[x]()', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we keep the old test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new parser doesn't consider the old test to be a valid expect call, and we've already got expect(a).rejects
as a valid
test which covers this change 🤷
@@ -20,7 +20,6 @@ ruleTester.run('no-standalone-expect', rule, { | |||
'it("an it", () => expect(1).toBe(1))', | |||
'const func = function(){ expect(1).toBe(1); };', | |||
'const func = () => expect(1).toBe(1);', | |||
'expect.hasAssertions()', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has become an error, since it's a standalone expect
.
code: "(() => {})('testing', () => expect(true))", | ||
errors: [{ endColumn: 41, column: 29, messageId: 'unexpectedExpect' }], | ||
code: "(() => {})('testing', () => expect(true).toBe(false))", | ||
errors: [{ column: 29, messageId: 'unexpectedExpect' }], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why no endColumn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh I typically don't include it as I don't think its super valuable since we can't control how the results are used in tools & editors so it just creates more work for us without much gain, but yeah I should include it here for consistency since the other tests have it 😅
'expect.hasAssertions', | ||
'expect.hasAssertions()', | ||
'expect.assertions(1)', | ||
'expect(true).toBe(...true)', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like a syntax error to me 😅
# [26.8.0](v26.7.0...v26.8.0) (2022-08-07) ### Features * resolve `expect` based on scope ([#1173](#1173)) ([aa4be21](aa4be21))
🎉 This PR is included in version 26.8.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This switches our handling of
expect
over to match the rest of our we now resolve jest functions, meaning it correctly respects@jest/globals
& the related patterns that come with that, done throughparseJestFnCall
.This required a lot more work than the others as currently we handle
expect
calls from theexpect(...)
call itself whereas for e.g.test
we do it at the "top" call expression (test.only(...)
) - inverting this forexpect
had some interesting impacts, the biggest of which is tovalid-expect
because now the act of parsing effectively enforces a "valid"expect
statement, which now is effectively a wrapper for exposing the "reason" thatparseJestFnCall
internally now returns (which is to keepvalid-expect
usable in the first place, and is only exposed withparseJestFnCallWithReason
).Elsewhere some places have become easier (
unbound-method
&no-restricted-matchers
especially) but it's also gotten more technical, so overall I think there's no net loss or gain (which is fine).This does come with a minor performance hit since we're doing a decent amount more work - as a basic test I checked the times of running
jest/all
on all file types in thejest
monorepo, and we're looking at about an extra 10 seconds; also importantlyparseJestFnCall
has a significant enough overhead that we need to be careful about calling it multiple times unless we really have to (I was able to clearly optimize the time ofno-standalone-expect
&prefer-expect-assertions
this way).While I think the current performance hit doesn't bother me (it's still less than 45 seconds on average, and when you include other rules that gets to 60s+) but that second point does as it's something we have to watch out for - luckily it looks like we can easily fix this by just chucking in a cache, which brings the times down to 10 seconds; I'm planning to land that in another PR to keep things clean (+ we'd have a cacheless version we can baseline against).
I'm opening this as a draft because I want to do some cleanup before it's merged and there are edge-cases to think about (especially in
valid-expect
), but it should be reviewable already. I focused first on just replacingparseExpectCall
with the low level API, to avoid premature optimizing - I plan to go back through the rules and identity common usage/patterns that we can expose on the parsed call, such as accessing the arguments for expect and checking modifiers nodes.As expected this has also identified a few edge-case bugs which I might try and land ahead of time to make things a bit easier.
I'm also going to run the smoke test against this branch.