Skip to content

Commit 6c7acab

Browse files
Mark1626SimenB
authored andcommitted
chore(valid-describe): migrate to TS (#308)
1 parent bdf1d38 commit 6c7acab

File tree

4 files changed

+116
-106
lines changed

4 files changed

+116
-106
lines changed

src/rules/__tests__/valid-describe.test.js renamed to src/rules/__tests__/valid-describe.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { RuleTester } from 'eslint';
1+
import { TSESLint } from '@typescript-eslint/experimental-utils';
22
import rule from '../valid-describe';
33

4-
const ruleTester = new RuleTester({
4+
const ruleTester = new TSESLint.RuleTester({
55
parserOptions: {
66
ecmaVersion: 8,
77
},

src/rules/tsUtils.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ export type FunctionExpression =
9090
| TSESTree.ArrowFunctionExpression
9191
| TSESTree.FunctionExpression;
9292

93-
/* istanbul ignore next */
9493
export const isFunction = (node: TSESTree.Node): node is FunctionExpression =>
9594
node.type === AST_NODE_TYPES.FunctionExpression ||
9695
node.type === AST_NODE_TYPES.ArrowFunctionExpression;

src/rules/valid-describe.js

Lines changed: 0 additions & 103 deletions
This file was deleted.

src/rules/valid-describe.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree';
2+
import {
3+
FunctionExpression,
4+
createRule,
5+
isDescribe,
6+
isFunction,
7+
} from './tsUtils';
8+
9+
const isAsync = (node: FunctionExpression): boolean => node.async;
10+
11+
const isString = (node: TSESTree.Node): boolean =>
12+
(node.type === AST_NODE_TYPES.Literal && typeof node.value === 'string') ||
13+
node.type === AST_NODE_TYPES.TemplateLiteral;
14+
15+
const hasParams = (node: FunctionExpression): boolean => node.params.length > 0;
16+
17+
const paramsLocation = (
18+
params: TSESTree.Expression[] | TSESTree.Parameter[],
19+
) => {
20+
const [first] = params;
21+
const last = params[params.length - 1];
22+
return {
23+
start: first.loc.start,
24+
end: last.loc.end,
25+
};
26+
};
27+
28+
export default createRule({
29+
name: __filename,
30+
meta: {
31+
type: 'problem',
32+
docs: {
33+
description:
34+
'Using an improper `describe()` callback function can lead to unexpected test errors.',
35+
category: 'Possible Errors',
36+
recommended: 'warn',
37+
},
38+
messages: {
39+
nameAndCallback: 'Describe requires name and callback arguments',
40+
firstArgumentMustBeName: 'First argument must be name',
41+
secondArgumentMustBeFunction: 'Second argument must be function',
42+
noAsyncDescribeCallback: 'No async describe callback',
43+
unexpectedDescribeArgument: 'Unexpected argument(s) in describe callback',
44+
unexpectedReturnInDescribe:
45+
'Unexpected return statement in describe callback',
46+
},
47+
schema: [],
48+
} as const,
49+
defaultOptions: [],
50+
create(context) {
51+
return {
52+
CallExpression(node) {
53+
if (isDescribe(node)) {
54+
if (node.arguments.length === 0) {
55+
return context.report({
56+
messageId: 'nameAndCallback',
57+
loc: node.loc,
58+
});
59+
}
60+
61+
const [name] = node.arguments;
62+
const [, callbackFunction] = node.arguments;
63+
if (!isString(name)) {
64+
context.report({
65+
messageId: 'firstArgumentMustBeName',
66+
loc: paramsLocation(node.arguments),
67+
});
68+
}
69+
if (!callbackFunction) {
70+
context.report({
71+
messageId: 'nameAndCallback',
72+
loc: paramsLocation(node.arguments),
73+
});
74+
75+
return;
76+
}
77+
if (isFunction(callbackFunction)) {
78+
if (isAsync(callbackFunction)) {
79+
context.report({
80+
messageId: 'noAsyncDescribeCallback',
81+
node: callbackFunction,
82+
});
83+
}
84+
if (hasParams(callbackFunction)) {
85+
context.report({
86+
messageId: 'unexpectedDescribeArgument',
87+
loc: paramsLocation(callbackFunction.params),
88+
});
89+
}
90+
if (
91+
callbackFunction.body &&
92+
callbackFunction.body.type === AST_NODE_TYPES.BlockStatement
93+
) {
94+
callbackFunction.body.body.forEach(node => {
95+
if (node.type === 'ReturnStatement') {
96+
context.report({
97+
messageId: 'unexpectedReturnInDescribe',
98+
node,
99+
});
100+
}
101+
});
102+
}
103+
} else {
104+
context.report({
105+
messageId: 'secondArgumentMustBeFunction',
106+
loc: paramsLocation(node.arguments),
107+
});
108+
return;
109+
}
110+
}
111+
},
112+
};
113+
},
114+
});

0 commit comments

Comments
 (0)