Skip to content

Commit

Permalink
feat(rules): prefer valid-title (#273) (#433)
Browse files Browse the repository at this point in the history
  • Loading branch information
suganya-sangith authored and G-Rath committed Oct 22, 2019
1 parent 5bd8f61 commit 1b2d24b
Show file tree
Hide file tree
Showing 4 changed files with 291 additions and 1 deletion.
65 changes: 65 additions & 0 deletions docs/rules/valid-title.md
@@ -0,0 +1,65 @@
# Disallow duplicate setup and teardown hooks (no-duplicate-hooks)

A describe/ test block should not contain accidentalSpace or duplicatePrefix.

## Rule Details

**duplicatePrefix**

A describe/ test block should not start with duplicatePrefix

Examples of **incorrect** code for this rule

```js
test('test foo', () => {});
it('it foo', () => {});

describe('foo', () => {
test('test bar', () => {});
});

describe('describe foo', () => {
test('bar', () => {});
});
```

Examples of **correct** code for this rule

```js
test('foo', () => {});
it('foo', () => {});

describe('foo', () => {
test('bar', () => {});
});
```

**accidentalSpace**

A describe/ test block should not contain accidentalSpace

Examples of **incorrect** code for this rule

```js
test(' foo', () => {});
it(' foo', () => {});

describe('foo', () => {
test(' bar', () => {});
});

describe(' foo', () => {
test('bar', () => {});
});
```

Examples of **correct** code for this rule

```js
test('foo', () => {});
it('foo', () => {});

describe('foo', () => {
test('bar', () => {});
});
```
2 changes: 1 addition & 1 deletion src/__tests__/rules.test.ts
Expand Up @@ -3,7 +3,7 @@ import { resolve } from 'path';
import plugin from '../';

const ruleNames = Object.keys(plugin.rules);
const numberOfRules = 40;
const numberOfRules = 41;

describe('rules', () => {
it('should have a corresponding doc for each rule', () => {
Expand Down
161 changes: 161 additions & 0 deletions src/rules/__tests__/valid-title.test.ts
@@ -0,0 +1,161 @@
import { TSESLint } from '@typescript-eslint/experimental-utils';
import rule from '../valid-title';

const ruleTester = new TSESLint.RuleTester({
parserOptions: {
ecmaVersion: 8,
},
});

ruleTester.run('no-accidental-space', rule, {
valid: [
'describe("foo", function () {})',
'describe(6, function () {})',
'fdescribe("foo", function () {})',
'xdescribe("foo", function () {})',
'it("foo", function () {})',
'fit("foo", function () {})',
'xit("foo", function () {})',
'test("foo", function () {})',
'xtest("foo", function () {})',
'someFn("foo", function () {})',
`
describe('foo', () => {
it('bar', () => {})
})
`,
],
invalid: [
{
code: 'describe(" foo", function () {})',
errors: [{ messageId: 'accidentalSpace', column: 1, line: 1 }],
},
{
code: 'fdescribe(" foo", function () {})',
errors: [{ messageId: 'accidentalSpace', column: 1, line: 1 }],
},
{
code: 'xdescribe(" foo", function () {})',
errors: [{ messageId: 'accidentalSpace', column: 1, line: 1 }],
},
{
code: 'it(" foo", function () {})',
errors: [{ messageId: 'accidentalSpace', column: 1, line: 1 }],
},
{
code: 'fit(" foo", function () {})',
errors: [{ messageId: 'accidentalSpace', column: 1, line: 1 }],
},
{
code: 'xit(" foo", function () {})',
errors: [{ messageId: 'accidentalSpace', column: 1, line: 1 }],
},
{
code: 'test(" foo", function () {})',
errors: [{ messageId: 'accidentalSpace', column: 1, line: 1 }],
},
{
code: 'xtest(" foo", function () {})',
errors: [{ messageId: 'accidentalSpace', column: 1, line: 1 }],
},
{
code: `
describe(' foo', () => {
it('bar', () => {})
})
`,
errors: [{ messageId: 'accidentalSpace', column: 7, line: 2 }],
},
{
code: `
describe('foo', () => {
it(' bar', () => {})
})
`,
errors: [{ messageId: 'accidentalSpace', column: 9, line: 3 }],
},
],
});

ruleTester.run('no-duplicate-prefix ft describe', rule, {
valid: [
'describe("foo", function () {})',
'fdescribe("foo", function () {})',
'xdescribe("foo", function () {})',
],
invalid: [
{
code: 'describe("describe foo", function () {})',
errors: [{ messageId: 'duplicatePrefix', column: 1, line: 1 }],
},
{
code: 'fdescribe("describe foo", function () {})',
errors: [{ messageId: 'duplicatePrefix', column: 1, line: 1 }],
},
{
code: 'xdescribe("describe foo", function () {})',
errors: [{ messageId: 'duplicatePrefix', column: 1, line: 1 }],
},
],
});

ruleTester.run('no-duplicate-prefix ft test', rule, {
valid: ['test("foo", function () {})', 'xtest("foo", function () {})'],
invalid: [
{
code: 'test("test foo", function () {})',
errors: [{ messageId: 'duplicatePrefix', column: 1, line: 1 }],
},
{
code: 'xtest("test foo", function () {})',
errors: [{ messageId: 'duplicatePrefix', column: 1, line: 1 }],
},
],
});

ruleTester.run('no-duplicate-prefix ft it', rule, {
valid: [
'it("foo", function () {})',
'fit("foo", function () {})',
'xit("foo", function () {})',
],
invalid: [
{
code: 'it("it foo", function () {})',
errors: [{ messageId: 'duplicatePrefix', column: 1, line: 1 }],
},
{
code: 'fit("it foo", function () {})',
errors: [{ messageId: 'duplicatePrefix', column: 1, line: 1 }],
},
{
code: 'xit("it foo", function () {})',
errors: [{ messageId: 'duplicatePrefix', column: 1, line: 1 }],
},
],
});

ruleTester.run('no-duplicate-prefix ft nested', rule, {
valid: [
`
describe('foo', () => {
it('bar', () => {})
})`,
],
invalid: [
{
code: `
describe('describe foo', () => {
it('bar', () => {})
})`,
errors: [{ messageId: 'duplicatePrefix', column: 7, line: 2 }],
},
{
code: `
describe('foo', () => {
it('it bar', () => {})
})`,
errors: [{ messageId: 'duplicatePrefix', column: 9, line: 3 }],
},
],
});
64 changes: 64 additions & 0 deletions src/rules/valid-title.ts
@@ -0,0 +1,64 @@
import {
createRule,
getNodeName,
getStringValue,
isDescribe,
isStringNode,
isTestCase,
} from './utils';

import { TSESTree } from '@typescript-eslint/experimental-utils';

const trimFXprefix = (word: string) =>
['f', 'x'].includes(word.charAt(0)) ? word.substr(1) : word;

const getNodeTitle = (node: TSESTree.CallExpression): string | null => {
const [argument] = node.arguments;

return isStringNode(argument) ? getStringValue(argument) : null;
};

export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Enforce valid titles',
recommended: false,
},
messages: {
duplicatePrefix: 'should not have duplicate prefix',
accidentalSpace: 'should not have space in the beginning',
},
type: 'suggestion',
schema: [],
},
defaultOptions: [],
create(context) {
return {
CallExpression(node) {
if (!isDescribe(node) && !isTestCase(node)) return;

const title = getNodeTitle(node);
if (!title) return;

if (title.trimLeft().length !== title.length) {
context.report({
messageId: 'accidentalSpace',
node,
});
}

const nodeName = trimFXprefix(getNodeName(node.callee));
const [firstWord] = title.split(' ');

if (firstWord.toLowerCase() === nodeName) {
context.report({
messageId: 'duplicatePrefix',
node,
});
}
},
};
},
});

0 comments on commit 1b2d24b

Please sign in to comment.