jquense / yup

Dead simple Object schema validation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`when` and `test` stopped working together

Sinled opened this issue · comments

Describe the bug
After migrating to yup v1.4 when and test stopped working together, worked fine in 0.32.11.

To Reproduce

Codesanbox removed ability to run tests, https://codesandbox.io/docs/learn/sandboxes/faq#where-can-i-find-the-tests-tab, so I am not sure where to add runnable test

But here simplified code and test example that worked in previous versions of yup:

Code here
import { object, mixed, string } from 'yup';
import { it, expect } from 'vitest';

const schema = object().shape({
    value: mixed<string | number>()
        .label('Value')
        .required()
        .when('$model.isStringValueType', {
            is: true,
            then: () => string().required(),
        })
        .test('is-unique-value', 'Value should be unique', function (newValue) {
            if (!newValue) {
                return true;
            }

            const values = this.parent.siblingValues.filter(({ otherValue }: { otherValue: string | number }) => {
                return otherValue === newValue;
            });

            return values.length === 1;
        }),
});

it('should be invalid if "when" is not entered', async () => {
    await expect(
        schema.isValid(
            {
                siblingValues: [{ otherValue: 'foo' }, { otherValue: 'foo' }],
                value: 'foo',
            },
            { context: { model: { isStringValueType: false } } },
        ),
    ).resolves.toBe(false);
});

it('should be invalid if not a string', async () => {
    await expect(
        schema.isValid(
            {
                siblingValues: [{ otherValue: 'foo' }],
                value: 1,
            },
            { context: { model: { isStringValueType: true } } },
        ),
    ).resolves.toBe(false);
});

it('should be invalid if "when" is entered and has similar siblings', async () => {
    await expect(
        schema.isValid(
            {
                siblingValues: [{ otherValue: 'foo' }, { otherValue: 'foo' }],
                value: 'foo',
            },
            { context: { model: { isStringValueType: true } } },
        ),
    ).resolves.toBe(false);
});

At the moment, 2nd and 3rd test fails.

Expected behavior
tests should pass, both .when and .test branches should be checked

Platform (please complete the following information):

  • Browser agnostic

Additional context
This is recreation of #2179

This is happening because your when is discarding the current schema and returning a fresh one without your custom test:

.when('$model.isStringValueType', {
    is: true,
-    then: () => string().required(),
+    then: schema => schema.required(),
})

@jquense thanks for reply, but what should I do if I need to return different schemas? e.g. string or number depending on condition?

It worked fine before, it is not very clear what to do now.

Switching types isn't really supported, it didn't work fine before, it was very inconsistent and often produced broken schema which is why it was removed. You are welcome to return a brand new schema still, but it won't be automatically concated with the old one. You can approximate the old behavior by doing the concat yourself, schema=> schema.concat(string().whatever())