Skip to content

test(form): run money forced values through every engine and strategy - #1432

Closed
gabrielseco wants to merge 11 commits into
mainfrom
test/money-engine-contract
Closed

gabrielseco wants to merge 11 commits into
mainfrom
test/money-engine-contract

Conversation

@gabrielseco

Copy link
Copy Markdown
Collaborator

Summary

Adds one test suite that checks money amounts are handled in cents for every combination of form engine and form setup the SDK uses. It fails on the Portugal allowance regression from #1195, which none of the existing tests caught.

Why

  • Two separate switches decide how a form behaves:
    • The server's schema metadata picks the kit engine (jsf v0 or v1, and v1 when there's no metadata).
    • The SDK's own country list picks the strategy: rebuild the form on every change, or build it once and call handleValidation.
  • Money is converted to cents in a different place for each strategy. Existing tests only covered the combinations their fixtures happened to use.
  • feat(playground) - fix france arch problems only on playground #1195 changed a shared default and broke only the rebuild strategy when options are passed, so nothing failed.
  • This tests the rule itself ("the engine sees money in cents") across every combination, instead of adding one more test per country.

What changed

Toggle details
  • New src/common/tests/moneyEngineContract.test.ts. It uses the existing Portugal contract details fixture with its x-rmt-meta replaced per engine: 3 engines × 3 strategies × 10 cases = 90 tests.
  • Each strategy has a small harness that follows the real call order:
    • rebuild: createHeadlessForm(schema, values, options) on each render, and handleValidation only on validate or submit.
    • build once: a single createHeadlessForm(schema, {}, { transformMoneyFields: false }), then handleValidation on every change, the way checkFieldUpdates does it.
    • Forced values are fed back into form state between renders, the way ForcedValueField does.
  • An earlier draft ran handleValidation on every rebuild render. That recomputed the const from cents and hid the regression. Rendering and validating have to be separate steps, or the suite passes on broken code.
  • Cases: the forced allowance in cents and its display text (regime yes and no); the allowance computed from the forced 40 hours, and from typed part-time hours; recomputing on the same form when the regime changes; the allowance dropped once extended hours are off; the full-time minimum salary checked in cents; a conditional nullable money field (signing_bonus_amount); forced acknowledgement strings submitted as their const.
  • Verified against a revert: with createHeadlessForm restored to feat(playground) - fix france arch problems only on playground #1195's options || { transformMoneyFields: true }, 11 tests fail, all in the rebuild with jsfModify column and on all three engines. The other columns pass either way. That's expected, since they aren't affected by the trap.
  • Not included, possible follow-ups:
    • A flow-level it.each over a rebuild country and a build-once country.
    • A made-up minimal schema, so the suite doesn't depend on Portugal's fixture.
    • Refreshing the Portugal fixture: production serves it without x-rmt-meta and with a 1288000 minimum, while the fixture pins v0 and 1218000.
  • Test-only. No public API change.

Screenshots

N/A

Related Resources

Testing

🤖 Generated with Claude Code

cammellos and others added 10 commits September 29, 2026 18:32
Portugal's extended work hours allowance is a forced money value computed
from the salary. Onboarding built its render-time form without converting
money fields to cents, so the allowance was computed from the salary in
major units (100x too small), and the forced value was then written into
the form state in cents while the form keeps money in major units.
Validation recomputed the correct value and rejected the submission on a
field with no input to show the error, blocking the step.

- Onboarding's useJSONSchemaForm passes transformMoneyFields: true, since
  createHeadlessForm only defaults it on when no options are passed.
- Forced money values are converted from cents before being set in the form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Default transformMoneyFields to true whenever it's not explicitly set,
instead of only when the whole options object is missing. Callers that
pass options without transformMoneyFields (e.g. only jsfModify) now get
money fields converted to cents too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tails path

The flow regression test only covers the legacy path while PRT is outside
JSF_V1_CONTRACT_DETAILS_COUNTRIES. These test the Onboarding useJSONSchemaForm
hook and JSONSchemaFormFields directly, so they keep covering the fix
whichever countries are on v1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Submitting a forced value already uses the field's `const` in cents
(parseFormValuesToAPI overwrites the form value with it), and the default
forced value component doesn't render `value`. The `transformMoneyFields`
change alone fixes the PRT allowance; getForcedValue would only change
what custom forcedValue components receive in `fieldData.value`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Correct submission of forced money values relies on parseFormValuesToAPI
overwriting the form value with the field's const. Covers a top-level field
and one nested in a fieldset; both fail with 100x the amount without it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
createHeadlessForm now defaults transformMoneyFields per key (#1426), so
the explicit override in useJSONSchemaForm is redundant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Runs the Portugal contract details schema through each combination of
kit engine (jsf v0, jsf v1, no meta) and SDK form strategy (rebuild
without options, rebuild with jsfModify, build once + handleValidation),
and asserts the same money rules in every cell: computed forced values
and their text in cents, forced non-money values untouched, dependent
recomputation, visibility on submit, money minimum validation.

With the #1195 default restored, the 11 rebuild-with-jsfModify cases
fail on all three engines; every other cell passes either way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

Metric Current Previous Change Status
Total (gzip) 167.23 kB 167.23 kB 0 B (0%) 🟢
Total (raw) 559.17 kB 559.17 kB 0 B (0%) 🟢
CSS (gzip) 21.94 kB 21.94 kB 0 B (0%) 🟢
CSS (raw) 114.43 kB 114.43 kB 0 B (0%) 🟢

Size Limits

  • ✅ Total gzipped: 167.23 kB / 350 kB (47.8%)
  • ✅ Total raw: 559.17 kB / 850 kB (65.8%)
  • ✅ CSS gzipped: 21.94 kB / 25 kB (87.8%)

Largest Files (Top 5)

  1. CheckBoxField-CBXcXbix.js - 24.61 kB (0 B (0%))
  2. ContractorOnboarding-mgqIYo0S.js - 13.54 kB (0 B (0%))
  3. Onboarding-CesFBlFc.js - 11.27 kB (0 B (0%))
  4. Termination-C97V8csk.js - 11.08 kB (0 B (0%))
  5. styles.css - 10.97 kB (0 B (0%))
View All Files (75 total)
File Size (gzip) Change
CheckBoxField-CBXcXbix.js 24.61 kB 0 B (0%)
ContractorOnboarding-mgqIYo0S.js 13.54 kB 0 B (0%)
Onboarding-CesFBlFc.js 11.27 kB 0 B (0%)
Termination-C97V8csk.js 11.08 kB 0 B (0%)
styles.css 10.97 kB 0 B (0%)
index.css 10.97 kB 0 B (0%)
CostCalculator-D7zKfNSe.js 10.68 kB 0 B (0%)
internals-CQxsI0di.js 8.23 kB 0 B (0%)
index.js 5.05 kB 0 B (0%)
JSONSchemaForm-DZ8d227x.js 4.92 kB 0 B (0%)

✅ Bundle size check passed

…verted

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Deploy preview for adp-cost-calculator ready!

Project:adp-cost-calculator
Status: ✅  Deploy successful!
Preview URL:https://adp-cost-calculator-im50l1gzz-remotecom.vercel.app
Latest Commit:a36e344

Deployed with vercel-action

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Deploy preview for remote-flows ready!

Project:remote-flows
Status: ✅  Deploy successful!
Preview URL:https://remote-flows-75a3tip9s-remotecom.vercel.app
Latest Commit:a36e344

Deployed with vercel-action

@github-actions

Copy link
Copy Markdown
Contributor

📊 Coverage Report

✅ Coverage increased! 🎉

Metric Current Previous Change Status
Lines 86.41% 86.41% 0% ⚪
Statements 85.98% 85.98% 0% ⚪
Functions 84.92% 84.92% 0% ⚪
Branches 77.96% 77.93% +0.03% 🟢

Detailed Breakdown

Lines Coverage
  • Covered: 4853 / 5616
  • Coverage: 86.41%
  • Change: 0% (0 lines)
Statements Coverage
  • Covered: 4937 / 5742
  • Coverage: 85.98%
  • Change: 0% (0 statements)
Functions Coverage
  • Covered: 1290 / 1519
  • Coverage: 84.92%
  • Change: 0% (0 functions)
Branches Coverage
  • Covered: 3010 / 3861
  • Coverage: 77.96%
  • Change: +0.03% (1 branches)

✅ Coverage check passed

Base automatically changed from refactor/drop-get-forced-value to main September 30, 2026 09:49
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