remix-validated-form icon indicating copy to clipboard operation
remix-validated-form copied to clipboard

[Bug]: zod-form-data won't validate all fields at once when using safeParse

Open thdk opened this issue 10 months ago • 2 comments

Which packages are impacted?

  • [ ] remix-validated-form
  • [ ] @remix-validated-form/with-zod
  • [ ] @remix-validated-form/with-yup
  • [X] zod-form-data

What version of these packages are you using?

"zod": "^3.22.4",
"zod-form-data": "^2.0.2"

Please provide a link to a minimal reproduction of the issue.

https://stackblitz.com/edit/vitest-dev-vitest-jswqx2?file=test%2Fbasic.test.ts

Steps to Reproduce the Bug or Issue

  import { describe, expect, test } from 'vitest';
  import { z } from 'zod';
  import { zfd } from 'zod-form-data';

  test('multiple fields should get validated at once', (v) => {
    const Schema = zfd.formData(
      z.object({
        field1: zfd.text(),
        field2: zfd.text(),
      })
    );

    const data = new FormData();
    data.append('field1', '');
    data.append('field2', '');

    const result = Schema.safeParse(data);

    expect(result.success).toBe(false);

    if (result.success) {
      throw new Error('Expected failure but got success');
    } else {
      const errors = result.error.flatten() as z.inferFlattenedErrors<
        typeof Schema
      >;

      // Both fields should have been validated but aren't
      expect.soft(errors.fieldErrors.field1).toEqual(['Required']);
      expect.soft(errors.fieldErrors.field2).toEqual(['Required']);
    }
  });

Expected behavior

When multiple fields are invalid, and the form data is parsed using z.safeParse then the result object should have an error property that contains the error information for both fields.

The actual result is that only the first field is validated. Next, when the first issue is solved by the user and resubmits the form, the error for the next field is shown.

Screenshots or Videos

No response

Platform

  • OS: macOS
  • Browser: arc

Additional context

No response

thdk avatar Apr 02 '24 20:04 thdk

Thank you for the thorough reproduction! Definitely a weird bug. Interestingly, if you use safeParseAsync instead, that fixes it (code)? Hopefully that's a reasonable workaround for now as I'm not sure when I'll have time to investigate.

airjp73 avatar Apr 02 '24 22:04 airjp73

I was already using the validator from withZod as workaround which also worked.

const validator = withZod(schema);
const result = await validator.validate(data);

After your message I had a look into the source code of withZod which seems very similar to how I was using it myself except for the use of safeParseAsync instead of safeParse indeed. I'll revert my code and use safeParseAsync instead of my withZod workaround.

I have one issue left for which I will create a separate issue.

thdk avatar Apr 03 '24 19:04 thdk