Skip to content

Commit 47b63a7

Browse files
committed
chore: lint and format on pre-commit and ci
1 parent 2ac6b81 commit 47b63a7

16 files changed

+1052
-705
lines changed

.huskyrc

Lines changed: 1 addition & 1 deletion
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

Lines changed: 6 additions & 2 deletions
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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ before_script:
1717

1818
jobs:
1919
include:
20+
- stage: test
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

Lines changed: 30 additions & 10 deletions
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(
Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
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+
findClosestCallNode,
6+
isMemberExpression,
7+
isCallExpression,
8+
isIdentifier,
9+
} from '../node-utils';
410

511
export const RULE_NAME = 'no-multiple-assertions-wait-for';
612

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

1015
export type MessageIds = 'noMultipleAssertionWaitFor';
1116
type Options = [];
@@ -15,36 +20,36 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
1520
meta: {
1621
type: 'suggestion',
1722
docs: {
18-
description:
19-
"It's preferred to avoid multiple assertions in `waitFor`",
23+
description: "It's preferred to avoid multiple assertions in `waitFor`",
2024
category: 'Best Practices',
2125
recommended: false,
2226
},
2327
messages: {
24-
noMultipleAssertionWaitFor: 'Avoid using multiple assertions within `waitFor` callback',
28+
noMultipleAssertionWaitFor:
29+
'Avoid using multiple assertions within `waitFor` callback',
2530
},
2631
fixable: null,
2732
schema: [],
2833
},
2934
defaultOptions: [],
3035
create: function(context) {
31-
function reportMultipleAssertion(
32-
node: TSESTree.BlockStatement
33-
) {
36+
function reportMultipleAssertion(node: TSESTree.BlockStatement) {
3437
const totalExpect = (body: Array<TSESTree.Node>): Array<TSESTree.Node> =>
3538
body.filter((node: TSESTree.ExpressionStatement) => {
3639
if (
3740
isCallExpression(node.expression) &&
3841
isMemberExpression(node.expression.callee) &&
3942
isCallExpression(node.expression.callee.object)
4043
) {
41-
const object: TSESTree.CallExpression = node.expression.callee.object
42-
const expressionName: string = isIdentifier(object.callee) && object.callee.name
43-
return expressionName === 'expect'
44+
const object: TSESTree.CallExpression =
45+
node.expression.callee.object;
46+
const expressionName: string =
47+
isIdentifier(object.callee) && object.callee.name;
48+
return expressionName === 'expect';
4449
} else {
45-
return false
50+
return false;
4651
}
47-
})
52+
});
4853

4954
if (isBlockStatement(node) && totalExpect(node.body).length > 1) {
5055
context.report({
@@ -59,5 +64,5 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
5964
[`${WAIT_EXPRESSION_QUERY} > ArrowFunctionExpression > BlockStatement`]: reportMultipleAssertion,
6065
[`${WAIT_EXPRESSION_QUERY} > FunctionExpression > BlockStatement`]: reportMultipleAssertion,
6166
};
62-
}
63-
})
67+
},
68+
});

lib/rules/no-node-access.ts

Lines changed: 3 additions & 1 deletion
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

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
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+
findClosestCallNode,
6+
isMemberExpression,
7+
isCallExpression,
8+
isIdentifier,
9+
} from '../node-utils';
410

511
export const RULE_NAME = 'no-side-effects-wait-for';
612

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

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

1217
export type MessageIds = 'noSideEffectsWaitFor';
1318
type Options = [];
@@ -17,13 +22,13 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
1722
meta: {
1823
type: 'suggestion',
1924
docs: {
20-
description:
21-
"It's preferred to avoid side effects in `waitFor`",
25+
description: "It's preferred to avoid side effects in `waitFor`",
2226
category: 'Best Practices',
2327
recommended: false,
2428
},
2529
messages: {
26-
noSideEffectsWaitFor: 'Avoid using side effects within `waitFor` callback',
30+
noSideEffectsWaitFor:
31+
'Avoid using side effects within `waitFor` callback',
2732
},
2833
fixable: null,
2934
schema: [],
@@ -32,25 +37,27 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
3237
create: function(context) {
3338
let isImportingTestingLibrary = false;
3439

35-
function reportSideEffects(
36-
node: TSESTree.BlockStatement
37-
) {
40+
function reportSideEffects(node: TSESTree.BlockStatement) {
3841
const hasSideEffects = (body: Array<TSESTree.Node>): boolean =>
3942
body.some((node: TSESTree.ExpressionStatement) => {
4043
if (
4144
isCallExpression(node.expression) &&
4245
isMemberExpression(node.expression.callee) &&
4346
isIdentifier(node.expression.callee.object)
4447
) {
45-
const object: TSESTree.Identifier = node.expression.callee.object
46-
const identifierName: string = object.name
47-
return SIDE_EFFECTS.includes(identifierName)
48+
const object: TSESTree.Identifier = node.expression.callee.object;
49+
const identifierName: string = object.name;
50+
return SIDE_EFFECTS.includes(identifierName);
4851
} else {
49-
return false
52+
return false;
5053
}
51-
})
54+
});
5255

53-
if (isImportingTestingLibrary && isBlockStatement(node) && hasSideEffects(node.body)) {
56+
if (
57+
isImportingTestingLibrary &&
58+
isBlockStatement(node) &&
59+
hasSideEffects(node.body)
60+
) {
5461
context.report({
5562
node,
5663
loc: node.loc.start,
@@ -64,7 +71,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
6471
[`${WAIT_EXPRESSION_QUERY} > FunctionExpression > BlockStatement`]: reportSideEffects,
6572
ImportDeclaration(node: TSESTree.ImportDeclaration) {
6673
isImportingTestingLibrary = hasTestingLibraryImportModule(node);
67-
}
74+
},
6875
};
69-
}
70-
})
76+
},
77+
});

lib/rules/prefer-screen-queries.ts

Lines changed: 22 additions & 11 deletions
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)