├── docs-content ├── example ├── lib │ └── math.js ├── long-slow-many.js └── mocha-example.js ├── docs ├── static │ ├── snapshot-example │ │ ├── .taprc │ │ ├── msgtime.js │ │ ├── index.js │ │ ├── test.js │ │ ├── test-no-snapshot.js │ │ ├── yaml.test.js │ │ ├── msgtime.test.js │ │ ├── tap-snapshots │ │ │ ├── test.js-TAP.test.js │ │ │ ├── msgtime.test.js-TAP.test.js │ │ │ ├── yaml.test.js-TAP.test.js │ │ │ └── index.html │ │ └── index.html │ ├── favicon.ico │ └── my-awesome-module │ │ ├── test │ │ ├── hello-world.js │ │ ├── basic.js │ │ ├── index.html │ │ └── async.js │ │ ├── coverage-1 │ │ ├── lcov-report │ │ │ ├── sort-arrow-sprite.png │ │ │ ├── prettify.css │ │ │ └── block-navigation.js │ │ ├── index.html │ │ └── lcov.info │ │ ├── my-awesome-module-broken.js │ │ ├── my-awesome-module.js │ │ ├── package.json │ │ ├── index.html │ │ └── package-lock.json ├── gatsby-browser.js ├── src │ ├── images │ │ ├── brain.gif │ │ ├── brain.png │ │ ├── logo.gif │ │ ├── logo.png │ │ ├── brain-3.gif │ │ ├── batteries.gif │ │ ├── batteries.png │ │ ├── batteries-2.gif │ │ ├── batteries-4.gif │ │ ├── exclamation.gif │ │ ├── question-mark.gif │ │ ├── question-mark-2.gif │ │ ├── separator.svg │ │ ├── close.svg │ │ └── hamburger.svg │ ├── content │ │ └── docs │ │ │ ├── cli │ │ │ ├── index.template.js │ │ │ └── index.template │ │ │ ├── configuring │ │ │ └── index.md │ │ │ ├── tap-files │ │ │ └── index.md │ │ │ ├── using-with │ │ │ └── index.md │ │ │ ├── watch │ │ │ └── index.md │ │ │ ├── rerunning-partial-suites │ │ │ └── index.md │ │ │ ├── coverage │ │ │ └── coverage-map │ │ │ │ └── index.md │ │ │ ├── reporting │ │ │ └── index.md │ │ │ └── api │ │ │ ├── mochalike │ │ │ └── index.md │ │ │ └── promises │ │ │ └── index.md │ ├── components │ │ ├── home │ │ │ ├── whyTap.js │ │ │ ├── credits.js │ │ │ ├── hero.js │ │ │ └── features.js │ │ ├── layout.js │ │ ├── sidebar.js │ │ ├── NavLinks.js │ │ ├── EncircledImage.js │ │ ├── links.js │ │ ├── mobileNavbar.js │ │ ├── DocLinks.js │ │ ├── seo.js │ │ └── navbar.js │ ├── theme.js │ ├── pages │ │ ├── 404.js │ │ └── index.js │ └── templates │ │ └── page.js ├── .prettierrc ├── README.md ├── .eslintrc ├── LICENSE ├── gatsby-node.js └── package.json ├── test ├── tap │ ├── ok.js │ ├── plan-unsatisfied.js │ ├── not-ok.js │ ├── bail.js │ ├── plan-0.js │ ├── throw-unpatched-nonerror.js │ ├── set-timeout.js │ ├── throw-unpatched.js │ ├── node-debug-tap.js │ ├── patch-process-twice.js │ ├── tap-debug-1.js │ ├── throw-nonerror.js │ ├── mocha-globals.js │ ├── too-much.js │ ├── teardown-throw-nonerror.js │ ├── teardown-throw.js │ ├── unhandled-promise.js │ ├── timeout-sigterm.js │ ├── close-even-if-exiting-hard.js │ ├── timeout-sigterm-with-handle.js │ ├── uncaught-exception.js │ ├── teardown-event-loop.js │ ├── tap-only.js │ ├── autoend-false-with-teardown.js │ ├── stdout-epipe.js │ ├── tap-grep.js │ ├── resume.js │ ├── timeout-sigterm-many-times.js │ ├── tap-grep-invert.js │ └── index.js ├── diags.js ├── obj-to-yaml.js ├── regression-pipe-backup.js ├── run │ ├── invalid-option.js │ ├── cat.js │ ├── bad-rcfile.js │ ├── env.js │ ├── comments.js │ ├── epipe-stdout.js │ ├── nonparallel.js │ ├── esm.js │ ├── jsx.js │ ├── setup-tap-env.js │ ├── executables.js │ ├── test-regex.js │ ├── files.js │ ├── flow.js │ ├── ts.js │ ├── stdin.js │ ├── reporters.js │ ├── parallel.js │ ├── before-after.js │ ├── save-file.js │ ├── index.js │ ├── output-file.js │ ├── watermarks.js │ └── dump-config.js ├── regression-many-asserts-epipe.js ├── synonyms.js ├── coverage-map.js ├── parse-test-args.js ├── snapshot.js ├── stack.js ├── fixture.js ├── point.js ├── clean-stacks.js └── stdin.js ├── .github └── FUNDING.yml ├── netlify.toml ├── CHANGELOG.md ├── lib ├── diags.js ├── obj-to-yaml.js ├── stdin.js ├── point.js ├── parse-test-args.js ├── stack.js ├── extra-from-error.js ├── synonyms.js ├── fixture.js └── snapshot.js ├── postpublish.sh ├── .travis.yml ├── bin └── jsx.js ├── .gitattributes ├── .gitignore ├── scripts ├── unit.sh └── snap.sh ├── tap-snapshots ├── test-run-jsx.js-TAP.test.js ├── test-run-executables.js-TAP.test.js ├── test-run-invalid-option.js-TAP.test.js ├── test-run-env.js-TAP.test.js ├── test-tap-bail.js-TAP.test.js ├── test-tap-ok.js-TAP.test.js ├── test-run-cat.js-TAP.test.js ├── test-tap-plan-0.js-TAP.test.js ├── test-tap-resume.js-TAP.test.js ├── test-tap-stdout-epipe.js-TAP.test.js ├── test-tap-mocha-globals.js-TAP.test.js ├── test-tap-patch-process-twice.js-TAP.test.js ├── test-tap-set-timeout.js-TAP.test.js ├── test-run-test-regex.js-TAP.test.js ├── test-tap-teardown-event-loop.js-TAP.test.js ├── test-run-stdin.js-TAP.test.js ├── test-tap-plan-unsatisfied.js-TAP.test.js ├── test-tap-close-even-if-exiting-hard.js-TAP.test.js ├── test-tap-autoend-false-with-teardown.js-TAP.test.js ├── test-tap-too-much.js-TAP.test.js ├── test-run-nonparallel.js-TAP.test.js ├── test-tap-teardown-throw-nonerror.js-TAP.test.js ├── test-tap-throw-unpatched.js-TAP.test.js ├── test-tap-throw-unpatched-nonerror.js-TAP.test.js ├── test-tap-tap-only.js-TAP.test.js ├── test-tap-teardown-throw.js-TAP.test.js ├── test-run-esm.js-TAP.test.js ├── test-run-flow.js-TAP.test.js ├── test-tap-timeout-sigterm.js-TAP.test.js ├── test-tap-throw-nonerror.js-TAP.test.js ├── test-tap-timeout-sigterm-with-handle.js-TAP.test.js ├── test-tap-not-ok.js-TAP.test.js ├── test-run-reporters.js-TAP.test.js ├── test-tap-timeout-sigterm-many-times.js-TAP.test.js ├── test-run-files.js-TAP.test.js ├── test-tap-unhandled-promise.js-TAP.test.js ├── test-tap-tap-grep.js-TAP.test.js ├── test-tap-uncaught-exception.js-TAP.test.js ├── test-tap-tap-grep-invert.js-TAP.test.js ├── test-run-ts.js-TAP.test.js ├── test-tap-node-debug-tap.js-TAP.test.js ├── test-run-parallel.js-TAP.test.js ├── test-clean-yaml-object.js-TAP.test.js ├── test-tap-tap-debug-1.js-TAP.test.js ├── test-watch.js-TAP.test.js ├── test-run-basic.js-TAP.test.js ├── test-base.js-TAP.test.js └── test-spawn.js-TAP.test.js ├── coverage-map.js ├── CONTRIBUTING.md ├── LICENSE └── package.json /docs-content: -------------------------------------------------------------------------------- 1 | docs/src/content -------------------------------------------------------------------------------- /example/lib/math.js: -------------------------------------------------------------------------------- 1 | module.exports = Math 2 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/.taprc: -------------------------------------------------------------------------------- 1 | coverage: false 2 | -------------------------------------------------------------------------------- /test/tap/ok.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => t.pass('fine') 3 | ) 4 | -------------------------------------------------------------------------------- /test/tap/plan-unsatisfied.js: -------------------------------------------------------------------------------- 1 | require('./')(t => t.plan(99)) 2 | -------------------------------------------------------------------------------- /test/tap/not-ok.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => t.fail('expected') 3 | ) 4 | -------------------------------------------------------------------------------- /test/tap/bail.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => t.bailout('cannot proceed') 3 | ) 4 | -------------------------------------------------------------------------------- /test/tap/plan-0.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => t.plan(0, 'skip it all') 3 | ) 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [isaacs] 4 | -------------------------------------------------------------------------------- /test/tap/throw-unpatched-nonerror.js: -------------------------------------------------------------------------------- 1 | require('./')(t => { 2 | throw 'not yet patched' 3 | }) 4 | -------------------------------------------------------------------------------- /docs/gatsby-browser.js: -------------------------------------------------------------------------------- 1 | require('prismjs/themes/prism-tomorrow.css'); 2 | require('./src/main.css'); 3 | -------------------------------------------------------------------------------- /docs/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/static/favicon.ico -------------------------------------------------------------------------------- /test/tap/set-timeout.js: -------------------------------------------------------------------------------- 1 | require('./')(t => { 2 | t.setTimeout(1234) 3 | t.pass('fine') 4 | }) 5 | -------------------------------------------------------------------------------- /test/tap/throw-unpatched.js: -------------------------------------------------------------------------------- 1 | require('./')(t => { 2 | throw new Error('not yet patched') 3 | }) 4 | -------------------------------------------------------------------------------- /docs/src/images/brain.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/brain.gif -------------------------------------------------------------------------------- /docs/src/images/brain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/brain.png -------------------------------------------------------------------------------- /docs/src/images/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/logo.gif -------------------------------------------------------------------------------- /docs/src/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/logo.png -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | base = "docs" 3 | command = "gatsby build" 4 | publish = "docs/public" 5 | -------------------------------------------------------------------------------- /test/tap/node-debug-tap.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | () => process.env.NODE_DEBUG = 'tap',t => t.plan(0) 3 | ) 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Please see [the tap website](http://www.node-tap.org/changelog/) for 2 | the curated changelog. 3 | -------------------------------------------------------------------------------- /docs/src/images/brain-3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/brain-3.gif -------------------------------------------------------------------------------- /docs/static/my-awesome-module/test/hello-world.js: -------------------------------------------------------------------------------- 1 | const tap = require('tap') 2 | tap.pass('this is fine') 3 | -------------------------------------------------------------------------------- /test/tap/patch-process-twice.js: -------------------------------------------------------------------------------- 1 | require('./')(t => { 2 | t.patchProcess() 3 | t.patchProcess() 4 | }) 5 | -------------------------------------------------------------------------------- /docs/src/images/batteries.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/batteries.gif -------------------------------------------------------------------------------- /docs/src/images/batteries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/batteries.png -------------------------------------------------------------------------------- /test/tap/tap-debug-1.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | () => process.env.TAP_DEBUG = '1',t => t.comment('this is fine') 3 | ) 4 | -------------------------------------------------------------------------------- /test/tap/throw-nonerror.js: -------------------------------------------------------------------------------- 1 | require('./')(t => { 2 | t.pass('this is fine') 3 | throw 'not an error' 4 | }) 5 | -------------------------------------------------------------------------------- /docs/src/images/batteries-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/batteries-2.gif -------------------------------------------------------------------------------- /docs/src/images/batteries-4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/batteries-4.gif -------------------------------------------------------------------------------- /docs/src/images/exclamation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/exclamation.gif -------------------------------------------------------------------------------- /docs/src/images/question-mark.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/question-mark.gif -------------------------------------------------------------------------------- /test/tap/mocha-globals.js: -------------------------------------------------------------------------------- 1 | require('./')(t => { 2 | t.mochaGlobals() 3 | t.equal(typeof describe, 'function') 4 | }) 5 | -------------------------------------------------------------------------------- /docs/src/images/question-mark-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/node-tap/master/docs/src/images/question-mark-2.gif -------------------------------------------------------------------------------- /test/tap/too-much.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.plan(1) 4 | t.pass('a little') 5 | t.pass('a lot') 6 | } 7 | ) 8 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/msgtime.js: -------------------------------------------------------------------------------- 1 | module.exports = function msgTime (msg) { 2 | return msg + ' time=' + Date.now() 3 | } 4 | -------------------------------------------------------------------------------- /test/tap/teardown-throw-nonerror.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.teardown(() => { throw 'poop' }) 4 | t.pass('x') 5 | } 6 | ) 7 | -------------------------------------------------------------------------------- /test/tap/teardown-throw.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.teardown(() => { throw new Error('poop') }) 4 | t.pass('x') 5 | } 6 | ) 7 | -------------------------------------------------------------------------------- /test/tap/unhandled-promise.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.pass('fine, i promise') 4 | Promise.reject(new Error('broken')) 5 | } 6 | ) 7 | -------------------------------------------------------------------------------- /docs/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function (tag, contents) { 2 | return '<' + tag + '>' + contents + '' 3 | } 4 | -------------------------------------------------------------------------------- /lib/diags.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const objToYaml = require('./obj-to-yaml.js') 4 | 5 | module.exports = extra => (y => y ? '\n' + y : '')(objToYaml(extra)) 6 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/test.js: -------------------------------------------------------------------------------- 1 | const t = require('tap') 2 | const tagger = require('./index.js') 3 | t.matchSnapshot(tagger('tagName', 'content'), 'output') 4 | -------------------------------------------------------------------------------- /test/tap/timeout-sigterm.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.pass('fine') 4 | process.kill(process.pid, 'SIGTERM') 5 | setTimeout(() => {}, 1000) 6 | } 7 | ) 8 | -------------------------------------------------------------------------------- /test/tap/close-even-if-exiting-hard.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | process.on('exit', (code) => process.exit(code)) 4 | t.pass('make sure, really') 5 | } 6 | ) 7 | -------------------------------------------------------------------------------- /test/tap/timeout-sigterm-with-handle.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | setTimeout(() => {}, 10000) 4 | t.pass('fine') 5 | process.kill(process.pid, 'SIGTERM') 6 | } 7 | ) 8 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/test-no-snapshot.js: -------------------------------------------------------------------------------- 1 | const t = require('tap') 2 | const tagger = require('./index.js') 3 | t.equal(tagger('tagName', 'content'), 'content') 4 | -------------------------------------------------------------------------------- /test/tap/uncaught-exception.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.pass('this is fine') 4 | setTimeout(() => { throw new Error('poop') }) 5 | t.pass('i am sure things are ok') 6 | } 7 | ) 8 | -------------------------------------------------------------------------------- /test/tap/teardown-event-loop.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.pass('fine') 4 | const interval = setInterval(() => {}, 10000) 5 | t.tearDown(() => clearInterval(interval)) 6 | } 7 | ) 8 | -------------------------------------------------------------------------------- /test/diags.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const t = require('../') 3 | const diags = require('../lib/diags.js') 4 | 5 | t.match(diags({ todo: true }), '') 6 | t.match(diags({ foo: 1 }), ' ---\n foo: 1\n ...\n') 7 | -------------------------------------------------------------------------------- /test/obj-to-yaml.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const t = require('../') 3 | const oty = require('../lib/obj-to-yaml.js') 4 | 5 | t.match(oty({ todo: true }), '') 6 | t.match(oty({ foo: 1 }), ' ---\n foo: 1\n ...') 7 | -------------------------------------------------------------------------------- /test/tap/tap-only.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | () => process.env.TAP_ONLY = '1',t => { 3 | t.only('only this one', t => t.end()) 4 | t.test('not this one', t => Promise.reject(new Error('no'))) 5 | } 6 | ) 7 | -------------------------------------------------------------------------------- /postpublish.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | set -x 4 | node docs/src/content/docs/cli/index.template.js 5 | git add docs/src/content/docs/cli 6 | git commit -m 'update cli doc' 7 | git push origin --follow-tags 8 | -------------------------------------------------------------------------------- /test/regression-pipe-backup.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // https://github.com/tapjs/node-tap/pull/506 4 | 5 | const t = require('../') 6 | 7 | t.plan(5000) 8 | for (let i = 1; i <= 5000; i++) { 9 | t.pass(i) 10 | } 11 | -------------------------------------------------------------------------------- /test/run/invalid-option.js: -------------------------------------------------------------------------------- 1 | const { 2 | run, 3 | t, 4 | } = require('./') 5 | 6 | t.test('print a nicer message on invalid argument errors', t => { 7 | t.plan(1) 8 | run(['-R'], {}, (er, o, e) => 9 | t.matchSnapshot(e)) 10 | }) 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "node" 5 | - 14 6 | - 12 7 | - 10 8 | - 8 9 | 10 | os: 11 | - linux 12 | 13 | cache: 14 | directories: 15 | - $HOME/.npm 16 | 17 | notifications: 18 | email: false 19 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/yaml.test.js: -------------------------------------------------------------------------------- 1 | const t = require('tap') 2 | const yaml = require('tap-yaml') 3 | t.formatSnapshot = object => yaml.stringify(object) 4 | 5 | // now all my snapshot files will be in yaml! 6 | t.matchSnapshot({ foo: ['bar', 'baz'] }) 7 | -------------------------------------------------------------------------------- /test/tap/autoend-false-with-teardown.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.options.autoend = false 4 | t.teardown(() => console.log('tear it down')) 5 | setTimeout(() => { 6 | t.pass('this is fine') 7 | t.end() 8 | }, 50) 9 | } 10 | ) 11 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | This is the content of the [node-tap website](https://www.node-tap.org) 2 | 3 | It's a [gatsby](https://www.gatsbyjs.org) website deployed to 4 | [netlify](https://www.netlify.com/). 5 | 6 | The markdown content lives in [./src/content](./src/content). 7 | -------------------------------------------------------------------------------- /test/tap/stdout-epipe.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | t.pass('this is fine') 4 | const er = new Error('fake pipe') 5 | er.code = 'EPIPE' 6 | process.stdout.emit('some other event') 7 | setTimeout(() => process.stdout.emit('error', er)) 8 | } 9 | ) 10 | -------------------------------------------------------------------------------- /bin/jsx.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | if (__filename !== process.argv[1] || process.argv.length < 3) 3 | throw new Error('this should only be used to load a jsx file') 4 | process.argv.splice(1, 2, require('path').resolve(process.argv[2])) 5 | require('import-jsx')(process.argv[1]) 6 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/coverage-1/lcov-report/sort-arrow-sprite.png: -------------------------------------------------------------------------------- 1 | �PNG 2 |  3 | IHDR�F�3tEXtSoftwareAdobe ImageReadyq�e<sIDATxڼRA� ������D���e[ � 4 | �HfFX� g�f���3�Dd F�w�-˘�� 5 | � n�g�M+OVں�=�""/�ĥ'Y���?H�hV� �@��p���Y�8Bwc,�IEND�B`� -------------------------------------------------------------------------------- /docs/static/my-awesome-module/my-awesome-module-broken.js: -------------------------------------------------------------------------------- 1 | module.exports = x => { 2 | if (x % 2 === 0) { 3 | return 'even' 4 | } else if (x % 2 === 1) { 5 | return 'odd' 6 | } else if (x > 100) { 7 | return 'big' 8 | } else if (x < 0) { 9 | return 'negative' 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/my-awesome-module.js: -------------------------------------------------------------------------------- 1 | // my-awesome-module.js 2 | module.exports = x => { 3 | if (x > 100) { 4 | return 'big' 5 | } else if (x < 0) { 6 | return 'negative' 7 | } else if (x % 2 === 0) { 8 | return 'even' 9 | } else { 10 | return 'odd' 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/regression-many-asserts-epipe.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // See https://github.com/tapjs/node-tap/issues/422 3 | const t = require('../') 4 | t.test('just a lot of asserts in rapid succession', t => { 5 | for (let i = 0; i < 5000; i++) { 6 | t.pass('a number is ' + i) 7 | } 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set 2 | * text=auto 3 | 4 | # Require Unix line endings 5 | * text eol=lf 6 | 7 | # Denote all files that are truly binary and should not be modified. 8 | *.png binary 9 | *.jpg binary 10 | *.ico binary 11 | *.gif binary 12 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-awesome-module", 3 | "version": "1.2.3", 4 | "devDependencies": { 5 | "tap": "^13.0.0" 6 | }, 7 | "scripts": { 8 | "test": "tap" 9 | }, 10 | "dependencies": { 11 | "tap-yaml": "^1.0.0", 12 | "yaml": "^1.5.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/msgtime.test.js: -------------------------------------------------------------------------------- 1 | const t = require('tap') 2 | const msgTime = require('./msgtime.js') 3 | 4 | t.cleanSnapshot = output => { 5 | return output.replace(/ time=[0-9]+$/g, ' time={time}') 6 | } 7 | 8 | const output = msgTime('this is a test') 9 | t.matchSnapshot(output, 'add timestamp to message') 10 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/test/basic.js: -------------------------------------------------------------------------------- 1 | // test/basic.js 2 | const tap = require('../../../..') 3 | const mam = require('../my-awesome-module.js') 4 | 5 | // Always call as (found, wanted) by convention 6 | tap.equal(mam(1), 'odd') 7 | tap.equal(mam(2), 'even') 8 | tap.equal(mam(200), 'big') 9 | tap.equal(mam(-10), 'negative') 10 | -------------------------------------------------------------------------------- /test/synonyms.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const t = require('../') 3 | const synonyms = require('../lib/synonyms.js') 4 | 5 | t.match(synonyms, { 6 | notOk: [ 7 | 'notOk', 8 | 'notok', 9 | 'not_ok', 10 | 'false', 11 | 'assertNot', 12 | 'assertnot', 13 | 'assert_not' 14 | ], 15 | type: [ 'type', 'isa', 'isA', 'isa', 'is_a' ] 16 | }) 17 | -------------------------------------------------------------------------------- /test/run/cat.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | t.test('cat', t => { 9 | const ok = tmpfile(t, 'ts/ok.tap', ` 10 | TAP version 13 11 | 1..1 12 | ok 1 - this is fine 13 | `) 14 | run([ok], {}, (er, o, e) => { 15 | t.equal(er, null) 16 | t.matchSnapshot(o) 17 | t.end() 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /test/tap/tap-grep.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | () => process.env.TAP_GREP = 'x\n/^y$/i',t => { 3 | t.test('axo', t => { 4 | t.test('yellow', t => Promise.reject(new Error('no'))) 5 | t.test('Y', t => t.end()) 6 | return t.test('y', t => t.test('this too', t => t.end())) 7 | }) 8 | t.test('nope', t => Promise.reject(new Error('no'))) 9 | } 10 | ) 11 | -------------------------------------------------------------------------------- /test/run/bad-rcfile.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | dir, 6 | t, 7 | } = require('./') 8 | 9 | const fs = require('fs') 10 | t.test('bad rc file', t => { 11 | fs.writeFileSync(`${dir}/.taprc`, 'this : is not : valid : yaml') 12 | run(['--dump-config'], { cwd: dir }, (er, o, e) => { 13 | t.match(er, { code: 1 }) 14 | t.end() 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /test/tap/resume.js: -------------------------------------------------------------------------------- 1 | const MiniPass = require('minipass') 2 | const mp = new MiniPass() 3 | mp.pipe(process.stdout) 4 | 5 | require('./')( 6 | t => { 7 | t.resume() 8 | t.pause() 9 | mp.write('1\n') 10 | t.pipe(mp) 11 | t.pass('2') 12 | t.pause() 13 | t.pass('4') 14 | mp.write('3\n') 15 | t.pass('5') 16 | t.resume() 17 | t.end() 18 | } 19 | ) 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /* 2 | /.* 3 | 4 | !bin/ 5 | !lib/ 6 | !docs/ 7 | /docs/public 8 | /docs/node_modules 9 | /docs/.cache 10 | !package.json 11 | !package-lock.json 12 | !README.md 13 | !CONTRIBUTING.md 14 | !LICENSE 15 | !CHANGELOG.md 16 | !example/ 17 | !scripts/ 18 | !tap-snapshots/ 19 | !test/ 20 | !.travis.yml 21 | !.gitignore 22 | !.gitattributes 23 | !coverage-map.js 24 | !postpublish.sh 25 | !netlify.toml 26 | -------------------------------------------------------------------------------- /test/coverage-map.js: -------------------------------------------------------------------------------- 1 | const t = require('../') 2 | const coverageMap = require('../coverage-map.js') 3 | t.strictSame(coverageMap('test/coverage-map.js'), ['coverage-map.js']) 4 | t.strictSame(coverageMap('test/run/xyz.js'), [ 5 | 'bin/jack.js', 6 | 'bin/jsx.js', 7 | 'bin/run.js' 8 | ]) 9 | t.strictSame(coverageMap('test/glorp.js'), null) 10 | t.strictSame(coverageMap('test/test.js'), ['lib/test.js']) 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/cli/index.template.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs') 3 | const template = fs.readFileSync(__dirname + '/index.template', 'utf8') 4 | const {spawnSync} = require('child_process') 5 | const bin = require.resolve('../../../../../bin/run.js') 6 | const usage = spawnSync(process.execPath, [bin, '-h']).output.join('') 7 | fs.writeFileSync(__dirname + '/index.md', template.replace(/\$\{USAGE\}/, usage)) 8 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/coverage-1/index.html: -------------------------------------------------------------------------------- 1 | Index of /

Index of /


../
2 | lcov-report/       2019-06-16T04:26:58.292Z         -
3 | index.html         2019-06-16T06:27:21.704Z         0
4 | lcov.info          2019-06-16T04:26:58.293Z       338
5 | 

-------------------------------------------------------------------------------- /lib/obj-to-yaml.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const cleanYamlObject = require('./clean-yaml-object.js') 4 | const yaml = require('tap-yaml') 5 | 6 | module.exports = obj => (clean => 7 | (clean && typeof clean === 'object' && Object.keys(clean).length) ? 8 | ' ---\n' + (yaml.stringify(clean).split('\n').map( 9 | l => l.trim() ? ' ' + l : l.trim() 10 | ).join('\n')) + ' ...\n' 11 | : '' 12 | )(cleanYamlObject(obj)) 13 | -------------------------------------------------------------------------------- /test/tap/timeout-sigterm-many-times.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | t => { 3 | const fs = require('fs') 4 | fs.readFile(__filename, (er, data) => {}) 5 | t.pass('fine') 6 | process.kill(process.pid, 'SIGTERM') 7 | process.kill(process.pid, 'SIGTERM') 8 | process.kill(process.pid, 'SIGTERM') 9 | process.kill(process.pid, 'SIGTERM') 10 | process.kill(process.pid, 'SIGTERM') 11 | process.kill(process.pid, 'SIGTERM') 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /test/tap/tap-grep-invert.js: -------------------------------------------------------------------------------- 1 | require('./')( 2 | () => { 3 | process.env.TAP_GREP = 'x\n/^y$/i' 4 | process.env.TAP_GREP_INVERT = 1 5 | },t => { 6 | t.test('yes this one', t => { 7 | t.test('Y', t => Promise.reject(new Error('no'))) 8 | t.test('yellow', t => t.end()) 9 | return t.test('apple', t => t.test('this too', t => t.end())) 10 | }) 11 | t.test('axo', t => Promise.reject(new Error('no'))) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/tap-snapshots/test.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test.js TAP > output 1`] = ` 9 | content 10 | ` 11 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/tap-snapshots/msgtime.test.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`msgtime.test.js TAP > add timestamp to message 1`] = ` 9 | this is a test time={time} 10 | ` 11 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/tap-snapshots/yaml.test.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`yaml.test.js TAP > must match snapshot 1`] = ` 9 | foo: 10 | - bar 11 | - baz 12 | 13 | ` 14 | -------------------------------------------------------------------------------- /test/run/env.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | const ok = tmpfile(t, 'ok.js', ` 9 | const t = require(${tap}) 10 | t.equal(process.env.glorp, 'foo') 11 | t.equal(process.env.USER, undefined) 12 | t.equal(process.env.TERM, '') 13 | `) 14 | 15 | t.plan(3) 16 | run(['--test-env=USER', '--test-env=TERM=', '--test-env=glorp=foo', ok], {}, (er, o, e) => { 17 | t.notOk(er) 18 | t.equal(e, '') 19 | t.matchSnapshot(o) 20 | }) 21 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/test/index.html: -------------------------------------------------------------------------------- 1 | Index of /

Index of /


../
2 | async.js             2019-06-16T04:26:58.294Z       460
3 | basic.js             2019-06-16T04:26:58.294Z       258
4 | hello-world.js       2019-06-16T04:26:58.294Z        52
5 | index.html           2019-06-16T06:27:36.295Z         0
6 | 

-------------------------------------------------------------------------------- /docs/static/my-awesome-module/coverage-1/lcov.info: -------------------------------------------------------------------------------- 1 | TN: 2 | SF:/Users/isaacs/dev/js/tap/docs/basics/my-awesome-module/my-awesome-module.js 3 | FN:1,(anonymous_0) 4 | FNF:1 5 | FNH:1 6 | FNDA:2,(anonymous_0) 7 | DA:1,1 8 | DA:2,2 9 | DA:3,1 10 | DA:4,1 11 | DA:5,1 12 | DA:6,0 13 | DA:7,0 14 | DA:8,0 15 | DA:9,0 16 | LF:9 17 | LH:5 18 | BRDA:2,0,0,1 19 | BRDA:2,0,1,1 20 | BRDA:4,1,0,1 21 | BRDA:4,1,1,0 22 | BRDA:6,2,0,0 23 | BRDA:6,2,1,0 24 | BRDA:8,3,0,0 25 | BRDA:8,3,1,0 26 | BRF:8 27 | BRH:3 28 | end_of_record 29 | -------------------------------------------------------------------------------- /test/run/comments.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | const ok = tmpfile(t, 'comments/ok.js', `'use strict' 9 | const t = require(${tap}) 10 | t.comment('root') 11 | t.test('parent', t => { 12 | t.comment('parent') 13 | t.test('child', t => { 14 | t.comment('child') 15 | t.end() 16 | }) 17 | t.end() 18 | }) 19 | `) 20 | 21 | t.plan(1) 22 | run(['--comments', ok], {}, (er, o, e) => 23 | t.equal(e, 'root\nparent\nchild\n')) 24 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/tap-snapshots/index.html: -------------------------------------------------------------------------------- 1 | Index of /

Index of /


../
2 | msgtime.test.js-TAP.test.js       2019-06-16T04:26:58.285Z       382
3 | test.js-TAP.test.js               2019-06-16T04:26:58.285Z       356
4 | yaml.test.js-TAP.test.js          2019-06-16T04:26:58.285Z       369
5 | 

6 | -------------------------------------------------------------------------------- /docs/src/content/docs/cli/index.template: -------------------------------------------------------------------------------- 1 | --- 2 | title: CLI 3 | section: 6 4 | redirect_from: 5 | - /cli/ 6 | - /cli 7 | --- 8 | 9 | # CLI 10 | 11 | You can get help on tap's command line interface by running `tap -h`. 12 | 13 | Any configuration options may be set on the command line, in your 14 | `package.json` file in a `tap` section, or in a YAML-formatted `.taprc` file in 15 | the root of your project. See [configuring tap](/docs/configuring/) for more 16 | information. 17 | 18 | ``` 19 | ${USAGE} 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/test/async.js: -------------------------------------------------------------------------------- 1 | // test/async.js 2 | // this is a silly test. 3 | var tap = require('tap') 4 | var fs = require('fs') 5 | tap.test('some async stuff', childTest => { 6 | fs.readdir(__dirname, (er, files) => { 7 | if (er) { 8 | throw er // tap will handle this 9 | } 10 | childTest.match(files.join(','), /\basync\.js\b/) 11 | childTest.end() 12 | }) 13 | }) 14 | 15 | tap.test('this waits until after', childTest => { 16 | // no asserts? no problem! 17 | // the lack of throwing means "success" 18 | childTest.end() 19 | }) 20 | -------------------------------------------------------------------------------- /scripts/unit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "${1}" = "" ]; then 3 | units=($(cd test &>/dev/null; ls)) 4 | for u in "${units[@]}"; do 5 | u=$(basename "$u" .js) 6 | if ! [ $u == "clean-stacks" ]; then 7 | $BASH scripts/unit.sh "$u" || exit 1 8 | fi 9 | done 10 | else 11 | shopt -s extglob 12 | include=$(echo +(bin|lib)/$1.js) 13 | if [ -f "$include" ]; then 14 | set -x 15 | node bin/run.js test/${1}* --nyc-arg=--include="$include" -Rterse -M coverage-map.js 16 | else 17 | set -x 18 | node bin/run.js test/${1}* --no-cov -Rterse 19 | fi 20 | fi 21 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-jsx.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/jsx.js TAP jsx > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - cli-tests/jsx/ok.jsx # {time} { 11 | ok 1 - this is fine 12 | 1..1 13 | # {time} 14 | } 15 | 16 | 1..1 17 | # {time} 18 | 19 | ` 20 | -------------------------------------------------------------------------------- /test/run/epipe-stdout.js: -------------------------------------------------------------------------------- 1 | const { 2 | run, 3 | t, 4 | } = require('./') 5 | 6 | t.plan(2) 7 | const c = run(['-', '-C'], { stdio: 'pipe' }, (er, o, e) => { 8 | t.equal(er, null) 9 | t.equal(o, str) 10 | }) 11 | // comes in two chunks, because it's going through a parser 12 | const str = 'TAP version 13\n1..9\nok\n' 13 | let seen = '' 14 | c.stdin.write(str) 15 | c.stdout.on('data', chunk => { 16 | seen += chunk 17 | if (seen.length >= str.length) { 18 | c.stdout.destroy() 19 | c.stdin.write('ok\nok\nok\nok\n') 20 | c.stdin.write('ok\nok\nok\nok\n') 21 | } 22 | }) 23 | -------------------------------------------------------------------------------- /test/run/nonparallel.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | dir, 6 | t, 7 | } = require('./') 8 | 9 | tmpfile(t, '1.js', ` 10 | console.log('start one') 11 | const t = require(${tap}) 12 | setTimeout(() => { 13 | t.pass('fine in 1') 14 | t.end() 15 | }, 250) 16 | `) 17 | tmpfile(t, '2.js', ` 18 | console.log('start two') 19 | const t = require(${tap}) 20 | t.pass('fine in 2') 21 | t.end() 22 | `) 23 | 24 | t.plan(3) 25 | run(['1.js', '2.js', '-j1'], { cwd: dir }, (er, o, e) => { 26 | t.equal(er, null) 27 | t.matchSnapshot(o, 'output') 28 | t.matchSnapshot(e, 'stderr') 29 | }) 30 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-executables.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/executables.js TAP executables > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - exe/ok.sh # {time} { 11 | 1..1 12 | ok 1 File with executable bit should be executed 13 | } 14 | 15 | 1..1 16 | # {time} 17 | 18 | ` 19 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-invalid-option.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/invalid-option.js TAP print a nicer message on invalid argument errors > must match snapshot 1`] = ` 9 | 10 | Error: no value provided for option: reporter 11 | {STACK} 12 | Run \`tap --help\` for usage information 13 | 14 | ` 15 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-env.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/env.js TAP > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - cli-tests/ok.js # {time} { 11 | ok 1 - should be equal 12 | ok 2 - should be equal 13 | ok 3 - should be equal 14 | 1..3 15 | # {time} 16 | } 17 | 18 | 1..1 19 | # {time} 20 | 21 | ` 22 | -------------------------------------------------------------------------------- /docs/src/components/home/whyTap.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import EncircledImage from '../EncircledImage'; 4 | import questionMark from '../../images/question-mark-2.gif'; 5 | 6 | const Content = styled.div` 7 | max-width: 700px; 8 | margin: auto; 9 | padding: 40px 20px 20px; 10 | `; 11 | 12 | const WhyTap = ({markdownData}) => { 13 | return( 14 |
15 | 16 | 17 |
18 | 19 |
20 | ); 21 | }; 22 | 23 | export default WhyTap; 24 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-bail.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/bail.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/bail.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/bail.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | Bail out! cannot proceed 22 | 23 | ` 24 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-ok.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/ok.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/ok.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/ok.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - fine 22 | 1..1 23 | # {time} 24 | 25 | ` 26 | -------------------------------------------------------------------------------- /docs/src/theme.js: -------------------------------------------------------------------------------- 1 | export const breakpoints = { 2 | PHABLET: '32em', 3 | TABLET: '48em', 4 | PC: '64em', 5 | WIDESCREEN: '80em', 6 | }; 7 | 8 | export const theme = { 9 | colors: { 10 | white: '#ffffff', 11 | lightestGrey: '#f8f8f8', 12 | lightGrey: '#f1f1f1', 13 | darkGrey: '#e9e9e9', 14 | black: '#333333', 15 | aqua: '#00ffff', 16 | blue: '#204dff', 17 | fushia: '#d630ff', 18 | lightFushia: '#e683ff', 19 | red: '#ff0000', 20 | yellow: '#fdfb00', 21 | }, 22 | breakpoints: [breakpoints.PHABLET, breakpoints.TABLET, breakpoints.PC, breakpoints.WIDESCREEN], 23 | space: [0, 5, 10, 20, 30, 40, 60, 80], 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-cat.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/cat.js TAP cat > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - cli-tests/ts/ok.tap # SKIP no tests found { 11 | 12 | # Subtest 13 | 1..1 14 | ok 1 - this is fine 15 | 16 | 1..0 # no tests found 17 | } 18 | 19 | 1..1 20 | # skip: 1 21 | # {time} 22 | 23 | ` 24 | -------------------------------------------------------------------------------- /test/run/esm.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | t.test('mjs', t => { 9 | const ok = tmpfile(t, 'mjs/ok.mjs', `'use strict' 10 | import t from ${tap} 11 | t.pass('this is fine') 12 | `) 13 | run([ok, '--esm'], {}, (er, o, e) => { 14 | t.equal(er, null) 15 | t.matchSnapshot(o) 16 | t.end() 17 | }) 18 | }) 19 | 20 | t.test('esm', t => { 21 | const ok = tmpfile(t, 'esm/ok.js', `'use strict' 22 | import {t} from ${tap} 23 | t.pass('this is fine') 24 | `) 25 | run([ok, '--esm'], {}, (er, o, e) => { 26 | t.equal(er, null) 27 | t.matchSnapshot(o) 28 | t.end() 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-plan-0.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/plan-0.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/plan-0.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/plan-0.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | 1..0 # skip it all 22 | # {time} 23 | 24 | ` 25 | -------------------------------------------------------------------------------- /docs/src/components/layout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import Navbar from './navbar'; 4 | import Sidebar from './sidebar'; 5 | import {Flex} from 'rebass'; 6 | 7 | const WidthWrapper = styled.div` 8 | max-width: 750px; 9 | margin: 0 auto; 10 | width: 100%; 11 | padding: 20px; 12 | box-sizing: border-box; 13 | `; 14 | 15 | const Layout = ({showSidebar, children}) => { 16 | return( 17 | <> 18 | 19 | 20 | {showSidebar && } 21 | 22 | {children} 23 | 24 | 25 | 26 | ); 27 | }; 28 | 29 | export default Layout; 30 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-resume.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/resume.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/resume.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/resume.js TAP > stdout 1`] = ` 20 | 1 21 | ok 1 - 2 22 | 3 23 | ok 2 - 4 24 | ok 3 - 5 25 | 1..3 26 | # {time} 27 | 28 | ` 29 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-stdout-epipe.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/stdout-epipe.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/stdout-epipe.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/stdout-epipe.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - this is fine 22 | 1..1 23 | # {time} 24 | 25 | ` 26 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-mocha-globals.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/mocha-globals.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/mocha-globals.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/mocha-globals.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - should be equal 22 | 1..1 23 | # {time} 24 | 25 | ` 26 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-patch-process-twice.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/patch-process-twice.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/patch-process-twice.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/patch-process-twice.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | 1..0 22 | # {time} 23 | 24 | ` 25 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/coverage-1/lcov-report/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} 2 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-set-timeout.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/set-timeout.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/set-timeout.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/set-timeout.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | # timeout=1234 22 | ok 1 - fine 23 | 1..1 24 | # {time} 25 | 26 | ` 27 | -------------------------------------------------------------------------------- /docs/src/components/sidebar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import DocLinks from './DocLinks'; 4 | import {theme} from '../theme'; 5 | 6 | const Container = styled.div` 7 | background-color: ${theme.colors.lightGrey}; 8 | flex: 0 0 250px; 9 | overflow-y: scroll; 10 | height: 100vh; 11 | top: 68px; 12 | position: sticky; 13 | padding: 20px 20px 100px; 14 | box-shadow: 1px 0 10px 1px #33333330; 15 | display: none; 16 | 17 | @media screen and (min-width: 1050px) { 18 | display: block; 19 | } 20 | `; 21 | 22 | const Sidebar = () => { 23 | return( 24 | 25 | 26 | 27 | ); 28 | }; 29 | 30 | export default Sidebar; 31 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-test-regex.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/test-regex.js TAP no args, pull in default files, not exclusions > output 1`] = ` 9 | TAP version 13 10 | ok 1 - file.spec.js # {time} { 11 | ok 1 - this is fine 12 | 1..1 13 | # {time} 14 | } 15 | 16 | ok 2 - tests.cjs # {time} { 17 | ok 1 - this is also fine 18 | 1..1 19 | # {time} 20 | } 21 | 22 | 1..2 23 | # {time} 24 | 25 | ` 26 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-teardown-event-loop.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/teardown-event-loop.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/teardown-event-loop.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/teardown-event-loop.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - fine 22 | 1..1 23 | # {time} 24 | 25 | ` 26 | -------------------------------------------------------------------------------- /coverage-map.js: -------------------------------------------------------------------------------- 1 | const glob = require('glob') 2 | const path = require('path') 3 | module.exports = t => { 4 | const parts = path.relative(process.cwd(), path.resolve(t)).split(/\\|\//) 5 | const unit = path.basename(parts[1], '.js') 6 | if (unit === 'run') 7 | return glob.sync('bin/*.js') 8 | if (unit === 'coverage-map') 9 | return [ path.basename(__filename) ] 10 | const cov = glob.sync(`lib/${unit}.js`) 11 | if (!cov.length) 12 | return null 13 | return cov 14 | } 15 | 16 | /* istanbul ignore next */ 17 | if (module === require.main) { 18 | const tests = process.argv.length > 2 19 | ? process.argv.slice(2) 20 | : glob.sync('test/**/*.js') 21 | console.log(tests.map(t => [t, module.exports(t)])) 22 | } 23 | -------------------------------------------------------------------------------- /test/run/jsx.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | t.test('jsx', t => { 9 | const ok = tmpfile(t, 'jsx/ok.jsx', ` 10 | const React = require('react') 11 | const t = require(${tap}) 12 | const div = (
Hello
) 13 | t.pass('this is fine') 14 | `) 15 | run([ok], {}, (er, o, e) => { 16 | t.equal(er, null) 17 | t.matchSnapshot(o) 18 | t.end() 19 | }) 20 | }) 21 | 22 | t.test('running jsx thingie directly raises an error', t => { 23 | const jsx = require.resolve('../../bin/jsx.js') 24 | const {execFile} = require('child_process') 25 | execFile(process.execPath, [jsx], (er, o, e) => { 26 | t.match(er, { code: 1 }) 27 | t.end() 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-stdin.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/stdin.js TAP with file > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - cli-tests/foo.test.js # {time} { 11 | ok 1 - child # {time} { 12 | ok 1 - this is fine 13 | 1..1 14 | } 15 | 16 | 1..1 17 | # {time} 18 | } 19 | 20 | ok 2 - /dev/stdin # {time} { 21 | 1..1 22 | ok 23 | } 24 | 25 | 1..2 26 | # {time} 27 | 28 | ` 29 | -------------------------------------------------------------------------------- /test/run/setup-tap-env.js: -------------------------------------------------------------------------------- 1 | const setup = require('../../bin/run.js').setupTapEnv 2 | const t = require('../../lib/tap.js') 3 | 4 | const cases = [ 5 | [{timeout: 999}, {TAP_TIMEOUT: 999}], 6 | [{color: false}, {TAP_COLORS: '0'}], 7 | [{color: true}, {TAP_COLORS: '1'}], 8 | [{snapshot: true}, {TAP_SNAPSHOT: '1'}], 9 | [{bail: true}, {TAP_BAIL: '1'}], 10 | [{invert: true}, {TAP_GREP_INVERT: '1'}], 11 | [{grep: [/a/, /b/]}, {TAP_GREP: '/a/\n/b/'}], 12 | [{only: true}, {TAP_ONLY: '1'}], 13 | ] 14 | 15 | const env = {...process.env} 16 | cases.forEach(c => { 17 | c[0].grep = c[0].grep || [] 18 | setup(c[0]) 19 | t.match(process.env, c[1]) 20 | for (let k in c[1]) { 21 | process.env[k] = env[k] 22 | } 23 | }) 24 | t.end() 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please consider signing [the neveragain.tech pledge](http://neveragain.tech/) 2 | 3 | - Check the [issues](https://github.com/tapjs/node-tap/issues) to see 4 | stuff that is likely to be accepted. 5 | - Every patch should have a new test that fails without the patch and 6 | passes with the patch. 7 | - All tests should pass on Node 8 and above. If some tests have to be 8 | skipped for very old Node versions that's fine, but the functionality 9 | should still work as intended. 10 | - Run `npm run snap` to re-generate the output tests whenever output is 11 | changed. However, when you do this, make sure to check the change to 12 | ensure that it's what you intended, and that it didn't cause any other 13 | inadvertent changes. 14 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-plan-unsatisfied.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/plan-unsatisfied.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/plan-unsatisfied.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/plan-unsatisfied.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | 1..99 22 | # test count(0) != plan(99) 23 | # failed 1 test 24 | # {time} 25 | 26 | ` 27 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-close-even-if-exiting-hard.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/close-even-if-exiting-hard.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/close-even-if-exiting-hard.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/close-even-if-exiting-hard.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - make sure, really 22 | 1..1 23 | # {time} 24 | 25 | ` 26 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-autoend-false-with-teardown.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/autoend-false-with-teardown.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/autoend-false-with-teardown.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/autoend-false-with-teardown.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - this is fine 22 | 1..1 23 | # {time} 24 | tear it down 25 | 26 | ` 27 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-too-much.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/too-much.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/too-much.js TAP > stderr 1`] = ` 16 | 17 | Error: test count exceeds plan 18 | {STACK} 19 | { name: 'TAP', test: 'TAP', plan: 1 } 20 | 21 | ` 22 | 23 | exports[`test/tap/too-much.js TAP > stdout 1`] = ` 24 | TAP version 13 25 | 1..1 26 | ok 1 - a little 27 | # {time} 28 | 29 | ` 30 | -------------------------------------------------------------------------------- /docs/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "node": true 5 | }, 6 | "rules": { 7 | "react/prop-types": 0, 8 | "react/no-unescaped-entities": 0, 9 | "react/display-name": 0, 10 | "strict": 0, 11 | "indent": [ 12 | "error", 13 | 2 14 | ], 15 | "linebreak-style": [ 16 | "error", 17 | "unix" 18 | ], 19 | "quotes": [ 20 | "error", 21 | "single", 22 | "avoid-escape" 23 | ], 24 | "semi": [ 25 | "error", 26 | "always" 27 | ], 28 | "global-require": 0 29 | }, 30 | "settings": { 31 | "react": { 32 | "version": "detect" 33 | } 34 | }, 35 | "extends": [ 36 | "eslint:recommended", 37 | "plugin:react/recommended" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-nonparallel.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/nonparallel.js TAP > output 1`] = ` 9 | TAP version 13 10 | # Subtest: 1.js 11 | start one 12 | ok 1 - fine in 1 13 | 1..1 14 | # {time} 15 | ok 1 - 1.js # {time} 16 | 17 | # Subtest: 2.js 18 | start two 19 | ok 1 - fine in 2 20 | 1..1 21 | # {time} 22 | ok 2 - 2.js # {time} 23 | 24 | 1..2 25 | # {time} 26 | 27 | ` 28 | 29 | exports[`test/run/nonparallel.js TAP > stderr 1`] = ` 30 | 31 | ` 32 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-teardown-throw-nonerror.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/teardown-throw-nonerror.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/teardown-throw-nonerror.js TAP > stderr 1`] = ` 16 | { error: 'poop', tapCaught: 'teardown', test: 'TAP' } 17 | 18 | ` 19 | 20 | exports[`test/tap/teardown-throw-nonerror.js TAP > stdout 1`] = ` 21 | TAP version 13 22 | ok 1 - x 23 | 1..1 24 | # {time} 25 | 26 | ` 27 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-throw-unpatched.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/throw-unpatched.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/throw-unpatched.js TAP > stderr 1`] = ` 16 | 17 | {CWD}/test/tap/throw-unpatched.js:2 18 | throw new Error('not yet patched') 19 | ^ 20 | Error: not yet patched 21 | {STACK} 22 | 23 | ` 24 | 25 | exports[`test/tap/throw-unpatched.js TAP > stdout 1`] = ` 26 | 27 | ` 28 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-throw-unpatched-nonerror.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/throw-unpatched-nonerror.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/throw-unpatched-nonerror.js TAP > stderr 1`] = ` 16 | 17 | {CWD}/test/tap/throw-unpatched-nonerror.js:2 18 | throw 'not yet patched' 19 | ^ 20 | not yet patched 21 | 22 | ` 23 | 24 | exports[`test/tap/throw-unpatched-nonerror.js TAP > stdout 1`] = ` 25 | 26 | ` 27 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-tap-only.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/tap-only.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/tap-only.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/tap-only.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | # Subtest: only this one 22 | 1..0 23 | ok 1 - only this one # {time} 24 | 25 | ok 2 - not this one # SKIP filter: only 26 | 1..2 27 | # skip: 1 28 | # {time} 29 | 30 | ` 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The ISC License 2 | 3 | Copyright (c) Isaac Z. Schlueter and Contributors 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 15 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-teardown-throw.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/teardown-throw.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/teardown-throw.js TAP > stderr 1`] = ` 16 | 17 | Error: poop 18 | {STACK} 19 | { name: 'TAP', autoend: true, tapCaught: 'teardown', test: 'TAP' } 20 | 21 | ` 22 | 23 | exports[`test/tap/teardown-throw.js TAP > stdout 1`] = ` 24 | TAP version 13 25 | ok 1 - x 26 | 1..1 27 | # {time} 28 | 29 | ` 30 | -------------------------------------------------------------------------------- /test/run/executables.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | dir, 5 | t, 6 | } = require('./') 7 | const fs = require('fs') 8 | 9 | t.test('executables', { 10 | todo: process.platform === 'win32' ? 11 | 'port the shell scripts to equivalent CMD files' : false 12 | }, t => { 13 | const ok = tmpfile(t, 'exe/ok.sh', `#!/bin/sh 14 | echo 1..1 15 | echo ok 1 File with executable bit should be executed 16 | `) 17 | fs.chmodSync(ok, 0o755) 18 | const notok = tmpfile(t, 'exe/notok.sh', `!#/bin/sh 19 | echo 1..1 20 | echo not ok 1 File without executable bit should not be run 21 | exit 1 22 | `) 23 | fs.chmodSync(notok, 0o644) 24 | run(['exe', '-C'], { cwd: dir }, (er, o, e) => { 25 | t.equal(er, null) 26 | t.matchSnapshot(o) 27 | t.equal(e, '') 28 | t.end() 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-esm.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/esm.js TAP esm > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - cli-tests/esm/ok.js # {time} { 11 | ok 1 - this is fine 12 | 1..1 13 | # {time} 14 | } 15 | 16 | 1..1 17 | # {time} 18 | 19 | ` 20 | 21 | exports[`test/run/esm.js TAP mjs > must match snapshot 1`] = ` 22 | TAP version 13 23 | ok 1 - cli-tests/mjs/ok.mjs # {time} { 24 | ok 1 - this is fine 25 | 1..1 26 | # {time} 27 | } 28 | 29 | 1..1 30 | # {time} 31 | 32 | ` 33 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-flow.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/flow.js TAP flow > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - cli-tests/flow/ok.js # {time} { 11 | ok 1 - this is fine 12 | 1..1 13 | # {time} 14 | } 15 | 16 | 1..1 17 | # {time} 18 | 19 | ` 20 | 21 | exports[`test/run/flow.js TAP flow manually > must match snapshot 1`] = ` 22 | TAP version 13 23 | ok 1 - cli-tests/flow/ok2.js # {time} { 24 | ok 1 - this is fine 25 | 1..1 26 | # {time} 27 | } 28 | 29 | 1..1 30 | # {time} 31 | 32 | ` 33 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-timeout-sigterm.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/timeout-sigterm.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": null, 11 | "signal": "SIGTERM", 12 | } 13 | ` 14 | 15 | exports[`test/tap/timeout-sigterm.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/timeout-sigterm.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - fine 22 | not ok 2 - timeout! 23 | --- 24 | expired: TAP 25 | signal: SIGTERM 26 | test: TAP 27 | ... 28 | 29 | 1..2 30 | # failed 1 of 2 tests 31 | # {time} 32 | 33 | ` 34 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/index.html: -------------------------------------------------------------------------------- 1 | Index of /

Index of /


../
2 | coverage-1/                       2019-06-16T04:26:58.293Z          -
3 | test/                             2019-06-16T04:26:58.294Z          -
4 | index.html                        2019-06-16T06:26:19.758Z          0
5 | my-awesome-module-broken.js       2019-06-16T04:26:58.293Z        199
6 | my-awesome-module.js              2019-06-16T04:26:58.293Z        206
7 | package-lock.json                 2019-06-16T04:26:58.293Z       1330
8 | package.json                      2019-06-16T04:26:58.293Z        215
9 | 

-------------------------------------------------------------------------------- /test/run/test-regex.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | bin, 4 | tap, 5 | node, 6 | dir, 7 | t, 8 | run, 9 | } = require('./') 10 | 11 | t.test('no args, pull in default files, not exclusions', t => { 12 | tmpfile(t, 'file.spec.js', ` 13 | const t = require(${tap}) 14 | t.pass('this is fine') 15 | `) 16 | tmpfile(t, 'tests.cjs', ` 17 | const t = require(${tap}) 18 | t.pass('this is also fine') 19 | `) 20 | tmpfile(t, 'node_modules/bad.test.js', ` 21 | const t = require(${tap}) 22 | t.fail('should not run this') 23 | `) 24 | run([], { cwd: dir }, (er, o, e) => { 25 | t.equal(er, null) 26 | t.matchSnapshot(o, 'output') 27 | t.end() 28 | }) 29 | }) 30 | 31 | t.test('error out if loading files fails', t => { 32 | run([], { cwd: '/dev' }, (er, o, e) => { 33 | t.match(er, { code: 1 }) 34 | t.end() 35 | }) 36 | }) 37 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-throw-nonerror.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/throw-nonerror.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/throw-nonerror.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/throw-nonerror.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - this is fine 22 | not ok 2 - (unnamed test) 23 | --- 24 | error: not an error 25 | tapCaught: uncaughtException 26 | test: TAP 27 | ... 28 | 29 | 1..2 30 | # failed 1 of 2 tests 31 | # {time} 32 | 33 | ` 34 | -------------------------------------------------------------------------------- /docs/static/snapshot-example/index.html: -------------------------------------------------------------------------------- 1 | Index of /

Index of /


../
 2 | tap-snapshots/            2019-06-16T18:46:27.985Z         -
 3 | .taprc                    2019-06-16T04:26:58.284Z        16
 4 | index.js                  2019-06-16T04:26:58.284Z       101
 5 | msgtime.js                2019-06-16T04:26:58.284Z        81
 6 | msgtime.test.js           2019-06-16T04:26:58.285Z       250
 7 | test-no-snapshot.js       2019-06-16T04:26:58.286Z       130
 8 | test.js                   2019-06-16T04:26:58.286Z       118
 9 | yaml.test.js              2019-06-16T04:26:58.286Z       198
10 | 

11 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-timeout-sigterm-with-handle.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/timeout-sigterm-with-handle.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": null, 11 | "signal": "SIGTERM", 12 | } 13 | ` 14 | 15 | exports[`test/tap/timeout-sigterm-with-handle.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/timeout-sigterm-with-handle.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - fine 22 | not ok 2 - timeout! 23 | --- 24 | expired: TAP 25 | signal: SIGTERM 26 | test: TAP 27 | ... 28 | 29 | 1..2 30 | # failed 1 of 2 tests 31 | # {time} 32 | 33 | ` 34 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-not-ok.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/not-ok.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/not-ok.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/not-ok.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | not ok 1 - expected 22 | --- 23 | at: 24 | line: # 25 | column: # 26 | file: test/tap/not-ok.js 27 | source: | 28 | require('./')( 29 | t => t.fail('expected') 30 | --^ 31 | ) 32 | ... 33 | 34 | 1..1 35 | # failed 1 test 36 | # {time} 37 | 38 | ` 39 | -------------------------------------------------------------------------------- /example/long-slow-many.js: -------------------------------------------------------------------------------- 1 | var t = require('../lib/tap.js') 2 | t.plan(2) 3 | 4 | t.test('gun show', function (t) { 5 | t.plan(100) 6 | 7 | var n = 0 8 | var i = setInterval(function () { 9 | if (n % 123 === 5) { 10 | t.fail('FIRE!') 11 | t.fail('THE BUILDING IS ON FIRE') 12 | } else { 13 | t.pass('this is ok') 14 | t.pass('i am ok with how things are proceeding') 15 | } 16 | if (++n === 50) { 17 | return clearInterval(i) 18 | } 19 | }, 100) 20 | }) 21 | 22 | t.test('wondermark', function (t) { 23 | t.plan(500) 24 | var n = 0 25 | var j = setInterval(function () { 26 | if (n % 123 === 35) { 27 | t.fail('I AM EATING BREAKFAST') 28 | t.fail('FUCKING SEALIONS') 29 | } else { 30 | t.pass('excuse me') 31 | t.pass('pardon me') 32 | } 33 | if (++n === 250) { 34 | return clearInterval(j) 35 | } 36 | }, 10) 37 | }) 38 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-reporters.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/reporters.js TAP builtin reporter > stdout 1`] = ` 9 | treport output 10 | ` 11 | 12 | exports[`test/run/reporters.js TAP cli reporter > stdout 1`] = ` 13 | TAP version 13 14 | ok 1 - cli-tests/ok.js > this is fine 15 | 1..1 16 | # {time} 17 | 18 | 19 | ` 20 | 21 | exports[`test/run/reporters.js TAP react component > stdout 1`] = ` 22 | treport output 23 | ` 24 | 25 | exports[`test/run/reporters.js TAP stream reporter > stdout 1`] = ` 26 | spec output 27 | ` 28 | 29 | exports[`test/run/reporters.js TAP tmr builtin reporter > stdout 1`] = ` 30 | spec output 31 | ` 32 | -------------------------------------------------------------------------------- /docs/src/components/home/credits.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const Content = styled.div` 5 | max-width: 700px; 6 | margin: auto; 7 | padding: 20px 20px 40px; 8 | border-top: 2px solid #eee; 9 | font-style:italic; 10 | `; 11 | 12 | const P = styled.p` 13 | font-style:italic; 14 | font-size:13px; 15 | padding:0; 16 | `; 17 | 18 | const Credits = () => { 19 | return( 20 |
21 | 22 |
23 |

24 | Node-tap is created and maintained by Isaac Z. Schlueter. 26 |

27 |

28 | Website design and implementation by Tanya Brassie. 30 |

31 |
32 |
33 |
34 | ); 35 | }; 36 | 37 | export default Credits; 38 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-timeout-sigterm-many-times.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/timeout-sigterm-many-times.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": null, 11 | "signal": "SIGTERM", 12 | } 13 | ` 14 | 15 | exports[`test/tap/timeout-sigterm-many-times.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/timeout-sigterm-many-times.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - fine 22 | not ok 2 - timeout! 23 | --- 24 | expired: TAP 25 | requests: 26 | - type: FSReqCallback 27 | signal: SIGTERM 28 | test: TAP 29 | ... 30 | 31 | 1..2 32 | # failed 1 of 2 tests 33 | # {time} 34 | 35 | ` 36 | -------------------------------------------------------------------------------- /test/run/files.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | const yaml = require('tap-yaml') 8 | 9 | const one = tmpfile(t, 'one.js', ` 10 | const t = require(${tap}) 11 | t.pass('one') 12 | `) 13 | 14 | const two = tmpfile(t, 'two.js', ` 15 | const t = require(${tap}) 16 | t.pass('two') 17 | `) 18 | 19 | const three = tmpfile(t, 'two.js', ` 20 | const t = require(${tap}) 21 | t.pass('three') 22 | `) 23 | 24 | t.test('--files work like explicit positional argument', t => { 25 | t.plan(3) 26 | run([`--files=${one}`, `--files=${two}`], {}, (er, o, e) => { 27 | t.notOk(er) 28 | t.equal(e, '') 29 | t.matchSnapshot(o) 30 | }) 31 | }) 32 | 33 | t.test('--files do not override explicit positional argument', t => { 34 | t.plan(3) 35 | run([`--files=${one}`, `--files=${two}`, three], {}, (er, o, e) => { 36 | t.notOk(er) 37 | t.equal(e, '') 38 | t.matchSnapshot(o) 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /docs/src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navbar from '../components/navbar'; 3 | import styled from 'styled-components'; 4 | import {Flex} from 'rebass'; 5 | import exclamationMark from '../images/exclamation.gif'; 6 | import EncircledImage from '../components/EncircledImage'; 7 | import SEO from '../components/seo'; 8 | 9 | const Container = styled(Flex)` 10 | flex-direction: column; 11 | align-items: center; 12 | min-height: 100vh; 13 | padding-top: 80px; 14 | `; 15 | 16 | const Headline = styled.h1` 17 | margin: 10px 0 0; 18 | `; 19 | 20 | const ErrorPage = () => { 21 | return ( 22 | <> 23 | 24 | 25 | 26 |
27 | 28 |
29 | 404 30 |

Page not found

31 |
32 | 33 | ); 34 | }; 35 | 36 | export default ErrorPage; 37 | -------------------------------------------------------------------------------- /docs/src/templates/page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Layout from '../components/layout'; 3 | import {graphql} from 'gatsby'; 4 | import SEO from '../components/seo'; 5 | 6 | const Page = ({data}) => { 7 | const pageData = data.markdownRemark; 8 | const showSidebar = !pageData.fields.slug.indexOf('/docs/'); 9 | 10 | return ( 11 | <> 12 | 17 | 18 |
19 | 20 | 21 | ); 22 | }; 23 | 24 | export default Page; 25 | 26 | export const query = graphql` 27 | query($slug: String!) { 28 | markdownRemark(fields: { slug: { eq: $slug } }) { 29 | html 30 | fields { 31 | slug 32 | } 33 | frontmatter { 34 | title 35 | } 36 | } 37 | } 38 | `; 39 | -------------------------------------------------------------------------------- /scripts/snap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export TAP_SNAPSHOT=1 4 | export TAP_NO_ESM=1 5 | export TAP_BAIL=1 6 | 7 | shopt -s globstar 8 | 9 | echo 'TAP version 13' 10 | failed=0 11 | 12 | pids=() 13 | snap () { 14 | f=$1 15 | id=$2 16 | out=$(node $f 2>&1) 17 | res=$? 18 | let '++id' 19 | if [ $res != 0 ]; then 20 | failed=1 21 | echo "not ok $id - $f {" 22 | echo "$out" | sed "s|^| |g" 23 | echo "}" 24 | exit 1 25 | else 26 | echo "ok $id - $f" 27 | fi 28 | } 29 | 30 | files=(test/**/*.js) 31 | 32 | echo "1..${#files[@]}" 33 | 34 | for (( id=0 ; id < ${#files[@]} ; id++ )) do 35 | t=${files[$id]} 36 | snap $t $id & 37 | pids+=($!) 38 | if [ $failed -eq 1 ]; then 39 | break 40 | fi 41 | done 42 | 43 | for p in "${pids[@]}"; do 44 | wait $p 45 | if [ $? != 0 ]; then 46 | for q in "${pids[@]}"; do 47 | kill -SIGINT $q &>/dev/null 48 | done 49 | echo "Bail out! # failed test" 50 | break 51 | fi 52 | done 53 | -------------------------------------------------------------------------------- /docs/src/images/separator.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 12 | separator 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/run/flow.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | 9 | t.test('flow', t => { 10 | const ok = tmpfile(t, 'flow/ok.js', ` 11 | // @flow 12 | const t = require(${tap}) 13 | function square(n: number): number { 14 | return n * n; 15 | } 16 | t.pass('this is fine') 17 | `) 18 | 19 | const args = [ok, '--flow'] 20 | 21 | run(args, {}, (er, o, e) => { 22 | t.equal(er, null) 23 | t.matchSnapshot(o) 24 | t.end() 25 | }) 26 | }) 27 | 28 | t.test('flow manually', t => { 29 | const ok = tmpfile(t, 'flow/ok2.js', ` 30 | // @flow 31 | const t = require(${tap}) 32 | function square(n: number): number { 33 | return n * n; 34 | } 35 | t.pass('this is fine') 36 | `) 37 | 38 | const args = [ok, '--node-arg=--require', '--node-arg=flow-remove-types/register'] 39 | 40 | run(args, {}, (er, o, e) => { 41 | t.equal(er, null) 42 | t.matchSnapshot(o) 43 | t.end() 44 | }) 45 | }) -------------------------------------------------------------------------------- /docs/src/components/NavLinks.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link, NavLink} from './links'; 3 | 4 | const NavLinks = (props) => { 5 | return( 6 | <> 7 | {props.desktop && 8 | 13 | Docs 14 | 15 | } 16 | 20 | Tap Protocol 21 | 22 | 26 | Changelog 27 | 28 | 31 | GitHub 32 | 33 | 36 | npm 37 | 38 | 39 | ); 40 | }; 41 | 42 | export default NavLinks; 43 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-files.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/files.js TAP --files do not override explicit positional argument > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - cli-tests/two.js # {time} { 11 | ok 1 - three 12 | 1..1 13 | # {time} 14 | } 15 | 16 | 1..1 17 | # {time} 18 | 19 | ` 20 | 21 | exports[`test/run/files.js TAP --files work like explicit positional argument > must match snapshot 1`] = ` 22 | TAP version 13 23 | ok 1 - cli-tests/one.js # {time} { 24 | ok 1 - one 25 | 1..1 26 | # {time} 27 | } 28 | 29 | ok 2 - cli-tests/two.js # {time} { 30 | ok 1 - three 31 | 1..1 32 | # {time} 33 | } 34 | 35 | 1..2 36 | # {time} 37 | 38 | ` 39 | -------------------------------------------------------------------------------- /docs/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navbar from '../components/navbar'; 3 | import Hero from '../components/home/hero'; 4 | import Features from '../components/home/features'; 5 | import WhyTap from '../components/home/whyTap'; 6 | import Credits from '../components/home/credits'; 7 | import {ThemeProvider} from 'styled-components'; 8 | import {graphql} from 'gatsby'; 9 | import {theme} from '../theme'; 10 | import SEO from '../components/seo'; 11 | 12 | export default ({data}) => { 13 | return ( 14 | <> 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 | 26 | ); 27 | }; 28 | 29 | export const query = graphql` 30 | query MyQuery { 31 | markdownRemark(frontmatter: {title: {eq: "why-tap"}}) { 32 | id 33 | html 34 | } 35 | } 36 | `; 37 | -------------------------------------------------------------------------------- /lib/stdin.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const Base = require('./base.js') 3 | const ownOr = require('own-or') 4 | 5 | class Stdin extends Base { 6 | constructor (options) { 7 | options = options || {} 8 | options.name = ownOr(options, 'name', '/dev/stdin') 9 | super(options) 10 | 11 | // This has to be here for node 0.10's wonky streams 12 | this.stream = ownOr(options, 'tapStream', process.stdin) 13 | this.stream.pause() 14 | } 15 | 16 | main (cb) { 17 | this.stream.on('error', er => { 18 | er.tapCaught = 'stdinError' 19 | this.threw(er) 20 | }) 21 | this.setTimeout(this.options.timeout) 22 | this.stream.pipe(this.parser) 23 | if (this.parent) 24 | this.parent.emit('stdin', this) 25 | this.stream.resume() 26 | this.once('end', cb) 27 | } 28 | 29 | threw (er, extra, proxy) { 30 | extra = super.threw(er, extra, proxy) 31 | this.options = extra 32 | this.parser.abort(er.message, extra) 33 | this.parser.end() 34 | } 35 | } 36 | 37 | module.exports = Stdin 38 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-unhandled-promise.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/unhandled-promise.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/unhandled-promise.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/unhandled-promise.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - fine, i promise 22 | not ok 2 - broken 23 | --- 24 | at: 25 | line: # 26 | column: # 27 | file: test/tap/unhandled-promise.js 28 | source: |2 29 | t.pass('fine, i promise') 30 | Promise.reject(new Error('broken')) 31 | --^ 32 | } 33 | ) 34 | tapCaught: unhandledRejection 35 | test: TAP 36 | ... 37 | 38 | 1..2 39 | # failed 1 of 2 tests 40 | # {time} 41 | 42 | ` 43 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-tap-grep.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/tap-grep.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/tap-grep.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/tap-grep.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | # Subtest: axo 22 | ok 1 - yellow # SKIP filter: /^y$/i 23 | # Subtest: Y 24 | 1..0 25 | ok 2 - Y # {time} 26 | 27 | # Subtest: y 28 | # Subtest: this too 29 | 1..0 30 | ok 1 - this too # {time} 31 | 32 | 1..1 33 | ok 3 - y # {time} 34 | 35 | 1..3 36 | # skip: 1 37 | ok 1 - axo # {time} 38 | 39 | ok 2 - nope # SKIP filter: /x/ 40 | 1..2 41 | # skip: 1 42 | # {time} 43 | 44 | ` 45 | -------------------------------------------------------------------------------- /test/parse-test-args.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const t = require('../') 3 | const pta = require('../lib/parse-test-args.js') 4 | 5 | const fn = _ => _ 6 | function named () {} 7 | const todoCb = pta().cb 8 | 9 | // call the funcs so that they're covered also 10 | named() 11 | fn() 12 | 13 | const cases = [ 14 | ['foo', {}, fn, null, { name: 'foo', cb: fn }], 15 | [undefined, {}, fn, null, { cb: fn }], 16 | [{}, named, undefined, undefined, { cb: named, name: 'named' }], 17 | [{}, named, false, undefined, { cb: named, name: 'named' }], 18 | [named, false, undefined, null, { cb: named, name: 'named' }], 19 | ['foo', undefined, undefined, null, { name: 'foo', todo: true, cb: todoCb }], 20 | [{name: 'foo'}, fn, undefined, null, { name: 'foo', cb: fn }], 21 | [undefined, undefined, undefined, 'def', { name: 'def', todo: true, cb: todoCb }] 22 | ] 23 | 24 | cases.forEach(c => t.match(pta(c[0], c[1], c[2], c[3]), c[4])) 25 | 26 | t.throws(_ => pta(null), 27 | new TypeError('unknown argument passed to parseTestArgs: null')) 28 | 29 | t.throws(_ => pta().cb(), new Error('callback called for TODO test')) 30 | -------------------------------------------------------------------------------- /docs/src/components/EncircledImage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {theme} from '../theme'; 3 | import styled from 'styled-components'; 4 | import {Image} from 'rebass'; 5 | 6 | const Symbol = styled(Image)` 7 | width: 80px; 8 | position: absolute; 9 | top: 0; 10 | bottom: 0; 11 | left: 0; 12 | right: 0; 13 | margin: auto; 14 | `; 15 | 16 | const WhiteCircle = styled.div` 17 | width: 130px; 18 | height: 130px; 19 | background-color: ${theme.colors.white}; 20 | border-radius: 50%; 21 | margin: auto; 22 | top: 0; 23 | right: 0; 24 | left: 0; 25 | bottom: 0; 26 | position: absolute; 27 | `; 28 | 29 | const GreyCircle = styled.div` 30 | width: 180px; 31 | height: 180px; 32 | background-color: ${theme.colors.lightGrey}; 33 | border-radius: 50%; 34 | margin: auto; 35 | position: relative; 36 | `; 37 | 38 | 39 | const EncircledImage = ({image, alt}) => { 40 | return( 41 | 42 | 43 | 44 | 45 | 46 | ); 47 | }; 48 | 49 | export default EncircledImage; 50 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-uncaught-exception.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/uncaught-exception.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 1, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/uncaught-exception.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/uncaught-exception.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | ok 1 - this is fine 22 | ok 2 - i am sure things are ok 23 | not ok 3 - poop 24 | --- 25 | at: 26 | line: # 27 | column: # 28 | file: test/tap/uncaught-exception.js 29 | source: |2 30 | t.pass('this is fine') 31 | setTimeout(() => { throw new Error('poop') }) 32 | --^ 33 | t.pass('i am sure things are ok') 34 | } 35 | tapCaught: uncaughtException 36 | test: TAP 37 | ... 38 | 39 | 1..3 40 | # failed 1 of 3 tests 41 | # {time} 42 | 43 | ` 44 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-tap-grep-invert.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/tap-grep-invert.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/tap-grep-invert.js TAP > stderr 1`] = ` 16 | 17 | ` 18 | 19 | exports[`test/tap/tap-grep-invert.js TAP > stdout 1`] = ` 20 | TAP version 13 21 | # Subtest: yes this one 22 | ok 1 - Y # SKIP filter out: /^y$/i 23 | # Subtest: yellow 24 | 1..0 25 | ok 2 - yellow # {time} 26 | 27 | # Subtest: apple 28 | # Subtest: this too 29 | 1..0 30 | ok 1 - this too # {time} 31 | 32 | 1..1 33 | ok 3 - apple # {time} 34 | 35 | 1..3 36 | # skip: 1 37 | ok 1 - yes this one # {time} 38 | 39 | ok 2 - axo # SKIP filter out: /x/ 40 | 1..2 41 | # skip: 1 42 | # {time} 43 | 44 | ` 45 | -------------------------------------------------------------------------------- /test/run/ts.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | t.test('ts', t => { 9 | const ok = tmpfile(t, 'ts/ok.ts', ` 10 | import * as t from ${tap} 11 | t.pass('this is fine') 12 | `) 13 | run([ok], {}, (er, o, e) => { 14 | t.equal(er, null) 15 | t.matchSnapshot(o) 16 | t.end() 17 | }) 18 | }) 19 | 20 | t.test('tsx', t => { 21 | const ok = tmpfile(t, 'tsx/ok.tsx', ` 22 | import * as React from 'react' 23 | import * as t from ${tap} 24 | const div = (
Hello
) 25 | t.pass('this is fine') 26 | `) 27 | run([ok], {}, (er, o, e) => { 28 | t.equal(er, null) 29 | t.matchSnapshot(o) 30 | t.end() 31 | }) 32 | }) 33 | 34 | t.test('ts manually', t => { 35 | const ok = tmpfile(t, 'mixed/ok.js', ` 36 | require('./foo.ts') 37 | `) 38 | const foots = tmpfile(t, 'mixed/foo.ts', ` 39 | import * as t from ${tap} 40 | t.pass('this is fine') 41 | `) 42 | const args = [ok, foots, '--no-ts', '--node-arg=--require', '--node-arg=ts-node/register'] 43 | run(args, {}, (er, o, e) => { 44 | t.equal(er, null) 45 | t.matchSnapshot(o) 46 | t.end() 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-ts.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/ts.js TAP ts > must match snapshot 1`] = ` 9 | TAP version 13 10 | ok 1 - cli-tests/ts/ok.ts # {time} { 11 | ok 1 - this is fine 12 | 1..1 13 | # {time} 14 | } 15 | 16 | 1..1 17 | # {time} 18 | 19 | ` 20 | 21 | exports[`test/run/ts.js TAP ts manually > must match snapshot 1`] = ` 22 | TAP version 13 23 | ok 1 - cli-tests/mixed/ok.js # {time} { 24 | ok 1 - this is fine 25 | 1..1 26 | # {time} 27 | } 28 | 29 | ok 2 - cli-tests/mixed/foo.ts # {time} { 30 | ok 1 - this is fine 31 | 1..1 32 | # {time} 33 | } 34 | 35 | 1..2 36 | # {time} 37 | 38 | ` 39 | 40 | exports[`test/run/ts.js TAP tsx > must match snapshot 1`] = ` 41 | TAP version 13 42 | ok 1 - cli-tests/tsx/ok.tsx # {time} { 43 | ok 1 - this is fine 44 | 1..1 45 | # {time} 46 | } 47 | 48 | 1..1 49 | # {time} 50 | 51 | ` 52 | -------------------------------------------------------------------------------- /docs/src/content/docs/configuring/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Configuring tap" 3 | section: 4 4 | redirect_from: 5 | - /configuring/ 6 | - /configuring 7 | --- 8 | # Configuring Tap 9 | 10 | There are 3 main ways to configure tap to behave the way you want it to. 11 | 12 | The first, and most straightforward, is to set a flag on the command line. 13 | 14 | The next is to create a `.taprc` file in the current working directory 15 | (typically the root of your project, where your `package.json` lives). This file is interpreted as yaml, and can contain any options that can also be set on the command line. 16 | 17 | To see what should be put in a yaml config file, you can run `tap 18 | --dump-config` to have it spit out its defaults. If `--dump-config` is 19 | combined with other options, then this will show the resulting configuration. 20 | 21 | You can change the location of the `.taprc` file by setting the `--rcfile` 22 | command-line option. 23 | 24 | Lastly, tap will look for a `tap` section in a `package.json` file in the 25 | current working directory, and use that object as as source of configuration as 26 | well. 27 | 28 | Information about all of the various config options can be obtained by running 29 | [`tap -h`](/docs/cli/). 30 | -------------------------------------------------------------------------------- /docs/src/images/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 16 | 17 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-node-debug-tap.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/node-debug-tap.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/node-debug-tap.js TAP > stderr 1`] = ` 16 | TAP {pid} TAP: END implicit=true 17 | TAP {pid} TAP: PROCESSING(TAP) 3 18 | TAP {pid} TAP: > STRING 19 | TAP {pid} TAP: LINE "TAP version 13\\n" 20 | TAP {pid} TAP: < already processing 21 | TAP {pid} TAP: > STRING 22 | TAP {pid} TAP: LINE "1..0\\n" 23 | TAP {pid} TAP: > METHOD 24 | TAP {pid} TAP: END implicit=true 25 | TAP {pid} TAP: < already processing 26 | TAP {pid} TAP: > EOF TAP 27 | TAP {pid} TAP: ONCOMPLETE "TAP" {"ok":true,"count":0,"pass":0,"fail":0,"bailout":false,"todo":0,"skip":0,"plan":{"start":1,"end":0,"skipAll":true,"skipReason":"","comment":""},"failures":[],"time":null} 28 | TAP {pid} TAP: done processing [] false 29 | 30 | ` 31 | 32 | exports[`test/tap/node-debug-tap.js TAP > stdout 1`] = ` 33 | TAP version 13 34 | 1..0 35 | # {time} 36 | 37 | ` 38 | -------------------------------------------------------------------------------- /docs/src/components/links.js: -------------------------------------------------------------------------------- 1 | import styled, {css} from 'styled-components'; 2 | import {Link as GatsbyLink} from 'gatsby'; 3 | import {theme} from '../theme'; 4 | 5 | const navLinkStyles = css` 6 | padding: 5px 10px; 7 | margin: 0 5px; 8 | line-height: 1.5; 9 | font-weight: 600; 10 | text-decoration: none; 11 | font-size: 14px; 12 | letter-spacing: 1px; 13 | transition: text-shadow 1s; 14 | display: block; 15 | font-family: Titillium Web, monospace; 16 | color: ${theme.colors.black}; 17 | 18 | &:hover, &:active, &:focus { 19 | color: ${theme.colors.blue}; 20 | } 21 | `; 22 | 23 | export const NavLink = styled(GatsbyLink)` 24 | ${navLinkStyles}; 25 | `; 26 | 27 | export const Link = styled.a` 28 | ${navLinkStyles}; 29 | `; 30 | 31 | export const buttonLinkStyles = css` 32 | color: #ffffff; 33 | background-color: ${theme.colors.lightFushia}; 34 | width: auto; 35 | text-decoration: none; 36 | text-align: center; 37 | border-radius: 40px; 38 | padding: 15px; 39 | font-size: 14px; 40 | `; 41 | 42 | export const ButtonLink = styled(GatsbyLink)` 43 | ${buttonLinkStyles} 44 | display: block; 45 | width: 150px; 46 | margin: 20px auto; 47 | transition: background-color .5s; 48 | 49 | &:hover, &:active, &:focus { 50 | color: ${theme.colors.white}; 51 | background-color: ${theme.colors.fushia}; 52 | } 53 | `; 54 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | Node-tap website design and content (c) Isaac Z. Schlueter and Tanya Brassie. 2 | All rights reserved. 3 | 4 | Gatsby platform used according to terms of MIT license, shown below: 5 | 6 | MIT License 7 | 8 | Copyright (c) 2018 gatsbyjs 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | -------------------------------------------------------------------------------- /docs/src/components/mobileNavbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import {theme} from '../theme'; 4 | import DocLinks from './DocLinks'; 5 | import closeIcon from '../images/close.svg'; 6 | import NavLinks from './NavLinks'; 7 | import {Flex} from 'rebass'; 8 | 9 | const Container = styled.div` 10 | background-color: ${theme.colors.white}; 11 | min-height: 100vh; 12 | position: absolute; 13 | box-shadow: 1px 0 10px 1px #33333330; 14 | top: 0; 15 | bottom: 0; 16 | left: 0; 17 | overflow-y: scroll; 18 | max-width: 250px; 19 | padding: 50px 20px 0px; 20 | `; 21 | 22 | const CloseButton = styled.button` 23 | border: none; 24 | background-image: url(${closeIcon}); 25 | background-repeat: no-repeat; 26 | height: 20px; 27 | width: 20px; 28 | position: absolute; 29 | top: 20px; 30 | right: 20px; 31 | cursor: pointer; 32 | background-color: transparent; 33 | `; 34 | 35 | const NavLinkContainer = styled(Flex)` 36 | border-top: 1px solid ${theme.colors.red}; 37 | padding-top: 10px; 38 | margin-top: 10px; 39 | margin-bottom: 100px; 40 | `; 41 | 42 | const MobileNavbar = (props) => { 43 | return( 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ); 52 | }; 53 | 54 | export default MobileNavbar; -------------------------------------------------------------------------------- /docs/gatsby-node.js: -------------------------------------------------------------------------------- 1 | const {createFilePath} = require('gatsby-source-filesystem'); 2 | const path = require('path'); 3 | 4 | // creating a new field that graphql will pick up 5 | exports.onCreateNode = ({node, getNode, actions}) => { 6 | const {createNodeField} = actions; 7 | if (node.internal.type === 'MarkdownRemark') { 8 | const slug = createFilePath({node, getNode, basePath: 'content'}); 9 | createNodeField({ 10 | node, 11 | name: 'slug', 12 | value: slug, 13 | }); 14 | } 15 | }; 16 | 17 | // actions is an object with a lot of action properties 18 | exports.createPages = ({graphql, actions}) => { 19 | // plucking create page from that action object and uses it below 20 | const {createPage} = actions; 21 | //returning graphql query that is a promise and creates a page for each 22 | //node that is returned from the query 23 | return graphql(` 24 | { 25 | allMarkdownRemark { 26 | edges { 27 | node { 28 | id 29 | fields { 30 | slug 31 | } 32 | html 33 | } 34 | } 35 | } 36 | } 37 | `).then(result => { 38 | result.data.allMarkdownRemark.edges.forEach(({node}) => { 39 | createPage({ 40 | path: node.fields.slug, 41 | component: path.resolve('./src/templates/page.js'), 42 | context: { 43 | slug: node.fields.slug, 44 | } 45 | }); 46 | }); 47 | }); 48 | }; 49 | -------------------------------------------------------------------------------- /docs/src/components/DocLinks.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {StaticQuery, graphql} from 'gatsby'; 3 | import {NavLink} from './links'; 4 | import {Flex, Box} from 'rebass'; 5 | 6 | const DocLinks = ({data}) => { 7 | const linkArray = data.allMarkdownRemark.edges; 8 | const sortedArray = linkArray.sort((a, b) => (a.node.frontmatter.section - b.node.frontmatter.section)); 9 | 10 | return( 11 | <> 12 | 13 | {sortedArray.map((link, i) => ( 14 | 15 | 19 | {link.node.frontmatter.title} 20 | 21 | 22 | ))} 23 | 24 | 25 | ); 26 | }; 27 | 28 | export default props => ( 29 | } 48 | /> 49 | ); 50 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-parallel.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/parallel.js TAP > output 1`] = ` 9 | TAP version 13 10 | ok 1 - p/y/1.js # {time} { 11 | ok 1 - one 12 | 1..1 13 | # {time} 14 | } 15 | 16 | ok 2 - p/y/2.js # {time} { 17 | ok 1 - 2 18 | 1..1 19 | # {time} 20 | } 21 | 22 | # Subtest: q/b/f1.js 23 | ok 1 - a/b 24 | 1..1 25 | # {time} 26 | ok 3 - q/b/f1.js # {time} 27 | 28 | # Subtest: q/b/f2.js 29 | ok 1 - c/d 30 | 1..1 31 | # {time} 32 | ok 4 - q/b/f2.js # {time} 33 | 34 | # Subtest: r/y/1.js 35 | ok 1 - one 36 | 1..1 37 | # {time} 38 | ok 5 - r/y/1.js # {time} 39 | 40 | # Subtest: r/y/2.js 41 | ok 1 - 2 42 | 1..1 43 | # {time} 44 | ok 6 - r/y/2.js # {time} 45 | 46 | ok 7 - z/y/1.js # {time} { 47 | ok 1 - one 48 | 1..1 49 | # {time} 50 | } 51 | 52 | ok 8 - z/y/2.js # {time} { 53 | ok 1 - 2 54 | 1..1 55 | # {time} 56 | } 57 | 58 | 1..8 59 | # {time} 60 | 61 | ` 62 | 63 | exports[`test/run/parallel.js TAP > stderr 1`] = ` 64 | start 65 | start 66 | end 67 | end 68 | f1 69 | f2 70 | ry1 71 | ry1 72 | ry2 73 | ry2 74 | start 75 | start 76 | end 77 | end 78 | 79 | ` 80 | -------------------------------------------------------------------------------- /tap-snapshots/test-clean-yaml-object.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/clean-yaml-object.js TAP diff stuff > another weird one 1`] = ` 9 | Object { 10 | "found": "Object {\\n \\"a\\": 1,\\n}", 11 | "wanted": Object { 12 | "a": 1, 13 | }, 14 | } 15 | ` 16 | 17 | exports[`test/clean-yaml-object.js TAP diff stuff > objects that do not strictly match 1`] = ` 18 | Object { 19 | "comparator": "===", 20 | "diff": "--- expected\\n+++ actual\\n@@ -1,3 +1,3 @@\\n Object {\\n- \\"a\\": \\"1\\",\\n+ \\"a\\": 1,\\n }\\n", 21 | } 22 | ` 23 | 24 | exports[`test/clean-yaml-object.js TAP diff stuff > string that differ 1`] = ` 25 | Object { 26 | "comparator": "===", 27 | "diff": "--- expected\\n+++ actual\\n@@ -1,1 +1,1 @@\\n-world\\n+hello\\n", 28 | } 29 | ` 30 | 31 | exports[`test/clean-yaml-object.js TAP diff stuff > this one is weird 1`] = ` 32 | Object { 33 | "found": Object { 34 | "a": 1, 35 | }, 36 | "wanted": "Object {\\n \\"a\\": 1,\\n}", 37 | } 38 | ` 39 | 40 | exports[`test/clean-yaml-object.js TAP string diffs > must match snapshot 1`] = ` 41 | Object { 42 | "diff": "--- expected\\n+++ actual\\n@@ -1,5 +1,2 @@\\n-a big\\n hello\\n world\\n-string\\n-\\n", 43 | } 44 | ` 45 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-awesome-module", 3 | "version": "1.2.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/runtime": { 8 | "version": "7.4.3", 9 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz", 10 | "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==", 11 | "requires": { 12 | "regenerator-runtime": "^0.13.2" 13 | } 14 | }, 15 | "regenerator-runtime": { 16 | "version": "0.13.2", 17 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", 18 | "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" 19 | }, 20 | "tap-yaml": { 21 | "version": "1.0.0", 22 | "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-1.0.0.tgz", 23 | "integrity": "sha512-Rxbx4EnrWkYk0/ztcm5u3/VznbyFJpyXO12dDBHKWiDVxy7O2Qw6MRrwO5H6Ww0U5YhRY/4C/VzWmFPhBQc4qQ==", 24 | "requires": { 25 | "yaml": "^1.5.0" 26 | } 27 | }, 28 | "yaml": { 29 | "version": "1.5.0", 30 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.5.0.tgz", 31 | "integrity": "sha512-nKxSWOa7vxAP2pikrGxbkZsG/garQseRiLn9mIDjzwoQsyVy7ZWIpLoARejnINGGLA4fttuzRFFNxxbsztdJgw==", 32 | "requires": { 33 | "@babel/runtime": "^7.4.3" 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tap-snapshots/test-tap-tap-debug-1.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/tap/tap-debug-1.js TAP > exit status 1`] = ` 9 | Object { 10 | "code": 0, 11 | "signal": null, 12 | } 13 | ` 14 | 15 | exports[`test/tap/tap-debug-1.js TAP > stderr 1`] = ` 16 | TAP {pid} TAP: PROCESSING(TAP) 2 17 | TAP {pid} TAP: > STRING 18 | TAP {pid} TAP: LINE "TAP version 13\\n" 19 | TAP {pid} TAP: < already processing 20 | TAP {pid} TAP: > STRING 21 | TAP {pid} TAP: LINE "# this is fine\\n" 22 | TAP {pid} TAP: done processing [] false 23 | TAP {pid} TAP: PROCESSING(TAP) 1 24 | TAP {pid} TAP: > METHOD 25 | TAP {pid} TAP: END implicit=true 26 | TAP {pid} TAP: END(TAP) implicit plan 0 27 | TAP {pid} TAP: END implicit=true 28 | TAP {pid} TAP: < already processing 29 | TAP {pid} TAP: > STRING 30 | TAP {pid} TAP: LINE "1..0\\n" 31 | TAP {pid} TAP: > EOF TAP 32 | TAP {pid} TAP: ONCOMPLETE "TAP" {"ok":true,"count":0,"pass":0,"fail":0,"bailout":false,"todo":0,"skip":0,"plan":{"start":1,"end":0,"skipAll":true,"skipReason":"","comment":""},"failures":[],"time":null} 33 | TAP {pid} TAP: done processing [] false 34 | 35 | ` 36 | 37 | exports[`test/tap/tap-debug-1.js TAP > stdout 1`] = ` 38 | TAP version 13 39 | # this is fine 40 | 1..0 41 | # {time} 42 | 43 | ` 44 | -------------------------------------------------------------------------------- /test/run/stdin.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | const fs = require('fs') 9 | const tapcode = 'TAP version 13\n1..1\nok\n' 10 | 11 | t.test('with output file', t => { 12 | const c = run(['-', '-c', '-Rspec', '-ofoo.txt', '--cov'], { env: { 13 | TAP: '0' 14 | }}, (er, o, e) => { 15 | t.equal(er, null) 16 | t.equal(e, '') 17 | t.match(o, /✓|√/) 18 | t.equal(fs.readFileSync('foo.txt', 'utf8'), tapcode) 19 | fs.unlinkSync('foo.txt') 20 | t.end() 21 | }) 22 | c.stdin.end(tapcode) 23 | }) 24 | 25 | t.test('no output file', t => { 26 | const c = run(['-', '--only', '-gx', '-iC', '-Rclassic'], { env: { 27 | TAP: '0' 28 | }}, (er, o, e) => { 29 | t.equal(er, null) 30 | t.equal(e, '') 31 | t.match(o, /total \.+ 1\/1/) 32 | t.throws(() => fs.statSync('foo.txt')) 33 | t.end() 34 | }) 35 | c.stdin.end(tapcode) 36 | }) 37 | 38 | t.test('with file', t => { 39 | const foo = tmpfile(t, 'foo.test.js', ` 40 | 'use strict' 41 | require(${tap}).test('child', t => { 42 | t.pass('this is fine') 43 | t.end() 44 | }) 45 | `) 46 | const args = ['-', foo, '-CRclassic', '-ofoo.txt'] 47 | const c = run(args, { env: { TAP: 0, TAP_BUFFER: 1 }}, (er, o, e) => { 48 | t.equal(er, null) 49 | t.matchSnapshot(fs.readFileSync('foo.txt', 'utf8')) 50 | t.match(o, /foo.test.js \.+ 1\/1.*\n\/dev\/stdin \.+ 1\/1\n/) 51 | fs.unlinkSync('foo.txt') 52 | t.end() 53 | }) 54 | c.stdin.end(tapcode) 55 | }) 56 | -------------------------------------------------------------------------------- /docs/src/content/docs/tap-files/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "TAP Output Files" 3 | section: 11 4 | redirect_from: 5 | - /tap-files/ 6 | - /tap-files 7 | --- 8 | 9 | # Working with TAP Output Files 10 | 11 | Sometimes, you may want to run tests, and view the output in a nice 12 | human-readable way, but save the raw [TAP](/tap-protocol/) files for later replay 13 | or analysis, or feeding into some other system in a CI build toolchain. 14 | 15 | There are two ways to do this with tap: as a single file, or as many files. 16 | 17 | ## All One: `--output-file=` 18 | 19 | Specify `-o` or `--output-file=` to dump the entire test 20 | suite to a single file as raw TAP. 21 | 22 | To parse this and spit out a [report](/docs/reporting/), you can pipe the single 23 | file into a new tap invocation. For example: 24 | 25 | ``` 26 | tap -o file.tap 27 | cat file.tap | tap - 28 | ``` 29 | 30 | ## Multiple Files: `--output-dir=` 31 | 32 | To create multiple smaller files, specify `-d` or `--output-dir=`. 33 | The resulting TAP files will be the name of the test file plus `.tap`, in 34 | otherwise the same directory structure. 35 | 36 | You can then later load those into tap to print a report by executing them as 37 | if they were tests. For example: 38 | 39 | ``` 40 | # run tests, dump raw output to dir 41 | tap -d output-dir 42 | # run all the tap files in the dir, print a report 43 | tap output-dir 44 | ``` 45 | 46 | Of course, you may also find these files useful in various other TAP-consuming 47 | tools. 48 | -------------------------------------------------------------------------------- /test/snapshot.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const t = require('../') 3 | const Snapshot = require('../lib/snapshot.js') 4 | const rimraf = require('rimraf') 5 | const mkdirp = require('mkdirp') 6 | const path = require('path') 7 | const dir = path.resolve(__dirname, 'snapshot') 8 | const fs = require('fs') 9 | 10 | t.test('cleanup first', t => { 11 | rimraf.sync(dir) 12 | mkdirp.sync(dir) 13 | process.chdir(dir) 14 | t.end() 15 | }) 16 | 17 | t.test('actual test', t => { 18 | t.comment('not using subtests, because snapshots are per-test') 19 | 20 | t.test('checking snapshot without creating throws', t => { 21 | const s = new Snapshot(t) 22 | t.throws(_ => s.read('asdf', 'asdf')) 23 | t.end() 24 | }) 25 | 26 | const s = new Snapshot(t) 27 | t.comment('create some snapshots') 28 | s.snap(fs.readFileSync(__filename, 'utf8'), 'this file') 29 | s.snap('this is fine', 'a statement of acceptance') 30 | s.save() 31 | 32 | t.comment('now check that the snapshots are valid') 33 | const ss = new Snapshot(t) 34 | t.equal(fs.readFileSync(__filename, 'utf8'), ss.read('this file')) 35 | t.equal('this is fine', ss.read('a statement of acceptance')) 36 | t.throws(_ => ss.read('this is not in the file')) 37 | 38 | t.comment('saving without snapping anything removes the file') 39 | const sss = new Snapshot(t) 40 | sss.save() 41 | t.throws(_ => fs.statSync(sss.file), 'file is gone') 42 | 43 | t.end() 44 | }) 45 | 46 | t.test('cleanup after', t => { 47 | rimraf.sync(dir) 48 | process.chdir(__dirname) 49 | t.end() 50 | }) 51 | -------------------------------------------------------------------------------- /lib/point.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | const binpath = path.resolve(__dirname, '../bin') 5 | const util = require('util') 6 | const diags = require('./diags.js') 7 | 8 | class TestPoint { 9 | constructor (ok, message, extra) { 10 | if (typeof ok !== 'boolean') 11 | throw new TypeError('ok must be boolean') 12 | 13 | if (typeof message !== 'string') 14 | throw new TypeError('message must be a string') 15 | 16 | extra = extra || {} 17 | 18 | this.ok = ok ? 'ok ' : 'not ok ' 19 | this.message = tpMessage(message.trim(), extra) 20 | } 21 | } 22 | 23 | const tpMessage = (message, extra) => { 24 | if (message) 25 | message = ' - ' + message 26 | 27 | // replace \r\n with one space, \t with 2, separately 28 | message = message.replace(/[\n\r]/g, ' ').replace(/\t/g, ' ') 29 | 30 | if (extra.skip) { 31 | message += ' # SKIP' 32 | if (typeof extra.skip === 'string') 33 | message += ' ' + extra.skip 34 | } else if (extra.todo) { 35 | message += ' # TODO' 36 | if (typeof extra.todo === 'string') 37 | message += ' ' + extra.todo 38 | } else if (extra.time) 39 | message += ' # time=' + extra.time + 'ms' 40 | 41 | const diagYaml = extra.diagnostic ? diags(extra) : '' 42 | message += diagYaml 43 | 44 | if (extra.tapChildBuffer || extra.tapChildBuffer === '') { 45 | if (!diagYaml) 46 | message += ' ' 47 | message += '{\n' + extra.tapChildBuffer.trimRight() + '\n}\n' 48 | } 49 | 50 | message += '\n' 51 | 52 | return message 53 | } 54 | 55 | module.exports = TestPoint 56 | -------------------------------------------------------------------------------- /test/stack.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const t = require('../') 3 | const path = require('path') 4 | 5 | t.test('in tapdir, no envs', t => { 6 | delete require.cache[require.resolve('../lib/stack.js')] 7 | process.chdir(path.resolve(__dirname, '..')) 8 | process.env.TAP_DEV_LONGSTACK = 0 9 | process.env.TAP_DEV_SHORTSTACK = 0 10 | const stack = require('../lib/stack.js').captureString() 11 | t.match(stack, /test[\/\\]stack\.js:\w+:\w+\)\n/) 12 | t.notMatch(stack, '\.node-spawn-wrap') 13 | t.end() 14 | }) 15 | 16 | t.test('in ~, no envs', t => { 17 | delete require.cache[require.resolve('../lib/stack.js')] 18 | process.chdir(process.env.HOME) 19 | process.env.TAP_DEV_LONGSTACK = 0 20 | process.env.TAP_DEV_SHORTSTACK = 0 21 | const stack = require('../lib/stack.js').captureString() 22 | t.equal(stack, '') 23 | t.end() 24 | }) 25 | 26 | t.test('in home, longstack', t => { 27 | delete require.cache[require.resolve('../lib/stack.js')] 28 | process.chdir(process.env.HOME) 29 | process.env.TAP_DEV_LONGSTACK = 1 30 | process.env.TAP_DEV_SHORTSTACK = 0 31 | const stack = require('../lib/stack.js').captureString() 32 | t.match(stack, /test[\/\\]stack\.js:\w+:\w+\)\n/) 33 | t.notMatch(stack, '\.node-spawn-wrap') 34 | t.end() 35 | }) 36 | 37 | t.test('in tapdir, shortstack', t => { 38 | delete require.cache[require.resolve('../lib/stack.js')] 39 | process.chdir(path.resolve(__dirname, '..')) 40 | process.env.TAP_DEV_LONGSTACK = 0 41 | process.env.TAP_DEV_SHORTSTACK = 1 42 | const stack = require('../lib/stack.js').captureString() 43 | t.equal(stack, '') 44 | t.end() 45 | }) 46 | -------------------------------------------------------------------------------- /test/tap/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const node = process.execPath 3 | 4 | if (module === require.main) 5 | require('../../lib/tap.js').pass('just the index') 6 | 7 | process.env.TAP_DEV_SHORTSTACK = '1' 8 | 9 | module.exports = (...test) => { 10 | if (process.argv[2] === 'runtest') { 11 | // run the init function _before_ loading the root tap object 12 | if (test.length === 2) { 13 | test[0]() 14 | test[1](require('../../lib/tap.js')) 15 | } else 16 | test[0](require('../../lib/tap.js')) 17 | } else { 18 | const spawn = require('child_process').spawn 19 | const env = Object.keys(process.env).reduce((env, k) => { 20 | env[k] = env[k] || process.env[k] 21 | return env 22 | }, { TAP_BAIL: '0', TAP_BUFFER: '0' }) 23 | const t = require('../../lib/tap.js') 24 | const cs = require('../clean-stacks.js') 25 | t.cleanSnapshot = str => cs(str).replace(/[^\n]*DEP0018[^\n]*\n/g, '') 26 | t.plan(3) 27 | const c = spawn(node, [process.argv[1], 'runtest'], { env: env }) 28 | let out = '' 29 | c.stdout.on('data', c => out += c) 30 | let err = '' 31 | c.stderr.on('data', c => err += c) 32 | c.on('close', (code, signal) => { 33 | t.matchSnapshot({ 34 | code: code, 35 | signal: signal 36 | }, 'exit status') 37 | t.matchSnapshot(out, 'stdout') 38 | t.matchSnapshot( 39 | err.split('\n') 40 | // Remove node.js 13.0.0+ message: 41 | .filter(a => a !== '(Use `node --trace-uncaught ...` to show where the exception was thrown)') 42 | .join('\n'), 43 | 'stderr' 44 | ) 45 | }) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/parse-test-args.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const typeOf = arg => 3 | typeof arg === 'object' ? (arg ? 'object' : 'null') 4 | : typeof arg 5 | 6 | module.exports = (name_, extra_, cb_, defaultName) => { 7 | let name 8 | let extra 9 | let cb 10 | 11 | const args = [name_, extra_, cb_] 12 | 13 | // this only works if it's literally the 4th argument. 14 | // used internally. 15 | defaultName = defaultName || '' 16 | 17 | for (let i = 0; i < 3 && i < args.length; i++) { 18 | const arg = args[i] 19 | const type = typeOf(arg) 20 | if (name === undefined && (type === 'string' || type === 'number')) 21 | name = '' + arg 22 | else if (type === 'object') { 23 | extra = arg 24 | if (name === undefined) 25 | name = null 26 | } else if (type === 'function') { 27 | if (extra === undefined) 28 | extra = {} 29 | if (name === undefined) 30 | name = null 31 | cb = arg 32 | } else if (arg === false) { 33 | // it's handy while developing to put a ! in front of a 34 | // function to temporarily make a test todo 35 | continue 36 | } else if (type !== 'undefined') 37 | throw new TypeError('unknown argument passed to parseTestArgs: ' + type) 38 | } 39 | 40 | if (!extra) 41 | extra = {} 42 | 43 | if (!cb && defaultName !== '/dev/stdin') 44 | extra.todo = extra.todo || true 45 | 46 | if (!name && extra.name) 47 | name = extra.name 48 | 49 | if (!name && cb && cb.name) 50 | name = cb.name 51 | 52 | name = name || defaultName 53 | extra.name = name 54 | extra.cb = cb || todoCb 55 | return extra 56 | } 57 | 58 | const todoCb = () => { 59 | throw new Error('callback called for TODO test') 60 | } 61 | -------------------------------------------------------------------------------- /tap-snapshots/test-watch.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/watch.js TAP run tests on changes change a file > logs 1`] = ` 9 | initial test run 10 | - {TAPDIR}/bin/run.js 11 | - 1.test.js 12 | - 2.test.js 13 | - 3.test.js 14 | - 4.test.js 15 | - --watch 16 | - --no-watch 17 | 18 | change ko.js 19 | running tests 20 | - 4.test.js 21 | 22 | 23 | ` 24 | 25 | exports[`test/watch.js TAP run tests on changes change a file > spawn test run on change 1`] = ` 26 | 4.test.js 27 | 28 | ` 29 | 30 | exports[`test/watch.js TAP run tests on changes change a file mid-test > logs 1`] = ` 31 | change 1.test.js 32 | test in progress, queuing for next run 33 | running tests 34 | - 1.test.js 35 | 36 | 37 | ` 38 | 39 | exports[`test/watch.js TAP run tests on changes change a file mid-test > spawn queued test 1`] = ` 40 | 1.test.js 41 | 42 | ` 43 | 44 | exports[`test/watch.js TAP run tests on changes initial test > logs 1`] = ` 45 | 46 | ` 47 | 48 | exports[`test/watch.js TAP run tests on changes initial test > spawn initial test run 1`] = ` 49 | false 50 | ` 51 | 52 | exports[`test/watch.js TAP run tests on changes new file added > log after spawn 1`] = ` 53 | change new.js 54 | running tests 55 | - 3.test.js 56 | 57 | 58 | ` 59 | 60 | exports[`test/watch.js TAP run tests on changes new file added > logs 1`] = ` 61 | 62 | ` 63 | 64 | exports[`test/watch.js TAP run tests on changes new file added > spawn test for new file 1`] = ` 65 | 3.test.js 66 | 67 | ` 68 | -------------------------------------------------------------------------------- /test/fixture.js: -------------------------------------------------------------------------------- 1 | const t = require('../') 2 | const Fixture = require('../lib/fixture.js') 3 | 4 | const dir = t.testdirName 5 | require('rimraf').sync(dir) 6 | 7 | const f = new Fixture('file', 'bar') 8 | t.match(f, { 9 | type: 'file', 10 | content: 'bar', 11 | constructor: Fixture, 12 | }) 13 | t.equal(f.toString(), '[object Fixture]') 14 | 15 | t.throws(() => new Fixture('foo', 'bar'), { 16 | message: 'invalid fixture type: foo' 17 | }) 18 | 19 | t.throws(() => Fixture.make(`${dir}/nope`, 1234), { 20 | message: 'invalid fixture type: 1234' 21 | }) 22 | 23 | t.throws(() => new Fixture('dir', 'not an object'), { 24 | message: 'dir fixture must have object content' 25 | }) 26 | t.throws(() => new Fixture('link'), { 27 | message: 'link fixture must have string target' 28 | }) 29 | t.throws(() => new Fixture('symlink'), { 30 | message: 'symlink fixture must have string target' 31 | }) 32 | t.throws(() => new Fixture('file'), { 33 | message: 'file fixture must have string/buffer content' 34 | }) 35 | 36 | Fixture.make(dir, { 37 | file: 'content', 38 | dir: {}, 39 | symlink: new Fixture('symlink', 'file'), 40 | dirlink: new Fixture('symlink', 'dir'), 41 | link: new Fixture('link', 'file'), 42 | dir: new Fixture('dir', {}), 43 | noexist: new Fixture('symlink', 'non-existent-file'), 44 | }) 45 | const fs = require('fs') 46 | t.ok(fs.statSync(dir).isDirectory(), 'dir is a dir') 47 | t.equal(fs.readFileSync(`${dir}/file`, 'utf8'), 'content', 'file written') 48 | t.match(fs.statSync(`${dir}/link`), fs.statSync(`${dir}/file`), 49 | 'hardlink is hard link') 50 | t.equal(fs.readlinkSync(`${dir}/symlink`), 'file', 'symlink is symlink') 51 | t.ok(fs.statSync(`${dir}/dir`).isDirectory(), 'subdir is a dir') 52 | 53 | require('rimraf').sync(dir) 54 | -------------------------------------------------------------------------------- /docs/src/images/hamburger.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 11 | 12 | 16 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter-hello-world", 3 | "private": true, 4 | "description": "A simplified bare-bones starter for Gatsby", 5 | "version": "0.1.0", 6 | "license": "MIT", 7 | "scripts": { 8 | "build": "gatsby build", 9 | "develop": "gatsby develop", 10 | "format": "prettier --write src/**/*.{js,jsx}", 11 | "start": "npm run develop", 12 | "serve": "gatsby serve", 13 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"" 14 | }, 15 | "dependencies": { 16 | "babel-plugin-styled-components": "^1.10.1", 17 | "gatsby": "^2.8.2", 18 | "gatsby-plugin-catch-links": "^2.0.15", 19 | "gatsby-plugin-manifest": "^2.2.0", 20 | "gatsby-plugin-meta-redirect": "^1.1.1", 21 | "gatsby-plugin-offline": "^2.2.0", 22 | "gatsby-plugin-prefetch-google-fonts": "^1.4.2", 23 | "gatsby-plugin-react-helmet": "^3.1.0", 24 | "gatsby-plugin-styled-components": "^3.0.7", 25 | "gatsby-redirect-from": "^0.2.1", 26 | "gatsby-remark-autolink-headers": "^2.0.18", 27 | "gatsby-remark-prismjs": "^3.2.9", 28 | "gatsby-source-filesystem": "^2.0.38", 29 | "gatsby-transformer-remark": "^2.3.12", 30 | "prismjs": "^1.16.0", 31 | "react": "^16.8.6", 32 | "react-dom": "^16.8.6", 33 | "react-helmet": "^5.2.1", 34 | "rebass": "^3.1.1", 35 | "styled-components": "^4.3.1" 36 | }, 37 | "devDependencies": { 38 | "babel-eslint": "^10.0.1", 39 | "eslint": "^5.16.0", 40 | "eslint-loader": "^2.1.2", 41 | "eslint-plugin-import": "^2.17.3", 42 | "eslint-plugin-react": "^7.13.0", 43 | "gatsby-plugin-eslint": "^2.0.5", 44 | "prettier": "^1.17.1" 45 | }, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/gatsbyjs/gatsby-starter-hello-world" 49 | }, 50 | "bugs": { 51 | "url": "https://github.com/gatsbyjs/gatsby/issues" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tap-snapshots/test-run-basic.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/run/basic.js TAP --parser-version > output 1`] = ` 9 | 10.0.1 10 | 11 | ` 12 | 13 | exports[`test/run/basic.js TAP --versions > output 1`] = ` 14 | tap: {version} 15 | tap-parser: {version} 16 | nyc: {version} 17 | tap-yaml: {version} 18 | treport: {version} 19 | tcompare: {version} 20 | 21 | 22 | ` 23 | 24 | exports[`test/run/basic.js TAP basic test run > ok.js output 1`] = ` 25 | TAP version 13 26 | ok 1 - cli-tests/ok.js # {time} { 27 | ok 1 - this is fine 28 | 1..1 29 | # {time} 30 | } 31 | 32 | 1..1 33 | # {time} 34 | 35 | ` 36 | 37 | exports[`test/run/basic.js TAP ignored files > stdout 1`] = ` 38 | TAP version 13 39 | ok 1 - test/ok.js # {time} { 40 | ok 1 - this is fine 41 | 1..1 42 | # {time} 43 | } 44 | 45 | 1..1 46 | # {time} 47 | 48 | ` 49 | 50 | exports[`test/run/basic.js TAP ignored files > stdout 2`] = ` 51 | 52 | ` 53 | 54 | exports[`test/run/basic.js TAP nonexistent file > stderr 1`] = ` 55 | 56 | ` 57 | 58 | exports[`test/run/basic.js TAP nonexistent file > stdout 1`] = ` 59 | TAP version 13 60 | not ok 1 - does not exist # {time} { 61 | not ok 1 - ENOENT: no such file or directory, stat 'does not exist' 62 | --- 63 | at: 64 | line: # 65 | column: # 66 | file: #INTERNAL# 67 | code: ENOENT 68 | errno: -2 69 | path: does not exist 70 | stack: | 71 | {STACK} 72 | syscall: stat 73 | test: does not exist 74 | ... 75 | 76 | 1..1 77 | # failed 1 test 78 | } 79 | 80 | 1..1 81 | # failed 1 test 82 | # {time} 83 | 84 | ` 85 | -------------------------------------------------------------------------------- /lib/stack.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const sourceMapSupport = require('source-map-support') 3 | const StackUtils = require('stack-utils') 4 | const path = require('path') 5 | const tapDir = path.resolve(__dirname, '..') 6 | const {homedir} = require('os') 7 | 8 | const resc = str => 9 | str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&') 10 | 11 | // Ignore tap if it's a dependency, or anything 12 | // in this lib folder. 13 | // don't skip when developing on tap itself 14 | const skip = (process.cwd() !== tapDir || 15 | +process.env.TAP_DEV_SHORTSTACK === 1) && 16 | +process.env.TAP_DEV_LONGSTACK !== 1 17 | ? [ 18 | /node_modules[\/\\]tap[\/\\]/, 19 | /at internal\/.*\.js:\d+:\d+/m, 20 | new RegExp(resc(path.resolve(homedir(), '.node-spawn-wrap-')) + '.*'), 21 | new RegExp(resc(tapDir) + '\\b', 'i'), 22 | new RegExp('at ' + resc('Generator.next ()'), 'i'), 23 | ].concat(/* istanbul ignore next */ require.resolve 24 | ? [ 25 | new RegExp(resc(require.resolve('function-loop'))), 26 | new RegExp(resc(require.resolve('esm'))), 27 | new RegExp(resc(require.resolve('nyc').replace(/(node_modules[\/\\]nyc).*$/, '$1'))), 28 | new RegExp(resc(require.resolve('import-jsx'))), 29 | ] 30 | : []) 31 | : +process.env.TAP_DEV_LONGSTACK !== 1 ? [ 32 | /at internal\/.*\.js:\d+:\d+/m, 33 | new RegExp(resc(require.resolve('esm'))), 34 | new RegExp(resc(require.resolve('nyc').replace(/(node_modules[\/\\]nyc).*$/, '$1'))), 35 | new RegExp(resc(require.resolve('import-jsx'))), 36 | ] 37 | : [] 38 | 39 | sourceMapSupport.install({environment:'node', hookRequire: true}) 40 | 41 | let nodeInternals = [] 42 | try { 43 | nodeInternals = StackUtils.nodeInternals() 44 | } catch (error) { 45 | // Do nothing. 46 | } 47 | 48 | module.exports = new StackUtils({ 49 | internals: nodeInternals.concat(skip), 50 | wrapCallSite: sourceMapSupport.wrapCallSite 51 | }) 52 | -------------------------------------------------------------------------------- /tap-snapshots/test-base.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/base.js TAP parser event stuff no bail > counts 1`] = ` 9 | Object { 10 | "fail": 1, 11 | "pass": 1, 12 | "skip": 1, 13 | "todo": 1, 14 | "total": 4, 15 | } 16 | ` 17 | 18 | exports[`test/base.js TAP parser event stuff no bail > lists 1`] = ` 19 | Object { 20 | "fail": Array [ 21 | Result { 22 | "diag": Object { 23 | "fine": false, 24 | }, 25 | "fullname": "", 26 | "id": 2, 27 | "name": "actually not fine", 28 | "ok": false, 29 | }, 30 | ], 31 | "skip": Array [ 32 | Result { 33 | "fullname": "", 34 | "id": 4, 35 | "name": "not so fine", 36 | "ok": false, 37 | "skip": "dont care for now", 38 | }, 39 | ], 40 | "todo": Array [ 41 | Result { 42 | "fullname": "", 43 | "id": 3, 44 | "name": "not so fine", 45 | "ok": false, 46 | "todo": "will be fine later", 47 | }, 48 | ], 49 | } 50 | ` 51 | 52 | exports[`test/base.js TAP parser event stuff yes bail > counts 1`] = ` 53 | Object { 54 | "fail": 1, 55 | "pass": 1, 56 | "skip": 0, 57 | "todo": 0, 58 | "total": 2, 59 | } 60 | ` 61 | 62 | exports[`test/base.js TAP parser event stuff yes bail > expected bailout 1`] = ` 63 | actually not fine 64 | ` 65 | 66 | exports[`test/base.js TAP parser event stuff yes bail > lists 1`] = ` 67 | Object { 68 | "fail": Array [ 69 | Result { 70 | "diag": Object { 71 | "fine": false, 72 | }, 73 | "fullname": "", 74 | "id": 2, 75 | "name": "actually not fine", 76 | "ok": false, 77 | }, 78 | ], 79 | "skip": Array [], 80 | "todo": Array [], 81 | } 82 | ` 83 | -------------------------------------------------------------------------------- /test/run/reporters.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | clean, 5 | tap, 6 | t, 7 | } = require('./') 8 | const path = require('path') 9 | 10 | const ok = tmpfile(t, 'ok.js', ` 11 | require(${tap}).test(t => { 12 | t.pass('this is fine') 13 | t.end() 14 | }) 15 | `) 16 | 17 | const reactReporter = tmpfile(t, 'reporter.js', ` 18 | module.exports = class ReactyReporter extends require('treport').Base {} 19 | `) 20 | 21 | const check = t => (er, o, e) => { 22 | t.error(er) 23 | o = clean(o) 24 | .replace(/^[\S\s]*SUMMARY RESULTS[\S\s]*$/,'treport output') 25 | .replace(/^[\S\s]*✓[\S\s]*$/, 'spec output') 26 | t.matchSnapshot(o, 'stdout') 27 | t.equal(e, '', 'stderr') 28 | t.end() 29 | } 30 | 31 | const opt = {env: {TAP_COLORS: 0, PATH: process.env.PATH}} 32 | 33 | t.test('builtin reporter', t => 34 | run([ok, '-Rbase'], opt, check(t))) 35 | 36 | t.test('tmr builtin reporter', t => 37 | run([ok, '-Rspec'], opt, check(t))) 38 | 39 | t.test('cli reporter', t => 40 | run([ok, '-Rtap-parser', '-r-t', '-r-f'], opt, check(t))) 41 | 42 | t.test('stream reporter', t => 43 | run([ok, '-Rtap-mocha-reporter', '-rspec'], { 44 | ...opt, 45 | env: { 46 | ...opt.env, 47 | PATH: '' 48 | } 49 | }, check(t))) 50 | 51 | t.test('react component', t => 52 | run([ok, '-R', './' + reactReporter], opt, check(t))) 53 | 54 | t.test('failures', t => { 55 | const nonfunc = tmpfile(t, 'nonfunc.js', `module.exports = "hello"`) 56 | const func = tmpfile(t, 'func.js', `module.exports = function () {}`) 57 | const {makeReporter} = require('../../bin/run.js') 58 | 59 | t.throws(() => makeReporter(t, {reporter: 'not a reporter actually'}), 60 | { message: `Cannot find module 'not a reporter actually'` }) 61 | 62 | t.throws(() => makeReporter(t, {reporter: path.resolve(nonfunc)}), 63 | { message: 'Invalid reporter: non-class exported by ' }) 64 | 65 | t.throws(() => makeReporter(t, {reporter: path.resolve(func)}), 66 | { message: 'Invalid reporter: not a stream or react component ' }) 67 | 68 | t.end() 69 | }) 70 | -------------------------------------------------------------------------------- /test/run/parallel.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | dir, 6 | t, 7 | } = require('./') 8 | 9 | const timeout = process.env.CI ? 1000 : 100 10 | 11 | // should see start, start, end, end, in the output 12 | tmpfile(t, 'p/y/1.js', `'use strict' 13 | console.error('start') 14 | setTimeout(() => console.error('end'), ${timeout}) 15 | const t = require(${tap}) 16 | t.pass('one') 17 | `) 18 | 19 | tmpfile(t, 'p/y/2.js', `'use strict' 20 | console.error('start') 21 | setTimeout(() => console.error('end'), ${timeout}) 22 | const t = require(${tap}) 23 | t.pass('2') 24 | `) 25 | 26 | tmpfile(t, 'p/tap-parallel-not-ok', '') 27 | tmpfile(t, 'p/y/tap-parallel-ok', '') 28 | 29 | tmpfile(t, 'q/b/f1.js', `'use strict' 30 | require(${tap}).pass('a/b') 31 | setTimeout(() => console.error('f1'), ${timeout}) 32 | `) 33 | 34 | tmpfile(t, 'q/b/f2.js', `'use strict' 35 | require(${tap}).pass('c/d') 36 | console.error('f2') 37 | `) 38 | 39 | tmpfile(t, 'q/tap-parallel-ok', '') 40 | tmpfile(t, 'q/b/tap-parallel-not-ok', '') 41 | 42 | tmpfile(t, 'r/y/1.js', `'use strict' 43 | console.error('ry1') 44 | setTimeout(() => console.error('ry1'), ${timeout}) 45 | const t = require(${tap}) 46 | t.pass('one') 47 | `) 48 | 49 | tmpfile(t, 'r/y/2.js', `'use strict' 50 | console.error('ry2') 51 | setTimeout(() => console.error('ry2'), ${timeout}) 52 | const t = require(${tap}) 53 | t.pass('2') 54 | `) 55 | 56 | tmpfile(t, 'r/tap-parallel-not-ok', '') 57 | 58 | tmpfile(t, 'z/y/1.js', `'use strict' 59 | console.error('start') 60 | setTimeout(() => console.error('end'), ${timeout}) 61 | const t = require(${tap}) 62 | t.pass('one') 63 | `) 64 | 65 | tmpfile(t, 'z/y/2.js', `'use strict' 66 | console.error('start') 67 | setTimeout(() => console.error('end'), ${timeout}) 68 | const t = require(${tap}) 69 | t.pass('2') 70 | `) 71 | 72 | t.plan(3) 73 | run(['p/y/*.js', 'q', 'q/b/f1.js', 'r/y', 'z', '-j2'], { cwd: dir }, (er, o, e) => { 74 | t.equal(er, null) 75 | t.matchSnapshot(o, 'output') 76 | t.matchSnapshot(e, 'stderr') 77 | }) 78 | -------------------------------------------------------------------------------- /tap-snapshots/test-spawn.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/spawn.js TAP childId via TAP_CHILD_ID env > must match snapshot 1`] = ` 9 | childId=69420 10 | 1..0 # no tests found 11 | 12 | ` 13 | 14 | exports[`test/spawn.js TAP childId via childId option > must match snapshot 1`] = ` 15 | childId=69420 16 | 1..0 # no tests found 17 | 18 | ` 19 | 20 | exports[`test/spawn.js TAP failure to spawn > must match snapshot 1`] = ` 21 | 22 | not ok 1 - spawn something that does not exist ENOENT 23 | --- 24 | args: [] 25 | at: 26 | line: # 27 | column: # 28 | file: #INTERNAL# 29 | code: ENOENT 30 | command: something that does not exist 31 | cwd: {CWD} 32 | env: {} 33 | errno: ENOENT 34 | path: something that does not exist 35 | spawnargs: [] 36 | stdio: 37 | - 0 38 | - pipe 39 | - 2 40 | syscall: spawn something that does not exist 41 | test: "something that does not exist " 42 | ... 43 | 1..1 44 | # failed 1 test 45 | 46 | ` 47 | 48 | exports[`test/spawn.js TAP skip stuff > must match snapshot 1`] = ` 49 | TAP version 13 50 | ok 1 - skipper # SKIP { 51 | 1..0 52 | # {time} 53 | } 54 | 55 | # Subtest: node ./test/spawn.js skip-reason 56 | 1..0 # for no raisins 57 | # {time} 58 | ok 2 - node ./test/spawn.js skip-reason # SKIP for no raisins 59 | 60 | 61 | ` 62 | 63 | exports[`test/spawn.js TAP timeout KILL > must match snapshot 1`] = ` 64 | SIGTERM 65 | 66 | not ok 1 - timeout! 67 | --- 68 | expired: killa 69 | ... 70 | 1..1 71 | # failed 1 test 72 | 73 | ` 74 | 75 | exports[`test/spawn.js TAP timeout update > must match snapshot 1`] = ` 76 | TAP version 13 77 | # timeout=42069 78 | ok 1 - this is fine 79 | 1..1 80 | # {time} 81 | 82 | ` 83 | 84 | exports[`test/spawn.js TAP using proc event > must match snapshot 1`] = ` 85 | TAP version 13 86 | ok 87 | 1..1 88 | 89 | ` 90 | -------------------------------------------------------------------------------- /example/mocha-example.js: -------------------------------------------------------------------------------- 1 | require('../lib/tap.js').mochaGlobals() 2 | /* standard ignore next */ 3 | describe('parent', function () { 4 | 5 | before('name', function () { 6 | console.error('before') 7 | }); 8 | 9 | after(function () { 10 | console.error('after') 11 | }); 12 | 13 | beforeEach(function () { 14 | console.error('beforeEach') 15 | }); 16 | 17 | afterEach(function () { 18 | console.error('afterEach') 19 | }); 20 | 21 | it('first', function () { 22 | console.error('first it') 23 | }) 24 | it('second', function () { 25 | console.error('second it') 26 | }) 27 | 28 | describe('child 1', function () { 29 | console.error('in child 1') 30 | before(function () { 31 | console.error('before 2') 32 | }); 33 | 34 | after(function () { 35 | console.error('after 2') 36 | }); 37 | 38 | beforeEach(function () { 39 | console.error('beforeEach 2') 40 | }); 41 | 42 | afterEach(function () { 43 | console.error('afterEach 2') 44 | }); 45 | 46 | it('first x', function () { 47 | console.error('first it') 48 | }) 49 | it('second', function (done) { 50 | console.error('second it') 51 | setTimeout(done) 52 | }) 53 | describe('gc 1', function () { 54 | it('first y', function () { 55 | console.error('first it') 56 | }) 57 | it('second', function (done) { 58 | console.error('second it') 59 | setTimeout(done) 60 | }) 61 | it('third', function (done) { 62 | console.error('third it') 63 | done() 64 | }) 65 | }) 66 | it('third after gc 1', function () { 67 | console.error('second it') 68 | }) 69 | }) 70 | 71 | describe('child 2', function () { 72 | console.error('in child 2') 73 | it('first z', function () { 74 | console.error('first it') 75 | }) 76 | it('second', function (done) { 77 | console.error('second it') 78 | setTimeout(done) 79 | }) 80 | it('third', function (done) { 81 | console.error('third it') 82 | done() 83 | }) 84 | }) 85 | 86 | it('third', function () { 87 | console.error('second it') 88 | }) 89 | }) 90 | -------------------------------------------------------------------------------- /test/point.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const t = require('../') 3 | const TestPoint = require('../lib/point.js') 4 | 5 | t.throws(_ => new TestPoint(99), 6 | new TypeError('ok must be boolean')) 7 | 8 | t.throws(_ => new TestPoint(true, Math), 9 | new TypeError('message must be a string')) 10 | 11 | const cases = [ 12 | [true, 'this is fine', null, { 13 | ok: 'ok ', 14 | message: ' - this is fine\n' 15 | }], 16 | [false, 'this is fine', null, { 17 | ok: 'not ok ', 18 | message: ' - this is fine\n' 19 | }], 20 | [true, ' ', null, { 21 | ok: 'ok ', 22 | message: '\n' 23 | }], 24 | [false, '\n\r\t\n', null, { 25 | ok: 'not ok ', 26 | message: '\n' 27 | }], 28 | [true, 'this is fine ', { skip: true }, { 29 | ok: 'ok ', 30 | message: ' - this is fine # SKIP\n' 31 | }], 32 | [true, 'this is fine', { skip: 'nope' }, { 33 | ok: 'ok ', 34 | message: ' - this is fine # SKIP nope\n' 35 | }], 36 | [true, 'this is fine', { todo: true }, { 37 | ok: 'ok ', 38 | message: ' - this is fine # TODO\n' 39 | }], 40 | [true, 'this is fine', { todo: 'later' }, { 41 | ok: 'ok ', 42 | message: ' - this is fine # TODO later\n' 43 | }], 44 | [true, 'time waits for no one', { time: 12345 }, { 45 | ok: 'ok ', 46 | message: 'time waits for no one # time=12345ms\n' 47 | }], 48 | [true, 'fine', { foo: 'bar', diagnostic: true }, { 49 | ok: 'ok ', 50 | message: ' - fine\n ---\n foo: bar\n ...\n\n' 51 | }], 52 | [true, '', { foo: 'bar', diagnostic: true }, { 53 | ok: 'ok ', 54 | message: '\n ---\n foo: bar\n ...\n\n' 55 | }], 56 | [false, 'x\ny\r\nz', {}, { 57 | ok: 'not ok ', 58 | message: 'x y z\n' 59 | }], 60 | [true, '', { 61 | tapChildBuffer: 'child output', 62 | diagnostic: true, 63 | fluffer: 'nutter' 64 | }, { 65 | ok: 'ok ', 66 | message: '\n ---\n fluffer: nutter\n ...\n{\nchild output\n}\n' 67 | }], 68 | [true, '', { 69 | tapChildBuffer: 'child output', 70 | fluffer: 'nutter' 71 | }, { 72 | ok: 'ok ', 73 | message: ' {\nchild output\n}\n' 74 | }], 75 | ] 76 | 77 | cases.forEach(c => t.match(new TestPoint(c[0], c[1], c[2]), c[3])) 78 | -------------------------------------------------------------------------------- /docs/src/content/docs/using-with/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Using tap with..." 3 | section: 3 4 | redirect_from: 5 | - /using-with/ 6 | - /using-with 7 | --- 8 | 9 | # Using tap with ESM 10 | 11 | ES-Modules are supported by default, using the [esm](http://npm.im/esm) module. 12 | If your test file ends in `.mjs`, then this will automatically use Node's 13 | built-in experimental module system. 14 | 15 | Although, if you are using ES-modules with `.js` extension & `type: module` pattern 16 | on Node.js v12.13+, you will face warnings and/or crashes while running tests. 17 | In this case it is advised to turn "esm" support off & use native Node.js 18 | module loader. 19 | 20 | To turn _off_ ES-Module support, run your tests with `--no-esm`. 21 | 22 | In future releases (v15+) "esm" module will not be provided by tap. 23 | 24 | # Using tap with TypeScript 25 | 26 | Name your test files `.ts` and they'll be loaded as TypeScript. 27 | 28 | For TypeScript with JSX (ie, TSX), name your files with a `.tsx` extension. 29 | 30 | If you want to provide your own TypeScript configs or version, disable tap's 31 | built-in TypeScript support, and use the `--node-arg` argument to load your 32 | TypeScript loader. For example: 33 | 34 | ``` 35 | tap --no-ts --node-arg=--require=my-ts-node/register 36 | ``` 37 | 38 | This is useful in some cases where you might have a mix of JavaScript and 39 | TypeScript in your tests and modules, and want to ensure that the correct 40 | TypeScript compiler is used. 41 | 42 | # Using tap with JSX 43 | 44 | Name your test files `.jsx` and they'll be loaded as JSX. 45 | 46 | To provide your own JSX handling preloader instead of tap's built-in use of 47 | [`import-jsx`](http://npm.im/import-jsx), disable tap's built-in JSX handling, 48 | and provide your own loader via the `--node-arg` option. For example: 49 | 50 | ``` 51 | tap --no-jsx --node-arg=--require=my-jsx-preloader 52 | ``` 53 | 54 | This is useful in some cases where you might have a mix of JavaScript and 55 | JSX in your tests and modules, and want to ensure that the correct JSX 56 | compiler is used. 57 | 58 | # Using tap with Flow 59 | 60 | Pass the `--flow` argument on the command line, or set `flow: true` in 61 | `.taprc`, or `{ "tap": { "flow": true } }` in `package.json`, and tap will 62 | automatically remove flow annotations from tests and code. 63 | -------------------------------------------------------------------------------- /lib/extra-from-error.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const stack = require('./stack.js') 3 | 4 | module.exports = (er, extra, options) => { 5 | // the yaml module puts big stuff here, pluck it off 6 | if (er.source && typeof er.source === 'object' && er.source.context) 7 | er.source = { ...er.source, context: null } 8 | 9 | extra = Object.keys(options || {}).reduce((set, k) => { 10 | if (!(k in set) && !/^tapChild/.test(k)) 11 | set[k] = options[k] 12 | return set 13 | }, extra || {}) 14 | 15 | if (!er || typeof er !== 'object') { 16 | extra.error = er 17 | return extra 18 | } 19 | 20 | const message = er.message ? er.message 21 | : er.stack ? er.stack.split('\n')[0] 22 | : '' 23 | const addName = er.message || !er.stack 24 | 25 | if (er.message) { 26 | try { 27 | Object.defineProperty(er, 'message', { 28 | value: '', 29 | configurable: true 30 | }) 31 | } catch (e) {} 32 | } 33 | 34 | const st = er.stack && er.stack.substr( 35 | er._babel ? (message + er.codeFrame).length : 0) 36 | if (st) { 37 | const splitst = st.split('\n') 38 | if (er._babel && er.loc) { 39 | const msplit = message.split(': ') 40 | const f = msplit[0].trim() 41 | extra.message = msplit.slice(1).join(': ') 42 | .replace(/ \([0-9]+:[0-9]+\)$/, '').trim() 43 | const file = f.indexOf(process.cwd()) === 0 44 | ? f.substr(process.cwd().length + 1) : f 45 | if (file !== 'unknown') 46 | delete er.codeFrame 47 | extra.at = { 48 | file, 49 | line: er.loc.line, 50 | column: er.loc.column + 1, 51 | } 52 | } else { 53 | // parse out the 'at' bit from the first line. 54 | extra.at = stack.parseLine(splitst[1]) 55 | } 56 | extra.stack = stack.clean(splitst) 57 | } 58 | 59 | if (message) { 60 | try { 61 | Object.defineProperty(er, 'message', { 62 | value: message, 63 | configurable: true 64 | }) 65 | } catch (e) {} 66 | } 67 | 68 | if (er.name && er.name !== 'Error') 69 | extra.type = er.name 70 | 71 | Object.keys(er).forEach(k => { 72 | if (k === 'message' || 73 | k === 'domainEmitter' || 74 | k === 'domainThrown' || 75 | k === 'domain' || 76 | k === 'domainBound') 77 | return 78 | extra[k] = er[k] 79 | }) 80 | 81 | return extra 82 | } 83 | -------------------------------------------------------------------------------- /test/run/before-after.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | tap, 5 | t, 6 | } = require('./') 7 | 8 | const ok = tmpfile(t, 'ok.js', `console.log('ok')`) 9 | const fail = tmpfile(t, 'fail.js', ` 10 | throw new Error('fail') 11 | `) 12 | const slow = tmpfile(t, 'slow.js', `setTimeout(() => console.log('slow'))`) 13 | const slowFail = tmpfile(t, 'slow-fail.js', `setTimeout(() => { 14 | throw new Error('slow fail') 15 | })`) 16 | 17 | const sigfail = tmpfile(t, 'sigfail.js', ` 18 | process.kill(process.pid, 'SIGKILL') 19 | setTimeout(() => {}, 1000000) 20 | `) 21 | 22 | const t1 = tmpfile(t, 't1.js', `const t = require(${tap}) 23 | t.pass('this is fine') 24 | `) 25 | const t2 = tmpfile(t, 't2.js', `const t = require(${tap}) 26 | t.test('sub', async t => t.pass('this is fine')) 27 | `) 28 | const t3 = tmpfile(t, 't3.js', `const t = require(${tap}) 29 | t.test('sub', async t => t.fail('not fine')) 30 | `) 31 | 32 | t.test('basic', t => { 33 | t.plan(3) 34 | run([`--before=${slow}`, `--after=${ok}`, ok, slow, t1, t2, t3], {}, (er, o, e) => { 35 | t.ok(er, 'error') 36 | t.matchSnapshot(o, 'stdout') 37 | t.matchSnapshot(e, 'stderr') 38 | }) 39 | }) 40 | 41 | t.test('failing before', t => { 42 | t.plan(3) 43 | run([`--before=${fail}`, t1, t2, t3, fail], {}, (er, o, e) => { 44 | t.ok(er, 'error') 45 | t.matchSnapshot(o, 'stdout') 46 | t.matchSnapshot(e, 'stderr') 47 | }) 48 | }) 49 | 50 | t.test('failing after', t => { 51 | t.plan(3) 52 | run([`--after=${fail}`, t1, fail], {}, (er, o, e) => { 53 | t.ok(er, 'error') 54 | t.matchSnapshot(o, 'stdout') 55 | t.matchSnapshot(e, 'stderr') 56 | }) 57 | }) 58 | 59 | t.test('slow fail before', t => { 60 | t.plan(3) 61 | run([`--before=${slowFail}`, t1, t2, t3], {}, (er, o, e) => { 62 | t.ok(er, 'error') 63 | t.matchSnapshot(o, 'stdout') 64 | t.matchSnapshot(e, 'stderr') 65 | }) 66 | }) 67 | 68 | t.test('signal fail after', t => { 69 | t.plan(3) 70 | run([`--before=${sigfail}`, t1, t2, t3], {}, (er, o, e) => { 71 | t.ok(er, 'error') 72 | t.matchSnapshot(o, 'stdout') 73 | t.matchSnapshot(e, 'stderr') 74 | }) 75 | }) 76 | 77 | t.test('run after even on bailout', t => { 78 | t.plan(3) 79 | run(['--bail', `--after=${ok}`, t1, t2, t3], {}, (er, o, e) => { 80 | t.ok(er, 'error') 81 | t.matchSnapshot(o, 'stdout') 82 | t.matchSnapshot(e, 'stderr') 83 | }) 84 | }) 85 | -------------------------------------------------------------------------------- /test/run/save-file.js: -------------------------------------------------------------------------------- 1 | process.env.TAP_NO_ESM = '1' 2 | const { 3 | tmpfile, 4 | run, 5 | bin, 6 | tap, 7 | node, 8 | dir, 9 | t, 10 | winSkip, 11 | } = require('./') 12 | 13 | const path = require('path') 14 | const fs = require('fs') 15 | 16 | const xy1 = tmpfile(t, 'x/y/1.js', ` 17 | const t = require(${tap}) 18 | t.pass('one') 19 | `) 20 | 21 | const ab2 = tmpfile(t, 'a/b/2.js', ` 22 | const t = require(${tap}) 23 | t.pass('2') 24 | `) 25 | 26 | const abf1 = tmpfile(t, 'a/b/f1.js', `//f1.js 27 | require(${tap}).fail('a/b') 28 | `) 29 | 30 | const abf2 = tmpfile(t, 'z.js', `//z.js 31 | require(${tap}).fail('c/d') 32 | `) 33 | 34 | const savefile = path.resolve(tmpfile(t, 'fails.txt', '')) 35 | const opt = { cwd: dir, env: { TAP_NO_ESM: '1' } } 36 | 37 | t.test('with bailout, should save all untested', t => { 38 | run(['a', 'x', 'z.js', '-s', savefile, '-b'], opt, (er, o, e) => { 39 | t.match(er, { code: 1 }) 40 | t.matchSnapshot(o, 'stdout', { skip: winSkip }) 41 | t.equal(e, '') 42 | t.matchSnapshot(fs.readFileSync(savefile, 'utf8'), 'savefile') 43 | t.end() 44 | }) 45 | }) 46 | 47 | t.test('without bailout, run untested, save failures', t => { 48 | run(['a', 'x', 'z.js', '-s', savefile], opt, (er, o, e) => { 49 | t.match(er, { code: 1 }) 50 | t.matchSnapshot(o, 'stdout', { skip: winSkip }) 51 | t.equal(e, '') 52 | t.matchSnapshot(fs.readFileSync(savefile, 'utf8'), 'savefile') 53 | t.end() 54 | }) 55 | }) 56 | 57 | t.test('make fails pass', t => { 58 | fs.writeFileSync(abf1, ` 59 | require(${tap}).pass('fine now') 60 | `) 61 | fs.writeFileSync(abf2, ` 62 | require(${tap}).pass('fine now too') 63 | `) 64 | t.end() 65 | }) 66 | 67 | t.test('pass, empty save file', t => { 68 | run(['a', 'x', 'z.js', '-s', savefile], opt, (er, o, e) => { 69 | t.equal(er, null) 70 | t.matchSnapshot(o, 'stdout') 71 | t.equal(e, '') 72 | try { 73 | console.log(fs.readFileSync(savefile, 'utf8')) 74 | } catch (e) {} 75 | t.throws(() => fs.statSync(savefile), 'save file is gone') 76 | t.end() 77 | }) 78 | }) 79 | 80 | t.test('empty save file, run all tests', t => { 81 | run(['a', 'x', 'z.js', '-s', savefile], opt, (er, o, e) => { 82 | t.equal(er, null) 83 | t.matchSnapshot(o, 'stdout') 84 | t.equal(e, '') 85 | t.throws(() => fs.statSync(savefile), 'save file is gone') 86 | t.end() 87 | }) 88 | }) 89 | -------------------------------------------------------------------------------- /docs/src/content/docs/watch/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Watching Files for Changes 3 | section: 10 4 | redirect_from: 5 | - /watch/ 6 | - /watch 7 | --- 8 | 9 | # Watching Files for Changes 10 | 11 | When developing a projects, it's useful to run tap in watch mode. In this 12 | mode, tap will watch your project for changes to test files and the program 13 | files that they cover, and open a repl (Read, Eval, Print Loop) to control the 14 | process. 15 | 16 | To run tap in watch mode, run `tap --watch` or `tap -w`. 17 | 18 | Watching files for changes requires that [coverage](/docs/coverage/) is enabled, 19 | because it uses NYC to determine which test is relevant to which file being 20 | changed. 21 | 22 | At the start of the watch process, tap runs the full test suite. Thereafter, 23 | it automatically runs the files that are necessary as they change. 24 | 25 | Any tests that fail will be re-run on the next file change, even if they are 26 | not connected to the file that changed. 27 | 28 | ## TAP Repl Commands 29 | 30 | * `r []` 31 | Run test suite again, or just run the supplied filename. (Use this to add 32 | tests to the suite, if they're not already being watched.) 33 | 34 | * `u []` 35 | Update snapshots in the suite, or in the supplied filename. This supplied 36 | file will be added to the suite if it's not already included. 37 | 38 | * `n` 39 | Run the suite with [`--changed`](/docs/save-failures-run-changed/). This is 40 | useful when resuming after a pause. 41 | 42 | * `p` 43 | Pause/resume the file watcher. 44 | 45 | * `c []` 46 | Run coverage report. Default to 'text' style. 47 | 48 | * `exit` 49 | Exit the repl. You can also use `Ctrl-C` or `Ctrl-D` to terminate the repl, 50 | if a test run is not in progress. 51 | 52 | * `clear` 53 | Delete all coverage info and re-run the test suite. 54 | 55 | * `cls` 56 | Clear the screen. 57 | 58 | ## Adding Tests 59 | 60 | Due to the way that tap detects which files are covered by each change, _new_ 61 | files that are added to the test suite will not automatically be detected by 62 | the watcher. 63 | 64 | Use the `r ` or `u ` commands to add them to the suite. 65 | 66 | ## Tip: Use a Coverage Map Module 67 | 68 | If you specify a [`--coverage-map=`](/docs/coverage/coverage-map/) 69 | option, then you can be very precise about _which_ files under test should 70 | trigger a re-run of the tests. 71 | -------------------------------------------------------------------------------- /docs/src/components/home/hero.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import {theme} from '../../theme'; 4 | import {Image, Flex} from 'rebass'; 5 | import logo from '../../images/logo.gif'; 6 | import {ButtonLink} from '../links'; 7 | const description = require('../../../../package.json').description; 8 | 9 | const OuterCircle = styled.div` 10 | background-color: ${theme.colors.lightGrey}; 11 | position: relative; 12 | border-radius: 50%; 13 | width: 100%; 14 | height: auto; 15 | padding-top: 100%; 16 | `; 17 | 18 | const InnerCircle = styled.div` 19 | background-color: ${theme.colors.lightestGrey}; 20 | position: absolute; 21 | border-radius: 50%; 22 | width: 80%; 23 | height: auto; 24 | padding-top: 80%; 25 | top: 10%; 26 | left: 0; 27 | margin: auto; 28 | box-shadow: 1px 1px 15px 0px #3333330d; 29 | right: 0; 30 | `; 31 | 32 | const Content = styled(Flex)` 33 | position: relative; 34 | margin: 0px auto 40px; 35 | max-width: 800px; 36 | 37 | @media screen and (min-width: 768px) { 38 | margin: -90px auto 0; 39 | } 40 | `; 41 | 42 | const Container = styled.div` 43 | background-color: ${theme.colors.darkGrey}; 44 | padding: 20px 20px 40px; 45 | 46 | @media screen and (min-width: 768px) { 47 | padding: 20px 20px; 48 | } 49 | `; 50 | 51 | const Logo = styled(Image)` 52 | max-width: 60%; 53 | `; 54 | 55 | const BuildStatus = styled.a` 56 | width: 90px; 57 | height: 20px; 58 | top: -20px; 59 | text-indent: -999em; 60 | position: absolute; 61 | background-repeat: no-repeat; 62 | background-image: url(https://travis-ci.org/tapjs/node-tap.svg?branch=master); 63 | `; 64 | 65 | const Title = styled.h1` 66 | font-size: 18px; 67 | text-align: center; 68 | margin-bottom: 30px; 69 | `; 70 | 71 | const InnerBits = styled.div` 72 | position: absolute; 73 | max-width: 600px; 74 | left: 0; 75 | right: 0; 76 | margin: auto; 77 | text-align: center; 78 | top: 25%; 79 | `; 80 | 81 | const Hero = () => { 82 | return( 83 | 84 | 85 | 86 | 87 | 88 | Build status 89 | 90 | {description} 91 | Get Started 92 | 93 | 94 | 95 | ); 96 | }; 97 | 98 | export default Hero; 99 | -------------------------------------------------------------------------------- /docs/src/components/seo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Helmet } from 'react-helmet'; 3 | import { StaticQuery, graphql } from 'gatsby'; 4 | 5 | const SEO = ({ title, description, image, pathname, article }) => ( 6 | { 20 | const seo = { 21 | title: title, 22 | defaultTitle: defaultTitle, 23 | description: description || defaultDescription, 24 | image: `${siteUrl}${image || defaultImage}`, 25 | url: `${siteUrl}${pathname || '/'}`, 26 | }; 27 | 28 | return ( 29 | 30 | 31 | {seo.title && ({seo.title})} 32 | 33 | 34 | {seo.url && } 35 | {(article ? true : null) && ( 36 | 37 | )} 38 | {seo.title && } 39 | {seo.description && ( 40 | 41 | )} 42 | {seo.image && } 43 | 44 | {twitterUsername && ( 45 | 46 | )} 47 | {seo.title && } 48 | {seo.description && ( 49 | 50 | )} 51 | {seo.image && } 52 | 53 | ); 54 | }} 55 | /> 56 | ); 57 | 58 | export default SEO; 59 | 60 | const query = graphql` 61 | query SEO { 62 | site { 63 | siteMetadata { 64 | defaultTitle: title 65 | titleTemplate 66 | defaultDescription: description 67 | siteUrl: url 68 | defaultImage: image 69 | twitterUsername 70 | } 71 | } 72 | } 73 | `; 74 | -------------------------------------------------------------------------------- /lib/synonyms.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // A list of all the synonyms of assert methods. 3 | // In addition to these, multi-word camelCase are also synonymized to 4 | // all lowercase and snake_case 5 | 6 | const multiword = obj => 7 | Object.keys(obj).reduce((s, i) => 8 | (s[i] = [ multiword_(i) ] 9 | .concat(obj[i].map(multiword_)) 10 | .reduce((s, i) => (s.push.apply(s, i), s), []), s), obj) 11 | 12 | const multiword_ = str => 13 | str.match(/[A-Z]/) ? [ 14 | str, 15 | str.toLowerCase(), 16 | str.replace(/[A-Z]/g, $0 => '_' + $0.toLowerCase()) 17 | ] : [str] 18 | 19 | module.exports = multiword({ 20 | ok: ['true', 'assert'], 21 | notOk: ['false', 'assertNot'], 22 | 23 | error: ['ifError', 'ifErr'], 24 | throws: ['throw'], 25 | doesNotThrow: ['notThrow'], 26 | 27 | // exactly the same. === 28 | equal: [ 29 | 'equals', 'isEqual', 'is', 'strictEqual', 'strictEquals', 'strictIs', 30 | 'isStrict', 'isStrictly', 'identical' 31 | ], 32 | 33 | // not equal. !== 34 | not: [ 35 | 'inequal', 'notEqual', 'notEquals', 'notStrictEqual', 'notStrictEquals', 36 | 'isNotEqual', 'isNot', 'doesNotEqual', 'isInequal' 37 | ], 38 | 39 | // deep equivalence. == for scalars 40 | same: [ 41 | 'equivalent', 'looseEqual', 'looseEquals', 'deepEqual', 42 | 'deepEquals', 'isLoose', 'looseIs', 'isEquivalent' 43 | ], 44 | 45 | // deep inequivalence. != for scalars 46 | notSame: [ 47 | 'inequivalent', 'looseInequal', 'notDeep', 'deepInequal', 48 | 'notLoose', 'looseNot', 'notEquivalent', 'isNotDeepEqual', 49 | 'isNotDeeply', 'notDeepEqual', 'isInequivalent', 50 | 'isNotEquivalent' 51 | ], 52 | 53 | // deep equivalence, === for scalars 54 | strictSame: [ 55 | 'strictEquivalent', 'strictDeepEqual', 'sameStrict', 'deepIs', 56 | 'isDeeply', 'isDeep', 'strictDeepEquals' 57 | ], 58 | 59 | // deep inequivalence, !== for scalars 60 | strictNotSame: [ 61 | 'strictInequivalent', 'strictDeepInequal', 'notSameStrict', 'deepNot', 62 | 'notDeeply', 'strictDeepInequals', 'notStrictSame' 63 | ], 64 | 65 | // found has the fields in wanted, string matches regexp 66 | match: [ 67 | 'has', 'hasFields', 'matches', 'similar', 'like', 'isLike', 68 | 'includes', 'include', 'isSimilar', 'contains' 69 | ], 70 | 71 | notMatch: [ 72 | 'dissimilar', 'unsimilar', 'notSimilar', 'unlike', 'isUnlike', 73 | 'notLike', 'isNotLike', 'doesNotHave', 'isNotSimilar', 'isDissimilar' 74 | ], 75 | 76 | type: [ 77 | 'isa', 'isA' 78 | ] 79 | }) 80 | -------------------------------------------------------------------------------- /docs/src/content/docs/rerunning-partial-suites/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Re-running Partial Suites 3 | section: 9 4 | redirect_from: 5 | - /save-failures-run-changed/ 6 | - /save-failures-run-changed 7 | --- 8 | 9 | # Re-running Partial Test Suites 10 | 11 | Occasionally you'll want to re-run just part of a test suite, for example, just 12 | to run the tests that failed in the previous run, or running tests for files in 13 | your application that have changed since the last run. There are a few ways to 14 | do this in node-tap. 15 | 16 | ## Save Failures to a File 17 | 18 | With the `--save=` option, you can write all failed tests to a file. If 19 | that file exists, then only the tests in that file will be re-run. 20 | 21 | For example, say that you have two tests `foo.test.js` and `bar.test.js`. When 22 | you run `tap --save=tests.txt`, it will run both files, because the file does 23 | not exist. 24 | 25 | Let's say that `foo.test.js` passes, but `bar.test.js` fails. At the end of 26 | the test run, `bar.test.js` will be written to the `tests.txt` file. So, if 27 | you run `tap --save=tests.txt` again, it will _only_ run `bar.test.js`. When 28 | tap does this, it makes sure to keep the old coverage information around, and 29 | only delete the coverage information related to that test file, so that you 30 | don't end up with corrupted coverage results. 31 | 32 | The workflow, then goes like this: 33 | 34 | - Run tests with a `--save` argument. 35 | - Note the failures. 36 | - Fix the code. 37 | - Run again with the same `--save` argument. 38 | - When the file is empty, run it one last time to do the entire suite again. 39 | 40 | ### Bail on first failure, then resume 41 | 42 | One useful way to work through a project is to run with both a `--save=file` 43 | and with `--bail`. In this case, tap will bail out on the first failure, and 44 | any tests that were skipped will be put into the save file, so you can fix the 45 | failure, and then pick right back up where you were by running with `tap --bail 46 | --save=file` again. 47 | 48 | ## Changed 49 | 50 | If you run tap with `--changed` (or `-n`), it will only run tests if the test 51 | file, or any of the files it covers, have changed since the last run. 52 | 53 | Because this depends on tracking which test covered which file, it requires 54 | that you have [coverage](/docs/coverage/) enabled (which is on by default anyway). 55 | 56 | ### Tip: Use a Coverage Map Module 57 | 58 | If you specify a [`--coverage-map=`](/docs/coverage/coverage-map/) 59 | option, then you can be very precise about _which_ files under test should 60 | trigger a re-run of the tests. 61 | -------------------------------------------------------------------------------- /lib/fixture.js: -------------------------------------------------------------------------------- 1 | const {writeFileSync, linkSync, statSync, symlinkSync} = require('fs') 2 | const {resolve, dirname} = require('path') 3 | const mkdirp = require('mkdirp') 4 | 5 | class Fixture { 6 | constructor (type, content) { 7 | this.type = type 8 | this.content = content 9 | switch (type) { 10 | case 'dir': 11 | if (!content || typeof content !== 'object') 12 | throw new TypeError('dir fixture must have object content') 13 | break 14 | case 'file': 15 | if (typeof content !== 'string' && !Buffer.isBuffer(content)) 16 | throw new TypeError('file fixture must have string/buffer content') 17 | break 18 | case 'link': 19 | case 'symlink': 20 | if (typeof content !== 'string') 21 | throw new TypeError(type + ' fixture must have string target') 22 | break 23 | default: 24 | throw new Error('invalid fixture type: ' + type) 25 | } 26 | } 27 | 28 | get [Symbol.toStringTag] () { 29 | return 'Fixture<' + this.type + '>' 30 | } 31 | 32 | // have to gather up symlinks for the end 33 | static make (abs, f, symlinks = null) { 34 | if (typeof f === 'string' || Buffer.isBuffer(f)) 35 | f = new Fixture('file', f) 36 | else if (f && typeof f === 'object' && !(f instanceof Fixture)) 37 | f = new Fixture('dir', f) 38 | else if (!(f instanceof Fixture)) 39 | throw new Error('invalid fixture type: ' + f) 40 | 41 | const isRoot = symlinks === null 42 | symlinks = symlinks || {} 43 | 44 | switch (f.type) { 45 | case 'symlink': 46 | // have to gather up symlinks for the end, because windows 47 | symlinks[abs] = f.content 48 | break 49 | case 'link': 50 | linkSync(resolve(dirname(abs), f.content), abs) 51 | break 52 | case 'dir': 53 | mkdirp.sync(abs) 54 | for (const [name, fixture] of Object.entries(f.content)) 55 | Fixture.make(`${abs}/${name}`, fixture, symlinks) 56 | break 57 | case 'file': 58 | writeFileSync(abs, f.content) 59 | break 60 | } 61 | 62 | // create all those symlinks we were asked for 63 | if (isRoot) { 64 | for (const [abs, target] of Object.entries(symlinks)) { 65 | symlinkSync(target, abs, isDir(abs, target) ? 'junction' : 'file') 66 | } 67 | } 68 | } 69 | } 70 | 71 | // check if a symlink target is a directory 72 | const isDir = (abs, target) => { 73 | try { 74 | return statSync(resolve(dirname(abs), target)).isDirectory() 75 | } catch (er) { 76 | return false 77 | } 78 | } 79 | 80 | module.exports = Fixture 81 | -------------------------------------------------------------------------------- /docs/src/components/navbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Flex} from 'rebass'; 3 | import styled from 'styled-components'; 4 | import {theme, breakpoints} from '../theme'; 5 | import hamburgerIcon from '../images/hamburger.svg'; 6 | import MobileNavbar from './mobileNavbar'; 7 | import NavLinks from './NavLinks'; 8 | import {Link as GatsbyLink} from 'gatsby'; 9 | 10 | const version = require('../../../package.json').version; 11 | 12 | const NavbarOuter = styled(Flex)` 13 | background-color: ${theme.colors.white}; 14 | box-shadow: 0px 0px 10px 0px #b8b3b3; 15 | height: 68px; 16 | align-items: center; 17 | font-family: Titillium Web; 18 | z-index: 3; 19 | position: sticky; 20 | top: 0; 21 | `; 22 | 23 | const Content = styled(Flex)` 24 | max-width: ${theme.width}px; 25 | width: 100%; 26 | margin: auto; 27 | justify-content: space-between; 28 | align-items: center; 29 | padding: 0 20px; 30 | `; 31 | 32 | const Links = styled(Flex)` 33 | display: none; 34 | 35 | @media screen and (min-width: ${breakpoints.TABLET}) { 36 | display: flex; 37 | align-items: flex-end; 38 | } 39 | `; 40 | 41 | const Logo = styled(GatsbyLink)` 42 | text-transform: uppercase; 43 | color: ${theme.colors.black}; 44 | font-weight: 700; 45 | font-size: 26px; 46 | padding: 0 10px; 47 | letter-spacing: 1px; 48 | text-shadow: 1px -2px 1px #88888852; 49 | text-decoration: none; 50 | 51 | small { 52 | text-transform: none; 53 | font-size: 13px; 54 | } 55 | `; 56 | 57 | const Hamburger = styled.button` 58 | background-image: url(${hamburgerIcon}); 59 | background-repeat: no-repeat; 60 | background-position: center; 61 | background-size: contain; 62 | height: 20px; 63 | width: 30px; 64 | background-color: transparent; 65 | cursor: pointer; 66 | border: none; 67 | 68 | @media screen and (min-width: ${breakpoints.TABLET}) { 69 | display: none; 70 | } 71 | `; 72 | 73 | class Navbar extends React.Component { 74 | 75 | state = { 76 | navOpen: false, 77 | } 78 | 79 | toggleNav = () => { 80 | this.setState({navOpen: !this.state.navOpen}); 81 | } 82 | 83 | render() { 84 | return( 85 | 86 | {this.state.navOpen && 87 | 88 | } 89 | 90 | 91 | Node Tap v{version} 92 | 93 | 94 | 95 | 96 | 97 | ); 98 | } 99 | } 100 | 101 | export default Navbar; 102 | -------------------------------------------------------------------------------- /test/clean-stacks.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // Just a utility to clean up the snapshots for output tests 4 | 5 | const yaml = require('tap-yaml') 6 | const internals = Object.keys(process.binding('natives')) 7 | 8 | module.exports = out => out 9 | // sort keys in yaml blocks 10 | .replace(/\n( *)---\n((\1.*\n)*)\1\.\.\.\n/g, ($0, $1, $2) => { 11 | let o 12 | try { 13 | o = yaml.parse($2) 14 | } catch (er) { 15 | return $0 16 | } 17 | const out = Object.keys(o).sort().reduce((s, k) => { 18 | if (k === 'requests' || k === 'handles') 19 | o[k] = o[k].map(r => ({ type: r.type })) 20 | s[k] = o[k] 21 | return s 22 | }, {}) 23 | return '\n' + $1 + '---\n' + $1 + 24 | yaml.stringify(out).trim().split('\n').join('\n' + $1) 25 | + '\n' + $1 + '...\n' 26 | }) 27 | 28 | // https://github.com/nodejs/node/issues/25806 29 | .replace(/ handles:\n - type: Timer\n/g, '') 30 | 31 | // this key has changed names 32 | .replace(/FSReqWrap/g, 'FSReqCallback') 33 | 34 | // remove time details 35 | .replace(/ # time=[0-9\.]+m?s( \{.*)?\n/g, ' # {time}$1\n') 36 | .replace(/\n# time=.*/g, '\n# {time}') 37 | 38 | // debug output 39 | .replace(/(\n|^)TAP ([0-9]+) /g, '$1TAP {pid} ') 40 | 41 | // stacks are always changing 42 | .replace(/\n(( {2})+)stack: \|-?\n((\1 .*).*\n)+/gm, 43 | '\n$1stack: |\n$1 {STACK}\n') 44 | .replace(/\n(( {2})+)stack: \>-?\n((\1 .*).*\n(\1\n)?)+/gm, 45 | '\n$1stack: |\n$1 {STACK}\n') 46 | .replace(/(?:\n|^)([a-zA-Z]*Error): (.*)\n(( at .*\n)*)+/gm, 47 | '\n$1: $2\n {STACK}\n') 48 | .replace(/:[0-9]+:[0-9]+(\)?\n)/g, '#:#$1') 49 | .replace(/(line|column): [0-9]+/g, '$1: #') 50 | 51 | // type and function change often between node/v8 versions 52 | .replace(/\n( +)function: .*(\n\1 .*)*\n/g, '\n') 53 | .replace(/\n( +)method: .*(\n\1 .*)*\n/g, '\n') 54 | .replace(/\n( +)type: .*\n/g, '\n') 55 | .replace(/\n( +)file: (.*)\n/g, ($0, $1, $2) => 56 | internals.indexOf($2.replace(/\.js$/, '')) === -1 && !/node:/.test($0) 57 | ? $0 : '\n' + $1 + 'file: #INTERNAL#\n' 58 | ) 59 | 60 | // timeout values are different when coverage is present 61 | .replace(/\n( *)timeout: (30000|240000)(\n|$)/g, '\n$1timeout: {default}$3') 62 | 63 | // fix references to cwd 64 | .split(process.cwd()).join('{CWD}') 65 | .split(require('path').resolve(__dirname, '..')).join('{TAPDIR}') 66 | .split(process.execPath).join('{NODE}') 67 | 68 | .split(process.env.HOME).join('{HOME}') 69 | 70 | // the arrows in source printing bits, make that consistent 71 | .replace(/^(\s*)-+\^$/mg, '$1--^') 72 | 73 | // nothing to see here 74 | if (module === require.main) 75 | console.log('TAP version 13\n1..1\nok - 1\n') 76 | -------------------------------------------------------------------------------- /lib/snapshot.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs') 4 | const mkdirp = require('mkdirp') 5 | const path = require('path') 6 | const rimraf = require('rimraf') 7 | const cwd = process.cwd() 8 | 9 | class Snapshot { 10 | constructor (test) { 11 | this.indexes = new Map() 12 | this.test = test 13 | // name them .test.js so that nyc ignores them 14 | this.file = path.resolve( 15 | cwd, 16 | 'tap-snapshots', 17 | this.test.fullname.trim().replace(/[^a-zA-Z0-9\._\-]+/g, '-') 18 | ) + '.test.js' 19 | this.snapshot = null 20 | } 21 | 22 | // should only ever call _one_ of read/save 23 | read (message) { 24 | const index = +this.indexes.get(message) || 1 25 | this.indexes.set(message, index + 1) 26 | try { 27 | this.snapshot = this.snapshot || require(this.file) 28 | } catch (er) { 29 | throw new Error( 30 | 'Snapshot file not found: ' + this.file + '\n' + 31 | 'Run with TAP_SNAPSHOT=1 in the environment\n' + 32 | 'to create snapshot files' 33 | ) 34 | } 35 | 36 | const entry = message + ' ' + index 37 | const s = this.snapshot[entry] 38 | if (s === undefined) 39 | throw new Error( 40 | 'Snapshot entry not found: "' + entry + '"\n' + 41 | 'Run with TAP_SNAPSHOT=1 in the environment\n' + 42 | 'to create snapshots' 43 | ) 44 | 45 | return s.replace(/^\n|\n$/g, '') 46 | } 47 | 48 | snap (data, message) { 49 | const index = +this.indexes.get(message) || 1 50 | this.indexes.set(message, index + 1) 51 | this.snapshot = this.snapshot || {} 52 | this.snapshot[message + ' ' + index] = data 53 | } 54 | 55 | save () { 56 | if (!this.snapshot) 57 | rimraf.sync(this.file) 58 | else { 59 | const escape = s => s 60 | .replace(/\\/g, '\\\\') 61 | .replace(/\`/g, '\\\`') 62 | .replace(/\$\{/g, '\\${') 63 | 64 | const data = 65 | '/* IMPORTANT\n' + 66 | ' * This snapshot file is auto-generated, but designed for humans.\n' + 67 | ' * It should be checked into source control and tracked carefully.\n' + 68 | ' * Re-generate by setting TAP_SNAPSHOT=1 and running tests.\n' + 69 | ' * Make sure to inspect the output below. Do not ignore changes!\n' + 70 | ' */\n\'use strict\'\n' + ( 71 | Object.keys(this.snapshot).sort().map(s => 72 | `exports[\`${ 73 | escape(s) 74 | }\`] = \`\n${ 75 | escape(this.snapshot[s]) 76 | }\n\`\n`).join('\n')) 77 | mkdirp.sync(path.dirname(this.file)) 78 | const writeFile = require('write-file-atomic') 79 | writeFile.sync(this.file, data, 'utf8') 80 | } 81 | } 82 | } 83 | 84 | module.exports = Snapshot 85 | -------------------------------------------------------------------------------- /docs/static/my-awesome-module/coverage-1/lcov-report/block-navigation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var jumpToCode = (function init() { 3 | // Classes of code we would like to highlight in the file view 4 | var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; 5 | 6 | // Elements to highlight in the file listing view 7 | var fileListingElements = ['td.pct.low']; 8 | 9 | // We don't want to select elements that are direct descendants of another match 10 | var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` 11 | 12 | // Selecter that finds elements on the page to which we can jump 13 | var selector = 14 | fileListingElements.join(', ') + 15 | ', ' + 16 | notSelector + 17 | missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` 18 | 19 | // The NodeList of matching elements 20 | var missingCoverageElements = document.querySelectorAll(selector); 21 | 22 | var currentIndex; 23 | 24 | function toggleClass(index) { 25 | missingCoverageElements 26 | .item(currentIndex) 27 | .classList.remove('highlighted'); 28 | missingCoverageElements.item(index).classList.add('highlighted'); 29 | } 30 | 31 | function makeCurrent(index) { 32 | toggleClass(index); 33 | currentIndex = index; 34 | missingCoverageElements.item(index).scrollIntoView({ 35 | behavior: 'smooth', 36 | block: 'center', 37 | inline: 'center' 38 | }); 39 | } 40 | 41 | function goToPrevious() { 42 | var nextIndex = 0; 43 | if (typeof currentIndex !== 'number' || currentIndex === 0) { 44 | nextIndex = missingCoverageElements.length - 1; 45 | } else if (missingCoverageElements.length > 1) { 46 | nextIndex = currentIndex - 1; 47 | } 48 | 49 | makeCurrent(nextIndex); 50 | } 51 | 52 | function goToNext() { 53 | var nextIndex = 0; 54 | 55 | if ( 56 | typeof currentIndex === 'number' && 57 | currentIndex < missingCoverageElements.length - 1 58 | ) { 59 | nextIndex = currentIndex + 1; 60 | } 61 | 62 | makeCurrent(nextIndex); 63 | } 64 | 65 | return function jump(event) { 66 | switch (event.which) { 67 | case 78: // n 68 | case 74: // j 69 | goToNext(); 70 | break; 71 | case 66: // b 72 | case 75: // k 73 | case 80: // p 74 | goToPrevious(); 75 | break; 76 | } 77 | }; 78 | })(); 79 | window.addEventListener('keydown', jumpToCode); 80 | -------------------------------------------------------------------------------- /test/run/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const mkdirp = require('mkdirp') 4 | const rimraf = require('rimraf') 5 | // const rimraf = { sync: () => {} } 6 | const path = require('path') 7 | const cp = require('child_process') 8 | const execFile = cp.execFile 9 | const node = process.execPath 10 | const bin = require.resolve('../../bin/run.js') 11 | const tap = JSON.stringify(path.join(__dirname, '../..') + '/') 12 | const t = require('../../') 13 | 14 | const dir = path.join(__dirname, `../../cli-tests-${process.pid}`) 15 | 16 | // set this forcibly so it doesn't interfere with other tests. 17 | delete process.env.TAP_DIAG 18 | delete process.env.TAP_BAIL 19 | delete process.env.TAP_COLORS 20 | delete process.env.TAP_TIMEOUT 21 | 22 | const winSkip = process.platform === 'win32' ? 'known windows failure' : false 23 | 24 | const cleanStacks = require('../clean-stacks.js') 25 | // also clean up NYC output a bit, because the line lengths 26 | // in the text report can vary on different platforms. 27 | const clean = string => cleanStacks(string) 28 | .replace(/uncovered line( #)?s/i, 'Uncovered Lines') 29 | .replace(/ +\|/g, ' |') 30 | .replace(/\| +/g, '| ') 31 | .replace(/-+\|/g, '-|') 32 | .replace(/\|-+/g, '|-') 33 | // two that show up in config dump snapshots 34 | .replace(/snapshot: (true|false)\n/, '') 35 | .replace(/cli-tests-[0-9]+/g, 'cli-tests') 36 | 37 | t.cleanSnapshot = clean 38 | 39 | const run = (args, options, cb) => { 40 | if (options && options.env) 41 | options.env = Object.keys(process.env).reduce((env, k) => { 42 | if (env[k] === undefined) 43 | env[k] = process.env[k] 44 | return env 45 | }, options.env) 46 | 47 | return execFile(node, [bin, '--no-coverage'].concat(args), options, cb) 48 | } 49 | 50 | const tmpfile = (t, filename, content) => { 51 | const parts = filename.split('/') 52 | // make any necessary dirs 53 | if (parts.length > 1) 54 | mkdirp.sync(path.join(dir, parts.slice(0, -1).join('/'))) 55 | if (t.tmpfiles) 56 | t.tmpfiles.push(path.join(dir, parts[0])) 57 | else { 58 | t.tmpfiles = [path.join(dir, parts[0])] 59 | if (process.env._TAP_TEST_NO_TEARDOWN_TMP !== '1') 60 | t.teardown(() => t.tmpfiles.forEach(f => rimraf.sync(f))) 61 | } 62 | filename = path.join(dir, filename) 63 | fs.writeFileSync(filename, content) 64 | return path.relative('', filename) 65 | } 66 | 67 | if (module === require.main) 68 | t.pass('this is fine') 69 | else { 70 | mkdirp.sync(dir) 71 | if (process.env._TAP_TEST_NO_TEARDOWN_TMP !== '1') { 72 | t.teardown(() => rimraf.sync(dir)) 73 | process.on('exit', () => rimraf.sync(dir)) 74 | } 75 | } 76 | 77 | module.exports = { 78 | tmpfile, 79 | run, 80 | bin, 81 | tap, 82 | node, 83 | clean, 84 | dir, 85 | t, 86 | winSkip, 87 | } 88 | -------------------------------------------------------------------------------- /test/run/output-file.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | bin, 5 | tap, 6 | node, 7 | dir, 8 | t, 9 | winSkip, 10 | } = require('./') 11 | 12 | const path = require('path') 13 | const fs = require('fs') 14 | 15 | const tapdata = `TAP version 13 16 | 1..1 17 | ok 1 - totally fine result from stdin 18 | ` 19 | 20 | t.test('output-file', t => { 21 | const ok = tmpfile(t, 'ok.js', `require(${tap}).pass('this is fine')`) 22 | t.test('ok.js', t => { 23 | run([ok, `--output-file=${dir}/output.tap`], (er, o, e) => { 24 | t.equal(er, null) 25 | t.matchSnapshot(o, 'output') 26 | t.matchSnapshot(e, 'stderr') 27 | t.matchSnapshot(fs.readFileSync(`${dir}/output.tap`, 'utf8'), 28 | 'output file') 29 | t.end() 30 | }) 31 | }) 32 | t.test('stdin', t => { 33 | run(['-', `-o${dir}/output.tap`], (er, o, e) => { 34 | t.equal(er, null) 35 | t.matchSnapshot(o, 'output') 36 | t.matchSnapshot(e, 'stderr') 37 | t.matchSnapshot(fs.readFileSync(`${dir}/output.tap`, 'utf8'), 38 | 'output file') 39 | t.end() 40 | }).stdin.end(tapdata) 41 | }) 42 | t.test('file and stdin together', t => { 43 | run(['-', ok, `-o${dir}/output.tap`], (er, o, e) => { 44 | t.equal(er, null) 45 | t.matchSnapshot(o, 'output') 46 | t.matchSnapshot(e, 'stderr') 47 | t.matchSnapshot(fs.readFileSync(`${dir}/output.tap`, 'utf8'), 48 | 'output file') 49 | t.end() 50 | }).stdin.end(tapdata) 51 | }) 52 | t.end() 53 | }) 54 | 55 | t.test('output-file', t => { 56 | const d = `${dir}/output/${path.basename(dir)}` 57 | const ok = tmpfile(t, 'ok.js', `require(${tap}).pass('this is fine')`) 58 | t.test('ok.js', t => { 59 | run([ok, `--output-dir=${dir}/output`], (er, o, e) => { 60 | t.equal(er, null) 61 | t.matchSnapshot(o, 'output') 62 | t.matchSnapshot(e, 'stderr') 63 | t.matchSnapshot(fs.readFileSync(`${d}/ok.js.tap`, 'utf8'), 64 | 'output file') 65 | t.end() 66 | }) 67 | }) 68 | t.test('stdin', t => { 69 | run(['-', `-d${dir}/output`], (er, o, e) => { 70 | t.equal(er, null) 71 | t.matchSnapshot(o, 'output') 72 | t.matchSnapshot(e, 'stderr') 73 | t.matchSnapshot(fs.readFileSync(`${dir}/output/stdin.tap`, 'utf8'), 74 | 'output file') 75 | t.end() 76 | }).stdin.end(tapdata) 77 | }) 78 | t.test('file and stdin together', t => { 79 | run(['-', ok, `-d${dir}/output`], (er, o, e) => { 80 | t.equal(er, null) 81 | t.matchSnapshot(o, 'output') 82 | t.matchSnapshot(e, 'stderr') 83 | t.matchSnapshot(fs.readFileSync(`${d}/ok.js.tap`, 'utf8'), 84 | 'ok.js output file') 85 | t.matchSnapshot(fs.readFileSync(`${dir}/output/stdin.tap`, 'utf8'), 86 | 'stdin output file') 87 | t.end() 88 | }).stdin.end(tapdata) 89 | }) 90 | t.end() 91 | }) 92 | -------------------------------------------------------------------------------- /test/stdin.js: -------------------------------------------------------------------------------- 1 | const t = require('../') 2 | const Stdin = require('../lib/stdin.js') 3 | const MP = require('minipass') 4 | 5 | process.env.TAP_BAIL = '' 6 | process.env.TAP_BUFFER = '' 7 | 8 | t.test('uses stdin if no stream provided', t => { 9 | const s = new Stdin() 10 | t.equal(s.stream, process.stdin) 11 | t.equal(s.name, '/dev/stdin') 12 | t.end() 13 | }) 14 | 15 | t.test('basic test', t => { 16 | const stream = new MP() 17 | const s = new Stdin({ 18 | tapStream: stream, 19 | name: 'foo', 20 | buffered: true 21 | }) 22 | t.equal(s.stream, stream) 23 | t.equal(s.name, 'foo') 24 | 25 | s.main(_ => { 26 | t.match(s.results, { 27 | ok: true, 28 | count: 1, 29 | pass: 1, 30 | fail: 0, 31 | bailout: false, 32 | plan: { 33 | start: 1, 34 | end: 1, 35 | skipAll: false 36 | }, 37 | failures: [] 38 | }) 39 | t.end() 40 | }) 41 | 42 | s.stream.end(`TAP version 13 43 | 1..1 44 | ok 1 - this is fine 45 | `) 46 | }) 47 | 48 | t.test('failure test', t => { 49 | const stream = new MP() 50 | const s = new Stdin({ 51 | tapStream: stream 52 | }) 53 | 54 | s.main(_ => { 55 | t.match(s.results, { 56 | ok: false, 57 | count: 2, 58 | pass: 1, 59 | fail: 1, 60 | bailout: false, 61 | todo: 0, 62 | skip: 0, 63 | plan: { 64 | start: 1, 65 | end: 2, 66 | skipAll: false 67 | }, 68 | failures: [{ 69 | ok: false, 70 | id: 2, 71 | name: 'oops' 72 | }] 73 | }) 74 | t.end() 75 | }) 76 | 77 | s.stream.write(`TAP version 13 78 | ok 1 - this is fine 79 | `) 80 | 81 | s.threw(new Error('oops')) 82 | }) 83 | 84 | t.test('stream failure', t => { 85 | const stream = new MP() 86 | const s = new Stdin({ 87 | tapStream: stream 88 | }) 89 | 90 | s.main(_ => { 91 | t.match(s.results, { 92 | ok: false, 93 | count: 2, 94 | pass: 1, 95 | fail: 1, 96 | bailout: false, 97 | todo: 0, 98 | skip: 0, 99 | plan: { 100 | start: 1, 101 | end: 2, 102 | skipAll: false 103 | }, 104 | failures: [{ 105 | ok: false, 106 | id: 2, 107 | name: 'oops', 108 | diag: { tapCaught: 'stdinError' }, 109 | }] 110 | }) 111 | t.end() 112 | }) 113 | 114 | s.stream.write(`TAP version 13 115 | ok 1 - this is fine 116 | `) 117 | 118 | s.stream.emit('error', new Error('oops')) 119 | }) 120 | 121 | t.test('doting parent', t => { 122 | const EE = require('events').EventEmitter 123 | const parent = new EE() 124 | const tapStream = new MP() 125 | parent.on('stdin', child => { 126 | t.equal(child, s) 127 | t.end() 128 | }) 129 | const s = new Stdin({tapStream, parent}) 130 | s.main(() => {}) 131 | }) 132 | -------------------------------------------------------------------------------- /docs/src/content/docs/coverage/coverage-map/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Coverage Maps 3 | section: 8.02 4 | redirect_from: 5 | - /coverage-map/ 6 | - /coverage-map 7 | --- 8 | # Coverage Maps 9 | 10 | If you specify a `--coverage-map=` option, then you can be very precise 11 | about _which_ files under test should be covered by a specific test. 12 | 13 | A coverage map is a Node.js module that exports a single function. This 14 | function takes a test file as an argument, and returns a single filename or an 15 | array of program files that should be covered by that test. 16 | 17 | This is useful in cases where you want to have a part of your program at 18 | `foo.js` which should be 100% covered by `foo.test.js`, for example. Coverage 19 | generated with a coverage map will help guarantee that you are actually testing 20 | a piece of code directly, rather than "accidentally" adding lines of coverage 21 | via integration. 22 | 23 | When used with [`--changed`](/docs/save-failures-run-changed/) or 24 | [`--watch`](/docs/watch/), this also means that you limit which file's changes will 25 | trigger which test to re-run. Also, because less of your program is 26 | instrumented for each test, the overall suite can run significantly faster. 27 | 28 | ## Module Structure 29 | 30 | The coverage map must export a single function. This function takes a test filename as an argument, and returns one of the following values: 31 | 32 | - A filename of a single program file that should be covered by this test. 33 | - An array of filenames of program files that should be covered by this test. 34 | - An empty array, indicating that all program files should be covered, 35 | following NYC's default coverage logic. 36 | - Any falsey value, indicating that this test should not provide coverage. 37 | This is useful for regression tests that don't add coverage, but do verify 38 | some edge-case bug. 39 | 40 | ## Example 41 | 42 | For example, you might have a file at `index.js` which is the main entry point 43 | of your library or application, and exports a bunch of other functionality from 44 | inside a `lib` folder. If the file at `lib/foo.js` loads the index (perhaps 45 | just for one or two things), then this effectively means that any test that 46 | loads `lib/foo.js` _also_ loads everything else. 47 | 48 | Now any change anywhere in the program triggers a full test suite run, so why 49 | bother using `--changed` at all? 50 | 51 | With a `--coverage-map` argument, you can specify that the test at 52 | `foo.test.js` should only cover `foo.js`. 53 | 54 | Here's an example coverage-map file, which maps `*.test.js` to the 55 | corresponding `*.js`. 56 | 57 | ```js 58 | // map.js 59 | module.exports = testFile => testFile.replace(/\.test\.js$/, '.js') 60 | ``` 61 | 62 | To run tap with this coverage map, run this command: 63 | 64 | ``` 65 | tap --coverage-map=map.js 66 | ``` 67 | 68 | Or, you can add this config to your package.json file: 69 | 70 | ```json 71 | { 72 | "tap": { 73 | "coverage-map": "map.js" 74 | } 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /test/run/watermarks.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | node, 4 | dir, 5 | bin, 6 | tap, 7 | t, 8 | } = require('./') 9 | 10 | const { execFile } = require('child_process') 11 | const {dirname, basename} = require('path') 12 | 13 | const clean = t.cleanSnapshot 14 | t.cleanSnapshot = str => clean(str).replace(/[0-9\.]+m?s/g, '{TIME}') 15 | 16 | // escape from new york 17 | const escapePath = `${dirname(process.execPath)}:${process.env.PATH}` 18 | const esc = tmpfile(t, 'runtest.sh', 19 | `#!/bin/bash 20 | export PATH=${escapePath} 21 | "${node}" "${bin}" "\$@" \\ 22 | --cov \\ 23 | --nyc-arg=--temp-dir="${dir}/.nyc_output" \\ 24 | --nyc-arg=--cache=false 25 | `) 26 | 27 | const escape = (args, cb) => { 28 | const options = { 29 | cwd: dir, 30 | env: Object.keys(process.env).filter( 31 | k => !/^TAP|NYC|SW_ORIG|PWD/.test(k) 32 | ).reduce((env, k) => { 33 | if (!env.hasOwnProperty(k)) 34 | env[k] = process.env[k] 35 | return env 36 | }, { TAP_NO_ESM: '1' }), 37 | } 38 | const a = [basename(esc)].concat( 39 | args.map(a => !/^-/.test(a) ? basename(a) : a) 40 | ) 41 | return execFile('bash', a, options, cb) 42 | } 43 | 44 | const branch = tmpfile(t, 'branch.js', ` 45 | const ok = n => { 46 | if (n) { 47 | console.log('truthy') 48 | if (n > 5) 49 | console.log('gt 5') 50 | } else { 51 | console.log('falsey') 52 | } 53 | } 54 | const notCalled = () => {} 55 | module.exports = ok 56 | `) 57 | 58 | const test = tmpfile(t, 't.js', ` 59 | const ok = require('./branch.js') 60 | ok(1) 61 | ok(6) 62 | const t = require(${tap}) 63 | t.pass('this is fine') 64 | `) 65 | 66 | const args = [ 67 | test, 68 | '-Rtap', 69 | '-c', 70 | '--cov', 71 | '--nyc-arg=--include=' + branch, 72 | '--coverage-report=text', 73 | ] 74 | 75 | t.test('default watermarks, all set at 100, red', t => 76 | escape([...args, '-c'], (er, o, e) => { 77 | t.matchSnapshot(o, 'stdout') 78 | t.matchSnapshot(e, 'stderr') 79 | t.end() 80 | })) 81 | 82 | t.test('unmet, red', t => 83 | escape([ 84 | ...args, 85 | '-c', 86 | '--branches=76', 87 | '--statements=88', 88 | '--functions=51', 89 | '--lines=88', 90 | ], (er, o, e) => { 91 | t.matchSnapshot(o, 'stdout') 92 | t.matchSnapshot(e, 'stderr') 93 | t.end() 94 | })) 95 | 96 | 97 | t.test('less than halfway to 100, yellow', t => 98 | escape([ 99 | ...args, 100 | '-c', 101 | '--branches=51', 102 | '--statements=76', 103 | '--functions=1', 104 | '--lines=76', 105 | ], (er, o, e) => { 106 | t.matchSnapshot(o, 'stdout') 107 | t.matchSnapshot(e, 'stderr') 108 | t.end() 109 | })) 110 | 111 | t.test('more than halfway to 100, green', t => 112 | escape([ 113 | ...args, 114 | '-c', 115 | '--branches=49', 116 | '--statements=71', 117 | '--functions=0', 118 | '--lines=71' 119 | ], (er, o, e) => { 120 | t.matchSnapshot(o, 'stdout') 121 | t.matchSnapshot(e, 'stderr') 122 | t.end() 123 | })) 124 | -------------------------------------------------------------------------------- /docs/src/content/docs/reporting/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reporting 3 | section: 7 4 | redirect_from: 5 | - /reporting/ 6 | - /reporting 7 | --- 8 | 9 | # Reporting 10 | 11 | Tests can be reported in a variety of different ways. 12 | 13 | When you run a test script directly, it'll always output 14 | [TAP](/tap-protocol/). The tap runner will interpret this 15 | output, and can format it in a variety of different ways. 16 | 17 | Node-tap includes 2 reporting engines, and you can extend either one, or 18 | consume the TAP formatted output in custom modules of your own. 19 | 20 | The newer React-based reporter is called [treport](http://npm.im/treport). It 21 | uses [ink](http://npm.im/ink) to provide live feedback about tests in progress. 22 | 23 | The older streams-based bundled reporting engine is 24 | [tap-mocha-reporter](http://npm.im/tap-mocha-reporter), so named because it 25 | ports many of the report styles built into 26 | [mocha](http://mochajs.org/#reporters). 27 | 28 | The `--reporter` or `-R` argument on the command line can specify: 29 | 30 | - Any built-in reporter from either of these two libraries. 31 | - The name of a command-line program which parses a TAP stream. The 32 | `--reporter-arg=` or `-r` option can be specified one or more times 33 | to provide a list of arguments to pass to CLI reporters. 34 | - The name of a Node module that exports either a Stream or a treport-style 35 | React.Component class. 36 | 37 | The built-in reports are: 38 | 39 | ### base 40 | 41 | The default when stdout is a terminal and colors are enabled. Also the class 42 | to extend to create new treport reporters. Does all the things, handles all 43 | the edge cases, and ends with a pleasant surprise. 44 | 45 | ### terse 46 | 47 | A lot like Base, but says a lot less. No timer, no list of tests concurrently 48 | running, nothing printed on test passing. Just the failures and the terse 49 | summary. 50 | 51 | ### specy 52 | 53 | A `spec` style reporter with the current running jobs and Terse summary and 54 | footer. 55 | 56 | ### tap 57 | 58 | Setting `--reporter=tap` will dump the output as a raw TAP stream. 59 | 60 | This is the default when stdout is _not_ a terminal, or colors are disabled. 61 | 62 | ### classic 63 | 64 | The old default. Show a summary of each test file being run, along with 65 | reporting each failure and pending test. 66 | 67 | ### silent 68 | 69 | Output absolutely nothing 70 | 71 | ### spec 72 | 73 | Output based on rspec, with hierarchical indentation and unicode red and green 74 | checks and X's. 75 | 76 | ### xunit 77 | 78 | XML output popular in .NET land. 79 | 80 | ### json 81 | 82 | Output results in one big JSON object. 83 | 84 | ### jsonstream 85 | 86 | Output results as a stream of `\n`-delimited JSON. 87 | 88 | ### dot 89 | 90 | Output a dot for each pass and failure. 91 | 92 | ### list 93 | 94 | List out each test as it's run. 95 | 96 | ### min 97 | 98 | Just the post-test summary of failures and test count. 99 | 100 | ### nyan 101 | 102 | A magical cat who is also a toaster pastry. 103 | 104 | ### dump 105 | 106 | Mostly for debugging tap-mocha-reporter, dumping out the TAP 107 | output and the way that its being interpreted. 108 | -------------------------------------------------------------------------------- /docs/src/content/docs/api/mochalike/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mocha-like DSL 3 | section: 5.09 4 | redirect_from: 5 | - /mochalike/ 6 | - /mochalike 7 | --- 8 | 9 | # Mocha-like DSL 10 | 11 | If you prefer to use a BDD-style DSL like 12 | [mocha](http://mochajs.org/) instead of the traditional 13 | `t.whatever()`, tap lets you do that! 14 | 15 | You can do this by using the methods on the `tap.mocha` object, or 16 | dump them into the global namespace using `tap.mochaGlobals()`. 17 | 18 | So, instead of this: 19 | 20 | ```javascript 21 | // tap.js 22 | const t = require('tap') 23 | t.test('Array.indexOf', t => { 24 | const array = [1, 2, 3] 25 | t.test('when item is not found', t => { 26 | t.test('does not throw an error', t => { 27 | array.indexOf(4) 28 | t.end() 29 | }) 30 | t.equal(array.indexOf(4), -1, 'returns -1') 31 | t.end() 32 | }) 33 | t.end() 34 | }) 35 | ``` 36 | 37 | You can do this: 38 | 39 | ```javascript 40 | // bdd.js 41 | require('tap').mochaGlobals() 42 | const should = require('should') 43 | describe('Array.indexOf', () => { 44 | const array = [1, 2, 3] 45 | context('when item is not found', () => { 46 | it('does not throw an error', () => { 47 | array.indexOf(4) 48 | }) 49 | it('returns -1', () => { 50 | array.indexOf(4).should.equal(-1) 51 | }) 52 | }) 53 | }) 54 | ``` 55 | 56 | Running these with the `spec` reporter results in this output: 57 | 58 | ``` 59 | $ tap -Rspec tap.js bdd.js 60 | 61 | tap.js 62 | Array.indexOf 63 | when item is not found 64 | ✓ does not throw an error 65 | ✓ returns -1 66 | 67 | bdd.js 68 | Array.indexOf 69 | when item is not found 70 | ✓ does not throw an error 71 | ✓ returns -1 72 | 73 | 74 | 4 passing (527.355ms) 75 | ``` 76 | 77 | The following functions are provided: 78 | 79 | * `describe(function () {})` 80 | 81 | Defines a test suite. Runs synchronously. 82 | 83 | * `context(function () {})` 84 | 85 | Alias for `describe`. 86 | 87 | * `it(function ([done]) {})` 88 | 89 | Defines a test block. As long as nothing throws, it is considered 90 | passing. 91 | 92 | If a `Promise` is returned, then it'll wait for the Promise to 93 | resolve before continuing to the next test block. 94 | 95 | If the function takes an argument, then it'll get a callback which 96 | must be called to signal that the test block is complete. 97 | 98 | If the function does not take an argument, and does not return a 99 | Promise, then it is assumed to be done immediately. 100 | 101 | * `before(function ([done]) {})` 102 | 103 | Similar to `it`, but doesn't get reported. Run immediately. 104 | 105 | * `after(function ([done]) {})` 106 | 107 | Similar to `it`, but doesn't get reported. Run after all test 108 | blocks are completed. 109 | 110 | * `beforeEach(function ([done]) {})` 111 | 112 | Run before each test block. 113 | 114 | * `afterEach(function ([done]) {})` 115 | 116 | Run after each test block. 117 | 118 | Using the mocha-like BDD interface defines tests hanging off of the 119 | root `tap` object, so tests defined in this way will always start at 120 | the "top level", even if they are defined within a `t.test(...)` 121 | function. 122 | -------------------------------------------------------------------------------- /test/run/dump-config.js: -------------------------------------------------------------------------------- 1 | const { 2 | tmpfile, 3 | run, 4 | t, 5 | clean, 6 | } = require('./') 7 | 8 | t.cleanSnapshot = o => clean(o).replace(/jobs: \d+/, 'jobs: {number}') 9 | 10 | process.env.TAP_NO_ESM = '1' 11 | 12 | t.test('shotgun a bunch of option parsing junk', t => { 13 | run([ 14 | '--dump-config', '-J', '--jobs', '4', 15 | '--no-browser', '--no-coverage-report', '--coverage-report', 'json', 16 | '--coverage-report=html', '--no-cov', '--cov', '--save', 'foo.txt', 17 | '--reporter=spec', '--gc', '--strict', '--debug', '--debug-brk', 18 | '--harmony', '--node-arg=xyz', '--check-coverage', '--test-arg=xyz', 19 | '--test-arg', 'abc', '--100', '--branches=99', '--lines', '100', 20 | '--color', '-C', '--output-file=out.txt', '--no-timeout', 21 | '--timeout', '99', '--invert', '--no-invert', '--grep', 'x', 22 | '--grep=/y/i', '--bail', '--no-bail', '--only', '-R', 'spec', 23 | '--node-arg', 'abc', '--nyc-arg', 'abc', '-o', 'out.txt', 24 | '--comments', '-M', 'map.js', '--no-coverage-map' 25 | ], { env: { 26 | TAP: '0', 27 | TAP_BAIL: '0', 28 | }}, (er, o, e) => { 29 | t.equal(er, null) 30 | t.matchSnapshot(o, 'output') 31 | t.end() 32 | }) 33 | }) 34 | 35 | t.test('package.json parsing', t => { 36 | const cases = { 37 | good: JSON.stringify({ 38 | tap: { 39 | 100: true, 40 | bail: true, 41 | } 42 | }), 43 | bad: '!$@Q$AERWA#WERSTE$%W', 44 | missing: JSON.stringify({ 45 | foo: { 46 | lines: 69, 47 | bail: true, 48 | } 49 | }) 50 | } 51 | for (const c in cases) { 52 | t.test(c, t => { 53 | const data = cases[c] 54 | const pj = tmpfile(t, 'package.json', data) 55 | const path = require('path') 56 | const dir = path.dirname(pj) 57 | run(['--dump-config', '-B'], { 58 | cwd: dir, 59 | }, (er, o, e) => { 60 | t.equal(er, null) 61 | t.matchSnapshot(o, 'output') 62 | t.end() 63 | }) 64 | }) 65 | } 66 | t.end() 67 | }) 68 | 69 | t.test('turn color off and back on again', t => { 70 | run(['--no-color', '-c', '--dump-config'], { env: { 71 | TAP: '0', 72 | TAP_COLORS: '1', 73 | }}, (er, o, e) => { 74 | t.equal(er, null) 75 | t.matchSnapshot(o, 'output') 76 | t.end() 77 | }) 78 | }) 79 | 80 | t.test('short options as well as short flags', t => { 81 | run(['--dump-config','-j2','-Cb','-t=0' ], { env: { 82 | TAP: '0' 83 | }}, (er, o, e) => { 84 | t.equal(er, null) 85 | t.matchSnapshot(o, 'output') 86 | t.end() 87 | }) 88 | }) 89 | 90 | t.test('good rc file', t => { 91 | const rc = tmpfile(t, 'taprc', ` 92 | reporter: spec 93 | jobs: 3 94 | 100: true 95 | `) 96 | run(['--dump-config', '-j4'], { env: { 97 | TAP_RCFILE: rc, 98 | TAP: 0 99 | }}, (er, o, e) => { 100 | t.equal(er, null) 101 | t.matchSnapshot(o, 'output') 102 | t.end() 103 | }) 104 | }) 105 | 106 | t.test('empty rc file', t => { 107 | const rc = tmpfile(t, 'taprc', '') 108 | run(['--dump-config', '-c'], { env: { 109 | TAP_RCFILE: rc, 110 | TAP: '0', 111 | TAP_COLORS: '1' 112 | }}, (er, o, e) => { 113 | t.equal(er, null) 114 | t.matchSnapshot(o, 'output') 115 | t.end() 116 | }) 117 | }) 118 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tap", 3 | "version": "14.11.0", 4 | "author": "Isaac Z. Schlueter (http://blog.izs.me)", 5 | "description": "A Test-Anything-Protocol library for JavaScript", 6 | "homepage": "http://www.node-tap.org/", 7 | "bin": { 8 | "tap": "bin/run.js" 9 | }, 10 | "main": "lib/tap.js", 11 | "engines": { 12 | "node": ">=8" 13 | }, 14 | "dependencies": { 15 | "@types/react": "^16.9.16", 16 | "async-hook-domain": "^1.1.3", 17 | "bind-obj-methods": "^2.0.0", 18 | "browser-process-hrtime": "^1.0.0", 19 | "chokidar": "^3.3.0", 20 | "color-support": "^1.1.0", 21 | "coveralls": "^3.0.11", 22 | "diff": "^4.0.1", 23 | "esm": "^3.2.25", 24 | "findit": "^2.0.0", 25 | "flow-remove-types": "^2.112.0", 26 | "foreground-child": "^1.3.3", 27 | "fs-exists-cached": "^1.0.0", 28 | "function-loop": "^1.0.2", 29 | "glob": "^7.1.6", 30 | "import-jsx": "^3.1.0", 31 | "ink": "^2.6.0", 32 | "isexe": "^2.0.0", 33 | "istanbul-lib-processinfo": "^1.0.0", 34 | "jackspeak": "^1.4.0", 35 | "minipass": "^3.1.1", 36 | "mkdirp": "^0.5.4", 37 | "nyc": "^14.1.1", 38 | "opener": "^1.5.1", 39 | "own-or": "^1.0.0", 40 | "own-or-env": "^1.0.1", 41 | "react": "^16.12.0", 42 | "rimraf": "^2.7.1", 43 | "signal-exit": "^3.0.0", 44 | "source-map-support": "^0.5.16", 45 | "stack-utils": "^1.0.3", 46 | "tap-mocha-reporter": "^5.0.0", 47 | "tap-parser": "^10.0.1", 48 | "tap-yaml": "^1.0.0", 49 | "tcompare": "^3.0.0", 50 | "treport": "^1.0.2", 51 | "trivial-deferred": "^1.0.1", 52 | "ts-node": "^8.5.2", 53 | "typescript": "^3.7.2", 54 | "which": "^2.0.2", 55 | "write-file-atomic": "^3.0.1", 56 | "yaml": "^1.7.2", 57 | "yapool": "^1.0.0" 58 | }, 59 | "keywords": [ 60 | "assert", 61 | "tap", 62 | "test", 63 | "testing" 64 | ], 65 | "license": "ISC", 66 | "repository": "https://github.com/tapjs/node-tap.git", 67 | "scripts": { 68 | "snap": "bash scripts/snap.sh", 69 | "test": "node bin/run.js test -M coverage-map.js", 70 | "unit": "bash scripts/unit.sh", 71 | "posttest": "rm -rf cli-tests-*", 72 | "postunit": "npm run posttest", 73 | "t": "node bin/run.js test -J -sfails.txt", 74 | "preversion": "npm test", 75 | "postversion": "npm publish", 76 | "postpublish": "bash postpublish.sh", 77 | "www:build": "cd docs; npm ci; npm run build", 78 | "www:develop": "cd docs; npm run develop", 79 | "start": "npm run www:develop", 80 | "www:serve": "cd docs; npm run serve" 81 | }, 82 | "tap": { 83 | "esm": false, 84 | "test-ignore": "/(^|/)cli-tests-[0-9]+/", 85 | "check-coverage": true 86 | }, 87 | "nyc": { 88 | "include": [ 89 | "bin/run.js", 90 | "bin/jsx.js", 91 | "lib/*.js", 92 | "bin/jack.js" 93 | ] 94 | }, 95 | "files": [ 96 | "bin/run.js", 97 | "bin/jsx.js", 98 | "bin/jack.js", 99 | "lib/*.js" 100 | ], 101 | "bundleDependencies": [ 102 | "ink", 103 | "treport", 104 | "@types/react", 105 | "import-jsx", 106 | "minipass", 107 | "signal-exit", 108 | "tap-parser", 109 | "tap-yaml", 110 | "yaml" 111 | ], 112 | "funding": { 113 | "url": "https://github.com/sponsors/isaacs" 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /docs/src/components/home/features.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import {theme, breakpoints} from '../../theme'; 4 | import {Image, Flex, Box} from 'rebass'; 5 | import brain from '../../images/brain.gif'; 6 | import batteries from '../../images/batteries.gif'; 7 | import separator from '../../images/separator.svg'; 8 | import {ButtonLink} from '../links'; 9 | import {Link} from 'gatsby'; 10 | 11 | const OuterContainer = styled.section` 12 | background-color: ${theme.colors.white}; 13 | box-shadow: 0 0px 11px 5px #33333312; 14 | padding: 40px 20px; 15 | position:relative; 16 | z-index: 2; 17 | 18 | @media screen and (min-width: ${breakpoints.TABLET}) { 19 | padding: 70px 20px; 20 | margin-top: -80px; 21 | } 22 | `; 23 | 24 | const Content = styled(Flex)` 25 | max-width: 900px; 26 | margin: auto; 27 | flex-direction: column; 28 | `; 29 | 30 | const FeatureImage = styled(Image)` 31 | width: 150px; 32 | margin: auto; 33 | `; 34 | 35 | const Code = styled.code` 36 | background-color: #ebe7e7; 37 | font-size: 12px; 38 | word-break: break-word; 39 | `; 40 | 41 | const Separator = styled(Image)` 42 | width: 18px; 43 | margin: 0 10px; 44 | transform: rotate(90deg); 45 | margin: auto; 46 | 47 | @media screen and (min-width: ${breakpoints.TABLET}) { 48 | transform: rotate(0deg); 49 | margin: ${theme.space[7]}px ${theme.space[3]}px 0; 50 | } 51 | `; 52 | 53 | const TextBox = styled(Box)` 54 | max-width: 500px; 55 | `; 56 | 57 | const Features = () => { 58 | return( 59 | 60 | 61 |

Node-Tap Features

62 | 63 | 64 | 65 |

No Fancy DSL to Learn

66 | 67 |

68 | The API is relatively small, even though it's a powerful 69 | framework. t.test(), t.end(), and a 70 | handful of assertion 71 | methods are all you need. This results in having to 72 | write and remember less, so you can just write some tests. 73 |

74 |
75 |
76 | 77 | 78 | 79 |

Batteries Included

80 | 81 |

82 | Code coverage, test reporting, error handling, 84 | {' '}parallel tests, support 85 | for {' '}JSX, TypeScript, ESM, Flow, and 87 | a full-featured assertion 88 | set are all baked in. No need to choose any 89 | other stuff. Just write some tests. 90 |

91 |
92 |
93 |
94 | Get Started 95 |
96 |
97 | ); 98 | }; 99 | 100 | export default Features; 101 | -------------------------------------------------------------------------------- /docs/src/content/docs/api/promises/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Promises 3 | section: 5.02 4 | redirect_from: 5 | - /promises/ 6 | - /promises 7 | --- 8 | 9 | # Promises 10 | 11 | The `t.test()`, `t.spawn()` and `t.stdin()` methods all return a 12 | Promise which resolves to the `t` object once the child test, process, 13 | or input stream is done. (Note that the returned Promise does *not* 14 | resolve to the *child* object, because the child is already ended when 15 | control returns to the parent.) 16 | 17 | Additionally, if the function passed to `t.test()` *returns* a 18 | Promise, then the child test will be ended when the Promise resolves, 19 | or failed when it is rejected. 20 | 21 | These two features together mean that you can string together Promise 22 | chains in your tests, if that's a thing you're into. 23 | 24 | Unhandled promise rejections will be fail the active test, just like thrown 25 | errors would. 26 | 27 | Here is an example: 28 | 29 | ```javascript 30 | const t = require('tap') 31 | t.test('get thing', t => 32 | getSomeThing().then(result => 33 | t.test('check result', t => { 34 | t.equal(result.foo, 'bar') 35 | t.end() 36 | }))) 37 | .then(t => 38 | getTwoThings() 39 | .then(things => t.equal(things.length, 2)) 40 | .then(() => makeSomeOtherPromise()) 41 | .then(otherPromiseResult => 42 | t.equal(otherPromiseResult, 7, 'it should be seven'))) 43 | ``` 44 | 45 | If this sort of style offends you, you are welcome to ignore it. It's not 46 | mandatory. 47 | 48 | If you want to pass Promises to [assertions](/docs/api/asserts) and have them 49 | auto-resolve, then check out [tapromise](http://npm.im/tapromise). 50 | 51 | ## Rejected promise 52 | 53 | To verify that a promise is rejected, you can use the 54 | [`t.rejects()`](/asserts/#trejectspromise--fn-expectederror-message-extra) 55 | function. 56 | 57 | ## `async`/`await` 58 | 59 | Because `async` functions return a Promise, you can use them out of 60 | the box with node-tap. If you pass an `async` function as the 61 | `t.test()` callback, then tap will detect the promise return and move 62 | onto the next test once the async function has completely resolved. 63 | 64 | The above example could be written like this: 65 | 66 | ```js 67 | const t = require('tap') 68 | t.test('get thing', async t => { 69 | const result = await getSomeThing() 70 | await t.test('check result', async t => t.equal(result.foo, 'bar')) 71 | }).then(async function (t) { 72 | const things = await getTwoThings() 73 | 74 | const otherPromiseResult = await t.test('the things', async t => { 75 | t.equal(things.length, 2) 76 | }).then(() => makeSomeOtherPromise()) 77 | 78 | await t.test('check other promise thing', t => { 79 | t.equal(otherPromiseResult, 7, 'it should be seven') 80 | t.end() 81 | }) 82 | }) 83 | ``` 84 | 85 | Because subtests return promises, you can also `await` them to do 86 | things in between subtests. However, this requires a top-level async 87 | function. 88 | 89 | For example: 90 | 91 | ```js 92 | const t = require('tap') 93 | 94 | async main = () => { 95 | await t.test('get thing', t => 96 | getSomeThing().then(result => 97 | t.test('check result', async t => 98 | t.equal(result.foo, 'bar')))) 99 | 100 | const things = await getTwoThings() 101 | const otherPromiseResult = await t.test('got two things', async t => 102 | t.equal(things.length, 2)).then(() => makeSomeOtherPromise()) 103 | 104 | await t.test('check other promise thing', async t => 105 | t.equal(otherPromiseResult, 7, 'it should be seven')) 106 | 107 | console.log('tests are all done!') 108 | } 109 | main() 110 | ``` 111 | --------------------------------------------------------------------------------