├── .eslintignore ├── test ├── .eslintrc.yml └── test.js ├── .eslintrc.yml ├── .gitignore ├── .github ├── dependabot.yml └── workflows │ ├── codeql.yml │ ├── scorecard.yml │ └── ci.yml ├── LICENSE ├── package.json ├── index.js ├── HISTORY.md └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | -------------------------------------------------------------------------------- /test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | mocha: true 3 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | root: true 2 | extends: 3 | - standard 4 | - plugin:markdown/recommended 5 | plugins: 6 | - markdown 7 | overrides: 8 | - files: '**/*.md' 9 | processor: 'markdown/markdown' 10 | rules: 11 | no-param-reassign: error 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store* 3 | Icon? 4 | ._* 5 | 6 | # Windows 7 | Thumbs.db 8 | ehthumbs.db 9 | Desktop.ini 10 | 11 | # Linux 12 | .directory 13 | *~ 14 | 15 | 16 | # npm 17 | node_modules 18 | package-lock.json 19 | *.log 20 | *.gz 21 | 22 | 23 | # Coveralls 24 | coverage 25 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: monthly 7 | 8 | - package-ecosystem: npm 9 | directory: / 10 | schedule: 11 | interval: monthly 12 | time: "23:00" 13 | timezone: Europe/London 14 | open-pull-requests-limit: 10 15 | ignore: 16 | - dependency-name: "*" 17 | update-types: ["version-update:semver-major"] 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2014 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "http-assert", 3 | "description": "assert with status codes", 4 | "version": "1.5.0", 5 | "license": "MIT", 6 | "keywords": [ 7 | "assert", 8 | "http" 9 | ], 10 | "repository": "jshttp/http-assert", 11 | "dependencies": { 12 | "deep-equal": "~1.0.1", 13 | "http-errors": "~1.8.0" 14 | }, 15 | "devDependencies": { 16 | "eslint": "7.32.0", 17 | "eslint-config-standard": "14.1.1", 18 | "eslint-plugin-import": "2.24.2", 19 | "eslint-plugin-markdown": "2.2.0", 20 | "eslint-plugin-node": "11.1.0", 21 | "eslint-plugin-promise": "4.3.1", 22 | "eslint-plugin-standard": "4.1.0", 23 | "mocha": "10.2.0", 24 | "nyc": "15.1.0" 25 | }, 26 | "files": [ 27 | "HISTORY.md", 28 | "LICENSE", 29 | "README.md", 30 | "index.js" 31 | ], 32 | "engines": { 33 | "node": ">= 0.8" 34 | }, 35 | "scripts": { 36 | "lint": "eslint --plugin markdown --ext js,md .", 37 | "test": "mocha --reporter spec --check-leaks test/", 38 | "test-ci": "nyc --reporter=lcov --reporter=text npm test", 39 | "test-cov": "nyc --reporter=html --reporter=text npm test" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var createError = require('http-errors') 2 | var eql = require('deep-equal') 3 | 4 | module.exports = assert 5 | 6 | function assert (value, status, msg, opts) { 7 | if (value) return 8 | throw createError(status, msg, opts) 9 | } 10 | 11 | assert.fail = function (status, msg, opts) { 12 | assert(false, status, msg, opts) 13 | } 14 | 15 | assert.equal = function (a, b, status, msg, opts) { 16 | assert(a == b, status, msg, opts) // eslint-disable-line eqeqeq 17 | } 18 | 19 | assert.notEqual = function (a, b, status, msg, opts) { 20 | assert(a != b, status, msg, opts) // eslint-disable-line eqeqeq 21 | } 22 | 23 | assert.ok = function (value, status, msg, opts) { 24 | assert(value, status, msg, opts) 25 | } 26 | 27 | assert.strictEqual = function (a, b, status, msg, opts) { 28 | assert(a === b, status, msg, opts) 29 | } 30 | 31 | assert.notStrictEqual = function (a, b, status, msg, opts) { 32 | assert(a !== b, status, msg, opts) 33 | } 34 | 35 | assert.deepEqual = function (a, b, status, msg, opts) { 36 | assert(eql(a, b), status, msg, opts) 37 | } 38 | 39 | assert.notDeepEqual = function (a, b, status, msg, opts) { 40 | assert(!eql(a, b), status, msg, opts) 41 | } 42 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | 1.5.0 / 2021-08-25 2 | ================== 3 | 4 | * Add `assert.fail()` 5 | * deps: http-errors@~1.8.0 6 | - deps: inherits@2.0.4 7 | - deps: setprototypeof@1.2.0 8 | 9 | 1.4.1 / 2019-04-28 10 | ================== 11 | 12 | * deps: http-errors@~1.7.2 13 | - deps: setprototypeof@1.1.1 14 | 15 | 1.4.0 / 2018-09-09 16 | ================== 17 | 18 | * Add `assert.ok()` 19 | * deps: http-errors@~1.7.1 20 | - Set constructor name when possible 21 | - deps: depd@~1.1.2 22 | - deps: setprototypeof@1.1.0 23 | - deps: statuses@'>= 1.5.0 < 2' 24 | 25 | 1.3.0 / 2017-05-07 26 | ================== 27 | 28 | * deps: deep-equal@~1.0.1 29 | - Fix `null == undefined` for non-strict compares 30 | * deps: http-errors@~1.6.1 31 | - Accept custom 4xx and 5xx status codes in factory 32 | - Deprecate using non-error status codes 33 | - Make `message` property enumerable for `HttpError`s 34 | - Support new code `421 Misdirected Request` 35 | - Use `setprototypeof` module to replace `__proto__` setting 36 | - deps: inherits@2.0.3 37 | - deps: setprototypeof@1.0.3 38 | - deps: statuses@'>= 1.3.1 < 2' 39 | - perf: enable strict mode 40 | 41 | 1.2.0 / 2016-02-27 42 | ================== 43 | 44 | * deps: http-errors@~1.4.0 45 | 46 | 1.1.1 / 2015-02-13 47 | ================== 48 | 49 | * deps: deep-equal@~1.0.0 50 | * dpes: http-errors@~1.3.1 51 | 52 | 1.1.0 / 2014-12-10 53 | ================== 54 | 55 | * Add equality methods 56 | - `assert.deepEqual()` 57 | - `assert.equal()` 58 | - `assert.notDeepEqual()` 59 | - `assert.notEqual()` 60 | - `assert.notStrictEqual()` 61 | - `assert.strictEqual()` 62 | 63 | 1.0.2 / 2014-09-10 64 | ================== 65 | 66 | * Fix setting `err.expose` on invalid status 67 | * Use `http-errors` module 68 | * perf: remove duplicate status check 69 | 70 | 1.0.1 / 2014-01-20 71 | ================== 72 | 73 | * Fix typo causing `err.message` to be `undefined` 74 | 75 | 1.0.0 / 2014-01-20 76 | ================== 77 | 78 | * Default status to 500 79 | * Set `err.expose` to `false` for 5xx codes 80 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: ["master"] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: ["master"] 20 | schedule: 21 | - cron: "0 0 * * 1" 22 | 23 | permissions: 24 | contents: read 25 | 26 | jobs: 27 | analyze: 28 | name: Analyze 29 | runs-on: ubuntu-latest 30 | permissions: 31 | actions: read 32 | contents: read 33 | security-events: write 34 | 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | language: ["javascript"] 39 | # CodeQL supports [ $supported-codeql-languages ] 40 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 41 | 42 | steps: 43 | - name: Checkout repository 44 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 45 | 46 | # Initializes the CodeQL tools for scanning. 47 | - name: Initialize CodeQL 48 | uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 49 | with: 50 | languages: ${{ matrix.language }} 51 | # If you wish to specify custom queries, you can do so here or in a config file. 52 | # By default, queries listed here will override any specified in a config file. 53 | # Prefix the list here with "+" to use these queries and those in the config file. 54 | 55 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 56 | # If this step fails, then you should remove it and run the build manually (see below) 57 | - name: Autobuild 58 | uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 59 | 60 | # ℹ️ Command-line programs to run using the OS shell. 61 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 62 | 63 | # If the Autobuild fails above, remove it and uncomment the following three lines. 64 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 65 | 66 | # - run: | 67 | # echo "Run, Build Application using script" 68 | # ./location_of_script_within_repo/buildscript.sh 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 72 | with: 73 | category: "/language:${{matrix.language}}" 74 | -------------------------------------------------------------------------------- /.github/workflows/scorecard.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. They are provided 2 | # by a third-party and are governed by separate terms of service, privacy 3 | # policy, and support documentation. 4 | 5 | name: Scorecard supply-chain security 6 | on: 7 | # For Branch-Protection check. Only the default branch is supported. See 8 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection 9 | branch_protection_rule: 10 | # To guarantee Maintained check is occasionally updated. See 11 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained 12 | schedule: 13 | - cron: '16 21 * * 1' 14 | push: 15 | branches: [ "master" ] 16 | 17 | # Declare default permissions as read only. 18 | permissions: read-all 19 | 20 | jobs: 21 | analysis: 22 | name: Scorecard analysis 23 | runs-on: ubuntu-latest 24 | permissions: 25 | # Needed to upload the results to code-scanning dashboard. 26 | security-events: write 27 | # Needed to publish results and get a badge (see publish_results below). 28 | id-token: write 29 | # Uncomment the permissions below if installing in a private repository. 30 | # contents: read 31 | # actions: read 32 | 33 | steps: 34 | - name: "Checkout code" 35 | uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 36 | with: 37 | persist-credentials: false 38 | 39 | - name: "Run analysis" 40 | uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # v2.0.6 41 | with: 42 | results_file: results.sarif 43 | results_format: sarif 44 | # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: 45 | # - you want to enable the Branch-Protection check on a *public* repository, or 46 | # - you are installing Scorecard on a *private* repository 47 | # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. 48 | # repo_token: ${{ secrets.SCORECARD_TOKEN }} 49 | 50 | # Public repositories: 51 | # - Publish results to OpenSSF REST API for easy access by consumers 52 | # - Allows the repository to include the Scorecard badge. 53 | # - See https://github.com/ossf/scorecard-action#publishing-results. 54 | # For private repositories: 55 | # - `publish_results` will always be set to `false`, regardless 56 | # of the value entered here. 57 | publish_results: true 58 | 59 | # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF 60 | # format to the repository Actions tab. 61 | - name: "Upload artifact" 62 | uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 63 | with: 64 | name: SARIF file 65 | path: results.sarif 66 | retention-days: 5 67 | 68 | # Upload the results to GitHub's code scanning dashboard. 69 | - name: "Upload to code-scanning" 70 | uses: github/codeql-action/upload-sarif@2f93e4319b2f04a2efc38fa7f78bd681bc3f7b2f # v2.23.2 71 | with: 72 | sarif_file: results.sarif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # http-assert 2 | 3 | [![NPM Version][npm-version-image]][npm-url] 4 | [![NPM Downloads][npm-downloads-image]][npm-url] 5 | [![Node.js Version][node-version-image]][node-version-url] 6 | [![Build Status][ci-image]][ci-url] 7 | [![Test Coverage][coveralls-image]][coveralls-url] 8 | 9 | Assert with status codes. Like ctx.throw() in Koa, but with a guard. 10 | 11 | ## Install 12 | 13 | This is a [Node.js](https://nodejs.org/en/) module available through the 14 | [npm registry](https://www.npmjs.com/). Installation is done using the 15 | [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): 16 | 17 | ```bash 18 | $ npm install http-assert 19 | ``` 20 | 21 | ## Example 22 | ```js 23 | var assert = require('http-assert') 24 | var ok = require('assert') 25 | 26 | var username = 'foobar' // username from request 27 | 28 | try { 29 | assert(username === 'fjodor', 401, 'authentication failed') 30 | } catch (err) { 31 | ok(err.status === 401) 32 | ok(err.message === 'authentication failed') 33 | ok(err.expose) 34 | } 35 | ``` 36 | 37 | ## API 38 | 39 | The API of this module is intended to be similar to the 40 | [Node.js `assert` module](https://nodejs.org/dist/latest/docs/api/assert.html). 41 | 42 | Each function will throw an instance of `HttpError` from 43 | [the `http-errors` module](https://www.npmjs.com/package/http-errors) 44 | when the assertion fails. 45 | 46 | ### assert(value, [status], [message], [properties]) 47 | 48 | Tests if `value` is truthy. If `value` is not truthy, an `HttpError` 49 | is thrown that is constructed with the given `status`, `message`, 50 | and `properties`. 51 | 52 | ### assert.deepEqual(a, b, [status], [message], [properties]) 53 | 54 | Tests for deep equality between `a` and `b`. Primitive values are 55 | compared with the Abstract Equality Comparison (`==`). If `a` and `b` 56 | are not equal, an `HttpError` is thrown that is constructed with the 57 | given `status`, `message`, and `properties`. 58 | 59 | ### assert.equal(a, b, [status], [message], [properties]) 60 | 61 | Tests shallow, coercive equality between `a` and `b` using the Abstract 62 | Equality Comparison (`==`). If `a` and `b` are not equal, an `HttpError` 63 | is thrown that is constructed with the given `status`, `message`, 64 | and `properties`. 65 | 66 | ### assert.fail([status], [message], [properties]) 67 | 68 | Always throws an `HttpError` that is constructed with the given `status`, 69 | `message`, and `properties`. 70 | 71 | ### assert.notDeepEqual(a, b, [status], [message], [properties]) 72 | 73 | Tests for deep equality between `a` and `b`. Primitive values are 74 | compared with the Abstract Equality Comparison (`==`). If `a` and `b` 75 | are equal, an `HttpError` is thrown that is constructed with the given 76 | `status`, `message`, and `properties`. 77 | 78 | ### assert.notEqual(a, b, [status], [message], [properties]) 79 | 80 | Tests shallow, coercive equality between `a` and `b` using the Abstract 81 | Equality Comparison (`==`). If `a` and `b` are equal, an `HttpError` is 82 | thrown that is constructed with the given `status`, `message`, and 83 | `properties`. 84 | 85 | ### assert.notStrictEqual(a, b, [status], [message], [properties]) 86 | 87 | Tests strict equality between `a` and `b` as determined by the SameValue 88 | Comparison (`===`). If `a` and `b` are equal, an `HttpError` is thrown 89 | that is constructed with the given `status`, `message`, and `properties`. 90 | 91 | ### assert.ok(value, [status], [message], [properties]) 92 | 93 | Tests if `value` is truthy. If `value` is not truthy, an `HttpError` 94 | is thrown that is constructed with the given `status`, `message`, 95 | and `properties`. 96 | 97 | ### assert.strictEqual(a, b, [status], [message], [properties]) 98 | 99 | Tests strict equality between `a` and `b` as determined by the SameValue 100 | Comparison (`===`). If `a` and `b` are not equal, an `HttpError` 101 | is thrown that is constructed with the given `status`, `message`, 102 | and `properties`. 103 | 104 | ## Licence 105 | 106 | [MIT](LICENSE) 107 | 108 | [ci-image]: https://badgen.net/github/checks/jshttp/http-assert/master?label=ci 109 | [ci-url]: https://github.com/jshttp/http-assert/actions?query=workflow%3Aci 110 | [coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/http-assert/master 111 | [coveralls-url]: https://coveralls.io/r/jshttp/http-assert?branch=master 112 | [node-version-image]: https://badgen.net/npm/node/http-assert 113 | [node-version-url]: https://nodejs.org/en/download 114 | [npm-downloads-image]: https://badgen.net/npm/dm/http-assert 115 | [npm-url]: https://npmjs.org/package/http-assert 116 | [npm-version-image]: https://badgen.net/npm/v/http-assert 117 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var assert = require('..') 2 | var ok = require('assert') 3 | 4 | describe('assert()', function () { 5 | it('should throw when guard is falsy', function () { 6 | var err 7 | 8 | try { 9 | assert(false, 401, 'fail') 10 | } catch (e) { 11 | err = e 12 | } 13 | 14 | ok(err) 15 | ok(err.status === 401) 16 | ok(err.message === 'fail') 17 | ok(err.expose) 18 | }) 19 | 20 | it('should not throw when guard is truthy', function () { 21 | assert(true, 401, 'fail') 22 | }) 23 | 24 | it('should accept options for the error object', function () { 25 | var err 26 | 27 | try { 28 | assert(false, 401, 'fail', { expose: false }) 29 | } catch (e) { 30 | err = e 31 | } 32 | 33 | ok(err) 34 | ok(err.status === 401) 35 | ok(err.message === 'fail') 36 | ok(!err.expose) 37 | }) 38 | 39 | it('should not expose 5xx errors', function () { 40 | var err 41 | 42 | try { 43 | assert(false, 500) 44 | } catch (e) { 45 | err = e 46 | } 47 | 48 | ok(err) 49 | ok(err.status === 500) 50 | ok(err.message === 'Internal Server Error') 51 | ok(!err.expose) 52 | }) 53 | 54 | it('should default to status code 500', function () { 55 | var err 56 | 57 | try { 58 | assert(false, 'fail') 59 | } catch (e) { 60 | err = e 61 | } 62 | 63 | ok(err) 64 | ok(err.status === 500) 65 | ok(err.message === 'fail') 66 | ok(!err.expose) 67 | }) 68 | }) 69 | 70 | describe('assert.equal()', function () { 71 | it('should throw when things aren\'t equal', function () { 72 | var err 73 | try { 74 | assert.equal('a', 'b', 401, 'fail') 75 | } catch (e) { 76 | err = e 77 | } 78 | 79 | ok(err) 80 | ok(err.status === 401) 81 | ok(err.message === 'fail') 82 | }) 83 | 84 | it('should not throw when things are equal', function () { 85 | assert.equal(1, '1', 401, 'fail') 86 | }) 87 | }) 88 | 89 | describe('assert.notEqual()', function () { 90 | it('should throw when things are equal', function () { 91 | var err 92 | try { 93 | assert.notEqual('a', 'a', 401, 'fail') 94 | } catch (e) { 95 | err = e 96 | } 97 | 98 | ok(err) 99 | ok(err.status === 401) 100 | ok(err.message === 'fail') 101 | }) 102 | 103 | it('should not throw when things aren\'t equal', function () { 104 | assert.notEqual(1, 11, 401, 'fail') 105 | }) 106 | }) 107 | 108 | describe('assert.ok()', function () { 109 | it('should throw when value is falsy', function () { 110 | var err 111 | try { 112 | assert.ok(false, 401, 'fail') 113 | } catch (e) { 114 | err = e 115 | } 116 | 117 | ok(err) 118 | ok(err.status === 401) 119 | ok(err.message === 'fail') 120 | }) 121 | 122 | it('should not throw when value is truthy', function () { 123 | assert.ok(true, 401, 'fail') 124 | }) 125 | }) 126 | 127 | describe('assert.strictEqual()', function () { 128 | it('should throw when things aren\'t equal', function () { 129 | var err 130 | try { 131 | assert.strictEqual(1, '1', 401, 'fail') 132 | } catch (e) { 133 | err = e 134 | } 135 | 136 | ok(err) 137 | ok(err.status === 401) 138 | ok(err.message === 'fail') 139 | }) 140 | 141 | it('should not throw when things are equal', function () { 142 | assert.strictEqual(1, 1, 401, 'fail') 143 | }) 144 | }) 145 | 146 | describe('assert.notStrictEqual()', function () { 147 | it('should throw when things are equal', function () { 148 | var err 149 | try { 150 | assert.notStrictEqual(1, 1, 401, 'fail') 151 | } catch (e) { 152 | err = e 153 | } 154 | 155 | ok(err) 156 | ok(err.status === 401) 157 | ok(err.message === 'fail') 158 | }) 159 | 160 | it('should not throw when things aren\'t equal', function () { 161 | assert.notStrictEqual(1, '1', 401, 'fail') 162 | }) 163 | }) 164 | 165 | describe('assert.deepEqual()', function () { 166 | it('should throw when things aren\'t deeply equal', function () { 167 | var err 168 | try { 169 | assert.deepEqual({ a: 'a' }, { b: 'b' }, 401, 'fail') 170 | } catch (e) { 171 | err = e 172 | } 173 | 174 | ok(err) 175 | ok(err.status === 401) 176 | ok(err.message === 'fail') 177 | }) 178 | 179 | it('should not throw when things are deeply equal', function () { 180 | assert.deepEqual({ a: 'a' }, { a: 'a' }, 401, 'fail') 181 | }) 182 | }) 183 | 184 | describe('assert.notDeepEqual()', function () { 185 | it('should throw when things aren\'t deeply equal', function () { 186 | var err 187 | try { 188 | assert.notDeepEqual({ a: 'a' }, { a: 'a' }, 401, 'fail') 189 | } catch (e) { 190 | err = e 191 | } 192 | 193 | ok(err) 194 | ok(err.status === 401) 195 | ok(err.message === 'fail') 196 | }) 197 | 198 | it('should not throw when things are deeply equal', function () { 199 | assert.notDeepEqual({ a: 'a' }, { b: 'b' }, 401, 'fail') 200 | }) 201 | }) 202 | 203 | describe('assert.fail()', function () { 204 | it('should always throw', function () { 205 | var err 206 | try { 207 | assert.fail(401, 'fail') 208 | } catch (e) { 209 | err = e 210 | } 211 | 212 | ok(err) 213 | ok(err.status === 401) 214 | ok(err.message === 'fail') 215 | }) 216 | }) 217 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | - pull_request 5 | - push 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | test: 12 | permissions: 13 | checks: write # for coverallsapp/github-action to create new checks 14 | contents: read # for actions/checkout to fetch code 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | name: 19 | - Node.js 0.8 20 | - Node.js 0.10 21 | - Node.js 0.12 22 | - io.js 1.x 23 | - io.js 2.x 24 | - io.js 3.x 25 | - Node.js 4.x 26 | - Node.js 5.x 27 | - Node.js 6.x 28 | - Node.js 7.x 29 | - Node.js 8.x 30 | - Node.js 9.x 31 | - Node.js 10.x 32 | - Node.js 11.x 33 | - Node.js 12.x 34 | - Node.js 13.x 35 | - Node.js 14.x 36 | - Node.js 15.x 37 | - Node.js 16.x 38 | - Node.js 17.x 39 | - Node.js 18.x 40 | - Node.js 19.x 41 | - Node.js 20.x 42 | - Node.js 21.x 43 | - Node.js 22.x 44 | 45 | include: 46 | - name: Node.js 0.8 47 | node-version: "0.8" 48 | npm-i: mocha@2.5.3 49 | npm-rm: nyc 50 | 51 | - name: Node.js 0.10 52 | node-version: "0.10" 53 | npm-i: mocha@3.5.3 nyc@10.3.2 54 | 55 | - name: Node.js 0.12 56 | node-version: "0.12" 57 | npm-i: mocha@3.5.3 nyc@10.3.2 58 | 59 | - name: io.js 1.x 60 | node-version: "1.8" 61 | npm-i: mocha@3.5.3 nyc@10.3.2 62 | 63 | - name: io.js 2.x 64 | node-version: "2.5" 65 | npm-i: mocha@3.5.3 nyc@10.3.2 66 | 67 | - name: io.js 3.x 68 | node-version: "3.3" 69 | npm-i: mocha@3.5.3 nyc@10.3.2 70 | 71 | - name: Node.js 4.x 72 | node-version: "4.9" 73 | npm-i: mocha@5.2.0 nyc@11.9.0 74 | 75 | - name: Node.js 5.x 76 | node-version: "5.12" 77 | npm-i: mocha@5.2.0 nyc@11.9.0 78 | 79 | - name: Node.js 6.x 80 | node-version: "6.17" 81 | npm-i: mocha@6.2.2 nyc@14.1.1 82 | 83 | - name: Node.js 7.x 84 | node-version: "7.10" 85 | npm-i: mocha@6.2.2 nyc@14.1.1 86 | 87 | - name: Node.js 8.x 88 | node-version: "8.17" 89 | npm-i: mocha@7.1.2 nyc@14.1.1 90 | 91 | - name: Node.js 9.x 92 | node-version: "9.11" 93 | npm-i: mocha@7.1.2 nyc@14.1.1 94 | 95 | - name: Node.js 10.x 96 | node-version: "10.24" 97 | npm-i: mocha@8.4.0 98 | 99 | - name: Node.js 11.x 100 | node-version: "11.15" 101 | npm-i: mocha@8.4.0 102 | 103 | - name: Node.js 12.x 104 | node-version: "12.22" 105 | npm-i: mocha@9.2.2 106 | 107 | - name: Node.js 13.x 108 | node-version: "13.14" 109 | npm-i: mocha@9.2.2 110 | 111 | - name: Node.js 14.x 112 | node-version: "14.21" 113 | 114 | - name: Node.js 15.x 115 | node-version: "15.14" 116 | 117 | - name: Node.js 16.x 118 | node-version: "16.20" 119 | 120 | - name: Node.js 17.x 121 | node-version: "17.9" 122 | 123 | - name: Node.js 18.x 124 | node-version: "18.20" 125 | 126 | - name: Node.js 19.x 127 | node-version: "19.9" 128 | 129 | - name: Node.js 20.x 130 | node-version: "20.13" 131 | 132 | - name: Node.js 21.x 133 | node-version: "21.7" 134 | 135 | - name: Node.js 22.x 136 | node-version: "22.1" 137 | 138 | steps: 139 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 140 | 141 | - name: Install Node.js ${{ matrix.node-version }} 142 | shell: bash -eo pipefail -l {0} 143 | run: | 144 | nvm install --default ${{ matrix.node-version }} 145 | if [[ "${{ matrix.node-version }}" == 0.* && "$(cut -d. -f2 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then 146 | nvm install --alias=npm 0.10 147 | nvm use ${{ matrix.node-version }} 148 | if [[ "$(npm -v)" == 1.1.* ]]; then 149 | nvm exec npm npm install -g npm@1.1 150 | ln -fs "$(which npm)" "$(dirname "$(nvm which npm)")/npm" 151 | else 152 | sed -i '1s;^.*$;'"$(printf '#!%q' "$(nvm which npm)")"';' "$(readlink -f "$(which npm)")" 153 | fi 154 | npm config set strict-ssl false 155 | fi 156 | dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" 157 | 158 | - name: Configure npm 159 | run: | 160 | if [[ "$(npm config get package-lock)" == "true" ]]; then 161 | npm config set package-lock false 162 | else 163 | npm config set shrinkwrap false 164 | fi 165 | 166 | - name: Remove npm module(s) ${{ matrix.npm-rm }} 167 | run: npm rm --silent --save-dev ${{ matrix.npm-rm }} 168 | if: matrix.npm-rm != '' 169 | 170 | - name: Install npm module(s) ${{ matrix.npm-i }} 171 | run: npm install --save-dev ${{ matrix.npm-i }} 172 | if: matrix.npm-i != '' 173 | 174 | - name: Setup Node.js version-specific dependencies 175 | shell: bash 176 | run: | 177 | # eslint for linting 178 | # - remove on Node.js < 12 179 | if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then 180 | node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ 181 | grep -E '^eslint(-|$)' | \ 182 | sort -r | \ 183 | xargs -n1 npm rm --silent --save-dev 184 | fi 185 | 186 | - name: Install Node.js dependencies 187 | run: npm install 188 | 189 | - name: List environment 190 | id: list_env 191 | shell: bash 192 | run: | 193 | echo "node@$(node -v)" 194 | echo "npm@$(npm -v)" 195 | npm -s ls ||: 196 | (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT" 197 | 198 | - name: Run tests 199 | shell: bash 200 | run: | 201 | if npm -ps ls nyc | grep -q nyc; then 202 | npm run test-ci 203 | else 204 | npm test 205 | fi 206 | 207 | - name: Lint code 208 | if: steps.list_env.outputs.eslint != '' 209 | run: npm run lint 210 | 211 | - name: Collect code coverage 212 | uses: coverallsapp/github-action@09b709cf6a16e30b0808ba050c7a6e8a5ef13f8d # master 213 | if: steps.list_env.outputs.nyc != '' 214 | with: 215 | github-token: ${{ secrets.GITHUB_TOKEN }} 216 | flag-name: run-${{ matrix.test_number }} 217 | parallel: true 218 | 219 | coverage: 220 | permissions: 221 | checks: write # for coverallsapp/github-action to create new checks 222 | needs: test 223 | runs-on: ubuntu-latest 224 | steps: 225 | - name: Upload code coverage 226 | uses: coverallsapp/github-action@09b709cf6a16e30b0808ba050c7a6e8a5ef13f8d # master 227 | with: 228 | github-token: ${{ secrets.GITHUB_TOKEN }} 229 | parallel-finished: true 230 | --------------------------------------------------------------------------------