README
@putout/test
Test runner for 🐊Putout
. Basically it is supercharged tape
with aditional asseritions:
Install
npm i @putout/test -D
Autofix
Set environment variable UPDATE=1
to update transform
and format
fixtures.
☝️ Remember that -fix.js
fixtures will be removed when used in noReport, noTransform, noTransformWithOptions
UPDATE=1 tape test/*.js
Plugins API
All plugins 🐊Putout
plugins written in CommonJS
, since ESLint
written on CommonJS
and we have a huge ESLint
-based ecosystem which is good to reuse.
🐊Putout
can be used in all IDE's supported byESLint
as eslint-plugin-putout
.
When async rules will be supported we can switch to ESM
.
To write test for your plugins you need initialize test
using createTest
:
import {createTest} from '@putout/test';
const rmVars = require('@putout/plugin-remove-unused-variables');
const test = createTest(import.meta.url, {
'remove-unused-variables': rmVars,
});
report(filename, message | []messages)
checks error message (or messages) of a plugin
test('remove usless variables: for-of', (t) => {
t.report('dot', 'Dot files should be added to .gitignore');
t.end();
});
reportCode(input, message)
checks error message of a plugin from input
code
test('remove debugger: report', (t) => {
t.reportCode('debugger', 'Unexpected "debugger" statement');
t.end();
});
transform(filename [, output, plugins])
check transform of filename.js
-> filename-fix.js
in test/fixtures
directory
test('remove usless variables: for-of', (t) => {
t.transform('array-from', {
'remove-useless-array-from': removeUselessArrayFrom,
});
t.end();
});
transformCode(input, output)
check transform of input
-> output
code
test('remove-console: property identifier: code', (t) => {
t.transformCode('console.log()', '');
t.end();
});
reportWithOptions(filename, options)
check report of filename.js
with options
test('putout: test: reportWithOptions', (t) => {
const cache = new Map();
cache.set('x', 'y');
t.reportWithOptions('remove-import', 'avoid imports', {
cache,
});
t.end();
});
noReportWithOptions(filename, options)
check no report of filename.js
with options
test('putout: test: noReportWithOptions', (t) => {
const cache = new Map();
t.noReportWithOptions('remove-import', {
cache,
});
t.end();
});
transformWithOptions(filename, options)
check transform of filename.js
with options
test('putout: plugin: declare-undefined-variables: transform: parse', (t) => {
t.transformWithOptions('parse', {
dismiss: ['assign', 'stringify'],
});
t.end();
});
noTransformWithOptions(filename, options)
When file should not be transformed:
test('test: declared', (t) => {
t.noTransform('declared');
t.end();
});
noTransformWithOptions(filename, options)
check transform of filename.js
with options
test('putout: plugin: declare-undefined-variables: transform: assign: dismiss', (t) => {
t.noTransformWithOptions('assign', {
dismiss: ['assign', 'stringify'],
});
t.end();
});
noReport(filename)
checks error message of a plugin not produces
test('plugin-putout: check-replace-code: no report: typescript', (t) => {
t.noReport('typescript');
t.end();
});
noReportAfterTransform(filename)
checks error message of a plugin not produced
test('test: no report after transform', (t) => {
t.noReportAfterTransform('file');
t.end();
});
noTransform(filename)
check transform of filename.js
produce nothing
test('plugin-apply-numeric-separators: no transform: hex', (t) => {
t.noTransform('hex');
t.end();
});
Formatters API
First you need to create test with:
import {createTest} from '@putout/test';
import rmVars from '@putout/plugin-remove-unused-variables';
const test = createTest(import.meta.url, {
'remove-unused-variables': rmVars,
});
format(formatter, filename)
check file name formatting (pass process.env.UPDATE=1
to save fixture)
test('formatter: codeframe', async ({format}) => {
await format(codeframe);
});
noFormat
check that there is no formatting for for such file
test('formatter: codeframe: no', async ({noFormat}) => {
await noFormat(codeframe, 'no');
});
formatMany(formatter, [filename1, filename2])
check file name formatting (pass process.env.UPDATE=1
to save fixture)
test('formatter: dump: many', async ({formatMany}) => {
await formatMany(dump, ['var', 'var']);
});
Usage Example
Here is example of tests for remove-console:
const {createTest} = require('@putout/test');
const removeConsole = require('@putout/plugin-remove-console');
const test = createTest(__dirname, {
'remove-console': removeConsole,
});
test('remove-console: report', (t) => {
t.report('property-identifier', 'Unexpected "console" call');
t.end();
});
test('remove-console: property identifier', (t) => {
t.transform('property-identifier');
t.end();
});
// when code should not be transformed
test('test: declared', (t) => {
t.noTransformCode('alert()');
t.end();
});
ESLint API
First you need to create test with:
import {createTest} from '@putout/test/eslint';
const test = createTest(import.meta.url);
process(filename [, config])
Works in similar to transform way:
- ✅ reads
operator-linebreak.js
; - ✅ transforms it;
- ✅ checks that transformed is equal to
operator-linebreak-fix.js
;
Example:
test('test: eslint: transform', async ({process}) => {
await process('operator-linebreak');
});
test('test: eslint: transform', async ({process}) => {
await process('operator-linebreak', {
rules: {
'putout/putout': {
rules: {
'convert-esm-to-commonjs': 'on',
},
},
},
});
});
noProcess(filename)
Check that filename would not be processed.
Example:
test('test: eslint: noProcess', async ({noProcess}) => {
await noProcess('operator-linebreak-fix');
});
comparePlaces(filename, places)
test('eslint-config: operator-line-break', async ({comparePlaces}) => {
await comparePlaces('operator-linebreak', [{
"message": "There should be no line break before or after '='.",
"position": {
"column": 1,
"line": 2,
},
"rule": "operator-linebreak (eslint)",
}]);
});
Processors API
With processors api
you can test processors
in a simplest possible way.
First things first, init test
with:
const {createTest} = require('@putout/test/processor');
const test = createTest(__dirname, {
extension: 'json',
processors: [
'json',
],
plugins: [
'eslint',
],
});
process(filename [, plugins, ])
Example:
test('putout: processor: json', async ({process}) => {
await process('eslintrc');
});
test('putout: processor: json', async ({process}) => {
await process('package', ['package-json']);
});
noProcess(filename [, plugins, processors])
Check that filename would not be processed.
Example:
test('putout: process: json: no process', async ({noProcess}) => {
await noProcess('eslintrc', [], ['json']);
});
comparePlaces(filename, places)
test('putout: processor: css: places', async ({comparePlaces}) => {
await comparePlaces('style', [{
message: 'Expected indentation of 4 spaces (indentation)',
position: {
column: 1,
line: 2,
},
rule: 'indentation (stylelint)',
}]);
});
License
MIT