Skip to content

Refactor device plugin test files to use Vue Testing Library#14376

Open
curiouscoder-cmd wants to merge 3 commits intolearningequality:developfrom
curiouscoder-cmd:refactor-device-tests-vtl
Open

Refactor device plugin test files to use Vue Testing Library#14376
curiouscoder-cmd wants to merge 3 commits intolearningequality:developfrom
curiouscoder-cmd:refactor-device-tests-vtl

Conversation

@curiouscoder-cmd
Copy link
Contributor

@curiouscoder-cmd curiouscoder-cmd commented Mar 12, 2026

Summary

  • Refactored WelcomeModel.spec.js and DeviceSettingsPage.spec.js within the device plugin to use Vue Testing Library (@testing-library/vue) instead of @vue/test-utils.
  • Replaced assertions heavily reliant on component implementation details (like .vm.$data and wrapper.find) with user-centric DOM queries utilizing screen.getByRole.
  • Replaced mount with render handling and updated interactions using fireEvent and jest-dom assertions like toBeChecked().
  • Manual Verification: Ran the full device test suite (pnpm run test-jest -- --testPathPattern device) to verify that the changes do not break any existing test coverage. The entire suite passes cleanly (19 suites, 464 tests).

References

Fixes #14264

Reviewer guidance

  • Reviewers can checkout this branch and run pnpm run test-jest -- --testPathPattern device to ensure the device test suites pass.
  • Please note that within DeviceSettingsPage.spec.js, saveSpy is now configured to spy directly on the imported API saveDeviceSettings call instead of trying to spy on the internal component vm method, heavily adhering to VTL's guiding principles of keeping tests tightly bound to what the user and DOM see instead of Vue internals.

@github-actions github-actions bot added APP: Device Re: Device App (content import/export, facility-syncing, user permissions, etc.) DEV: frontend SIZE: medium labels Mar 12, 2026
@learning-equality-bot
Copy link

👋 Thanks for contributing!

We will assign a reviewer within the next two weeks. In the meantime, please ensure that:

  • You ran pre-commit locally
  • All issue requirements are satisfied
  • The contribution is aligned with our Contributing guidelines. Pay extra attention to Using generative AI. Pull requests that don't follow the guidelines will be closed.

We'll be in touch! 😊

@curiouscoder-cmd
Copy link
Contributor Author

Sorry for the delay, I was busy with exams. Please review the PR and let me know wherever changes are required.

@rtibbles
Copy link
Member

Hi @curiouscoder-cmd - just flagging that you have tagged this as fixing the tracking issue for the VTL migration work. Which actual issue is this targeted at? Will help us to review!

@curiouscoder-cmd
Copy link
Contributor Author

curiouscoder-cmd commented Mar 12, 2026

Hi @curiouscoder-cmd - just flagging that you have tagged this as fixing the tracking issue for the VTL migration work. Which actual issue is this targeted at? Will help us to review!

Apologies for the confusion there this PR is intended to address issue #14264 (Migrate Device settings tests to Vue Testing Library). I mistakenly referenced the tracking issue in the description. I have updated the references to point to the correct issue. Thanks for pointing it out :)

@github-actions
Copy link
Contributor

github-actions bot commented Mar 12, 2026

@rtibbles
Copy link
Member

No worries - thank you for updating!

@rtibbles rtibbles requested a review from rtibblesbot March 13, 2026 00:16
@learning-equality-bot
Copy link

📢✨ Before we assign a reviewer, we'll turn on @rtibblesbot to pre-review. Its comments are generated by an LLM, and should be evaluated accordingly.

Copy link
Contributor

@rtibblesbot rtibblesbot left a comment

Choose a reason for hiding this comment

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

Clean migration of both device test files from @vue/test-utils to VTL.

CI passing. No UI files changed — test-only PR.

  • blocking (1): Reduced coverage in loads the data test
  • suggestion (1): Helper indirection adds complexity without benefit
  • nitpick (1): Minor typo in test description
  • praise (2): Query strategy; API spy approach

@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 disallowGuestAccess = wrapper.find('[data-test="disallowGuestAccessButton"]');
const lockedContent = wrapper.find('[data-test="lockedContentButton"]');
function getButtons() {
const saveButton = screen.getByRole('button', { name: /save changes/i });
Copy link
Contributor

Choose a reason for hiding this comment

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

praise: Excellent use of screen.getByRole with accessible names instead of data-test attribute selectors. This validates that the component has proper accessibility semantics (radio buttons, button roles) while also making the tests resilient to implementation changes.

@curiouscoder-cmd curiouscoder-cmd force-pushed the refactor-device-tests-vtl branch from fd15e9a to c69b6b7 Compare March 13, 2026 09:08
Copy link
Contributor

@rtibblesbot rtibblesbot left a comment

Choose a reason for hiding this comment

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

Test-only migration from @vue/test-utils to VTL — good direction.

Prior Finding Status

# Finding Severity Status Evidence
1 Reduced coverage in loads the data test blocking UNADDRESSED No reply, no code change — downgraded to suggestion on re-evaluation (see below)
2 Helper indirection (getButtons) suggestion UNADDRESSED On reflection, getButtons() is reasonable DRY — extracting 7 role queries used across 10+ tests. Withdrawn.
3 Test description typo nitpick RESOLVED The current description 'emits submit event when continue button is clicked' is already accurate — the prior review appears to have referenced different text.
4 Query strategy praise praise N/A
5 API spy praise praise N/A

Summary: 1/3 actionable prior findings resolved. 1 re-raised (downgraded). 1 withdrawn.

CI failing — no-unused-vars lint error on Vuex import (see inline). JS tests pass.

  • blocking (1): Unused Vuex import fails CI lint
  • suggestion (1): loads the data test could verify the language select reflects loaded data

@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

await fireEvent.click(saveButton);
await global.flushPromises();
expect(saveSpy).toHaveBeenCalledWith(
expect(api.saveDeviceSettings).toHaveBeenCalledWith(
Copy link
Contributor

Choose a reason for hiding this comment

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

praise: Spying on the imported api.saveDeviceSettings instead of wrapper.vm.saveDeviceSettings is a big improvement — it verifies the actual API boundary rather than an internal method. Clean VTL migration.

@curiouscoder-cmd curiouscoder-cmd force-pushed the refactor-device-tests-vtl branch 2 times, most recently from 9b63386 to 819c09a Compare March 13, 2026 14:46
Copy link
Contributor

@rtibblesbot rtibblesbot left a comment

Choose a reason for hiding this comment

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

Clean VTL migration — test-only PR, no source changes.

CI passing (build checks still in progress but all test/smoke checks green).

Prior Finding Status

# Finding Severity Status Evidence
1 Unused Vuex import fails CI lint blocking UNADDRESSED Vuex still imported on line 3 but never used — downgraded to suggestion since no lint CI check appears to run
2 loads the data test could verify language select suggestion UNADDRESSED Acceptable given VTL philosophy — withdrawn
  • suggestion (1): Unused Vuex import
  • praise (1): API boundary testing approach

@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

Copy link
Contributor

@rtibblesbot rtibblesbot left a comment

Choose a reason for hiding this comment

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

Clean VTL migration — test-only PR, no source changes.

All CI checks passing. No UI files changed.

Prior Finding Status

# Finding Severity Status
1 Unused Vuex import suggestion RESOLVED — line 3 now imports only { Store }, not Vuex
2 loads the data language select suggestion Previously withdrawn

All prior findings resolved.

  • praise (2): Role-based queries; API boundary spying

@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 disallowGuestAccess = wrapper.find('[data-test="disallowGuestAccessButton"]');
const lockedContent = wrapper.find('[data-test="lockedContentButton"]');
function getButtons() {
const saveButton = screen.getByRole('button', { name: /save changes/i });
Copy link
Contributor

Choose a reason for hiding this comment

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

praise: Querying by role and accessible name (getByRole('radio', { name: /…/i })) rather than data-test selectors is exactly how VTL is meant to be used — these tests now double as implicit accessibility assertions that the radio buttons have correct labels.

await fireEvent.click(saveButton);
await global.flushPromises();
expect(saveSpy).toHaveBeenCalledWith(
expect(api.saveDeviceSettings).toHaveBeenCalledWith(
Copy link
Contributor

Choose a reason for hiding this comment

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

praise: Spying on api.saveDeviceSettings at the module boundary instead of wrapper.vm.saveDeviceSettings is a solid improvement — tests are now resilient to internal refactors while still verifying the correct API call and payload.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have also fixed the linting issue

@curiouscoder-cmd curiouscoder-cmd force-pushed the refactor-device-tests-vtl branch from 2fc5e05 to faf1e6c Compare March 13, 2026 16:49
@curiouscoder-cmd
Copy link
Contributor Author

@rtibbles I have addressed the requested changes , It seems the bot may sometimes be checking a previous commit instead of the latest one. Kindly review it once whenever possible.

Copy link
Member

@rtibbles rtibbles 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 we're still missing some coverage where the bot had previously identified a blocking comment.

We should be able to predict from the mock data the exact state of all the buttons, so we should also know if unlistedChannels exists or not - and it should be an error if it's present when it shouldn't be, or absent when it's not.

}
api.getDeviceSettings.mockResolvedValue(DeviceSettingsData);
await makeWrapper();
const { signInPage, unlistedChannels } = getButtons();
Copy link
Member

Choose a reason for hiding this comment

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

Feels like we're still only asserting these two settings and the language setting below? Seems like a reduction in coverage 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.

Fixed, assert all 6 buttons based on deviceSettingsData.

const checked = buttonProps.buttonValue === buttonProps.currentValue;
expect(checked).toBe(expected);
}
expect(screen.getAllByText(/english/i)[0]).toBeInTheDocument();
Copy link
Member

Choose a reason for hiding this comment

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

This is quite a broad test - this could also pass, if "english" just happens to be anywhere in the page, rather than specifically in the language selector drop down.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed I change it to use getAllByText('English')[0] with exact case match instead /english/i. now this ismore specific since it will not match partial case variations else where on the page.

@curiouscoder-cmd
Copy link
Contributor Author

There's a CI failure in the Python postgres unit tests but it appears to be unrelated to my changes.
The failing test is:

FAILED kolibri/core/content/test/test_content_app.py::ContentNodeAPITestCase::test_contentnode_tree
This is a backend content API test, while my PR only modifies frontend test files in the Device plugin. This looks like it may be a flaky test.

could a maintainer re-run the failed check when possible?
and let me know if any other changes need to be made. Thanks.

@rtibbles rtibbles self-assigned this Mar 19, 2026
@curiouscoder-cmd
Copy link
Contributor Author

Hello , just wanted to follow up , if the changes are meeting the requirements or any other changes updates are needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

APP: Device Re: Device App (content import/export, facility-syncing, user permissions, etc.) DEV: frontend SIZE: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate Device settings tests to Vue Testing Library

3 participants