@hapi/code
repository·master·Indexed 42 days ago
https://github.com/hapijs/codeA BDD assertion library for testing and validating values in JavaScript applications. Part of the hapi ecosystem but framework-agnostic, it features a chainable grammar and flags like .not, .once, .only, .part, and .shallow to create readable assertions. Version 9.0.3 provides comprehensive tools for asserting types, numeric ranges, string patterns, and promise rejections, while preventing silent failures through incomplete assertion detection.
What's inside Code
- @hapi/code is a BDD (Behavior-Driven Development) assertion library. While it is part of the hapi ecosystem and designed to work seamlessly with the hapi web framework, it is a standalone library that can be used with any other framework or in any JavaScript project.
How grammar and flags work in @hapi/code
masterAssertions in
@hapi/codeuse connecting words (grammar) and status toggles (flags) to build readable chains.Grammar Words
These words have no impact on the assertion outcome; they are for human readability and return
thisto allow chaining:a,an,and,at,be,have,in,to
Flags
Flags toggle a status for the current assertion. Including the same flag twice toggles the last value set (useful when chaining with
and):not: Inverses the expected result.once: Requires inclusion matches to appear exactly once (used withinclude()).only: Requires that only the provided elements appear in the value (used withinclude()).part: Allows a partial match (used withinclude()). Defaults tofalse.shallow: Performs a strict equality (===) comparison instead of the default deep comparison (used withequal()andinclude()).
const Code = require('code'); const expect = Code.expect; // Using grammar and flags expect(10).to.not.be.above(20); expect([1, 2, 3]).to.shallow.include(3); expect([1, 1, 2]).to.only.include([1, 2]); expect([1, 2, 3]).to.part.include([1, 4]);Quickstart with @hapi/code
masterTo use
@hapi/codefor assertions, import the module and use theexpect()method. The library uses a chainable grammar to make assertions readable.Note: Unlike some other libraries,
codeis designed to prevent silent failures. If you forget to call a method (e.g.,expect(5).to.be.a.stringinstead ofexpect(5).to.be.a.string()), the library can detect this incomplete assertion.const Code = require('@hapi/code'); const expect = Code.expect; expect(true).to.be.a.boolean().and.to.not.equal(false); expect('this string').to.only.include(['this', 'string']);Configure @hapi/code settings
masterGlobal settings can be adjusted via
Code.settings:truncateMessages(Boolean): Iftrue, long assertion error messages are truncated. Defaults totrue.comparePrototypes(Boolean): Iffalse, ignores object prototypes during deep comparison. Defaults tofalse.
const Code = require('code'); Code.settings.truncateMessages = false; Code.settings.comparePrototypes = false;Assertion flags and modifiers
masterYou can modify the behavior of an assertion chain using flags:
.not: Inverts the expected result of the assertion (e.g.,expect(x).not.equal(y))..once: Requires that inclusion matches appear exactly once in the provided value..only: Requires that only the provided elements appear in the provided value..part: Allows a partial match when asserting inclusion instead of a full comparison..shallow: Performs a comparison using strict equality (===) instead of a deep comparison.
import { expect } // Using .not to invert expect(true).not.equal(false) // Using .shallow for strict equality expect({ a: 1 }).shallow.equal({ a: 1 })Use assertion flags like not, once, and shallow
masterThe
Assertionobject supports several flags that modify the behavior of the subsequent method call:.not: Inverts the assertion (e.g.,expect(x).to.not.equal(y))..once: Used with certain methods to assert a single occurrence..shallow: Used with.equal()to perform a shallow comparison instead of a deep one..part: Used with.include()to check for property existence rather than value containment.
// Inverting an assertion Code.expect(5).to.not.equal(6); // Shallow comparison Code.expect({ a: 1 }).to.shallow.equal({ a: 1 });Assert inclusion and string patterns
masterMethods for checking contents of strings, arrays, or objects:
include(values): (Aliases:includes(),contain(),contains()). Asserts a string, array, or object includes the provided values. Supports flags like.only,.once,.part, and.shallow.startWith(value): (Alias:startsWith()). Asserts a string starts withvalue(case sensitive).endWith(value): (Alias:endsWith()). Asserts a string ends withvalue(case sensitive).
Use expect(value, [prefix]) for assertions
masterThe
expect(value, [prefix])function generates an assertion object.value: The reference value to assert against.prefix: An optional string used as an error message prefix to provide context in failures.
Example:
expect(10, 'Age').to.be.above(5);const Code = require('code'); const expect = Code.expect; expect(10, 'Age').to.be.above(5);Assert numeric ranges
masterUse these methods to check numeric boundaries:
above(value):value > target.at.least(value):value >= target.below(value):value < target.at.most(value):value <= target.within(from, to):from <= value <= to(inclusive).between(from, to):from < value < to(exclusive).about(value, delta): Value is withindeltaofvalue.
Assert types with @hapi/code
masterUse the following methods to verify the type of the reference value:
arguments(): Is anargumentsobject.array(): Is anArray.boolean(): Is a boolean.buffer(): Is aBuffer.date(): Is aDate.error([type], [message]): Is an error.typeis theinstanceofvalue;messageis a string (full match) or RegExp.function(): Is afunction.number(): Is anumber.regexp(): Is aRegExp.string(): Is astring.object(): Is an object (excluding array, buffer, or other native objects).instanceof(type): Has the providedinstanceofvalue.
Assert errors and promise rejections
masterVerify that code fails as expected:
Throwing Errors
Use
throw([type], [message])to assert that a function reference throws an exception.Promise Rejections
Use
await expect(promise).to.reject([type], [message])to assert that a Promise rejects. This returns a promise resolving to the rejected error object, allowing you to inspect it.// Throwing const throws = function () { throw new Error('Oh no!'); }; expect(throws).to.throw(Error, 'Oh no!'); // Rejecting const rejects = function () { return Promise.reject(new Error('Fail')); }; const err = await expect(rejects()).to.reject(Error, 'Fail');const NodeUtil = require('util'); const Code = require('code'); const expect = Code.expect; const CustomError = function (message) { Error.call(this, message); }; NodeUtil.inherit(CustomError, Error); const throws = function () { throw new CustomError('Oh no!'); }; expect(throws).to.throw(CustomError, 'Oh no!');Assert values and equality
masterVerify specific values or equality:
true(),false(),null(),undefined(),NaN(): Checks for specific primitive values.equal(value, [options]): Asserts equality. Defaults to deep comparison (viaHoek.deepEqual()). Use.shallowflag for===comparison.exist(): Asserts the value is notnullorundefined.empty(): Assertslength === 0or an object has no keys.length(size): Asserts thelengthproperty or number of object keys matchessize.match(regex): AssertstoString()matches the provided regular expression.satisfy(validator): Asserts the value satisfies a functionvalidator(value)that returnstrueorfalse.