-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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: make prettier optional for inline snapshots #7792
Conversation
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need the corporate CLA signed. If you have received this in error or have any questions, please contact us at cla@fb.com. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
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.
I like this approach! However, I think for this to be tenable we need to use something that's not prettier to walk the AST (I realize you talked about this in the OP). The approach of just walking backwards and modifying makes sense to me.
You have POC
in the title - what do you think is missing? The only thing I can think of is to be able to still use prettier - otherwise I'll probably have to format my file after Jest has done it's thing. I really like that it's properly formatted automatically.
(also, please update the changelog (and docs))
Regarding the optional usage of Prettier: |
@SimenB the main reason for Since babel now supports typescript, maybe |
This is a good optimisation of the current implementation of inline snapshots, but might be missing the broader context and reason I used Prettier in the first place. The end-game for inline snapshots is to be able to automatically create assertions that look like regular tests. For example, saving this file: test('inline snapshot', () => {
const obj = {
foo: 'bar',
fn: () => {},
};
expect(obj).toMatchInlineSnapshot();
}); Would auto-generate this: test('inline snapshot', () => {
const obj = {
foo: 'bar',
fn: () => {},
};
expect(obj).toMatchInlineSnapshot({
foo: 'bar',
fn: expect.any(Function),
});
}); Using strings for the snapshots were just a way of getting the feature of the ground (MVP if you will), and creating the framework for implementing more powerful, JavaScript/ So as much as this PR improves the way the feature is currently implemented, it may be pre-maturely optimising. @cpojer do you agree? |
@azz that does sound good, but out of scope for this PR - at least I wouldn't be able to make that big a change. @SimenB @jeysal in the end I went with making prettier optional. If there's no prettier, or if the version is too low, it uses IMHO, long-term prettier should just be dropped. But I'm biased since I don't use it, hence this PR. I guess if people care enough about formatting the file after insertion, it's worth maintaining both code paths. |
My point was Prettier provides the ability to parse, manipulate and re-print the AST without doing string manipulation. This will be required when generating more complex ASTs than just a template string literal. You could do this with |
@azz I see - if anything I think that's all the more reason to put this in now, before the coupling with prettier is increased. I think you should do that with I got the impression from the original PR that using prettier was a stopgap to get the feature out: |
had to do this manually; node-gyp is not playing nicely with windows. if CI complains I'll try on a mac.
* master: chore: make requiring from outside the Jest VM easier w/ a Babel plugin (jestjs#10824)
302bf5e
to
8364ca1
Compare
So after benchmarking this on 64 test files with a noop test case each, it appears to be between 1.05x and 1.1x as fast as master due to the reduced overhead of loading prettier once per worker instead of once per test file. |
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.
I pushed one cleanup commit to reduce the diff. @jeysal PTAL and merge if you're happy with it 👍 (with a more desriptive commit message than "uglier")
🎉 |
took almost 2 years 😅 Thanks @mmkal! |
jestjs#7792 suggests that Prettier is optional, but I assumed that all I needed to do was remove `prettier` from my dependencies. That still results in Jest trying to require `prettier`, causing Jest to fail. Took awhile to learn I needed to set `prettierPath` to `null` or `''`, so I added this to the docs.
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
Inline snapshots are awesome, but they use prettier to format the test file whenever they're added or updated. This is bad for two reasons:
In projects that use prettier, both of these are fine. But in projects that use other style tools, this can mean that prettier will fight with those other tools, and their configurations need to be kept in sync.
This PR addresses (1), but not (2). I would expect it could address (2) fairly easily too - prettier is now effectively only being used as a parser-finder, which provides a consistent AST to be walked. It's very possible there are more direct ways to do that, but I'm not familiar with prettier or babel, so I've left that for now. Any tips welcome - otherwise maybe it could be done as a follow up.This PR uses prettier when an up-to-date version is found; otherwise falls back to using Babel 7 to walk the AST and locate the snapshots.
I opened an issue in prettier (prettier/prettier#5807) but the suggestion was to fix here instead. I tried using the the range API (as I think did @azz when he first implemented inline snapshots in #6380), but there were a lot of gotchas and this approach is closer to getting rid of the prettier dependency entirely.
The basic implementation is - walk the AST in the same way as before, but instead of modifying at and using prettier to output a 'fixed' version, mark each snapshot with the character offsets of where they should be inserted. Then, walk backwards through each snapshot, and slice up the source file, inserting the snapshot text. Walking backwards means the offsets aren't messed up by the insertions.
Tagging a few people who took part in #6380:
@azz @SimenB @cpojer
Closes #7744
Test plan
Added some tests to
inline_snapshots.test.js
:Command run:
npm run jest packages/jest-snapshot/src/__tests__/inline_snapshots.test.js
Output: