{"id":21446192,"url":"https://github.com/spazmodius/assert","last_synced_at":"2026-05-19T00:36:47.658Z","repository":{"id":143019009,"uuid":"145573734","full_name":"spazmodius/assert","owner":"spazmodius","description":"Node assertions that no-op in production","archived":false,"fork":false,"pushed_at":"2019-08-09T18:13:18.000Z","size":20,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-23T11:23:43.633Z","etag":null,"topics":["module","node"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spazmodius.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-21T14:15:07.000Z","updated_at":"2020-08-10T15:34:36.000Z","dependencies_parsed_at":"2023-06-13T13:00:41.421Z","dependency_job_id":null,"html_url":"https://github.com/spazmodius/assert","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spazmodius%2Fassert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spazmodius%2Fassert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spazmodius%2Fassert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spazmodius%2Fassert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spazmodius","download_url":"https://codeload.github.com/spazmodius/assert/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243955933,"owners_count":20374407,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["module","node"],"created_at":"2024-11-23T02:42:19.389Z","updated_at":"2026-05-19T00:36:47.613Z","avatar_url":"https://github.com/spazmodius.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spaz's Debug-only Asserts\r\n\r\nLiberal use of assertions in your code is an important way to self-document assumptions and expected conditions.  \r\nBut, of course, they cost cycles.\r\n\r\nThis module lets you use assertions like they're free, because, in production, they are!\r\n\r\nAll calls in this module become no-ops when the environment defines either:\r\n\r\n - `NODE_ENV=production`\r\n - `NO_ASSERT=1` (any truthy value)\r\n\r\n## Installation and Usage\r\n```\r\nnpm install spazmodius/assert\r\n```\r\n\r\n```js\r\nconst assert = require('@spazmodius/assert')\r\nassert(count \u003c MAX_COUNT, 'count is too large')\r\n```\r\n\r\n## Compatible With Node's Assert API\r\n\r\nThis module exposes a subset of the [Node.js Assert API](https://nodejs.org/api/assert.html), using [strict mode](https://nodejs.org/api/assert.html#assert_strict_mode) \r\ncomparison.\r\n\r\n### assert(_value, [message]_)\r\n\r\nAlias for `assert.ok()`\r\n\r\n### assert.ok(_value, [message]_)\r\n### assert.fail(_[message]_)\r\n### assert.equal(_actual, expected, [message]_)\r\n### assert.notEqual(_actual, expected, [message]_)\r\n### assert.deepEqual(_actual, expected, [message]_)\r\n### assert.notDeepEqual(_actual, expected, [message]_)\r\n### assert.throws(_fn, [error], [message]_)\r\n### assert.doesNotThrow(_fn, [error], [message]_)\r\n\r\nFor example:\r\n```js\r\nassert.ok(count \u003c MAX_COUNT, 'count is too large')\r\nassert.fail('should never get here')\r\nassert.equal(remaining, 0, 'still some remaining')\r\nassert.notEqual(name, '', 'name is missing')\r\nassert.deepEqual(origin, {x:0, y:0}, 'origin is misaligned')\r\nassert.notDeepEqual(options, {}, 'no options given')\r\nassert.throws(() =\u003e { throw new Error('wat??') }, /wat/)\r\nassert.doesNotThrow(() =\u003e JSON.parse(json), SyntaxError, 'invalid JSON')\r\n```\r\n\r\n## Custom Assertions\r\n\r\nThe available assertions can be extended by registering **custom assertions**.\r\n\r\n### assert.register(_[name], predicate, [defaultMessage]_)\r\n\r\nArgument | Type | Optional | Description\r\n---|---|---|---\r\n`name` | string | \u0026check; | Name of the new assertion. Defaults to name of `predicate` function\r\n`predicate` | function | | Function that evaluates its arguments, and returns a falsy value on failure\r\n`defaultMessage` | string or function | \u0026check; | Message to use when this assertion fails and the caller did not supply a message\r\n\r\n**Returns** `assert` (to allow chaining)\r\n\r\nCustom logic is coded in the `predicate` function.  This function must take a fixed number of arguments, none of which are considered optional (it's `.length` is used internally). It returns a falsy value if the assertion fails.\r\n\r\nThe `defaultMessage` argument provides the default message to use if this assertion fails.\r\nIf it is a function, it will be called with the same arguments passed to `predicate`,\r\nand it should return a string or `undefined`.\r\nOmitting this argument, or returning `undefined`, will use an auto-generated message, which is usually pretty good.\r\n\r\nRegistration results in a custom assertion **assert._name_()**, which takes the same parameters as `predicate`, plus an optional `message` parameter.\r\nCustom assertions automatically benefit from **[No-op Actual Evaluation](#no-op-actual-evaluation)** and **[Informational Arguments](#informational-arguments)**.\r\n\r\n#### Simple registration:\r\n```js\r\nfunction startsWith(actual, prefix) { \r\n\treturn actual.indexOf(prefix) === 0 \r\n}\r\nassert.register(startsWith)\r\n\r\nassert.startsWith('abcd', 'xyz')\r\n// Throws [AssertionError [ERR_ASSERTION]: 'abcd' startsWith 'xyz']\r\n```\r\n\r\n#### Full-control registration:\r\n```js\r\nassert.register('lt', (x, y) =\u003e x \u003c y, (x, y) =\u003e `${x} should be less than ${y}` )\r\n\r\nassert.lt(99, 5)\r\n// Throws [AssertionError [ERR_ASSERTION]: 99 should be less than 5]\r\n```\r\n\r\n## No-op Actual Evaluation\r\n\r\nEven when assertions are no-op'd, there might still be a cost for evalulating arguments.\r\n\r\nConsider the example: \r\n```js\r\nassert(count \u003c MAX_COUNT, 'count is too large')\r\n```\r\n\r\nEven if `assert()` is a no-op, the expression `count \u003c MAX_COUNT` is evaluated unnecessarily.\r\nEven more expensive is this next line of code, which always allocates a closure, even when it won't be called:\r\n```js\r\nassert.doesNotThrow(() =\u003e JSON.parse(json), SyntaxError, 'invalid JSON')\r\n```\r\n\r\nTo handle such situations cleanly, this module implements an extension to defer calculation of the `actual` argument; this will no-op in production.\r\n\r\n### assert.that(_fn, [args...]_).ok(_[message]_)\r\n### assert.that(_fn, [args...]_).equal(_expected, [message]_)\r\n### assert.that(_fn, [args...]_).notEqual(_expected, [message]_)\r\n### assert.that(_fn, [args...]_).deepEqual(_expected, [message]_)\r\n### assert.that(_fn, [args...]_).notDeepEqual(_expected, [message]_)\r\n### assert.that(_fn, [args...]_).throws(_expected, [error], [message]_)\r\n### assert.that(_fn, [args...]_).doesNotThrow(_expected, [error], [message]_)\r\n\r\nFunction `fn` is called with arguments `args`, and the result is passed as the `actual` argument to the corresponding assertion.\r\nIn the case of `.throws()` and `.doesNotThrow()`,\r\na lambda that calls the function `fn` with arguments `args` is passed.\r\n\r\nFor example:\r\n```js\r\nconst isValid = n =\u003e n \u003c MAX_COUNT\r\nassert.that(isValid, count).ok('count is too large')\r\n\r\nassert.that(JSON.parse, json).doesNotThrow(SyntaxError, 'invalid JSON')\r\n```\r\n\r\n## Informational Arguments\r\n\r\nFor simplicity, all the assertions above are shown ending with a `message` parameter.\r\nHowever, every assertion can take additional **informational arguments** after the `message`.\r\nWhen the assertion fails, \r\nthese values will be represented in the error message,\r\nand included in the error object, as the `info` property (an array).\r\n\r\nWhen passing informational arguments, the normally optional `message` argument must be specified (but can be `undefined`).\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspazmodius%2Fassert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspazmodius%2Fassert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspazmodius%2Fassert/lists"}