Skip to content

Commit 44de9fc

Browse files
authored
chore: lint and format on pre-commit and ci (#216)
* chore: lint and format on pre-commit and ci * chore: changing stage name in travis ci conf
1 parent 2ac6b81 commit 44de9fc

16 files changed

+1052
-705
lines changed

.huskyrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"hooks": {
3-
"pre-commit": "npm run test && lint-staged",
3+
"pre-commit": "lint-staged",
44
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
55
}
66
}

.lintstagedrc

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2-
"*.js": ["eslint --fix", "git add"],
3-
"*.md": ["prettier --write", "git add"]
2+
"*.{js,ts}": [
3+
"eslint --fix",
4+
"prettier --write",
5+
"jest --findRelatedTests",
6+
],
7+
"*.md": ["prettier --write"]
48
}

.travis.yml

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ before_script:
1717

1818
jobs:
1919
include:
20+
- stage: validation
21+
node_js: 14
22+
env: ESLINT=6
23+
script:
24+
- npm run format:check
25+
- npm run lint -- --max-warnings 0
2026
- stage: release
2127
if: branch = master AND type != pull_request
2228
node_js: 14

lib/node-utils.ts

+30-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/experimental-utils';
1+
import {
2+
AST_NODE_TYPES,
3+
TSESTree,
4+
} from '@typescript-eslint/experimental-utils';
25
import { RuleContext } from '@typescript-eslint/experimental-utils/dist/ts-eslint';
36

47
export function isCallExpression(
@@ -96,8 +99,10 @@ export function findClosestCallNode(
9699
}
97100
}
98101

99-
export function isObjectExpression(node: TSESTree.Expression): node is TSESTree.ObjectExpression {
100-
return node?.type === AST_NODE_TYPES.ObjectExpression
102+
export function isObjectExpression(
103+
node: TSESTree.Expression
104+
): node is TSESTree.ObjectExpression {
105+
return node?.type === AST_NODE_TYPES.ObjectExpression;
101106
}
102107

103108
export function hasThenProperty(node: TSESTree.Node) {
@@ -114,16 +119,24 @@ export function isAwaitExpression(
114119
return node && node.type === AST_NODE_TYPES.AwaitExpression;
115120
}
116121

117-
export function isArrowFunctionExpression(node: TSESTree.Node): node is TSESTree.ArrowFunctionExpression {
118-
return node && node.type === AST_NODE_TYPES.ArrowFunctionExpression
122+
export function isArrowFunctionExpression(
123+
node: TSESTree.Node
124+
): node is TSESTree.ArrowFunctionExpression {
125+
return node && node.type === AST_NODE_TYPES.ArrowFunctionExpression;
119126
}
120127

121-
export function isReturnStatement(node: TSESTree.Node): node is TSESTree.ReturnStatement {
122-
return node && node.type === AST_NODE_TYPES.ReturnStatement
128+
export function isReturnStatement(
129+
node: TSESTree.Node
130+
): node is TSESTree.ReturnStatement {
131+
return node && node.type === AST_NODE_TYPES.ReturnStatement;
123132
}
124133

125134
export function isAwaited(node: TSESTree.Node) {
126-
return isAwaitExpression(node) || isArrowFunctionExpression(node) || isReturnStatement(node)
135+
return (
136+
isAwaitExpression(node) ||
137+
isArrowFunctionExpression(node) ||
138+
isReturnStatement(node)
139+
);
127140
}
128141

129142
export function isPromiseResolved(node: TSESTree.Node) {
@@ -138,8 +151,15 @@ export function isPromiseResolved(node: TSESTree.Node) {
138151
return hasThenProperty(parent);
139152
}
140153

141-
export function getVariableReferences(context: RuleContext<string, []>, node: TSESTree.Node) {
142-
return (isVariableDeclarator(node) && context.getDeclaredVariables(node)[0].references.slice(1)) || [];
154+
export function getVariableReferences(
155+
context: RuleContext<string, []>,
156+
node: TSESTree.Node
157+
) {
158+
return (
159+
(isVariableDeclarator(node) &&
160+
context.getDeclaredVariables(node)[0].references.slice(1)) ||
161+
[]
162+
);
143163
}
144164

145165
export function isRenderFunction(
+22-18
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'
2-
import { getDocsUrl } from '../utils'
3-
import { isBlockStatement, findClosestCallNode, isMemberExpression, isCallExpression, isIdentifier } from '../node-utils'
1+
import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils';
2+
import { getDocsUrl } from '../utils';
3+
import {
4+
isBlockStatement,
5+
isMemberExpression,
6+
isCallExpression,
7+
isIdentifier,
8+
} from '../node-utils';
49

510
export const RULE_NAME = 'no-multiple-assertions-wait-for';
611

7-
const WAIT_EXPRESSION_QUERY =
8-
'CallExpression[callee.name=/^(waitFor)$/]';
12+
const WAIT_EXPRESSION_QUERY = 'CallExpression[callee.name=/^(waitFor)$/]';
913

1014
export type MessageIds = 'noMultipleAssertionWaitFor';
1115
type Options = [];
@@ -15,36 +19,36 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
1519
meta: {
1620
type: 'suggestion',
1721
docs: {
18-
description:
19-
"It's preferred to avoid multiple assertions in `waitFor`",
22+
description: "It's preferred to avoid multiple assertions in `waitFor`",
2023
category: 'Best Practices',
2124
recommended: false,
2225
},
2326
messages: {
24-
noMultipleAssertionWaitFor: 'Avoid using multiple assertions within `waitFor` callback',
27+
noMultipleAssertionWaitFor:
28+
'Avoid using multiple assertions within `waitFor` callback',
2529
},
2630
fixable: null,
2731
schema: [],
2832
},
2933
defaultOptions: [],
3034
create: function(context) {
31-
function reportMultipleAssertion(
32-
node: TSESTree.BlockStatement
33-
) {
35+
function reportMultipleAssertion(node: TSESTree.BlockStatement) {
3436
const totalExpect = (body: Array<TSESTree.Node>): Array<TSESTree.Node> =>
3537
body.filter((node: TSESTree.ExpressionStatement) => {
3638
if (
3739
isCallExpression(node.expression) &&
3840
isMemberExpression(node.expression.callee) &&
3941
isCallExpression(node.expression.callee.object)
4042
) {
41-
const object: TSESTree.CallExpression = node.expression.callee.object
42-
const expressionName: string = isIdentifier(object.callee) && object.callee.name
43-
return expressionName === 'expect'
43+
const object: TSESTree.CallExpression =
44+
node.expression.callee.object;
45+
const expressionName: string =
46+
isIdentifier(object.callee) && object.callee.name;
47+
return expressionName === 'expect';
4448
} else {
45-
return false
49+
return false;
4650
}
47-
})
51+
});
4852

4953
if (isBlockStatement(node) && totalExpect(node.body).length > 1) {
5054
context.report({
@@ -59,5 +63,5 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
5963
[`${WAIT_EXPRESSION_QUERY} > ArrowFunctionExpression > BlockStatement`]: reportMultipleAssertion,
6064
[`${WAIT_EXPRESSION_QUERY} > FunctionExpression > BlockStatement`]: reportMultipleAssertion,
6165
};
62-
}
63-
})
66+
},
67+
});

lib/rules/no-node-access.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({
2626
let isImportingTestingLibrary = false;
2727

2828
function checkTestingEnvironment(node: TSESTree.ImportDeclaration) {
29-
isImportingTestingLibrary = /testing-library/g.test(node.source.value as string);
29+
isImportingTestingLibrary = /testing-library/g.test(
30+
node.source.value as string
31+
);
3032
}
3133

3234
function showErrorForNodeAccess(node: TSESTree.MemberExpression) {

lib/rules/no-side-effects-wait-for.ts

+27-21
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'
2-
import { getDocsUrl, hasTestingLibraryImportModule } from '../utils'
3-
import { isBlockStatement, findClosestCallNode, isMemberExpression, isCallExpression, isIdentifier } from '../node-utils'
1+
import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils';
2+
import { getDocsUrl, hasTestingLibraryImportModule } from '../utils';
3+
import {
4+
isBlockStatement,
5+
isMemberExpression,
6+
isCallExpression,
7+
isIdentifier,
8+
} from '../node-utils';
49

510
export const RULE_NAME = 'no-side-effects-wait-for';
611

7-
const WAIT_EXPRESSION_QUERY =
8-
'CallExpression[callee.name=/^(waitFor)$/]';
12+
const WAIT_EXPRESSION_QUERY = 'CallExpression[callee.name=/^(waitFor)$/]';
913

10-
const SIDE_EFFECTS: Array<string> = ['fireEvent', 'userEvent']
14+
const SIDE_EFFECTS: Array<string> = ['fireEvent', 'userEvent'];
1115

1216
export type MessageIds = 'noSideEffectsWaitFor';
1317
type Options = [];
@@ -17,13 +21,13 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
1721
meta: {
1822
type: 'suggestion',
1923
docs: {
20-
description:
21-
"It's preferred to avoid side effects in `waitFor`",
24+
description: "It's preferred to avoid side effects in `waitFor`",
2225
category: 'Best Practices',
2326
recommended: false,
2427
},
2528
messages: {
26-
noSideEffectsWaitFor: 'Avoid using side effects within `waitFor` callback',
29+
noSideEffectsWaitFor:
30+
'Avoid using side effects within `waitFor` callback',
2731
},
2832
fixable: null,
2933
schema: [],
@@ -32,25 +36,27 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
3236
create: function(context) {
3337
let isImportingTestingLibrary = false;
3438

35-
function reportSideEffects(
36-
node: TSESTree.BlockStatement
37-
) {
39+
function reportSideEffects(node: TSESTree.BlockStatement) {
3840
const hasSideEffects = (body: Array<TSESTree.Node>): boolean =>
3941
body.some((node: TSESTree.ExpressionStatement) => {
4042
if (
4143
isCallExpression(node.expression) &&
4244
isMemberExpression(node.expression.callee) &&
4345
isIdentifier(node.expression.callee.object)
4446
) {
45-
const object: TSESTree.Identifier = node.expression.callee.object
46-
const identifierName: string = object.name
47-
return SIDE_EFFECTS.includes(identifierName)
47+
const object: TSESTree.Identifier = node.expression.callee.object;
48+
const identifierName: string = object.name;
49+
return SIDE_EFFECTS.includes(identifierName);
4850
} else {
49-
return false
51+
return false;
5052
}
51-
})
53+
});
5254

53-
if (isImportingTestingLibrary && isBlockStatement(node) && hasSideEffects(node.body)) {
55+
if (
56+
isImportingTestingLibrary &&
57+
isBlockStatement(node) &&
58+
hasSideEffects(node.body)
59+
) {
5460
context.report({
5561
node,
5662
loc: node.loc.start,
@@ -64,7 +70,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
6470
[`${WAIT_EXPRESSION_QUERY} > FunctionExpression > BlockStatement`]: reportSideEffects,
6571
ImportDeclaration(node: TSESTree.ImportDeclaration) {
6672
isImportingTestingLibrary = hasTestingLibraryImportModule(node);
67-
}
73+
},
6874
};
69-
}
70-
})
75+
},
76+
});

lib/rules/prefer-screen-queries.ts

+22-11
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@ export const RULE_NAME = 'prefer-screen-queries';
1313
export type MessageIds = 'preferScreenQueries';
1414
type Options = [];
1515

16-
const ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING = ['container', 'baseElement']
16+
const ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING = [
17+
'container',
18+
'baseElement',
19+
];
1720
const ALL_QUERIES_COMBINATIONS_REGEXP = ALL_QUERIES_COMBINATIONS.join('|');
1821

1922
function usesContainerOrBaseElement(node: TSESTree.CallExpression) {
20-
const secondArgument = node.arguments[1]
21-
return isObjectExpression(secondArgument) && secondArgument.properties.some((property) => isProperty(property) && isIdentifier(property.key) && ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING.includes(property.key.name))
23+
const secondArgument = node.arguments[1];
24+
return (
25+
isObjectExpression(secondArgument) &&
26+
secondArgument.properties.some(
27+
property =>
28+
isProperty(property) &&
29+
isIdentifier(property.key) &&
30+
ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING.includes(property.key.name)
31+
)
32+
);
2233
}
2334

2435
export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
@@ -57,15 +68,14 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
5768

5869
return {
5970
VariableDeclarator(node) {
60-
if (!
61-
isCallExpression(node.init) || !
62-
isIdentifier(node.init.callee) ) {
63-
return
71+
if (!isCallExpression(node.init) || !isIdentifier(node.init.callee)) {
72+
return;
6473
}
65-
const isWithinFunction =
66-
node.init.callee.name === 'within';
74+
const isWithinFunction = node.init.callee.name === 'within';
6775
// TODO add the custom render option #198
68-
const usesRenderOptions = node.init.callee.name === 'render' && usesContainerOrBaseElement(node.init);
76+
const usesRenderOptions =
77+
node.init.callee.name === 'render' &&
78+
usesContainerOrBaseElement(node.init);
6979

7080
if (!isWithinFunction && !usesRenderOptions) {
7181
return;
@@ -117,7 +127,8 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
117127
isCallExpression(node.parent.object) &&
118128
isIdentifier(node.parent.object.callee) &&
119129
node.parent.object.callee.name !== 'within' &&
120-
node.parent.object.callee.name === 'render' && !usesContainerOrBaseElement(node.parent.object)
130+
node.parent.object.callee.name === 'render' &&
131+
!usesContainerOrBaseElement(node.parent.object)
121132
) {
122133
reportInvalidUsage(node);
123134
return;

0 commit comments

Comments
 (0)