Skip to content

Latest commit

 

History

History

README.md

@putout/plugin-tape NPM version

Tape-inspired TAP-compatible simplest high speed test runner with superpowers.

(c) 📼Supertape

🐊Putout plugin helps to apply best parctises for tests written with 📼Supertape.

Install

npm i @putout/plugin-tape -D

Rules

Config

{
    "rules": {
        "tape/jest": "on",
        "tape/apply-stub": "on",
        "tape/apply-destructuring": "on",
        "tape/apply-with-name": "on",
        "tape/add-t-end": "on",
        "tape/remove-useless-t-end": "on",
        "tape/sync-with-name": "on",
        "tape/switch-expected-with-result": "on",
        "tape/convert-tape-to-supertape": "on",
        "tape/convert-throws-to-try-catch": "on",
        "tape/convert-does-not-throw-to-try-catch": "on",
        "tape/convert-called-with-args": "on",
        "tape/convert-called-with-to-called-with-no-args": "on",
        "tape/convert-called-with-no-args-to-called-with": "on",
        "tape/convert-equal-to-called-once": "on",
        "tape/convert-equal-to-deep-equal": "on",
        "tape/convert-equals-to-equal": "on",
        "tape/convert-deep-equal-to-equal": "on",
        "tape/convert-emitter-to-promise": "on",
        "tape/convert-ok-to-match": "on",
        "tape/convert-ok-to-called-with": "on",
        "tape/convert-match-regexp-to-string": "on",
        "tape/add-args": "on",
        "tape/declare": "on",
        "tape/remove-default-messages": "on",
        "tape/remove-useless-not-called-args": "on",
        "tape/remove-only": ["on", {
            "allowed": ["test"]
        }],
        "tape/remove-skip": ["on", {
            "allowed": ["test"]
        }]
    }
}

jest

🐊Putout gives ability to switch easily from Jest to 📼Supertape. Checkout in 🐊Putout Editor.

❌ Example of incorrect code

it('should equal', () => {
    expect(a).toEqual(b);
});

✅ Example of correct code

import {test} from 'supertape';

test('should equal', () => {
    t.equal(a, b);
    t.end();
});

switch-expected-with-result

📼Supertape uses more natural way of comparing: first you pass result and then expected.

It gives you ability to use value instead of expected and understand code faster: no need to search for a second argument. While result is always a variable, so it most likely much shorter.

❌ Example of incorrect code

test('plugin-apply-destructuring: transform: array: destructuring', (t) => {
    t.equal(expected, result);
    t.end();
});

✅ Example of correct code

test('plugin-apply-destructuring: transform: array: destructuring', (t) => {
    t.equal(result, expected);
    t.end();
});

convert-tape-to-supertape

❌ Example of incorrect code

const test = require('tape');

✅ Example of correct code

const test = require('supertape');

convert-throws-to-try-catch

❌ Example of incorrect code

const test = require('supertape');

test('some message', (t) => {
    t.throws(copymitter, /from should be a string!/, 'should throw when no args');
    t.end();
});

✅ Example of correct code

const {tryCatch} = require('try-catch');
const test = require('supertape');

test('some message', (t) => {
    const [error] = tryCatch(copymitter);
    
    t.equal(error.message, 'from should be a string!');
    t.end();
});

convert-does-not-throw-to-try-catch

❌ Example of incorrect code

const test = require('supertape');

test('some message', (t) => {
    t.doesNotThrow(copymitter, 'should throw when no args');
    t.end();
});

✅ Example of correct code

const test = require('supertape');
const {tryCatch} = require('try-catch');

test('some test', (t) => {
    const [error] = tryCatch(copymitter);
    
    t.notOk(error, 'should not throw when no args');
    t.end();
});

convert-called-with-args

❌ Example of incorrect code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    const fn = stub();
    fn();
    
    t.calledWith(fn, 'hello');
    t.end();
});

✅ Example of correct code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    const fn = stub();
    fn();
    
    t.calledWith(fn, ['hello']);
    t.end();
});

convert-equal-to-called-once

No need to use equal, supertape supports calledOnce.

❌ Example of incorrect code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    const fn = stub();
    fn();
    
    t.equal(fn.callCount, 1);
    t.end();
});

✅ Example of correct code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    const fn = stub();
    fn();
    
    t.calledOnce(fn);
    t.end();
});

convert-deep-equal-to-equal

Use equal when comparing with primitives, deepEqual for Objects and Arrays;

❌ Example of incorrect code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    t.deepEqual(x, 5);
    t.end();
});

✅ Example of correct code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    t.equal(x, 5);
    t.end();
});

convert-called-with-to-called-with-no-args

❌ Example of incorrect code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    const fn = stub();
    fn();
    
    t.calledWith(fn);
    t.end();
});

✅ Example of correct code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    const fn = stub();
    fn();
    
    t.calledWithNoArgs(fn);
    t.end();
});

convert-called-with-no-args-to-called-with

❌ Example of incorrect code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    const fn = stub();
    fn();
    
    t.calledWithNoArgs(fn, [1, 2]);
    t.end();
});

✅ Example of correct code

const test = require('supertape');
const {stub} = test;

test('some message', (t) => {
    const fn = stub();
    fn();
    
    t.calledWith(fn, [1, 2]);
    t.end();
});

convert-emitter-to-promise

❌ Example of incorrect code

test('copymitter', (t) => {
    const cp = copymitter(from, to, ['1']);
    
    cp.on('end', (t) => {
        t.end();
    });
});

✅ Example of correct code

const {once} = require('node:events');

test('copymitter', async (t) => {
    const cp = copymitter(from, to, ['1']);
    
    await once(cp, 'end');
    
    t.end();
});

apply-destructuring

Check out in 🐊Putout Editor.

❌ Example of incorrect code

const test = require('supertape');

✅ Example of correct code

const {test} = require('supertape');

apply-stub

Apply stub functions created. Look how it works in 🐊Putout Editor.

❌ Example of incorrect code

const a = async () => true;
const b = async () => {};
const c = async () => throwError('hello');

const d = async () => {
    throw Error('hello');
};

✅ Example of correct code

const a = stub().resolves(true);
const b = stub().resolves();
const c = stub().rejects(Error('hello'));
const d = stub().rejects(Error('hello'));

apply-with-name

❌ Example of incorrect code

test('should call init before show', (t) => {
    const init = stub();
    const show = stub();
    
    t.calledInOrder([init, show]);
    t.end();
});

✅ Example of correct code

test('should call init before show', (t) => {
    const init = stub().withName('init');
    const show = stub().withName('show');
    
    t.calledInOrder([init, show]);
    t.end();
});

sync-with-name

❌ Example of incorrect code

test('should call init before show', (t) => {
    const init = stub().withName('show');
    const show = stub().withName('show');
    
    t.calledInOrder([init, show]);
    t.end();
});

✅ Example of correct code

test('should call init before show', (t) => {
    const init = stub().withName('init');
    const show = stub().withName('show');
    
    t.calledInOrder([init, show]);
    t.end();
});

declare

❌ Example of incorrect code

test('xxx', (t) => {
    const a = stub();
    t.end();
});

✅ Example of correct code

import {test, stub} from 'supertape';

test('xxx', (t) => {
    const a = stub();
    t.end();
});

add-args

❌ Example of incorrect code

test('xxx', () => {
    t.end();
});

✅ Example of correct code

test('xxx', (t) => {
    t.end();
});

add-t-end

❌ Example of incorrect code

test('xxx', () => {});

✅ Example of correct code

test('xxx', (t) => {
    t.end();
});

remove-useless-t-end

❌ Example of incorrect code

test('test: remove me', () => {
    t.end();
    t.end();
});

✅ Example of correct code

test('test: remove me', () => {
    t.end();
});

convert-ok-to-match

❌ Example of incorrect code

t.ok(result.includes('hello'));

✅ Example of correct code

t.match(result, /hello/);

convert-ok-to-called-with

❌ Example of incorrect code

t.ok(set.calledWith(1, 2));

✅ Example of correct code

t.calledWith(set, [1, 2]);

convert-equal-to-not-ok

❌ Example of incorrect code

t.equal(error, null);

✅ Example of correct code

t.notOk(error);

convert-equal-to-ok

❌ Example of incorrect code

t.equal(result, true);

✅ Example of correct code

t.ok(result);

convert-equal-to-deep-equal

❌ Example of incorrect code

const expected = {
    hello: 'world',
};

t.equal(error, expected);
t.end();

✅ Example of correct code

const expected = {
    hello: 'world',
};

t.deepEqual(error, expected);
t.end();

convert-equals-to-equal

Checkout in 🐊Putout Editor.

❌ Example of incorrect code

t.equals(e.message, 'token should be a string!', 'should throw');

✅ Example of correct code

t.equal(e.message, 'token should be a string!', 'should throw');

convert-match-regexp-to-string

❌ Example of incorrect code

t.match(result, RegExp('hello'));

✅ Example of correct code

t.match(result, 'hello');

remove-default-messages

📼Supertape will put this information for you, and it is always the same. No need to repeat the same information twice on one line, better to avoid it.

❌ Example of incorrect code

t.equal(result, expected, 'should equal');

✅ Example of correct code

t.equal(result, expected);

remove-useless-not-called-args

❌ Example of incorrect code

t.notCalled(fn, []);

✅ Example of correct code

t.notCalled(fn);

remove-only

❌ Example of incorrect code

test.only('some test', (t) => {
    t.end();
});

testDeclareBeforeReference.only('some test', (t) => {
    t.end();
});

✅ Example of correct code

test('some test', (t) => {
    t.end();
});

testDeclareBeforeReference('some test', (t) => {
    t.end();
});

remove-skip

❌ Example of incorrect code

test.skip('some test', (t) => {
    t.end();
});

✅ Example of correct code

test('some test', (t) => {
    t.end();
});

License

MIT