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

PaletteEdit: improve unit tests #57645

Merged
merged 12 commits into from
Jan 12, 2024
Merged

PaletteEdit: improve unit tests #57645

merged 12 commits into from
Jan 12, 2024

Conversation

t-hamano
Copy link
Contributor

@t-hamano t-hamano commented Jan 8, 2024

Preparation for solving #57309

What?

This PR updates the unit tests for the PaletteEdit component to cover as many scenarios as possible.

Why?

To prevent regressions and bugs and to clarify component specifications.

How?

I wrote the tests to cover as many scenarios as possible based on the current specifications.

Testing Instructions

Run npm run test:unit packages/components/src/palette-edit/test/index.tsx

@t-hamano t-hamano added the [Package] Components /packages/components label Jan 8, 2024
@t-hamano t-hamano self-assigned this Jan 8, 2024
} )
);

await waitFor( () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

onChange is debounced, so we need to use waitFor. It appears to have been debounced for performance improvements. See #40285.

Copy link
Member

Choose a reason for hiding this comment

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

To better mimic actual user behavior, it might be better to click the "Done" button rather than do a wait for the onChange.

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 don't think onChange is called because the "Done" button only clears the internal editing state. Strictly speaking, this button should probably be called "Back" or "Exit Edit Mode"...

Copy link
Member

Choose a reason for hiding this comment

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

Fair point.

Comment on lines -94 to -97
it( 'opens color selector for color palettes', () => {
render( <PaletteEdit { ...defaultProps } /> );
fireEvent.click( screen.getByLabelText( 'Color: Base' ) );
expect( screen.getByLabelText( 'Hex color' ) ).toBeInTheDocument();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test should be covered by the "can update color palette value" test.

await user.selectOptions( typeSelectElement, 'radial-gradient' );

await waitFor( () => {
expect( defaultProps.onChange ).toHaveBeenLastCalledWith( [
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Somehow I had to use toHaveBeenLastCalledWith here. Where I used toHaveBeenCalledTimes, received number of calls was 5, so maybe that has something to do with it.

Copy link
Member

Choose a reason for hiding this comment

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

This is because we're reusing the jest.fn() mock that was set on defaultProps.onChange. We would need to do a reset between tests (e.g. jest.resetAllMocks() in a afterEach()) if we wanted to do it that way. Or we usually just use a fresh mock for each test that needs one:

const onChange = jest.fn();
render( <PaletteEdit { ...defaultProps } onChange={ onChange } /> );

@t-hamano t-hamano requested a review from a team January 8, 2024 14:00
@t-hamano t-hamano added the [Type] Code Quality Issues or PRs that relate to code quality label Jan 8, 2024
@t-hamano t-hamano marked this pull request as ready for review January 8, 2024 14:03
Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

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

Thank you for adding test coverage!

packages/components/src/palette-edit/test/index.tsx Outdated Show resolved Hide resolved
packages/components/src/palette-edit/test/index.tsx Outdated Show resolved Hide resolved
packages/components/src/palette-edit/test/index.tsx Outdated Show resolved Hide resolved
packages/components/src/palette-edit/test/index.tsx Outdated Show resolved Hide resolved
} )
);

await waitFor( () => {
Copy link
Member

Choose a reason for hiding this comment

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

To better mimic actual user behavior, it might be better to click the "Done" button rather than do a wait for the onChange.

packages/components/src/palette-edit/test/index.tsx Outdated Show resolved Hide resolved
} );
} );

it( 'can not add a new palette', () => {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
it( 'can not add a new palette', () => {
it( 'can not add new colors when `canOnlyChangeValues` is enabled', () => {

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe it's important to check both aspects — either in the same test, or in two separate tests. One checks that our public APIs work as expected, the other one tests that the component works as intended for the end user.

We could technically omit the onChange check if the component is tested in controlled mode, because if onChange didn't work as expected, the component wouldn't work for the end user either.

But I still prefer to test onChange (and the number of times it's been called) because in my experience it's also a great proxy for other undetected issues.

Copy link
Member

Choose a reason for hiding this comment

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

Agreed. Not a blocker for this particular PR though.

packages/components/src/palette-edit/test/index.tsx Outdated Show resolved Hide resolved
name: 'Show details',
} )
);
await user.click( screen.getByText( 'Primary' ) );
Copy link
Member

Choose a reason for hiding this comment

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

This is a great example of our tests doubling as accessibility tests. The fact that there's no labeled button to click means that this part of the UI is not accessible. Let's fix this in a follow-up.

packages/components/src/palette-edit/test/index.tsx Outdated Show resolved Hide resolved
t-hamano and others added 10 commits January 11, 2024 11:03
Co-authored-by: Lena Morita <lena@jaguchi.com>
Co-authored-by: Lena Morita <lena@jaguchi.com>
Co-authored-by: Lena Morita <lena@jaguchi.com>
Co-authored-by: Lena Morita <lena@jaguchi.com>
Co-authored-by: Lena Morita <lena@jaguchi.com>
Co-authored-by: Lena Morita <lena@jaguchi.com>
Co-authored-by: Lena Morita <lena@jaguchi.com>
Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Not much to add on top of Lena's comment, but still wanted to thank you for the great work so far!

Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

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

🚀

@t-hamano
Copy link
Contributor Author

@ciampo @mirka Thanks for the review! As I continue to work on #57309, I would like to add unit tests as needed.

@t-hamano t-hamano merged commit d0287db into trunk Jan 12, 2024
56 checks passed
@t-hamano t-hamano deleted the quality/palette-edit-add-test branch January 12, 2024 03:19
@github-actions github-actions bot added this to the Gutenberg 17.6 milestone Jan 12, 2024
@brookewp
Copy link
Contributor

brookewp commented Jan 12, 2024

Thank for working on this! I just noticed in trunk the PaletteEdit tests are a bit flaky after this merge. It seems to be caused by these two tests:

shows an option to remove all colors and shows a reset option when the canReset

One option could be using waitFor():

diff --git a/packages/components/src/palette-edit/test/index.tsx b/packages/components/src/palette-edit/test/index.tsx
index 31b712225a..9c3cb14a6b 100644
--- a/packages/components/src/palette-edit/test/index.tsx
+++ b/packages/components/src/palette-edit/test/index.tsx
@@ -176,11 +176,13 @@ describe( 'PaletteEdit', () => {
 				name: 'Color options',
 			} )
 		);
-		expect(
-			screen.getByRole( 'button', {
-				name: 'Reset colors',
-			} )
-		).toBeVisible();
+		await waitFor( () => {
+			expect(
+				screen.getByRole( 'button', {
+					name: 'Reset colors',
+				} )
+			).toBeVisible();
+		} );
 	} );
 
 	it( 'does not show a reset colors option when `canReset` is disabled', async () => {
@@ -192,11 +194,13 @@ describe( 'PaletteEdit', () => {
 				name: 'Color options',
 			} )
 		);
-		expect(
-			screen.queryByRole( 'button', {
-				name: 'Reset colors',
-			} )
-		).not.toBeInTheDocument();
+		await waitFor( () => {
+			expect(
+				screen.queryByRole( 'button', {
+					name: 'Reset colors',
+				} )
+			).not.toBeInTheDocument();
+		} );
 	} );
 
 	it( 'calls the `onChange` with the new color appended', async () => {

What do you think? 🙂

@t-hamano
Copy link
Contributor Author

I just noticed in trunk the PaletteEdit tests are a bit flaky after this merge. It seems to be caused by these two tests:

Thank you for noticing 🙇

One option could be using waitFor():

To me, this approach makes sense.

  • It appears that many of the tests using the toBeVisible assertion use waitFor
  • Especially for the dropdown, we may need to wait for the animation to finish (See this comment).

@t-hamano
Copy link
Contributor Author

@ciampo In #57809, I discovered that the instability of unit tests including the PaletteEdit component has been resolved. Thank you for your response 🙇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Code Quality Issues or PRs that relate to code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants