Skip to content

Fleet UI: Update empty states in Controls - #44965

Merged
RachelElysia merged 15 commits into
mainfrom
35483-empty-states-controls
May 13, 2026
Merged

Fleet UI: Update empty states in Controls#44965
RachelElysia merged 15 commits into
mainfrom
35483-empty-states-controls

Conversation

@RachelElysia

@RachelElysia RachelElysia commented May 7, 2026

Copy link
Copy Markdown
Member

Issue

Closes #44326 4.86.0
Second half of #35483 from 4.85.0

Description

Screenshots of updates

Screenshot 2026-05-11 at 10 04 24 AM Screenshot 2026-05-11 at 10 06 54 AM Screenshot 2026-05-11 at 10 07 03 AM Screenshot 2026-05-11 at 10 09 53 AM Screenshot 2026-05-11 at 10 10 14 AM Screenshot 2026-05-11 at 10 14 32 AM Screenshot 2026-05-11 at 10 14 39 AM Screenshot 2026-05-11 at 10 14 44 AM Screenshot 2026-05-11 at 10 14 48 AM Screenshot 2026-05-11 at 10 15 25 AM

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • New Features

    • Added a redirect route to the batch scripts learn-more page.
  • Improvements

    • Replaced "custom secrets" UI and workflows with "custom variables" (listing, add/delete, copy token).
    • Enhanced empty-state messaging with richer content and contextual links.
    • Unified script upload empty-state and added multi-OS upload instructions.
    • Clarified setup messaging to require enabling MDM and automatic enrollment.
    • Introduced a variables API/endpoint replacing prior secrets endpoints.
  • Style

    • Adjusted empty-state form sizing for consistent layout.
  • Tests

    • Updated and added tests for variables, scripts, and setup flows.

Review Change Stack

Comment thread frontend/components/EmptyState/EmptyState.stories.tsx Fixed
@codecov

codecov Bot commented May 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.16393% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.76%. Comparing base (d2033df) to head (88c9248).
⚠️ Report is 158 commits behind head on main.

Files with missing lines Patch % Lines
...d/pages/ManageControlsPage/Variables/Variables.tsx 84.00% 4 Missing ⚠️
...Page/Scripts/cards/ScriptLibrary/ScriptLibrary.tsx 88.88% 1 Missing ⚠️
.../AddCustomVariableModal/AddCustomVariableModal.tsx 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #44965      +/-   ##
==========================================
- Coverage   66.78%   66.76%   -0.03%     
==========================================
  Files        2718     2727       +9     
  Lines      218769   219193     +424     
  Branches    10745    10912     +167     
==========================================
+ Hits       146109   146345     +236     
- Misses      59496    59686     +190     
+ Partials    13164    13162       -2     
Flag Coverage Δ
frontend 55.31% <90.16%> (+<0.01%) ⬆️

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

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

@RachelElysia

Copy link
Copy Markdown
Member Author

@claude review

Comment thread frontend/pages/ManageControlsPage/Scripts/helpers.tsx
Comment thread frontend/pages/ManageControlsPage/Scripts/cards/ScriptLibrary/ScriptLibrary.tsx Outdated
@RachelElysia

Copy link
Copy Markdown
Member Author

@claude review

@RachelElysia

Copy link
Copy Markdown
Member Author

@claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM — all prior feedback addressed; the remaining inline comment is a pre-existing minor UX nit.

Extended reasoning...

Overview

This PR updates empty states across the Controls section (Scripts library, Batch progress, Bootstrap package, Variables) and renames the Secrets domain to Variables (interface, service, state, copy). It's primarily UI/UX copy and structural changes plus a mechanical rename, with a small route addition for a learn-more link.

Security risks

None identified. No auth, crypto, permissions, or input-handling code is touched. The Variables rename preserves the same backend endpoint (/fleet/custom_variables), API surface, and access semantics. Role gating (isTechnician, canEdit) is preserved and now consistent between empty/populated states. The new GitOps tooltip wrapper around the Upload button matches the existing pattern.

Level of scrutiny

Moderate — frontend-only, narrowly scoped to ManageControls pages. No CODEOWNER-sensitive code, no backend changes, no schema migrations. The Secrets→Variables rename is mechanical but touches multiple files; it's been done consistently and tests were updated alongside.

Other factors

  • All prior review feedback has been addressed: the getWhen named-import fix landed in ScriptBatchDetailsPage.tsx, the canUploadScripts predicate was simplified to !isTechnician and now matches the populated-state heading, the Upload CTA is wrapped in GitOpsModeTooltipWrapper, and the two stale 'secret' error strings in AddCustomVariableModal were renamed to 'variable'.
  • New tests were added for both ScriptLibrary empty-state role variants and Variables read-only/edit empty states, including a GitOps-mode test for Variables.
  • The remaining inline comment flags a pre-existing bug (EmptyState rendering alongside DataError when the scripts API errors) that this PR magnifies visually but did not introduce; the author can address it as a follow-up.

Comment thread frontend/pages/ManageControlsPage/Scripts/cards/ScriptLibrary/ScriptLibrary.tsx Outdated
@RachelElysia
RachelElysia force-pushed the 35483-empty-states-controls branch from 1c3b751 to f6b86c6 Compare May 8, 2026 20:06
@fleet-release
fleet-release requested a review from eashaw May 11, 2026 20:34

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

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

This PR renames and repurposes the custom secrets flow to custom variables: new IVariable/IVariablePayload interfaces, a variables service with get/add/delete, endpoint key rename SECRETS→VARIABLES, refactored Variables page and add/delete modals, removed legacy secrets service, updated styles/tests and mock responses. Separately, script helpers and components normalize empty states to JSX (learn-more links, uploader text), convert getWhen to a named export, add a batch-scripts redirect route, and update setup-card empty-state copy about enabling MDM and automatic enrollment.

Possibly related PRs

  • fleetdm/fleet#31875: Both PRs touch the custom variables/custom_variables plumbing (endpoints and UI) that this change migrates from the legacy secrets implementation.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fleet UI: Update empty states in Controls' accurately summarizes the main focus of this pull request, which updates empty state UI across multiple Control pages.
Description check ✅ Passed The pull request description is mostly complete. It references the related issues (#44326 and #35483), explains the context (Part 5 of a multi-part effort), includes testing confirmation, and provides comprehensive screenshots showing the empty state updates.
Linked Issues check ✅ Passed The PR addresses multiple objectives from issue #44326, including empty state updates for Controls setup pages (Bootstrap package, Run script, Setup Assistant) and adding OS tabs as specified in the Figma designs.
Out of Scope Changes check ✅ Passed All changes are scoped to Controls empty state updates and variable refactoring. Changes include rename/refactor from 'secrets' to 'variables' API, helper function updates, test additions, and endpoint changes that directly support the empty state implementation objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 35483-empty-states-controls

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx (1)

117-123: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use dynamic count in the mock GET response.

count is tied to mockSecrets.length (static), but add/delete mutate secretsResponse.secrets. This can mask list/pagination regressions in tests after mutations.

💡 Suggested test fix
     const secretsHandler = http.get(baseUrl("/custom_variables"), () => {
       return HttpResponse.json({
         custom_variables: secretsResponse.secrets,
-        count: mockSecrets.length,
+        count: secretsResponse.secrets.length,
         has_prev_results: false,
         has_next_results: false,
       });
     });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx` around lines
117 - 123, The mock GET response currently uses a static count
(mockSecrets.length) which doesn't reflect runtime mutations to
secretsResponse.secrets; update the mock response returned by the
HttpResponse.json call to compute count from the live array (e.g., use
secretsResponse.secrets.length) so adds/deletes in tests change the returned
count and pagination behavior; locate the mock handler that calls
HttpResponse.json and replace the static reference to mockSecrets with a dynamic
length derived from secretsResponse.secrets.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx`:
- Around line 117-123: The mock GET response currently uses a static count
(mockSecrets.length) which doesn't reflect runtime mutations to
secretsResponse.secrets; update the mock response returned by the
HttpResponse.json call to compute count from the live array (e.g., use
secretsResponse.secrets.length) so adds/deletes in tests change the returned
count and pagination behavior; locate the mock handler that calls
HttpResponse.json and replace the static reference to mockSecrets with a dynamic
length derived from secretsResponse.secrets.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: eab7aed5-bf30-4bfc-9d86-d327c8df04fd

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa4d53 and f6b86c6.

📒 Files selected for processing (19)
  • frontend/interfaces/variables.ts
  • frontend/pages/ManageControlsPage/Scripts/ScriptBatchDetailsPage/ScriptBatchDetailsPage.tsx
  • frontend/pages/ManageControlsPage/Scripts/cards/ScriptBatchProgress/ScriptBatchProgress.tests.tsx
  • frontend/pages/ManageControlsPage/Scripts/cards/ScriptBatchProgress/ScriptBatchProgress.tsx
  • frontend/pages/ManageControlsPage/Scripts/cards/ScriptLibrary/ScriptLibrary.tests.tsx
  • frontend/pages/ManageControlsPage/Scripts/cards/ScriptLibrary/ScriptLibrary.tsx
  • frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/ScriptUploader.tsx
  • frontend/pages/ManageControlsPage/Scripts/helpers.tsx
  • frontend/pages/ManageControlsPage/SetupExperience/cards/BootstrapPackage/BootstrapPackage.tests.tsx
  • frontend/pages/ManageControlsPage/SetupExperience/cards/BootstrapPackage/BootstrapPackage.tsx
  • frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx
  • frontend/pages/ManageControlsPage/Variables/Variables.tsx
  • frontend/pages/ManageControlsPage/Variables/_styles.scss
  • frontend/pages/ManageControlsPage/Variables/components/AddCustomVariableModal/AddCustomVariableModal.tsx
  • frontend/pages/ManageControlsPage/Variables/components/DeleteCustomVariableModal/DeleteCustomVariableModal.tsx
  • frontend/services/entities/secrets.tsx
  • frontend/services/entities/variables.tsx
  • frontend/utilities/endpoints.ts
  • website/config/routes.js
💤 Files with no reviewable changes (1)
  • frontend/services/entities/secrets.tsx

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates several “Controls” UI surfaces to use the normalized empty-state patterns (copy, CTAs, and learn-more links), and refactors the “custom variables” frontend API naming from “secrets” to “variables”.

Changes:

  • Normalized empty states and CTAs across Controls (Custom variables, Scripts library, Batch script progress, Bootstrap package).
  • Refactored custom variables frontend plumbing: renamed endpoints key, replaced secrets entity service with variables, and updated related UI/components/tests.
  • Added a website redirect for the new “Learn more about batch scripts” link target.

Reviewed changes

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

Show a summary per file
File Description
website/config/routes.js Adds /learn-more-about/batch-scripts redirect used by the new batch-scripts learn-more links.
frontend/utilities/endpoints.ts Renames the custom variables endpoint key from SECRETS to VARIABLES.
frontend/services/entities/variables.tsx New entity service for listing/creating/deleting custom variables via /custom_variables.
frontend/services/entities/secrets.tsx Removes old custom-variables service named secrets.
frontend/pages/ManageControlsPage/Variables/Variables.tsx Updates custom variables page copy/empty state behavior and swaps to variablesAPI + IVariable.
frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx Updates tests for the custom variables page, including new read-only empty state expectations.
frontend/pages/ManageControlsPage/Variables/components/DeleteCustomVariableModal/DeleteCustomVariableModal.tsx Swaps modal to variable naming and variablesAPI.deleteVariable.
frontend/pages/ManageControlsPage/Variables/components/AddCustomVariableModal/AddCustomVariableModal.tsx Swaps modal to variable naming and variablesAPI.addVariable, updates flash messages.
frontend/pages/ManageControlsPage/Variables/_styles.scss Renames CSS selectors to match updated variables page class names.
frontend/pages/ManageControlsPage/SetupExperience/cards/BootstrapPackage/BootstrapPackage.tsx Updates Bootstrap package empty state copy to the normalized format.
frontend/pages/ManageControlsPage/SetupExperience/cards/BootstrapPackage/BootstrapPackage.tests.tsx Updates assertions to match new Bootstrap package empty state copy.
frontend/pages/ManageControlsPage/Scripts/ScriptBatchDetailsPage/ScriptBatchDetailsPage.tsx Updates getWhen import after helpers refactor (named export).
frontend/pages/ManageControlsPage/Scripts/helpers.tsx Adds shared script-uploader empty-state text constants and converts getWhen to named export.
frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/ScriptUploader.tsx Uses the shared SCRIPT_UPLOADER_TEXT constant for consistent copy.
frontend/pages/ManageControlsPage/Scripts/cards/ScriptLibrary/ScriptLibrary.tsx Replaces empty-state uploader UI with normalized EmptyState + Upload CTA + GitOps wrapper.
frontend/pages/ManageControlsPage/Scripts/cards/ScriptLibrary/ScriptLibrary.tests.tsx Adds automated coverage for Script Library empty state role-based CTA visibility.
frontend/pages/ManageControlsPage/Scripts/cards/ScriptBatchProgress/ScriptBatchProgress.tsx Updates batch progress empty states (copy + learn-more link) and header text.
frontend/pages/ManageControlsPage/Scripts/cards/ScriptBatchProgress/ScriptBatchProgress.tests.tsx Updates tests to match the new empty state rendering (text assertions).
frontend/interfaces/variables.ts Renames ISecret/ISecretPayload to IVariable/IVariablePayload.
Comments suppressed due to low confidence (1)

frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx:122

  • In this list /custom_variables handler, the mocked response doesn’t match the real API shape:
  • Pagination should be under meta: { has_next_results, has_previous_results } (not top-level has_prev_results/has_next_results).
  • count should reflect the current number of returned variables (e.g. secretsResponse.secrets.length), otherwise add/delete flows can behave differently than production when the list becomes empty.
    const secretsHandler = http.get(baseUrl("/custom_variables"), () => {
      return HttpResponse.json({
        custom_variables: secretsResponse.secrets,
        count: mockSecrets.length,
        has_prev_results: false,
        has_next_results: false,
      });

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

Comment thread frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx Outdated
Comment thread frontend/services/entities/variables.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@frontend/pages/ManageControlsPage/SetupExperience/cards/SetupAssistant/SetupAssistant.tests.tsx`:
- Around line 56-58: Prettier formatting requires the regex argument to
screen.getByText to be on the same line; in SetupAssistant.tests.tsx locate the
assertion using screen.getByText(/Turn on MDM and automatic enrollment to
customize/) and put the regex directly inside the parentheses (i.e.,
screen.getByText(/Turn on MDM and automatic enrollment to customize/)) so the
pattern isn't on a separate line.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5c2000e0-52e0-4fd3-bfdd-d1e95bed8892

📥 Commits

Reviewing files that changed from the base of the PR and between b70445c and c9d7794a070718f55f677d28108d971d0bc4099b.

📒 Files selected for processing (1)
  • frontend/pages/ManageControlsPage/SetupExperience/cards/SetupAssistant/SetupAssistant.tests.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx (1)

137-139: ⚡ Quick win

Generate new mock IDs from current state, not a fixed seed.

Line 138 always derives from mockVariables.length, which can duplicate IDs if more than one variable is added in a test.

Suggested fix
-        const newVariable = {
-          id: mockVariables.length + 1,
+        const newVariable = {
+          id: (variablesResponse.variables.at(-1)?.id ?? 0) + 1,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx` around lines
137 - 139, The test creates newVariable with id computed as mockVariables.length
+ 1 which can produce duplicate IDs when multiple variables are added; change
the ID generation in the test helper so it derives from the current IDs (e.g.
compute max ID from mockVariables and add 1, or use a unique generator like
Date.now()/a UUID) instead of using mockVariables.length; update the creation
site referenced as newVariable and any test helpers that append to mockVariables
so each new entry uses the computed unique id.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx`:
- Around line 120-122: The test mock returns metadata count that can drift from
the actual payload; change the mock to derive count from the payload instead of
a fixed value. Replace the hardcoded count (currently using
mockVariables.length) with a dynamic value computed from the returned array
(e.g., count: variablesResponse.variables.length or compute from
custom_variables) so count always reflects the actual custom_variables in
variablesResponse.

In `@frontend/services/mock_service/mocks/responses.ts`:
- Around line 10645-10650: The new variable ID is being pre-incremented using
(nextVariableId += 1) which causes an off-by-one gap; change the assignment so
the current nextVariableId is used and then incremented (e.g., replace
(nextVariableId += 1) with nextVariableId++) when creating the object in the
mockVariables array (the entry containing name: secret.name, id: ...,
created_at: ...), ensuring nextVariableId increments after assignment so IDs
start at the expected value.

---

Nitpick comments:
In `@frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx`:
- Around line 137-139: The test creates newVariable with id computed as
mockVariables.length + 1 which can produce duplicate IDs when multiple variables
are added; change the ID generation in the test helper so it derives from the
current IDs (e.g. compute max ID from mockVariables and add 1, or use a unique
generator like Date.now()/a UUID) instead of using mockVariables.length; update
the creation site referenced as newVariable and any test helpers that append to
mockVariables so each new entry uses the computed unique id.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f77765bd-368f-4639-9064-d2662fb49145

📥 Commits

Reviewing files that changed from the base of the PR and between c9d7794a070718f55f677d28108d971d0bc4099b and e30bd493ccc74feac06adfc9496ebc1a4c7920eb.

📒 Files selected for processing (6)
  • frontend/pages/ManageControlsPage/Scripts/cards/ScriptBatchProgress/ScriptBatchProgress.tsx
  • frontend/pages/ManageControlsPage/SetupExperience/cards/SetupAssistant/SetupAssistant.tests.tsx
  • frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx
  • frontend/pages/ManageControlsPage/Variables/components/AddCustomVariableModal/AddCustomVariableModal.tsx
  • frontend/services/mock_service/mocks/config.ts
  • frontend/services/mock_service/mocks/responses.ts
✅ Files skipped from review due to trivial changes (1)
  • frontend/pages/ManageControlsPage/SetupExperience/cards/SetupAssistant/SetupAssistant.tests.tsx

Comment thread frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx
Comment on lines +10645 to 10650
mockVariables = [
...mockVariables,
{
name: secret.name,
id: (nextSecretId += 1),
id: (nextVariableId += 1),
created_at: new Date().toISOString(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix off-by-one ID assignment for newly added variables.

Line 10649 increments before assignment, so the first created variable skips an ID (starts at 41 instead of 40).

Suggested fix
-      id: (nextVariableId += 1),
+      id: nextVariableId++,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/services/mock_service/mocks/responses.ts` around lines 10645 -
10650, The new variable ID is being pre-incremented using (nextVariableId += 1)
which causes an off-by-one gap; change the assignment so the current
nextVariableId is used and then incremented (e.g., replace (nextVariableId += 1)
with nextVariableId++) when creating the object in the mockVariables array (the
entry containing name: secret.name, id: ..., created_at: ...), ensuring
nextVariableId increments after assignment so IDs start at the expected value.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fixed

Comment thread website/config/routes.js
@@ -1228,6 +1201,7 @@ module.exports.routes = {
'GET /learn-more-about/exe-install-scripts': '/guides/exe-install-scripts',
'GET /learn-more-about/install-scripts': '/guides/deploy-software-packages#install-script',
'GET /learn-more-about/uninstall-scripts': '/guides/deploy-software-packages#uninstall-script',
'GET /learn-more-about/batch-scripts': '/guides/scripts#batch-execute-scripts',

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@eashaw quick review from ya!

Comment on lines +10644 to 10650
nextVariableId += 1;
mockVariables = [
...mockVariables,
{
name: secret.name,
id: (nextSecretId += 1),
name: variable.name,
id: nextVariableId,
created_at: new Date().toISOString(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 🟣 The CodeRabbit suggestion at line 10649 was marked "fixed" in commit 9b1a12f, but the rewrite (nextVariableId += 1; ... id: nextVariableId) is functionally identical to the pre-PR id: (nextSecretId += 1) — both pre-increment before assignment, so the first newly-added variable still gets id=41 instead of 40. The suggested id: nextVariableId++ (post-increment) would have actually fixed the off-by-one. Mock/storybook only — no production or test impact, just worth noting since the comment was resolved without the underlying issue being addressed.

Extended reasoning...

What's wrong

This file initializes nextVariableId = mockVariables.length + 1 = 40 at line 10611, since mockVariables contains 39 entries with ids 1..39. The CodeRabbit suggestion on this exact line was to change id: (nextSecretId += 1) to id: nextVariableId++ (post-increment), so the first newly-added variable would receive id=40 (no gap).

The rewrite in commit 9b1a12f split the increment onto its own line:

nextVariableId += 1;
mockVariables = [
  ...mockVariables,
  {
    name: variable.name,
    id: nextVariableId,
    ...
  },
];

This is functionally identical to the original id: (nextSecretId += 1). Both pre-increment, then assign. So the off-by-one persists.

Step-by-step proof

  1. mockVariables is built with 39 entries via new Array(39).fill(null).map((_, index) => ({ id: index + 1, ... })) — ids 1..39.
  2. nextVariableId = mockVariables.length + 1 = 40.
  3. First call to addVariable: line 10645 runs nextVariableId += 1nextVariableId becomes 41.
  4. Line 10649 assigns id: nextVariableId → new variable gets id=41.
  5. id=40 is never used. The CodeRabbit-suggested post-increment (nextVariableId++) would have used 40 first and incremented after, eliminating the gap.

Why this doesn't bite anything

  • IDs remain unique (gap, not collision), so React keys and parseInt(id, 10) filtering still work.
  • This is frontend/services/mock_service/mocks/responses.ts — only used in the Storybook/local-dev MSW handlers, never production.
  • No tests assert on specific sequential id values.

Fix

-      nextVariableId += 1;
       mockVariables = [
         ...mockVariables,
         {
           name: variable.name,
-          id: nextVariableId,
+          id: nextVariableId++,
           created_at: new Date().toISOString(),
           updated_at: new Date().toISOString(),
         },
       ];

Worth flagging only because the original CodeRabbit suggestion was explicitly marked "fixed" in a reply, but the rewrite kept the pre-increment semantics — so the resolved-comment trail doesn't reflect the actual code state. Severity: nit.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

ok, this was preexisitng and not breaking anything, will followup eventually

@RachelElysia
RachelElysia merged commit 2268960 into main May 13, 2026
26 checks passed
@RachelElysia
RachelElysia deleted the 35483-empty-states-controls branch May 13, 2026 20:53
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.

Fleet UI: Empty states followup

4 participants