@fosco110/expectations-js
TypeScript icon, indicating that this package has built-in type declarations

0.7.1 • Public • Published

expectations-js

A developer-friendly, no-dependency Typescript data-validation framework

Installation

npm install expectations-js

What does it do?

When dealing with user input, you cannot rely on the data to be valid. This library allows you to easily validate data, and get a list of errors if the data is invalid.
You just need to define a set of expectations to which your data should conform. If it does not, you will get a list of errors, which you can then use to display to the user.
This is particularly suited to form validation, but it can be used for any kind of data validation. (e.g. API responses)

Usage

To get started, you can import these functions:

import { when, expect, validate, isValid } from '@fosco110/expectations-js';

You will then need to create an array, in which you can put your validation rules.

const expectations = [
	expect('name').toMatch(/^[a-zA-Z]+$/),
	when('age').isLessThan(18).expect('name').not.toEqual('John'),
]

To run the validation, you can use the validate function.

const data = {
	name: 'John',
	age: 17,
}
const res = validate(data, expectations);

If you need to check whether the data is valid, you can use the isValid function.

const valid = isValid(data, expectations);

API

The expect function takes a key, and creates a Expectation object. You can then chain methods to it, to create a validation rule.

expect('name').toMatch(/^[a-zA-Z]+$/)

By default, when you expect a key, it will be considered required. If you want to allow it to be undefined, you can use the notRequired method.

expect('name').notRequired().toMatch(/^[a-zA-Z]+$/)

If you need to run an inverse check, just use not.

expect('name').not.toMatch(/^[a-zA-Z]+$/)

If you need to perform a validation on multiple items (e.g. an array), you can use the each method.

expect('names').each().toMatch(/^[a-zA-Z]+$/)

For more complex operations (e.g. two values dependent on eachother), use the when method. You can then expect a key to be a certain value, or then expect some more expectations.

when('age').isLessThan(18).then(expect('name').not.toBe('John'))
when('age').isLessThan(18).then([
	expect('name').not.toBe('John'),
	expect('surname').not.toBe('Doe'),
])

You can chain these conditions with the and and or methods.

when('age').isLessThan(18).and('parentConsent').is(true).then(expect('name').not.toBe('Mike')) // Mike is a bad kid, he can't ever use this service
when('age').isLessThan(18).or('parentConsent').is(false).then(expect('name').toBe('John')) // John is special, he doesn't need his parents' consent

You can also chain the onConditionsMet, onConditionsNotMet, onExpectationsMet, onExpectationsNotMet methods to set custom error messages.

when('age').isLessThan(18).and('parentConsent').is(false).onConditionsNotMet('parentConsent', "You must have your parent's consent to use this service")
when('age').isLessThan(18)

If you put a %key% in the error message, it will be replaced with the value of the key. If you need it capitalized, just use %key.capitalize%.

expect('age').toBeLessThan(18).ifNot('%key.capitalize% must be 18 or older') // Age must be 18 or older

In case of more complex validation operations (e.g. an object, an object inside an array, an object inside another object), you can use SubExpectations.

const data = {
	user: {
		name: 'John',
		age: 17,
	},
};
const expectations = [
	expect('user').toSatisfy([
		expect('name').toMatch(/^[a-zA-Z]+$/),
		expect('age').toBeGreaterThan(18),
	])
];
const res = validate(data, expectations);
/**
 * res = {
 * 	user: {
 * 		age: 'age must be greater than 18',
 * 	},
 * }
 */

You can chain these conditions with the and and or methods, and use the error method to set a custom error message.

when('age').isLessThan(18).and('parentConsent').is(false).error('parentConsent', "You must have your parent's consent to use this service")

Interpreting return values

The validate function returns an object, whose keys are set when a validation fails. If the key corresponds to an array, it will by default create an empty array. Check for failures in the array, to see what went wrong. If it corresponds to an object, it will create an empty object. Again, check for failures in the object, to see what went wrong.

Example

const data = {
	name: 'John',
	age: 17,
	agreeToTerms: false,
}
const expectations = [
	expect('name').toMatch(/^[a-zA-Z]+$/),
	when('age').isLessThan(18).then(
		expect('name').not.toEqual('John').ifNot("Sorry John, you're too young")
	),
	expect('agreeToTerms').toBe(true).ifNot('You must agree to the terms'),
]
const res = validate(data, expectations);

In this example, the res object will look like this:

{
	name: "Sorry John, you're too young",
	agreeToTerms: 'You must agree to the terms',
}

This means that the validation failed for the fields name and agreeToTerms.

NOTE: The age field is not present in the res object, because the validation passed for that field. If you wanted to check for the user to be at least 18, you could put this expectation:

expect('age').toBeGreaterThan(17).ifNot("You must be 18 or older to use this service")

or

expect('age').not.toBeLessThan(18).ifNot("You must be 18 or older to use this service")

Debugging

If you need to debug your expectations, you can chain the debug method to any expectation.

expect('name').debug().toMatch(/^[a-zA-Z]+$/)

You can chain this anywhere, on the when function too.

when('age').debug().isLessThan(18).expect('name').not.toEqual('John')

Package Sidebar

Install

npm i @fosco110/expectations-js

Weekly Downloads

50

Version

0.7.1

License

LGPL-3.0-or-later

Unpacked Size

85.5 kB

Total Files

26

Last publish

Collaborators

  • fosco110