Convert trash modal unit tests to Vue Testing Library#5816
Convert trash modal unit tests to Vue Testing Library#5816Prashant-thakur77 wants to merge 10 commits into
Conversation
|
👋 Hi @Prashant-thakur77, thanks for contributing! For the review process to begin, please verify that the following is satisfied:
Also check that issue requirements are satisfied & you ran Pull requests that don't follow the guidelines will be closed. Reviewer assignment can take up to 2 weeks. |
|
Hlo @MisRob ,I have resolved the issue,do review when you have time. |
08ea025 to
90f477b
Compare
|
📢✨ Before we assign a reviewer, we'll turn on |
|
📢✨ Before we assign a reviewer, we'll invite community pre-review. See the community review guidance for both authors and reviewers. |
AllanOXDi
left a comment
There was a problem hiding this comment.
Hi @Prashant-thakur77, thanks for working on this. I left a few clean up
| .mockResolvedValue({}); | ||
| jest.spyOn(TrashModal.methods, 'loadAncestors').mockResolvedValue(); | ||
| jest.spyOn(TrashModal.methods, 'removeContentNodes').mockResolvedValue(); | ||
| const loadNodesSpy = jest.spyOn(TrashModal.methods, 'loadNodes'); |
There was a problem hiding this comment.
This works but is non-obvious; add a comment explaining that real execution is intentional.
| jest.spyOn(TrashModal.methods, 'loadChildren').mockReturnValue(new Promise(() => {})); | ||
| } else { | ||
| jest.spyOn(TrashModal.methods, 'loadChildren').mockResolvedValue({ | ||
| more: items === testChildren ? null : { parent: TRASH_ID, page: 2 }, |
There was a problem hiding this comment.
using (===) to decide pagination is not quite right "show more unless the exact same array object was passed." Use an explicit hasMore parameter instead.
| expect(wrapper.vm.selected).toEqual([]); | ||
| expect(wrapper.vm.previewNodeId).toBe(null); | ||
| await waitFor(() => { | ||
| expect(loadContentNodesSpy).toHaveBeenCalledWith({ parent: TRASH_ID, page: 2 }); |
There was a problem hiding this comment.
The assertion uses toHaveBeenCalledWith, which passes if any call matches, so the initial call and the "Show more" call are both included. This passes correctly but could be more precise with toHaveBeenLastCalledWith to explicitly assert the pagination call was the most recent one.
|
|
||
| await user.click(showMoreBtn); | ||
|
|
||
| it('moveNoves should clear selected and previewNodeId', async () => { |
There was a problem hiding this comment.
The original had a test for clicking an item, setting previewNodeId (which opens ResourceDrawer). This has been dropped entirely. It should either be added back or explicitly noted in the PR description as an intentional omission.
There was a problem hiding this comment.
I’ve restored the missing coverage in line with Testing Library patterns:
- Reintroduced the test that verifies clicking an item sets previewNodeId and opens the ResourceDrawer.
- Reworked the previous moveNodes test to follow user interactions instead of directly invoking wrapper.vm. The test now selects an item, opens the preview drawer, completes the “Move here” flow, and asserts that selections are cleared and the drawer is closed.
What are your thoughts on this apporach @AllanOXDi .
| import { RouteNames } from '../../../constants'; | ||
| import TrashModal from '../TrashModal'; | ||
|
|
||
| const store = factory(); |
There was a problem hiding this comment.
Move inside makeWrapper so each test gets a clean store.
| const utils = render( | ||
| TrashModal, | ||
| { | ||
| store, |
There was a problem hiding this comment.
Passing the shared module-level store into render. See line 9, the shared store's dispatch spy in the deletion test ( see line 200) may not be fully cleaned up before subsequent tests run.
There was a problem hiding this comment.
Fixed as part of moving store into makeWrapper
| expect(screen.getByTestId('delete')).toBeDisabled(); | ||
| expect(screen.getByTestId('restore')).toBeDisabled(); | ||
|
|
||
| await user.click(screen.getAllByRole('checkbox')[1]); |
There was a problem hiding this comment.
A bit brittle. [1] assumes the second checkbox in DOM order is the first item checkbox (index 0 being select-all). If any component renders an additional checkbox before the list, this clicks the wrong element. Use screen.getAllByTestId('checkbox')[0] instead.
There was a problem hiding this comment.
Done. Changed to within(screen.getAllByTestId('checkbox')[0]).getByRole('checkbox').
Note: data-test="checkbox" is on the k-checkbox-container div, not the input, so within() is needed to reach the actual checkbox input for clicking.
|
|
||
| await waitFor(() => { | ||
| screen | ||
| .getAllByRole('checkbox') |
There was a problem hiding this comment.
Relies on the select-all being first in DOM order. Works today but fragile for the same reason as line 117.
|
|
||
| it('successful deletion triggers snackbar and reloads nodes', async () => { | ||
| jest.spyOn(TrashModal.methods, 'deleteContentNodes').mockResolvedValue(); | ||
| const dispatchSpy = jest.spyOn(store, 'dispatch').mockImplementation(() => Promise.resolve()); |
There was a problem hiding this comment.
Since makeWrapper is called after this line, the spy is active during mount. But because the store is shared (line 9), this mock intercepts dispatch calls in other tests if cleanup races. The fix is again to move store into makeWrapper.
90f477b to
812d4fc
Compare
|
Hlo @AllanOXDi I have done the requested changes,do look at them when you have time .Please do tell if any other changes are required. |
|
📢✨ Before we assign a reviewer, we'll turn on |
rtibblesbot
left a comment
There was a problem hiding this comment.
Solid migration — the tests correctly verify observable behavior throughout, and CI is passing.
No UI files changed — Phase 3 skipped.
- suggestion:
getByTestIdused for buttons with accessible names — inline comment at the first occurrence - praise: two inline comments
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
Reviewed the pull request diff checking for:
- Correctness: bugs, edge cases, undocumented behavior, resource leaks, hardcoded values
- Design: unnecessary complexity, naming, readability, comment accuracy, redundant state
- Architecture: duplicated concerns, minimal interfaces, composition over inheritance
- Testing: behavior-based assertions, mocks only at hard boundaries, accurate coverage
- Completeness: missing dependencies, unupdated usages, i18n, accessibility, security
- Principles: DRY (same reason to change), SRP, Rule of Three (no premature abstraction)
- Checked CI status and linked issue acceptance criteria
- For UI changes: inspected screenshots for layout, visual completeness, and consistency
| it('checking an item enables the Delete and Restore buttons', async () => { | ||
| const { user } = await makeWrapper(); | ||
|
|
||
| expect(screen.getByTestId('delete')).toBeDisabled(); |
There was a problem hiding this comment.
suggestion: The acceptance criteria ask to follow the Testing Library query priority, which puts getByRole above getByTestId. The Delete and Restore buttons have accessible text labels, so prefer:
expect(screen.getByRole('button', { name: /Delete/i })).toBeDisabled();
expect(screen.getByRole('button', { name: /Restore/i })).toBeDisabled();The same applies wherever getByTestId('delete'), getByTestId('restore'), getByTestId('selectall'), and findByTestId('close') appear throughout the file. getByTestId remains appropriate for structural/state containers (loading, empty, list) where no accessible role exists.
rtibblesbot
left a comment
There was a problem hiding this comment.
Prior findings
Resolved:
getByTestId('delete')/getByTestId('restore')for labeled buttons (suggestion) — replaced withgetByRole('button', { name: /Delete/i })andgetByRole('button', { name: /Restore/i })throughout;getByTestId('selectall')direct clicks also updated towithin(getByTestId('selectall')).getByRole('checkbox')across all test flows.
1/1 prior findings resolved. 0 re-raised.
CI passing. No UI files changed — Phase 3 skipped.
- praise: inline comment on the getByRole changes
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
Compared the current PR state against findings from a prior review:
- Retrieved prior bot reviews deterministically via the GitHub API
- Classified each prior finding as RESOLVED, UNADDRESSED, ACKNOWLEDGED, or CONTESTED
- Only raised NEW findings for newly introduced code
- Reviewed the pull request diff checking for correctness, design, architecture, testing, completeness, and adherence to DRY/SRP principles
- Checked CI status and linked issue acceptance criteria
| it('checking an item enables the Delete and Restore buttons', async () => { | ||
| const { user } = await makeWrapper(); | ||
|
|
||
| expect(screen.getByRole('button', { name: /Delete/i })).toBeDisabled(); |
There was a problem hiding this comment.
praise: The getByRole migration is thorough and consistent — every getByTestId('delete'), getByTestId('restore'), and direct getByTestId('selectall') click across all six affected tests has been updated. The remaining getByTestId usages (loading, empty, list, checkbox container wrappers, item links, close icon button) are all cases where no accessible role or label is available, so testId is the appropriate fallback per Testing Library's query priority.
Summary
Migrates trashModal.spec.js from @vue/test-utils to @testing-library/vue, as part of the broader effort to make Studio's frontend tests more user-centric and resilient to implementation changes.
Manual verification:
Screencast.From.2026-04-07.16-36-39.webm
References
Closes #5790
See #5789
Reviewer guidance
1)Only trashModal.spec.js was changed.
2) Reviewer need to check if all the needed testcases are present and testing-library is properly used.
AI usage
I used Claude to help plan and implement the migration.I checked other Testing-library implementations and verified the tests written and updated wherever needed.I followed the guidance given in the issue description and its parent issue description.I again checked if all the test cases are passing properly.