{"id":21297504,"url":"https://github.com/fvdm/nodejs-dotest","last_synced_at":"2025-07-11T18:32:32.948Z","repository":{"id":5885853,"uuid":"54168181","full_name":"fvdm/nodejs-dotest","owner":"fvdm","description":"Yet another unit test runner for Node.js","archived":false,"fork":false,"pushed_at":"2025-03-28T23:29:51.000Z","size":484,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-04-06T07:09:52.402Z","etag":null,"topics":["debugger","nodejs","unit-testing","unlicense"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/dotest","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fvdm.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"ko_fi":"franklin"}},"created_at":"2016-03-18T02:43:54.000Z","updated_at":"2025-03-28T23:27:48.000Z","dependencies_parsed_at":"2024-05-20T23:27:04.284Z","dependency_job_id":"0f7ad0d7-527d-486e-aa7a-5fb9f65c4186","html_url":"https://github.com/fvdm/nodejs-dotest","commit_stats":{"total_commits":525,"total_committers":8,"mean_commits":65.625,"dds":0.06285714285714283,"last_synced_commit":"f3196b2876984c410c3920ff468866b0a3a82f44"},"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"purl":"pkg:github/fvdm/nodejs-dotest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fvdm%2Fnodejs-dotest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fvdm%2Fnodejs-dotest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fvdm%2Fnodejs-dotest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fvdm%2Fnodejs-dotest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fvdm","download_url":"https://codeload.github.com/fvdm/nodejs-dotest/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fvdm%2Fnodejs-dotest/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264870618,"owners_count":23676277,"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":["debugger","nodejs","unit-testing","unlicense"],"created_at":"2024-11-21T14:37:50.913Z","updated_at":"2025-07-11T18:32:32.654Z","avatar_url":"https://github.com/fvdm.png","language":"JavaScript","funding_links":["https://ko-fi.com/franklin"],"categories":[],"sub_categories":[],"readme":"# dotest\n\nOne dev dependency for your [Node.js](https://nodejs.org) package to run ESLint,\nyour test.js, coverage and report to Coveralls.io when running in a CI environment.\n\n[![npm](https://img.shields.io/npm/v/dotest.svg?maxAge=3600)](https://www.npmjs.com/package/dotest?activeTab=versions)\n[![Build Status](https://github.com/fvdm/nodejs-dotest/actions/workflows/node.js.yml/badge.svg?branch=master)](https://github.com/fvdm/nodejs-dotest/actions/workflows/node.js.yml)\n[![Coverage Status](https://coveralls.io/repos/github/fvdm/nodejs-dotest/badge.svg?branch=master)](https://coveralls.io/github/fvdm/nodejs-dotest?branch=master)\n\n* It runs ESLint with your package's `eslint.config.mjs` file\n* Then it runs your `test.js` with `nyc` to generate a coverage report\n* When it detects the code is running in a CI it will also submit the coverage report to [Coveralls.io](https://coveralls.io)\n* In case it runs in a Github action the warning, fail and error lines are highlighted\n\n\n## Example\n\n**test.js**\n\n```js\n// Load test runner and your app\nconst doTest = require( 'dotest' );\nconst app = require( './' );\n\n// Check app interface\ndoTest.add( 'App interface', test =\u003e {\n  test()\n    .isFunction( 'fail', 'methodOne', app.methodOne )\n    .isObject( 'fail', 'sub', app.sub )\n    .isFunction( 'fail', 'sub.methodTwo', app.sub.methodTwo )\n    .done()\n  ;\n} );\n\n// Check method response\ndoTest.add( 'App methodOne', test =\u003e {\n  app.methodOne( ( err, data ) =\u003e {\n    test( err )\n      .isObject( 'fail', 'Callback data', data )\n      .isArray( 'fail', 'data.music', data.music )\n      .isNotEmpty( 'warn', 'data.music', data.music )\n      .done()\n    ;\n  } );\n} );\n\n// Check promise\ndoTest.add( 'Promise good', async test =\u003e {\n  let error;\n  let data;\n\n  try {\n    data = await myPromise();\n  }\n  catch ( err ) {\n    error = err;\n  }\n\n  test( error )\n    .isObject( 'fail', 'data', data );\n    .done()\n  ;\n} );\n\n// Run the tests\ndoTest.run();\n```\n\n**package.json**\n\nFull test including ESLint, test.js, coverage report and Coveralls.io submit.\n\n```json\n\"scripts\": {\n  \"test\": \"dotest\"\n}\n```\n\nOr just run your `test.js`\n\n```json\n\"scripts\": {\n  \"test\": \"node test.js\"\n}\n```\n\n\nJust run `npm test`\n\n\n## Installation\n\nThis is usually intended for CI builds,\nso best to make sure it's in your `devDependencies`\n\n```sh\nnpm i dotest --save-dev\n```\n\n\n## Configuration\n\nThe script takes these env variables. They override the code settings.\n\n\nname                   | default          | description\n:----------------------|:-----------------|:-----------\n[DOTEST_WAIT]          | 0                | Pause N ms between tests\n[DOTEST_NOCOV]         |                  | Set to 'true' to skip coverage report\n[DOTEST_MINCOV]        | 85               | Minimum coverage % default\n[DOTEST_COVBRANCHES]   | `$DOTEST_MINCOV` | Minimum coverage % for branches\n[DOTEST_COVLINES]      | `$DOTEST_MINCOV` | Minimum coverage % for lines\n[DOTEST_COVFUNCTIONS]  | `$DOTEST_MINCOV` | Minimum coverage % for functions\n[DOTEST_COVSTATEMENTS] | `$DOTEST_MINCOV` | Minimum coverage % for statements\n\n\n## Methods\n\n### add\n**( label, testFunction )**\n\nAdd a new test to the queue.\n\n\n```js\ndoTest.add( 'App interface', test =\u003e {\n  test()\n    .isArray( 'fail', 'my array', [] )\n    .done()\n  ;\n} );\n```\n\n\n### run\n**( [wait] )**\n\nRun the tests from the queue, one by one.\n\n\nparam  | type   | default | description\n:------|:-------|:--------|:-----------\n[wait] | number | 0       | Wait N ms between tests\n\n\n```js\n// Normal, without pause between tests\ndoTest.run();\n\n// Or wait 2 seconds\ndoTest.run( 2000 );\n```\n\n\n### log\n**( [type], str, [dontCount] )**\n\nFancy `console.log` with style.\n\n\nparam       | type    | default | description\n:-----------|:--------|:--------|:-----------\n[type]      | string  | plain   | Text style to apply, see below\nstr         | string  |         | The string to output\n[dontCount] | boolean | false   | Don't count a fail or error towards the exit status\n\n\nstyle | description\n:-----|:-----------\nfail  | `FAIL    Text` with _FAIL_ in red\ngood  | `good    Text` with _good_ in green\nwarn  | `warn    Text` with _warn_ in yellow\ninfo  | `info    Text` with _info_ in cyan\nnote  | `Text` with _Text_ in bold\nerror | `ERROR   Error.message\\nError\\nError.stack` with _ERROR_ in red\nplain | No styling\n\n\nThe styles `error`, `fail` and `warn` add to the _errors_ and _warnings_ counters,\nwhere `error` and `fail` also cause the script to fail.\n\n\n```js\n// Bold text\ndoTest.log( 'note', 'Hello world' );\n```\n\n\n### exit\n**( )**\n\nForce exit the process, after writing statistics to the console.\n\n```js\ndoTest.exit();\n```\n\n\n### test\n**( [err] )**\n\nReturns check functions.\nOptionally test for `err` instance of `Error` and dump it to the console.\n\nThe check functions take a `level` parameter.\nWhen set to `fail` the check reports _fail_ and the whole test script will eventually fail.\nWhen set to `warn` the check reports _warn_ but won't cause the script to fail.\n\nYou can concat the check functions for clean code.\n\n\n```js\n// Using the method\ndoTest.add( 'App interface', () =\u003e {\n  doTest.test()\n    .isObject( 'fail', 'Callback data', data )\n    .done()\n  ;\n} );\n\n// Or using the shortcut\ndoTest.add( 'App interface', test =\u003e {\n  test()\n    .isObject( 'fail', 'Callback data', data )\n    .done()\n  ;\n} );\n```\n\n\n### test() .done\n**( [callback] )**\n\nRun the next test from the queue.\nOptionally run a `callback` function before the next test.\n\nSee example above.\n\n\n### test() .exit\n**( )**\n\nAlias to [dotest.exit()](#exit).\nWorks similar to `.done()` where it ends the test,\nbut `.exit()` also ends the whole script.\n\n```js\ntest()\n  .isArray( 'fail', 'data', [] )\n  .exit()\n;\n```\n\n\n### test() .info\n**( message )**\n\nOutput 'info' log line.\n\nThe `message` can be of any type.\nWhen it is not a string, the type is written instead\nand the full value of `message` dumped right below.\n\n```js\ntest()\n  .info( { hello: 'world' } )\n  .done()\n;\n\n// Output:\n// info    Object\n// { hello: 'world' }\n```\n\n\n### test() .good\n**( message )**\n\nOutput 'good' log line.\n\nThe `message` can be of any type.\nWhen it is not a string, the type is written instead\nand the full value of `message` dumped right below.\n\n```js\ntest()\n  .good( 'It works great' )\n  .done()\n;\n\n// Output:\n// good    It works great\n```\n\n\n### test() .warn\n**( message )**\n\nOutput 'warn' log line.\n\nThe `message` can be of any type.\nWhen it is not a string, the type is written instead\nand the full value of `message` dumped right below.\n\n```js\ntest()\n  .warn( 'Hmm something odd happened' )\n  .done()\n;\n\n// Output:\n// warn    Hmm something odd happend\n```\n\n\n### test() .fail\n**( message, [dontCount] )**\n\nOutput 'FAIL' log line.\n\nThe `message` can be of any type.\nWhen it is not a string, the type is written instead\nand the full value of `message` dumped right below.\n\n```js\ntest()\n  .fail( 'We have a problem' )\n  .done()\n;\n\n// Output:\n// FAIL    We have a problem\n```\n\n\n### test() .error\n**( err, [dontCount] )**\n\nOutput 'ERROR' log line with dump and stack trace.\n\n```js\nconst err = new Error( 'Oops' );\n\ntest()\n  .error( err )\n  .done()\n;\n\n// Output:\n// ERROR   Oops\n//\n// [Error: Oops]\n// ...\n```\n\n\n### test() .isError\n**( level, what, input )**\n\nCheck if `input` is an instance of _Error_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isError( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isObject\n**( level, what, input )**\n\nCheck if `input` is an instance of _Object_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isObject( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isArray\n**( level, what, input )**\n\nCheck if `input` is an instance of _Array_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isArray( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isString\n**( level, what, input )**\n\nCheck if `input` is a _string_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isString( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isNumber\n**( level, what, input )**\n\nCheck if `input` is a _number_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isNumber( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isUndefined\n**( level, what, input )**\n\nCheck if `input` is _undefined_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\nfunction ( err, data ) {\n  test()\n    .isUndefined( 'warn', 'My data', data )\n    .done()\n  ;\n}\n```\n\n\n### test() .isNull\n**( level, what, input )**\n\nCheck if `input` is _null_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\nfunction ( err, data ) {\n  test()\n    .isNull( 'warn', 'My data', data )\n    .done()\n  ;\n}\n```\n\n\n### test() .isNaN\n**( level, what, input )**\n\nCheck if `input` is _NaN_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\nfunction ( err, data ) {\n  test()\n    .isNaN( 'warn', 'My data', data )\n    .done()\n  ;\n}\n```\n\n\n### test() .isBoolean\n**( level, what, input )**\n\nCheck if `input` is a _boolean_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isBoolean( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isFunction\n**( level, what, input )**\n\nCheck if `input` is an instance of _Function_ or _AsyncFunction_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isFunction( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isNormalFunction\n**( level, what, input )**\n\nCheck if `input` is an instance of _Function_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isFunction( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isAsyncFunction\n**( level, what, input )**\n\nCheck if `input` is an instance of _AsyncFunction_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\ntest()\n  .isAsyncFunction( 'fail', 'My data', data )\n  .done()\n;\n```\n\n\n### test() .isDate\n**( level, what, input )**\n\nCheck if `input` is an instance of _Date_.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\nconst myDate = new Date();\n\ntest()\n  .isDate( 'fail', 'My data', myDate )\n  .done()\n;\n```\n\n\n### test() .isExactly\n**( level, what, one, two )**\n\nCheck if `one` is exactly of the same type and value as `two`.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\none   | mixed  | The variable to check\ntwo   | mixed  | The variable to check against\n\n\n```js\ntest()\n  .isExactly( 'fail', 'My data', 'foo', 'bar' )\n  .done()\n;\n```\n\n\n### test() .isCondition\n**( level, what, one, operator, two )**\n\nCheck if the two values meet the condition.\n\n\nparam    | type   | description\n:--------|:-------|:-----------\nlevel    | string | Either `fail` or `warn`\nwhat     | string | Text to prepend to check result\none      | mixed  | Variable to test against\noperator | string | `\u003c`, `\u003e`, `\u003c=`, `\u003e=`\ntwo      | mixed  | Variable to test against\n\n\n```js\ntest()\n  .isCondition( 'fail', 'My data', 1, '\u003c', 2 )\n  .done()\n;\n```\n\n\n### test() .isEmpty\n**( level, what, input )**\n\nCheck if `input` is _undefined_, _null_, or an empty _string_, _object_, _array_ or _Error_.\nIn case of _Error_ the `input.message` and `Object.keys( input )` are checked.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\n// Object is empty\ntest()\n  .isEmpty( 'fail', 'My data', {} )\n  .done()\n;\n```\n\n\n### test() .isNotEmpty\n**( level, what, input )**\n\nCheck if `input` is not _undefined_, _null_, or an empty _string_, _object_, _array_ or _Error_.\nIn case of _Error_ the `input.message` and `Object.keys( input )` are checked.\n\n\nparam | type   | description\n:-----|:-------|:-----------\nlevel | string | Either `fail` or `warn`\nwhat  | string | Text to prepend to check result\ninput | mixed  | The variable to check\n\n\n```js\n// Object is not empty\ntest()\n  .isNotEmpty( 'fail', 'My data', { foo: 'bar' } )\n  .done()\n;\n```\n\n\n## Unlicense\n\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to \u003chttps://unlicense.org\u003e\n\n\n## Author\n\n[Franklin](https://fvdm.com)\n| [Buy me a coffee](https://fvdm.com/donating)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffvdm%2Fnodejs-dotest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffvdm%2Fnodejs-dotest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffvdm%2Fnodejs-dotest/lists"}