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

SnackbarList, Snackbar: Add unit test #59157

Merged
merged 10 commits into from Feb 28, 2024
Merged

SnackbarList, Snackbar: Add unit test #59157

merged 10 commits into from Feb 28, 2024

Conversation

t-hamano
Copy link
Contributor

@t-hamano t-hamano commented Feb 19, 2024

Preparation to tackle #59139

What?

This PR adds unit tests for SnackbarList and Snackbar components.

Why?

While investigating #59139, I discovered that there are no unit tests for the Snackbar component.

Testing is necessary to ensure that the current implementation works as specified or to prevent future regressions.

How?

We tested as many cases as possible according to the actual implementation and README.

Testing Instructions

Run the following command:

  • npm run test:unit packages/components/src/snackbar/test/index.tsx
  • npm run test:unit packages/components/src/snackbar/test/list.tsx

@t-hamano t-hamano added [Type] Code Quality Issues or PRs that relate to code quality [Package] Components /packages/components labels Feb 19, 2024
@t-hamano t-hamano self-assigned this Feb 19, 2024
Comment on lines -141 to +145
role={ ! explicitDismiss ? 'button' : '' }
role={ ! explicitDismiss ? 'button' : undefined }
onKeyPress={ ! explicitDismiss ? dismissMe : undefined }
aria-label={ ! explicitDismiss ? __( 'Dismiss this notice' ) : '' }
aria-label={
! explicitDismiss ? __( 'Dismiss this notice' ) : undefined
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Prevents attributes without values from being applied.

Copy link
Contributor

Choose a reason for hiding this comment

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

The negation in all of these ternaries feels totally backwards to me, but hey ho... at least they're consistent!

Perhaps instead we could separate out the dismiss props?

// `explicitDismiss || { ... }` also works,
// as long as it's guaranteed to be a boolean!

const dismissProps = explicitDismiss ? {} : {
  onClick: dismissMe,
  onKeyPress: dismissMe,
  role: 'button',
  'aria-label': __( 'Dismiss this notice' ),
}

return (
  <div { ...dismissProps } />
);

Anyway, scope creep 🚨

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although this is a negative form, how about the following approach?

const dismissProps = {
	onClick: dismissMe,
	onKeyPress: dismissMe,
	role: 'button',
	'aria-label': __( 'Dismiss this notice' ),
};

return (
	<div
		// When there is no explicit close button to close the snackbar,
		// give the snackbar itself a prop that can be dismissed.
		{ ...( ! explicitDismiss && dismissProps ) }
	>
);

@@ -70,7 +70,6 @@ Default.args = {
},
],
content: 'Post published.',
isDismissible: true,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

isDismissible is not present in the Snackbar component's action property.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh wait... this bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a little confusing, but the Snackbar component inherits the type of the Notice component. As mentioned in this comment, the current Snackbar component inherits a type that contains unintended properties.

In fact, if you search the ./packages/components/src/snackbar directory with isDismissible, you shouldn't find any code containing isDismissible.

} );
} );

describe( 'useSpokenMessage', () => {
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 is the same as testing the Notice component. We are testing the useSpokenMessage hook itself, and if it has been tested with the Notice component, there might be no need to test it again here.

*/
import SnackbarList from '../list';

window.scrollTo = jest.fn();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

When the Snackbar component is removed, the animation runs through motion.div. If we don't mock window.scrollTo, the following error seems to occur.

expect(jest.fn()).not.toHaveErrored(expected)

Expected mock function not to be called but it was called with:
[[Error: Not implemented: window.scrollTo]],[[Error: Not implemented: window.scrollTo]]

Copy link

github-actions bot commented Feb 19, 2024

Flaky tests detected in 65f7b6b.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/7953430355
📝 Reported issues:

@@ -28,8 +32,32 @@ type SnackbarOnlyProps = {
listRef?: MutableRefObject< HTMLDivElement | null >;
};

export type SnackbarProps = Omit< NoticeProps, '__unstableHTML' > &
SnackbarOnlyProps;
export type SnackbarProps = Pick<
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 was the part I had the most trouble with. This component uses the types of the Notice component, and I discovered that the following types, which are not available in the Snackbar component, also apply to the Snackbar component.

  • isDismissible
  • status
  • actions.className
  • actions.noDefaultClasses
  • actions.variant

I used Pick instead of Omit so that when new props are added to the Notice component in the future, they are not unintentionally exposed to the Snackbar component as well.

At the same time, the code editor should also correctly display the description of the actions prop.

image

@t-hamano t-hamano requested a review from a team February 19, 2024 01:55
@t-hamano t-hamano marked this pull request as ready for review February 19, 2024 01:55
Copy link

github-actions bot commented Feb 19, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: t-hamano <wildworks@git.wordpress.org>
Co-authored-by: andrewhayward <andrewhayward@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@@ -138,9 +138,12 @@ function UnforwardedSnackbar(
className={ classes }
onClick={ ! explicitDismiss ? dismissMe : undefined }
tabIndex={ 0 }
role={ ! explicitDismiss ? 'button' : '' }
role={ ! explicitDismiss ? 'button' : undefined }
Copy link
Member

Choose a reason for hiding this comment

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

May be a nitpick, and I might be missing something, but shouldn't an element without a role have a null role instead of an undefined one?

Copy link
Member

Choose a reason for hiding this comment

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

Also, is "no-role" the best to do in this case? Is alert or any other status role a better fit perhaps? @andrewhayward what do you think?

packages/components/src/snackbar/test/index.tsx Outdated Show resolved Hide resolved
packages/components/src/snackbar/test/index.tsx Outdated Show resolved Hide resolved
packages/components/src/snackbar/test/index.tsx Outdated Show resolved Hide resolved
packages/components/src/snackbar/test/index.tsx Outdated Show resolved Hide resolved
packages/components/src/snackbar/test/list.tsx Outdated Show resolved Hide resolved
Copy link
Member

@tyxla tyxla left a comment

Choose a reason for hiding this comment

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

Nothing further from my perspective. Nice work 🚀

@t-hamano
Copy link
Contributor Author

Thanks for the review!

This PR also includes a change to remove the role attribute which has no value, which I believe is at least an improvement and not a regression. I would like to merge this PR as I think that what role is appropriate or not if the Snackbar is not a button, or any refactoring mentioned in this comment could also be addressed in a follow-up.

@t-hamano t-hamano merged commit 33f5094 into trunk Feb 28, 2024
60 of 61 checks passed
@t-hamano t-hamano deleted the snackbar/add-unit-test branch February 28, 2024 02:08
@github-actions github-actions bot added this to the Gutenberg 17.9 milestone Feb 28, 2024
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.

None yet

3 participants