Skip to content

feat(reactjs-todo-davinci): add ValidatedPasswordCollector support#116

Merged
ancheetah merged 7 commits into
mainfrom
feat/validated-password-collector
Jul 17, 2026
Merged

feat(reactjs-todo-davinci): add ValidatedPasswordCollector support#116
ancheetah merged 7 commits into
mainfrom
feat/validated-password-collector

Conversation

@ryanbas21

@ryanbas21 ryanbas21 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Upgrades @forgerock/davinci-client to PR#638 preview build (adds ValidatedPasswordCollector support)
  • Extends the Password component to render a static requirements list, inline validation errors on keystroke, and an optional confirm field (when verify: true) with real-time mismatch feedback
  • Wires ValidatedPasswordCollector into form.js via a new validator function exposed from useDavinci
  • Adds 2 Playwright e2e tests against the 356a254c PingOne tenant (which returns a passwordPolicy on the registration password field)

Changes

File Change
package.json @forgerock/davinci-clientpkg.pr.new PR#638 build
hooks/davinci.hook.js Expose validator(collector) with try/catch safety fallback
password.js Requirements list, inline errors, split visibility state, real-time confirm mismatch
form.js ValidatedPasswordCollector case in mapCollectorsToComponents
e2e/davinci-validated-password.spec.js 2 e2e tests: requirements list visible, inline errors appear/clear
playwright.config.ts 8443 webServer points to 356a254c tenant for ValidatedPassword tests

Notes

  • The pkg.pr.new URL should be replaced with the published npm tag once PR#638 is merged to the SDK
  • The verify: true confirm field is implemented but not reachable in the current PingOne environment (collector.output.verify is false) — the code is correct and will activate automatically when the environment is configured
  • The 356a254c tenant's pingOneSSOConnector/createUser step is returning "requestTimedOut" so a happy-path registration e2e test is not included — covered by the existing davinci-register-user.spec.js against 02fb4743

Test plan

  • npm run e2e -- --grep "ValidatedPasswordCollector" — 4 passing (Chromium + Firefox)
  • npm run e2e -- --grep "Login" — existing login tests still pass
  • Navigate to registration form manually and confirm requirements list and inline errors render

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for validated password fields.
    • Password requirements and inline validation errors are now displayed.
    • Added optional password confirmation with mismatch feedback.
  • Documentation

    • Documented ValidatedPasswordCollector as a supported collector.
  • Bug Fixes

    • Improved request validation handling in end-to-end tests.
  • Tests

    • Added coverage for password requirements and validation behavior.

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

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

Walkthrough

Adds ValidatedPasswordCollector support to DaVinci forms with password requirements, validation errors, confirmation matching, Playwright coverage, safer request inspection, and Playwright configuration and dependency updates.

Changes

DaVinci validated password support

Layer / File(s) Summary
Validation hook API
javascript/reactjs-todo-davinci/client/components/davinci-client/hooks/davinci.hook.js
Exposes a validator helper that delegates collector validation to the DaVinci client.
ValidatedPasswordCollector form integration
javascript/reactjs-todo-davinci/client/components/davinci-client/form.js, javascript/reactjs-todo-davinci/README.md
Maps validated password collectors to the enhanced Password component and lists the collector as supported.
Password validation and confirmation UI
javascript/reactjs-todo-davinci/client/components/davinci-client/password.js
Displays password requirements and validation errors, supports independent visibility toggles, and optionally validates confirmation-password matches.
E2E coverage and request validation hardening
javascript/reactjs-todo-davinci/e2e/davinci-validated-password.spec.js, javascript/reactjs-todo-davinci/e2e/davinci-protect.spec.js
Tests requirements and validation behavior, while restricting Protect payload inspection to eligible JSON POST requests.
Playwright module and dependency updates
javascript/reactjs-todo-journey/package.json, javascript/reactjs-todo-journey/playwright.config.js, package.json
Converts the journey Playwright configuration to CommonJS and upgrades Playwright Test.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Form
  participant Password
  participant DaVinciClient
  User->>Form: Open validated password form
  Form->>Password: Pass validator and verify
  User->>Password: Enter password
  Password->>DaVinciClient: Validate collector
  DaVinciClient-->>Password: Return validation errors
  Password-->>User: Render requirements or errors
  User->>Password: Enter confirmation
  Password-->>User: Render mismatch state
Loading

Suggested reviewers: ancheetah, steingabriel

Poem

A bunny checks each password bright,
With carrots for wrong and right.
Two fields compare, errors hop away,
Requirements guide the form today.
Tests leap through the login door—
Validation blooms once more!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding ValidatedPasswordCollector support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/validated-password-collector

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.

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

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 `@javascript/reactjs-todo-davinci/package.json`:
- Line 42: The package.json currently pins `@forgerock/davinci-client` to a
preview pkg.pr.new URL; replace that entry in
javascript/reactjs-todo-davinci/package.json so the dependency references the
published npm version string (e.g. "`@forgerock/davinci-client`":
">=<stable-version>" or a specific semver) instead of the pkg.pr.new URL, then
regenerate the lockfile (run npm install/npm ci locally) so package-lock.json no
longer contains a resolved pkg.pr.new URL; ensure the final package-lock.json
committed to the repo points to the stable registry artifact so CI installs
reliably.
🪄 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: 518e875a-ed2f-4793-b3ca-eb263fe249c5

📥 Commits

Reviewing files that changed from the base of the PR and between bc9ebef and 2745e9a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • javascript/reactjs-todo-davinci/client/components/davinci-client/form.js
  • javascript/reactjs-todo-davinci/client/components/davinci-client/hooks/davinci.hook.js
  • javascript/reactjs-todo-davinci/client/components/davinci-client/password.js
  • javascript/reactjs-todo-davinci/e2e/davinci-validated-password.spec.js
  • javascript/reactjs-todo-davinci/package.json
  • javascript/reactjs-todo-davinci/playwright.config.ts

Comment thread javascript/reactjs-todo-davinci/package.json Outdated

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

Left some comments about error handling.

Comment on lines +14 to +29
/**
* Override configs keyed by clientId URL param — allows tests to target a
* different PingOne tenant without recompiling the app.
*/
const CLIENT_CONFIGS = {
'fb456db5-2e08-46d3-adf0-05bf8d26ad60': {
clientId: 'fb456db5-2e08-46d3-adf0-05bf8d26ad60',
redirectUri: `${window.location.origin}/callback.html`,
scope: 'openid profile email phone name revoke',
serverConfig: {
wellknown:
'https://auth.pingone.ca/356a254c-cba3-4ade-be1a-860136e8df01/as/.well-known/openid-configuration',
},
},
};

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.

Why are we hardcoding a tenant here? I feel like this should be moved into a test and not something exposed to the customer.

Comment on lines +104 to +107
} catch (error) {
console.error('Error creating validator for collector:', error);
return () => [];
}

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.

I don't believe validate can throw. Can we remove this? If we want to handle errors then we should look for them like if (error) in validateResult {}.


if (validator) {
const errors = validator(value);
setValidationErrors(Array.isArray(errors) ? errors : []);

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.

Do we need to do the Array.isArray check? Validators should always return an array even if it's empty.

Comment on lines +72 to +82
const result = updater(value);
if (result && result.error) {
console.error('Error updating password collector:', result.error.message);
}

// Keep confirm error in sync as the primary value changes
if (confirmValue && value !== confirmValue) {
setConfirmError('Passwords do not match');
} else if (confirmValue) {
setConfirmError('');
}

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.

Is there anything blocking the user from submitting the form if there is an error? Or are these just UI hints?

@ancheetah ancheetah added the do not merge Do not merge label Jun 11, 2026
cerebrl
cerebrl previously approved these changes Jun 11, 2026
ancheetah
ancheetah previously approved these changes Jun 16, 2026

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

Approved. I added a do not merge label. Let's remember to update the deps to latest once we release and this is ready.

- Upgrades @forgerock/davinci-client to latest (2.0.0) which ships
  ValidatedPasswordCollector with password policy validation support
- Extends the Password component to render a static requirements list
  from the password policy, inline validation errors on keystroke,
  and an optional confirm field with real-time mismatch feedback
- Wires ValidatedPasswordCollector into form.js via a new validator
  function exposed from useDavinci with proper error handling
- Adds a second webServer (port 8444, 356a254c tenant) in playwright
  config for ValidatedPasswordCollector e2e tests; skipped in CI
  where only the 02fb4743 tenant is available
- Add defensive null check in request listener to handle non-JSON requests
- Use optional chaining for safe property access
- Fix swapped assertions in collector test (was checking bootstrap log instead of collector log)
- Tests now pass with beta packages which have different request patterns

These bugs were pre-existing but masked by original package's request order.
Beta package's different request pattern exposed them.
- Upgrade @playwright/test from 1.41.2 to 1.60.0 for better ESM support
- Remove 'type: module' from reactjs-todo-journey/package.json
- Convert playwright.config.js to CommonJS (require/module.exports)
- Journey e2e tests now run (5 passed, 7 failed due to pre-existing backend issues)

The ESM config issue was caused by Playwright 1.41.2 not properly handling
ESM configs when package.json has 'type: module'. Upgrading Playwright and
using CommonJS config resolves the issue.
- Remove hardcoded CLIENT_CONFIGS from create-client.utils.js (production code should not contain test-specific config)
- Remove unnecessary try/catch from validator function (davinciClient.validate doesn't throw)
- Remove redundant Array.isArray check in password.js (validators always return arrays)
- Update e2e test to use standard CONFIG instead of clientId URL param override
@ancheetah
ancheetah dismissed stale reviews from cerebrl and themself via 6300736 July 15, 2026 18:50
@ancheetah
ancheetah force-pushed the feat/validated-password-collector branch from 17d4a80 to 6300736 Compare July 15, 2026 18:50
@ancheetah ancheetah removed the do not merge Do not merge label Jul 15, 2026

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
javascript/reactjs-todo-journey/package.json (1)

25-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

javascript/reactjs-todo-journey/package.json:25 — Pin @forgerock/sdk-utilities to an explicit version. latest makes installs non-reproducible; use 2.1.0 or another fixed semver range instead.

🤖 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 `@javascript/reactjs-todo-journey/package.json` at line 25, Replace the
floating "latest" version for `@forgerock/sdk-utilities` in package.json with an
explicit pinned semver version, preferably 2.1.0, to ensure reproducible
installs.
javascript/reactjs-todo-davinci/client/components/davinci-client/password.js (1)

114-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add accessible names to the visibility toggle buttons.

The password visibility toggle buttons are icon-only. Without an aria-label or equivalent accessible text, screen readers will only announce them amorphously as "button", leaving visually impaired users without context.

  • javascript/reactjs-todo-davinci/client/components/davinci-client/password.js#L114-L120: Add an aria-label (e.g., aria-label={isPrimaryVisible ? "Hide password" : "Show password"}) to the primary password toggle button.
  • javascript/reactjs-todo-davinci/client/components/davinci-client/password.js#L142-L148: Add an aria-label (e.g., aria-label={isConfirmVisible ? "Hide password" : "Show password"}) to the confirm password toggle button.
🤖 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 `@javascript/reactjs-todo-davinci/client/components/davinci-client/password.js`
around lines 114 - 120, Add accessible labels to both icon-only visibility
toggle buttons in the password component: update the primary toggle near lines
114-120 and the confirm toggle near lines 142-148 with labels that indicate
“Show password” when hidden and “Hide password” when visible, using
isPrimaryVisible and isConfirmVisible respectively.
🤖 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
`@javascript/reactjs-todo-davinci/client/components/davinci-client/password.js`:
- Around line 77-83: Update the primary password change handler’s confirm-error
synchronization logic by changing the `else if (confirmValue)` branch to an
unconditional `else`, so `setConfirmError('')` runs when the confirm field is
empty as well as when the values match. Keep the existing mismatch condition
unchanged and mirror `handleConfirmChange` behavior.

In `@javascript/reactjs-todo-davinci/e2e/davinci-protect.spec.js`:
- Around line 31-37: Move each postDataJSON() call in davinci-protect.spec.js
inside its corresponding POST/customHTMLTemplate condition at lines 31-37 and
76-82, so non-JSON requests are never parsed; preserve the existing request
tracking and payload processing behavior.

---

Nitpick comments:
In
`@javascript/reactjs-todo-davinci/client/components/davinci-client/password.js`:
- Around line 114-120: Add accessible labels to both icon-only visibility toggle
buttons in the password component: update the primary toggle near lines 114-120
and the confirm toggle near lines 142-148 with labels that indicate “Show
password” when hidden and “Hide password” when visible, using isPrimaryVisible
and isConfirmVisible respectively.

In `@javascript/reactjs-todo-journey/package.json`:
- Line 25: Replace the floating "latest" version for `@forgerock/sdk-utilities` in
package.json with an explicit pinned semver version, preferably 2.1.0, to ensure
reproducible installs.
🪄 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: 803e364a-3df1-429b-82a9-ec211e1a9bfb

📥 Commits

Reviewing files that changed from the base of the PR and between 17d4a80 and 6300736.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • javascript/reactjs-todo-davinci/README.md
  • javascript/reactjs-todo-davinci/client/components/davinci-client/form.js
  • javascript/reactjs-todo-davinci/client/components/davinci-client/hooks/davinci.hook.js
  • javascript/reactjs-todo-davinci/client/components/davinci-client/password.js
  • javascript/reactjs-todo-davinci/e2e/davinci-protect.spec.js
  • javascript/reactjs-todo-davinci/e2e/davinci-validated-password.spec.js
  • javascript/reactjs-todo-journey/package.json
  • javascript/reactjs-todo-journey/playwright.config.js
  • package.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • javascript/reactjs-todo-davinci/README.md
  • javascript/reactjs-todo-davinci/client/components/davinci-client/form.js
  • javascript/reactjs-todo-davinci/client/components/davinci-client/hooks/davinci.hook.js
  • javascript/reactjs-todo-journey/playwright.config.js
  • javascript/reactjs-todo-davinci/e2e/davinci-validated-password.spec.js

Comment on lines +77 to +83
// Keep confirm error in sync as the primary value changes
if (confirmValue && value !== confirmValue) {
setConfirmError('Passwords do not match');
} else if (confirmValue) {
setConfirmError('');
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clear the confirm error when both fields are emptied.

If a user types in both fields (triggering a mismatch error), clears the Confirm field, and then clears the Primary field, the "Passwords do not match" error remains visible even when both fields are empty. This happens because when confirmValue is empty, both conditions in the if/else if block evaluate to false, leaving the confirmError state unchanged.

Change else if (confirmValue) to else to ensure the error clears when both fields become empty, mirroring the logic in handleConfirmChange.

🐛 Proposed fix
     // Keep confirm error in sync as the primary value changes
     if (confirmValue && value !== confirmValue) {
       setConfirmError('Passwords do not match');
-    } else if (confirmValue) {
+    } else {
       setConfirmError('');
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Keep confirm error in sync as the primary value changes
if (confirmValue && value !== confirmValue) {
setConfirmError('Passwords do not match');
} else if (confirmValue) {
setConfirmError('');
}
}
// Keep confirm error in sync as the primary value changes
if (confirmValue && value !== confirmValue) {
setConfirmError('Passwords do not match');
} else {
setConfirmError('');
}
}
🤖 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 `@javascript/reactjs-todo-davinci/client/components/davinci-client/password.js`
around lines 77 - 83, Update the primary password change handler’s confirm-error
synchronization logic by changing the `else if (confirmValue)` branch to an
unconditional `else`, so `setConfirmError('')` runs when the confirm field is
empty as well as when the values match. Keep the existing mismatch condition
unchanged and mirror `handleConfirmChange` behavior.

Comment thread javascript/reactjs-todo-davinci/e2e/davinci-protect.spec.js
@ancheetah
ancheetah force-pushed the feat/validated-password-collector branch from 6300736 to 3c94b3f Compare July 15, 2026 19:30
@ancheetah
ancheetah force-pushed the feat/validated-password-collector branch from 3c94b3f to 70eaca6 Compare July 15, 2026 19:49

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

Discussed with Ryan about the fact that we're submitting even with invalid password, but it's just a sample app, so I think it's nbd, so approving. Everything else seems to be working as expected.

@ancheetah
ancheetah merged commit f46e25f into main Jul 17, 2026
17 checks passed
@ancheetah
ancheetah deleted the feat/validated-password-collector branch July 17, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants