Skip to content

Add test monitor developer tool page#7565

Merged
jpople merged 11 commits intomainfrom
jpople/2026-03-04/test-monitor-flow
Mar 6, 2026
Merged

Add test monitor developer tool page#7565
jpople merged 11 commits intomainfrom
jpople/2026-03-04/test-monitor-flow

Conversation

@jpople
Copy link
Contributor

@jpople jpople commented Mar 4, 2026

Ticket

Description Of Changes

I got tired of copy-pasting JSONs into Swagger, so adds a dev-only UI for seeding monitor data using the test-datastore and test-website monitors.

Code Changes

  • New page at src/pages/poc/test-monitors.tsx with two monitor cards (TestDatastoreMonitor, TestWebsiteMonitor) and shared utilities
  • Nav entry added under the Developer section

Steps to Confirm

  1. Run the dev environment with FIDES__DEV_MODE=true
  2. Navigate to Developer → Test Monitors in the sidebar
  3. Click Create and run on either card — a success toast should appear with the execution ID
  4. View the results in the Action Center

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Add a db-migration This indicates that a change includes a database migration label to the entry if your change includes a DB migration
    • Add a high-risk This issue suggests changes that have a high-probability of breaking existing code label to the entry if your change includes a high-risk change (i.e. potential for performance impact or unexpected regression) that should be flagged
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
    • No UX review needed
  • Followup issues:
    • Followup issues created
    • No followup issues
  • Database migrations:
    • No migrations
  • Documentation:
    • No documentation updates required

Summary by CodeRabbit

  • New Features

    • Added a Test Monitors developer tool page (visible in development builds) for seeding test data.
    • Datastore Monitor: configure and run test datastore generation with customizable counts and nesting; includes randomize and reset.
    • Website Monitor: configure and run test website scenarios with adjustable asset counts and consent/vendor percentages; includes randomize and reset.
    • Run actions display execution status and success/error messages, including optional execution IDs.
  • Chore

    • Added changelog entry for the new developer tool.

@vercel
Copy link
Contributor

vercel bot commented Mar 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fides-plus-nightly Ready Ready Preview, Comment Mar 5, 2026 5:24pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Mar 5, 2026 5:24pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

📝 Walkthrough

Walkthrough

Adds a developer-only Test Monitors page with two UI components (datastore and website), a new route and nav entry, supporting utils, mutation-driven flows to patch connections, put monitors, execute monitors, and a changelog entry documenting the addition.

Changes

Cohort / File(s) Summary
Changelog & Navigation
changelog/7565-test-monitor-developer-tool.yaml, clients/admin-ui/src/features/common/nav/routes.ts, clients/admin-ui/src/features/common/nav/nav-config.tsx
New changelog entry; export TEST_MONITORS_ROUTE (/poc/test-monitors); added "Test Monitors" nav item under Developer, shown only in development.
Monitor UI Components
clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx, clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx
New React TSX components rendering forms for monitor parameters, randomize/reset helpers, and a run flow that patches a test connection, creates/updates a discovery monitor, and executes it with user-facing messages and running-state handling.
Utilities
clients/admin-ui/src/features/test-monitors/utils.ts
Added generateDefaultKey(prefix) and randInt(min,max) helpers used by the monitor components.
Page
clients/admin-ui/src/pages/poc/test-monitors.tsx
New Next.js page composing the Test Monitors UI and rendering both monitor components within the admin layout.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant UI as TestDatastoreMonitor (Form)
    participant Mutations as Mutation Hooks
    participant API as Backend API

    User->>UI: Fill form & click Run
    UI->>Mutations: patchConnection(params)
    Mutations->>API: PATCH /connections
    API-->>Mutations: connection response

    UI->>Mutations: putMonitor(monitorConfig)
    Mutations->>API: PUT /monitors
    API-->>Mutations: monitor response

    UI->>Mutations: executeMonitor(monitorId)
    Mutations->>API: POST /monitors/:id/execute
    API-->>Mutations: execution result

    Mutations-->>UI: success (execution id)
    UI->>User: show success & update UI
Loading
sequenceDiagram
    actor User
    participant UI as TestWebsiteMonitor (Form)
    participant Mutations as Mutation Hooks
    participant API as Backend API

    User->>UI: Configure & click Create and run
    UI->>Mutations: patchConnection(siteParams)
    Mutations->>API: PATCH /connections
    API-->>Mutations: connection response

    UI->>Mutations: putMonitor(websiteMonitorConfig)
    Mutations->>API: PUT /monitors
    API-->>Mutations: monitor response

    UI->>Mutations: executeMonitor(monitorId)
    Mutations->>API: POST /monitors/:id/execute
    API-->>Mutations: execution result

    Mutations-->>UI: success (execution id)
    UI->>User: show success & reset/new monitor name
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • speaker-ender

Poem

🐰 I hopped in with keys and random seeds,
Two monitors ready for testing deeds.
Patch, create, execute — a cheerful run,
Dev-only tools to seed the fun!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% 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 title 'Add test monitor developer tool page' clearly and concisely describes the main change—adding a new developer-only UI page for test monitors.
Description check ✅ Passed The PR description includes all key sections: description of changes, code changes list, confirmation steps, and pre-merge checklist with relevant items completed.

✏️ 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 jpople/2026-03-04/test-monitor-flow

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

@jpople jpople marked this pull request as ready for review March 4, 2026 20:08
@jpople jpople requested a review from a team as a code owner March 4, 2026 20:08
@jpople jpople requested review from gilluminate and removed request for a team March 4, 2026 20:08
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 4, 2026

Greptile Summary

This PR adds a developer-only UI page at /poc/test-monitors for quickly seeding test data through the configurable test-datastore and test-website monitors, replacing the previous workflow of manually crafting JSON payloads in Swagger. The feature is correctly gated behind NEXT_PUBLIC_APP_ENV === "development" and fits neatly into the existing poc/ page pattern.

Key findings:

  • Key/name mismatch when entering a custom monitor name (TestDatastoreMonitor.tsx, TestWebsiteMonitor.tsx): When a user types a custom name that differs from the auto-generated default, the logic generates a fresh timestamp key instead of using the user's input as the key — the typed value only becomes the monitor's display name. The form also resets to a new auto-key on success, so the custom name is discarded entirely. If the field is purely cosmetic, the label should clarify this.
  • Consent percentage sum can exceed 100% (TestWebsiteMonitor.tsx): randomizeParams draws consent_granted_percentage (30–90) and consent_denied_percentage (0–30) independently, allowing their combined total to reach 120%, which is semantically invalid.
  • Empty scopes on the Test Monitors nav entry (nav-config.tsx): Sibling dev-mode entries require ScopeRegistryEnum.DEVELOPER_READ; this entry uses scopes: [], making it visible to any authenticated dev-mode user regardless of scope. This may be intentional but warrants a clarifying comment.

Confidence Score: 4/5

  • Safe to merge with minor fixes — this is a dev-only tool with no production impact.
  • The page is correctly gated to development mode only and touches no production code paths. The issues found (key/name mismatch, consent percentage overflow in randomizer, empty scopes) are all low-severity within the context of a developer convenience tool, but the consent percentage bug and the silent key override could confuse developers using the tool.
  • TestDatastoreMonitor.tsx and TestWebsiteMonitor.tsx — both share the key/name mismatch logic, and TestWebsiteMonitor also has the consent percentage randomization issue.

Important Files Changed

Filename Overview
clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx New card component for seeding test datastore monitor data; has a subtle key/name mismatch when the user enters a custom monitor name — the user's input only becomes the display name while the actual connection/monitor key is a newly generated timestamp value.
clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx New card component for seeding test website monitor data; shares the same key/name mismatch as TestDatastoreMonitor, and the randomize logic for consent percentages can generate consent_granted + consent_denied values that sum above 100%.
clients/admin-ui/src/features/common/nav/nav-config.tsx Adds "Test Monitors" nav entry under the dev-only section with empty scopes, deviating from the sibling entries that require ScopeRegistryEnum.DEVELOPER_READ.
clients/admin-ui/src/features/common/nav/routes.ts Adds TEST_MONITORS_ROUTE constant; straightforward, no issues.
clients/admin-ui/src/features/test-monitors/utils.ts Small utility module providing generateDefaultKey (timestamp-based slug) and randInt helpers; clean and correct.
clients/admin-ui/src/pages/poc/test-monitors.tsx New poc page that composes the two monitor cards inside a responsive Flex layout; clean and straightforward.
changelog/7565-test-monitor-developer-tool.yaml Changelog entry for the new developer tool page; no issues.

Last reviewed commit: b520a5e

Comment on lines +59 to +69
function randomizeParams(): Omit<FormValues, "monitor_name"> {
return {
num_cookies: randInt(5, 50),
num_javascript_requests: randInt(5, 30),
num_image_requests: randInt(1, 20),
num_iframe_requests: randInt(0, 10),
num_browser_requests: randInt(2, 20),
consent_granted_percentage: randInt(30, 90),
consent_denied_percentage: randInt(0, 30),
vendor_match_percentage: randInt(20, 90),
};
Copy link
Contributor

Choose a reason for hiding this comment

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

consent_granted_percentage + consent_denied_percentage can exceed 100%

randomizeParams draws consent_granted_percentage from randInt(30, 90) and consent_denied_percentage independently from randInt(0, 30). Their sum can reach up to 120% (e.g. 90 granted + 30 denied), which is semantically invalid — the two values together with "no consent" should sum to ≤ 100%.

Consider constraining the second value so granted + denied ≤ 100, for example by capping denied at 100 - granted.

Copy link

@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 (2)
clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx (1)

82-96: Consider validating the form before proceeding.

The monitor_name field is typed as optional and accessed with a non-null assertion (monitorName!). While the form has a required: true rule, handleRun doesn't trigger form validation before proceeding. If validation fails silently, this could lead to a runtime issue.

🛡️ Suggested approach to validate before running
  const handleRun = async () => {
+   try {
+     await form.validateFields();
+   } catch {
+     return;
+   }
    const {
      monitor_name: monitorName,
      consent_granted_percentage: grantedPct,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx` around
lines 82 - 96, The handleRun function uses form.getFieldsValue and a non-null
assertion on monitor_name (monitorName!) without validating the form; change it
to call and await form.validateFields() (or form.validateFields([...required
fields])) at the start of handleRun, use the returned validated values instead
of form.getFieldsValue, remove the non-null assertion when assigning name, and
handle validation errors by aborting the run so you never proceed with
missing/invalid fields; reference handleRun, form.getFieldsValue, monitor_name,
and the name assignment when making the change.
clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx (1)

73-83: Consider validating the form before proceeding.

Same pattern as TestWebsiteMonitor — the monitor_name field uses a non-null assertion without explicit form validation. Consider adding await form.validateFields() at the start of handleRun for consistency and safety.

🛡️ Suggested approach
  const handleRun = async () => {
+   try {
+     await form.validateFields();
+   } catch {
+     return;
+   }
    const {
      monitor_name: monitorName,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx` around
lines 73 - 83, The handler handleRun should validate the form before reading
values: call await form.validateFields() at the start of handleRun (same pattern
as TestWebsiteMonitor) so monitor_name and other fields are guaranteed valid;
then read values from form.getFieldsValue(), drop the unsafe non-null assertion
on monitorName or keep it only after successful validation, and ensure any
validation errors are allowed to surface (or caught and returned) so you don't
proceed with undefined monitor_name or invalid nested_field_percentage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx`:
- Around line 73-83: The handler handleRun should validate the form before
reading values: call await form.validateFields() at the start of handleRun (same
pattern as TestWebsiteMonitor) so monitor_name and other fields are guaranteed
valid; then read values from form.getFieldsValue(), drop the unsafe non-null
assertion on monitorName or keep it only after successful validation, and ensure
any validation errors are allowed to surface (or caught and returned) so you
don't proceed with undefined monitor_name or invalid nested_field_percentage.

In `@clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx`:
- Around line 82-96: The handleRun function uses form.getFieldsValue and a
non-null assertion on monitor_name (monitorName!) without validating the form;
change it to call and await form.validateFields() (or
form.validateFields([...required fields])) at the start of handleRun, use the
returned validated values instead of form.getFieldsValue, remove the non-null
assertion when assigning name, and handle validation errors by aborting the run
so you never proceed with missing/invalid fields; reference handleRun,
form.getFieldsValue, monitor_name, and the name assignment when making the
change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 75d7e922-4f37-42f2-8d5f-b3e0ac3f3aaa

📥 Commits

Reviewing files that changed from the base of the PR and between bb5b67f and b520a5e.

📒 Files selected for processing (7)
  • changelog/7565-test-monitor-developer-tool.yaml
  • clients/admin-ui/src/features/common/nav/nav-config.tsx
  • clients/admin-ui/src/features/common/nav/routes.ts
  • clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx
  • clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx
  • clients/admin-ui/src/features/test-monitors/utils.ts
  • clients/admin-ui/src/pages/poc/test-monitors.tsx

setIsRunning(false);
return;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: the three sequential awaits aren't wrapped in try/catch, so if any of them reject (vs returning an error result), setIsRunning(false) never fires and the button gets stuck in a permanent loading state. You'd have to refresh the page.

A try/catch/finally would fix it and also let you drop the three duplicated setIsRunning(false) calls:

const handleRun = async () => {
  setIsRunning(true);
  try {
    // ... existing logic, minus the setIsRunning(false) in each early return ...
  } catch (e) {
    message.error('Unexpected error');
  } finally {
    setIsRunning(false);
  }
};

Same pattern applies in TestWebsiteMonitor.tsx.

setIsRunning(true);

const connResult = await patchConnection({
key,
Copy link
Contributor

Choose a reason for hiding this comment

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

This key logic is a bit hard to follow — if the user edits the name field, this branch generates a new timestamp-based key that differs from both the auto-key and the user's input. So key and name silently diverge, which could be confusing when debugging monitor results.

Would it be simpler to either always use name as the key (slugified if needed), or always generate a fresh key regardless of what the user typed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I think I overengineered this one a bit. I've simplified so it uses the autogenerated key for the connection name and key and the monitor key and the name field just changes the monitor name.

Copy link

@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 (1)
clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx (1)

200-232: Consider adding validation that granted + denied percentages do not exceed 100.

The form allows users to manually input values where consent_granted_percentage + consent_denied_percentage > 100 (e.g., 80% granted + 50% denied = 130%). While randomizeParams() prevents this, manual entry does not. This could lead to unexpected behavior when the values are converted to fractions and passed to the API.

💡 Suggested approach using form-level validation

Add a custom validator to one of the percentage fields:

<Form.Item
  label="Denied %"
  name="consent_denied_percentage"
  rules={[
    {
      validator: async (_, value) => {
        const granted = form.getFieldValue("consent_granted_percentage") ?? 0;
        if (granted + (value ?? 0) > 100) {
          throw new Error("Granted + Denied cannot exceed 100%");
        }
      },
    },
  ]}
  dependencies={["consent_granted_percentage"]}
>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx` around
lines 200 - 232, The grant/deny percentage fields (Form.Item names
"consent_granted_percentage" and "consent_denied_percentage") need form-level
validation so their sum cannot exceed 100; add a custom validator rule to the
denied field (or both fields) that uses
form.getFieldValue("consent_granted_percentage") and checks granted + (value ??
0) <= 100, mark the field invalid with an error message if it exceeds 100, and
include dependencies={["consent_granted_percentage"]} on the Form.Item so
changes revalidate; this mirrors the protection in randomizeParams() but
enforces it for manual input.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx`:
- Around line 200-232: The grant/deny percentage fields (Form.Item names
"consent_granted_percentage" and "consent_denied_percentage") need form-level
validation so their sum cannot exceed 100; add a custom validator rule to the
denied field (or both fields) that uses
form.getFieldValue("consent_granted_percentage") and checks granted + (value ??
0) <= 100, mark the field invalid with an error message if it exceeds 100, and
include dependencies={["consent_granted_percentage"]} on the Form.Item so
changes revalidate; this mirrors the protection in randomizeParams() but
enforces it for manual input.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ac0d6a4-e799-4f42-a49c-269964ca766e

📥 Commits

Reviewing files that changed from the base of the PR and between b520a5e and 7191848.

📒 Files selected for processing (4)
  • clients/admin-ui/src/features/common/nav/nav-config.tsx
  • clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx
  • clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx
  • clients/admin-ui/src/pages/poc/test-monitors.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • clients/admin-ui/src/pages/poc/test-monitors.tsx
  • clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx
  • clients/admin-ui/src/features/common/nav/nav-config.tsx

Copy link

@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

🧹 Nitpick comments (1)
clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx (1)

202-208: Clarify reset behavior for monitor name.

The button label says “Reset to default” but only numeric params are reset; monitor_name is preserved. Either include monitor_name: key in reset or rename to “Reset params” for clarity.

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

In `@clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx` around
lines 202 - 208, The reset button in TestDatastoreMonitor currently calls
form.setFieldsValue({ ...DEFAULT_PARAMS }) which leaves monitor_name unchanged;
update the onClick to include monitor_name: key (i.e. form.setFieldsValue({
...DEFAULT_PARAMS, monitor_name: key })) so the monitor name resets too,
referencing the DEFAULT_PARAMS constant, the form.setFieldsValue call, and the
monitor_name field in the TestDatastoreMonitor component; alternatively, if you
prefer preserving the name, rename the Button label from "Reset to default" to
"Reset params" to match current behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx`:
- Around line 73-87: handleRun currently only relies on validateFields() for
monitor_name, so numeric inputs like nested_field_percentage can be
undefined/invalid and cause nestedFieldPct / 100 to produce bad payloads; add
required and numeric validation rules to the form schema for fields such as
nested_field_percentage (and any other numeric fields used in params) or
explicitly validate/normalize values after form.getFieldsValue() inside
handleRun (e.g., check that nestedFieldPct is a finite number, provide a default
or show validation error and return) before constructing params; update
references in handleRun and the form field declarations to use these validators
so params only contain valid numeric values.

---

Nitpick comments:
In `@clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx`:
- Around line 202-208: The reset button in TestDatastoreMonitor currently calls
form.setFieldsValue({ ...DEFAULT_PARAMS }) which leaves monitor_name unchanged;
update the onClick to include monitor_name: key (i.e. form.setFieldsValue({
...DEFAULT_PARAMS, monitor_name: key })) so the monitor name resets too,
referencing the DEFAULT_PARAMS constant, the form.setFieldsValue call, and the
monitor_name field in the TestDatastoreMonitor component; alternatively, if you
prefer preserving the name, rename the Button label from "Reset to default" to
"Reset params" to match current behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59d1ee2a-78df-4902-b0b2-9629aca5a05e

📥 Commits

Reviewing files that changed from the base of the PR and between 7191848 and 32b5cd1.

📒 Files selected for processing (2)
  • clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx
  • clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • clients/admin-ui/src/features/test-monitors/TestWebsiteMonitor.tsx

Comment on lines +73 to +87
const handleRun = async () => {
try {
await form.validateFields();
} catch {
return;
}
const {
monitor_name: monitorName,
nested_field_percentage: nestedFieldPct,
...rest
} = form.getFieldsValue();
const params = {
...rest,
nested_field_percentage: nestedFieldPct / 100,
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add required validation for numeric fields before building monitor params.

validateFields() currently enforces only monitor_name (Line 150). If numeric inputs are empty/invalid, Line 86 can produce an invalid payload (nestedFieldPct / 100), causing avoidable API failures.

Proposed fix
        <Form.Item
          label="Monitor name"
          name="monitor_name"
          rules={[{ required: true }]}
        >
          <Input />
        </Form.Item>
...
-            <Form.Item label="Databases" name="num_databases">
+            <Form.Item
+              label="Databases"
+              name="num_databases"
+              rules={[{ required: true, type: "number", min: 1 }]}
+            >
               <InputNumber min={1} className="w-full" />
             </Form.Item>
...
-            <Form.Item label="Schemas / DB" name="num_schemas_per_db">
+            <Form.Item
+              label="Schemas / DB"
+              name="num_schemas_per_db"
+              rules={[{ required: true, type: "number", min: 1 }]}
+            >
               <InputNumber min={1} className="w-full" />
             </Form.Item>
...
-            <Form.Item label="Tables / schema" name="num_tables_per_schema">
+            <Form.Item
+              label="Tables / schema"
+              name="num_tables_per_schema"
+              rules={[{ required: true, type: "number", min: 1 }]}
+            >
               <InputNumber min={1} className="w-full" />
             </Form.Item>
...
-            <Form.Item label="Fields / table" name="num_fields_per_table">
+            <Form.Item
+              label="Fields / table"
+              name="num_fields_per_table"
+              rules={[{ required: true, type: "number", min: 1 }]}
+            >
               <InputNumber min={1} className="w-full" />
             </Form.Item>
...
-            <Form.Item label="Max nesting level" name="max_nesting_level">
+            <Form.Item
+              label="Max nesting level"
+              name="max_nesting_level"
+              rules={[{ required: true, type: "number", min: 0 }]}
+            >
               <InputNumber min={0} className="w-full" />
             </Form.Item>
...
-            <Form.Item label="Nested field %" name="nested_field_percentage">
+            <Form.Item
+              label="Nested field %"
+              name="nested_field_percentage"
+              rules={[{ required: true, type: "number", min: 0, max: 100 }]}
+            >
               <InputNumber
                 min={0}
                 max={100}

Also applies to: 147-189

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

In `@clients/admin-ui/src/features/test-monitors/TestDatastoreMonitor.tsx` around
lines 73 - 87, handleRun currently only relies on validateFields() for
monitor_name, so numeric inputs like nested_field_percentage can be
undefined/invalid and cause nestedFieldPct / 100 to produce bad payloads; add
required and numeric validation rules to the form schema for fields such as
nested_field_percentage (and any other numeric fields used in params) or
explicitly validate/normalize values after form.getFieldsValue() inside
handleRun (e.g., check that nestedFieldPct is a finite number, provide a default
or show validation error and return) before constructing params; update
references in handleRun and the form field declarations to use these validators
so params only contain valid numeric values.

Copy link
Contributor

@gilluminate gilluminate left a comment

Choose a reason for hiding this comment

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

Changes look good, thanks.

@jpople jpople added this pull request to the merge queue Mar 6, 2026
Merged via the queue into main with commit b942798 Mar 6, 2026
46 of 47 checks passed
@jpople jpople deleted the jpople/2026-03-04/test-monitor-flow branch March 6, 2026 16:42
mfbrown pushed a commit that referenced this pull request Mar 12, 2026
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.

2 participants