Skip to content

Conversation

wjrosa
Copy link
Contributor

@wjrosa wjrosa commented Aug 20, 2025

Fixes STRIPE-454
Base PR #4264

Changes proposed in this Pull Request:

As part of the Node 20 upgrade project, this PR extracts most of the required frontend unit tests fixes from the source PR (#4264). The changes here are compatible with both versions (16 and 20).

What this changes:

  • Adds the await clause in front of every userEvent.click call
  • Mocks the createSelector method when mocking the @wordpress/data library
  • Correctly awaits getByRole calls
  • Apply some lint fixes (tests only)

Testing instructions

  • Code review
  • Check if the frontend tests and lint validations are still passing

  • Covered with tests (or have a good reason not to test in description ☝️)
  • Tested on mobile (or does not apply)

Changelog entry

  • This Pull Request does not require a changelog entry. (Comment required below)
Changelog Entry Comment

Comment

Post merge

@wjrosa wjrosa self-assigned this Aug 20, 2025
@wjrosa wjrosa marked this pull request as ready for review August 20, 2025 15:17
@wjrosa wjrosa mentioned this pull request Aug 20, 2025
12 tasks
@wjrosa wjrosa requested review from a team, daledupreez and Mayisha and removed request for a team August 20, 2025 15:40
Copy link
Contributor

@daledupreez daledupreez left a comment

Choose a reason for hiding this comment

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

@wjrosa, this seems OK at a glance, but I have some questions for you:

  • Why are we switching from userEvent to fireEvent? Per the Testing Library docs for userEvent, we should prefer userEvent over fireEvent as it is a more realistic reflection of user interactions.
    • I am OK if this is meant to be temporary or a workaround, but I think we should clarify why we're doing this. It's possible we did it in the original PR too, in which case we should understand why we did it there!
  • How can/should we test that these changes still pass in node 20? It would be good to clarify how we can confirm that is true. (But I don't think it's blocking, but I'd rather make sure we confirm it is working so we can avoid later cleanup.)


expect( checkbox ).toBeDisabled();
expect( checkbox ).not.toBeChecked();
expect( mockSetIsOCEnabled ).toHaveBeenCalledWith( false );
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the render calling a state setter? That feels pretty weird to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hum, how would you do it instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

My confusion stems from the fact that the previous test was waiting for the user to click on a button before checking for a state change. Simply rendering a component should generally not result in a state change, which was why I was confused.

Looking at this more closely, I now realise that we have a far more subtle situation: useIsOCEnabled() only looks at the underlying setting and not whether that setting is being overridden by UPE being disabled, and we're using an effect to update the client-side state when we detect that UPE is disabled.

It feels to me like it would be cleaner if the useIsOCEnabled() logic took into account whether UPE was enabed/disabled so our client-side state more directly represents the server-side state.

But I think that it something we should tackle in other PRs!

@wjrosa
Copy link
Contributor Author

wjrosa commented Aug 21, 2025

Hey Dale!

Why are we switching from userEvent to fireEvent? Per the Testing Library docs for userEvent, we should prefer userEvent over fireEvent as it is a more realistic reflection of user interactions.

That's just because it works with Node 20, while userEvent does not (at least with our changes here). I saw it in the docs for the latest versions and decided to give it a try. I will do some testing with the latest versions of testing library to see if that works for us.

How can/should we test that these changes still pass in node 20? It would be good to clarify how we can confirm that is true. (But I don't think it's blocking, but I'd rather make sure we confirm it is working so we can avoid later cleanup.)

The changes I made here are exactly the same as I did in the main PR. You can see that tests are passing there now. You can compare both.

Copy link
Contributor

@daledupreez daledupreez left a comment

Choose a reason for hiding this comment

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

I think it's worth explaining why you're using fireEvent instead of userEvent in the PR description, even if it's just "it continues to work". 😁

That said, I think we should eventually aim to switch back to userEvent at some point after we've completed the upgrade to Node 20, as I think the idea of testing user interactions is going to help us write better tests in the long run. However, I think that the big obstacle here is the 14.0 release of @testing-library/user-event, as that was when the core API changed from synchronous to asynchronous. Still, let's take that on after we have node 20 running.


expect( checkbox ).toBeDisabled();
expect( checkbox ).not.toBeChecked();
expect( mockSetIsOCEnabled ).toHaveBeenCalledWith( false );
Copy link
Contributor

Choose a reason for hiding this comment

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

My confusion stems from the fact that the previous test was waiting for the user to click on a button before checking for a state change. Simply rendering a component should generally not result in a state change, which was why I was confused.

Looking at this more closely, I now realise that we have a far more subtle situation: useIsOCEnabled() only looks at the underlying setting and not whether that setting is being overridden by UPE being disabled, and we're using an effect to update the client-side state when we detect that UPE is disabled.

It feels to me like it would be cleaner if the useIsOCEnabled() logic took into account whether UPE was enabed/disabled so our client-side state more directly represents the server-side state.

But I think that it something we should tackle in other PRs!

@wjrosa
Copy link
Contributor Author

wjrosa commented Aug 21, 2025

I think it's worth explaining why you're using fireEvent instead of userEvent in the PR description, even if it's just "it continues to work". 😁

I conducted some tests and was able to resolve the issue by simply adding the await clause in front of all userEvent.click calls. So I reverted that replacement in both here and in the base PR. Thanks for flagging that!

@wjrosa wjrosa added this to the 9.9.0 milestone Aug 21, 2025
Copy link
Contributor

@daledupreez daledupreez left a comment

Choose a reason for hiding this comment

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

Thanks for the updates! They look good to me!

Another thing we might be able to is split out a PR to update @testing-library/user-event to 14.0.0 (or some similarly early 14.x release), as that was released quite a while ago. We may not be able to switch to a current version until we upgrade React, but we might be able to reduce our work by tackling some of the work in an interim PR.

@wjrosa wjrosa force-pushed the dev/node-20-unit-tests-fixes branch from 4ed908b to 08ca917 Compare August 22, 2025 18:26
Copy link
Contributor

@Mayisha Mayisha left a comment

Choose a reason for hiding this comment

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

Changes are straightforward and look good to me. 👍
I have suggested a few additional missing await.
+1 to the suggestion of updating @testing-library/user-event in a follow-up PR.

maybeShowCashAppLimitNotice,
} from 'wcstripe/stripe-utils/cash-app-limit-notice-handler';
import { callWhenElementIsAvailable } from 'wcstripe/blocks/upe/call-when-element-is-available';
import { CASH_APP_NOTICE_AMOUNT_THRESHOLD } from 'wcstripe/data/constants';
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't CASH_APP_NOTICE_AMOUNT_THRESHOLD still part of the constant file? 🤔

@wjrosa wjrosa enabled auto-merge (squash) August 25, 2025 10:13
@wjrosa wjrosa merged commit 41e360d into develop Aug 25, 2025
40 checks passed
@wjrosa wjrosa deleted the dev/node-20-unit-tests-fixes branch August 25, 2025 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants