jquense / yup

Dead simple Object schema validation
MIT License
22.72k stars 925 forks source link

[v1] Required fields in an optional object are required even if the optional object isn't defined #2215

Closed mikeseese closed 4 months ago

mikeseese commented 4 months ago

Describe the bug This bug is similar to #1890 where optional objects with required fields are causing unexpected behavior when the optional object isn't provided. However, this issue documents a problem with the latest version of yup and a different error.

To Reproduce

It seems the CodeSandbox tests panel was removed, but here is a test that should pass, but the objWithoutFoo will fail.

const yup = require("yup");

it("should pass", async () => {
  const schema = yup.object({
    fooValid: yup.boolean().required(),
    foo: object({
      str: yup.string().required(),
      num: yup.number().required(),
      bool: yup.boolean().required(),
    }).optional(),
  });

  const objWithFoo = {
    fooValid: true,
    foo: {
      str: "hello world",
      num: 42,
      bool: true,
    },
  };

  await expect(schema.isValid(objWithFoo)).resolves.toBe(true);

  const objWithoutFoo = {
    fooValid: false,
  };

  await expect(schema.isValid(objWithoutFoo)).resolves.toBe(true);
});

Expected behavior I expect all of the provided tests to pass. Required fields in an optional object should only be required if the optional object is defined.

Platform (please complete the following information):

Additional context N/A

mikeseese commented 4 months ago

Apparently this is desired behavior. I find it confusing the ObjectSchema.optional() is not intended to allow the object to be undefined but rather for it to be at least {}. It seems like the design wants you to use object().default(undefined) for this desired behavior. It's very counterintuitive, but it seems like that's the opinion the author wants, so I'll close this issue.