{"id":16127240,"url":"https://github.com/gr0uch/tapdance","last_synced_at":"2026-03-07T16:31:44.231Z","repository":{"id":65412369,"uuid":"38826248","full_name":"gr0uch/tapdance","owner":"gr0uch","description":"Test harness that emits the Test Anything Protocol (TAP).","archived":false,"fork":false,"pushed_at":"2019-09-26T22:12:04.000Z","size":56,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-21T04:39:11.171Z","etag":null,"topics":["tap","test-harness"],"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/gr0uch.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2015-07-09T14:44:52.000Z","updated_at":"2024-08-24T22:53:09.000Z","dependencies_parsed_at":"2023-01-22T07:55:25.418Z","dependency_job_id":null,"html_url":"https://github.com/gr0uch/tapdance","commit_stats":null,"previous_names":["daliwali/tapdance","0x8890/tapdance"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gr0uch/tapdance","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gr0uch%2Ftapdance","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gr0uch%2Ftapdance/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gr0uch%2Ftapdance/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gr0uch%2Ftapdance/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gr0uch","download_url":"https://codeload.github.com/gr0uch/tapdance/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gr0uch%2Ftapdance/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30221507,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T14:02:48.375Z","status":"ssl_error","status_checked_at":"2026-03-07T14:02:43.192Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["tap","test-harness"],"created_at":"2024-10-09T21:43:27.914Z","updated_at":"2026-03-07T16:31:44.193Z","avatar_url":"https://github.com/gr0uch.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tapdance\n\n[![Build Status](https://img.shields.io/travis/daliwali/tapdance/master.svg?style=flat-square)](https://travis-ci.org/daliwali/tapdance)\n[![npm Version](https://img.shields.io/npm/v/tapdance.svg?style=flat-square)](https://www.npmjs.com/package/tapdance)\n[![License](https://img.shields.io/npm/l/tapdance.svg?style=flat-square)](https://raw.githubusercontent.com/daliwali/tapdance/master/LICENSE)\n\nTest harness that emits the [Test Anything Protocol (TAP)](https://testanything.org). It runs in Node.js and web browsers, and is written in literate Parenscript (Common Lisp).\n\n```\n$ npm install tapdance\n```\n\n\n## Usage\n\nWhen the test exits, Tapdance will return a `0` exit code if nothing went wrong, and a non-zero exit code otherwise. There is no need to manually call when a test ends.\n\n\n### tapdance(fn)\n\nRun a function which may return a Promise. Calls to `runTest` get collected synchronously and run in sequential order in the next tick, which is useful when splitting up asynchronous tests in different files. The `fn` accepts two arguments, `assert` and `comment`.\n\n\n### assert(value, [message])\n\nCheck if a value is truthy or not.\n\n\n### comment([message])\n\nOutput a comment line.\n\n\n### runTest.assert\n\nThis can be overridden to use a different assert function.\n\n\n## Building\n\nYou will need a Common Lisp implementation like [SBCL](http://www.sbcl.org), and `wget`. If installing the developer dependencies didn't work the first time, you may need to `cd node_modules/sigil-cli \u0026\u0026 make`.\n\n\n## License\n\nThis software is licensed under the [MIT License](//github.com/daliwali/tapdance/blob/master/LICENSE).\n\n\n## Code\n\nHere's the full source code.\n\n    \"use strict\"\n    (defvar *assert* (require \"assert\"))\n\nCheck if it's running in Node.js, this determines whether or not to call\nNode.js specific APIs.\n\n    (defvar *is-node*\n     (and (not (eq (typeof process) 'undefined))\n          (eq (typeof (@ process exit)) 'function)\n          (eq (typeof (@ process next-tick)) 'function)))\n\nInitialize the local state of the program which is read \u0026 written later.\n\n    (defvar *start-time* ((@ *date now)))\n    (defvar *stack* (array))\n    (defvar *count* 0)\n    (defvar *passing* 0)\n\nA bit a ceremony is needed to kick off the TAP output. This kicks off the\nrunning of tests.\n\n    (println \"TAP version 13\")\n    (if *is-node*\n        (progn ((@ process on) 'exit exit)\n               ((@ process next-tick) flush))\n      (set-timeout flush 0))\n\nDefine the main public function, it accepts a test function that takes two\narguments, `assert` and `comment`.\n\n    (setf (@ module exports) run-test)\n    (setf (@ run-test assert) *assert*)\n    (defun run-test (fn)\n      (defun assert (exp message)\n        (incf *count*)\n        (try\n          (progn ((@ run-test assert) exp)\n                 (incf *passing*)\n                 (println (+ \"ok \" *count* \" \" message)))\n          (:catch (error)\n            (println (+ \"not ok \" *count* \" \" message))\n            (show-error error))))\n      (defun comment (message) (println (+ \"# \" message)))\n      ((@ *stack* push) (lambda () (fn assert comment))))\n\nThis is an implementation detail which runs all of the testing functions in\nthe order that they are declared.\n\n    (defun flush ()\n      ((@ ((@ *stack* reduce)\n           (lambda (chain fn)\n             ((@ ((@ chain then) fn) catch)\n              (lambda (error)\n                (progn\n                  (incf *count*)\n                  (println (+ \"not ok \" *count* \" \" (@ error message)))\n                  (show-error error)))))\n           ((@ *promise resolve))) then)\n       (lambda () (if *is-node* ((@ process exit)) (exit)))))\n\nUpon exiting, print the results as well as some useful information such as\nhow many tests failed and how long it took.\n\n    (defun exit ()\n      (if *is-node*\n          (setf (@ process exit-code)\n                (if (and *count* (eq *count* *passing*)) 0 1)))\n      (if (not *count*)\n          (progn (incf *count*) (println \"not ok 1 no tests found\")))\n      (println (+ \"1..\" *count*))\n      (println)\n      (if (eq *count* *passing*)\n          (println \"# all tests passed\")\n        (let ((failing (- *count* *passing*)))\n          (println\n           (+ \"# \" failing \" test\" (if (\u003e failing 1) \"s\" \"\") \" failed\"))))\n      (println\n       (+ \"# test finished in \" (- ((@ *date now)) *start-time*) \" ms\"))\n      (println))\n\nInternal function to pretty print errors that happen while running tests.\n\n    (defun show-error (error)\n      (println \"  ---\")\n      (println (+ \"  name: \" (@ error name)))\n      (if ((@ (regex \"\\\\n\") test) (@ error message))\n          (progn\n            (println \"  message:\")\n            ((@ ((@ error message split) #\\linefeed) map)\n             (lambda (line)\n               (println (+ \"    - \" line)))))\n        (progn\n          (println (+ \"  message: \" (@ error message)))\n          (if (@ error stack)\n              (progn\n                (println \"  stack:\")\n                ((@ ((@ error stack split) #\\linefeed) for-each)\n                 (lambda (line)\n                   (setf line ((@ line trim)))\n                   (if (not (eq ((@ line index-of) (@ error name)) 0))\n                       (println (+ \"    - \" line)))))))))\n      (println \"  ...\"))\n\nInternal function to print lines while escaping new lines in the input.\n\n    (defun println (str)\n      ((@ console log)\n       (if str ((@ str replace) #\\linefeed \"\") \"\")))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgr0uch%2Ftapdance","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgr0uch%2Ftapdance","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgr0uch%2Ftapdance/lists"}