Skip to content

fix: prevent onboarding on API errors#1917

Open
Ajit-Mehrotra wants to merge 5 commits intomainfrom
codex/onboarding-error-fallback
Open

fix: prevent onboarding on API errors#1917
Ajit-Mehrotra wants to merge 5 commits intomainfrom
codex/onboarding-error-fallback

Conversation

@Ajit-Mehrotra
Copy link
Contributor

@Ajit-Mehrotra Ajit-Mehrotra commented Mar 15, 2026

Summary

This PR hardens the onboarding flow so transient API problems do not incorrectly block or break the modal, while still hiding onboarding when we genuinely cannot trust the state.

It also includes the small plugin install-script cleanup that came along with this work and the generated GraphQL/schema updates that are currently part of the branch.

Behavior Changes

Onboarding tracker handling

  • A missing onboarding-tracker.json file is treated as a valid empty onboarding state rather than a read failure.
  • Real tracker read failures are still surfaced as errors instead of being silently flattened into default state.
  • Public runtime tracker readers now go through the error-propagating getStateResult() path so customization and onboarding mutation responses behave consistently.

Onboarding modal gating

  • The onboarding modal is now hidden when the onboarding query truly fails and there is no usable onboarding data.
  • If a resumable onboarding draft exists, the modal stays displayable even during API restart/error windows so users can continue from summary or later steps.
  • If Apollo returns existing onboarding data alongside an error during a refetch/restart window, the modal remains displayable instead of being over-blocked.

Review follow-ups

  • Renamed the loading-state onboarding store test so the title matches the asserted behavior.
  • Relaxed the customization resolver spec so it verifies rejection behavior without depending on exact error text.
  • Removed the duplicated corepack / npm / npx symlink block from the plugin doinst.sh.

Files / Areas Touched

  • API onboarding tracker service and related specs
  • Customization onboarding resolver and spec
  • Onboarding mutation resolver and spec
  • Web onboarding status store and tests
  • Plugin install script
  • Generated GraphQL/schema artifacts currently included in the branch

Testing

API

  • pnpm exec vitest run src/unraid-api/config/onboarding-tracker.service.spec.ts src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts src/unraid-api/graph/resolvers/onboarding/onboarding.mutation.spec.ts src/unraid-api/config/api-config.test.ts

Web

  • pnpm exec vitest run __test__/store/onboardingStatus.test.ts __test__/components/Onboarding/OnboardingModal.test.ts
  • pnpm test

Plugin

  • sh -n plugin/source/dynamix.unraid.net/install/doinst.sh

Summary by CodeRabbit

  • Bug Fixes

    • Improved onboarding error handling with better state management and recovery paths
    • Enabled users to resume onboarding progress even when query errors occur (if draft exists)
    • Enhanced error propagation for more reliable state tracking
  • Refactor

    • Consolidated notification schema definitions for consistency

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 15, 2026

Walkthrough

Refactors onboarding tracker to return a discriminated union OnboardingTrackerStateResult (kind: 'ok' | 'missing' | 'error') via a new async getStateResult() API; updates service bootstrap, resolvers, mutations, tests, and frontend stores/tests to consume and propagate the new result shape. Also adds/normalizes notification types in the GraphQL schema and removes duplicated schema blocks.

Changes

Cohort / File(s) Summary
GraphQL Schema
api/generated-schema.graphql
Added notification-related public types and enums (NotificationCounts, NotificationOverview, Notification, NotificationImportance, NotificationType, Notifications, NotificationFilter) and removed a duplicated earlier definition; minor Subscription closing-brace formatting change.
Onboarding Tracker Service
api/src/unraid-api/config/onboarding-tracker.service.ts
Introduced PublicTrackerState and exported OnboardingTrackerStateResult discriminated union; added async getStateResult() and private readTrackerStateResult(); converted bootstrap/read paths and logging to return typed results; isCompleted() and getCompletedAtVersion() made async.
Onboarding Tracker Tests
api/src/unraid-api/config/onboarding-tracker.service.spec.ts, api/src/unraid-api/config/api-config.test.ts
Tests updated/added to assert getStateResult() behavior for missing file, read errors, overrides, and propagation; expectations updated to the { kind, state } shape.
Resolvers / Onboarding Logic
api/src/unraid-api/graph/resolvers/customization/customization.resolver.ts, api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts, api/src/unraid-api/graph/resolvers/onboarding/onboarding.mutation.ts, api/src/unraid-api/graph/resolvers/onboarding/onboarding.mutation.spec.ts, api/src/unraid-api/graph/resolvers/customization/onboarding.service.ts
Replaced synchronous state reads with await getStateResult(); added error handling (throw GraphQLError or propagate errors when kind === 'error'); tests updated to mock and assert the discriminated-union result and to include a test for tracker-read error propagation.
Web Onboarding Store
web/src/components/Onboarding/store/onboardingDraft.ts, web/src/components/Onboarding/store/onboardingStatus.ts, web/__test__/store/onboardingStatus.test.ts
Added hasResumableDraft computed to draft store and exposed it; onboardingStatus now consumes hasResumableDraft and onboarding query error (hasOnboardingQueryError); updated modal gating logic and added comprehensive tests covering loading, error, draft, and success scenarios.
Misc Tests & Small Fixes
api/src/unraid-api/config/api-config.test.ts
Adjusted tests to await and assert getStateResult() result shapes.
Packaging Script
plugin/source/dynamix.unraid.net/install/doinst.sh
Removed duplicated re-removal/re-creation of corepack/npm/npx symlink block (eliminated repeated auto-generated actions).

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Resolver
  participant Tracker as OnboardingTrackerService
  participant FS as Filesystem/Override

  rect rgba(200,220,255,0.5)
  Client->>Resolver: GraphQL request (resolveOnboarding / mutation)
  end

  rect rgba(200,255,200,0.5)
  Resolver->>Tracker: await getStateResult()
  Tracker->>FS: read tracker file or read override
  FS-->>Tracker: { kind: 'ok' | 'missing' | 'error', state? }
  Tracker-->>Resolver: return OnboardingTrackerStateResult
  end

  alt kind === 'error'
    Resolver->>Resolver: throw GraphQLError / propagate error
    Resolver-->>Client: error response
  else kind === 'ok' or 'missing'
    Resolver->>Resolver: extract state and continue business logic
    Resolver-->>Client: success response (onboarding data)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • elibosley

🐰
I hopped through code with nimble feet,
I sorted states so errors meet,
Missing, ok, and those that break—
Now resolvers know which road to take! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: prevent onboarding on API errors' accurately reflects the main objective of this pull request—hardening the onboarding flow to handle API errors appropriately.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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 codex/onboarding-error-fallback
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@Ajit-Mehrotra Ajit-Mehrotra changed the title fix: preserve onboarding resume flow across API errors fix: prevent onboarding on API errors Mar 15, 2026
@codecov
Copy link

codecov bot commented Mar 15, 2026

Codecov Report

❌ Patch coverage is 83.51648% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.12%. Comparing base (1ca2129) to head (98a07b3).

Files with missing lines Patch % Lines
...src/components/Onboarding/store/onboardingDraft.ts 0.00% 9 Missing and 1 partial ⚠️
...rc/unraid-api/config/onboarding-tracker.service.ts 91.52% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1917      +/-   ##
==========================================
+ Coverage   50.98%   51.12%   +0.14%     
==========================================
  Files        1024     1024              
  Lines       70558    70628      +70     
  Branches     7714     7748      +34     
==========================================
+ Hits        35974    36111     +137     
+ Misses      34458    34393      -65     
+ Partials      126      124       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 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.

@Ajit-Mehrotra
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai bot requested a review from elibosley March 15, 2026 20:56
Copy link
Contributor

@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)
api/src/unraid-api/config/onboarding-tracker.service.ts (1)

57-109: ⚠️ Potential issue | 🟠 Major

Don't leave getState() as a non-erroring runtime read path.

getStateResult() only helps callers that opt in. api/src/unraid-api/graph/resolvers/onboarding/onboarding.mutation.ts:32-61 still builds its response from getState(), so those mutation paths can keep returning cached/default onboarding status when the tracker file can't be read. That means this PR fixes the customization query, but not all onboarding responses.

Please migrate the remaining runtime readers to getStateResult() or make getState() internal/cached-only so tracker read failures are surfaced consistently.

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

In `@api/src/unraid-api/config/onboarding-tracker.service.ts` around lines 57 -
109, The current getState() exposes a non-erroring runtime read path and must be
made cached-only or replaced by an error-propagating API; change usages to call
getStateResult() (which surfaces read errors) instead of getState() so
tracker-read failures aren't silently ignored. Specifically, make getState()
private or document it as cached-only, update public readers (isCompleted(),
getCompletedAtVersion(), and any external callers such as the GraphQL mutation
that currently uses getState()) to call getStateResult() and handle the returned
OnboardingTrackerStateResult (extract state on kind==='ok' or propagate the
error), and ensure readTrackerStateResult() remains the single source of truth
for runtime reads. Use the function names getState(), getStateResult(),
isCompleted(), getCompletedAtVersion(), getCurrentVersion(), and
readTrackerStateResult() to locate and update all references.
🧹 Nitpick comments (3)
plugin/source/dynamix.unraid.net/install/doinst.sh (1)

40-45: Remove this duplicated symlink setup block.

Line 40 through Line 45 duplicate the same corepack/npm/npx link recreation already done earlier, so this just re-runs identical operations. Keep only one block to avoid redundant install steps and future drift.

Suggested diff
-( cd usr/local/bin ; rm -rf corepack )
-( cd usr/local/bin ; ln -sf ../lib/node_modules/corepack/dist/corepack.js corepack )
-( cd usr/local/bin ; rm -rf npm )
-( cd usr/local/bin ; ln -sf ../lib/node_modules/npm/bin/npm-cli.js npm )
-( cd usr/local/bin ; rm -rf npx )
-( cd usr/local/bin ; ln -sf ../lib/node_modules/npm/bin/npx-cli.js npx )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/source/dynamix.unraid.net/install/doinst.sh` around lines 40 - 45,
Remove the duplicated symlink recreation block that repeats the corepack/npm/npx
setup (the lines performing "( cd usr/local/bin ; rm -rf corepack )", "( cd
usr/local/bin ; ln -sf ../lib/node_modules/corepack/dist/corepack.js corepack
)", "( cd usr/local/bin ; rm -rf npm )", "( cd usr/local/bin ; ln -sf
../lib/node_modules/npm/bin/npm-cli.js npm )", "( cd usr/local/bin ; rm -rf npx
)", "( cd usr/local/bin ; ln -sf ../lib/node_modules/npm/bin/npx-cli.js npx )");
keep the original single block earlier in the script and delete this repeated
block so the symlinks for corepack, npm and npx are only created once.
web/src/components/Onboarding/store/onboardingStatus.ts (1)

90-93: Verify partial-data GraphQL errors don’t over-block modal display.

With errorPolicy: 'all', Apollo can return both result and error. Current logic blocks on any error unless a draft exists, which may hide the modal even when onboarding data is still present.

Suggested adjustment (after verification)
-  const canDisplayOnboardingModal = computed(
-    () => isVersionSupported.value && (hasResumableDraft.value || !hasOnboardingQueryError.value)
-  );
+  const canDisplayOnboardingModal = computed(
+    () =>
+      isVersionSupported.value &&
+      (hasResumableDraft.value || Boolean(onboardingData.value) || !hasOnboardingQueryError.value)
+  );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/components/Onboarding/store/onboardingStatus.ts` around lines 90 -
93, The current blocking logic treats any Apollo error as fatal; change
hasOnboardingQueryError to only consider an error blocking when there is no
usable onboarding data returned. Replace the Boolean(onboardingError.value)
check with one that also ensures the query result is empty (e.g., computed(() =>
Boolean(onboardingError.value) && !onboardingQueryResult.value?.data)), so
canDisplayOnboardingModal uses errors only when there is truly no onboarding
data; update references to onboardingError, onboardingQueryResult,
hasOnboardingQueryError, and canDisplayOnboardingModal accordingly.
api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts (1)

50-58: Avoid asserting the exact error text here.

The behavior that matters is that tracker read failures reject. This assertion will fail on harmless message edits while the resolver behavior is still correct.

♻️ Suggested tweak
-        await expect(resolver.resolveOnboarding()).rejects.toThrow(
-            'Onboarding tracker state is unavailable.'
-        );
+        await expect(resolver.resolveOnboarding()).rejects.toThrow();
Based on learnings: "Test what the code does, not implementation details like exact error message wording - avoid writing tests that break when minor changes are made to error messages, log formats, or other non-essential details"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts`
around lines 50 - 58, The test currently asserts the exact error message from
resolver.resolveOnboarding; change it to only assert that the promise rejects
(or rejects with an Error) rather than matching the exact text. Update the spec
that mocks onboardingTracker.getStateResult (in this test using
onboardingTracker.getStateResult and resolver.resolveOnboarding) to assert using
await expect(resolver.resolveOnboarding()).rejects.toThrow() or
.rejects.toBeInstanceOf(Error) instead of checking the specific message string
so the test verifies failure behavior without depending on exact wording.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/__test__/store/onboardingStatus.test.ts`:
- Around line 74-82: Rename the test title to accurately reflect the asserted
behavior: change the it(...) description that currently says the modal is
blocked while loading to something like "blocks auto-show while the onboarding
query is still loading" so it matches the assertions on
canDisplayOnboardingModal and shouldShowOnboarding; update the test description
surrounding the useOnboardingStore invocation and the expectations for
canDisplayOnboardingModal and shouldShowOnboarding accordingly.

---

Outside diff comments:
In `@api/src/unraid-api/config/onboarding-tracker.service.ts`:
- Around line 57-109: The current getState() exposes a non-erroring runtime read
path and must be made cached-only or replaced by an error-propagating API;
change usages to call getStateResult() (which surfaces read errors) instead of
getState() so tracker-read failures aren't silently ignored. Specifically, make
getState() private or document it as cached-only, update public readers
(isCompleted(), getCompletedAtVersion(), and any external callers such as the
GraphQL mutation that currently uses getState()) to call getStateResult() and
handle the returned OnboardingTrackerStateResult (extract state on kind==='ok'
or propagate the error), and ensure readTrackerStateResult() remains the single
source of truth for runtime reads. Use the function names getState(),
getStateResult(), isCompleted(), getCompletedAtVersion(), getCurrentVersion(),
and readTrackerStateResult() to locate and update all references.

---

Nitpick comments:
In
`@api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts`:
- Around line 50-58: The test currently asserts the exact error message from
resolver.resolveOnboarding; change it to only assert that the promise rejects
(or rejects with an Error) rather than matching the exact text. Update the spec
that mocks onboardingTracker.getStateResult (in this test using
onboardingTracker.getStateResult and resolver.resolveOnboarding) to assert using
await expect(resolver.resolveOnboarding()).rejects.toThrow() or
.rejects.toBeInstanceOf(Error) instead of checking the specific message string
so the test verifies failure behavior without depending on exact wording.

In `@plugin/source/dynamix.unraid.net/install/doinst.sh`:
- Around line 40-45: Remove the duplicated symlink recreation block that repeats
the corepack/npm/npx setup (the lines performing "( cd usr/local/bin ; rm -rf
corepack )", "( cd usr/local/bin ; ln -sf
../lib/node_modules/corepack/dist/corepack.js corepack )", "( cd usr/local/bin ;
rm -rf npm )", "( cd usr/local/bin ; ln -sf
../lib/node_modules/npm/bin/npm-cli.js npm )", "( cd usr/local/bin ; rm -rf npx
)", "( cd usr/local/bin ; ln -sf ../lib/node_modules/npm/bin/npx-cli.js npx )");
keep the original single block earlier in the script and delete this repeated
block so the symlinks for corepack, npm and npx are only created once.

In `@web/src/components/Onboarding/store/onboardingStatus.ts`:
- Around line 90-93: The current blocking logic treats any Apollo error as
fatal; change hasOnboardingQueryError to only consider an error blocking when
there is no usable onboarding data returned. Replace the
Boolean(onboardingError.value) check with one that also ensures the query result
is empty (e.g., computed(() => Boolean(onboardingError.value) &&
!onboardingQueryResult.value?.data)), so canDisplayOnboardingModal uses errors
only when there is truly no onboarding data; update references to
onboardingError, onboardingQueryResult, hasOnboardingQueryError, and
canDisplayOnboardingModal accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6e51ce32-b72a-4f08-9707-5c1451ccb2c2

📥 Commits

Reviewing files that changed from the base of the PR and between c3e9767 and 997272a.

⛔ Files ignored due to path filters (1)
  • api/src/unraid-api/cli/generated/graphql.ts is excluded by !**/generated/**
📒 Files selected for processing (9)
  • api/generated-schema.graphql
  • api/src/unraid-api/config/onboarding-tracker.service.spec.ts
  • api/src/unraid-api/config/onboarding-tracker.service.ts
  • api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts
  • api/src/unraid-api/graph/resolvers/customization/customization.resolver.ts
  • plugin/source/dynamix.unraid.net/install/doinst.sh
  • web/__test__/store/onboardingStatus.test.ts
  • web/src/components/Onboarding/store/onboardingDraft.ts
  • web/src/components/Onboarding/store/onboardingStatus.ts

- Purpose: tighten onboarding error handling so real API/tracker failures hide the modal, while missing tracker state and saved drafts can still resume the flow.
- Before: onboarding tracker reads flattened missing and failed states together, and the modal gate did not preserve resumable drafts during restart windows.
- Problem: summary-step API restarts could strand users mid-flow, while tracker failures could be misinterpreted as normal onboarding state.
- Change: model tracker reads with explicit ok/missing/error results, surface true tracker failures as GraphQL errors, and allow the web modal to stay displayable when a resumable draft exists.
- How: add tracker/result tests, update the customization resolver and generated GraphQL artifacts, and compute resumable draft visibility in the onboarding stores.
- Purpose: make the packaged plugin expose the expected package-manager entrypoints after install.
- Before: the install script only recreated npm and npx links, leaving corepack unavailable from the installed environment.
- Problem: package-manager workflows that rely on corepack could fail even though Node tooling was otherwise installed.
- Change: create the corepack symlink during plugin install alongside the npm and npx links.
- How: extend doinst.sh to link usr/local/bin/corepack to the bundled corepack entrypoint while preserving the existing npm and npx setup.
- Purpose: restore the web test suite after the onboarding branch was rebased onto newer mainline GraphQL changes.
- Before: the generated GraphQL file contained two ServerStateDocument exports after conflict resolution.
- Problem: Vite/esbuild failed during test transforms with a duplicate export error, causing a large slice of the web suite to fail before execution.
- Change: remove the stale duplicate ServerStateDocument export and keep the version that matches the current serverState query shape.
- How: clean up the generated GraphQL artifact so only the up-to-date ServerStateDocument remains.
- Purpose: resolve the outstanding CodeRabbit findings on PR #1917 after rebasing onto the latest mainline.
- Before: the onboarding store over-blocked on partial Apollo errors, tracker read failures could still be flattened through mutation/runtime helper paths, one resolver spec asserted exact error text, and the plugin install script repeated the symlink block.
- Problem: review comments highlighted behavior drift, brittle tests, and redundant install steps that could leave the PR confusing or incomplete.
- Change: tighten the onboarding error gate for partial data, route runtime tracker readers through the error-propagating result path, relax the brittle spec assertion, rename the mismatched test, and collapse the duplicated install block.
- How: update the API/web logic and focused tests for onboarding state handling, mutation responses, and tracker reads, then validate with targeted Vitest runs plus a shell syntax check for the install script.
@Ajit-Mehrotra Ajit-Mehrotra force-pushed the codex/onboarding-error-fallback branch from 997272a to 98a07b3 Compare March 15, 2026 21:13
@github-actions
Copy link
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1917/dynamix.unraid.net.plg

@Ajit-Mehrotra Ajit-Mehrotra marked this pull request as ready for review March 16, 2026 00:42
Copy link
Contributor

@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.

🧹 Nitpick comments (3)
web/__test__/store/onboardingStatus.test.ts (1)

162-172: Consider moving vi.mock() calls above the describe block for readability.

While Vitest automatically hoists vi.mock() calls, placing them after imports (before the describe block) is the conventional location and improves readability for developers scanning the file.

♻️ Suggested reordering
 import { useOnboardingDraftStore } from '~/components/Onboarding/store/onboardingDraft';
 import { useOnboardingStore } from '~/components/Onboarding/store/onboardingStatus';
 import { useServerStore } from '~/store/server';
 
+vi.mock('@vue/apollo-composable', () => ({
+  useQuery: () => useQueryMock(),
+}));
+
+vi.mock('~/components/Onboarding/store/onboardingDraft', () => ({
+  useOnboardingDraftStore: vi.fn(),
+}));
+
+vi.mock('~/store/server', () => ({
+  useServerStore: vi.fn(),
+}));
+
 type OnboardingQueryResult = {
   // ...
 };
 
 // ... rest of file ...
 
-vi.mock('@vue/apollo-composable', () => ({
-  useQuery: () => useQueryMock(),
-}));
-
-vi.mock('~/components/Onboarding/store/onboardingDraft', () => ({
-  useOnboardingDraftStore: vi.fn(),
-}));
-
-vi.mock('~/store/server', () => ({
-  useServerStore: vi.fn(),
-}));

As per coding guidelines: "Place all mock declarations at the top level in Pinia store tests."

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

In `@web/__test__/store/onboardingStatus.test.ts` around lines 162 - 172, Move the
three vi.mock declarations for '@vue/apollo-composable',
'~/components/Onboarding/store/onboardingDraft', and '~/store/server' out of the
describe block and place them at the top-level (after the imports, before the
describe) so they are easier to find; keep the mocked factories the same
(useQueryMock for useQuery, vi.fn() for useOnboardingDraftStore and
useServerStore) and ensure they remain hoisted by Vitest.
api/src/unraid-api/config/onboarding-tracker.service.spec.ts (1)

171-186: Consider removing exact error message assertions.

These tests assert the exact error message string 'permission denied'. Per coding guidelines, tests should use .rejects.toThrow() without arguments to avoid brittle tests that break when error messages change.

♻️ Suggested refactor
-        await expect(tracker.isCompleted()).rejects.toThrow('permission denied');
+        await expect(tracker.isCompleted()).rejects.toThrow();
-        await expect(tracker.getCompletedAtVersion()).rejects.toThrow('permission denied');
+        await expect(tracker.getCompletedAtVersion()).rejects.toThrow();

As per coding guidelines: "Use .rejects.toThrow() without arguments to test that functions throw errors. Don't test exact error message strings unless the message format is specifically what you're testing."

Also applies to: 188-203

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

In `@api/src/unraid-api/config/onboarding-tracker.service.spec.ts` around lines
171 - 186, The test asserts the exact error message 'permission denied' which is
brittle; update the assertions in the OnboardingTrackerService spec so they only
check that the promise rejects (use .rejects.toThrow() with no argument) for
calls to tracker.isCompleted() after onApplicationBootstrap(), and similarly
update the other occurrence noted (lines ~188-203) that uses mockReadFile to
throw to avoid matching exact error strings; leave the mock behavior and error
throw intact but remove the specific message argument from the .rejects.toThrow
assertions.
api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts (1)

50-57: Consider adding test coverage for the 'missing' kind variant.

The resolver treats both 'ok' and 'missing' state kinds identically—both provide a state object that is processed normally, while only 'error' throws. Currently, all successful tests use 'ok', leaving no coverage for the 'missing' variant. Adding a test case would document that a missing tracker file is a valid scenario (not an error) and ensure all three union type variants are exercised.

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

In
`@api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts`
around lines 50 - 57, Add a new unit test that covers the
onboardingTracker.getStateResult "missing" variant: mock
vi.mocked(onboardingTracker.getStateResult) to resolve to { kind: 'missing' }
and call resolver.resolveOnboarding(), asserting it does not throw and
returns/handles the default state result the same way as the 'ok' path; place
this alongside the existing tests for 'ok' and 'error' to ensure the
resolver.resolveOnboarding behavior for the 'missing' kind is explicitly
verified.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@api/src/unraid-api/config/onboarding-tracker.service.spec.ts`:
- Around line 171-186: The test asserts the exact error message 'permission
denied' which is brittle; update the assertions in the OnboardingTrackerService
spec so they only check that the promise rejects (use .rejects.toThrow() with no
argument) for calls to tracker.isCompleted() after onApplicationBootstrap(), and
similarly update the other occurrence noted (lines ~188-203) that uses
mockReadFile to throw to avoid matching exact error strings; leave the mock
behavior and error throw intact but remove the specific message argument from
the .rejects.toThrow assertions.

In
`@api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts`:
- Around line 50-57: Add a new unit test that covers the
onboardingTracker.getStateResult "missing" variant: mock
vi.mocked(onboardingTracker.getStateResult) to resolve to { kind: 'missing' }
and call resolver.resolveOnboarding(), asserting it does not throw and
returns/handles the default state result the same way as the 'ok' path; place
this alongside the existing tests for 'ok' and 'error' to ensure the
resolver.resolveOnboarding behavior for the 'missing' kind is explicitly
verified.

In `@web/__test__/store/onboardingStatus.test.ts`:
- Around line 162-172: Move the three vi.mock declarations for
'@vue/apollo-composable', '~/components/Onboarding/store/onboardingDraft', and
'~/store/server' out of the describe block and place them at the top-level
(after the imports, before the describe) so they are easier to find; keep the
mocked factories the same (useQueryMock for useQuery, vi.fn() for
useOnboardingDraftStore and useServerStore) and ensure they remain hoisted by
Vitest.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5db607d5-941a-40ea-9de7-b662abd53980

📥 Commits

Reviewing files that changed from the base of the PR and between 997272a and 98a07b3.

⛔ Files ignored due to path filters (1)
  • api/src/unraid-api/cli/generated/graphql.ts is excluded by !**/generated/**
📒 Files selected for processing (13)
  • api/generated-schema.graphql
  • api/src/unraid-api/config/api-config.test.ts
  • api/src/unraid-api/config/onboarding-tracker.service.spec.ts
  • api/src/unraid-api/config/onboarding-tracker.service.ts
  • api/src/unraid-api/graph/resolvers/customization/customization.resolver.spec.ts
  • api/src/unraid-api/graph/resolvers/customization/customization.resolver.ts
  • api/src/unraid-api/graph/resolvers/customization/onboarding.service.ts
  • api/src/unraid-api/graph/resolvers/onboarding/onboarding.mutation.spec.ts
  • api/src/unraid-api/graph/resolvers/onboarding/onboarding.mutation.ts
  • plugin/source/dynamix.unraid.net/install/doinst.sh
  • web/__test__/store/onboardingStatus.test.ts
  • web/src/components/Onboarding/store/onboardingDraft.ts
  • web/src/components/Onboarding/store/onboardingStatus.ts
💤 Files with no reviewable changes (1)
  • plugin/source/dynamix.unraid.net/install/doinst.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/src/components/Onboarding/store/onboardingStatus.ts
  • web/src/components/Onboarding/store/onboardingDraft.ts

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.

1 participant