pax_global_header00006660000000000000000000000064143413433270014516gustar00rootroot0000000000000052 comment=0de76047dcf4b6875872879204d0547d4a684fd3 code-9.0.2/000077500000000000000000000000001434134332700124405ustar00rootroot00000000000000code-9.0.2/.github/000077500000000000000000000000001434134332700140005ustar00rootroot00000000000000code-9.0.2/.github/workflows/000077500000000000000000000000001434134332700160355ustar00rootroot00000000000000code-9.0.2/.github/workflows/ci-module.yml000066400000000000000000000003141434134332700204340ustar00rootroot00000000000000name: ci on: push: branches: - master pull_request: workflow_dispatch: jobs: test: uses: hapijs/.github/.github/workflows/ci-module.yml@master with: min-node-version: 14 code-9.0.2/.gitignore000066400000000000000000000001541434134332700144300ustar00rootroot00000000000000**/node_modules **/package-lock.json coverage.* **/.DS_Store **/._* **/*.pem **/.vs **/.vscode **/.idea code-9.0.2/API.md000077500000000000000000000437041434134332700134060ustar00rootroot00000000000000 ### Introduction **code** was created as a direct rewrite of the powerful [**chai**](http://chaijs.com) assertions library. This virtual fork was created for a few reasons. First, **chai** mixed usage of methods and properties creates a problematic environment in which it is too easy to forget a method `()` and result in an assertion that is never executed (and therefore passes incorrectly). This observation was noted by the [**must**](https://github.com/moll/js-must) author. The second reason is that similar to [**lab**](https://github.com/hapijs/lab), our test runner, we wanted an assertion library that is small, simple, and intuitive - without plugins, extensions, or the overhead of having to support testing in the browser. **code** provides much of the same functionality in about 300 lines of code that are trivial to read in a few minutes. And last, we wanted to experiment with some new features that allow deeper integration between the test runner and assertions library. The first of which are two methods exported (and used by **lab**) for getting the total assertions count (which is a measure of the tests comprehensiveness), and by verifying that every assertion created (e.g. every `expect()` call) is also executed. This will alert when a statement like `expect(5).to.be.a.string` is not allowed to remain unnoticed (and fail to throw due to the missing `()`). Like **lab**, the goal is to keep this module small and simple. If you need extensibility or other functionality, we recommend looking at the many other excellent assertions libraries available. ### Example ```js 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']); ``` ### Grammar **code** supports usage of connecting words to make assertions more readable. The inclusion of these grammar elements has no impact over the assertion outcome and are used for human readability only. Every method or property of the assertion object returned by `expect()` returns `this` which allows chaining addition assertions or grammar words. The supported words are: - `a` - `an` - `and` - `at` - `be` - `have` - `in` - `to` ```js const Code = require('code'); const expect = Code.expect; expect(10).to.be.above(5); expect('abc').to.be.a.string(); expect([1, 2]).to.be.an.array(); expect(20).to.be.at.least(20); expect('abc').to.have.length(3); expect('abc').to.be.a.string().and.contain(['a', 'b']); expect(6).to.be.in.range(5, 6); ``` ### Flags The following words toggle a status flag for the current assertion: - `not` - inverses the expected result of any assertion. - `once` - requires that inclusion matches appear only once in the provided value. Used by `include()`. - `only` - requires that only the provided elements appear in the provided value. Used by `include()`. - `part` - allows a partial match when asserting inclusion. Used by `include()`. Defaults to `false`. - `shallow` - performs a comparison using strict equality (`===`). Code defaults to deep comparison. Used by `equal()` and `include()`. ```js const Code = require('code'); const expect = Code.expect; 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]).to.once.include([1, 2]); expect([1, 2, 3]).to.part.include([1, 4]); ``` Note that including the same flag twice toggles the last value set. This is especially important when chaining multiple assertions in a single statement (e.g. when using the `and` grammar word). ### `expect(value, [prefix])` Generates an assertion object where: - `value` - the reference value on which to apply the assertion rules. - `prefix` - an optional string used as an error message prefix. ```js const Code = require('code'); const expect = Code.expect; expect(10, 'Age').to.be.above(5); ``` #### Types Asserts that the reference value is of a certain type. ##### `arguments()` Asserts that the reference value is an `arguments` object. ```js const Code = require('code'); const expect = Code.expect; const func = function () { return arguments; }; expect(func()).to.be.arguments(); ``` ##### `array()` Asserts that the reference value is an `Array`. ```js const Code = require('code'); const expect = Code.expect; expect([1, 2]).to.be.an.array(); ``` ##### `boolean()` Asserts that the reference value is a boolean. ```js const Code = require('code'); const expect = Code.expect; expect(true).to.be.a.boolean(); ``` ##### `buffer()` Asserts that the reference value is a `Buffer`. ```js const Code = require('code'); const expect = Code.expect; expect(new Buffer('')).to.be.a.buffer(); ``` ##### `date()` Asserts that the reference value is a `Date`. ```js const Code = require('code'); const expect = Code.expect; expect(new Date()).to.be.a.date(); ``` ##### `error([type], [message])` Asserts that the reference value is an error. You can provide optional requirements where: - `type` - the `instanceof` value of the error. - `message` a string or regular expression matching the error `message` property. Note that a string must provide a full match. ```js const Code = require('code'); const expect = Code.expect; const err = new Error('Oops an error occured.'); expect(err).to.be.an.error(); expect(err).to.be.an.error(Error); expect(err).to.be.an.error('Oops an error occured.'); expect(err).to.be.an.error(Error, /occured/); ``` ##### `function()` Asserts that the reference value is a `function`. ```js const Code = require('code'); const expect = Code.expect; expect(function () {}).to.be.a.function(); ``` ##### `number()` Asserts that the reference value is a `number`. ```js const Code = require('code'); const expect = Code.expect; expect(123).to.be.a.number(); ``` ##### `regexp()` Asserts that the reference value is an `RegExp`. ```js const Code = require('code'); const expect = Code.expect; expect(/abc/).to.be.a.regexp(); ``` ##### `string()` Asserts that the reference value is a string. ```js const Code = require('code'); const expect = Code.expect; expect('abc').to.be.a.string(); ``` ##### `object()` Asserts that the reference value is an object (excluding array, buffer, or other native objects). ```js const Code = require('code'); const expect = Code.expect; expect({ a: '1' }).to.be.an.object(); ``` #### Values Asserts that the reference value is equal to a predefined value. ##### `true()` Asserts that the reference value is true. ```js const Code = require('code'); const expect = Code.expect; expect(true).to.be.true(); ``` ##### `false()` Asserts that the reference value is false. ```js const Code = require('code'); const expect = Code.expect; expect(false).to.be.false(); ``` ##### `null()` Asserts that the reference value is null. ```js const Code = require('code'); const expect = Code.expect; expect(null).to.be.null(); ``` ##### `undefined()` Asserts that the reference value is undefined. ```js const Code = require('code'); const expect = Code.expect; expect(undefined).to.be.undefined(); ``` ##### `NaN()` Asserts that the reference value is `NaN`. ```js const Code = require('code'); const expect = Code.expect; expect(NaN).to.be.NaN(); ``` #### `include(values)` Aliases: `includes()`, `contain()`, `contains()` See also: [`Hoek.contain()`](https://github.com/hapijs/hoek/blob/master/API.md#containref-values-options) Asserts that the reference value (a string, array, or object) includes the provided values where: - `values` - a single or array of values. If the reference value is a string, the values must be strings. If the reference value is an array, the values can be any array member. If the reference value is an object, the values can be key names, or a single object with key-value pairs to match. ```js const Code = require('code'); const expect = Code.expect; expect('abc').to.include('ab'); expect('abc').to.only.include('abc'); expect('aaa').to.only.include('a'); expect('abc').to.once.include('b'); expect('abc').to.include(['a', 'c']); expect('abc').to.part.include(['a', 'd']); expect([1, 2, 3]).to.include(1); expect([{ a: 1 }]).to.include({ a: 1 }); expect([1, 2, 3]).to.include([1, 2]); expect([{ a: 1 }]).to.include([{ a: 1 }]); expect([1, 1, 2]).to.only.include([1, 2]); expect([1, 2]).to.once.include([1, 2]); expect([1, 2, 3]).to.part.include([1, 4]); expect([[1], [2]]).to.include([[1]]); expect({ a: 1, b: 2, c: 3 }).to.include('a'); expect({ a: 1, b: 2, c: 3 }).to.include(['a', 'c']); expect({ a: 1, b: 2, c: 3 }).to.only.include(['a', 'b', 'c']); expect({ a: 1, b: 2, c: 3 }).to.include({ a: 1 }); expect({ a: 1, b: 2, c: 3 }).to.include({ a: 1, c: 3 }); expect({ a: 1, b: 2, c: 3 }).to.part.include({ a: 1, d: 4 }); expect({ a: 1, b: 2, c: 3 }).to.only.include({ a: 1, b: 2, c: 3 }); expect({ a: [1], b: [2], c: [3] }).to.include({ a: [1], c: [3] }); ``` #### `startWith(value)` Aliases: `startsWith()`, Asserts that the reference value (a string) starts with the provided value where: - `value` - a string. Note that this assertion is case sensitive. ```js const Code = require('code'); const expect = Code.expect; expect('https://example.org/secure').to.startWith('https://'); ``` #### `endWith(value)` Aliases: `endsWith()`, Asserts that the reference value (a string) ends with the provided value where: - `value` - a string. Note that this assertion is case sensitive. ```js const Code = require('code'); const expect = Code.expect; expect('http://example.org/relative').to.endWith('/relative'); ``` #### `exist()` Aliases: `exists` Asserts that the reference value exists (not `null` or `undefined`). ```js const Code = require('code'); const expect = Code.expect; expect(4).to.exist(); expect(null).to.not.exist(); ``` #### `empty()` Asserts that the reference value has a `length` property equal to zero or an object with no keys. ```js const Code = require('code'); const expect = Code.expect; expect('abc').to.be.empty(); ``` #### `length(size)` Asserts that the reference value has a `length` property matching the provided size or an object with the specified number of keys where: - `size` - the required size. ```js const Code = require('code'); const expect = Code.expect; expect('abcd').to.have.length(4); ``` #### `equal(value[, options])` Aliases: `equals()` Asserts that the reference value equals the provided value where: - `value` - the value to compare to. - `options` - optional object specifying comparison options. This is ignored on `shallow` comparisons. ```js const Code = require('code'); const expect = Code.expect; expect(5).to.equal(5); expect({ a: 1 }).to.equal({ a: 1 }); ``` Deep comparisons (the default) are performed using [`Hoek.deepEqual()`](https://github.com/hapijs/hoek/blob/master/API.md#deepequalb-a-options). The optional `options` argument is passed directly to `Hoek.deepEqual()`. An example deep comparison which ignores object prototypes is shown below. ```js const Code = require('code'); const expect = Code.expect; expect(Object.create(null)).to.equal({}, { prototype: false }); ``` Strict equality can be checked using the `shallow` modifier. This yields the same output as a `===` check. ```js const Code = require('code'); const expect = Code.expect; expect(5).to.shallow.equal(5); expect({ a: 1 }).to.shallow.equal({ a: 1 }); // fails as they are not the same reference ``` #### `above(value)` Aliases: `greaterThan()` Asserts that the reference value is greater than (`>`) the provided value where: - `value` - the value to compare to. ```js const Code = require('code'); const expect = Code.expect; expect(10).to.be.above(5); ``` #### `least(value)` Aliases: `min()` Asserts that the reference value is at least (`>=`) the provided value where: - `value` - the value to compare to. ```js const Code = require('code'); const expect = Code.expect; expect(10).to.be.at.least(10); ``` #### `below(value)` Aliases: `lessThan()` Asserts that the reference value is less than (`<`) the provided value where: - `value` - the value to compare to. ```js const Code = require('code'); const expect = Code.expect; expect(10).to.be.below(20); ``` #### `most(value)` Aliases: `max()` Asserts that the reference value is at most (`<=`) the provided value where: - `value` - the value to compare to. ```js const Code = require('code'); const expect = Code.expect; expect(10).to.be.at.most(10); ``` #### `within(from, to)` Aliases: `range()` Asserts that the reference value is within (`from <= value <= to`) the provided values where: - `from` - the start of the range (inclusive). - `to` - the end of the range (inclusive). ```js const Code = require('code'); const expect = Code.expect; expect(10).to.be.within(10, 20); expect(20).to.be.within(10, 20); ``` #### `between(from, to)` Asserts that the reference value is between but not equal (`from < value < to`) the provided values where: - `from` - the start of the range (exclusive). - `to` - the end of the range (exclusive). ```js const Code = require('code'); const expect = Code.expect; expect(15).to.be.between(10, 20); ``` #### `about(value, delta)` Asserts that the reference value is about the provided value within a delta margin of difference where: - `value` - the value to compare to. - `delta` - the allowed margin of difference. ```js const Code = require('code'); const expect = Code.expect; expect(10).to.be.about(9, 1); ``` #### `instanceof(type)` Aliases: `instanceOf()` Asserts that the reference value has the provided `instanceof` value where: - `type` - the type value to match. ```js const Code = require('code'); const expect = Code.expect; expect(new Date()).to.be.an.instanceof(Date); ``` #### `match(regex)` Aliases: `matches()` Asserts that the reference value's `toString()` representation matches the provided regular expression where: - `regex` - the regular expression to match. ```js const Code = require('code'); const expect = Code.expect; expect('a5').to.match(/\w\d/); expect(["abc", "def"]).to.match(/^[\w\d,]*$/); expect(1).to.match(/^\d$/); ``` #### `satisfy(validator)` Aliases: `satisfies()` Asserts that the reference value satisfies the provided validator function where: - `validator` - a function with the signature `function(value)` with return value `true` or `false`. The reference value is passed as the only argument to the `validator` function and the assertion passes if the return value is `true`. ```js const Code = require('code'); const expect = Code.expect; expect('x').to.satisfy(function (value) { return value === 'x'; }); ``` #### `throw([type], [message])` Aliases: `throws` Asserts that the function reference value throws an exception when called. The provided reference function is invoked within a `try`-`catch` block and any error throws is caught and compared to the provided optional requirements where: - `type` - the `instanceof` value of the thrown object. - `message` a string or regular expression matching the thrown error `message` property. Note that a string must provide a full match. ```js 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!'); ``` #### `await reject([type], [message])` Aliases: `rejects` Asserts that the `Promise` reference value rejects with an exception when called. The provided reference promise is resolved using an `await` statement within a `try`-`catch` block and any error throws is caught and compared to the provided optional requirements where: - `type` - the `instanceof` value of the rejected object. - `message` a string or regular expression matching the rejected error `message` property. Note that a string must provide a full match. Returns a promise resolving to the rejected error object. ```js const NodeUtil = require('util'); const Code = require('code'); const expect = Code.expect; const CustomError = function (message, code) { this.message = message; this.code = code; }; NodeUtil.inherits(CustomError, Error); const rejects = function () { return new Promise((resolve, reject) => reject(new CustomError('Oh no!', 123))); }; const err = await expect(rejects()).to.reject(CustomError, 'Oh no!'); expect(err.code).to.equal(123); ``` ### `fail(message)` Makes the test fail with `message`. ```js const Code = require('code'); Code.fail('This should not occur'); ``` ### `count()` Returns the total number of assertions created using the `expect()` method. ```js const Code = require('code'); const expect = Code.expect; expect(5).to.not.be.a.string(); console.log(Code.count()); // -> 1 ``` ### `incomplete()` Returns an array of the locations where incomplete assertions were declared or `null` if no incomplete assertions found. ```js const Code = require('code'); const expect = Code.expect; expect(5).to.not.be.a.string; console.log(Code.incomplete()); // -> [ 'readme.js:667:1' ] ``` ### `thrownAt([error])` Returns the filename, line number, and column number of where the `error` was created. If no error is provided, the current location returned. ```js const Code = require('code'); const error = new Error('oops'); Code.thrownAt(error); ``` ### Settings **code** can be configured using the module's `settings` object. The following settings are supported: #### `truncateMessages` A Boolean value that, when `true`, causes long assertion error messages to be truncated for readability. Setting this to `false` causes the entire message to be displayed. Defaults to `true`. ```js const Code = require('code'); const expect = Code.expect; const foo = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; Code.settings.truncateMessages = false; expect(foo).to.equal([]); ``` #### `comparePrototypes` A Boolean value that, when `false`, ignores object prototypes when doing a deep comparison. Defaults to `false`. ```js const Code = require('code'); const expect = Code.expect; const foo = Object.create(null); Code.settings.comparePrototypes = false; expect(foo).to.equal({}); Code.settings.comparePrototypes = true; expect(foo).to.equal({}); // fails ``` code-9.0.2/LICENSE.md000077500000000000000000000030151434134332700140460ustar00rootroot00000000000000Copyright (c) 2014-2022, Project contributors Copyright (c) 2014-2020, Sideway Inc Copyright (c) 2014, Walmart Copyright (c) 2011-2014 Jake Luer All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS OFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. code-9.0.2/README.md000077500000000000000000000017571434134332700137340ustar00rootroot00000000000000 # @hapi/code #### BDD assertion library. **code** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) – they work even better together. ### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support ## Useful resources - [Documentation and API](https://hapi.dev/family/code/) - [Versions status](https://hapi.dev/resources/status/#code) (builds, dependencies, node versions, licenses, eol) - [Changelog](https://hapi.dev/family/code/changelog/) - [Project policies](https://hapi.dev/policies/) - [Free and commercial support options](https://hapi.dev/support/) code-9.0.2/lib/000077500000000000000000000000001434134332700132065ustar00rootroot00000000000000code-9.0.2/lib/index.d.ts000077500000000000000000000463071434134332700151240ustar00rootroot00000000000000/// import * as Hoek from '@hapi/hoek'; // Internal helpers type Class = new (...args: any[]) => T; type UnpackArray = T extends (infer U)[] ? U : T; type RecursivePartial = T extends object ? { [P in keyof T]?: T[P] extends Array ? Array> : RecursivePartial; } : T; type Loosely = T extends object ? RecursivePartial & { [key: string]: any } : T; /** * Configure code behavior */ export const settings: Settings; export interface Settings { /** * Truncate long assertion error messages for readability. * * @default false */ truncateMessages?: boolean; /** * Ignore object prototypes when doing a deep comparison. * * @defaults false */ comparePrototypes?: boolean; } /** * Makes the test fail. * * @param message - the error message generated. */ export function fail(message?: string): void; /** * Returns the total number of assertions created using the `expect()` method. * * @returns total number of assertions. */ export function count(): number; /** * Returns an array of the locations where incomplete assertions were declared or `null` if no incomplete assertions found. * * @returns array of incomplete assertion locations. */ export function incomplete(): string[] | null; /** * Returns the filename, line number, and column number of where the `error` was created. If no error is provided, the current location returned. * * @param error - an error object. * * @returns the location where the error was thrown. */ export function thrownAt(error?: Error): thrownAt.Location; export namespace thrownAt { interface Location { filename: string; line: string; column: string; } } /** * Declares an assertion chain. * * @param value - the value being asserted. * @param prefix - a string prefix added to error messages. * * @returns Assertion object. */ export function expect(value: T, prefix?: string): expect.Assertion; declare namespace expect { type Assertion = TTest extends Function ? expect.FunctionAssertion : TTest extends string ? expect.StringAssertion : TTest extends number | bigint ? expect.NumberAssertion : TTest extends Promise ? expect.PromiseAssertion : expect.BaseAssertion; interface BaseAssertion { // Grammar a: this; an: this; and: this; at: this; be: this; have: this; in: this; to: this; // Flags /** * Inverses the expected result of the assertion chain. */ not: TTest extends Function ? expect.Not_FunctionAssertion : TTest extends Promise ? expect.Not_PromiseAssertion : this; /** * Requires that inclusion matches appear only once in the provided value. */ once: this; /** * Requires that only the provided elements appear in the provided value. */ only: this; /** * Allows a partial match when asserting inclusion instead of a full comparison. */ part: this; /** * Performs a comparison using strict equality (===) instead of a deep comparison. */ shallow: this; // Types /** * Asserts that the reference value is an arguments object. * * @returns assertion chain object. */ arguments(): Assertion; /** * Asserts that the reference value is an Array. * * @returns assertion chain object. */ array(): Assertion; /** * Asserts that the reference value is a boolean. * * @returns assertion chain object. */ boolean(): Assertion; /** * Asserts that the reference value is a Buffer. * * @returns assertion chain object. */ buffer(): Assertion; /** * Asserts that the reference value is a Date * * @returns assertion chain object. */ date(): Assertion; /** * Asserts that the reference value is an error. * * @param type - constructor function the error must be an instance of. * @param message - string or regular expression the error message must match. * * @returns assertion chain object. */ error(type: Class, message?: string | RegExp): Assertion; error(message?: string | RegExp): Assertion; /** * Asserts that the reference value is a function. * * @returns assertion chain object. */ function(): Assertion; /** * Asserts that the reference value is a number. * * @returns assertion chain object. */ number(): Assertion; /** * Asserts that the reference value is a RegExp. * * @returns assertion chain object. */ regexp(): Assertion; /** * Asserts that the reference value is a string. * * @returns assertion chain object. */ string(): Assertion; /** * Asserts that the reference value is an object (excluding array, buffer, or other native objects). * * @returns assertion chain object. */ object(): Assertion; // Values /** * Asserts that the reference value is true. * * @returns assertion chain object. */ true(): Assertion; /** * Asserts that the reference value is false. * * @returns assertion chain object. */ false(): Assertion; /** * Asserts that the reference value is null. * * @returns assertion chain object. */ null(): Assertion; /** * Asserts that the reference value is undefined. * * @returns assertion chain object. */ undefined(): Assertion; /** * Asserts that the reference value is `NaN`. * * @returns assertion chain object. */ NaN(): Assertion; // Tests /** * Asserts that the reference value (a string, array, or object) includes the provided values. * * @param values - the values to include. * * @returns assertion chain object. */ include(values: UnpackArray | Loosely[]>): Assertion; include(values: string | string[]): Assertion; /** * Asserts that the reference value (a string, array, or object) includes the provided values. * * @param values - the values to include. * * @returns assertion chain object. */ includes(values: UnpackArray | Loosely[]>): Assertion; includes(values: string | string[]): Assertion; /** * Asserts that the reference value (a string, array, or object) includes the provided values. * * @param values - the values to include. * * @returns assertion chain object. */ contain(values: UnpackArray | Loosely[]>): Assertion; contain(values: string | string[]): Assertion; /** * Asserts that the reference value (a string, array, or object) includes the provided values. * * @param values - the values to include. * * @returns assertion chain object. */ contains(values: UnpackArray | Loosely[]>): Assertion; contains(values: string | string[]): Assertion; /** * Asserts that the reference value exists (not null or undefined). * * @returns assertion chain object. */ exist(): Assertion; /** * Asserts that the reference value exists (not null or undefined). * * @returns assertion chain object. */ exists(): Assertion; /** * Asserts that the reference value has a length property equal to zero or is an object with no keys. * * @returns assertion chain object. */ empty(): Assertion; /** * Asserts that the reference value has a length property matching the provided size or an object with the specified number of keys. * * @param size - the required length. * * @returns assertion chain object. */ length(size: T extends string | Buffer | object | any[] ? number : never): Assertion; /** * Asserts that the reference value equals the provided value. * * @param value - the value to match. * @param options - comparison options. * * @returns assertion chain object. */ equal(value: RecursivePartial, options?: Hoek.deepEqual.Options): Assertion; /** * Asserts that the reference value equals the provided value. * * @param value - the value to match. * @param options - comparison options. * * @returns assertion chain object. */ equals(value: RecursivePartial, options?: Hoek.deepEqual.Options): Assertion; /** * Asserts that the reference value has the provided instanceof value. * * @param type - the constructor function to be an instance of. */ instanceof(type: Class): Assertion; /** * Asserts that the reference value has the provided instanceof value. * * @param type - the constructor function to be an instance of. */ instanceOf(type: Class): Assertion; /** * Asserts that the reference value's toString() representation matches the provided regular expression. * * @param regex - the pattern to match. * * @returns assertion chain object. */ match(regex: RegExp): Assertion; /** * Asserts that the reference value's toString() representation matches the provided regular expression. * * @param regex - the pattern to match. * * @returns assertion chain object. */ matches(regex: RegExp): Assertion; /** * Asserts that the reference value satisfies the provided validator function. * * @param validator * * @returns assertion chain object. */ satisfy(validator: (value: T) => boolean): Assertion; /** * Asserts that the reference value satisfies the provided validator function. * * @param validator * * @returns assertion chain object. */ satisfies(validator: (value: T) => boolean): Assertion; } interface FunctionAssertion extends BaseAssertion { /** * Asserts that the function reference value throws an exception when called. * * @param type - constructor function the error must be an instance of. * @param message - string or regular expression the error message must match. * * @returns thrown value. */ throw(type: Class, message?: string | RegExp): E; throw(message?: string | RegExp): E; /** * Asserts that the function reference value throws an exception when called. * * @param type - constructor function the error must be an instance of. * @param message - string or regular expression the error message must match. * * @returns thrown value. */ throws(type: Class, message?: string | RegExp): E; throws(message?: string | RegExp): E; } interface Not_FunctionAssertion extends BaseAssertion { /** * Asserts that the function reference value throws an exception when called. * * @returns assertion chain object. */ throw(): Assertion; throw(): Assertion; /** * Asserts that the function reference value throws an exception when called. * * @returns assertion chain object. */ throws(): Assertion; throws(): Assertion; } interface StringAssertion extends BaseAssertion { /** * Asserts that the reference value (a string) starts with the provided value. * * @param value - the value to start with. * * @returns assertion chain object. */ startWith(value: string): Assertion; /** * Asserts that the reference value (a string) starts with the provided value. * * @param value - the value to start with. * * @returns assertion chain object. */ startsWith(value: string): Assertion; /** * Asserts that the reference value (a string) ends with the provided value. * * @param value - the value to end with. * * @returns assertion chain object. */ endWith(value: string): Assertion; /** * Asserts that the reference value (a string) ends with the provided value. * * @param value - the value to end with. * * @returns assertion chain object. */ endsWith(value: string): Assertion; } interface NumberAssertion extends BaseAssertion { /** * Asserts that the reference value is greater than (>) the provided value. * * @param value - the value to compare to. * * @returns assertion chain object. */ above(value: T): Assertion; /** * Asserts that the reference value is within a delta difference from the provided value. * * @param value - the value to compare to. * @param delta - the delta +/- range value. * * @returns assertion chain object. */ about(value: T, delta: number): Assertion; /** * Asserts that the reference value is greater than (>) the provided value. * * @param value - the value to compare to. * * @returns assertion chain object. */ greaterThan(value: T): Assertion; /** * Asserts that the reference value is at least (>=) the provided value. * * @param value - the value to compare to. * * @returns assertion chain object. */ least(value: T): Assertion; /** * Asserts that the reference value is at least (>=) the provided value. * * @param value - the value to compare to. * * @returns assertion chain object. */ min(value: T): Assertion; /** * Asserts that the reference value is less than (<) the provided value. * * @param value - the value to compare to. * * @returns assertion chain object. */ below(value: T): Assertion; /** * Asserts that the reference value is less than (<) the provided value. * * @param value - the value to compare to. * * @returns assertion chain object. */ lessThan(value: T): Assertion; /** * Asserts that the reference value is at most (<=) the provided value. * * @param value - the value to compare to. * * @returns assertion chain object. */ most(value: T): Assertion; /** * Asserts that the reference value is at most (<=) the provided value. * * @param value - the value to compare to. * * @returns assertion chain object. */ max(value: T): Assertion; /** * Asserts that the reference value is within (from <= value <= to) the provided values. * * @param from - the value to be equal to or above. * @param to - the value to be equal to or below. * * @returns assertion chain object. */ within(from: T, to: T): Assertion; /** * Asserts that the reference value is within (from <= value <= to) the provided values. * * @param from - the value to be equal to or above. * @param to - the value to be equal to or below. * * @returns assertion chain object. */ range(from: T, to: T): Assertion; /** * Asserts that the reference value is between but not equal (from < value < to) the provided values. * * @param from - the value to be above. * @param to - the value to be below. * * @returns assertion chain object. */ between(from: T, to: T): Assertion; /** * Asserts that the reference value is about the provided value within a delta margin of difference. * * @param value - the value to be near. * @param delta - the max distance to be from the value. * * @returns assertion chain object. */ about(value: T extends number ? T : never, delta: T extends number ? T : never): Assertion; } interface PromiseAssertion extends BaseAssertion { /** * Asserts that the Promise reference value rejects with an exception when called. * * @param type - constructor function the error must be an instance of. * @param message - string or regular expression the error message must match. * * @returns a promise resolving to the rejected value. */ reject(type: Class, message?: string | RegExp): Promise; reject(message?: string | RegExp): Promise; /** * Asserts that the Promise reference value rejects with an exception when called. * * @param type - constructor function the error must be an instance of. * @param message - string or regular expression the error message must match. * * @returns a promise resolving to the rejected value. */ rejects(type: Class, message?: string | RegExp): Promise; rejects(message?: string | RegExp): Promise; } interface Not_PromiseAssertion extends BaseAssertion { /** * Asserts that the Promise reference value rejects with an exception when called. * * @returns a promise resolving to null. */ reject(): Promise; /** * Asserts that the Promise reference value rejects with an exception when called. * * @returns a promise resolving to null. */ rejects(): Promise; } } code-9.0.2/lib/index.js000077500000000000000000000346661434134332700146750ustar00rootroot00000000000000'use strict'; const Util = require('util'); const Hoek = require('@hapi/hoek'); const internals = { flags: ['not', 'once', 'only', 'part', 'shallow'], grammar: ['a', 'an', 'and', 'at', 'be', 'have', 'in', 'to'], locations: {}, count: 0 }; // Global settings exports.settings = { truncateMessages: false, comparePrototypes: false }; // Utilities exports.fail = function (message) { throw new Error(message); }; exports.count = function () { return internals.count; }; exports.incomplete = function () { const locations = Object.keys(internals.locations); return locations.length ? locations : null; }; internals.atNamedRx = /^\s*at (?:async )?[^(/]*\(?(.+)\:(\d+)\:(\d+)\)?$/; internals.atUnnamedRx = /^\s*at (?:async )?(.+)\:(\d+)\:(\d+)\)?$/; exports.thrownAt = function (error) { error = error ?? new Error(); const stack = typeof error.stack === 'string' ? error.stack : ''; const frame = stack.replace(error.toString(), '').split('\n').slice(1).filter(internals.filterLocal)[0] ?? ''; const at = frame.match(frame.includes('(') ? internals.atNamedRx : internals.atUnnamedRx); return Array.isArray(at) ? { filename: at[1], line: at[2], column: at[3] } : undefined; }; internals.filterLocal = function (line) { return line.indexOf(__dirname) === -1; }; // Expect interface exports.expect = function (value, prefix) { const at = exports.thrownAt(); const location = at.filename + ':' + at.line + '.' + at.column; internals.locations[location] = true; ++internals.count; return new internals.Assertion(value, prefix, location, at); }; internals.Assertion = function (ref, prefix, location, at) { this._ref = ref; this._prefix = prefix ?? ''; this._location = location; this._at = at; this._flags = {}; }; internals.Assertion.prototype.assert = function (result, verb, actual, expected) { delete internals.locations[this._location]; if (this._flags.not ? !result : result) { this._flags = {}; return this; } if (verb === 'exist' && this._flags.not && this._ref instanceof Error) { const original = this._ref; original.at = exports.thrownAt(); throw original; } let message = ''; if (this._prefix) { message += this._prefix + ': '; } message += 'Expected ' + internals.display(this._ref) + ' to '; if (this._flags.not) { message += 'not '; } message += verb; if (this._flags.once) { message += ' once'; } if (arguments.length === 3) { // 'actual' without 'expected' message += ' but got ' + internals.display(actual); } const error = new Error(message); Error.captureStackTrace(error, this.assert); error.actual = actual; error.expected = expected; error.at = exports.thrownAt(error) ?? this._at; throw error; }; internals.flags.forEach((word) => { Object.defineProperty(internals.Assertion.prototype, word, { get: function () { this._flags[word] = !this._flags[word]; return this; }, configurable: true }); }); internals.grammar.forEach((word) => { Object.defineProperty(internals.Assertion.prototype, word, { get: function () { return this; }, configurable: true }); }); internals.addMethod = function (names, fn) { const method = function (name) { internals.Assertion.prototype[name] = fn; }; names = [].concat(names); names.forEach(method); }; ['arguments', 'array', 'boolean', 'buffer', 'date', 'function', 'number', 'regexp', 'string', 'object'].forEach((word) => { const article = ['a', 'e', 'i', 'o', 'u'].indexOf(word[0]) !== -1 ? 'an ' : 'a '; const method = function () { const type = internals.type(this._ref); return this.assert(type === word, 'be ' + article + word, type); }; internals.addMethod(word, method); }); internals.addMethod('error', function (...args /* type, message */) { const type = args.length && typeof args[0] !== 'string' && !(args[0] instanceof RegExp) ? args[0] : Error; const lastArg = args[1] ?? args[0]; const message = typeof lastArg === 'string' || lastArg instanceof RegExp ? lastArg : null; const err = this._ref; if (!this._flags.not || message === null) { this.assert(err instanceof type, 'be an error with ' + (type.name || 'provided') + ' type'); } if (message !== null) { const error = err.message || ''; this.assert(typeof message === 'string' ? error === message : error.match(message), 'be an error with specified message', error, message); } }); [true, false, null, undefined].forEach((value) => { const name = Util.inspect(value); const method = function () { return this.assert(this._ref === value, 'be ' + name); }; internals.addMethod(name, method); }); internals.nan = function () { return this.assert(Number.isNaN(this._ref), 'be NaN'); }; internals.addMethod('NaN', internals.nan); internals.include = function (value) { internals.assert(this, arguments.length === 1, 'Can only assert include with a single parameter'); this._flags.deep = !this._flags.shallow; this._flags.part = this._flags.hasOwnProperty('part') ? this._flags.part : false; return this.assert(Hoek.contain(this._ref, value, this._flags), 'include ' + internals.display(value)); }; internals.addMethod(['include', 'includes', 'contain', 'contains'], internals.include); internals.endWith = function (value) { internals.assert(this, typeof this._ref === 'string' && typeof value === 'string', 'Can only assert endsWith on a string, with a string'); const comparator = this._ref.slice(-value.length); return this.assert(comparator === value, 'endWith ' + internals.display(value)); }; internals.addMethod(['endWith', 'endsWith'], internals.endWith); internals.startWith = function (value) { internals.assert(this, typeof this._ref === 'string' && typeof value === 'string', 'Can only assert startsWith on a string, with a string'); const comparator = this._ref.slice(0, value.length); return this.assert(comparator === value, 'startWith ' + internals.display(value)); }; internals.addMethod(['startWith', 'startsWith'], internals.startWith); internals.exist = function () { return this.assert(this._ref !== null && this._ref !== undefined, 'exist'); }; internals.addMethod(['exist', 'exists'], internals.exist); internals.empty = function () { internals.assert(this, typeof this._ref === 'object' || typeof this._ref === 'string', 'Can only assert empty on object, array or string'); const length = this._ref.length !== undefined ? this._ref.length : Object.keys(this._ref).length; return this.assert(!length, 'be empty'); }; internals.addMethod('empty', internals.empty); internals.length = function (size) { internals.assert(this, (typeof this._ref === 'object' && this._ref !== null) || typeof this._ref === 'string', 'Can only assert length on object, array or string'); const length = this._ref.length !== undefined ? this._ref.length : Object.keys(this._ref).length; return this.assert(length === size, 'have a length of ' + size, length); }; internals.addMethod('length', internals.length); internals.equal = function (value, options) { options = options ?? {}; const settings = Hoek.applyToDefaults({ prototype: exports.settings.comparePrototypes, deepFunction: true }, options); const compare = this._flags.shallow ? (a, b) => a === b : (a, b) => Hoek.deepEqual(a, b, settings); return this.assert(compare(this._ref, value), `equal specified value: ${internals.display(value)}`, this._ref, value); }; internals.addMethod(['equal', 'equals'], internals.equal); internals.above = function (value) { return this.assert(this._ref > value, 'be above ' + value); }; internals.addMethod(['above', 'greaterThan'], internals.above); internals.least = function (value) { return this.assert(this._ref >= value, 'be at least ' + value); }; internals.addMethod(['least', 'min'], internals.least); internals.below = function (value) { return this.assert(this._ref < value, 'be below ' + value); }; internals.addMethod(['below', 'lessThan'], internals.below); internals.most = function (value) { return this.assert(this._ref <= value, 'be at most ' + value); }; internals.addMethod(['most', 'max'], internals.most); internals.within = function (from, to) { return this.assert(this._ref >= from && this._ref <= to, 'be within ' + from + '..' + to); }; internals.addMethod(['within', 'range'], internals.within); internals.between = function (from, to) { return this.assert(this._ref > from && this._ref < to, 'be between ' + from + '..' + to); }; internals.addMethod('between', internals.between); internals.about = function (value, delta) { internals.assert(this, internals.type(this._ref) === 'number', 'Can only assert about on numbers'); internals.assert(this, internals.type(value) === 'number' && internals.type(delta) === 'number', 'About assertion requires two number arguments'); return this.assert(Math.abs(this._ref - value) <= delta, 'be about ' + value + ' \u00b1' + delta); }; internals.addMethod('about', internals.about); internals.instanceof = function (type) { return this.assert(this._ref instanceof type, 'be an instance of ' + (type.name || 'provided type')); }; internals.addMethod(['instanceof', 'instanceOf'], internals.instanceof); internals.match = function (regex) { return this.assert(regex.exec(this._ref), 'match ' + regex); }; internals.addMethod(['match', 'matches'], internals.match); internals.satisfy = function (validator) { return this.assert(validator(this._ref), 'satisfy rule'); }; internals.addMethod(['satisfy', 'satisfies'], internals.satisfy); internals.throw = function (...args /* type, message */) { internals.assert(this, typeof this._ref === 'function', 'Can only assert throw on functions'); internals.assert(this, !this._flags.not || !args.length, 'Cannot specify arguments when expecting not to throw'); const type = args.length && typeof args[0] !== 'string' && !(args[0] instanceof RegExp) ? args[0] : null; const lastArg = args[1] ?? args[0]; const message = typeof lastArg === 'string' || lastArg instanceof RegExp ? lastArg : null; let thrown = false; try { this._ref(); } catch (err) { thrown = true; if (type) { this.assert(err instanceof type, 'throw ' + (type.name || 'provided type')); } if (message !== null) { const error = err.message ?? ''; this.assert(typeof message === 'string' ? error === message : error.match(message), 'throw an error with specified message', error, message); } this.assert(thrown, 'throw an error', err); return err; } return this.assert(thrown, 'throw an error'); }; internals.addMethod(['throw', 'throws'], internals.throw); internals.reject = async function (...args/* type, message */) { try { internals.assert(this, internals.isPromise(this._ref), 'Can only assert reject on promises'); const type = args.length && typeof args[0] !== 'string' && !(args[0] instanceof RegExp) ? args[0] : null; const lastArg = args[1] ?? args[0]; const message = typeof lastArg === 'string' || lastArg instanceof RegExp ? lastArg : null; let thrown = null; try { await this._ref; } catch (err) { thrown = err; } internals.assert(this, !this._flags.not || !args.length, 'Cannot specify arguments when expecting not to reject'); if (thrown) { internals.assert(this, args.length < 2 || message, 'Can not assert with invalid message argument type'); internals.assert(this, args.length < 1 || message !== null || typeof type === 'function', 'Can not assert with invalid type argument'); if (type) { this.assert(thrown instanceof type, 'reject with ' + (type.name || 'provided type')); } if (message !== null) { const error = thrown.message ?? ''; this.assert(typeof message === 'string' ? error === message : error.match(message), 'reject with an error with specified message', error, message); } this.assert(thrown, 'reject with an error', thrown); } this.assert(thrown, 'reject with an error'); return thrown; } catch (err) { return new Promise((resolve, reject) => { reject(err); }); } }; internals.addMethod(['reject', 'rejects'], internals.reject); internals.isPromise = function (promise) { return typeof promise?.then === 'function'; }; internals.display = function (value) { const string = value instanceof Error ? `[${value.toString()}]` : internals.isPromise(value) ? '[Promise]' : typeof value === 'function' ? '[Function]' : Util.inspect(value); if (!exports.settings.truncateMessages || string.length <= 40) { return string; } if (Array.isArray(value)) { return '[Array(' + value.length + ')]'; } if (typeof value === 'object') { const keys = Object.keys(value); return '{ Object (' + (keys.length > 2 ? (keys.splice(0, 2).join(', ') + ', ...') : keys.join(', ')) + ') }'; } return string.slice(0, 40) + '...\''; }; internals.natives = { '[object Arguments]': 'arguments', '[object Array]': 'array', '[object AsyncFunction]': 'function', '[object Date]': 'date', '[object Function]': 'function', '[object Number]': 'number', '[object RegExp]': 'regexp', '[object String]': 'string' }; internals.type = function (value) { if (value === null) { return 'null'; } if (value === undefined) { return 'undefined'; } if (Buffer.isBuffer(value)) { return 'buffer'; } const name = Object.prototype.toString.call(value); if (internals.natives[name]) { return internals.natives[name]; } if (value === Object(value)) { return 'object'; } return typeof value; }; internals.assert = function (assertion, condition, error) { if (!condition) { delete internals.locations[assertion._location]; Hoek.assert(condition, error); } }; code-9.0.2/package.json000077500000000000000000000012631434134332700147330ustar00rootroot00000000000000{ "name": "@hapi/code", "description": "assertion library", "version": "9.0.2", "repository": "git://github.com/hapijs/code", "main": "lib/index.js", "types": "lib/index.d.ts", "keywords": [ "test", "expect", "assertion" ], "files": [ "lib" ], "eslintConfig": { "extends": [ "plugin:@hapi/module" ] }, "dependencies": { "@hapi/hoek": "10.x.x" }, "devDependencies": { "@hapi/eslint-plugin": "*", "@hapi/lab": "^25.0.1", "@types/node": "^17.0.25", "typescript": "~4.6.3" }, "scripts": { "test": "lab -t 100 -L -Y", "test-cov-html": "lab -L -r html -o coverage.html" }, "license": "BSD-3-Clause" } code-9.0.2/test/000077500000000000000000000000001434134332700134175ustar00rootroot00000000000000code-9.0.2/test/index.js000077500000000000000000002176511434134332700151030ustar00rootroot00000000000000'use strict'; const Util = require('util'); const Hoek = require('@hapi/hoek'); const Lab = require('@hapi/lab'); const Code = require('..'); const internals = {}; const { describe, it } = exports.lab = Lab.script(); describe('count()', () => { it('returns assertion count', () => { Code.expect(10).to.be.above(5); Code.expect('abc').to.be.a.string(); Hoek.assert(Code.count() === 2); }); }); describe('expect()', () => { it('validates assertion', () => { try { Code.expect('abcd').to.contain('a'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('uses grammar', () => { try { Code.expect(10).to.be.above(5); Code.expect('abc').to.be.a.string(); Code.expect([1, 2]).to.be.an.array(); Code.expect(20).to.be.at.least(20); Code.expect('abc').to.have.length(3); Code.expect('abc').to.be.a.string().and.contain(['a', 'b']); Code.expect(6).to.be.in.range(5, 6); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('asserts on invalid condition', () => { try { Code.expect('abcd').to.contain('e'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'abcd\' to include \'e\'', exception); }); it('asserts on invalid condition (not)', () => { try { Code.expect('abcd').to.not.contain('a'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'abcd\' to not include \'a\'', exception); }); it('asserts on invalid condition (once)', () => { try { Code.expect('abcad').to.once.contain('a'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'abcad\' to include \'a\' once', exception); }); it('asserts on invalid condition (with actual)', () => { try { Code.expect('abcd').to.have.length(3); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'abcd\' to have a length of 3 but got 4', exception); }); it('asserts on invalid condition (prefix)', () => { try { Code.expect('abcd', 'Oops').to.contain('e'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Oops: Expected \'abcd\' to include \'e\'', exception); }); it('asserts on invalid condition (large array, display truncated)', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = true; Code.expect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]).to.be.a.string(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; Hoek.assert(exception.message === 'Expected [Array(18)] to be a string but got \'array\'', exception); }); it('asserts on invalid condition (large array, display not truncated)', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = false; Code.expect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]).to.be.a.string(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; const message = exception.message.replace(/\n/g, '').replace(/ {2,}/g, ' ').replace(/8]/, '8 ]'); Hoek.assert(message === 'Expected [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 ] to be a string but got \'array\'', exception); }); it('asserts on invalid condition (large object, display truncated)', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = true; Code.expect({ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }).to.be.a.string(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; Hoek.assert(exception.message === 'Expected { Object (a, b, ...) } to be a string but got \'object\'', exception); }); it('asserts on invalid condition (large object, display not truncated)', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = false; Code.expect({ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }).to.be.a.string(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; Hoek.assert(exception.message === 'Expected { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 } to be a string but got \'object\'', exception); }); it('handles multi-line error message', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = false; Code.expect({ a: 1, b: '12345678901234567890123456789012345678901234567890' }).to.be.a.string(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; const message = exception.message.replace(/\n/g, '').replace(/ {2,}/g, ' '); Hoek.assert(message === `Expected { a: 1, b: '12345678901234567890123456789012345678901234567890' } to be a string but got 'object'`, exception); }); it('asserts on invalid condition (long object values, display truncated)', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = true; Code.expect({ a: 12345678901234567890, b: 12345678901234567890 }).to.be.a.string(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; Hoek.assert(exception.message === 'Expected { Object (a, b) } to be a string but got \'object\'', exception); }); it('asserts on invalid condition (long object values, display not truncated)', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = false; Code.expect({ a: 12345678901234567890, b: 12345678901234567890 }).to.be.a.string(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; Hoek.assert(exception.message === 'Expected { a: 12345678901234567000, b: 12345678901234567000 } to be a string but got \'object\'', exception); }); it('asserts on invalid condition (long string, display truncated)', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = true; Code.expect('{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }').to.be.a.number(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; Hoek.assert(exception.message === 'Expected \'{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g...\' to be a number but got \'string\'', exception); }); it('asserts on invalid condition (long string, display not truncated)', () => { const origTruncate = Code.settings.truncateMessages; try { Code.settings.truncateMessages = false; Code.expect('{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }').to.be.a.number(); } catch (err) { var exception = err; } Code.settings.truncateMessages = origTruncate; Hoek.assert(exception.message === 'Expected \'{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }\' to be a number but got \'string\'', exception); }); it('resets flags between chained assertions', () => { try { Code.expect('abc').to.contain('a').and.to.not.contain('d'); Code.expect('abc').to.not.contain('d').and.to.contain('a'); Code.expect('abc').to.not.contain('d').and.to.not.contain('e'); Code.expect('abc').to.contain('a').and.to.not.contain('d').and.to.contain('c').to.not.contain('f'); Code.expect(() => { }).to.not.throw().and.to.be.a.function(); Code.expect(10).to.not.be.about(8, 1).and.to.be.about(9, 1); Code.expect(10).to.be.about(9, 1).and.to.not.be.about(8, 1); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('uses the global prototype setting when doing deep compares on objects', () => { const origPrototype = Code.settings.comparePrototypes; Code.settings.comparePrototypes = false; try { const obj = Object.create(null); Code.expect({}).to.equal(obj); obj.foo = 'bar'; Code.expect({ foo: 'bar' }).to.equal(obj); Code.expect({ foo: 'bar' }).to.equal({ foo: 'bar' }); } catch (err) { var exception1 = err; } Code.settings.comparePrototypes = origPrototype; Hoek.assert(!exception1, exception1); Code.settings.comparePrototypes = true; try { const obj = Object.create(null); Code.expect({}).to.equal(obj); } catch (err) { var exception2 = err; } Code.settings.comparePrototypes = origPrototype; Hoek.assert(exception2.message === `Expected {} to equal specified value: ${Util.format(Object.create(null))}`, exception2); }); describe('assertion', () => { describe('argument()', () => { it('validates correct type', () => { const grab = function () { return arguments; // eslint-disable-line prefer-rest-params }; try { Code.expect(grab(1, 2, 3)).to.be.arguments(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect({ 1: 1, 2: 2, 3: 3, length: 3 }).to.be.arguments(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected { \'1\': 1, \'2\': 2, \'3\': 3, length: 3 } to be an arguments but got \'object\'', exception); }); }); describe('array()', () => { it('validates correct type', () => { try { Code.expect([1]).to.be.an.array(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect({ 1: 1 }).to.be.an.array(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected { \'1\': 1 } to be an array but got \'object\'', exception); }); }); describe('boolean()', () => { it('validates correct type', () => { try { Code.expect(true).to.be.a.boolean(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect(undefined).to.be.a.boolean(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected undefined to be a boolean but got \'undefined\'', exception); }); }); describe('buffer()', () => { it('validates correct type', () => { try { Code.expect(Buffer.from([1])).to.be.a.buffer(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect(null).to.be.a.buffer(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected null to be a buffer but got \'null\'', exception); }); }); describe('date()', () => { it('validates correct type', () => { try { Code.expect(new Date()).to.be.a.date(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect(true).to.be.a.date(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected true to be a date but got \'boolean\'', exception); }); }); describe('error()', () => { const error = new Error('kaboom'); it('validates assertion', () => { try { Code.expect(error).to.be.an.error(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (not error)', () => { const Custom = class extends Error { }; try { Code.expect(false).to.not.be.an.error(); Code.expect(new Error('kaboom')).to.not.be.an.error('baboom'); Code.expect(new Error('kaboom')).to.not.be.an.error(Error, 'baboom'); Code.expect(new Error()).to.not.be.an.error(Custom); Code.expect(new Error('kaboom')).to.not.be.an.error(Custom, 'baboom'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect(false).to.be.an.error(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected false to be an error with Error type', exception); }); it('validates assertion (message)', () => { try { Code.expect(error).to.be.an.error('kaboom'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (empty message)', () => { try { Code.expect(new Error('')).to.be.an.error(''); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (message regex)', () => { try { Code.expect(error).to.be.an.error(/boom/); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (missing message)', () => { const Custom = class extends Error { }; try { Code.expect(new Custom()).to.be.an.error('kaboom'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Error] to be an error with specified message', exception); }); it('invalidates assertion (empty message)', () => { try { Code.expect(new Error('kaboom')).to.be.an.error(''); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Error: kaboom] to be an error with specified message', exception); }); it('validates assertion (type)', () => { try { Code.expect(error).to.be.an.error(Error); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion (known type)', () => { const Custom = function () { }; try { Code.expect(new Custom()).to.be.an.error(Error); } catch (err) { var exception = err; } Hoek.assert(/Expected (Custom )?{} to be an error with Error type/.test(exception.message), exception); }); it('invalidates assertion (anonymous type)', () => { const Custom = class extends Error { static name = undefined; // Ensure that the type is anonymous }; try { Code.expect(error).to.be.an.error(Custom); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Error: kaboom] to be an error with provided type', exception); }); it('validates assertion (type and message)', () => { try { Code.expect(error).to.be.an.error(Error, 'kaboom'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); }); describe('function()', () => { it('validates correct type', () => { try { Code.expect(() => { }).to.be.a.function(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect(false).to.be.a.function(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected false to be a function but got \'boolean\'', exception); }); it('identifies async functions', () => { try { Code.expect(async () => { }).to.be.a.function(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); }); describe('number()', () => { it('validates correct type', () => { try { Code.expect(22).to.be.a.number(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect(() => { }).to.be.a.number(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Function] to be a number but got \'function\'', exception); }); }); describe('regexp()', () => { it('validates correct type', () => { try { Code.expect(/a/).to.be.a.regexp(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect(new Date()).to.be.a.regexp(); } catch (err) { var exception = err; } Hoek.assert(exception.message.match(/Expected .* to be a regexp but got 'date'/), exception); }); }); describe('string()', () => { it('validates correct type', () => { try { Code.expect('asd').to.be.a.string(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect(/a/).to.be.a.string(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected /a/ to be a string but got \'regexp\'', exception); }); }); describe('object()', () => { it('validates correct type', () => { try { Code.expect({}).to.be.a.object(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect(Buffer.from([20])).to.be.an.object(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected to be an object but got \'buffer\'', exception); }); }); describe('true()', () => { it('validates correct type', () => { try { Code.expect(true).to.be.true(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect('a').to.be.true(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'a\' to be true', exception); }); }); describe('false()', () => { it('validates correct type', () => { try { Code.expect(false).to.be.false(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect('a').to.be.false(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'a\' to be false', exception); }); }); describe('null()', () => { it('validates correct type', () => { try { Code.expect(null).to.be.null(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect('a').to.be.null(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'a\' to be null', exception); }); }); describe('undefined()', () => { it('validates correct type', () => { try { Code.expect(undefined).to.be.undefined(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates correct type (missing)', () => { try { Code.expect().to.be.undefined(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect('a').to.be.undefined(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'a\' to be undefined', exception); }); }); describe('NaN()', () => { it('validates correct type', () => { try { Code.expect(NaN).to.be.NaN(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { const fail = (value) => { try { Code.expect(value).to.be.NaN(); } catch (err) { var exception = err; } Hoek.assert(exception.message === `Expected ${Util.inspect(value)} to be NaN`, exception); }; fail(1); fail(0); fail(Infinity); fail(undefined); fail(null); fail(true); fail(false); fail(''); fail('foo'); fail({}); fail([]); }); }); describe('include()', () => { it('validates strings', () => { try { Code.expect('abc').to.include('ab'); Code.expect('abc').to.shallow.include('ab'); Code.expect('abc').to.only.include('abc'); Code.expect('abc').to.only.shallow.include('abc'); Code.expect('aaa').to.only.include('a'); Code.expect('aaa').to.only.shallow.include('a'); Code.expect('abc').to.once.include('b'); Code.expect('abc').to.once.shallow.include('b'); Code.expect('abc').to.include(['a', 'c']); Code.expect('abc').to.shallow.include(['a', 'c']); Code.expect('abc').to.part.include(['a', 'd']); Code.expect('abc').to.part.shallow.include(['a', 'd']); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates arrays', () => { try { Code.expect([1, 2, 3]).to.include(1); Code.expect([1, 2, 3]).to.shallow.include(1); Code.expect([{ a: 1 }]).to.include({ a: 1 }); Code.expect([1, 2, 3]).to.include([1, 2]); Code.expect([{ a: 1 }]).to.include([{ a: 1 }]); Code.expect([1, 1, 2]).to.only.include([1, 2]); Code.expect([1, 2]).to.once.include([1, 2]); Code.expect([1, 2, 3]).to.part.include([1, 4]); Code.expect([[1], [2]]).to.include([[1]]); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates array with only a partial object value', () => { try { Code.expect([{ a: 1, b: 1 }]).to.include({ a: 1 }); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [ { a: 1, b: 1 } ] to include { a: 1 }', exception); }); it('invalidates arrays (shallow)', () => { try { Code.expect([{ a: 1 }]).to.shallow.include({ a: 1 }); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [ { a: 1 } ] to include { a: 1 }', exception); }); it('validates objects', () => { try { Code.expect({ a: 1, b: 2, c: 3 }).to.include('a'); Code.expect({ a: 1, b: 2, c: 3 }).to.shallow.include('a'); Code.expect({ a: 1, b: 2, c: 3 }).to.include(['a', 'c']); Code.expect({ a: 1, b: 2, c: 3 }).to.only.include(['a', 'b', 'c']); Code.expect({ a: 1, b: 2, c: 3 }).to.include({ a: 1 }); Code.expect({ a: 1, b: 2, c: 3 }).to.include({ a: 1, c: 3 }); Code.expect({ a: 1, b: 2, c: 3 }).to.part.include({ a: 1, d: 4 }); Code.expect({ a: 1, b: 2, c: 3 }).to.only.include({ a: 1, b: 2, c: 3 }); Code.expect({ a: [1], b: [2], c: [3] }).to.include({ a: [1], c: [3] }); Code.expect({ a: 1, b: { c: 3, d: 4 } }).to.part.include({ b: { c: 3 } }); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates objects (shallow)', () => { try { Code.expect({ a: [1] }).to.shallow.include({ a: [1] }); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected { a: [ 1 ] } to include { a: [ 1 ] }', exception); }); it('validates aliases', () => { try { Code.expect('abc').to.includes('ab'); Code.expect('abc').to.only.contain('abc'); Code.expect('aaa').to.only.contains('a'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('asserts called with only one argument', () => { try { Code.expect('abc').to.include(); } catch (err) { var exception1 = err; } Hoek.assert(exception1.message === 'Can only assert include with a single parameter', exception1); try { Code.expect('abc').to.include('a', 'b'); } catch (err) { var exception2 = err; } Hoek.assert(exception2.message === 'Can only assert include with a single parameter', exception2); }); }); describe('endWith()', () => { it('validates strings', () => { try { Code.expect('http://xyz.abc/def').to.endWith('abc/def'); Code.expect('abcdefgh').not.to.endWith('abc'); Code.expect('foobar').not.to.endWith('not-long-enough'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('does not validate arrays', () => { try { Code.expect(['a', 'b', 'c']).to.endWith('abcdef'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Can only assert endsWith on a string, with a string', exception); }); it('does not validate using arrays', () => { try { Code.expect('abcdef').to.endWith(['a', 'b', 'c']); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Can only assert endsWith on a string, with a string', exception); }); }); describe('startWith()', () => { it('validates strings', () => { try { Code.expect('http://xyz.abc/def').to.startWith('http://'); Code.expect('eeeaaaeee').to.startWith('eee'); Code.expect('eeeaaaeee').not.to.startWith('aaa'); Code.expect('http://xyz.abc/def').not.to.startWith('https://'); Code.expect('abcdefgh').not.to.startWith('fgh'); Code.expect('foobar').not.to.startWith('not-long-enough'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('does not validate arrays', () => { try { Code.expect(['a', 'b', 'c']).to.startWith('abcdef'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Can only assert startsWith on a string, with a string', exception); }); it('does not validate using arrays', () => { try { Code.expect('abcdef').to.startWith(['a', 'b', 'c']); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Can only assert startsWith on a string, with a string', exception); }); }); describe('exist()', () => { it('validates assertion', () => { try { Code.expect('a').to.exist(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion (null)', () => { try { Code.expect(null).to.be.exist(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected null to exist', exception); }); it('invalidates assertion (undefined)', () => { try { Code.expect(undefined).to.be.exist(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected undefined to exist', exception); }); it('validates assertion (alias)', () => { try { Code.expect('a').exists(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (not error)', () => { const failed = new Error('some message'); // Create error on a different line than where the assertion is try { Code.expect(failed).to.not.exist(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'some message', exception); Hoek.assert(exception.at.line !== Code.thrownAt(failed).line, 'Reports the wrong line number'); Hoek.assert(exception.at.filename === __filename, `expected ${exception.at.filename} to equal ${__filename}`); }); it('validates assertion (error)', () => { try { Code.expect({}).to.not.exist(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected {} to not exist', exception); Hoek.assert(exception.actual === undefined, exception); Hoek.assert(exception.expected === undefined, exception); Hoek.assert(exception.at.filename === __filename, `expected ${exception.at.filename} to equal ${__filename}`); }); }); describe('empty()', () => { it('validates string', () => { try { Code.expect('').to.be.empty(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates buffer', () => { try { Code.expect(Buffer.from('')).to.be.empty(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates array', () => { try { Code.expect([]).to.be.empty(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates object', () => { try { Code.expect({}).to.be.empty(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect('a').to.be.empty(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'a\' to be empty', exception); }); }); describe('length()', () => { it('validates string', () => { try { Code.expect('a').to.have.length(1); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates buffer', () => { try { Code.expect(Buffer.from('a')).to.have.length(1); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates array', () => { try { Code.expect([1]).to.have.length(1); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates object', () => { try { Code.expect({ a: 10 }).to.have.length(1); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates incorrect type', () => { try { Code.expect('a').to.have.length(10); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'a\' to have a length of 10 but got 1', exception); }); it('throws on length check on objects with no length property', () => { try { Code.expect(null).to.have.length(2); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Can only assert length on object, array or string', exception); }); }); describe('equal()', () => { it('validates assertion', () => { try { Code.expect('abc').to.equal('abc'); Code.expect(['abc']).to.equal(['abc']); Code.expect({ a: 1 }).to.equal({ a: 1 }); Code.expect({}).to.not.equal({ a: 1 }); Code.expect({ a: 1 }).to.not.equal({}); Code.expect(Object.create(null)).to.not.equal({}, { prototype: true }); Code.expect(Object.create(null)).to.equal({}, { prototype: false }); Code.expect(Object.create(null)).to.equal({}); Code.expect({ a: 1, b: 2 }).to.equal({ a: 1, b: 3 }, { skip: ['b'] }); const f1 = () => { }; const f1a = () => { }; Code.expect({ f1 }).to.equal({ f1: f1a }); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect('abc').equals('abc'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect({ foo: 1 }).to.equal({ foo: 2 }); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected { foo: 1 } to equal specified value: { foo: 2 }', exception); }); it('validates assertion (shallow)', () => { try { const foo = { bar: 'baz' }; Code.expect('a').to.shallow.equal('a'); Code.expect(1).to.shallow.equal(1); Code.expect(foo).to.shallow.equal(foo); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion (shallow)', () => { try { Code.expect(['a']).to.shallow.equal(['a']); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [ \'a\' ] to equal specified value: [ \'a\' ]', exception); }); it('prints the specified value', () => { try { Code.expect('test').to.equal('junk'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'test\' to equal specified value: \'junk\'', exception); }); }); describe('above()', () => { it('validates assertion', () => { try { Code.expect(10).to.be.above(5); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect(1).to.be.greaterThan(0); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect(10).to.be.above(50); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected 10 to be above 50', exception); }); }); describe('least()', () => { it('validates assertion', () => { try { Code.expect(10).to.be.at.least(10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect(10).to.be.min(10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect(10).to.be.at.least(20); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected 10 to be at least 20', exception); }); }); describe('below()', () => { it('validates assertion', () => { try { Code.expect(1).to.be.below(10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect(1).to.be.lessThan(10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect(1).to.be.below(0); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected 1 to be below 0', exception); }); }); describe('most()', () => { it('validates assertion', () => { try { Code.expect(10).to.be.at.most(10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect(10).to.be.max(10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect(100).to.be.at.most(20); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected 100 to be at most 20', exception); }); }); describe('within()', () => { it('validates assertion', () => { try { Code.expect(5).to.be.within(0, 10); Code.expect(0).to.be.within(0, 10); Code.expect(10).to.be.within(0, 10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect(5).to.be.in.range(0, 10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion (over)', () => { try { Code.expect(5).to.be.within(0, 4); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected 5 to be within 0..4', exception); }); it('invalidates assertion (under)', () => { try { Code.expect(-1).to.be.within(0, 4); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected -1 to be within 0..4', exception); }); }); describe('between()', () => { it('validates assertion', () => { try { Code.expect(5).to.be.between(0, 10); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion (over)', () => { try { Code.expect(4).to.be.between(0, 4); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected 4 to be between 0..4', exception); }); it('invalidates assertion (under)', () => { try { Code.expect(0).to.be.between(0, 4); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected 0 to be between 0..4', exception); }); }); describe('about()', () => { it('validates assertion', () => { try { Code.expect(10).to.be.about(8, 2); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect(10).to.be.about(8, 1); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected 10 to be about 8 \u00b11', exception); }); it('invalidates assertion (invalid arguments)', () => { try { Code.expect(10).to.be.about('8', '1'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'About assertion requires two number arguments', exception); }); }); describe('instanceof()', () => { it('validates assertion', () => { try { Code.expect(new Date()).to.be.instanceof(Date); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect(new Date()).to.be.instanceOf(Date); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect([]).to.be.instanceof(RegExp); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [] to be an instance of RegExp', exception); }); it('invalidates assertion (anonymous)', () => { const Custom = function () { }; delete Custom.name; // Ensure that the type is anonymous try { Code.expect([]).to.be.instanceof(Custom); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [] to be an instance of provided type', exception); }); it('invalidates assertion (anonymous)', () => { function Custom() { } /* eslint func-style:0 */ try { Code.expect([]).to.be.instanceof(Custom); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [] to be an instance of Custom', exception); }); }); describe('match()', () => { it('validates assertion', () => { try { Code.expect('a4x').to.match(/\w\dx/); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect('a4x').matches(/\w\dx/); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect('a4x').to.match(/\w\dy/); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'a4x\' to match /\\w\\dy/', exception); }); }); describe('satisfy()', () => { const validate = function (value) { return value === 'some value'; }; it('validates assertion', () => { try { Code.expect('some value').to.satisfy(validate); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (alias)', () => { try { Code.expect('some value').satisfies(validate); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect('wrong').to.satisfy(validate); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected \'wrong\' to satisfy rule', exception); }); }); describe('throw()', () => { const throws = function () { throw Object.assign(new Error('kaboom'), { code: 123 }); }; it('validates assertion', () => { try { var thrown = Code.expect(throws).to.throw(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); Hoek.assert(thrown.code === 123, thrown); }); it('validates assertion (alias)', () => { try { Code.expect(throws).throws(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion', () => { try { Code.expect(() => { }).to.throw(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Function] to throw an error', exception); }); it('forbids arguments on negative assertion', () => { try { Code.expect(() => { }).to.not.throw('message'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Cannot specify arguments when expecting not to throw', exception); }); it('validates assertion (message)', () => { try { Code.expect(throws).to.throw('kaboom'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (empty message)', () => { try { Code.expect(() => { throw new Error(''); }).to.throw(''); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (message regex)', () => { try { Code.expect(throws).to.throw(/boom/); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates assertion (missing message)', () => { const Custom = function () { }; try { Code.expect(() => { throw new Custom(); }).to.throw('kaboom'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Function] to throw an error with specified message', exception); }); it('invalidates assertion (message)', () => { try { Code.expect(() => { }).to.throw('steve'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Function] to throw an error', exception); }); it('invalidates assertion (empty message)', () => { try { Code.expect(() => { throw new Error('kaboom'); }).to.throw(''); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Function] to throw an error with specified message', exception); }); it('validates assertion (type)', () => { try { Code.expect(throws).to.throw(Error); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates assertion (known type)', () => { const Custom = function () { }; try { Code.expect(() => { throw new Custom(); }).to.throw(Error); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Function] to throw Error', exception); }); it('invalidates assertion (anonymous type)', () => { const Custom = function () { }; delete Custom.name; // Ensure that the type is anonymous try { Code.expect(throws).to.throw(Custom); } catch (err) { var exception = err; } Hoek.assert(/Expected \[Function(: throws)?\] to throw provided type/.test(exception.message), exception); }); it('validates assertion (type and message)', () => { try { Code.expect(throws).to.throw(Error, 'kaboom'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); }); describe('reject()', () => { it('validates rejection', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).to.reject(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates resolution', async () => { try { await Code.expect(Promise.resolve(3)).to.not.reject(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates rejection', async () => { try { await Code.expect(Promise.resolve(3)).to.reject(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Promise] to reject with an error', exception); }); it('validates rejection (alias)', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).rejects(); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates rejection (not a promise)', async () => { try { await Code.expect(() => { }).to.reject(); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Can only assert reject on promises', exception); }); it('forbids arguments on negative rejection', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).to.not.reject('message'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Cannot specify arguments when expecting not to reject', exception); }); it('validates rejection (message)', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).to.reject('kaboom'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates rejection (empty message)', async () => { try { await Code.expect(Promise.reject(new Error(''))).to.reject(''); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates rejection (message regex)', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).to.reject(/boom/); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('validates rejection (missing message)', async () => { const Custom = function () { }; try { var expectedLineNumber = Number(new Error().stack.match(/:(\d+)/)[1]) + 1; await Code.expect(Promise.reject(new Custom())).to.reject('kaboom'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Promise] to reject with an error with specified message', exception); Hoek.assert(Number(exception.at.line) === expectedLineNumber, `expected ${expectedLineNumber}, got ${exception.at.line}`); Hoek.assert(exception.at.filename === __filename, `expected ${exception.at.filename} to equal ${__filename}`); }); it('invalidates rejection (message)', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).to.reject('steve'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Promise] to reject with an error with specified message', exception); }); it('invalidates rejection (empty message)', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).to.rejects(''); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Promise] to reject with an error with specified message', exception); }); it('validates rejection (type)', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).to.reject(Error); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('invalidates rejection (known type)', async () => { const Custom = function () { }; try { await Code.expect(Promise.reject(new Custom())).to.reject(Error); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Expected [Promise] to reject with Error', exception); }); it('invalidates rejection (anonymous type)', async () => { const Custom = function () { }; delete Custom.name; // Ensure that the type is anonymous try { await Code.expect(Promise.reject(new Error('kaboom'))).to.reject(Custom); } catch (err) { var exception = err; } Hoek.assert(/Expected \[Promise\] to reject with provided type/.test(exception.message), exception); }); it('invalidates rejection (invalid type)', async () => { const promise = Promise.reject(new Error('kaboom')); const fail = async (value) => { try { await Code.expect(promise).to.reject(value); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Can not assert with invalid type argument', exception); }; await fail(0); await fail(1); await fail(Infinity); await fail(undefined); await fail(null); await fail(true); await fail(false); await fail({}); await fail([]); await fail(NaN); }); it('invalidates rejection (invalid message type)', async () => { const promise = Promise.reject(new Error('kaboom')); const fail = async (value) => { try { await Code.expect(promise).to.reject(Error, value); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Can not assert with invalid message argument type', exception); }; await fail(1); await fail(0); await fail(Infinity); await fail(undefined); await fail(null); await fail(true); await fail(false); await fail({}); await fail([]); await fail(NaN); }); it('validates rejection (type and message)', async () => { try { await Code.expect(Promise.reject(new Error('kaboom'))).to.reject(Error, 'kaboom'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); it('returns rejection error', async () => { const Custom = function () { }; delete Custom.name; // Ensure that the type is anonymous try { const err = await Code.expect(Promise.reject(new Error('kaboom'))).to.reject(); Code.expect(err).to.be.an.error('kaboom'); } catch (err) { var exception = err; } Hoek.assert(!exception, exception); }); }); }); it('handles cases where thrownAt() cannot parse the error', () => { const captureStackTrace = Error.captureStackTrace; Error.captureStackTrace = (error) => { error.stack = 5; }; try { Code.expect(1).to.equal(2); } catch (err) { var exception = err; } finally { Error.captureStackTrace = captureStackTrace; } Hoek.assert(exception); Hoek.assert(exception.message === 'Expected 1 to equal specified value: 2', exception.message); Hoek.assert(exception.at.filename === __filename); Hoek.assert(exception.at.column === '18'); }); }); describe('fail', () => { it('trigger failure', () => { try { Code.fail('Something wrong happened!'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Something wrong happened!', exception); }); it('trigger failure only once', () => { try { Code.fail('Final Failure'); Code.fail('FAIL AGAIN'); } catch (err) { var exception = err; } Hoek.assert(exception.message === 'Final Failure', exception); }); }); describe('incomplete()', () => { it('keeps track of incomplete assertions', () => { const a = Code.expect(1).to; Code.expect(2).to.equal(2); Hoek.assert(Code.incomplete().length === 1); a.equal(1); Hoek.assert(!Code.incomplete()); }); }); describe('thrownAt()', () => { it('handles error with missing stack', () => { const failed = new Error('foo'); failed.stack = undefined; const at = Code.thrownAt(failed); Hoek.assert(at === undefined, 'Reports the wrong at information'); }); it('handles error with unnamed functions', () => { const test = (f) => f(); try { // eslint-disable-next-line prefer-arrow-callback test(function () { Code.expect(true).to.be.false(); }); Code.fail('an error should have been thrown'); } catch (ex) { const at = Code.thrownAt(ex); Hoek.assert(at.filename === __filename); } }); }); code-9.0.2/test/index.ts000077500000000000000000000141461434134332700151070ustar00rootroot00000000000000import * as Code from '..'; import * as Lab from '@hapi/lab'; const { expect } = Lab.types; // settings Code.settings.comparePrototypes = true; Code.settings.comparePrototypes = false; Code.settings.truncateMessages = true; Code.settings.truncateMessages = false; expect.type(Code.settings); expect.type(Code.settings.comparePrototypes); expect.type(Code.settings.truncateMessages); expect.error(Code.settings.x); expect.error(Code.settings.comparePrototypes = 1); // fail() Code.fail('something is wrong'); // $lab:types:skip$ Code.fail(); // $lab:types:skip$ expect.type(Code.fail('error')); // $lab:types:skip$ expect.error(Code.fail(123)); // count() Code.count(); expect.type(Code.count()); expect.error(Code.count(123)); // incomplete() Code.incomplete(); expect.type(Code.incomplete()); expect.error(Code.incomplete(123)); // thrownAt() Code.thrownAt(); Code.thrownAt(new Error()); const location = Code.thrownAt(new Error('oops')); expect.type(location); expect.type(location.column); expect.type(location.filename); expect.type(location.line); expect.error(Code.thrownAt('abc')); // expect() Code.expect(10).to.be.above(5); Code.expect('abc').to.be.a.string(); Code.expect([1, 2]).to.be.an.array(); Code.expect(20).to.be.at.least(20); Code.expect('abc').to.have.length(3); Code.expect('abc').to.be.a.string().and.contain(['a', 'b']); Code.expect(6).to.be.in.range(5, 6); Code.expect(10).to.not.be.above(20); Code.expect([1, 2, 3]).to.shallow.include(3); Code.expect([1, 1, 2]).to.only.include([1, 2]); Code.expect([1, 2]).to.once.include([1, 2]); Code.expect([1, 2, 3]).to.part.include([1, 4]); Code.expect(10, 'Age').to.be.above(5); const test = function () { return arguments; }; Code.expect(test()).to.be.arguments(); Code.expect([1, 2]).to.be.an.array(); Code.expect(true).to.be.a.boolean(); Code.expect(new Date()).to.be.a.date(); const err = new Error('Oops an error occurred.'); Code.expect(err).to.be.an.error(); Code.expect(err).to.be.an.error(Error); Code.expect(err).to.be.an.error('Oops an error occurred.'); Code.expect(err).to.be.an.error(Error, /occurred/); Code.expect(function () { }).to.be.a.function(); Code.expect(123).to.be.a.number(); Code.expect(/abc/).to.be.a.regexp(); Code.expect('abc').to.be.a.string(); Code.expect({ a: '1' }).to.be.an.object(); Code.expect(true).to.be.true(); Code.expect(false).to.be.false(); Code.expect(null).to.be.null(); Code.expect(undefined).to.be.undefined(); Code.expect(Number.NaN).to.be.NaN(); Code.expect('abc').to.include('ab'); Code.expect('abc').to.only.include('abc'); Code.expect('aaa').to.only.include('a'); Code.expect('abc').to.once.include('b'); Code.expect('abc').to.include(['a', 'c']); Code.expect('abc').to.part.include(['a', 'd']); Code.expect([1, 2, 3]).to.include(1); Code.expect([{ a: 1 }]).to.include({ a: 1 }); Code.expect([1, 2, 3]).to.include([1, 2]); Code.expect([{ a: 1 }]).to.include([{ a: 1 }]); Code.expect([1, 1, 2]).to.only.include([1, 2]); Code.expect([1, 2]).to.once.include([1, 2]); Code.expect([1, 2, 3]).to.part.include([1, 4]); Code.expect([[1], [2]]).to.include([[1]]); Code.expect({ a: 1, b: 2, c: 3 }).to.include('a'); Code.expect({ a: 1, b: 2, c: 3 }).to.include(['a', 'c']); Code.expect({ a: 1, b: 2, c: 3 }).to.only.include(['a', 'b', 'c']); Code.expect({ a: 1, b: 2, c: 3 }).to.only.include({ a: 1, b: 2, c: 3 }); Code.expect({ a: 1, b: 2, c: 3 }).to.include({ a: 1 }); Code.expect({ a: 1, b: 2, c: 3 }).to.part.include({ a: 1, d: 4 }); Code.expect({ a: [1], b: [2], c: [3] }).to.include({ a: [1], c: [3] }); Code.expect({ a: 1, b: { c: 3, d: 4 } }).to.part.include({ b: { c: 3 } }); interface TestType { a: number; b?: number; c?: number; d?: number; } interface TestType2 { a: number[]; b?: number[]; c: number[]; } Code.expect({ a: 1, b: 2, c: 3 }).to.include({ a: 1 }); Code.expect({ a: 1, b: 2, c: 3 }).to.include({ c: 3 }); Code.expect({ a: 1, b: 2, c: 3 }).to.include({ a: 1, c: 3 }); Code.expect({ a: 1, b: 2, c: 3 }).to.part.include({ a: 1, d: 4 }); Code.expect({ a: [1], b: [2], c: [3] }).to.include({ a: [1], c: [3] }); Code.expect('abc').to.startWith('ab'); Code.expect('abc').to.endWith('bc'); Code.expect(4).to.exist(); Code.expect(null).to.not.exist(); Code.expect('').to.be.empty(); Code.expect('abc').to.have.length(3); Code.expect(5).to.equal(5); Code.expect({ a: 1 }).to.equal({ a: 1 }); Code.expect([1, 2, 3]).to.equal([1, 2, 3]); Code.expect(Object.create(null)).to.equal({}, { prototype: false }); Code.expect(5).to.shallow.equal(5); Code.expect({ a: 1 }).to.not.shallow.equal({ a: 1 }); Code.expect(10).to.be.above(5); Code.expect(10).to.be.at.least(10); Code.expect(10).to.be.below(20); Code.expect(10).to.be.at.most(10); Code.expect(10).to.be.within(10, 20); Code.expect(20).to.be.within(10, 20); Code.expect(15).to.be.between(10, 20); Code.expect(10).to.be.about(9, 1); Code.expect(new Date()).to.be.an.instanceof(Date); Code.expect('a5').to.match(/\w\d/); Code.expect(['abc', 'def']).to.match(/^[\w\d,]*$/); Code.expect(1).to.match(/^\d$/); Code.expect('x').to.satisfy(value => value === 'x'); const type2 = { a: [1], c: [2] }; Code.expect(type2).to.equal({ a: [1] }, { skip: ['c'] }); const rejection = Promise.reject(new Error('Oh no!')); expect.type>(Code.expect(rejection).to.reject('Oh no!')); expect.type>(Code.expect(rejection).rejects('Oh no!')); class CustomError extends Error { } const throws = () => { throw new CustomError('Oh no!'); }; Code.expect(throws).to.throw(CustomError, 'Oh no!'); Code.expect(() => { }).to.not.throw().and.to.be.a.function(); const typedRejection = Promise.reject(new CustomError('Oh no!')); expect.type>(Code.expect(typedRejection).to.reject(CustomError, 'Oh no!')); expect.type>(Code.expect(typedRejection).rejects(CustomError, 'Oh no!')); expect.type>(Code.expect(Promise.resolve(true)).to.not.reject()); function foo(): number | undefined { return 123; } Code.expect(foo()).to.equal(123);