Skip to content

chore(playground): Restore Form.Item single child in the connection wizard - #11841

Merged
ovr merged 2 commits into
masterfrom
ci-failure-pr-11839
Sep 10, 2026
Merged

chore(playground): Restore Form.Item single child in the connection wizard#11841
ovr merged 2 commits into
masterfrom
ci-failure-pr-11839

Conversation

@ovr

@ovr ovr commented Sep 10, 2026

Copy link
Copy Markdown
Member

Check List

  • Tests have been run in packages where changes have been made if available
  • Linter has been run for changed code
  • Tests for the changes have been added if not covered yet
  • Docs have been added / updated if required

Description of Changes Made (if issue reference is not provided)

The oxlint migration (#11790) unrolled the nested ternary that picks the input control into three sibling && expressions inside <Form.Item name={param.env}>, and antd 4.16 only injects value/onChange when isValidElement(children) holds — with an array it warns and renders the children untouched, leaving every connection wizard input unbound from the form. That has kept two Cypress birdbox tests red on master since that commit: copies values of the localhost tip box (the tip box's form.setFieldsValue({ CUBEJS_DB_HOST }) never reached the input) and PostgreSQL connection flow -- connects to the DB (typed credentials never landed in form state, so submit posted empty values and the error alert never cleared). This moves the control selection into a DatabaseFormControl helper so Form.Item gets a single child again, with identical logic and no nested ternary. Existing Cypress coverage already exercises both paths, so no new tests were needed; I could not run the linter or Cypress locally because this worktree has no installed node_modules.

🤖 Generated with Claude Code

The oxlint migration (#11790) unrolled the nested ternary picking the
input control into three sibling `&&` expressions inside
`<Form.Item name={param.env}>`. antd 4.16 only injects `value`/`onChange`
when `isValidElement(children)` holds; with an array it warns and renders
the children untouched, leaving every wizard input unbound from the form.

Two Cypress birdbox tests have been red on master since that commit:

| Test | Symptom |
| --- | --- |
| `copies values of the localhost tip box` | `form.setFieldsValue({ CUBEJS_DB_HOST })` never reached the input, so the assertion saw an empty value instead of `host.docker.internal` |
| `PostgreSQL connection flow -- connects to the DB` | typed credentials never landed in form state, so submit posted empty values and the error alert never cleared |

Move the control selection into a `DatabaseFormControl` helper so
`Form.Item` gets a single child again, keeping the logic identical and
free of nested ternaries.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ovr
ovr requested a review from a team as a code owner September 10, 2026 17:04
@github-actions github-actions Bot added client:playground Issues relating to the Developer Playground javascript Pull requests that update Javascript code labels Sep 10, 2026
@claude

claude Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ovr's task in 1m 6s —— View job


Review complete — 1 blocking issue: the fix does not restore form binding

Full review
  • Read the PR diff and the full changed file
  • Check antd/rc-field-form child-cloning semantics against antd@4.16.13
  • Check existing review threads (none)
  • Post findings

Blocking — inputs remain unbound (inline)

The diagnosis in the description is right: Form.Item in antd 4 only injects the control props when isValidElement(children) holds, and the oxlint migration turned the single child into an array of three && expressions.

But the fix moves the problem rather than removing it. Form.Item → rc-field-form Field does roughly React.cloneElement(getOnlyChild(children), { ...control, id, ref }). With <DatabaseFormControl param={param} /> as the child, value, onChange, id and the item ref are now injected into DatabaseFormControl — whose signature is ({ param }). Every injected prop is discarded, and the inner Input/Input.Password/Input.TextArea still gets no value/onChange.

Concrete failure: both Cypress specs named in the description should still be red.

  • copies values of the localhost tip boxform.setFieldsValue({ CUBEJS_DB_HOST }) updates form state, but the Input never reads value, so the field stays visually empty.
  • PostgreSQL connection flow -- connects to the DB — typed characters never reach onChange, so onFinish posts empty credentials.

Secondary: passing a ref to a plain function component triggers React's "Function components cannot be given refs" warning; antd uses that ref for scrollToField/focus.

The inline comment carries a suggested patch — turn DatabaseFormControl into a plain helper databaseFormControl(param) returning the element, invoked as {databaseFormControl(param)}. That keeps the nested ternary gone (the stated oxlint motivation) while letting antd clone the real Input, which is byte-for-byte the pre-#11790 behaviour. A forwardRef component that spreads ...props also works but is more machinery for the same result.

Other observations

  • Control-selection logic is otherwise a faithful transcription of the original three branches — !titleTextArea, CUBEJS_DB_PASSPassword, else Input. No behaviour drift there.
  • param is untyped (implicit any) in a .tsx file, but that matches the surrounding DatabaseForm props, so not worth churning here.
  • No new tests needed — existing Cypress coverage does exercise both paths, as the description says. Worth actually running them against the patch before merge, since they are the acceptance criteria for this fix.
  • No security or performance concerns; the change is render-local.

I could not run the linter or Cypress either — this checkout has no installed node_modules. The finding above is from reading rc-field-form's cloning contract against the pinned antd@4.16.13, not from a live run, so please confirm with the birdbox suite.

· branch [`ci-failure-pr-11839`](https://github.com/cube-js/cube/tree/ci-failure-pr-11839)

@ovr ovr changed the title fix(playground): restore Form.Item single child in the connection wizard chore(playground): Restore Form.Item single child in the connection wizard Sep 10, 2026
Comment thread packages/cubejs-playground/src/pages/ConnectionWizard/components/DatabaseForm.tsx Outdated
@codecov

codecov Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.22%. Comparing base (1699910) to head (0d813d3).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #11841      +/-   ##
==========================================
+ Coverage   60.16%   60.22%   +0.05%     
==========================================
  Files         239      239              
  Lines       19206    19177      -29     
  Branches     3886     3881       -5     
==========================================
- Hits        11556    11550       -6     
+ Misses       7100     7077      -23     
  Partials      550      550              
Flag Coverage Δ
cube-backend 60.22% <ø> (+0.05%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

…input

The previous commit moved the control selection into a `DatabaseFormControl`
component, which did not fix anything: `Form.Item` clones its single child and
injects `value`/`onChange`, so those props landed on the wrapper component,
which dropped them, and the `<Input>` stayed unbound exactly as before.

Call the helper during render instead, so `Form.Item` receives the `<Input>`
element itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ovr's task in 1m 5s —— View job


Re-review after 0d813d3 — the fix is now correct; no blocking issues (0 high, 0 medium, 2 low)

Full review

The previous blocker is resolved

0d813d3 applied the suggested shape: DatabaseFormControl became a plain helper databaseFormControl(param) that returns the element, invoked as {databaseFormControl(param)} at DatabaseForm.tsx:80. Form.Item's only child is now a real Input / Input.Password / Input.TextArea element, so rc-field-form's cloneElement(getOnlyChild(children), { ...control, id, ref }) injects value/onChange/id/ref onto the input itself. No function component sits in the way, so the earlier "Function components cannot be given refs" concern is gone too.

I diffed the head version against 98eb17b~1 (the commit before the oxlint migration). It is logically identical:

param pre-#11790 head
no title Input.TextArea rows={1}, overflow: hidden, resize: none same
title, env === 'CUBEJS_DB_PASS' Input.Password same
title, other Input same

data-testid={param.env} is present on all three branches (:10, :21, :24) — that matters, since the birdbox specs select by it. The nested ternary that #11790 objected to is gone, replaced by early returns in a named helper, so the oxlint motivation still holds.

That should un-red both specs named in the description: copies values of the localhost tip box (the Input now reads injected value, so form.setFieldsValue({ CUBEJS_DB_HOST }) becomes visible) and PostgreSQL connection flow -- connects to the DB (keystrokes reach the injected onChange, so onFinish posts real credentials). Reasoning from the cloning contract, not a live run — this checkout has no node_modules, so I could run neither oxlint nor Cypress. The birdbox suite is the acceptance criterion; please confirm it goes green before merge. CI on this head is still in progress at the time of writing.

Low

  • Stale PR description. The body still describes the fix as "moves the control selection into a DatabaseFormControl helper", which was the first commit's approach. Worth a one-line edit before merge so the merge commit message matches the code (databaseFormControl(param), a function returning the element — not a component).
  • param is untyped (implicit any) in a .tsx file. Consistent with the surrounding DatabaseForm props, which are also untyped, so not worth churning in a CI-unblocking PR — just noting it if anyone types this file later.

Other observations

  • Extracting the helper above the component (module scope, not re-created per render) is the right call — a nested definition would allocate a new function identity each render for no benefit.
  • No new tests needed, as the description says: existing Cypress coverage exercises all three control branches.
  • No security or performance implications; the change is render-local with no new data flow.
  • Resolved my one prior inline thread — the concern no longer applies to the current diff.
· branch [`ci-failure-pr-11839`](https://github.com/cube-js/cube/tree/ci-failure-pr-11839)

@ovr
ovr merged commit 5517eed into master Sep 10, 2026
39 checks passed
@ovr
ovr deleted the ci-failure-pr-11839 branch September 10, 2026 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client:playground Issues relating to the Developer Playground javascript Pull requests that update Javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants