feat(surveys): add validation types and utilities#2820
Conversation
- Add SurveyValidationType enum (MinLength, MaxLength, Email) - Add SurveyValidationRule interface - Add validation field to SurveyQuestionBase type - Create validation utility functions: - getValidationError() - validates survey responses with trim fix - getMinLengthFromRules() - extract minLength from rules - getMaxLengthFromRules() - extract maxLength from rules - Add comprehensive unit tests with 100% coverage - Backwards compatible with existing surveys
- Import validation utilities from @posthog/core - Update OpenTextQuestion with validation-aware implementation: - Use useMemo for validation error calculation - Native HTML5 setCustomValidity for error display - Add minLength/maxLength textarea attributes - Trim response on submit - Add validation field to browser SurveyQuestionBase type - Add Playwright E2E tests for validation scenarios
…stion - Import getValidationError from @posthog/core - Update OpenTextQuestion with validation-aware implementation: - Add validationError state - Show error text below input when validation fails - Red border on input when error present - Disable submit when validation fails - Trim response on submit - Add validationError style to StyleSheet - Add unit tests for validation in React Native
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Size Change: +15.7 kB (+0.27%) Total Size: 5.92 MB
ℹ️ View Unchanged
|
Fixes CodeQL security alert about polynomial regex vulnerability. The previous email regex pattern could cause exponential backtracking on malicious inputs like '!@!.!.!.!.!.'. Changes: - Replace regex with simple string-based isValidEmail() function - Add tests for edge cases (multiple @, dots at boundaries, ReDoS) - Fix survey preview test to use fireEvent.input instead of change
Follow established pattern in other Playwright tests where route promise is stored and awaited after start() to ensure proper test setup.
- Await route setup promise after start() per established pattern - Wait for .survey-form inside container, not just container div - Check button is disabled for validation failures instead of clicking
Use useMemo to calculate validation error once per render instead of calling getValidationError twice (in submitDisabled and handleSubmit).
…type Remove email validation from the validation system - email collection will be implemented as a dedicated question type with: - Privacy-first masked input - Proper email input type with native validation - Option for multiple email collection Kept minLength and maxLength validators.
|
Been thinking about this, this PR was conflating too many concerns. The user's original issue was that users can bypass required questions by entering empty spaces, I've kept that fix and the length utilities. However, for emails we should consider adding a specific "Email" question type that uses a proper email field for privacy and full email validation. Now, users will be able to enforce a minimum and maximum length in text type questions, which is helpful if their getting many useless answers, but if they don't set a length constraint, they'll still get the benefit of not getting empty spaces that by pass required responses. |
…logic - Extract duplicated hint string building to shared util in core - Skip showing hint for min=1 (redundant for required, useless for optional) - Add pluralization for edge cases (e.g., "Maximum 1 character") - Add comprehensive tests for the new util
lucasheriques
left a comment
There was a problem hiding this comment.
minor comment. PR looks great overall
| value: string, | ||
| rules: SurveyValidationRule[] | undefined, | ||
| optional: boolean | undefined | ||
| ): string | false { |
There was a problem hiding this comment.
nit: i'd remove this return types and use typescript infer instead
|
This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, post a comment or remove the |
|
@ordehi is this good to merge? just checking in! |
| minLength={minLength} | ||
| maxLength={maxLength} |
There was a problem hiding this comment.
Critical bug: HTML5 minLength and maxLength attributes validate the raw untrimmed value, but the custom validation logic validates the trimmed value (line 113 calls getValidationError which trims on line 12 of validation.ts). This creates inconsistent behavior:
Example scenario with maxLength=10:
- User types
" hello world "(15 chars raw, 11 chars trimmed) - HTML5 maxLength prevents typing beyond 10 characters, blocking at
" hello wo" - User can't type more, but trimmed value is only 8 chars
- Custom validation may expect more characters if minLength > 8
Fix: Remove these HTML5 attributes since validation is handled by custom logic:
<textarea
id={htmlFor}
rows={4}
placeholder={appearance?.placeholder}
// Remove minLength and maxLength attributes
onInput={(e) => {| minLength={minLength} | |
| maxLength={maxLength} | |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
|
This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, post a comment or remove the |
Resolve conflicts: - QuestionTypes.tsx: Keep validation utilities and add thumbs emoji imports - posthog-surveys-types.ts: Keep Properties and SurveyValidationRule imports
Problem
Relies on PostHog/posthog#44076 for setting lengths in surveys, but works without it as it's back compat.
Survey open text questions with
optional: false(required) currently accept whitespace-only responses like" "as valid input. Users can bypass required field validation by entering just spaces. Additionally, there's no way to configure validation rules (like minimum length) for survey responses.Changes
React Native:
@posthog/core): AddedSurveyValidationTypeenum andSurveyValidationRuleinterface. CreatedgetValidationError(),getMinLengthFromRules(), andgetMaxLengthFromRules()utilities in newsurveys/validation.tsmodule. ExtendedSurveyQuestionBasetype with optionalvalidationfield.posthog-js): UpdatedOpenTextQuestioncomponent to use validation utilities. Now trims responses before submission, uses HTML5setCustomValidity()for native validation UI, and supportsminLength/maxLengthtextarea attributes. Added Playwright E2E tests.posthog-react-native): UpdatedOpenTextQuestioncomponent with validation error state, red border on error, error text display below input, and trim on submit. Added unit tests.Backwards compatible: Existing surveys without
validationrules work unchanged but now properly reject blank responses. API surveys receive validation rules in data but enforcement is left to the user (they can importgetValidationErrorfrom@posthog/core).Libraries affected
Checklist
If releasing new changes
pnpm changesetto generate a changeset file