eslint-plugin-jest 22.3.0 → 22.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -96,6 +96,7 @@ for more information about extending configuration files.
96
96
  | [lowercase-name][] | Disallow capitalized test names | | ![fixable-green][] |
97
97
  | [no-alias-methods][] | Disallow alias methods | ![recommended][] | ![fixable-green][] |
98
98
  | [no-disabled-tests][] | Disallow disabled tests | ![recommended][] | |
99
+ | [no-empty-title][] | Disallow empty titles | | |
99
100
  | [no-focused-tests][] | Disallow focused tests | ![recommended][] | |
100
101
  | [no-hooks][] | Disallow setup and teardown hooks | | |
101
102
  | [no-identical-title][] | Disallow identical titles | ![recommended][] | |
@@ -131,6 +132,7 @@ for more information about extending configuration files.
131
132
  [lowercase-name]: docs/rules/lowercase-name.md
132
133
  [no-alias-methods]: docs/rules/no-alias-methods.md
133
134
  [no-disabled-tests]: docs/rules/no-disabled-tests.md
135
+ [no-empty-title]: docs/rules/no-empty-title.md
134
136
  [no-focused-tests]: docs/rules/no-focused-tests.md
135
137
  [no-hooks]: docs/rules/no-hooks.md
136
138
  [no-identical-title]: docs/rules/no-identical-title.md
@@ -0,0 +1,36 @@
1
+ # Disallow empty titles
2
+
3
+ Having an empty string as your test title is pretty useless. This rule reports
4
+ an error if it finds an empty string as s test title.
5
+
6
+ This rule is not auto-fixable.
7
+
8
+ ## Rule Details
9
+
10
+ The following patterns are considered warnings:
11
+
12
+ ```js
13
+ describe('', () => {});
14
+ describe('foo', () => {
15
+ it('', () => {});
16
+ });
17
+ it('', () => {});
18
+ test('', () => {});
19
+ xdescribe('', () => {});
20
+ xit('', () => {});
21
+ xtest('', () => {});
22
+ ```
23
+
24
+ These patterns would not be considered warnings:
25
+
26
+ ```js
27
+ describe('foo', () => {});
28
+ describe('foo', () => {
29
+ it('bar', () => {});
30
+ });
31
+ test('foo', () => {});
32
+ it('foo', () => {});
33
+ xdescribe('foo', () => {});
34
+ xit('foo', () => {});
35
+ xtest('foo', () => {});
36
+ ```
package/index.js CHANGED
@@ -1,34 +1,16 @@
1
1
  'use strict';
2
2
 
3
- const consistentTestIt = require('./rules/consistent-test-it');
4
- const expectExpect = require('./rules/expect-expect');
5
- const lowercaseName = require('./rules/lowercase-name');
6
- const noDisabledTests = require('./rules/no-disabled-tests');
7
- const noFocusedTests = require('./rules/no-focused-tests');
8
- const noHooks = require('./rules/no-hooks');
9
- const noIdenticalTitle = require('./rules/no-identical-title');
10
- const noJasmineGlobals = require('./rules/no-jasmine-globals');
11
- const noJestImport = require('./rules/no-jest-import');
12
- const noLargeSnapshots = require('./rules/no-large-snapshots');
13
- const noTestPrefixes = require('./rules/no-test-prefixes');
14
- const noTestReturnStatement = require('./rules/no-test-return-statement');
15
- const preferSpyOn = require('./rules/prefer-spy-on');
16
- const preferToBeNull = require('./rules/prefer-to-be-null');
17
- const preferToBeUndefined = require('./rules/prefer-to-be-undefined');
18
- const preferToContain = require('./rules/prefer-to-contain');
19
- const preferToHaveLength = require('./rules/prefer-to-have-length');
20
- const validDescribe = require('./rules/valid-describe');
21
- const validExpect = require('./rules/valid-expect');
22
- const preferExpectAssertions = require('./rules/prefer-expect-assertions');
23
- const validExpectInPromise = require('./rules/valid-expect-in-promise');
24
- const preferInlineSnapshots = require('./rules/prefer-inline-snapshots');
25
- const preferStrictEqual = require('./rules/prefer-strict-equal');
26
- const requireTothrowMessage = require('./rules/require-tothrow-message');
27
- const noAliasMethods = require('./rules/no-alias-methods');
28
- const noTestCallback = require('./rules/no-test-callback');
29
- const noTruthyFalsy = require('./rules/no-truthy-falsy');
30
- const preferTodo = require('./rules/prefer-todo');
31
- const preferCalledWith = require('./rules/prefer-called-with');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const rules = fs
7
+ .readdirSync(path.join(__dirname, 'rules'))
8
+ .filter(rule => rule !== '__tests__' && rule !== 'util.js')
9
+ .map(rule => path.basename(rule, '.js'))
10
+ .reduce(
11
+ (acc, curr) => Object.assign(acc, { [curr]: require(`./rules/${curr}`) }),
12
+ {}
13
+ );
32
14
 
33
15
  const snapshotProcessor = require('./processors/snapshot-processor');
34
16
 
@@ -88,35 +70,5 @@ module.exports = {
88
70
  processors: {
89
71
  '.snap': snapshotProcessor,
90
72
  },
91
- rules: {
92
- 'consistent-test-it': consistentTestIt,
93
- 'expect-expect': expectExpect,
94
- 'lowercase-name': lowercaseName,
95
- 'no-disabled-tests': noDisabledTests,
96
- 'no-focused-tests': noFocusedTests,
97
- 'no-hooks': noHooks,
98
- 'no-identical-title': noIdenticalTitle,
99
- 'no-jasmine-globals': noJasmineGlobals,
100
- 'no-jest-import': noJestImport,
101
- 'no-large-snapshots': noLargeSnapshots,
102
- 'no-test-prefixes': noTestPrefixes,
103
- 'no-test-return-statement': noTestReturnStatement,
104
- 'prefer-spy-on': preferSpyOn,
105
- 'prefer-to-be-null': preferToBeNull,
106
- 'prefer-to-be-undefined': preferToBeUndefined,
107
- 'prefer-to-contain': preferToContain,
108
- 'prefer-to-have-length': preferToHaveLength,
109
- 'valid-describe': validDescribe,
110
- 'valid-expect': validExpect,
111
- 'prefer-expect-assertions': preferExpectAssertions,
112
- 'valid-expect-in-promise': validExpectInPromise,
113
- 'prefer-inline-snapshots': preferInlineSnapshots,
114
- 'prefer-strict-equal': preferStrictEqual,
115
- 'require-tothrow-message': requireTothrowMessage,
116
- 'no-alias-methods': noAliasMethods,
117
- 'no-test-callback': noTestCallback,
118
- 'no-truthy-falsy': noTruthyFalsy,
119
- 'prefer-todo': preferTodo,
120
- 'prefer-called-with': preferCalledWith,
121
- },
73
+ rules,
122
74
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-jest",
3
- "version": "22.3.0",
3
+ "version": "22.4.1",
4
4
  "description": "Eslint rules for Jest",
5
5
  "repository": "jest-community/eslint-plugin-jest",
6
6
  "license": "MIT",
@@ -35,7 +35,7 @@
35
35
  "@commitlint/cli": "^7.0.0",
36
36
  "@commitlint/config-conventional": "^7.0.1",
37
37
  "eslint": "^5.1.0",
38
- "eslint-config-prettier": "^3.0.1",
38
+ "eslint-config-prettier": "^4.1.0",
39
39
  "eslint-plugin-eslint-plugin": "^2.0.0",
40
40
  "eslint-plugin-node": "^8.0.0",
41
41
  "eslint-plugin-prettier": "^3.0.0",
@@ -0,0 +1,108 @@
1
+ 'use strict';
2
+
3
+ const { RuleTester } = require('eslint');
4
+ const rule = require('../no-empty-title');
5
+
6
+ const ruleTester = new RuleTester({
7
+ parserOptions: {
8
+ sourceType: 'module',
9
+ },
10
+ });
11
+
12
+ ruleTester.run('no-empty-title', rule, {
13
+ valid: [
14
+ 'someFn("", function () {})',
15
+ 'describe(1, function () {})',
16
+ 'describe("foo", function () {})',
17
+ 'describe("foo", function () { it("bar", function () {}) })',
18
+ 'test("foo", function () {})',
19
+ 'test(`foo`, function () {})',
20
+ 'test(`${foo}`, function () {})',
21
+ "it('foo', function () {})",
22
+ "xdescribe('foo', function () {})",
23
+ "xit('foo', function () {})",
24
+ "xtest('foo', function () {})",
25
+ ],
26
+ invalid: [
27
+ {
28
+ code: 'describe("", function () {})',
29
+ errors: [
30
+ {
31
+ message: rule.errorMessages.describe,
32
+ column: 1,
33
+ line: 1,
34
+ },
35
+ ],
36
+ },
37
+ {
38
+ code: ["describe('foo', () => {", "it('', () => {})", '})'].join('\n'),
39
+ errors: [
40
+ {
41
+ message: rule.errorMessages.test,
42
+ column: 1,
43
+ line: 2,
44
+ },
45
+ ],
46
+ },
47
+ {
48
+ code: 'it("", function () {})',
49
+ errors: [
50
+ {
51
+ message: rule.errorMessages.test,
52
+ column: 1,
53
+ line: 1,
54
+ },
55
+ ],
56
+ },
57
+ {
58
+ code: 'test("", function () {})',
59
+ errors: [
60
+ {
61
+ message: rule.errorMessages.test,
62
+ column: 1,
63
+ line: 1,
64
+ },
65
+ ],
66
+ },
67
+ {
68
+ code: 'test(``, function () {})',
69
+ errors: [
70
+ {
71
+ message: rule.errorMessages.test,
72
+ column: 1,
73
+ line: 1,
74
+ },
75
+ ],
76
+ },
77
+ {
78
+ code: "xdescribe('', () => {})",
79
+ errors: [
80
+ {
81
+ message: rule.errorMessages.describe,
82
+ column: 1,
83
+ line: 1,
84
+ },
85
+ ],
86
+ },
87
+ {
88
+ code: "xit('', () => {})",
89
+ errors: [
90
+ {
91
+ message: rule.errorMessages.test,
92
+ column: 1,
93
+ line: 1,
94
+ },
95
+ ],
96
+ },
97
+ {
98
+ code: "xtest('', () => {})",
99
+ errors: [
100
+ {
101
+ message: rule.errorMessages.test,
102
+ column: 1,
103
+ line: 1,
104
+ },
105
+ ],
106
+ },
107
+ ],
108
+ });
@@ -12,6 +12,8 @@ ruleTester.run('no-identical-title', rule, {
12
12
  ' it("it", function() {});',
13
13
  '});',
14
14
  ].join('\n'),
15
+ ['describe();describe();'].join('\n'),
16
+ ['it();it();'].join('\n'),
15
17
  [
16
18
  'describe("describe1", function() {',
17
19
  ' it("it1", function() {});',
@@ -67,6 +69,12 @@ ruleTester.run('no-identical-title', rule, {
67
69
  es6: true,
68
70
  },
69
71
  },
72
+ {
73
+ code: 'it(`${n}`, function() {});',
74
+ env: {
75
+ es6: true,
76
+ },
77
+ },
70
78
  [
71
79
  'describe("title " + foo, function() {',
72
80
  ' describe("describe1", function() {});',
@@ -81,6 +89,32 @@ ruleTester.run('no-identical-title', rule, {
81
89
  ' });',
82
90
  '});',
83
91
  ].join('\n'),
92
+ {
93
+ code: [
94
+ 'describe("describe", () => {',
95
+ ' it(`testing ${someVar} with the same title`, () => {});',
96
+ ' it(`testing ${someVar} with the same title`, () => {});',
97
+ '});',
98
+ ].join('\n'),
99
+ env: {
100
+ es6: true,
101
+ },
102
+ },
103
+ {
104
+ code: ['it(`it1`, () => {});', 'it(`it2`, () => {});'].join('\n'),
105
+ env: {
106
+ es6: true,
107
+ },
108
+ },
109
+ {
110
+ code: [
111
+ 'describe(`describe1`, () => {});',
112
+ 'describe(`describe2`, () => {});',
113
+ ].join('\n'),
114
+ env: {
115
+ es6: true,
116
+ },
117
+ },
84
118
  ],
85
119
 
86
120
  invalid: [
@@ -212,5 +246,24 @@ ruleTester.run('no-identical-title', rule, {
212
246
  },
213
247
  ],
214
248
  },
249
+ {
250
+ code: [
251
+ 'describe("describe", () => {',
252
+ ' it(`testing backticks with the same title`, () => {});',
253
+ ' it(`testing backticks with the same title`, () => {});',
254
+ '});',
255
+ ].join('\n'),
256
+ env: {
257
+ es6: true,
258
+ },
259
+ errors: [
260
+ {
261
+ message:
262
+ 'Test title is used multiple times in the same describe block.',
263
+ column: 5,
264
+ line: 3,
265
+ },
266
+ ],
267
+ },
215
268
  ],
216
269
  });
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ getDocsUrl,
5
+ hasExpressions,
6
+ isDescribe,
7
+ isTestCase,
8
+ isTemplateLiteral,
9
+ isString,
10
+ getStringValue,
11
+ } = require('./util');
12
+
13
+ const errorMessages = {
14
+ describe: 'describe should not have an empty title',
15
+ test: 'test should not have an empty title',
16
+ };
17
+
18
+ module.exports = {
19
+ meta: {
20
+ docs: {
21
+ url: getDocsUrl(__filename),
22
+ },
23
+ },
24
+ create(context) {
25
+ return {
26
+ CallExpression(node) {
27
+ const is = {
28
+ describe: isDescribe(node),
29
+ testCase: isTestCase(node),
30
+ };
31
+ if (!is.describe && !is.testCase) {
32
+ return;
33
+ }
34
+ const [firstArgument] = node.arguments;
35
+ if (!isString(firstArgument)) {
36
+ return;
37
+ }
38
+ if (isTemplateLiteral(firstArgument) && hasExpressions(firstArgument)) {
39
+ return;
40
+ }
41
+ if (getStringValue(firstArgument) === '') {
42
+ const message = is.describe
43
+ ? errorMessages.describe
44
+ : errorMessages.test;
45
+ context.report({
46
+ message,
47
+ node,
48
+ });
49
+ }
50
+ },
51
+ };
52
+ },
53
+ errorMessages,
54
+ };
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
 
3
- const { getDocsUrl, isDescribe, isTestCase } = require('./util');
3
+ const {
4
+ getDocsUrl,
5
+ isDescribe,
6
+ isTestCase,
7
+ isString,
8
+ hasExpressions,
9
+ getStringValue,
10
+ } = require('./util');
4
11
 
5
12
  const newDescribeContext = () => ({
6
13
  describeTitles: [],
@@ -34,8 +41,15 @@ const handleDescribeBlockTitles = (context, titles, node, title) => {
34
41
  titles.push(title);
35
42
  };
36
43
 
37
- const isFirstArgLiteral = node =>
38
- node.arguments && node.arguments[0] && node.arguments[0].type === 'Literal';
44
+ const isFirstArgValid = arg => {
45
+ if (!arg || !isString(arg)) {
46
+ return false;
47
+ }
48
+ if (arg.type === 'TemplateLiteral' && hasExpressions(arg)) {
49
+ return false;
50
+ }
51
+ return true;
52
+ };
39
53
 
40
54
  module.exports = {
41
55
  meta: {
@@ -51,11 +65,11 @@ module.exports = {
51
65
  if (isDescribe(node)) {
52
66
  contexts.push(newDescribeContext());
53
67
  }
54
- if (!isFirstArgLiteral(node)) {
68
+ const [firstArgument] = node.arguments;
69
+ if (!isFirstArgValid(firstArgument)) {
55
70
  return;
56
71
  }
57
-
58
- const title = node.arguments[0].value;
72
+ const title = getStringValue(firstArgument);
59
73
  handleTestCaseTitles(context, currentLayer.testTitles, node, title);
60
74
  handleDescribeBlockTitles(
61
75
  context,
package/rules/util.js CHANGED
@@ -132,7 +132,14 @@ const isFunction = node =>
132
132
 
133
133
  const isString = node =>
134
134
  (node.type === 'Literal' && typeof node.value === 'string') ||
135
- node.type === 'TemplateLiteral';
135
+ isTemplateLiteral(node);
136
+
137
+ const isTemplateLiteral = node => node.type === 'TemplateLiteral';
138
+
139
+ const hasExpressions = node => node.expressions && node.expressions.length > 0;
140
+
141
+ const getStringValue = arg =>
142
+ isTemplateLiteral(arg) ? arg.quasis[0].value.raw : arg.value;
136
143
 
137
144
  /**
138
145
  * Generates the URL to documentation for the given rule name. It uses the
@@ -208,10 +215,13 @@ module.exports = {
208
215
  expectToEqualCase,
209
216
  expectNotToEqualCase,
210
217
  getNodeName,
218
+ getStringValue,
211
219
  isDescribe,
212
220
  isFunction,
221
+ isTemplateLiteral,
213
222
  isTestCase,
214
223
  isString,
224
+ hasExpressions,
215
225
  getDocsUrl,
216
226
  scopeHasLocalReference,
217
227
  composeFixers,