UNPKG

1.94 kBJavaScriptView Raw
1'use strict';
2
3const { getDocsUrl } = require('./util');
4
5const ruleMsg =
6 'Every test should have either `expect.assertions(<number of assertions>)` or `expect.hasAssertions()` as its first expression';
7
8const validateArguments = expression => {
9 return (
10 expression.arguments &&
11 expression.arguments.length === 1 &&
12 Number.isInteger(expression.arguments[0].value)
13 );
14};
15
16const isExpectAssertionsOrHasAssertionsCall = expression => {
17 try {
18 const expectAssertionOrHasAssertionCall =
19 expression.type === 'CallExpression' &&
20 expression.callee.type === 'MemberExpression' &&
21 expression.callee.object.name === 'expect' &&
22 (expression.callee.property.name === 'assertions' ||
23 expression.callee.property.name === 'hasAssertions');
24
25 if (expression.callee.property.name === 'assertions') {
26 return expectAssertionOrHasAssertionCall && validateArguments(expression);
27 }
28 return expectAssertionOrHasAssertionCall;
29 } catch (e) {
30 return false;
31 }
32};
33
34const getFunctionFirstLine = functionBody => {
35 return functionBody[0] && functionBody[0].expression;
36};
37
38const isFirstLineExprStmt = functionBody => {
39 return functionBody[0] && functionBody[0].type === 'ExpressionStatement';
40};
41
42const reportMsg = (context, node) => {
43 context.report({
44 message: ruleMsg,
45 node,
46 });
47};
48
49module.exports = {
50 meta: {
51 docs: {
52 url: getDocsUrl(__filename),
53 },
54 },
55 create(context) {
56 return {
57 'CallExpression[callee.name=/^(it|test)$/][arguments.1.body.body]'(node) {
58 const testFuncBody = node.arguments[1].body.body;
59
60 if (!isFirstLineExprStmt(testFuncBody)) {
61 reportMsg(context, node);
62 } else {
63 const testFuncFirstLine = getFunctionFirstLine(testFuncBody);
64 if (!isExpectAssertionsOrHasAssertionsCall(testFuncFirstLine)) {
65 reportMsg(context, node);
66 }
67 }
68 },
69 };
70 },
71};