Migrate epub viewer search tests to Vue Testing Library#14321
Migrate epub viewer search tests to Vue Testing Library#14321rtibbles merged 6 commits intolearningequality:developfrom
Conversation
|
👋 Thanks for contributing! We will assign a reviewer within the next two weeks. In the meantime, please ensure that:
We'll be in touch! 😊 |
|
Requesting rtibblesbot review for first pass, we will do a full review when it is satisfied! |
rtibblesbot
left a comment
There was a problem hiding this comment.
Clean migration of epub viewer search tests to Vue Testing Library. CI passing (admin checks only — no build/test CI ran).
- blocking: Focus test in SearchSideBar no longer tests the component's
focusOnInput()method (see inline comment) - praise: Good use of
getByRolequeries in both files
@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
|
|
||
| const input = screen.getByRole('searchbox'); | ||
|
|
||
| input.focus(); |
There was a problem hiding this comment.
blocking: This test no longer verifies the component's focusOnInput() public method — it just calls input.focus() directly on the DOM element, which tests native browser behavior rather than component behavior.
The original test called wrapper.vm.focusOnInput(), which verified that the component's ref wiring (this.$refs.searchInput.focus() at line 181 of SearchSideBar.vue) works correctly. The new test bypasses that entirely.
Vue Testing Library's render returns the component instance on the container property's parent. One option that preserves the behavioral test while staying within VTL patterns:
it('should allow parent to focus on input box', async () => {
const { container } = renderComponent();
const vm = container.__vue_app__ ? ... // Vue 3
// For Vue 2 with VTL, you can access the instance via:
// const wrapper = renderComponent();
// wrapper.vm is not exposed by VTL by design.Since VTL intentionally discourages vm access, consider testing this indirectly — e.g., by simulating what a parent component would do. Alternatively, if the team accepts that focusOnInput is an internal detail not worth testing through VTL, the test description should at minimum be updated to reflect what it actually tests (e.g., "search input should be focusable") rather than implying it tests the parent-facing API.
| it('should render', () => { | ||
| render(SearchButton); | ||
|
|
||
| const button = screen.getByRole('button'); |
There was a problem hiding this comment.
praise: Good use of getByRole('button') — queries by accessible role rather than CSS selectors, which is exactly what Testing Library encourages.
rtibblesbot
left a comment
There was a problem hiding this comment.
Clean migration overall, but the focus test finding from the prior review remains unaddressed.
CI passing.
- blocking: Focus test still bypasses the component's
focusOnInput()public method (see inline comment) - nitpick: Missing newline at end of
SearchSideBar.spec.js
1 prior finding(s) resolved (praise on getByRole usage).
@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
|
|
||
| const input = screen.getByRole('searchbox'); | ||
|
|
||
| input.focus(); |
There was a problem hiding this comment.
blocking (UNADDRESSED): This still calls input.focus() directly on the DOM element rather than testing the component's focusOnInput() method (line 180 of SearchSideBar.vue, marked @public). The test now only proves that a native <input> can receive focus, which is a browser default.
Since VTL discourages vm access, the pragmatic options are:
- Rename the test to "search input should be focusable" so it describes what it actually tests, accepting that
focusOnInput()is no longer unit-tested. - Use a thin wrapper parent component in the test that calls the child's
focusOnInput()via a template ref, verifying the public API as a parent would.
There was a problem hiding this comment.
Apologies for the duplicate review here!
I do agree though that we still need to test the component method, not the trivial assertion that an input, once focused, has focus.
There was a problem hiding this comment.
thanks for the review!
i understand the issue that the current test focuses the input directly instead of verifying the component’s 'focusOnInput()' method.
so i’ll update the test acc, and will push a fix shortly.
|
@rtibbles i've updated the test to verify the component's focusOnInput() behavior using a parent wrapper component. please let me know if further adjustments are needed. |
rtibblesbot
left a comment
There was a problem hiding this comment.
Clean migration to Vue Testing Library. The focus test now properly verifies focusOnInput() through a parent wrapper component.
CI passing.
- nitpick: Commented-out
renderComponent()on line 23 of SearchSideBar.spec.js (see inline) - praise: Parent wrapper pattern for testing
focusOnInput()(see inline)
2 prior finding(s) resolved.
@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
| const elementThatIsFocused = document.activeElement; | ||
| expect(elementThatIsFocused).toHaveClass('search-input'); | ||
| it('should allow parent to focus on input box', async () => { | ||
| // renderComponent(); |
There was a problem hiding this comment.
nitpick: Remove the commented-out // renderComponent(); — it's leftover from development and not needed since the parent wrapper handles rendering.
| const sidebarRef = ref(null); | ||
|
|
||
| function focusInput() { | ||
| sidebarRef.value.focusOnInput(); |
There was a problem hiding this comment.
praise: Nice use of a parent wrapper to test focusOnInput() through its intended public API — this verifies the real parent-child interaction rather than reaching into component internals.
There was a problem hiding this comment.
Yes, this is a very nice way of asserting the overall behaviour!
|
yeah, even the cleanup's done |
rtibblesbot
left a comment
There was a problem hiding this comment.
Clean migration of epub viewer search tests to Vue Testing Library. All prior findings resolved.
CI passing.
3 prior finding(s) resolved.
@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
| expect(wrapper.emitted().click).toBeTruthy(); | ||
|
|
||
| it('should emit an event when the button is clicked', async() => { | ||
| const { emitted } = render(SearchButton); |
There was a problem hiding this comment.
praise: Clean use of emitted() destructuring from the render return — keeps the assertion on line 18 concise and readable.
rtibbles
left a comment
There was a problem hiding this comment.
Looks good, should be good to merge assuming the tests pass.
| const sidebarRef = ref(null); | ||
|
|
||
| function focusInput() { | ||
| sidebarRef.value.focusOnInput(); |
There was a problem hiding this comment.
Yes, this is a very nice way of asserting the overall behaviour!
Build Artifacts
|
|
Linting failures still present:
|
…lity#14321) * Migrate epub viewer search tests to Vue Testing Library * fixed SearchSideBar focus test to verify focusOnInput method * removed leftover comment renderComponent & added a newline at the end as well * [pre-commit.ci lite] apply automatic fixes * fixes lint errors and updated focus assertion * fixing lint errors in SearchSideBar.spec test wrapper --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Summary
This PR migrates the epub viewer search unit tests from
@vue/test-utilsto@testing-library/vue.The following files were updated:
SearchButton.spec.jsSearchSideBar.spec.jsChanges include:
@vue/test-utilsusagegetByRole)wrapper,vm, etc.)Manual verification
pnpm run test-jest -- --testPathPattern epub_viewerReferences
Closes #14187
Reviewer guidance
pnpm run test-jest -- --testPathPattern epub_viewer