Skip to content

Commit

Permalink
feat: Add requiredWhen support
Browse files Browse the repository at this point in the history
  • Loading branch information
Codycody31 committed Mar 16, 2024
1 parent 5b5dc8f commit ea7b454
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 3 deletions.
57 changes: 57 additions & 0 deletions __tests__/validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,63 @@ describe("Validator - Required Validation", () => {
});
});

describe("Validator - Required When Validation", () => {
it("should validate requiredWhen fields", () => {
const validator = new Validator(
{
name: { type: "string", requiredWhen: { field: "age", value: 18 } },
age: { type: "number" },
},
{
name: {
type: "Name must be a string",
requiredWhen: "Name is required",
},
age: {
type: "Age must be a number",
},
}
);

expect(validator.validate({ name: "John Doe", age: 18 })).resolves.toBe(
true
);
expect(validator.validate({ age: 18 })).resolves.toBe(false);
});

it("should validate requiredWhen fields with multiple values", () => {
const validator = new Validator(
{
name: {
type: "string",
requiredWhen: {
field: "age",
value: [18, 20],
},
},
age: { type: "number" },
},
{
name: {
type: "Name must be a string",
requiredWhen: "Name is required",
},
age: {
type: "Age must be a number",
},
}
);

expect(validator.validate({ name: "John Doe", age: 18 })).resolves.toBe(
true
);
expect(validator.validate({ name: "John Doe", age: 20 })).resolves.toBe(
true
);
expect(validator.validate({ age: 18 })).resolves.toBe(false);
});
});

describe("Validator - Min/Max Validation", () => {
it("should validate number fields against a minimum value", () => {
const validator = new Validator(
Expand Down
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,18 @@
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@types/jest": "^29.5.10",
"@types/mocha": "^10.0.6",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"conventional-changelog-conventionalcommits": "^7.0.2",
"eslint": "^8.54.0",
"fix-tsup-cjs": "^1.2.0",
"jest": "^29.7.0",
"jest-sonar-reporter": "^2.0.0",
"semantic-release": "^22.0.12",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"tsup": "^8.0.1",
"typescript": "^5.3.2",
"fix-tsup-cjs": "^1.2.0"
"typescript": "^5.3.2"
}
}
}
36 changes: 36 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ interface Rule {
* Enumeration of valid values.
*/
enum?: Array<string | number | boolean>;
/**
* Field is required when another field matches a specific value.
*/
requiredWhen?: { field: string; value: any | any[] };
}

/**
Expand Down Expand Up @@ -84,6 +88,10 @@ interface Message {
* The error message for invalid enum value.
*/
enum?: string;
/**
* The error message for requiredWhen validation failure.
*/
requiredWhen?: string;
}

/**
Expand Down Expand Up @@ -255,6 +263,34 @@ class Validator {
continue; // Skip further checks if the field is missing
}

// Handle requiredWhen condition
if (rule.requiredWhen) {
const conditionField = rule.requiredWhen.field;
const conditionValue = rule.requiredWhen.value;
let conditionMet = false;

// Check if conditionValue is an array and if it includes the input value
if (Array.isArray(conditionValue)) {
conditionMet = conditionValue.includes(input[conditionField]);
} else {
// If conditionValue is not an array, proceed with the normal equality check
conditionMet = input[conditionField] === conditionValue;
}

// If the condition is met and the field is required but not present or empty
if (conditionMet && (value === "" || value === undefined)) {
this.errors[key] =
this.messages[key].required ??
`"${key}" is required when "${conditionField}" is set to ${
Array.isArray(conditionValue)
? conditionValue.join(" or ")
: conditionValue
}.`;
isValid = false;
continue; // Skip further checks for this field
}
}

// If the value is not present, no need to check further rules
if (value === undefined) continue;

Expand Down

0 comments on commit ea7b454

Please sign in to comment.