Skip to content

Commit

Permalink
fix: partial()
Browse files Browse the repository at this point in the history
BREAKING CHANGE: 'required' no longer adds a test for most schema, to determine if a schema is required, check it's `spec.optional` and `spec.nullable` values, also accessible via `describe()`
  • Loading branch information
jquense committed Mar 9, 2022
1 parent 0001b0b commit 1207261
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 63 deletions.
10 changes: 6 additions & 4 deletions src/array.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import isAbsent from './util/isAbsent';
import isSchema from './util/isSchema';
import printValue from './util/printValue';
import parseJson from './util/parseJson';
Expand Down Expand Up @@ -192,8 +191,9 @@ export default class ArraySchema<
name: 'length',
exclusive: true,
params: { length },
skipAbsent: true,
test(value) {
return isAbsent(value) || value.length === this.resolve(length);
return value!.length === this.resolve(length);
},
});
}
Expand All @@ -206,9 +206,10 @@ export default class ArraySchema<
name: 'min',
exclusive: true,
params: { min },
skipAbsent: true,
// FIXME(ts): Array<typeof T>
test(value) {
return isAbsent(value) || value.length >= this.resolve(min);
return value!.length >= this.resolve(min);
},
});
}
Expand All @@ -220,8 +221,9 @@ export default class ArraySchema<
name: 'max',
exclusive: true,
params: { max },
skipAbsent: true,
test(value) {
return isAbsent(value) || value.length <= this.resolve(max);
return value!.length <= this.resolve(max);
},
});
}
Expand Down
7 changes: 4 additions & 3 deletions src/date.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// @ts-ignore
import isoParse from './util/isodate';
import { date as locale } from './locale';
import isAbsent from './util/isAbsent';
import Ref from './Reference';
import type { AnyObject, Message } from './types';
import type {
Expand Down Expand Up @@ -85,8 +84,9 @@ export default class DateSchema<
name: 'min',
exclusive: true,
params: { min },
skipAbsent: true,
test(value) {
return isAbsent(value) || value >= this.resolve(limit);
return value! >= this.resolve(limit);
},
});
}
Expand All @@ -99,8 +99,9 @@ export default class DateSchema<
name: 'max',
exclusive: true,
params: { max },
skipAbsent: true,
test(value) {
return isAbsent(value) || value <= this.resolve(limit);
return value! <= this.resolve(limit);
},
});
}
Expand Down
15 changes: 10 additions & 5 deletions src/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ export default class NumberSchema<
name: 'min',
exclusive: true,
params: { min },
skipAbsent: true,
test(value: Maybe<number>) {
return isAbsent(value) || value >= this.resolve(min);
return value! >= this.resolve(min);
},
});
}
Expand All @@ -79,8 +80,9 @@ export default class NumberSchema<
name: 'max',
exclusive: true,
params: { max },
skipAbsent: true,
test(value: Maybe<number>) {
return isAbsent(value) || value <= this.resolve(max);
return value! <= this.resolve(max);
},
});
}
Expand All @@ -91,8 +93,9 @@ export default class NumberSchema<
name: 'max',
exclusive: true,
params: { less },
skipAbsent: true,
test(value: Maybe<number>) {
return isAbsent(value) || value < this.resolve(less);
return value! < this.resolve(less);
},
});
}
Expand All @@ -103,8 +106,9 @@ export default class NumberSchema<
name: 'min',
exclusive: true,
params: { more },
skipAbsent: true,
test(value: Maybe<number>) {
return isAbsent(value) || value > this.resolve(more);
return value! > this.resolve(more);
},
});
}
Expand All @@ -121,7 +125,8 @@ export default class NumberSchema<
return this.test({
name: 'integer',
message,
test: (val) => isAbsent(val) || Number.isInteger(val),
skipAbsent: true,
test: (val) => Number.isInteger(val),
});
}

Expand Down
26 changes: 3 additions & 23 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -627,10 +627,6 @@ export default abstract class Schema<
return this.clone({ strict: isStrict });
}

protected _isPresent(value: any) {
return value != null;
}

protected nullability(nullable: boolean, message?: Message<any>) {
const next = this.clone({ nullable });
next.internalTests.nullable = createValidation({
Expand Down Expand Up @@ -671,27 +667,11 @@ export default abstract class Schema<

required(message: Message<any> = locale.required): any {
return this.clone().withMutation((next) =>
next
.nonNullable(message)
.defined(message)
.test({
message,
name: 'required',
exclusive: true,
test(value: any) {
return this.schema._isPresent(value);
},
}),
) as any;
next.nonNullable(message).defined(message),
);
}

notRequired(): any {
return this.clone().withMutation((next) => {
next.tests = next.tests.filter(
(test) => test.OPTIONS!.name !== 'required',
);
return next.nullable().optional();
});
return this.clone().withMutation((next) => next.nullable().optional());
}

transform(fn: TransformFunction<this>) {
Expand Down
36 changes: 27 additions & 9 deletions src/string.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MixedLocale, string as locale } from './locale';
import { MixedLocale, mixed as mixedLocale, string as locale } from './locale';
import isAbsent from './util/isAbsent';
import type Reference from './Reference';
import type { Message, AnyObject } from './types';
Expand Down Expand Up @@ -83,8 +83,22 @@ export default class StringSchema<
});
}

protected _isPresent(value: any) {
return super._isPresent(value) && !!value.length;
required(message?: Message<any>) {
return super.required(message).withMutation((schema: this) =>
schema.test({
message: message || mixedLocale.required,

This comment has been minimized.

Copy link
@baluram-kumavat-acute

baluram-kumavat-acute Jun 1, 2024

@jquense Hey, in the old version of Yup (0.32.9), my schema validation worked fine. However, in the latest version, I am encountering an error because of the message: message || mixedLocale.required. The error says 'This field is required'. What should I pass to fix this?

"schemaValidation": {
"type": "string",
"rules": [
{
"name": "required",
"params": [
""
]
},
{
"name": "max",
"params": [
2,
"No. of Dependence maximum 3 digit."
]
}
]
},

name: 'required',
skipAbsent: true,
test: (value) => !!value!.length,
}),
);
}

notRequired() {
return super.notRequired().withMutation((schema: this) => {
schema.tests.filter((t) => t.OPTIONS!.name !== 'required');
return schema;
});
}

length(
Expand All @@ -96,8 +110,9 @@ export default class StringSchema<
name: 'length',
exclusive: true,
params: { length },
skipAbsent: true,
test(value: Maybe<string>) {
return isAbsent(value) || value.length === this.resolve(length);
return value!.length === this.resolve(length);
},
});
}
Expand All @@ -111,8 +126,9 @@ export default class StringSchema<
name: 'min',
exclusive: true,
params: { min },
skipAbsent: true,
test(value: Maybe<string>) {
return isAbsent(value) || value.length >= this.resolve(min);
return value!.length >= this.resolve(min);
},
});
}
Expand All @@ -126,8 +142,9 @@ export default class StringSchema<
exclusive: true,
message,
params: { max },
skipAbsent: true,
test(value: Maybe<string>) {
return isAbsent(value) || value.length <= this.resolve(max);
return value!.length <= this.resolve(max);
},
});
}
Expand All @@ -153,10 +170,9 @@ export default class StringSchema<
name: name || 'matches',
message: message || locale.matches,
params: { regex },
skipAbsent: true,
test: (value: Maybe<string>) =>
isAbsent(value) ||
(value === '' && excludeEmptyString) ||
value.search(regex) !== -1,
(value === '' && excludeEmptyString) || value!.search(regex) !== -1,
});
}

Expand Down Expand Up @@ -206,6 +222,7 @@ export default class StringSchema<
message,
name: 'string_case',
exclusive: true,
skipAbsent: true,
test: (value: Maybe<string>) =>
isAbsent(value) || value === value.toLowerCase(),
});
Expand All @@ -218,6 +235,7 @@ export default class StringSchema<
message,
name: 'string_case',
exclusive: true,
skipAbsent: true,
test: (value: Maybe<string>) =>
isAbsent(value) || value === value.toUpperCase(),
});
Expand Down
11 changes: 8 additions & 3 deletions src/util/createValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from '../types';
import Reference from '../Reference';
import type { AnySchema } from '../schema';
import isAbsent from './isAbsent';

export type PanicCallback = (err: Error) => void;

Expand Down Expand Up @@ -58,6 +59,7 @@ export type TestConfig<TValue = unknown, TContext = {}> = {
test: TestFunction<TValue, TContext>;
params?: ExtraParams;
exclusive?: boolean;
skipAbsent?: boolean;
};

export type Test = ((
Expand All @@ -73,6 +75,7 @@ export default function createValidation(config: {
test: TestFunction;
params?: ExtraParams;
message?: Message<any>;
skipAbsent?: boolean;
}) {
function validate<TSchema extends AnySchema = AnySchema>(
{
Expand All @@ -88,7 +91,7 @@ export default function createValidation(config: {
panic: PanicCallback,
next: NextCallback,
) {
const { name, test, params, message } = config;
const { name, test, params, message, skipAbsent } = config;
let { parent, context, abortEarly = rest.schema.spec.abortEarly } = options;

function resolve<T>(item: T | Reference<T>) {
Expand Down Expand Up @@ -144,9 +147,11 @@ export default function createValidation(config: {
else panic(err);
};

const shouldSkip = skipAbsent && isAbsent(value);

if (!sync) {
try {
Promise.resolve(test.call(ctx, value, ctx)).then(
Promise.resolve(!shouldSkip ? test.call(ctx, value, ctx) : true).then(
handleResult,
handleError,
);
Expand All @@ -159,7 +164,7 @@ export default function createValidation(config: {

let result: ReturnType<TestFunction>;
try {
result = test.call(ctx, value, ctx);
result = !shouldSkip ? test.call(ctx, value, ctx) : true;

if (typeof (result as any)?.then === 'function') {
throw new Error(
Expand Down
21 changes: 6 additions & 15 deletions test/mixed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,10 +711,11 @@ describe('Mixed Types ', () => {
await expect(inst.isValid('a')).resolves.toBe(true);
});

it('concat should maintain explicit presence', async function () {
let inst = string().required().concat(string());
it('concat should override presence', async function () {
let inst = string().required().concat(string().nullable());

await expect(inst.isValid(undefined)).resolves.toBe(false);
await expect(inst.isValid(undefined)).resolves.toBe(true);
await expect(inst.isValid(null)).resolves.toBe(true);
});

it('gives whitelist precedence to second in concat', async function () {
Expand Down Expand Up @@ -968,12 +969,7 @@ describe('Mixed Types ', () => {
label: undefined,
nullable: false,
optional: false,
tests: [
{
name: 'required',
params: undefined,
},
],
tests: [],
oneOf: [],
notOneOf: [],
innerType: {
Expand Down Expand Up @@ -1040,12 +1036,7 @@ describe('Mixed Types ', () => {
label: undefined,
nullable: false,
optional: false,
tests: [
{
name: 'required',
params: undefined,
},
],
tests: [],
oneOf: [],
notOneOf: [],
innerType: {
Expand Down
Loading

0 comments on commit 1207261

Please sign in to comment.