Skip to content

Restructuring frontend tests & add Vitest projects#611

Open
therobbiedavis wants to merge 5 commits into
canaryfrom
feature/fe-test-architecture
Open

Restructuring frontend tests & add Vitest projects#611
therobbiedavis wants to merge 5 commits into
canaryfrom
feature/fe-test-architecture

Conversation

@therobbiedavis
Copy link
Copy Markdown
Collaborator

Summary

Reorganizes the frontend test architecture around colocated test/ folders, adds Vitest projects for clearer runtime separation, cleans up shared test utilities, and updates Cypress e2e mocks to match the current versioned API routes.

Changes

Added

  • Vitest projects for node, jsdom, and smoke test groups.
  • Colocated frontend test folders beside the components, views, stores, services, composables, and utils they cover.
  • Shared frontend test helpers for mounting, waits, storage, API mocks, SignalR mocks, stubs, and fixture factories.
  • Frontend test structure guard for enforcing the new colocated test layout.
  • Cypress API path helper for versioned /api/v*/... e2e route stubs.
  • Frontend verification scripts that include linting, type-checking, and coverage.

Changed

  • Moved frontend unit tests out of the old central src/__tests__ layout into colocated test/ folders.
  • Renamed node-only specs to the *.node.spec.ts convention.
  • Updated Vitest config to use project-based test grouping instead of manually maintained node-spec lists.
  • Updated Cypress e2e specs to use version-aware API route stubs.
  • Updated settings.cy.ts to test the current General Settings UI instead of removed proxy/output-path controls.
  • Aligned Cypress baseUrl with the e2e script port 4173.
  • Updated FE test documentation and README references for the new structure.
  • Updated Husky/lint-staged execution to work reliably from Git Bash on Windows.

Fixed

  • Fixed Cypress e2e mocks missing current /api/v1/... app requests.
  • Fixed stale Cypress settings test selectors and assertions.
  • Fixed pre-commit lint/format execution failing when Git clients could not launch bash-based npm wrappers.
  • Fixed stale frontend test/tooling references, including unused Playwright/Nightwatch type references.

Removed

  • Removed the old central fe/src/__tests__ structure.
  • Removed the old Vitest no-setup config.
  • Removed stale generated frontend eslint report output.

Testing

  • npm run verify:frontend
  • npm run lint:eslint
  • node node_modules/typescript/bin/tsc -p cypress/tsconfig.json --noEmit
  • node node_modules/cypress/bin/cypress verify
  • Targeted Cypress e2e: cypress/e2e/settings.cy.ts
  • Git Bash pre-commit hook: ./.husky/pre-commit

Restructure the frontend test layout and test tooling: move many __tests__ into organized fe/src/test/* folders, add test factories, mocks, stubs and utility helpers, and remove the checked-in fe/eslint-report.json. Add a Vitest multi-project entry (fe/vitest.projects.ts) and a test-structure guard script (fe/scripts/check-test-structure.mjs), update vitest and TypeScript configs and Vite settings, and remove the old vitest.no-setup.config.ts. Update fe/README.md with guidance on running Vitest projects and the new frontend verification gate, add npm verify scripts in package.json, and adjust .gitignore entries to ignore eslint-report.json. Miscellaneous edits: VS Code file nesting settings and other small config tweaks to support the new test layout.
Change Cypress baseUrl and centralize API intercepts by adding a support helper. Updated fe/cypress.config.ts to use port 4173. Added fe/cypress/support/api.ts exporting apiPath() (wraps endpoints with /api/v*) and stubAppShellApi() to centralize common stubs. Refactored multiple e2e specs to use apiPath for intercept URLs and to use stubAppShellApi in settings, plus minor test cleanup/formatting and consistent mock response shapes. Affected files: cypress.config.ts, support/api.ts, and several tests under fe/cypress/e2e (file-naming-patterns.cy.ts, hardlink-move-flow.cy.ts, move-flow.cy.ts, settings-root-folders.cy.ts, settings.cy.ts).
@therobbiedavis therobbiedavis requested review from a team and Copilot May 21, 2026 16:48
@therobbiedavis therobbiedavis added the patch patch version bump - backward compatible bug fixes label May 21, 2026
@therobbiedavis therobbiedavis requested a review from T4g1 May 21, 2026 16:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Reorganizes the frontend testing/tooling setup around Vitest projects, colocated test/ folders, shared test utilities, and updated Cypress e2e stubs for versioned API routes.

Changes:

  • Added Vitest project-based configuration (node/jsdom/smoke) with coverage configuration and a test structure guard script.
  • Introduced shared frontend test utilities (mounting helpers, waits, storage mocks, factories, stubs, API/SignalR mocks).
  • Updated Cypress e2e tests to use a version-aware API path helper and aligned baseUrl/verification scripts.

Reviewed changes

Copilot reviewed 89 out of 116 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/lint-staged.mjs Runs frontend lint/format via local node bin paths to improve Windows/Git Bash reliability.
package.json Adds a root convenience script for running the frontend verification gate.
fe/vitest.projects.ts Defines Vitest projects and globs for runtime separation.
fe/vitest.no-setup.config.ts Removes the legacy “no setup” Vitest config.
fe/vitest.config.ts Switches to project-based Vitest config and adds unit coverage settings/thresholds.
fe/vite.config.ts Tweaks production-only build minify/esbuild options.
fe/tsconfig.vitest.json Updates test TS includes and library targets for Vitest typechecking.
fe/tsconfig.node.json Updates Node TS includes (adds vitest projects/config patterns; removes stale configs).
fe/tsconfig.app.json Excludes new colocated src/**/test/**/* paths from app TS build.
fe/src/test/utils/wait.ts Adds shared async helpers (delay/flush/waitFor/deferred).
fe/src/test/utils/storage.ts Adds a Vitest storage mock helper.
fe/src/test/utils/mount.ts Adds reusable mount helpers for Pinia/router + stubs merging.
fe/src/test/stubs.ts Adds shared component stubs (modal/base/app).
fe/src/test/mocks/signalr.ts Adds a SignalR service mock factory.
fe/src/test/mocks/api.ts Adds API service/module mock factories.
fe/src/test/factories/settings.ts Adds settings factory helper.
fe/src/test/factories/searchResult.ts Adds SearchResult factory helper.
fe/src/test/factories/rootFolder.ts Adds RootFolder factory helper.
fe/src/test/factories/qualityProfile.ts Adds QualityProfile factory helper.
fe/src/test/factories/indexer.ts Adds Indexer factory helper.
fe/src/test/factories/downloadClient.ts Adds download client configuration factory helper.
fe/src/test/factories/download.ts Adds Download factory helper.
fe/src/test/factories/audiobook.ts Adds Audiobook factory helper.
fe/src/test/README.md Documents the new frontend test layout and rules.
fe/src/components/base/BrandLogo.vue Makes logo source a bound constant (helps tests/static asset handling).
fe/src/tests/useScore.spec.ts Refactors to use shared SearchResult factory.
fe/src/tests/useScore.rejection.spec.ts Refactors to use shared SearchResult factory.
fe/src/tests/test-setup.ts Removes the global Vitest setup file and its centralized mocks/polyfills.
fe/src/tests/startupConfigCache.test.ts Refactors concurrency test to use shared deferred helper.
fe/src/tests/sessionTokenStorage.test.ts Uses explicit storage mock + module reset; switches to async import.
fe/src/tests/searchResultHelpers.spec.ts Adjusts casting to align with new lint rules for tests.
fe/src/tests/searchResultFormatting.spec.ts Adjusts casting to align with new lint rules for tests.
fe/src/tests/sanity.spec.js Removes legacy sanity test (JS).
fe/src/tests/sanity.js Removes legacy sanity test (JS).
fe/src/tests/libraryImport.store.spec.ts Uses shared flush helper and adjusts test casts.
fe/src/tests/import-activity.spec.ts Updates path reference for ActivityView compile check.
fe/src/tests/grabsSortable.spec.ts Uses shared stubs/factories/wait helpers; improves polling logic.
fe/src/tests/debug_AddNew.spec.ts Removes debug placeholder spec.
fe/src/tests/customFilterEvaluator.spec.ts Adjusts casting style for tests.
fe/src/tests/audiobook-detailview.signalr.spec.ts Uses shared delay helper; adjusts SignalR callback injection.
fe/src/tests/api.removeFromLibrary.spec.ts Adjusts fetch call typing/casting.
fe/src/tests/api.ensureImageCached.spec.ts Switches to alias imports + unmock; adjusts casting.
fe/src/tests/api.downloadLogs.spec.ts Switches to alias imports for unmock + dynamic import.
fe/src/tests/api.csrf-retry.spec.ts Tightens apiService shape and normalizes casting.
fe/src/tests/api.advancedSearch.spec.ts Adjusts fetch call typing/casting.
fe/src/tests/WantedView.spec.ts Uses shared delay helper; adjusts store typing casts.
fe/src/tests/SettingsView.spec.ts Refactors to shared mount helpers and introduces mocked auth store.
fe/src/tests/SearchResultCard.spec.ts Adjusts casting style for tests.
fe/src/tests/RootFoldersSettings.spec.ts Uses deferred + flush helpers; normalizes API spy typing.
fe/src/tests/RenamePreviewModal.spec.ts Adds modal stubs and local API mock for test stability.
fe/src/tests/QualityProfilesTab.spec.ts Uses vi.doMock + flush helper; adds base stubs.
fe/src/tests/NotificationsTab.spec.ts Adds modal stubs; normalizes casts.
fe/src/tests/ManualSearchModal.spec.ts Centralizes modal stubs; swaps ad-hoc waits for shared delay helper.
fe/src/tests/LibraryImportSearchModal.spec.ts Adds modal stubs and uses shared flush helper.
fe/src/tests/LibraryImportFooter.spec.ts Uses shared flush helper and normalizes casts.
fe/src/tests/IndexersTab.spec.ts Adds modal stubs + flush helper; normalizes vi.doMock typing.
fe/src/tests/IndexerFormModal.spec.ts Adjusts casting style for tests.
fe/src/tests/EditAudiobookModal.relativePath.spec.ts Uses shared delay helper; simplifies casts.
fe/src/tests/EditAudiobookModal.moveOptions.spec.ts Adds modal stubs and replaces sleeps with shared delay helper.
fe/src/tests/DownloadsView.spec.ts Uses shared delay helper.
fe/src/tests/DownloadClientsTab.spec.ts Uses factory helper; normalizes vi.doMock typing/casts.
fe/src/tests/DownloadClientFormModal.spec.ts Switches to hoisted API mock and adds modal stubs.
fe/src/tests/CollectionView.spec.ts Uses shared flush helper; normalizes global stubs and casts.
fe/src/tests/AudiobooksView.spec.ts Adds explicit browser/storage mocks; improves cleanup across tests.
fe/src/tests/AudiobookDetailView.spec.ts Uses shared delay/flush helpers; normalizes casts.
fe/src/tests/AppActivityBadge.spec.ts Uses shared delay helper; normalizes casts.
fe/src/tests/ApiKeyControl.spec.ts Uses shared flush helper; normalizes navigator clipboard mocking.
fe/src/tests/AddNewView.spec.ts Adds explicit API/SignalR mocks; uses storage + delay helpers.
fe/src/tests/AddLibraryModal.relativePath.spec.ts Adds modal stubs and uses shared delay helper.
fe/src/tests/AddLibraryModal.editableMetadata.spec.ts Adds modal stubs for consistent modal rendering.
fe/src/tests/AddLibraryModal.accessibility.spec.ts Adds modal stubs and uses shared flush helper.
fe/src/tests/ActivityView.spec.ts Uses shared flush helper; normalizes interval mock typing.
fe/src/tests/ActivityView.mobile.spec.ts Uses shared delay helper; normalizes interval mock typing.
fe/scripts/check-test-structure.mjs Adds a guard script enforcing colocated tests and config rules.
fe/package.json Adds frontend verify gate, coverage script, structure lint, and Vitest project runs.
fe/eslint.config.ts Updates Vitest lint file globs and relaxes no-explicit-any for tests.
fe/cypress/support/api.ts Adds apiPath + shared app shell API stubs for e2e tests.
fe/cypress/e2e/settings.cy.ts Updates Settings e2e stubs to version-aware API paths and current UI fields.
fe/cypress/e2e/settings-root-folders.cy.ts Updates Root Folders e2e to version-aware API paths.
fe/cypress/e2e/move-flow.cy.ts Updates move flow e2e to version-aware API paths.
fe/cypress/e2e/hardlink-move-flow.cy.ts Updates hardlink/copy move flow e2e to version-aware API paths.
fe/cypress/e2e/file-naming-patterns.cy.ts Updates file naming e2e coverage to version-aware API paths.
fe/cypress.config.ts Aligns Cypress baseUrl to port 4173 (matches e2e scripts).
fe/README.md Updates documentation for Vitest projects and the frontend verify script.
fe/.vscode/settings.json Removes Playwright nesting references and updates config nesting.
fe/.gitignore Updates ignored tooling outputs (eslint report) in frontend.
CONTRIBUTING.md Updates contributor instructions to run the new frontend verification gate.
.husky/pre-push Runs version sync + backend format + FE typecheck + FE tests with Node PATH workaround.
.husky/pre-commit Replaces npm wrapper invocation with node script + adds enforcement checks.
.gitignore Updates ignored tooling outputs (eslint report) at repo root.
Files not reviewed (1)
  • fe/package-lock.json: Language not supported
Comments suppressed due to low confidence (2)

fe/src/test/utils/storage.ts:1

  • installStorageMock() references window unconditionally, which will throw a ReferenceError if this helper is ever imported/used from a node-environment Vitest project (unit-node). Guard these Object.defineProperty(window, ...) calls behind a typeof window !== 'undefined' check (and rely on vi.stubGlobal for non-DOM environments), so the helper is safe in both runtimes.
    fe/src/test/utils/mount.ts:1
  • Swallowing router.isReady() failures makes test failures harder to debug and can mask navigation/setup problems (tests may proceed with a router that isn’t actually ready). Prefer letting the rejection propagate, or rethrow with additional context so failures are actionable.

Comment on lines +28 to +30
if (fs.existsSync(path.join(srcRoot, '__tests__'))) {
failures.push('src/__tests__ must not exist; colocate tests in src/**/test/.')
}
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 93c7c1bd64

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .husky/pre-push
fi

echo "Syncing version..."
node scripts/sync-fe-version-from-csproj.mjs
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Stop push when version sync mutates tracked files

Running node scripts/sync-fe-version-from-csproj.mjs inside the pre-push hook can rewrite package.json/lockfiles, but the hook continues without checking for new diffs. When versions are out of sync, this means the push sends commits that were not validated against the exact files being pushed, and it also leaves the developer’s worktree dirty after a successful push. The hook should fail (or require recommit) if sync changes tracked files so the validated content matches the pushed commit.

Useful? React with 👍 / 👎.

Add esbuild@0.28.0 to fe/package.json as a dev dependency.
Remove esbuild from front-end dependencies and update Vite config to use the 'oxc' minifier. Add production minification options (drop console/debugger, mangle and codegen) via Rollup output config and keep sourcemaps enabled for bundle analysis. Also tidy the visualizer plugin cast/comment to avoid TypeScript signature mismatches.
Introduce a reusable SignalR test mock and an opt-in Vitest setup file for SignalR. Adds src/test/mocks/signalr.ts with a callback registry, emit/reset helpers and a signalRServiceMock, and a setup file src/test/setup/signalr.ts that auto-mocks the real service and resets the mock after each test. Update a spec to use the new mock (remove manual spy/callback plumbing), add the setup file to vitest.config.ts, and extend the test README to document the allowed global mock and guidelines. Also tighten check-test-structure.mjs to only permit the specific setup file and to allow only that setupFiles config, and add a few asset/font entries to .gitignore.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch patch version bump - backward compatible bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants