From c8f31a39ca7a2b13a5b3c85c5b1467da2ecc5c7a Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Mon, 27 Apr 2020 15:09:58 +0200 Subject: [PATCH] Test AVA using AVA --- .c8rc.json | 2 +- .github/CONTRIBUTING.md | 2 +- .gitignore | 7 +- ava.config.js | 4 ++ lib/cli.js | 13 ++++ maintaining.md | 1 + package-lock.json | 71 ++++++++++++++++++++ package.json | 3 +- test/README.md | 7 ++ test/assertions/fixtures/happy-path.js | 29 ++++++++ test/assertions/fixtures/happy-path.js.md | 13 ++++ test/assertions/fixtures/happy-path.js.snap | Bin 0 -> 144 bytes test/assertions/fixtures/package.json | 10 +++ test/assertions/snapshots/test.js.md | 29 ++++++++ test/assertions/snapshots/test.js.snap | Bin 0 -> 415 bytes test/assertions/test.js | 7 ++ test/helpers/exec.js | 65 ++++++++++++++++++ test/node_modules/ava | 1 + 18 files changed, 259 insertions(+), 5 deletions(-) create mode 100644 ava.config.js create mode 100644 test/README.md create mode 100644 test/assertions/fixtures/happy-path.js create mode 100644 test/assertions/fixtures/happy-path.js.md create mode 100644 test/assertions/fixtures/happy-path.js.snap create mode 100644 test/assertions/fixtures/package.json create mode 100644 test/assertions/snapshots/test.js.md create mode 100644 test/assertions/snapshots/test.js.snap create mode 100644 test/assertions/test.js create mode 100644 test/helpers/exec.js create mode 120000 test/node_modules/ava diff --git a/.c8rc.json b/.c8rc.json index c87c82ea..985af975 100644 --- a/.c8rc.json +++ b/.c8rc.json @@ -1,7 +1,7 @@ { "all": true, "exclude": [ - "{coverage,media,test-d,test-tap}/**", + "{coverage,media,test,test-d,test-tap}/**", "*.config.js", "index.d.ts" ], diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index efc58999..6935579b 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -59,7 +59,7 @@ Try and avoid making breaking changes. Those take more time to ship. Instead mak Non-experimental features should be accompanied with tests and documentation. -Don't include unrelated changes in your pull request. Make sure tests pass on your machine by running `npm test`. You can run specific test files as well using `npx tap test-tap/{file}.js`. +Don't include unrelated changes in your pull request. Make sure tests pass on your machine by running `npm test`. You can run specific test files as well using `npx tap test-tap/{file}.js` or `npx test-ava test/{file}.js`. When you make a pull request please use a clear and descriptive title. Be specific about what's changed and why. diff --git a/.gitignore b/.gitignore index ba2a97b5..20a3cc17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ -node_modules -coverage +/coverage +/media/**/node_modules/ +/node_modules/ +/test-tap/**/node_modules/ +/test/**/fixtures/**/node_modules/*/ diff --git a/ava.config.js b/ava.config.js new file mode 100644 index 00000000..363e4279 --- /dev/null +++ b/ava.config.js @@ -0,0 +1,4 @@ +export default { + files: ['test/**', '!test/**/{fixtures,helpers}/**'], + ignoredByWatcher: ['{coverage,docs,media,test-d,test-tap}/**'] +}; diff --git a/lib/cli.js b/lib/cli.js index 2a0fd4e4..69a3c0b9 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -410,6 +410,19 @@ exports.run = async () => { // eslint-disable-line complexity api.on('run', plan => { reporter.startRun(plan); + if (process.env.AVA_EMIT_RUN_STATUS_OVER_IPC === 'I\'ll find a payphone baby / Take some time to talk to you') { + if (process.versions.node >= '12.16.0') { + plan.status.on('stateChange', evt => { + process.send(evt); + }); + } else { + const v8 = require('v8'); + plan.status.on('stateChange', evt => { + process.send([...v8.serialize(evt)]); + }); + } + } + plan.status.on('stateChange', evt => { if (evt.type === 'interrupt') { reporter.endRun(); diff --git a/maintaining.md b/maintaining.md index c2c98fd4..eb834759 100644 --- a/maintaining.md +++ b/maintaining.md @@ -8,6 +8,7 @@ * `npm test`: Lint the code and run the entire test suite with coverage. * `npx tap test-tap/fork.js --bail`: Run a specific test file and bail on the first failure (useful when hunting bugs). +* `npx test-ava test/{file}.js`: Run self-hosted tests. ## CI diff --git a/package-lock.json b/package-lock.json index e2c55010..c7091a78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,6 +47,77 @@ "integrity": "sha512-N7w4g+P/SUL8SF+HC4Z4e/ctV6nQ5AERC90K90r4xZQ8WVrJux9albvfyYAzygyU47CSqMWh6yJwFs8DYaeWmg==", "dev": true }, + "@ava/test": { + "version": "github:avajs/test#46dbf16d19cccfdb5b599fb80ec3baf97ceb9605", + "from": "github:avajs/test", + "dev": true, + "requires": { + "@ava/v3": "npm:ava@^3.8.1" + } + }, + "@ava/v3": { + "version": "npm:ava@3.8.1", + "resolved": "https://registry.npmjs.org/ava/-/ava-3.8.1.tgz", + "integrity": "sha512-OPWrTxcf1EbtAaGGFQPLbx4AaVqPrFMumKOKn2SzIRo+RTKb33lF2aoVnWqBeZaJ68uSc9R6jqIE7qkG6O33uQ==", + "dev": true, + "requires": { + "@concordance/react": "^2.0.0", + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1", + "ansi-styles": "^4.2.1", + "arrgv": "^1.0.2", + "arrify": "^2.0.1", + "callsites": "^3.1.0", + "chalk": "^4.0.0", + "chokidar": "^3.4.0", + "chunkd": "^2.0.1", + "ci-info": "^2.0.0", + "ci-parallel-vars": "^1.0.0", + "clean-yaml-object": "^0.1.0", + "cli-cursor": "^3.1.0", + "cli-truncate": "^2.1.0", + "code-excerpt": "^2.1.1", + "common-path-prefix": "^3.0.0", + "concordance": "^4.0.0", + "convert-source-map": "^1.7.0", + "currently-unhandled": "^0.4.1", + "debug": "^4.1.1", + "del": "^5.1.0", + "emittery": "^0.6.0", + "equal-length": "^1.0.0", + "figures": "^3.2.0", + "globby": "^11.0.0", + "ignore-by-default": "^1.0.0", + "import-local": "^3.0.2", + "indent-string": "^4.0.0", + "is-error": "^2.2.2", + "is-plain-object": "^3.0.0", + "is-promise": "^3.0.0", + "lodash": "^4.17.15", + "matcher": "^3.0.0", + "md5-hex": "^3.0.1", + "mem": "^6.1.0", + "ms": "^2.1.2", + "ora": "^4.0.4", + "p-map": "^4.0.0", + "picomatch": "^2.2.2", + "pkg-conf": "^3.1.0", + "plur": "^4.0.0", + "pretty-ms": "^6.0.1", + "read-pkg": "^5.2.0", + "resolve-cwd": "^3.0.0", + "slash": "^3.0.0", + "source-map-support": "^0.5.19", + "stack-utils": "^2.0.1", + "strip-ansi": "^6.0.0", + "supertap": "^1.0.0", + "temp-dir": "^2.0.0", + "trim-off-newlines": "^1.0.1", + "update-notifier": "^4.1.0", + "write-file-atomic": "^3.0.3", + "yargs": "^15.3.1" + } + }, "@babel/code-frame": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", diff --git a/package.json b/package.json index f9c17549..7bd12a03 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=13.5.0 <14 || >=14.0.0" }, "scripts": { - "test": "xo && tsd && c8 tap" + "test": "xo && tsd && c8 --report=none tap && c8 --report=none --no-clean test-ava && c8 report" }, "files": [ "lib", @@ -113,6 +113,7 @@ }, "devDependencies": { "@ava/babel": "^1.0.1", + "@ava/test": "github:avajs/test", "@babel/plugin-proposal-do-expressions": "^7.8.3", "@sinonjs/fake-timers": "^6.0.1", "ansi-escapes": "^4.3.1", diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000..4e35d7e8 --- /dev/null +++ b/test/README.md @@ -0,0 +1,7 @@ +# Self-hosted tests + +This directory contains tests that are run using a stable version of AVA. You can run them using `npx test-ava`. + +Tests should be placed in their own directory, grouped by area of responsibility. Use the `exec.fixture()` helper to launch the AVA version that is in the repository to run tests. Place these in a nested `fixtures` directory. Add a relative dependency in `package.json`. You can then import from `ava`. + +Prefer snapshotting the test results. diff --git a/test/assertions/fixtures/happy-path.js b/test/assertions/fixtures/happy-path.js new file mode 100644 index 00000000..41c1ee54 --- /dev/null +++ b/test/assertions/fixtures/happy-path.js @@ -0,0 +1,29 @@ +const test = require('ava'); + +const passes = async (t, assertion, ...args) => { + await t[assertion](...args); +}; + +passes.title = (_, assertion, ...args) => `t.${assertion}(${args.map(v => JSON.stringify(v)).join(', ')}) passes`; + +test(passes, 'pass'); +test(passes, 'is', 1, 1); +test(passes, 'not', 1, 2); +test(passes, 'deepEqual', {foo: 'bar'}, {foo: 'bar'}); +test(passes, 'notDeepEqual', {foo: 'bar'}, {foo: 'baz'}); +test(passes, 'throws', () => { + throw new Error('error'); +}); +test(passes, 'throwsAsync', async () => { + throw new Error('error'); +}); +test(passes, 'notThrows', () => {}); +test(passes, 'notThrowsAsync', async () => {}); +test(passes, 'snapshot', {foo: 'bar'}); +test(passes, 'truthy', 1); +test(passes, 'falsy', ''); +test(passes, 'true', true); +test(passes, 'false', false); +test(passes, 'regex', 'foo', /foo/); +test(passes, 'notRegex', 'bar', /foo/); +test(passes, 'assert', 1); diff --git a/test/assertions/fixtures/happy-path.js.md b/test/assertions/fixtures/happy-path.js.md new file mode 100644 index 00000000..6d4a0d56 --- /dev/null +++ b/test/assertions/fixtures/happy-path.js.md @@ -0,0 +1,13 @@ +# Snapshot report for `happy-path.js` + +The actual snapshot is saved in `happy-path.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## t.snapshot({"foo":"bar"}) passes + +> Snapshot 1 + + { + foo: 'bar', + } diff --git a/test/assertions/fixtures/happy-path.js.snap b/test/assertions/fixtures/happy-path.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..0c4a201cb27fb7b3b28acff820c8606f85ce41b1 GIT binary patch literal 144 zcmZ<^b5sbzV&<2IEt~?}#+x{eHvLpjU8*+S!06CS uCMG7Ho;^H0Jv=>s987(bdd~3ltZC{wllk*!L0M3eAj65-k6sr8tpNbI7&)u} literal 0 HcmV?d00001 diff --git a/test/assertions/fixtures/package.json b/test/assertions/fixtures/package.json new file mode 100644 index 00000000..ac13570c --- /dev/null +++ b/test/assertions/fixtures/package.json @@ -0,0 +1,10 @@ +{ + "ava": { + "files": [ + "*.js" + ] + }, + "dependencies": { + "ava": "file:../../.." + } +} diff --git a/test/assertions/snapshots/test.js.md b/test/assertions/snapshots/test.js.md new file mode 100644 index 00000000..d98073e0 --- /dev/null +++ b/test/assertions/snapshots/test.js.md @@ -0,0 +1,29 @@ +# Snapshot report for `test/assertions/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## happy path + +> Snapshot 1 + + [ + 't.assert(1) passes', + 't.deepEqual({"foo":"bar"}, {"foo":"bar"}) passes', + 't.false(false) passes', + 't.falsy("") passes', + 't.is(1, 1) passes', + 't.not(1, 2) passes', + 't.notDeepEqual({"foo":"bar"}, {"foo":"baz"}) passes', + 't.notRegex("bar", {}) passes', + 't.notThrows() passes', + 't.notThrowsAsync() passes', + 't.pass() passes', + 't.regex("foo", {}) passes', + 't.snapshot({"foo":"bar"}) passes', + 't.throws() passes', + 't.throwsAsync() passes', + 't.true(true) passes', + 't.truthy(1) passes', + ] diff --git a/test/assertions/snapshots/test.js.snap b/test/assertions/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..30f1537db4768de27703e5ad3ead0fdf5553dc3a GIT binary patch literal 415 zcmV;Q0bu??RzV$(*V|pT_PZEiD%-SSfb1_W=+gAICld?wK5C?umETR7Rk_{ zf;wQv#FBJeAv`WwZPgltOYyBBDra3fC!RNGo(|m}yRuupZ*SU1F1N3%*00xOf~FGY zq|{9#j^NUabY*( ziYqGBl8)%R1JR)m_vf8X$1XyS?`1|Q^GX@th@rePd3@-xa7aqCv0J5m*$ICB)KB7s J5wu?e003QNy}tke literal 0 HcmV?d00001 diff --git a/test/assertions/test.js b/test/assertions/test.js new file mode 100644 index 00000000..c0207d42 --- /dev/null +++ b/test/assertions/test.js @@ -0,0 +1,7 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +test('happy path', async t => { + const result = await exec.fixture('happy-path.js'); + t.snapshot(result.stats.passed.map(({title}) => title)); +}); diff --git a/test/helpers/exec.js b/test/helpers/exec.js new file mode 100644 index 00000000..0f3f0635 --- /dev/null +++ b/test/helpers/exec.js @@ -0,0 +1,65 @@ +const path = require('path'); +const v8 = require('v8'); + +const test = require('@ava/test'); +const execa = require('execa'); + +const cliPath = path.resolve(__dirname, '../../cli.js'); +const serialization = process.versions.node >= '12.16.0' ? 'advanced' : 'json'; + +exports.fixture = async (...args) => { + const cwd = path.join(path.dirname(test.meta.file), 'fixtures'); + const running = execa.node(cliPath, args, { + env: { + AVA_EMIT_RUN_STATUS_OVER_IPC: 'I\'ll find a payphone baby / Take some time to talk to you' + }, + cwd, + serialization + }); + + const stats = { + passed: [] + }; + + running.on('message', message => { + if (serialization === 'json') { + message = v8.deserialize(Uint8Array.from(message)); + } + + switch (message.type) { + case 'test-passed': { + const {title, testFile} = message; + stats.passed.push({title, file: path.posix.relative(cwd, testFile)}); + break; + } + + default: + break; + } + }); + + try { + return { + stats, + ...await running + }; + } catch (error) { + throw Object.assign(error, {stats}); + } finally { + stats.passed.sort((a, b) => { + if (a.file < b.file) { + return -1; + } + + if (a.file > b.file) { + return 1; + } + + if (a.title < b.title) { + return -1; + } + + return 1; + }); + } +}; diff --git a/test/node_modules/ava b/test/node_modules/ava new file mode 120000 index 00000000..6581736d --- /dev/null +++ b/test/node_modules/ava @@ -0,0 +1 @@ +../../ \ No newline at end of file