Skip to content

Commit 45bdfff

Browse files
committed
fix: support for YUP .ref() and .when() methods
fix: #626
1 parent 24f649d commit 45bdfff

File tree

6 files changed

+163
-18
lines changed

6 files changed

+163
-18
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 6.12.1 (master)
2+
3+
- Feat: Support for YUP .ref() and .when() methods
4+
- Fix: #626
5+
16
# 6.12.0 (master)
27

38
- Feat: validation package type inference when extending validation plugins

src/utils.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,11 @@ const hasFiles = ($: any): boolean =>
164164
const isBool = ($: any, val: any): boolean =>
165165
_.isBoolean(val) && _.isBoolean($.target.checked);
166166

167-
const $try = (...args: any) => {
168-
let found: any | null | undefined = undefined;
169-
170-
args.map(( val: any ) =>
171-
found === undefined && !_.isUndefined(val) && (found = val));
172-
173-
return found;
167+
const $try = (...args: any[]) => {
168+
for (const val of args) {
169+
if (val !== undefined) return val;
170+
}
171+
return undefined;
174172
};
175173

176174
export {

src/validators/YUP.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,13 @@ class YUP<TValidator = any> implements ValidationPluginInterface {
4646

4747
// Creazione della promise per la validazione
4848
private createValidationPromise(field: any): Promise<any> {
49-
return new Promise((resolve) =>
50-
(this.validator as any)
51-
.reach(this.schema, field.path)
52-
.label(field.label)
53-
.validate(field.validatedValue, { strict: true })
49+
return new Promise((resolve) => {
50+
this.schema
51+
.validateAt(field.path, this.state.form.values(), { strict: true })
5452
.then(() => this.handleAsyncPasses(field, resolve))
55-
.catch((error) => this.handleAsyncFails(field, resolve, error))
56-
);
53+
.catch((error) => this.handleAsyncFails(field, resolve, error));
54+
});
5755
}
58-
5956
// Gestione dei successi della validazione asincrona
6057
private handleAsyncPasses(field: any, resolve: Function): void {
6158
field.setValidationAsyncData(true);
@@ -64,9 +61,16 @@ class YUP<TValidator = any> implements ValidationPluginInterface {
6461

6562
// Gestione dei fallimenti della validazione asincrona
6663
private handleAsyncFails(field: any, resolve: Function, error: any): void {
67-
field.setValidationAsyncData(false, error.errors[0]);
68-
this.executeAsyncValidation(field);
69-
resolve();
64+
// Yup a volte restituisce errori senza path (es. array vuoti)
65+
const isSameField = error.path === field.path || error.path === undefined;
66+
67+
if (isSameField) {
68+
const message = error.message?.replace(error.path ?? field.path, field.label);
69+
field.setValidationAsyncData(false, message);
70+
this.executeAsyncValidation(field);
71+
}
72+
73+
resolve(undefined);
7074
}
7175

7276
// Esecuzione della validazione asincrona

tests/data/_.fixes.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ import $519 from "./forms/fixes/form.519";
4747
import $585 from "./forms/fixes/form.585";
4848
import $531 from "./forms/fixes/form.531";
4949

50+
import { form626a as $626a } from "./forms/fixes/form.626a";
51+
import { form626b as $626b } from "./forms/fixes/form.626b";
52+
5053
export default {
5154
$formEmptyConstructor,
5255
$A,
@@ -92,4 +95,7 @@ export default {
9295

9396
$585,
9497
$531,
98+
99+
$626a,
100+
$626b,
95101
};

tests/data/forms/fixes/form.626a.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { expect } from 'chai';
2+
import { describe, it } from 'mocha';
3+
import * as yup from 'yup';
4+
import Form from '../../../../src';
5+
import $yup from "../../../../src/validators/YUP";
6+
7+
const plugins = {
8+
dvr: $yup({
9+
package: yup,
10+
schema: (y: any) =>
11+
y.object().shape({
12+
password: y.string().required('Password is required'),
13+
passwordConfirm: y
14+
.string()
15+
.required('Confirm password is required')
16+
.oneOf([y.ref('password')], 'Passwords must match'),
17+
}),
18+
}),
19+
};
20+
21+
const fields = [
22+
{
23+
name: 'password',
24+
label: 'Password',
25+
placeholder: 'Enter password',
26+
},
27+
{
28+
name: 'passwordConfirm',
29+
label: 'Confirm Password',
30+
placeholder: 'Confirm password',
31+
},
32+
];
33+
34+
export const form626a = new Form({ fields }, { plugins });
35+
36+
37+
describe('Yup plugin with yup.ref()', () => {
38+
it('should invalidate passwordConfirm when different from password', async () => {
39+
form626a.reset()
40+
form626a.$('password').set('123456');
41+
form626a.$('passwordConfirm').set('654321');
42+
43+
await form626a.validate();
44+
45+
expect(form626a.isValid).to.be.false;
46+
expect(form626a.$('passwordConfirm').hasError).to.be.true;
47+
expect(form626a.$('passwordConfirm').error).to.equal('Passwords must match');
48+
});
49+
50+
it('should validate when password and passwordConfirm match', async () => {
51+
form626a.reset()
52+
form626a.$('password').set('123456');
53+
form626a.$('passwordConfirm').set('123456');
54+
55+
await form626a.validate();
56+
57+
expect(form626a.isValid).to.be.true;
58+
expect(form626a.$('passwordConfirm').hasError).to.be.false;
59+
});
60+
});

tests/data/forms/fixes/form.626b.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { expect } from 'chai';
2+
import { describe, it } from 'mocha';
3+
import * as yup from 'yup';
4+
import Form from '../../../../src';
5+
import $yup from "../../../../src/validators/YUP";
6+
7+
const plugins = {
8+
dvr: $yup({
9+
package: yup,
10+
schema: (y: any) =>
11+
y.object().shape({
12+
subscribe: y.boolean(),
13+
email: y.string().when('subscribe', {
14+
is: true,
15+
then: (schema: any) => schema.required('Email is required if subscribed'),
16+
otherwise: (schema: any) => schema.notRequired(),
17+
}),
18+
}),
19+
}),
20+
};
21+
22+
const fields = [
23+
{
24+
name: 'subscribe',
25+
label: 'Subscribe',
26+
type: 'checkbox',
27+
},
28+
{
29+
name: 'email',
30+
label: 'Email',
31+
placeholder: 'Enter your email',
32+
},
33+
];
34+
35+
export const form626b = new Form({ fields }, { plugins });
36+
37+
38+
describe('Yup plugin with yup.when()', () => {
39+
it('should require email when subscribe is true', async () => {
40+
form626b.reset();
41+
form626b.$('subscribe').set(true);
42+
form626b.$('email').set('');
43+
44+
await form626b.validate();
45+
46+
expect(form626b.isValid).to.be.false;
47+
expect(form626b.$('email').hasError).to.be.true;
48+
expect(form626b.$('email').error).to.equal('Email is required if subscribed');
49+
});
50+
51+
it('should not require email when subscribe is false', async () => {
52+
form626b.reset();
53+
form626b.$('subscribe').set(false);
54+
form626b.$('email').set('');
55+
56+
await form626b.validate();
57+
58+
expect(form626b.isValid).to.be.true;
59+
expect(form626b.$('email').hasError).to.be.false;
60+
});
61+
62+
it('should pass validation if email is set when subscribe is true', async () => {
63+
form626b.reset();
64+
form626b.$('subscribe').set(true);
65+
form626b.$('email').set('test@example.com');
66+
67+
await form626b.validate();
68+
69+
expect(form626b.isValid).to.be.true;
70+
expect(form626b.$('email').hasError).to.be.false;
71+
});
72+
});

0 commit comments

Comments
 (0)