diff --git a/package.json b/package.json index 43ffd63..b1735d7 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "repository": "https://github.com/get-alex/alex", "bugs": "https://github.com/get-alex/alex/issues", "funding": { - "url": "https://github.com/sponsors/wooorm" - }, + "url": "https://github.com/sponsors/wooorm" + }, "homepage": "https://alexjs.com", "keywords": [ "cli-app", @@ -75,13 +75,12 @@ "vfile-sort": "^2.0.0" }, "devDependencies": { - "ava": "^2.0.0", "browserify": "^16.0.0", - "execa": "^3.0.0", - "nyc": "^14.0.0", + "nyc": "^15.0.0", "prettier": "^1.0.0", "remark-cli": "^7.0.0", "remark-preset-wooorm": "^6.0.0", + "tape": "^4.0.0", "tinyify": "^2.0.0", "xo": "^0.25.0" }, @@ -90,8 +89,8 @@ "build-bundle": "browserify . -s alex -o alex.js", "build-mangle": "browserify . -s alex -p tinyify -o alex.min.js", "build": "npm run build-bundle && npm run build-mangle", - "test-api": "ava", - "test-coverage": "nyc --reporter lcov ava", + "test-api": "node test", + "test-coverage": "nyc --reporter lcov tape test/index.js", "test": "npm run format && npm run build && npm run test-coverage" }, "alex": { diff --git a/test/api.js b/test/api.js index c005e0a..5206153 100644 --- a/test/api.js +++ b/test/api.js @@ -2,9 +2,11 @@ var fs = require('fs') var path = require('path') -var test = require('ava') +var test = require('tape') var alex = require('..') +var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'three.html')) + // Tests. Note that these are small because alex is in fact // just a collection of well-tested modules. // See `retextjs/retext-equality` for the gist of what @@ -29,35 +31,32 @@ test('alex()', function(t) { '3:10-3:17: `cripple` may be insensitive, use `person with a ' + 'limp` instead', '5:36-5:40: Be careful with `butt`, it’s profane in some cases' - ] + ], + 'should work' ) -}) -test('alex() with an allow array', function(t) { - var messages = alex('Eric is pretty set on beating your butt for sheriff.', [ - 'butt' - ]).messages - - t.is(messages.length, 0) -}) + t.deepEqual( + alex('Eric is pretty set on beating your butt for sheriff.', ['butt']) + .messages, + [], + 'should work with an allow array' + ) -test('alex() with profantity config', function(t) { - var messages = alex( - 'Eric, the asshat, is pretty set on beating your butt for sheriff.', - { + t.deepEqual( + alex('Eric, the asshat, is pretty set on beating your butt for sheriff.', { allow: ['asshat'], profanitySureness: 1 - } - ).messages - - t.is(messages.length, 0, 'We dont expect any messages') -}) + }).messages, + [], + 'should work with profantity config' + ) -test('alex.markdown()', function(t) { - t.deepEqual(alex.markdown('The `boogeyman`.').messages.map(String), []) -}) + t.deepEqual( + alex.markdown('The `boogeyman`.').messages.map(String), + [], + 'alex.markdown()' + ) -test('alex.text()', function(t) { t.deepEqual( alex .text( @@ -70,11 +69,10 @@ test('alex.text()', function(t) { [ '1:6-1:15: `boogeyman` may be insensitive, use `boogeymonster` instead', '2:36-2:40: Be careful with `butt`, it’s profane in some cases' - ] + ], + 'alex.text()' ) -}) -test('alex.text() with allow config', function(t) { t.deepEqual( alex .text( @@ -85,11 +83,10 @@ test('alex.text() with allow config', function(t) { {allow: ['butt']} ) .messages.map(String), - ['1:6-1:15: `boogeyman` may be insensitive, use `boogeymonster` instead'] + ['1:6-1:15: `boogeyman` may be insensitive, use `boogeymonster` instead'], + 'alex.text() with allow config' ) -}) -test('alex.text() with allow array', function(t) { t.deepEqual( alex .text( @@ -100,37 +97,37 @@ test('alex.text() with allow array', function(t) { ['butt'] ) .messages.map(String), - ['1:6-1:15: `boogeyman` may be insensitive, use `boogeymonster` instead'] + ['1:6-1:15: `boogeyman` may be insensitive, use `boogeymonster` instead'], + 'alex.text() with allow array' ) -}) - -test('alex.html()', function(t) { - var fp = path.join(__dirname, 'fixtures', 'three.html') - var fixture = fs.readFileSync(fp) - - t.deepEqual(alex.html(fixture).messages.map(String), [ - '9:18-9:20: `He` may be insensitive, use `They`, `It` instead', - '10:1-10:4: `She` may be insensitive, use `They`, `It` instead', - '11:36-11:40: Be careful with `butt`, it’s profane in some cases' - ]) -}) -test('alex.html() with allow config', function(t) { - var fp = path.join(__dirname, 'fixtures', 'three.html') - var fixture = fs.readFileSync(fp) + t.deepEqual( + alex.html(html).messages.map(String), + [ + '9:18-9:20: `He` may be insensitive, use `They`, `It` instead', + '10:1-10:4: `She` may be insensitive, use `They`, `It` instead', + '11:36-11:40: Be careful with `butt`, it’s profane in some cases' + ], + 'alex.html()' + ) - t.deepEqual(alex.html(fixture, {allow: ['butt']}).messages.map(String), [ - '9:18-9:20: `He` may be insensitive, use `They`, `It` instead', - '10:1-10:4: `She` may be insensitive, use `They`, `It` instead' - ]) -}) + t.deepEqual( + alex.html(html, {allow: ['butt']}).messages.map(String), + [ + '9:18-9:20: `He` may be insensitive, use `They`, `It` instead', + '10:1-10:4: `She` may be insensitive, use `They`, `It` instead' + ], + 'alex.html() with allow config' + ) -test('alex.html() with allow array', function(t) { - var fp = path.join(__dirname, 'fixtures', 'three.html') - var fixture = fs.readFileSync(fp) + t.deepEqual( + alex.html(html, ['butt']).messages.map(String), + [ + '9:18-9:20: `He` may be insensitive, use `They`, `It` instead', + '10:1-10:4: `She` may be insensitive, use `They`, `It` instead' + ], + 'alex.html() with allow array' + ) - t.deepEqual(alex.html(fixture, ['butt']).messages.map(String), [ - '9:18-9:20: `He` may be insensitive, use `They`, `It` instead', - '10:1-10:4: `She` may be insensitive, use `They`, `It` instead' - ]) + t.end() }) diff --git a/test/cli.js b/test/cli.js index 1b416e4..4df351a 100644 --- a/test/cli.js +++ b/test/cli.js @@ -1,183 +1,302 @@ 'use strict' var path = require('path') -var test = require('ava') -var execa = require('execa') +var childProcess = require('child_process') +var test = require('tape') -test('version', async function(t) { - var result = await execa('./cli.js', ['-v']) - t.is(result.stdout, require('../package').version) -}) +var pkg = require('../package') -test('help', async function(t) { - var result = await execa('./cli.js', ['-h']) - t.regex(result.stdout, /Usage: alex \[ ...] /) -}) +test('alex-cli', function(t) { + t.test('version', function(t) { + t.plan(1) -test('stdin', async function(t) { - try { - await execa('./cli.js', ['--stdin'], {input: 'His'}) - } catch (error) { - t.is( - error.stderr, - [ - '', - ' 1:1-1:4 warning `His` may be insensitive, when referring to a person, use `Their`, `Theirs`, `Them` instead her-him retext-equality', - '', - '⚠ 1 warning' - ].join('\n') - ) - } -}) + childProcess.exec('./cli.js -v', onexec) -test('stdin and globs', async function(t) { - var filePath = path.join('test', 'fixtures', 'one.md') + function onexec(err, stdout, stderr) { + t.deepEqual( + [err, stderr, stdout], + [null, '', pkg.version + '\n'], + 'should work' + ) + } + }) - try { - await execa('./cli.js', ['--stdin', filePath]) - } catch (error) { - t.regex(error.stderr, /Do not pass globs with `--stdin`/) - } -}) + t.test('help', function(t) { + t.plan(1) -test('markdown by default', async function(t) { - var filePath = path.join('test', 'fixtures', 'one.md') - var result = await execa('./cli.js', [filePath]) + childProcess.exec('./cli.js -h', onexec) - t.is(result.stderr, filePath + ': no issues found') -}) + function onexec(err, stdout, stderr) { + t.deepEqual( + [err, stderr, /Usage: alex \[ ...] /.test(stdout)], + [null, '', true], + 'should work' + ) + } + }) -test('text optional', async function(t) { - var filePath = path.join('test', 'fixtures', 'one.md') - - try { - await execa('./cli.js', [filePath, '--text']) - } catch (error) { - t.is( - error.stderr, - [ - filePath, - ' 1:18-1:21 warning `his` may be insensitive, when referring to a person, use `their`, `theirs`, `them` instead her-him retext-equality', - '', - '⚠ 1 warning' - ].join('\n') - ) - } -}) + t.test('stdin', function(t) { + t.plan(1) -test('text on html', async function(t) { - var filePath = path.join('test', 'fixtures', 'three.html') + var subprocess = childProcess.exec('./cli.js --stdin', onexec) - try { - await execa('./cli.js', [filePath, '--text']) - } catch (error) { - t.regex(error.stderr, /9 warnings/) - } -}) + setTimeout(end, 10) -test('html optional', async function(t) { - var filePath = path.join('test', 'fixtures', 'three.html') - - try { - await execa('./cli.js', [filePath, '--html']) - } catch (error) { - t.is( - error.stderr, - [ - filePath, - ' 9:18-9:20 warning `He` may be insensitive, use `They`, `It` instead he-she retext-equality', - ' 10:1-10:4 warning `She` may be insensitive, use `They`, `It` instead he-she retext-equality', - '', - '⚠ 2 warnings' - ].join('\n') - ) - } -}) + function end() { + subprocess.stdin.end('His') + } -test('successful files', async function(t) { - var filePath = path.join('test', 'fixtures', 'ok.txt') - var result = await execa('./cli.js', [filePath]) + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, stderr, stdout], + [ + 1, + [ + '', + ' 1:1-1:4 warning `His` may be insensitive, when referring to a person, use `Their`, `Theirs`, `Them` instead her-him retext-equality', + '', + '⚠ 1 warning', + '' + ].join('\n'), + '' + ], + 'should work' + ) + } + }) - t.is(result.stderr, filePath + ': no issues found') -}) + t.test('stdin and globs', function(t) { + var fp = path.join('test', 'fixtures', 'one.md') -test('quiet on ok files', async function(t) { - var fp = path.join(__dirname, 'fixtures', 'ok.txt') - var result = await execa('./cli.js', [fp, '-q']) + t.plan(1) - t.is(result.stderr, '') -}) + childProcess.exec('./cli.js --stdin ' + fp, onexec) -test('quiet on nok files', async function(t) { - var filePath = path.join('test', 'fixtures', 'one.md') - - try { - await execa('./cli.js', [filePath, '--text']) - } catch (error) { - t.is( - error.stderr, - [ - filePath, - ' 1:18-1:21 warning `his` may be insensitive, when referring to a person, use `their`, `theirs`, `them` instead her-him retext-equality', - '', - '⚠ 1 warning' - ].join('\n') - ) - } -}) + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, /Do not pass globs with `--stdin`/.test(stderr), stdout], + [1, true, ''], + 'should work' + ) + } + }) -test('binary (default)', async function(t) { - var filePath = path.join('test', 'fixtures', 'binary', 'two.md') - var result = await execa('./cli.js', [filePath]) + t.test('markdown by default', function(t) { + var fp = path.join('test', 'fixtures', 'one.md') - t.is(result.stderr, filePath + ': no issues found') -}) + t.plan(1) -test('non-binary (optional)', async function(t) { - var filePath = path.join('test', 'fixtures', 'non-binary', 'two.md') - - try { - await execa('./cli.js', [filePath]) - } catch (error) { - t.is( - error.stderr, - [ - filePath, - ' 1:1-1:3 warning `He` may be insensitive, use `They`, `It` instead he-she retext-equality', - ' 1:7-1:10 warning `she` may be insensitive, use `they`, `it` instead he-she retext-equality', - '', - '⚠ 2 warnings' - ].join('\n') - ) - } -}) + childProcess.exec('./cli.js ' + fp, onexec) -test('profanity (default)', async function(t) { - var filePath = path.join('test', 'fixtures', 'profanity', 'two.md') - - try { - await execa('./cli.js', [filePath]) - } catch (error) { - var expected = [ - filePath, - ' 1:5-1:11 warning Be careful with `beaver`, it’s profane in some cases beaver retext-profanities', - '', - '⚠ 1 warning' - ].join('\n') - - t.is(error.stderr, expected) - } -}) + function onexec(err, stdout, stderr) { + t.deepEqual( + [err, stderr, stdout], + [null, fp + ': no issues found\n', ''], + 'should work' + ) + } + }) -test('profanity (profanitySureness: 1)', async function(t) { - var filePath = path.join('test', 'fixtures', 'profanity-sureness', 'two.md') - var result = await execa('./cli.js', [filePath]) + t.test('optionally html', function(t) { + var fp = path.join('test', 'fixtures', 'three.html') - t.is(result.stderr, filePath + ': no issues found') -}) + t.plan(1) + + childProcess.exec('./cli.js ' + fp + ' --html', onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, /2 warnings/.test(stderr), stdout], + [1, true, ''], + 'should work' + ) + } + }) + + t.test('optionally text (on markdown)', function(t) { + var fp = path.join('test', 'fixtures', 'one.md') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp + ' --text', onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, /1 warning/.test(stderr), stdout], + [1, true, ''], + 'should work' + ) + } + }) + + t.test('optionally text (on html)', function(t) { + var fp = path.join('test', 'fixtures', 'three.html') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp + ' --text', onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, /9 warnings/.test(stderr), stdout], + [1, true, ''], + 'should work' + ) + } + }) + + t.test('successful', function(t) { + var fp = path.join('test', 'fixtures', 'ok.txt') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp, onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err, stderr, stdout], + [null, fp + ': no issues found\n', ''], + 'should work' + ) + } + }) + + t.test('quiet (ok)', function(t) { + var fp = path.join('test', 'fixtures', 'ok.txt') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp + ' -q', onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual([err, stderr, stdout], [null, '', ''], 'should work') + } + }) + + t.test('quiet (on error)', function(t) { + var fp = path.join('test', 'fixtures', 'one.md') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp + ' -q --text', onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, stderr, stdout], + [ + 1, + [ + fp, + ' 1:18-1:21 warning `his` may be insensitive, when referring to a person, use `their`, `theirs`, `them` instead her-him retext-equality', + '', + '⚠ 1 warning', + '' + ].join('\n'), + '' + ], + 'should work' + ) + } + }) + + t.test('binary (default: ok)', function(t) { + var fp = path.join('test', 'fixtures', 'binary', 'two.md') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp, onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err, stderr, stdout], + [null, fp + ': no issues found\n', ''], + 'should work' + ) + } + }) + + t.test('binary (with config file)', function(t) { + var fp = path.join('test', 'fixtures', 'non-binary', 'two.md') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp, onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, stderr, stdout], + [ + 1, + [ + fp, + ' 1:1-1:3 warning `He` may be insensitive, use `They`, `It` instead he-she retext-equality', + ' 1:7-1:10 warning `she` may be insensitive, use `they`, `it` instead he-she retext-equality', + '', + '⚠ 2 warnings', + '' + ].join('\n'), + '' + ], + 'should work' + ) + } + }) + + t.test('profanity (default)', function(t) { + var fp = path.join('test', 'fixtures', 'profanity', 'two.md') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp, onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err.code, stderr, stdout], + [ + 1, + [ + fp, + ' 1:5-1:11 warning Be careful with `beaver`, it’s profane in some cases beaver retext-profanities', + '', + '⚠ 1 warning', + '' + ].join('\n'), + '' + ], + 'should work' + ) + } + }) + + t.test('profanity (with config file)', function(t) { + var fp = path.join('test', 'fixtures', 'profanity-sureness', 'two.md') + + t.plan(1) + + childProcess.exec('./cli.js ' + fp, onexec) + + function onexec(err, stdout, stderr) { + t.deepEqual( + [err, stderr, stdout], + [null, fp + ': no issues found\n', ''], + 'should work' + ) + } + }) + + t.test('default globs', function(t) { + t.plan(1) + + childProcess.exec('./cli.js', onexec) -test('default globs', async function(t) { - var result = await execa('./cli.js') + function onexec(err, stdout, stderr) { + t.deepEqual( + [err, stderr, stdout], + [null, 'readme.md: no issues found\n', ''], + 'should work' + ) + } + }) - t.is(result.stderr, 'readme.md: no issues found') + t.end() }) diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..8ff5c64 --- /dev/null +++ b/test/index.js @@ -0,0 +1,6 @@ +'use strict' + +/* eslint-disable import/no-unassigned-import, ava/no-import-test-files */ +require('./api') +require('./cli') +/* eslint-enable import/no-unassigned-import, ava/no-import-test-files */