@hapi/code

repository·master·Indexed 42 days ago

https://github.com/hapijs/code

A 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.

Tokens
4.7K
Snippets
17
Records
23
Agent score
51%

What's inside Code

  1. Overview of @hapi/code

    master
    @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.
  2. How grammar and flags work in @hapi/code

    master

    Assertions in @hapi/code use 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 this to 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 with include()).
    • only: Requires that only the provided elements appear in the value (used with include()).
    • part: Allows a partial match (used with include()). Defaults to false.
    • shallow: Performs a strict equality (===) comparison instead of the default deep comparison (used with equal() and include()).
    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]);
  3. Quickstart with @hapi/code

    master

    To use @hapi/code for assertions, import the module and use the expect() method. The library uses a chainable grammar to make assertions readable.

    Note: Unlike some other libraries, code is designed to prevent silent failures. If you forget to call a method (e.g., expect(5).to.be.a.string instead of expect(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']);
  4. Configure @hapi/code settings

    master

    Global settings can be adjusted via Code.settings:

    • truncateMessages (Boolean): If true, long assertion error messages are truncated. Defaults to true.
    • comparePrototypes (Boolean): If false, ignores object prototypes during deep comparison. Defaults to false.
    const Code = require('code');
    Code.settings.truncateMessages = false;
    Code.settings.comparePrototypes = false;
  5. Assertion flags and modifiers

    master

    You 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 })
  6. Use assertion flags like not, once, and shallow

    master

    The Assertion object 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 });
  7. Assert inclusion and string patterns

    master

    Methods 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 with value (case sensitive).
    • endWith(value): (Alias: endsWith()). Asserts a string ends with value (case sensitive).
  8. Use expect(value, [prefix]) for assertions

    master

    The 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);
  9. Assert numeric ranges

    master

    Use 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 within delta of value.
  10. Assert types with @hapi/code

    master

    Use the following methods to verify the type of the reference value:

    • arguments(): Is an arguments object.
    • array(): Is an Array.
    • boolean(): Is a boolean.
    • buffer(): Is a Buffer.
    • date(): Is a Date.
    • error([type], [message]): Is an error. type is the instanceof value; message is a string (full match) or RegExp.
    • function(): Is a function.
    • number(): Is a number.
    • regexp(): Is a RegExp.
    • string(): Is a string.
    • object(): Is an object (excluding array, buffer, or other native objects).
    • instanceof(type): Has the provided instanceof value.
  11. Assert errors and promise rejections

    master

    Verify 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!');
  12. Assert values and equality

    master

    Verify specific values or equality:

    • true(), false(), null(), undefined(), NaN(): Checks for specific primitive values.
    • equal(value, [options]): Asserts equality. Defaults to deep comparison (via Hoek.deepEqual()). Use .shallow flag for === comparison.
    • exist(): Asserts the value is not null or undefined.
    • empty(): Asserts length === 0 or an object has no keys.
    • length(size): Asserts the length property or number of object keys matches size.
    • match(regex): Asserts toString() matches the provided regular expression.
    • satisfy(validator): Asserts the value satisfies a function validator(value) that returns true or false.