-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
ColorPalette
: refine test query
#53704
Conversation
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.
Using selector
is a good idea IMHO 👍 We don't have many other options, given the markup of the color palette color components.
I've left a few improvement suggestions, let me know what you think.
expect( screen.getByText( EXAMPLE_COLORS[ 0 ].name ) ).toBeVisible(); | ||
expect( screen.getByText( EXAMPLE_COLORS[ 0 ].color ) ).toBeVisible(); | ||
expect( | ||
screen.getByText( colorName, { selector: 'span' } ) |
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.
If you want to get a bit more specific, you can customize the selector
by attribute:
screen.getByText( colorName, { selector: 'span' } ) | |
screen.getByText( colorName, { selector: 'span[data-wp-component="Truncate"]' } ) |
or by classname:
screen.getByText( colorName, { selector: 'span' } ) | |
screen.getByText( colorName, { | |
selector: '.components-color-palette__custom-color-name', | |
} ) |
or you can combine classname with tagname:
screen.getByText( colorName, { selector: 'span' } ) | |
screen.getByText( colorName, { | |
selector: 'span.components-color-palette__custom-color-name', | |
} ) |
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.
If we use your first suggestion, then we could put it into a variable as well:
const truncateComponent = {
selector: 'span[data-wp-component="Truncate"]',
};
But this made me wonder...
I am not 100% sure if the Truncate
component will be kept in the upcoming ColorPalette
changes. But if the parent is updated from a button to options, we can use a getByRole
query, as I mentioned earlier.
This made me think about tests in general: Is it best to specify the component so it would error if it is changed (so we remember to update to a better query), or is it better to use the class since it's more likely to stay the same and therefore, pass?
I realize this is an implementation detail since it doesn't matter what we use as long as it ensures the behavior works for the user. I was just curious if you had an opinion on this. 🙂
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.
If we use your first suggestion, then we could put it into a variable as well
We could if we need it multiple times, yes 👍
I am not 100% sure if the Truncate component will be kept in the upcoming ColorPalette changes. But if the parent is updated from a button to options, we can use a getByRole query, as I mentioned earlier.
getByRole
is always preferred 👍
This made me think about tests in general: Is it best to specify the component so it would error if it is changed (so we remember to update to a better query), or is it better to use the class since it's more likely to stay the same and therefore, pass? I realize this is an implementation detail since it doesn't matter what we use as long as it ensures the behavior works for the user. I was just curious if you had an opinion on this.
It really depends. In this case, we could argue that both the classname that I'm suggesting and the span
that you are suggesting are implementation details. I guess in this case it's about what's the ideal implementation detail to include in the test. I believe the classname one is better, because there might be multiple span with the queried text and it would break the test; while it's a smaller chance to have multiple elements with the same text and the same classname.
Anyway, I wanted to offer a few alternatives that seemed a bit better than just specifying a tagname, but feel free to ignore them, especially if we can change the query to be by role.
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.
Your suggestions are definitely better than just specifying a tag name, so thank you. And this answered my question!
I believe the classname one is better, because there might be multiple span with the queried text and it would break the test; while it's a smaller chance to have multiple elements with the same text and the same classname.
expect( | ||
screen.getByText( colorName, { selector: 'span' } ) | ||
).toBeVisible(); | ||
expect( screen.getByText( colorCode ) ).toBeVisible(); |
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 could be further clarified, similar to how we did for the color name above. For example, you could do:
expect( screen.getByText( colorCode ) ).toBeVisible(); | |
expect( | |
screen.getByText( colorCode, { | |
selector: '.components-color-palette__custom-color-value', | |
} ) | |
).toBeVisible(); |
expect( | ||
screen.getByRole( 'button', { | ||
name: `Custom color picker. The currently selected color is called "${ EXAMPLE_COLORS[ 0 ].name }" and has a value of "${ EXAMPLE_COLORS[ 0 ].color }".`, | ||
name: `Custom color picker. The currently selected color is called "${ colorName }" and has a value of "${ EXAMPLE_COLORS[ 0 ].color }".`, |
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.
Maybe we could rename the color value too:
name: `Custom color picker. The currently selected color is called "${ colorName }" and has a value of "${ EXAMPLE_COLORS[ 0 ].color }".`, | |
name: `Custom color picker. The currently selected color is called "${ colorName }" and has a value of "${ colorCode }".`, |
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.
Good catch! Missed that one 😅
const colorName = EXAMPLE_COLORS[ 0 ].name; | ||
const colorCode = EXAMPLE_COLORS[ 0 ].color; |
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 be simplified by using destructuring with aliases:
const colorName = EXAMPLE_COLORS[ 0 ].name; | |
const colorCode = EXAMPLE_COLORS[ 0 ].color; | |
const { name: colorName, color: colorCode } = EXAMPLE_COLORS[ 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.
Great suggestion!
).not.toBeInTheDocument(); | ||
expect( | ||
screen.queryByText( EXAMPLE_COLORS[ 0 ].color ) | ||
screen.queryByText( colorName, { selector: 'span' } ) |
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 selector could be made further specific like we did for the color code and color name queries above, but for non-existence queries it should be fine as-is.
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 missed this earlier, but I came across it when I updated the selector to class names, so this should be set with the latest commit. 😄
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.
LGTM 👍 Thanks!
I have my own opinion about what implementation detail selector to use, but it's not a requirement or anything. As you said, ideally we can use a role query later.
Anyway, feel free to ship as-is! 🚀
@@ -222,9 +222,15 @@ describe( 'ColorPalette', () => { | |||
|
|||
it( 'should display the selected color name and value', async () => { | |||
const user = userEvent.setup(); | |||
// selector for Truncate component to make test queries more explicit | |||
const truncateComponent = { | |||
selector: 'span[data-wp-component="Truncate"]', |
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.
From the three options I suggested above, this is the least preferred one. If I had to pick, I'd pick the span.classname
or .classname
one. But leaving that to your judgment.
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 initially thought it would be good if it errored so we'd update the selector if the opportunity arose, but after reading your reply to my question on which implementation detail is best, it makes sense to change it! With both of the updates in the last commit, I think it is also cleaner and easier to read.
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.
Thanks, the changes look awesome 🙌 🚀
e46f69f
to
092d4cc
Compare
The failing unit test isn't related - seems like it's been flaky all day for some other branches too. Retriggered it, hope it becomes green this time. |
Flaky tests detected in 092d4cced8394f5f200644d9b323c39ad62c963d. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5894170920
|
092d4cc
to
2f3b2dd
Compare
Looks like it's still failing 😞 |
The remaining failing e2e test is consistently failing on |
I only have the option to enable auto-merge - is that what you mean? Or perhaps it's possible to merge now but I don't have those permissions? |
Correct, only Core team members have rights to bypass the merge protections. I'll go ahead and merge this then 👍 |
What?
Updates the query for testing the color display name in
ColorPalette
's test.Why?
This test fails due to the upcoming changes to tooltip (#48222). In the new version, tooltip can be found in the dom even while hidden. Therefore, the
getByText
query is returning multiple elements, including tooltip. If we change the query toscreen.getByRole( 'button', { name: /red/i } )
, it matches more than one button.How?
Until the changes are merged from #52255 (@andrewhayward), I could not find a better way to avoid the above issues other than to specify the
span
selector. This will fail in the aforementioned PR, but that will be a good reminder to update togetByRole( 'option' )
instead 😄 (or we can add it as a to-do item).Testing Instructions
Verify tests still pass
npm run test:unit packages/components/src/color-palette/test/index.tsx