Skip to content

Chore: test exec speedup#267

Merged
HardMax71 merged 8 commits intomainfrom
chore/test-exec-speedup
Mar 5, 2026
Merged

Chore: test exec speedup#267
HardMax71 merged 8 commits intomainfrom
chore/test-exec-speedup

Conversation

@HardMax71
Copy link
Copy Markdown
Owner

@HardMax71 HardMax71 commented Mar 5, 2026


Summary by cubic

Speed up CI test runs by parallelizing E2E setup and cutting Python env syncs. Frontend tests now run on happy-dom with isolation, centralized mocks, and cleaner select/checkbox binding.

  • Refactors
    • e2e-boot pre-pulls executor images and Kueue manifest in background; e2e-ready verifies manifest SHA256 with timeout, waits on background PIDs, can skip Kueue install, waits for image pulls, and health checks poll every 1s.
    • Workflows use uv run --no-sync for pytest, ruff, and mypy; mypy sync includes the test group for test-only deps.
    • Vitest uses happy-dom, re-enables test isolation, tunes worker counts for CI, trims optimizer deps, and drops jsdom.
    • Centralized frontend test mocks in setup; added mockApi and selectOption helpers; tests use path aliases. Pagination and AutoRefreshControl bind values; onPageSizeChange has no argument and admin pages reset to page 1. Removed redundant test comments.

Written for commit 6775931. Summary will update on new commits.

Summary by CodeRabbit

  • Chores

    • Faster, more reliable CI/E2E: background pre-pulls for images/manifests, optional Kueue install flag, tightened readiness checks, reduced health-check intervals, and workflow command invocation tweaks.
  • New Features

    • Pagination now supports two-way page-size binding; page-size change callback is parameterless and handlers reset to page 1.
  • Tests

    • Test suite migrated to happy-dom; unified mocking utilities (central mockApi and selectOption), broader global test setup and storage/observer polyfills, and removed many local toast spies.

Copilot AI review requested due to automatic review settings March 5, 2026 12:38
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds background pre-pull tasks for Kueue manifests and executor images in the E2E boot action, introduces an install-kueue toggle and readiness checks in e2e-ready, prepends --no-sync to several CI commands, switches frontend tests to happy-dom with new test utilities (mockApi, selectOption), and changes Pagination to use two-way binding.

Changes

Cohort / File(s) Summary
E2E actions
/.github/actions/e2e-boot/action.yml, /.github/actions/e2e-ready/action.yml
e2e-boot starts concurrent nohup background tasks to download Kueue manifests and pre-pull images (writes PIDs and exit codes). e2e-ready adds install-kueue input, tighter shell error handling, readiness checks that tail logs/read exit files, and moves config prep earlier.
Workflows & CI invocations
/.github/workflows/grimp.yml, /.github/workflows/mypy.yml, /.github/workflows/ruff.yml, /.github/workflows/stack-tests.yml
Prepends --no-sync to uv run invocations and pytest; replaces some uses: with named steps and sets install-kueue: 'false' for final e2e-ready calls.
Test runtime & config
frontend/vitest.config.ts, frontend/vitest.setup.ts, frontend/package.json
Switches vitest environment from jsdomhappy-dom, adjusts worker sizing/coverage reporters, removes dynamic pkg import/fakeTimers, and adds extensive global polyfills/mocks for tests. Adds happy-dom dependency.
Test utilities & many tests
frontend/src/__tests__/test-utils.ts, frontend/src/.../__tests__/*
Adds mockApi(...) and selectOption(...) helpers; consolidates API mocking via mockApi and vi.mocked(...), standardizes alias imports, and updates many tests to use new helpers and shapes.
Pagination & consuming routes
frontend/src/components/Pagination.svelte, frontend/src/routes/admin/...
Pagination now exposes bindable pageSize (uses bind:value); onPageSizeChange becomes parameterless. Admin routes switch to bind:pageSize and update handlers to reset page and reload data.
Component bindings refactor
frontend/src/components/admin/AutoRefreshControl.svelte
Replaces manual event handlers with Svelte two-way bindings (bind:checked, bind:value) and inline onchange callbacks; removes parse logic and simplifies state flow.
Tests: path aliasing & small edits
many frontend/src/components/**/__tests__/*, frontend/src/routes/**/__tests__/*, frontend/src/lib/**/__tests__/*
Standardizes test import paths to aliases, removes many inline router/toast spies, updates expectations to use vi.mocked(...), and adapts tests to the new helpers and data shapes.

Sequence Diagram(s)

sequenceDiagram
  participant Runner as GitHub Actions Runner
  participant Boot as e2e-boot Action
  participant Net as Manifest Server
  participant K3s as k3s/crictl
  participant FS as Filesystem (/tmp)

  Runner->>Boot: start e2e-boot
  Boot->>Net: nohup download Kueue manifest -> /tmp/kueue-manifests.yaml
  Boot->>K3s: nohup pull python:3.11-slim
  Boot->>K3s: nohup pull busybox:1.36
  Boot->>FS: write PIDs and redirect logs, record exit codes to /tmp/*.exit
  Note right of FS: background tasks run independently
  Runner->>Runner: continue workflow
  Runner->>FS: e2e-ready tails logs and checks PIDs/exit files
  alt all background tasks succeeded
    Runner->>Runner: apply manifests / start services
  else any task failed
    Runner->>Runner: fail workflow
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
I nibbled manifests through the night,
pulled images snug in soft moonlight,
PIDs tucked in /tmp, logs warm and bright,
nohup hummed — CI hopped into flight,
now tests can dance at morning light.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'Chore: test exec speedup' accurately reflects the main objective of the changeset: optimizing test execution through e2e setup parallelization, environment sync reduction, and frontend test infrastructure improvements.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/test-exec-speedup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 5, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 84.61538% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
frontend/src/routes/admin/AdminExecutions.svelte 33.33% 2 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Flag Coverage Δ
backend-e2e 83.22% <ø> (+0.01%) ⬆️
backend-unit 67.91% <ø> (ø)
frontend-unit 86.51% <84.61%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
frontend/src/components/Pagination.svelte 89.65% <100.00%> (+3.94%) ⬆️
...end/src/components/admin/AutoRefreshControl.svelte 95.00% <100.00%> (+4.09%) ⬆️
frontend/src/routes/admin/AdminSagas.svelte 91.07% <100.00%> (+0.16%) ⬆️
frontend/src/routes/admin/AdminUsers.svelte 83.01% <ø> (+0.41%) ⬆️
frontend/src/routes/admin/AdminExecutions.svelte 80.20% <33.33%> (-0.85%) ⬇️

... and 1 file with indirect coverage changes

Components Coverage Δ
Backend 90.07% <ø> (ø)
Frontend 86.51% <84.61%> (+0.02%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

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

This PR optimizes CI execution time by reducing redundant uv syncing during Python checks and by overlapping slow E2E setup work (Kueue manifest download + image pulls) in the background.

Changes:

  • Use uv run --no-sync in unit tests and lint/typecheck workflows to avoid re-syncing after uv sync.
  • Speed up/parallelize E2E environment preparation by moving Kueue manifest download + executor image pre-pulls into e2e-boot and gating Kueue install via a new install-kueue input.
  • Add step names and minor wait-loop tuning (sleep 2s → 1s) for faster readiness checks.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
.github/workflows/stack-tests.yml Uses --no-sync, names E2E steps, and disables Kueue install for frontend E2E shards
.github/workflows/ruff.yml Uses uv run --no-sync for ruff
.github/workflows/mypy.yml Uses uv run --no-sync for mypy
.github/workflows/grimp.yml Uses uv run --no-sync for grimp script
.github/actions/e2e-boot/action.yml Adds background prefetch of Kueue manifest and executor runtime images
.github/actions/e2e-ready/action.yml Adds install-kueue input; waits for background prefetch and makes Kueue install conditional

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/actions/e2e-boot/action.yml
Comment thread .github/actions/e2e-ready/action.yml Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/actions/e2e-ready/action.yml:
- Around line 43-46: The background wait using `tail --pid="$(cat
/tmp/kueue-download.pid)" -f /dev/null` must be bounded to avoid hung CI; wrap
that call with a timeout (e.g. `timeout 300s`) so the wait ends after a fixed
period, and surface a clearer failure if the timeout occurs instead of silently
continuing — update the snippet that reads `/tmp/kueue-download.pid`,
`/tmp/kueue-download.log`, and checks `/tmp/kueue-download.exit` to use
`timeout` around `tail`, preserve the `|| true` where appropriate, and add an
explicit check that treats a timed-out tail as a failure (including a
descriptive message) before evaluating the exit file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7b65a731-96ce-4946-8f40-687f32c84bf1

📥 Commits

Reviewing files that changed from the base of the PR and between 666d9e1 and fabd8c9.

📒 Files selected for processing (6)
  • .github/actions/e2e-boot/action.yml
  • .github/actions/e2e-ready/action.yml
  • .github/workflows/grimp.yml
  • .github/workflows/mypy.yml
  • .github/workflows/ruff.yml
  • .github/workflows/stack-tests.yml

Comment thread .github/actions/e2e-ready/action.yml Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/actions/e2e-ready/action.yml">

<violation number="1" location=".github/actions/e2e-ready/action.yml:43">
P2: The `tail --pid=... -f /dev/null` call has no timeout. If the background kueue download process hangs, this step will block indefinitely until the job-level hard timeout is reached, wasting CI minutes. Wrap with `timeout 300` (or similar) to fail fast.</violation>

<violation number="2" location=".github/actions/e2e-ready/action.yml:84">
P2: Same unbounded `tail --pid` wait issue here — if the python image pull hangs, this blocks until the job hard timeout. Add a `timeout` wrapper to fail fast.</violation>

<violation number="3" location=".github/actions/e2e-ready/action.yml:88">
P2: Same unbounded `tail --pid` wait issue here — if the busybox image pull hangs, this blocks until the job hard timeout. Add a `timeout` wrapper to fail fast.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread .github/actions/e2e-ready/action.yml Outdated
Comment thread .github/actions/e2e-ready/action.yml Outdated
Comment thread .github/actions/e2e-ready/action.yml Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/package.json`:
- Around line 74-76: package.json currently lists "jsdom" as a devDependency but
vitest.config.ts is configured to use "happy-dom" and there are no active
imports of jsdom; remove the "jsdom" entry from devDependencies in package.json,
run your package manager to update the lockfile (npm/yarn/pnpm install) and
verify no code imports or requires reference "jsdom" (search the repo for
"jsdom" and confirm only a comment remains); update any CI or tooling configs if
they explicitly install jsdom.

In `@frontend/vitest.setup.ts`:
- Around line 92-98: Remove the HTMLSelectElement.prototype.querySelectorAll
override: delete the origQSA assignment and the entire function that replaces
querySelectorAll (the code referencing origQSA and returning
Array.from(this.options)). Keep only the existing
HTMLSelectElement.prototype.querySelector override used for ':checked' handling
(used for Svelte bind:value). Ensure no other code relies on the removed
override and that querySelectorAll behavior falls back to the native
implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0678bd6e-640b-4900-9324-4405a7276b5d

📥 Commits

Reviewing files that changed from the base of the PR and between fabd8c9 and d20bbf4.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (15)
  • .github/workflows/mypy.yml
  • frontend/package.json
  • frontend/src/__tests__/test-utils.ts
  • frontend/src/components/Pagination.svelte
  • frontend/src/components/__tests__/Pagination.test.ts
  • frontend/src/components/admin/AutoRefreshControl.svelte
  • frontend/src/routes/admin/AdminExecutions.svelte
  • frontend/src/routes/admin/AdminSagas.svelte
  • frontend/src/routes/admin/AdminUsers.svelte
  • frontend/src/routes/admin/__tests__/AdminEvents.test.ts
  • frontend/src/routes/admin/__tests__/AdminExecutions.test.ts
  • frontend/src/routes/admin/__tests__/AdminSagas.test.ts
  • frontend/src/routes/admin/__tests__/AdminUsers.test.ts
  • frontend/vitest.config.ts
  • frontend/vitest.setup.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/mypy.yml

Comment thread frontend/package.json Outdated
Comment thread frontend/vitest.setup.ts Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 28 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="frontend/src/lib/notifications/__tests__/stream.test.ts">

<violation number="1" location="frontend/src/lib/notifications/__tests__/stream.test.ts:8">
P2: `vi.mocked` does not mock the API function; without `vi.mock`/`vi.spyOn`, `mockImplementation` will be undefined and the test will fail or call the real API. Add an explicit mock or spy for `$lib/api` before using `mockImplementation`.</violation>
</file>

<file name="frontend/src/routes/__tests__/Login.test.ts">

<violation number="1" location="frontend/src/routes/__tests__/Login.test.ts:95">
P2: `getErrorMessage` is no longer mocked, so `vi.mocked(getErrorMessage).mockReturnValue(...)` will fail because it’s a real function. Restore a module mock or spy on the module function before using mockReturnValue.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread frontend/src/lib/notifications/__tests__/stream.test.ts
Comment thread frontend/src/routes/__tests__/Login.test.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/src/lib/notifications/__tests__/stream.test.ts (1)

54-62: ⚠️ Potential issue | 🟡 Minor

Add required test hook hygiene: vi.clearAllMocks() and cleanup().

The file is missing the required beforeEach/afterEach cleanup pattern, which can cause test state leakage.

Suggested patch
+import { cleanup } from '@testing-library/svelte';
 import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
@@
     beforeEach(() => {
+        vi.clearAllMocks();
         callback = vi.fn();
         mockSseFn.mockReset();
         notificationStream.disconnect();
     });
 
     afterEach(() => {
+        cleanup();
         vi.unstubAllGlobals();
     });

Per coding guidelines: "Call cleanup() in Vitest afterEach, vi.clearAllMocks() in beforeEach".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/lib/notifications/__tests__/stream.test.ts` around lines 54 -
62, Add the missing test-hygiene calls: in the existing beforeEach (where
callback, mockSseFn.mockReset and notificationStream.disconnect are already
called) add vi.clearAllMocks() to reset mocks before each test; in the existing
afterEach (which currently calls vi.unstubAllGlobals()) call cleanup() as well
to unmount DOM between tests (import cleanup from the appropriate testing
library, e.g., '@testing-library/svelte'). Reference the existing
beforeEach/afterEach blocks and the symbols callback, mockSseFn,
notificationStream.disconnect, and vi.unstubAllGlobals when making the change.
frontend/src/routes/__tests__/Settings.test.ts (1)

7-31: ⚠️ Potential issue | 🟡 Minor

Mock data missing created_at and updated_at fields.

According to the UserSettings type from types.gen.ts, the mock is missing required created_at and updated_at string fields. If the component accesses these fields, tests may behave unexpectedly.

Proposed fix
 function createMockSettings() {
     return {
         user_id: 'user-1',
         theme: 'dark',
         timezone: 'UTC',
         date_format: 'YYYY-MM-DD',
         time_format: '24h',
         notifications: {
             execution_completed: true,
             execution_failed: false,
             system_updates: true,
             security_alerts: false,
             channels: ['in_app'],
         },
         editor: {
             font_size: 16,
             tab_size: 2,
             use_tabs: true,
             word_wrap: false,
             show_line_numbers: true,
         },
         custom_settings: {},
         version: 1,
+        created_at: '2024-01-01T00:00:00Z',
+        updated_at: '2024-01-01T00:00:00Z',
     };
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/routes/__tests__/Settings.test.ts` around lines 7 - 31, The mock
returned by createMockSettings does not include the required created_at and
updated_at string fields from the UserSettings type; update the
createMockSettings function to add created_at and updated_at (use valid ISO
timestamp strings, e.g. new Date().toISOString() or fixed ISO strings) so the
mock matches UserSettings and tests that access those properties won't fail.
🧹 Nitpick comments (5)
frontend/src/stores/__tests__/auth.test.ts (1)

4-26: Path aliases correctly applied.

The mock paths now use $lib/api, $stores/userSettings.svelte, and $lib/user-settings, matching the actual imports in auth.svelte.ts and the Vitest alias configuration.

One optional refinement: the coding guidelines recommend using vi.hoisted() for mock function variables that are referenced inside vi.mock() factories. This ensures deterministic hoisting behavior.

,

♻️ Optional: Use vi.hoisted() pattern
+const { mockLoginApi, mockLogoutApi, mockGetProfileApi } = vi.hoisted(() => ({
+    mockLoginApi: vi.fn(),
+    mockLogoutApi: vi.fn(),
+    mockGetProfileApi: vi.fn(),
+}));
-const mockLoginApi = vi.fn();
-const mockLogoutApi = vi.fn();
-const mockGetProfileApi = vi.fn();

 vi.mock('$lib/api', () => ({
     loginApiV1AuthLoginPost: (...args: unknown[]) => mockLoginApi(...args),
     logoutApiV1AuthLogoutPost: (...args: unknown[]) => mockLogoutApi(...args),
     getCurrentUserProfileApiV1AuthMeGet: (...args: unknown[]) => mockGetProfileApi(...args),
 }));

+const { mockClearUserSettings } = vi.hoisted(() => ({
+    mockClearUserSettings: vi.fn(),
+}));
-const mockClearUserSettings = vi.fn();

 vi.mock('$stores/userSettings.svelte', () => ({
     clearUserSettings: () => mockClearUserSettings(),
     setUserSettings: vi.fn(),
     userSettingsStore: { settings: null, editorSettings: {} },
 }));

+const { mockLoadUserSettings } = vi.hoisted(() => ({
+    mockLoadUserSettings: vi.fn(),
+}));
-const mockLoadUserSettings = vi.fn();

 vi.mock('$lib/user-settings', () => ({
     loadUserSettings: () => mockLoadUserSettings(),
 }));

As per coding guidelines: "Frontend Vitest tests must hoist mocks with vi.hoisted() before vi.mock() declarations".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/stores/__tests__/auth.test.ts` around lines 4 - 26, Replace the
plain vi.fn() mock declarations with hoisted mocks so Vitest deterministically
hoists them before the vi.mock factories: change mockLoginApi, mockLogoutApi,
mockGetProfileApi, mockClearUserSettings and mockLoadUserSettings to be created
via vi.hoisted(() => vi.fn()) and keep using those symbols inside the existing
vi.mock(...) factories (loginApiV1AuthLoginPost, logoutApiV1AuthLogoutPost,
getCurrentUserProfileApiV1AuthMeGet, clearUserSettings, loadUserSettings) so the
mocks are hoisted correctly.
frontend/src/lib/editor/__tests__/execution.test.ts (1)

30-34: Consider adding cleanup() in afterEach for consistency.

The coding guidelines specify calling cleanup() in Vitest afterEach for test files in this path. While this test file doesn't render Svelte components (so cleanup isn't strictly necessary here), adding it maintains consistency across the test suite and future-proofs against component rendering being added later.

♻️ Optional: Add afterEach with cleanup
+import { cleanup } from '@testing-library/svelte';
+import { afterEach } from 'vitest';
+
 // ... existing imports ...

 describe('createExecutionState', () => {
     beforeEach(() => {
         mockCreateExecution.mockReset();
         mockSseFn.mockReset();
     });
+
+    afterEach(() => {
+        cleanup();
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/lib/editor/__tests__/execution.test.ts` around lines 30 - 34,
Add an afterEach that calls cleanup() alongside the existing mock resets to
follow the Vitest guideline; in the describe block for "createExecutionState"
add an afterEach that invokes cleanup() (and you may also reset mocks there or
keep the existing beforeEach mockReset calls) so the test file calls cleanup()
for future Svelte component rendering and consistency with the test suite.
frontend/src/__tests__/test-utils.ts (1)

36-37: Remove redundant type assertion.

The as ReturnType<typeof vi.fn> assertion is unnecessary since vi.mocked(fn) already returns the correct mock type. This was flagged by static analysis.

Proposed fix
 export function mockApi(fn: (...args: any[]) => any) {
-    const mock = vi.mocked(fn) as ReturnType<typeof vi.fn>;
+    const mock = vi.mocked(fn);
     return {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/__tests__/test-utils.ts` around lines 36 - 37, The current
mockApi implementation uses a redundant type assertion on the mocked function;
update the line in mockApi so that it simply assigns vi.mocked(fn) to mock
(i.e., use const mock = vi.mocked(fn);) and remove the trailing "as
ReturnType<typeof vi.fn>" cast so the inferred mock type from vi.mocked is used
(refer to the mockApi function and vi.mocked usage).
frontend/vitest.setup.ts (1)

47-48: Use for...of loop instead of forEach with delete.

The delete expression returns a value, which triggers the Biome lint warning about returning values from forEach callbacks. Using a for...of loop is cleaner.

Proposed fix
     clear: vi.fn(() => {
-        Object.keys(localStorageStore).forEach((key) => delete localStorageStore[key]);
+        for (const key of Object.keys(localStorageStore)) {
+            delete localStorageStore[key];
+        }
     }),

Apply the same pattern to sessionStorageMock.clear (line 68) and the beforeEach cleanup (lines 181-182).

Also applies to: 67-68, 181-182

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/vitest.setup.ts` around lines 47 - 48, Replace the forEach + delete
pattern with a for...of loop to avoid returning values from the callback: in
localStorageMock.clear (the clear: vi.fn(...) that iterates
Object.keys(localStorageStore)), change to iterating
Object.keys(localStorageStore) with for (const key of ...) and delete
localStorageStore[key]; do the same update for sessionStorageMock.clear and the
beforeEach cleanup block that currently uses Object.keys(...).forEach(...) so
each key is deleted inside a for...of loop.
frontend/src/lib/__tests__/user-settings.test.ts (1)

51-53: Add cleanup() call in afterEach.

Per coding guidelines, cleanup() should be called in afterEach to ensure proper DOM cleanup between tests.

Proposed fix
+import { cleanup } from '@testing-library/svelte';
+
 import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
     afterEach(() => {
         vi.restoreAllMocks();
+        cleanup();
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/lib/__tests__/user-settings.test.ts` around lines 51 - 53, The
tests in user-settings.test.ts currently call vi.restoreAllMocks() in afterEach
but omit DOM cleanup; update the afterEach block to call cleanup() as well
(e.g., afterEach(() => { cleanup(); vi.restoreAllMocks(); })), and ensure the
testing library's cleanup function is imported (import { cleanup } from
'@testing-library/svelte' or the project's testing-library wrapper) so cleanup()
is available; reference the existing afterEach and the cleanup symbol when
making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/lib/notifications/__tests__/stream.test.ts`:
- Line 8: Add missing test lifecycle cleanup calls: inside the beforeEach block
(where callback = vi.fn() is set) call vi.clearAllMocks() to reset mocks like
mockSseFn/notificationStreamApiV1EventsNotificationsStreamGet, and inside the
afterEach block (after vi.unstubAllGlobals()) call cleanup() to unmount DOM
state; ensure these calls are placed in the existing beforeEach/afterEach
functions so test hygiene is preserved.

In `@frontend/src/routes/admin/__tests__/AdminEvents.test.ts`:
- Around line 88-91: The mock implementations for
browseEventsApiV1AdminEventsBrowsePost (and the other similar mocks) are
directly calling toast.error(...) inside the mock; instead they should only
return an error response so the global API interceptor shows the toast. Replace
the mockImplementation that invokes toast with one that returns an error-shaped
response (use the shared test helper pattern mockApi(...).err() or return {
data: null, error: <ErrorLike> } ) for browseEventsApiV1AdminEventsBrowsePost
and the other affected mocks so component error handling and the global
interceptor drive toast/display behavior rather than the mock itself.

In `@frontend/src/routes/admin/__tests__/AdminExecutions.test.ts`:
- Around line 18-21: Wrap the existing vi.mock(...) call that returns
MockAdminLayout.svelte inside a vi.hoisted() block so the mock is hoisted before
component imports; specifically, replace the standalone vi.mock for
'$routes/admin/AdminLayout.svelte' with a vi.hoisted(() => {
vi.mock('$routes/admin/AdminLayout.svelte', async () => { const { default:
MockLayout } = await
import('$routes/admin/__tests__/mocks/MockAdminLayout.svelte'); return {
default: MockLayout }; }); }); ensuring the vi.hoisted call surrounds the
vi.mock declaration for proper hoisting.

In `@frontend/src/routes/admin/__tests__/AdminSagas.test.ts`:
- Around line 7-10: The vi.mock call registering the AdminLayout mock needs to
be hoisted: wrap the existing vi.mock('$routes/admin/AdminLayout.svelte', ...)
invocation inside vi.hoisted(() => { ... }) so Vitest hoists the mock; keep the
same async import of '$routes/admin/__tests__/mocks/MockAdminLayout.svelte' and
return { default: MockLayout } inside the hoisted callback, preserving the
module string and mock behavior.

In `@frontend/src/routes/admin/__tests__/AdminUsers.test.ts`:
- Around line 16-24: The vi.mock() declarations for the formatter and
AdminLayout are not hoisted; wrap them using vi.hoisted so the mocks evaluate at
module load time: create hoisted mock objects for formatTimestamp and for the
AdminLayout import (referencing formatTimestamp and
AdminLayout/MockAdminLayout.svelte) and then pass those hoisted objects into
vi.mock() calls instead of the current inline factories (i.e., replace the
current vi.mock('$lib/formatters', ...) and
vi.mock('$routes/admin/AdminLayout.svelte', ...) with hoisted versions so mocks
run before imports and component rendering).
- Around line 50-53: The test mocks (e.g.,
vi.mocked(listUsersApiV1AdminUsersGet)) are calling toast.error inside the mock
which short-circuits the component's own error handling; change each mock
implementation to simply return an error-shaped response (e.g., { data: null,
error: ... }) and remove any toast.error calls so the component's unwrap() path
can run and trigger toasts itself; update all similar mocks (the ones around the
other indicated blocks) to follow this pattern and assert the
component-triggered toast instead of the mock doing it.

---

Outside diff comments:
In `@frontend/src/lib/notifications/__tests__/stream.test.ts`:
- Around line 54-62: Add the missing test-hygiene calls: in the existing
beforeEach (where callback, mockSseFn.mockReset and
notificationStream.disconnect are already called) add vi.clearAllMocks() to
reset mocks before each test; in the existing afterEach (which currently calls
vi.unstubAllGlobals()) call cleanup() as well to unmount DOM between tests
(import cleanup from the appropriate testing library, e.g.,
'@testing-library/svelte'). Reference the existing beforeEach/afterEach blocks
and the symbols callback, mockSseFn, notificationStream.disconnect, and
vi.unstubAllGlobals when making the change.

In `@frontend/src/routes/__tests__/Settings.test.ts`:
- Around line 7-31: The mock returned by createMockSettings does not include the
required created_at and updated_at string fields from the UserSettings type;
update the createMockSettings function to add created_at and updated_at (use
valid ISO timestamp strings, e.g. new Date().toISOString() or fixed ISO strings)
so the mock matches UserSettings and tests that access those properties won't
fail.

---

Nitpick comments:
In `@frontend/src/__tests__/test-utils.ts`:
- Around line 36-37: The current mockApi implementation uses a redundant type
assertion on the mocked function; update the line in mockApi so that it simply
assigns vi.mocked(fn) to mock (i.e., use const mock = vi.mocked(fn);) and remove
the trailing "as ReturnType<typeof vi.fn>" cast so the inferred mock type from
vi.mocked is used (refer to the mockApi function and vi.mocked usage).

In `@frontend/src/lib/__tests__/user-settings.test.ts`:
- Around line 51-53: The tests in user-settings.test.ts currently call
vi.restoreAllMocks() in afterEach but omit DOM cleanup; update the afterEach
block to call cleanup() as well (e.g., afterEach(() => { cleanup();
vi.restoreAllMocks(); })), and ensure the testing library's cleanup function is
imported (import { cleanup } from '@testing-library/svelte' or the project's
testing-library wrapper) so cleanup() is available; reference the existing
afterEach and the cleanup symbol when making this change.

In `@frontend/src/lib/editor/__tests__/execution.test.ts`:
- Around line 30-34: Add an afterEach that calls cleanup() alongside the
existing mock resets to follow the Vitest guideline; in the describe block for
"createExecutionState" add an afterEach that invokes cleanup() (and you may also
reset mocks there or keep the existing beforeEach mockReset calls) so the test
file calls cleanup() for future Svelte component rendering and consistency with
the test suite.

In `@frontend/src/stores/__tests__/auth.test.ts`:
- Around line 4-26: Replace the plain vi.fn() mock declarations with hoisted
mocks so Vitest deterministically hoists them before the vi.mock factories:
change mockLoginApi, mockLogoutApi, mockGetProfileApi, mockClearUserSettings and
mockLoadUserSettings to be created via vi.hoisted(() => vi.fn()) and keep using
those symbols inside the existing vi.mock(...) factories
(loginApiV1AuthLoginPost, logoutApiV1AuthLogoutPost,
getCurrentUserProfileApiV1AuthMeGet, clearUserSettings, loadUserSettings) so the
mocks are hoisted correctly.

In `@frontend/vitest.setup.ts`:
- Around line 47-48: Replace the forEach + delete pattern with a for...of loop
to avoid returning values from the callback: in localStorageMock.clear (the
clear: vi.fn(...) that iterates Object.keys(localStorageStore)), change to
iterating Object.keys(localStorageStore) with for (const key of ...) and delete
localStorageStore[key]; do the same update for sessionStorageMock.clear and the
beforeEach cleanup block that currently uses Object.keys(...).forEach(...) so
each key is deleted inside a for...of loop.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: be7917fd-c04b-4e8e-8498-0cdc1dfa2233

📥 Commits

Reviewing files that changed from the base of the PR and between d20bbf4 and 14cb2cf.

📒 Files selected for processing (28)
  • frontend/src/__tests__/test-utils.ts
  • frontend/src/components/__tests__/Header.test.ts
  • frontend/src/components/__tests__/NotificationCenter.test.ts
  • frontend/src/components/admin/users/__tests__/RateLimitsModal.test.ts
  • frontend/src/components/editor/__tests__/OutputPanel.test.ts
  • frontend/src/lib/__tests__/api-interceptors.test.ts
  • frontend/src/lib/__tests__/user-settings.test.ts
  • frontend/src/lib/admin/__tests__/pagination.test.ts
  • frontend/src/lib/admin/stores/__tests__/eventsStore.test.ts
  • frontend/src/lib/admin/stores/__tests__/executionsStore.test.ts
  • frontend/src/lib/admin/stores/__tests__/sagasStore.test.ts
  • frontend/src/lib/editor/__tests__/execution.test.ts
  • frontend/src/lib/notifications/__tests__/stream.test.ts
  • frontend/src/routes/__tests__/Editor.test.ts
  • frontend/src/routes/__tests__/Home.test.ts
  • frontend/src/routes/__tests__/Login.test.ts
  • frontend/src/routes/__tests__/Notifications.test.ts
  • frontend/src/routes/__tests__/Register.test.ts
  • frontend/src/routes/__tests__/Settings.test.ts
  • frontend/src/routes/admin/__tests__/AdminEvents.test.ts
  • frontend/src/routes/admin/__tests__/AdminExecutions.test.ts
  • frontend/src/routes/admin/__tests__/AdminLayout.test.ts
  • frontend/src/routes/admin/__tests__/AdminSagas.test.ts
  • frontend/src/routes/admin/__tests__/AdminSettings.test.ts
  • frontend/src/routes/admin/__tests__/AdminUsers.test.ts
  • frontend/src/stores/__tests__/auth.test.ts
  • frontend/src/stores/__tests__/theme.test.ts
  • frontend/vitest.setup.ts
💤 Files with no reviewable changes (4)
  • frontend/src/components/editor/tests/OutputPanel.test.ts
  • frontend/src/routes/tests/Home.test.ts
  • frontend/src/routes/admin/tests/AdminLayout.test.ts
  • frontend/src/routes/tests/Notifications.test.ts
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/lib/admin/tests/pagination.test.ts

Comment thread frontend/src/lib/notifications/__tests__/stream.test.ts
Comment thread frontend/src/routes/admin/__tests__/AdminEvents.test.ts
Comment thread frontend/src/routes/admin/__tests__/AdminExecutions.test.ts
Comment thread frontend/src/routes/admin/__tests__/AdminSagas.test.ts
Comment thread frontend/src/routes/admin/__tests__/AdminUsers.test.ts
Comment thread frontend/src/routes/admin/__tests__/AdminUsers.test.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/stores/__tests__/theme.test.ts (1)

3-11: ⚠️ Potential issue | 🟡 Minor

Hoist mock handles with vi.hoisted() before vi.mock().

Lines 3-11 declare mocks directly in vi.mock() factories. Per the required testing patterns, mocks must be created in a hoisted block first, then referenced from vi.mock().

Proposed fix
+const mocks = vi.hoisted(() => ({
+    saveUserSettings: vi.fn().mockResolvedValue(true),
+    authStore: {
+        isAuthenticated: false,
+    },
+}));
+
 vi.mock('$lib/user-settings', () => ({
-    saveUserSettings: vi.fn().mockResolvedValue(true),
+    saveUserSettings: mocks.saveUserSettings,
 }));
 
 vi.mock('$stores/auth.svelte', () => ({
-    authStore: {
-        isAuthenticated: false,
-    },
+    authStore: mocks.authStore,
 }));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/stores/__tests__/theme.test.ts` around lines 3 - 11, The tests
currently define mock implementations inline inside vi.mock factories for
saveUserSettings and authStore; instead, create hoisted mock handles using
vi.hoisted() (e.g., const saveUserSettingsMock = vi.hoisted(() =>
vi.fn().mockResolvedValue(true)) and const authStoreMock = vi.hoisted(() => ({
authStore: { isAuthenticated: false } }))) and then reference those handles
inside vi.mock factories (vi.mock('$lib/user-settings', () => ({
saveUserSettings: saveUserSettingsMock })) and vi.mock('$stores/auth.svelte', ()
=> authStoreMock)); update the references in theme.test.ts to use these hoisted
handles so mocks are created before imports.
♻️ Duplicate comments (1)
.github/actions/e2e-ready/action.yml (1)

43-46: ⚠️ Potential issue | 🟠 Major

Timeout outcomes are still masked by || true, making hang failures opaque.

On Line 43, Line 84, Line 88, and Line 98, timeout ... tail ... || true hides whether the wait timed out (exit 124). The step then fails later via exit-file checks, but without a clear timeout error source.

🔧 Suggested pattern (apply to each wait block)
-        timeout 120 tail --pid="$(cat /tmp/kueue-download.pid)" -f /dev/null 2>/dev/null || true
+        if ! timeout 120 tail --pid="$(cat /tmp/kueue-download.pid)" -f /dev/null 2>/dev/null; then
+          echo "::error::Timed out waiting for kueue download background task"
+          exit 1
+        fi
         cat /tmp/kueue-download.log 2>/dev/null || true
         [ "$(cat /tmp/kueue-download.exit)" = "0" ]

Use this script to confirm all masked timeout sites before patching:

#!/bin/bash
set -euo pipefail
rg -n -C1 'timeout\s+120\s+tail\s+--pid=.*\|\|\s*true' .github/actions/e2e-ready/action.yml

Expected result: matches on the current wait blocks (kueue/crictl/infra), which should be replaced with explicit timeout handling.

Also applies to: 84-90, 98-100

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/actions/e2e-ready/action.yml around lines 43 - 46, The wait blocks
use the pattern "timeout 120 tail --pid=... -f /dev/null || true" which masks
timeout exit code 124; update each such block (the kueue/crictl/infra wait
invocations and the ones that touch "/tmp/kueue-download.exit" etc.) to remove
the unconditional "|| true", capture the timeout command's exit status, and
explicitly handle a 124 timeout by logging a clear timeout error and propagating
a non-zero exit (and/or writing the appropriate exit file) so the pipeline fails
with an explicit timeout instead of being masked; ensure the new logic still
preserves existing successful-wait behavior.
🧹 Nitpick comments (5)
frontend/src/stores/__tests__/auth.test.ts (2)

42-63: Move vi.clearAllMocks() from afterEach to beforeEach.

The coding guidelines specify calling vi.clearAllMocks() in beforeEach, not afterEach. This ensures a clean state before each test runs.

♻️ Proposed refactor
     beforeEach(async () => {
+        vi.clearAllMocks();
         sessionStorageData = {};
         vi.mocked(sessionStorage.getItem).mockImplementation((key: string) => sessionStorageData[key] ?? null);
         // ... rest of beforeEach
     });

     afterEach(() => {
-        vi.clearAllMocks();
     });

As per coding guidelines: "Call cleanup() in Vitest afterEach, vi.clearAllMocks() in beforeEach".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/stores/__tests__/auth.test.ts` around lines 42 - 63, Move the
vi.clearAllMocks() call out of the afterEach block and into the beforeEach setup
so mocks are cleared before each test; update the test file's lifecycle hooks by
removing vi.clearAllMocks() from the afterEach block and adding a
vi.clearAllMocks() invocation at the start of the existing beforeEach (where
sessionStorage mocks and mock* resets are performed) to conform to the guideline
that vi.clearAllMocks() runs in beforeEach rather than afterEach.

4-26: Mock functions should be hoisted with vi.hoisted().

The mock functions (mockLoginApi, mockLogoutApi, mockGetProfileApi, mockClearUserSettings, mockLoadUserSettings) are declared at module scope without vi.hoisted(). Per coding guidelines, Vitest tests must hoist mocks before vi.mock() declarations to ensure proper execution order.

♻️ Proposed refactor using vi.hoisted()
-const mockLoginApi = vi.fn();
-const mockLogoutApi = vi.fn();
-const mockGetProfileApi = vi.fn();
+const { mockLoginApi, mockLogoutApi, mockGetProfileApi } = vi.hoisted(() => ({
+    mockLoginApi: vi.fn(),
+    mockLogoutApi: vi.fn(),
+    mockGetProfileApi: vi.fn(),
+}));

 vi.mock('$lib/api', () => ({
     loginApiV1AuthLoginPost: (...args: unknown[]) => mockLoginApi(...args),
     logoutApiV1AuthLogoutPost: (...args: unknown[]) => mockLogoutApi(...args),
     getCurrentUserProfileApiV1AuthMeGet: (...args: unknown[]) => mockGetProfileApi(...args),
 }));

-// Mock clearUserSettings (static import in auth.svelte.ts)
-const mockClearUserSettings = vi.fn();
+const { mockClearUserSettings } = vi.hoisted(() => ({
+    mockClearUserSettings: vi.fn(),
+}));
+
 vi.mock('$stores/userSettings.svelte', () => ({
     clearUserSettings: () => mockClearUserSettings(),
     setUserSettings: vi.fn(),
     userSettingsStore: { settings: null, editorSettings: {} },
 }));

-// Mock loadUserSettings (dynamic import in auth.svelte.ts)
-const mockLoadUserSettings = vi.fn();
+const { mockLoadUserSettings } = vi.hoisted(() => ({
+    mockLoadUserSettings: vi.fn(),
+}));
+
 vi.mock('$lib/user-settings', () => ({
     loadUserSettings: () => mockLoadUserSettings(),
 }));

As per coding guidelines: "Frontend Vitest tests must hoist mocks with vi.hoisted() before vi.mock() declarations".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/stores/__tests__/auth.test.ts` around lines 4 - 26, The
test-level mock functions (mockLoginApi, mockLogoutApi, mockGetProfileApi,
mockClearUserSettings, mockLoadUserSettings) must be created with vi.hoisted()
so they are defined before vi.mock() calls; replace the current top-level const
declarations with hoisted mocks (e.g., const mockLoginApi = vi.hoisted(() =>
vi.fn()) etc.), keep referencing the same identifiers used by the vi.mock()
callbacks (loginApiV1AuthLoginPost, logoutApiV1AuthLogoutPost,
getCurrentUserProfileApiV1AuthMeGet, clearUserSettings, loadUserSettings) so the
existing mock implementations continue to call those hoisted functions.
frontend/src/routes/__tests__/Editor.test.ts (1)

21-28: Consider moving imports to the top of the file.

The API function imports are placed after the createMockLimits function definition, which is unconventional. While JavaScript hoisting makes this work, grouping all imports at the top improves readability and follows standard conventions.

Suggested reordering

Move these imports to appear right after line 6 (after other imports, before any function definitions):

 import Editor from '$routes/Editor.svelte';
+
+import {
+    getK8sResourceLimitsApiV1K8sLimitsGet,
+    getExampleScriptsApiV1ExampleScriptsGet,
+    listSavedScriptsApiV1ScriptsGet,
+    createSavedScriptApiV1ScriptsPost,
+    updateSavedScriptApiV1ScriptsScriptIdPut,
+    deleteSavedScriptApiV1ScriptsScriptIdDelete,
+} from '$lib/api';
 
 function createMockLimits() {

Then remove lines 21-29.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/routes/__tests__/Editor.test.ts` around lines 21 - 28, Move the
API function imports (getK8sResourceLimitsApiV1K8sLimitsGet,
getExampleScriptsApiV1ExampleScriptsGet, listSavedScriptsApiV1ScriptsGet,
createSavedScriptApiV1ScriptsPost, updateSavedScriptApiV1ScriptsScriptIdPut,
deleteSavedScriptApiV1ScriptsScriptIdDelete) so they appear with the other
imports at the top of the file (i.e., immediately after the existing import
block and before the createMockLimits function definition), and remove the
duplicate import block currently placed after createMockLimits to keep imports
grouped and consistent.
frontend/vitest.setup.ts (2)

171-175: Add vi.clearAllMocks() to reset mock call state between tests.

The global mocks ($lib/api, router, toast, interceptors) defined at module level will accumulate call counts across tests without this. Add it to ensure each test starts with fresh mock state:

Suggested fix
 beforeEach(() => {
+    vi.clearAllMocks();
     Object.keys(localStorageStore).forEach((key) => delete localStorageStore[key]);
     Object.keys(sessionStorageStore).forEach((key) => delete sessionStorageStore[key]);
     cleanup();
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/vitest.setup.ts` around lines 171 - 175, Add a call to
vi.clearAllMocks() inside the existing beforeEach so global mocks are reset
between tests; update the beforeEach block that currently clears
localStorageStore/sessionStorageStore and calls cleanup() (the function named
beforeEach, and the variables localStorageStore, sessionStorageStore, and
cleanup) to invoke vi.clearAllMocks() (preferably at the start) to reset mock
call state for module-level mocks like $lib/api, router, toast, and
interceptors.

44-44: Refactor forEach callbacks to use for...of loops for better code clarity.

Lines 44, 63, 172, and 173 use Object.keys(...).forEach((key) => delete store[key]). While this works, using a for...of loop is more idiomatic and explicit:

Suggested refactor
-        Object.keys(localStorageStore).forEach((key) => delete localStorageStore[key]);
+        for (const key of Object.keys(localStorageStore)) {
+            delete localStorageStore[key];
+        }

-        Object.keys(sessionStorageStore).forEach((key) => delete sessionStorageStore[key]);
+        for (const key of Object.keys(sessionStorageStore)) {
+            delete sessionStorageStore[key];
+        }

-    Object.keys(localStorageStore).forEach((key) => delete localStorageStore[key]);
-    Object.keys(sessionStorageStore).forEach((key) => delete sessionStorageStore[key]);
+    for (const key of Object.keys(localStorageStore)) {
+        delete localStorageStore[key];
+    }
+    for (const key of Object.keys(sessionStorageStore)) {
+        delete sessionStorageStore[key];
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/vitest.setup.ts` at line 44, Replace the use of
Object.keys(...).forEach((key) => delete store[key]) with an explicit for...of
loop for clarity: locate the occurrences (e.g., the localStorageStore cleanup in
vitest.setup.ts and the other similar cleanups referenced at lines 63, 172, 173)
and change the callback style to iterate keys via for (const key of
Object.keys(store)) { delete store[key]; } so each store cleanup
(localStorageStore and the other store variables) uses a for...of loop instead
of forEach.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/routes/__tests__/Editor.test.ts`:
- Line 2: The tests import from '@testing-library/svelte' but do not import or
call cleanup; update the import to include cleanup and modify the test lifecycle
to call cleanup() in afterEach and vi.clearAllMocks() in beforeEach so
components are unmounted and mocks reset; locate the import line bringing in
render/screen/waitFor and add cleanup, then add/adjust the beforeEach to call
vi.clearAllMocks() and the afterEach to call cleanup() (referencing the symbols
render, cleanup, beforeEach, afterEach, vi.clearAllMocks).

---

Outside diff comments:
In `@frontend/src/stores/__tests__/theme.test.ts`:
- Around line 3-11: The tests currently define mock implementations inline
inside vi.mock factories for saveUserSettings and authStore; instead, create
hoisted mock handles using vi.hoisted() (e.g., const saveUserSettingsMock =
vi.hoisted(() => vi.fn().mockResolvedValue(true)) and const authStoreMock =
vi.hoisted(() => ({ authStore: { isAuthenticated: false } }))) and then
reference those handles inside vi.mock factories (vi.mock('$lib/user-settings',
() => ({ saveUserSettings: saveUserSettingsMock })) and
vi.mock('$stores/auth.svelte', () => authStoreMock)); update the references in
theme.test.ts to use these hoisted handles so mocks are created before imports.

---

Duplicate comments:
In @.github/actions/e2e-ready/action.yml:
- Around line 43-46: The wait blocks use the pattern "timeout 120 tail --pid=...
-f /dev/null || true" which masks timeout exit code 124; update each such block
(the kueue/crictl/infra wait invocations and the ones that touch
"/tmp/kueue-download.exit" etc.) to remove the unconditional "|| true", capture
the timeout command's exit status, and explicitly handle a 124 timeout by
logging a clear timeout error and propagating a non-zero exit (and/or writing
the appropriate exit file) so the pipeline fails with an explicit timeout
instead of being masked; ensure the new logic still preserves existing
successful-wait behavior.

---

Nitpick comments:
In `@frontend/src/routes/__tests__/Editor.test.ts`:
- Around line 21-28: Move the API function imports
(getK8sResourceLimitsApiV1K8sLimitsGet, getExampleScriptsApiV1ExampleScriptsGet,
listSavedScriptsApiV1ScriptsGet, createSavedScriptApiV1ScriptsPost,
updateSavedScriptApiV1ScriptsScriptIdPut,
deleteSavedScriptApiV1ScriptsScriptIdDelete) so they appear with the other
imports at the top of the file (i.e., immediately after the existing import
block and before the createMockLimits function definition), and remove the
duplicate import block currently placed after createMockLimits to keep imports
grouped and consistent.

In `@frontend/src/stores/__tests__/auth.test.ts`:
- Around line 42-63: Move the vi.clearAllMocks() call out of the afterEach block
and into the beforeEach setup so mocks are cleared before each test; update the
test file's lifecycle hooks by removing vi.clearAllMocks() from the afterEach
block and adding a vi.clearAllMocks() invocation at the start of the existing
beforeEach (where sessionStorage mocks and mock* resets are performed) to
conform to the guideline that vi.clearAllMocks() runs in beforeEach rather than
afterEach.
- Around line 4-26: The test-level mock functions (mockLoginApi, mockLogoutApi,
mockGetProfileApi, mockClearUserSettings, mockLoadUserSettings) must be created
with vi.hoisted() so they are defined before vi.mock() calls; replace the
current top-level const declarations with hoisted mocks (e.g., const
mockLoginApi = vi.hoisted(() => vi.fn()) etc.), keep referencing the same
identifiers used by the vi.mock() callbacks (loginApiV1AuthLoginPost,
logoutApiV1AuthLogoutPost, getCurrentUserProfileApiV1AuthMeGet,
clearUserSettings, loadUserSettings) so the existing mock implementations
continue to call those hoisted functions.

In `@frontend/vitest.setup.ts`:
- Around line 171-175: Add a call to vi.clearAllMocks() inside the existing
beforeEach so global mocks are reset between tests; update the beforeEach block
that currently clears localStorageStore/sessionStorageStore and calls cleanup()
(the function named beforeEach, and the variables localStorageStore,
sessionStorageStore, and cleanup) to invoke vi.clearAllMocks() (preferably at
the start) to reset mock call state for module-level mocks like $lib/api,
router, toast, and interceptors.
- Line 44: Replace the use of Object.keys(...).forEach((key) => delete
store[key]) with an explicit for...of loop for clarity: locate the occurrences
(e.g., the localStorageStore cleanup in vitest.setup.ts and the other similar
cleanups referenced at lines 63, 172, 173) and change the callback style to
iterate keys via for (const key of Object.keys(store)) { delete store[key]; } so
each store cleanup (localStorageStore and the other store variables) uses a
for...of loop instead of forEach.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 37864b5e-d847-48c3-ba3a-e48517845d4a

📥 Commits

Reviewing files that changed from the base of the PR and between 14cb2cf and ed64ed5.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (14)
  • .github/actions/e2e-ready/action.yml
  • frontend/package.json
  • frontend/src/components/__tests__/ErrorDisplay.test.ts
  • frontend/src/components/__tests__/Footer.test.ts
  • frontend/src/components/__tests__/Header.test.ts
  • frontend/src/components/__tests__/NotificationCenter.test.ts
  • frontend/src/components/__tests__/Spinner.test.ts
  • frontend/src/components/admin/users/__tests__/RateLimitsModal.test.ts
  • frontend/src/lib/editor/__tests__/languages.test.ts
  • frontend/src/routes/__tests__/Editor.test.ts
  • frontend/src/stores/__tests__/auth.test.ts
  • frontend/src/stores/__tests__/theme.test.ts
  • frontend/src/utils/__tests__/meta.test.ts
  • frontend/vitest.setup.ts
💤 Files with no reviewable changes (5)
  • frontend/src/lib/editor/tests/languages.test.ts
  • frontend/src/components/tests/Spinner.test.ts
  • frontend/src/components/tests/ErrorDisplay.test.ts
  • frontend/src/components/tests/Footer.test.ts
  • frontend/src/utils/tests/meta.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/admin/users/tests/RateLimitsModal.test.ts

@@ -1,28 +1,33 @@
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { render, screen, waitFor } from '@testing-library/svelte';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing cleanup() call in afterEach.

Per coding guidelines, Vitest tests should call cleanup() in afterEach to properly unmount components and prevent test pollution between tests. The cleanup function also needs to be imported from @testing-library/svelte.

Proposed fix

Update the import on line 2:

-import { render, screen, waitFor } from '@testing-library/svelte';
+import { cleanup, render, screen, waitFor } from '@testing-library/svelte';

Update afterEach on line 107:

-    afterEach(() => vi.unstubAllGlobals());
+    afterEach(() => {
+        cleanup();
+        vi.unstubAllGlobals();
+    });

Based on learnings: "Call cleanup() in Vitest afterEach, vi.clearAllMocks() in beforeEach"

Also applies to: 107-107

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/routes/__tests__/Editor.test.ts` at line 2, The tests import
from '@testing-library/svelte' but do not import or call cleanup; update the
import to include cleanup and modify the test lifecycle to call cleanup() in
afterEach and vi.clearAllMocks() in beforeEach so components are unmounted and
mocks reset; locate the import line bringing in render/screen/waitFor and add
cleanup, then add/adjust the beforeEach to call vi.clearAllMocks() and the
afterEach to call cleanup() (referencing the symbols render, cleanup,
beforeEach, afterEach, vi.clearAllMocks).

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Mar 5, 2026

@HardMax71 HardMax71 merged commit 4912a21 into main Mar 5, 2026
17 checks passed
@HardMax71 HardMax71 deleted the chore/test-exec-speedup branch March 5, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants