`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 concat
ed with the old one. You can approximate the old behavior by doing the concat
yourself, schema=> schema.concat(string().whatever())