Skip to content

Commit

Permalink
fix(ObjectType): fix required message for properties not being replac…
Browse files Browse the repository at this point in the history
…ed (#79)

* fix(ObjectType): fix required message for properties not being replaced

* test: update tests

* test: add tests for rule priority
  • Loading branch information
simonguo authored Apr 12, 2024
1 parent c349fe7 commit 2aab276
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .codesandbox/ci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"sandboxes": ["new"]
}
20 changes: 11 additions & 9 deletions src/MixedType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ export class MixedType<ValueType = any, DataType = any, E = ErrorMessageType, L
this.fieldLabel
);

const checkStatus = validator(value, this.priorityRules);
const checkResult = validator(value, this.priorityRules);

if (checkStatus) {
return checkStatus;
// If the priority rule fails, return the result directly
if (checkResult) {
return checkResult;
}

if (!this.required && isEmpty(value)) {
Expand Down Expand Up @@ -124,9 +125,10 @@ export class MixedType<ValueType = any, DataType = any, E = ErrorMessageType, L

return new Promise(resolve =>
validator(value, this.priorityRules)
.then((checkStatus: CheckResult<E | string> | void | null) => {
if (checkStatus) {
resolve(checkStatus);
.then((checkResult: CheckResult<E | string> | void | null) => {
// If the priority rule fails, return the result directly
if (checkResult) {
resolve(checkResult);
}
})
.then(() => {
Expand All @@ -135,9 +137,9 @@ export class MixedType<ValueType = any, DataType = any, E = ErrorMessageType, L
}
})
.then(() => validator(value, this.rules))
.then((checkStatus: CheckResult<E | string> | void | null) => {
if (checkStatus) {
resolve(checkStatus);
.then((checkResult: CheckResult<E | string> | void | null) => {
if (checkResult) {
resolve(checkResult);
}
resolve({ hasError: false });
})
Expand Down
4 changes: 2 additions & 2 deletions src/ObjectType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class ObjectType<DataType = any, E = ErrorMessageType> extends MixedType<
if (type.required && !checkRequired(value, type.trim, type.emptyAllowed)) {
return {
hasError: true,
errorMessage: formatErrorMessage<E>(this.requiredMessage || this.locale.isRequired, {
errorMessage: formatErrorMessage<E>(type.requiredMessage || type.locale?.isRequired, {
name: type.fieldLabel || childFieldKey || fieldName
})
};
Expand Down Expand Up @@ -75,7 +75,7 @@ export class ObjectType<DataType = any, E = ErrorMessageType> extends MixedType<
if (type.required && !checkRequired(value, type.trim, type.emptyAllowed)) {
return Promise.resolve({
hasError: true,
errorMessage: formatErrorMessage<E>(this.requiredMessage || this.locale.isRequired, {
errorMessage: formatErrorMessage<E>(type.requiredMessage || type.locale?.isRequired, {
name: type.fieldLabel || childFieldKey || fieldName
})
});
Expand Down
7 changes: 7 additions & 0 deletions src/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ export class Schema<DataType = any, ErrorMsgType = string> {
return Object.keys(this.$spec);
}

/**
* Get the schema specification
*/
getSchemaSpec() {
return this.$spec;
}

checkForField<T extends keyof DataType>(
fieldName: T,
data: DataType,
Expand Down
68 changes: 68 additions & 0 deletions test/MixedTypeSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,74 @@ describe('#MixedType', () => {
schema2.checkForField('str', { str: '12' }).hasError.should.equal(true);
schema2.checkForField('str', { str: '12' }).errorMessage.should.equal('error');
});

describe('priority - async', () => {
it('Should have the correct priority', async () => {
const schema = SchemaModel({
name: StringType()
.isEmail('error1')
.addRule(() => false, 'error2')
});

const result = await schema.checkAsync({ name: 'a' });

expect(result).to.deep.equal({
name: { hasError: true, errorMessage: 'error1' }
});

const schema2 = SchemaModel({
name: StringType()
.isEmail('error1')
.addRule(() => false, 'error2', true)
});

const result2 = await schema2.checkAsync({ name: 'a' });

expect(result2).to.deep.equal({
name: { hasError: true, errorMessage: 'error2' }
});

const schema3 = SchemaModel({
name: StringType().addRule(() => true, 'error2', true)
});

const result3 = await schema3.checkAsync({ name: 'a' });

expect(result3).to.deep.equal({
name: { hasError: false }
});
});

it('Should be isRequired with a higher priority than addRule', async () => {
const schema = SchemaModel({
str: StringType()
.isRequired('required')
.addRule(value => value === '', 'error')
});

const result = await schema.checkAsync({ str: '' });

expect(result).to.deep.equal({
str: { hasError: true, errorMessage: 'required' }
});

const result2 = await schema.checkAsync({ str: '12' });

expect(result2).to.deep.equal({
str: { hasError: true, errorMessage: 'error' }
});

const schema2 = SchemaModel({
str: StringType().addRule(value => value === '', 'error')
});

const result3 = await schema2.checkAsync({ str: '12' });

expect(result3).to.deep.equal({
str: { hasError: true, errorMessage: 'error' }
});
});
});
});

describe('required', () => {
Expand Down
90 changes: 90 additions & 0 deletions test/ObjectTypeSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,4 +323,94 @@ describe('#ObjectType', () => {
const result = await schema.checkAsync({ user: null });
expect(result).to.deep.equal({ user: { hasError: false } });
});

it('Should replace default required message', () => {
const schema = new Schema({
user: ObjectType().shape({
email1: StringType().isEmail().isRequired(),
email2: StringType().isEmail().isRequired('Email is required')
})
});

const result = schema.check({ user: { email1: '', email2: '' } });

expect(result.user.object.email1.errorMessage).to.equal('email1 is a required field');
expect(result.user.object.email2.errorMessage).to.equal('Email is required');
});

it('Should replace default required message with async', async () => {
const schema = new Schema({
user: ObjectType().shape({
email1: StringType().isEmail().isRequired(),
email2: StringType().isEmail().isRequired('Email is required')
})
});

const result = await schema.checkAsync({ user: { email1: '', email2: '' } });

expect(result.user.object.email1.errorMessage).to.equal('email1 is a required field');
expect(result.user.object.email2.errorMessage).to.equal('Email is required');
});

describe('priority', () => {
it('Should have the correct priority', () => {
const schema = new Schema({
user: ObjectType().shape({
name: StringType()
.isEmail('error1')
.addRule(() => false, 'error2')
})
});

const result = schema.check({ user: { name: 'a' } });

expect(result.user.object).to.deep.equal({
name: { hasError: true, errorMessage: 'error1' }
});

const schema2 = new Schema({
user: ObjectType().shape({
name: StringType()
.isEmail('error1')
.addRule(() => false, 'error2', true)
})
});

const result2 = schema2.check({ user: { name: 'a' } });

expect(result2.user.object).to.deep.equal({
name: { hasError: true, errorMessage: 'error2' }
});
});

it('Should have the correct priority with async', async () => {
const schema = new Schema({
user: ObjectType().shape({
name: StringType()
.isEmail('error1')
.addRule(() => false, 'error2')
})
});

const result = await schema.checkAsync({ user: { name: 'a' } });

expect(result.user.object).to.deep.equal({
name: { hasError: true, errorMessage: 'error1' }
});

const schema2 = new Schema({
user: ObjectType().shape({
name: StringType()
.isEmail('error1')
.addRule(() => false, 'error2', true)
})
});

const result2 = await schema2.checkAsync({ user: { name: 'a' } });

expect(result2.user.object).to.deep.equal({
name: { hasError: true, errorMessage: 'error2' }
});
});
});
});
9 changes: 9 additions & 0 deletions test/SchemaSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ describe('#Schema', () => {
});
});

it('Should get the schema spec by calling getSchemaSpec', () => {
const model = SchemaModel({
username: StringType().isRequired(),
email: StringType().isEmail()
});

model.getSchemaSpec().should.deep.equal(model.$spec);
});

describe('## getKeys', () => {
it('Should return keys', () => {
const model = SchemaModel({
Expand Down

0 comments on commit 2aab276

Please sign in to comment.