-
-
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
Ignore indentation of data structures in jest-diff #3429
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3429 +/- ##
==========================================
+ Coverage 56.17% 56.37% +0.19%
==========================================
Files 191 191
Lines 6424 6452 +28
Branches 6 6
==========================================
+ Hits 3609 3637 +28
Misses 2812 2812
Partials 3 3
Continue to review full report at Codecov.
|
This is great, but what about testing indentation (e.g. in CLI output)? I wonder if we could add options object as an argument for snapshot matchers, something like: expect(diff).toMatchSnapshot({whitespace: true}); |
Good point, you mean that I might have caused a regression for a multiline string by itself? |
Yeah, but I'm not so sure how to deal with it properly. It's still just a diff, so snapshots wouldn't be affected (on the filesystem), but it may be weird for user to see Jest tests passing and having whitespace differences in their commit. I mean this would require to be extra careful while giving code review. |
Here are the prerequisites that I know about before we continue reviewing this PR: [x] For the question about snapshots of multiline strings especially CLI output, verify that The last two items bring up a question about an inconsistency:
|
As mentioned above, snapshot of multiline string is okay because it contains quotes. Ready for review to continue, [EDIT: s/but not yet/and maybe now/] to merge, because I need to follow up on multiline string in Compared values have no visual difference. So I need to look more carefully at the code paths to deal with string value not from snapshot. [EDIT: commit below adds test and conditional code for multiline string not from snapshot. |
To answer the question in #3429 (comment) with a question: can we make sure that (or improve fix needed so) this PR only affects the feedback about a change not the criterion for a change? Especially if we can make sure that ignoring indentation applies to output from |
Oh, something just hit me. Clunk! The algorithm becomes clearer and safer if:
|
Now ready for review. Here are two changes that affect the public interface:
|
While reading code for #3825 I realized that this change might ignore changes to leading spaces in text content of a React or HTML element. After I return from visit with family next week, I will think more about it. As was suggested elsewhere, maybe develop a diff of data structures instead? |
Rebased and reduced scope of improvement to ignore indentation:
If you think this is too much code change and potential confusion from a difference in feedback for similar tests with snapshot versus non-snapshot assertions, I can cut the PR back as follows:
|
Oh, after thinking about the code diff for #3962 and then waking up in the middle of the night to stray fireworks thinking red-white-blue, I wonder about a third color code for differences only in indentation? Maybe then it can apply to snapshots too, after all :) As follow up to this thought, I will
|
Your critique is welcome about developer experience when a test fails: to decide whether (or which part of) the diff is correct or incorrect. Each of the following 4 scenarios has 3 pictures:
First form your impression of the meaning, and then read the intended meaning below :) Data structure with decreasing indentation React elements with increasing indentation React elements with changes to edge spaces in text React elements with increasing indentation and changes to edge spaces in text The new third color cyan means the only difference in a line is:
If we decide to move forward with this or a derived proposal, I will rebase and update this PR for non-snapshot diffs, and then submit another PR for snapshot diffs. |
Oh, and do y’all have any preference:
|
Pushing these commits isn’t an expectation. I trust y’all to decide on priorities for Jest :)
|
@pedrottimark you were kind of on a monologue on this PR, and sorry for not jumping in earlier. I don't currently have time to read through the whole thing but I agree with the overall premise. What do we need to do to get this into Jest 21? :) |
I need to:
|
@cpojer Ready for review, at your convenience. Summary from “reducer function” for comments :)
Except for removing space in second column, pictures in #3429 (comment) are still relevant:
|
type DIFF_D = -1 | 1 | 0; // diff digit: removed | added | equal | ||
|
||
// Given chunk, return diff character. | ||
const getC = (chunk): string => (chunk.removed ? '-' : chunk.added ? '+' : ' '); |
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.
"getDiffCharacter"?
const getC = (chunk): string => (chunk.removed ? '-' : chunk.added ? '+' : ' '); | ||
|
||
// Given diff character by getC from chunk or line from hunk, return diff digit. | ||
const getD = (c: string): DIFF_D => (c === '-' ? -1 : c === '+' ? 1 : 0); |
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.
getDiffDigit
?
}, | ||
}, | ||
} | ||
Object { |
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.
It's suspicious that these are indented less by one space now. Why was this change made? It makes "Object" not line up with "Received" any longer.
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 space or no space confused me for a long while. We can go either way. Your choice!
Before this pull request the result changed according to CLI option:
- default
--no-expand
option uses hunk format fromdiff
with no space between the first column marker and the actual line --expand
option formatted the chunk lines fromdiff
with a space there.
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 didn't realize that it was different based on cli options, it shouldn't be! I think two spaces (make it line up with "Received") makes more sense, and it would be good to be consistent.
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 it better too. To make double sure I understand:
- The first column consists of -/+/space for removed/added/unchanged
- The second column consists of space to separate from line content and align with legend
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.
Yep! The first column may be empty space as well.
// If compared lines are equal and expected and received are data structures, | ||
// then delta is difference in length of original lines. | ||
const getColor = (d: DIFF_D, delta?: number) => | ||
d === 1 ? chalk.red : d === -1 ? chalk.green : delta ? chalk.cyan : chalk.dim; |
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 is really hard to read. Would it hurt to use one if-statement and one ternary? :D
const formatLine = ( | ||
c: string, | ||
lineCompared: string, | ||
getOriginal?: Function, |
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.
Could we type this function better?
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.
You mean more specific type than Function
for the optional argument?
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.
Yeah, like annotating the input type and return value using (number) => ReturnValue
etc.
// If compared lines are equal, | ||
// then delta is difference in length of original lines. | ||
const delta = d === 0 ? lengthOriginal - gotOriginal[0].length : 0; | ||
return getColor(d, delta)( |
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 function call is also incredibly hard to read. Any way we could factor out the inline ternaries etc.?
@@ -1,43 +1,43 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
|
|||
exports[`ReactElement plugin highlights syntax 1`] = ` | |||
"<Mouse</> | |||
"<cyan><Mouse</> |
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 is cyan added here?
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 is side effect of supporting cyan and background colors in ConvertAnsi
plugin. I can revert that change and that diff produces the correct colors in a more specific way.
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.
With all your explanation, I'm still not sure why the cyan is printed here at all. Is this just syntax highlighting for the React component itself? If yes, then this change is fine. If no, I'd like to understand better why the cyan is there now.
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.
Aha, got it. What you said. When we changed from raw ANSI codes to ConvertAnsi
plugin, we overlooked that not all colors in the default React plugin color options were supported, so there was a loss of information. The change to display cyan as the default color for markers is correct, but really an unintended side effect.
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.
Yup, makes sense to me now. Thanks for explaining.
Thanks @pedrottimark, a lot of work went into this and the result (or intermediary step) is pretty awesome. I have a few questions inline, mostly I think those snapshots shouldn't be changing at this point. What do you think? |
To make sure I don’t make a different change than you want: which snapshots did you mean shouldn’t be changing? The React components? |
@cpojer Thank you for such careful review, especially of changes to snapshots. AppVeyor build failed: I think because other packages not linked to Now snapshots from expect matchers have updates. It will be a sweeter PR than this, if
@thymikee Consistently formatting lines with space in second column as in |
Nice! Seems like this fails on AppVeyor though :( |
Yeah, the last time that a change affected snapshots in other packages, the Appveyor build healed itself eventually after some other PRs had been merged. @cpojer Until then, what do you think about a small change to this PR: By analogy with green background color on the second-column spaces added to snapshots in the diff as displayed on GitHub split view, people could misunderstand green or red background color as meaning leading or trailing spaces are changes. Furthermore, So how about a gray background color to communicate a neutral meaning: although unchanged, don’t overlook leading or trailing spaces in lines. The |
Surprise discovery: |
I merged this now, and will leave it to you to send follow-up PRs to fix behavior up. Could you send a few screenshots of different styles other than cyan? It's easier to make a decision then. |
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
To minimize incorrect decisions about diffs for tests that fail, display some lines in data structures as unchanged with the received indentation, if their only change is indentation. That is, distinguish content that remains the same from changes to the surrounding hierarchy.
Except multiline strings in data structures [EDIT: and snapshots of strings] where change in indentation seems significant.
Baseline diff is less clear:
Proposed diff is more clear:
I have doubts at times it’s worth 100 lines of code, but the diff for a hypothetical change to hierarchy of rendered elements came up in again yesterday in #2202 (comment)
Test plan