Convert the User screen test suites from Enzyme to React Testing Library - #398
Merged
Merged
Conversation
Converts all 22 test suites under screens/User/ to RTL, continuing the migration started in ctrliq#385. Tests drive the real UI through roles and labels instead of reaching into component props. Infrastructure fixes surfaced by the conversion: - setupTests.js: mockument's createRange stub lacks cloneRange and most of the Range API, crashing @testing-library/user-event's pointer handling. Restore jsdom's real Range with the two rect-method stubs the editor components need. - testUtils/rtlContexts.js gains settleTooltips(): a PF Modal close restores focus to a Tooltip-wrapped button, and a tooltip pending at unmount logs a state-update warning into the NEXT test, producing order-dependent failures. Applied in the three list suites that end right after closing an error modal. - testUtils/rtlContexts.js gains assertDetail() shared by the detail suites. - DisassociateButton: drop the invalid ouiaId prop on PF Tooltip that leaked to the DOM (enzyme never opened the tooltip; user-event's real hover exposed the warning). - Delete the orphaned enzymeHelpers.test.jsx.snap behind the perpetual 'snapshot file obsolete' notice.
This was referenced Jun 13, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Migrates the awx/ui/src/screens/User/ test suites from Enzyme to React Testing Library, aligning the UI test strategy with React 18+ compatibility and improving resilience by asserting on accessible roles/labels rather than component internals.
Changes:
- Converted User screen tests from Enzyme
mountWithContexts/wrapper assertions to RTLrenderWithContexts+screen/userEventinteractions. - Enhanced RTL test infrastructure (
settleTooltips(),assertDetail()) and updated Jest setup to restore a functionaldocument.createRangefor@testing-library/user-event. - Removed an obsolete Jest snapshot and eliminated a
Tooltipprop that caused React unknown-prop warnings.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| awx/ui/testUtils/rtlContexts.js | Expands RTL helpers (incl. tooltip settling and shared Detail assertions). |
| awx/ui/testUtils/snapshots/enzymeHelpers.test.jsx.snap | Deletes obsolete Enzyme snapshot output. |
| awx/ui/src/setupTests.js | Restores jsdom Range behavior to support RTL user-event pointer handling. |
| awx/ui/src/screens/User/UserTokens/UserTokens.test.js | Converts token creation modal test to RTL interactions. |
| awx/ui/src/screens/User/UserTokenList/UserTokenListItem.test.js | Converts list-row rendering assertions to RTL. |
| awx/ui/src/screens/User/UserTokenList/UserTokenList.test.js | Converts list selection/deletion/error flows to RTL; uses settleTooltips(). |
| awx/ui/src/screens/User/UserTokenDetail/UserTokenDetail.test.js | Converts detail rendering and delete/error flows to RTL; uses assertDetail(). |
| awx/ui/src/screens/User/UserTokenAdd/UserTokenAdd.test.js | Converts add-form flows to RTL using real form interactions. |
| awx/ui/src/screens/User/UserToken/UserToken.test.js | Converts token screen tab rendering/API call assertions to RTL. |
| awx/ui/src/screens/User/UserTeams/UserTeamListItem.test.js | Converts team list row rendering checks to RTL. |
| awx/ui/src/screens/User/UserTeams/UserTeamList.test.js | Converts team association/disassociation flows to RTL; uses settleTooltips(). |
| awx/ui/src/screens/User/Users.test.js | Converts breadcrumb/header assertions to RTL with a resetMocks-safe mock. |
| awx/ui/src/screens/User/UserRoles/UserRolesListItem.test.js | Converts role list row assertions (including chip affordances) to RTL. |
| awx/ui/src/screens/User/UserRoles/UserRolesList.test.js | Converts roles list flows (wizard, disassociate, errors, empty state) to RTL. |
| awx/ui/src/screens/User/UserOrganizations/UserOrganizations.test.js | Replaces Enzyme shallow test with RTL render + mock child list. |
| awx/ui/src/screens/User/UserOrganizations/UserOrganizationListItem.test.js | Converts organization list row rendering to RTL. |
| awx/ui/src/screens/User/UserOrganizations/UserOrganizationList.test.js | Converts organization list route-based mount + API assertions to RTL. |
| awx/ui/src/screens/User/UserList/UserListItem.test.js | Converts user list-row permission-based rendering assertions to RTL. |
| awx/ui/src/screens/User/UserList/UserList.test.js | Converts Users list load/select/delete/error flows to RTL; uses settleTooltips(). |
| awx/ui/src/screens/User/UserEdit/UserEdit.test.js | Converts edit-form save/cancel flows to RTL interactions. |
| awx/ui/src/screens/User/UserDetail/UserDetail.test.js | Converts detail assertions + edit/delete/error flows to RTL; uses assertDetail(). |
| awx/ui/src/screens/User/UserAdd/UserAdd.test.js | Converts add-form flows to RTL and accounts for PF required-label rendering. |
| awx/ui/src/screens/User/User.test.js | Converts User screen routing/tab visibility/error route test coverage to RTL. |
| awx/ui/src/screens/User/shared/UserTokenForm.test.js | Converts shared token form behavior tests to RTL (lookup + validation). |
| awx/ui/src/screens/User/shared/UserForm.test.js | Converts shared user form behavior tests to RTL (org lookup + required fields). |
| awx/ui/src/components/DisassociateButton/DisassociateButton.js | Removes unsupported Tooltip prop that produced React DOM warnings. |
# Conflicts: # awx/ui/testUtils/rtlContexts.js
…values The submit handler mutated Formik's values object (deleting password, assigning is_superuser/is_system_auditor). Deleting password flips the still-mounted password field from controlled to uncontrolled after a successful submit, which React warns about — surfaced once the merged react-router-dom-v5-compat bridge drives a re-render of the mounted form on navigate(). Destructure into a fresh submitValues and mutate only the copy; Formik's own state is left intact.
Contributor
Author
|
Rebased onto current main now that the react-router v6 compat migration has merged. Two things the merge required:
Full suite green against current main: 546 suites passed (1 skipped), 2,902 tests passed (5 skipped), lint clean. |
cigamit
approved these changes
Jun 14, 2026
This was referenced Jun 16, 2026
cigamit
pushed a commit
that referenced
this pull request
Jun 16, 2026
* enzyme -> RTL: convert the CredentialType screen suites Convert the six enzyme test suites in screens/CredentialType to React Testing Library via renderWithContexts (continuing the step-3 directory conversions after screens/User in #398): - CredentialTypeListItem, CredentialTypeList, CredentialTypeDetails, CredentialTypeAdd, CredentialTypeEdit, and the shared CredentialTypeForm. - Container suites (Add/Edit) stub the shared form and drive its onSubmit/onCancel/submitError props, matching how the enzyme tests treated the form as a unit (it has its own suite). - Delete flows interact for real; PF4's Modal aria-hides the tree under jsdom, so the confirm button is queried by label and clicked via fireEvent. - Drop a prop-inspection-only assertion (ToolbarDeleteButton deleteDetailsRequests count) that has no DOM-observable behavior. 33 tests pass; screens/CredentialType no longer references enzyme. * Address Copilot review on the CredentialType RTL suites - CredentialTypeForm: the value-update test now exercises both Name and Description and asserts the inputs exist before typing. - CredentialTypeListItem: pass rowIndex so the selection checkbox has a stable accessible name, and assert it by name ('Select row 0'). - CredentialTypeList: select row checkboxes by accessible name ('Select row 0') instead of a brittle getAllByRole('checkbox') index.
cigamit
pushed a commit
that referenced
this pull request
Jun 18, 2026
* enzyme -> RTL: convert the NotificationTemplate screen suites Convert the four enzyme test suites in screens/NotificationTemplate to React Testing Library via renderWithContexts (continuing step 3 after #398/#433): - NotificationTemplateListItem, NotificationTemplateList, NotificationTemplateDetail, and the shared NotificationTemplateForm. - Bulk-delete uses the PF4-modal-in-jsdom pattern (confirm by label + fireEvent). The test-notification toast asserts on its title text since the PF AlertGroup toast has no role=alert. - The poll-and-toast flow uses jest.runAllTimersAsync to drain the test() -> setTimeout -> readDetail -> onAddToast chain under fake timers. - The form's react-ace editors are stubbed to render their value (jsdom cannot query ace content), and OrganizationLookup's async fetch is settled in act; secret-revert is covered for all six notification types. 31 tests pass; screens/NotificationTemplate no longer references enzyme. * Address Copilot review comments
cigamit
pushed a commit
that referenced
this pull request
Jun 18, 2026
* enzyme -> RTL: convert the Template screen suites Convert all 47 enzyme test suites under screens/Template to React Testing Library (the last remaining screens/ directory), matching the renderWithContexts + screen/fireEvent/waitFor pattern of the prior conversions (#398, #433-#453). Covers: Templates / Template / WorkflowJobTemplate + TemplateSurvey, the JobTemplate and WorkflowJobTemplate Add/Edit/Detail screens, the shared JobTemplateForm / WorkflowJobTemplateForm / WebhookSubForm, the Survey editor (list/item/question add-edit-form/reorder/toolbar/multiple-choice), and the entire WorkflowJobTemplateVisualizer tree (graph/node/link/start/toolbar, the link and node modals, and the node-type resource lists). d3/SVG and PatternFly portals are asserted via element ids, data-cy / data-ouia-component-id, foreignObject content and accessible names rather than geometry or component-name lookups. Two interactions that are infeasible in jsdom (native drag reorder; one visualizer save-error scenario that passes in the browser) are kept as documented skips. 48 suites / 257 tests pass (2 documented skips); no production code changed. * Address Copilot review feedback on PR #483 RTL tests Remove the duplicated Delete All dispatch test; fix the 'incrimented' and 'survery' test-name typos. * Remove accidentally committed node_modules symlink awx/ui/node_modules was committed as a self-referential symlink; .gitignore only excludes the directory contents, not the symlink itself. Untrack it so checkout doesn't clobber a real node_modules. * Cede the 3 Template entry/detail test files to PR #484 Templates.test.js, Template.test.js and WorkflowJobTemplate.test.js are the only files this PR shared with #484 (Templates route tree -> v6). #484 now owns and RTL-converts those three (mounted for v6). Revert them here so the two PRs touch disjoint files and are independently mergeable in either order; this PR still converts the rest of screens/Template to RTL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SUMMARY
Converts all 22 test suites under
screens/User/(~1,100 lines) from Enzyme to React Testing Library, continuing the migration started in #385. Zeroenzymeimports remain in the directory. Tests now drive the real UI through roles and labels instead of reaching into component props, so they survive the React 18 upgrade that I'm pursuing.Infrastructure fixes the conversion surfaced
setupTests.js:@nteract/mockumentreplacesdocument.createRangewith a stub missingcloneRangeand most of the Range API, which crashes@testing-library/user-event's pointer handling. Restored jsdom's real Range and grafted on the two rect methods the editor components actually need from the stub.testUtils/rtlContexts.jsgainssettleTooltips(): closing a PF Modal restores focus (on a timeout) to the button that opened it; if that button is wrapped in a PFTooltip, the tooltip engages after its 300ms entry delay and a tooltip still pending at unmount logs "state update on unmounted component" into the next test — an order-dependent failure that bisects to nothing. Applied in the three list suites that end shortly after closing an error modal (UserTeamList,UserList,UserTokenList). Every list-screen conversion from here on will want this helper.testUtils/rtlContexts.jsgainsassertDetail(): shared label/value assertion for<Detail>pairs;UserDetailandUserTokenDetailuse it now, the other ~10 detail suites will as they convert.DisassociateButton: PF4Tooltipdoesn't acceptouiaIdand forwards it to a DOM div, which React warns about. Enzyme'ssimulate('click')never opened the tooltip so this went unnoticed for years; user-event's real hover found it. One-line removal — nothing selects on that id.enzymeHelpers.test.jsx.snapthat made Jest print "1 snapshot file obsolete" on every run.Gotchas for the next conversion batches
resetMocks: truestripsjest.fn(() => …)implementations fromjest.mockfactories between tests — use a plain function (capture props via amock-prefixed variable if you need them)."Label *"— anchor withgetByLabelText(/^Label/), exact match fails.aria-labeloverrides visible text as the accessible name (the Edit link isname: 'edit').aria-labelledbyinflates the dialog's accessible name — match dialogs with a regex, not the exact title.settleTooltips()(see above).TZ=UTClike the npm script does — barenpx jestfails the date assertions with a confusing 1-hour offset.Fully independent of every other open PR.
ISSUE TYPE
COMPONENT NAME
ASCENDER VERSION
ADDITIONAL INFORMATION
The converted suites plus testUtils were additionally run 3× in a loop to shake out order/timing flakes (106 tests green each pass), since the tooltip bug class this PR fixes only shows up across test boundaries.