{"id":13624496,"url":"https://github.com/vesln/nixt","last_synced_at":"2025-04-04T21:07:14.093Z","repository":{"id":11449888,"uuid":"13909919","full_name":"vesln/nixt","owner":"vesln","description":"Simple and elegant end-to-end testing for command-line apps","archived":false,"fork":false,"pushed_at":"2019-03-05T10:36:56.000Z","size":112,"stargazers_count":311,"open_issues_count":3,"forks_count":18,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-28T01:56:37.985Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vesln.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-10-27T20:40:15.000Z","updated_at":"2025-03-25T22:52:43.000Z","dependencies_parsed_at":"2022-09-23T21:30:59.879Z","dependency_job_id":null,"html_url":"https://github.com/vesln/nixt","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vesln%2Fnixt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vesln%2Fnixt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vesln%2Fnixt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vesln%2Fnixt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vesln","download_url":"https://codeload.github.com/vesln/nixt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247249524,"owners_count":20908212,"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":[],"created_at":"2024-08-01T21:01:43.183Z","updated_at":"2025-04-04T21:07:14.062Z","avatar_url":"https://github.com/vesln.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"[![NPM version](https://badge.fury.io/js/nixt.svg)](http://badge.fury.io/js/nixt)\n[![Build Status](https://secure.travis-ci.org/vesln/nixt.svg)](http://travis-ci.org/vesln/nixt)\n\n![Nixt](http://i.imgur.com/aBudpSE.jpg)\n\n## Synopsis\n\nSimple and powerful end-to-end testing for command-line apps.\n\n## Description\n\nNixt is aiming to make testing of command-line apps as simple as possible. It\nplays nice with the testing tools that you are already using and in case you are\none of those devs who practice outside-in BDD, it has the potential to become\nsomething that lives in every command-line app that you are going to build.\n\n### How it looks\n\n```js\nvar nixt = require('nixt');\n\nnixt()\n.exec('touch /tmp/test')\n.run('ls /tmp/')\n.stdout(/test/)\n.end();\n```\n\n### Formatting options\n\nNixt can strip newlines and colors. You can tell it to do so by passing an\nobject that looks like this:\n\n```js\nvar options = {\n  colors: false,\n  newlines: false,\n};\n\nnixt(options).stdout...\n```\n\n### Custom expectations\n\nWhile Nixt comes with built-in expectations, you can use your own too.\n\n```js\nnixt()\n.expect(function(result) {\n  if (result.stdout !== 'unicorns') {\n    return new Error('NO!');\n  }\n})\n.run('unicorns')\n.end(fn);\n```\n\n### Custom middlewares\n\nYou can register as many before and after middlewares as you wish.\n\n```js\nnixt()\n.before(setupDatabase)\n.before(runMigrations)\n.run(cmd)\n.after(downgradeCron)\n.after(deleteDatabase)\n.end();\n```\n\n### Middleware order\n\nThe Middleware execution order is very simple - \"before\" middlewares always run\nbefore everything else, \"after\" middlewares always run after everything else.\nThe other middlewares will match the order that you have specified.\n\n```js\nnixt()\n.before(before1)\n.before(before2)\n.after(after1)\n.after(after2)\n.writeFile(file, '')\n.run(cmd)\n.unlink(file)\n.end(fn)\n\n// Execution order:\n// before1, before2, writeFile, cmd, unlink, after1, after2\n```\n\nYou may also want to reuse before and after middlewares as much as possible,\nespecially when testing something that requires extensive setup and cleanup. You\ncan accomplish this by cloning a Nixt instance.\n\n```js\nvar base = nixt()\n  .before(setupDatabase)\n  .after(removeDatabase);\n\n// Later on\n\nbase.clone().run....\n```\n\n### Plugins\n\nNixt has primitive support for plugins. You can register any expectation or/and\nany middleware by calling `nixt.register`.\n\n```js\nvar fn = function() {};\nnixt.register('foo', fn);\n```\n\nOr you may want to register many functions at once.\n\n```js\nvar fn = function() {};\nvar fn1 = function() {};\nnixt.register({ baz: fn, bar: fn1 });\n```\n\n### Usage with a test runner\n\nNixt plays nice with any test runner out there. Here is a minimal example how\nyou could use it with Mocha.\n\n```js\ndescribe('todo add', function() {\n  it('adds a new todo item', function(done) {\n    nixt()\n    .run('todo add')\n    .stdout('A new todo has been added')\n    .end(done);\n  });\n});\n```\n\n### Usage without a test runner\n\nWhile using a test runner is recommended nixt is completely 'nodeable'. Here is\na simple example how you could accomplish that:\n\n```js\nvar assert = require('assert');\n\nfunction refute(err) {\n  assert(!err);\n}\n\nnixt()\n.run(cmd)\n.end(refute);\n\nnixt()\n.run(anotherCmd)\n.end(refute);\n```\n\n### Responding to interactive prompts\n\nNixt can respond to apps that run interactively using the `on()` and\n`respond()` functions.\n\n```js\nnixt()\n.run(cmd)\n.on('Your name: ').respond('Joe User\\n')\n.end();\n```\n\nSee `test/prompt.test.js` for more examples.\n\n## API\n\n### #before\n\nRegister a \"before\" middleware.\n\n```js\nnixt()\n.before(fn)\n.before(fn2)\n.run(cmd)\n.end();\n```\n\n### #after\n\nRegister an \"after\" middleware.\n\n```js\nnixt()\n.run(cmd)\n.after(fn)\n.after(fn2)\n.end();\n```\n\n### #cwd\n\nChange the current working directory of the main command (specified with `run`).\nPlease note that this won't affect any other commands like `unlink` etc.\n\n```js\nnixt()\n.cwd(__dirname)\n.run('pwd')\n.stdout(/test$/)\n.end();\n```\n\n### #base\n\nSet a base command. Useful for templates.\n\n```js\nnixt()\n.base('node ')\n.run('--version')\n.stdout('0.10.16')\n.end();\n```\n\n### #run\n\nSet a primary command to execute:\n\n```js\nnixt()\n.run('node --version')\n.stdout('0.10.16')\n.end(fn);\n```\n\nYou could also run the test right after specifying the command to run:\n\n```js\nnixt()\n.stdout('0.10.16')\n.run('node --version', fn)\n```\n\n### #stdin\n\nSet the contents of stdin.\n\n```js\nnixt()\n.stdin('foobar')\n.run('rev')\n.stdout('raboof')\n.end(fn);\n```\n\n### #env\n\nSet environment variables.\n\n```js\nnixt()\n.env('foo', 'bar')\n.env('baz', 'boo')\n.run('node --version')\n.stdout('0.10.16')\n.end(fn);\n```\n\n### #timeout\n\nSet a timeout for the main command that you are about to test.\n\n```js\nnixt()\n.timeout(1) // ms\n.run('cat /dev/null')\n.end(fn);\n```\n\n### #stdout\n\nSet expectations on stdout.\n\n```js\nnixt()\n.stdout('LICENSE Makefile')\n.run('ls')\n.end(fn);\n```\n\nWorks with regular expressions too.\n\n```js\nnixt()\n.stdout(/system/)\n.run('time')\n.end(fn);\n```\n\n### #stderr\n\nSame as `stdout` but well.. surprise works with stderr.\n\n```js\nnixt()\n.run('todo add')\n.stderr('Please speicfy a todo')\n.end(fn);\n```\n\n### #code\n\nExpect a given exit code.\n\n```js\nnixt()\n.run('todo add')\n.code(1)\n.end(fn);\n```\n\n### #exist\n\nCheck if a given path exists (works with both files and directories).\n\n```js\nnixt()\n.run('mkdir /tmp/test')\n.exist('/tmp/test')\n.end(fn);\n```\n\n### #notExist\n\nCheck if a given path does not exist (works with both files and directories).\n\n```js\nnixt()\n.run('rm /tmp/file')\n.notExist('/tmp/file')\n.end(fn);\n```\n\n### #match\n\nCheck the contents of a file.\n\n```js\nnixt()\n.writeFile(file, 'Hello')\n.run('node void.js')\n.match(file, 'Hello')\n.unlink(file)\n.end(done);\n```\n\n```js\nnixt()\n.writeFile(file, 'Hello')\n.run('node void.js')\n.match(file, /ello/)\n.unlink(file)\n.end(done);\n```\n\n### #mkdir\n\nCreate a new directory.\n\n```js\nnixt()\n.mkdir('xml-database')\n.run('this does stuff with the xml-database directory')\n.end(fn);\n```\n\n### #exec\n\nExecute a given command.\n\n```js\nnixt()\n.writeFile('LICENSE', 'MIT License')\n.exec('git add -a')\n.exec('git commit -m \"Add LICENSE\"')\n.run('git log')\n.stdout(/LICENSE/)\n.end();\n```\n\nBy default the commands will inherit the \"world\" for the main command which\nincludes environment variables, cwd, timeout. However, you can override this by\nsupplying a different \"world\":\n\n```js\nnixt()\n.exec('git add LICENSE', { timeout: 4, cwd: '/tmp' })\n.run('git log')\n.stdout(/LICENSE/)\n.end();\n```\n\n### #writeFile\n\nCreate a file with or without given contents.\n\nWithout:\n\n```js\nnixt()\n.writeFile(pathToFile)\n.end();\n```\n\nWith:\n\n```js\nnixt()\n.writeFile(pathToFile, data)\n.end();\n```\n\n### #rmdir\n\nRemove a directory.\n\n```js\nnixt()\n.mkdir('xml-database')\n.run('this does stuff with the xml-database directory')\n.rmdir('xml-database')\n.end(fn);\n```\n\n### #unlink\n\nUnlink a file.\n\n```js\nnixt()\n.writeFile('my-file', data)\n.run('this does stuff with my file')\n.unlink('my-file')\n.end(fn);\n```\n\n### #on\n\nDetect a prompt for user input. Accepts a String or RegExp that appears in\nthe the stdout stream. Must be paired with #respond.\n\n```js\nnixt()\n.run(cmd)\n.on('Your name: ').respond('Joe User\\n')\n.end();\n```\n\n### #respond\n\nWrite a response to the stdin stream when a prompt is detected.\n\nSee #on\n\n### #end\n\nRun the given test.\n\n```js\nnixt()\n.run('ls')\n.stdout('this-is-not-porn-i-promise')\n.end(function(err) {\n\n});\n```\n\nThe same might be accomplished with supplying a function to `run`:\n\n```js\nnixt()\n.stdout('this-is-not-porn-i-promise')\n.run('ls', function(err) {\n\n})\n```\n\n### #clone\n\nDeep clone a Nixt instance.\n\n```js\nvar clone = nixt()\n.before(fn)\n.after(fn)\n.run('my awesome command')\n.end()\n.clone();\n```\n\n### #expect\n\nRegister a custom expectation.\n\n```js\nnixt()\n.expect(function(result) {\n  if (result.stdout !== 'Unicorns') {\n    return new Error('OMG');\n  }\n})\n.run('ls')\n.end(fn);\n```\n\n## Installation\n\n```bash\n$ npm install nixt\n```\n\n## Tests\n\n### Running the tests\n\n```bash\n$ make\n```\n\n## Credits\n\nSpecial thanks to:\n\n  - [Alexander Petkov](https://dribbble.com/apetkov) - logo design\n  - [Martin Lazarov](https://github.com/mlazarov) - various ideas\n  - [Radoslav Stankov](https://github.com/rstankov)\n\n## Support the author\n\nDo you like this project? Star the repository, spread the word - it really helps. You may want to follow\nme on [Twitter](https://twitter.com/vesln) and\n[GitHub](https://github.com/vesln). Thanks!\n\n## License\n\n**MIT License**\n\nCopyright (C) 2013 Veselin Todorov (hi@vesln.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial\nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\nTHE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvesln%2Fnixt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvesln%2Fnixt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvesln%2Fnixt/lists"}