Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(next): string validation #118

Merged
merged 15 commits into from
Feb 4, 2025
Merged

feat(next): string validation #118

merged 15 commits into from
Feb 4, 2025

Conversation

lukad
Copy link
Collaborator

@lukad lukad commented Feb 3, 2025

This implements string validation (minLength, maxLength, pattern) as well as the groundwork for validating objects.
I will address building fields, as well as formErrors compatibility with v0 in a follow up PR.

@lukad lukad changed the title WIP feat(next): string validation Feb 3, 2025
@lukad lukad force-pushed the devxp-2538-validate-strings branch from fa53f81 to f473cbf Compare February 3, 2025 12:33
@lukad lukad force-pushed the devxp-2538-validate-strings branch from 768dbab to 37385ec Compare February 3, 2025 12:53
@lukad lukad marked this pull request as ready for review February 3, 2025 13:05
@thien-remote thien-remote requested review from dragidavid and thien-remote and removed request for dragidavid February 3, 2025 13:09
Copy link
Collaborator

@dragidavid dragidavid left a comment

Choose a reason for hiding this comment

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

Left a few comments but largely I think this is a good approach. I guess we'll see how everything falls into place as we work on the upcoming parts.

Last question about testing:
I assume when it comes to testing, we should run the tests from v0 against the new code + run the new ones we write, right?

next/src/validation/schema.ts Show resolved Hide resolved
next/src/validation/string.ts Show resolved Hide resolved
next/test/validation/string.test.ts Show resolved Hide resolved
next/src/types.ts Show resolved Hide resolved
thien-remote
thien-remote previously approved these changes Feb 3, 2025
Copy link
Collaborator

@thien-remote thien-remote left a comment

Choose a reason for hiding this comment

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

✅ Since we're in a WIP state, but would love if you can address some questions

next/src/types.ts Show resolved Hide resolved
next/src/types.ts Show resolved Hide resolved
next/src/types.ts Show resolved Hide resolved
next/src/types.ts Show resolved Hide resolved
next/src/types.ts Outdated Show resolved Hide resolved
next/src/validation/schema.ts Show resolved Hide resolved
next/src/validation/schema.ts Outdated Show resolved Hide resolved
next/src/validation/schema.ts Show resolved Hide resolved
next/src/validation/object.ts Show resolved Hide resolved
next/src/validation/object.ts Show resolved Hide resolved
@dragidavid
Copy link
Collaborator

Approving this as it seems we all agree that this is a good starting point! Thanks for adding it Luka 🙌

dragidavid
dragidavid previously approved these changes Feb 3, 2025
next/src/form.ts Show resolved Hide resolved
@lukad
Copy link
Collaborator Author

lukad commented Feb 4, 2025

@dragidavid I just noticed I missed your question regarding tests.

Last question about testing:
I assume when it comes to testing, we should run the tests from v0 against the new code + run the new ones we write, right?

The new tests should all pass. While we continue building next more and more v0 tests should pass as well.

@lukad lukad merged commit f19f2d4 into main Feb 4, 2025
3 checks passed
@lukad lukad deleted the devxp-2538-validate-strings branch February 4, 2025 11:21
* Each property is validated with `validateSchema`.
*/
export function validateObject(value: SchemaValue, schema: NonBooleanJsfSchema): ValidationError[] {
if (typeof schema === 'object' && schema.properties && typeof value === 'object') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

@lukad / @dragidavid can we adopt the "early return" pattern anywhere we can? In this case it would be:

if (typeof schema !== 'object' || !schema.properties || typeof value !== 'object') {
  return []
}

// the actual code...

Copy link
Collaborator

Choose a reason for hiding this comment

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

I love early return! It makes the code much easier to read.

Also we have concluded in internal discussion that early return would use a safe fallback (e.g., empty array for errors) instead of fail-fast errors (e.g., throw) (Slack).


export function createHeadlessForm(schema: JsfSchema, options: CreateHeadlessFormOptions = {}): FormResult {
const errors = validateSchema(options.initialValues, schema)
const validationResult = validationErrorsToFormErrors(errors)
Copy link
Collaborator

Choose a reason for hiding this comment

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

praise: Thanks for doing this, following the official spec of json schema errors, and turn them into "formErrors" ✨

next/src/form.ts Show resolved Hide resolved

if (getSchemaType(schema) === 'string' && typeof value === 'string') {
if (schema.minLength !== undefined && value.length < schema.minLength) {
errors.push({ path: [], validation: 'minLength', message: 'must be at least 3 characters' })
Copy link
Collaborator

Choose a reason for hiding this comment

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

🐛 Question: Why is "3 characters hardcoded"? 🤔

errors.push({
path: [],
validation: 'pattern',
message: `must match the pattern '${schema.pattern}'`,
Copy link
Collaborator

Choose a reason for hiding this comment

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

For UX reasons, we improve this message even more v0 source. Must have a valid format. E.g. ${randomPlaceholder}

import { createHeadlessForm } from '../../src'

describe('object schema validation', () => {
it('returns an error if the value is not an object', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Could we keep the same naming convention as v0 tests. Instead of saying if, saying when or given

expect(form.handleValidation({})).not.toHaveProperty('formErrors')
expect(form.handleValidation({ address: {} })).not.toHaveProperty('formErrors')
expect(form.handleValidation({ address: 'not an object' })).toMatchObject({
formErrors: { '.address': 'should be object' },
Copy link
Collaborator

Choose a reason for hiding this comment

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

bug/question: Why does the path has a . prefix. This is different from v0 and would break the internal code.


expect(form.handleValidation({ address: { street: 'some street' } })).not.toHaveProperty('formErrors')
expect(form.handleValidation({ address: { street: 10 } })).toMatchObject({
formErrors: { '.address.street': 'should be string' },
Copy link
Collaborator

Choose a reason for hiding this comment

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

bug/question: @lukad / @dragidavid do you realize that these error messages are different from v0? This will fail all tests. The error messages MUST be the same, otherwise a lot of tests (here and in internal codebases) will fail.

If we want to change the errors message, let that for later as an opt-in config or something.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, I mentioned this in another thread which I can't find now but after all we want all the error messages to be the same as before, definitely!

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.

4 participants