UNPKG

2.98 kBJavaScriptView Raw
1'use strict';
2
3const astUtils = require('../util/ast');
4const { additionalSuiteNames } = require('../util/settings');
5
6const FUNCTION = 1;
7const DESCRIBE = 2;
8// "Pure" nodes are hooks (like `beforeEach`) or `it` calls
9const PURE = 3;
10
11module.exports = function noSetupInDescribe(context) {
12 const nesting = [];
13 const settings = context.settings;
14
15 function isPureNode(node) {
16 return astUtils.isHookCall(node) ||
17 astUtils.isTestCase(node) ||
18 astUtils.isSuiteConfigCall(node);
19 }
20
21 function reportCallExpression(callExpression) {
22 const message = 'Unexpected function call in describe block.';
23
24 context.report({
25 message,
26 node: callExpression.callee
27 });
28 }
29
30 function reportMemberExpression(memberExpression) {
31 const message = 'Unexpected member expression in describe block. ' +
32 'Member expressions may call functions via getters.';
33
34 context.report({
35 message,
36 node: memberExpression
37 });
38 }
39
40 function isNestedInDescribeBlock() {
41 return nesting.length &&
42 nesting.indexOf(PURE) === -1 &&
43 nesting.lastIndexOf(FUNCTION) < nesting.lastIndexOf(DESCRIBE);
44 }
45
46 function handleCallExpressionInDescribe(node) {
47 if (isPureNode(node)) {
48 nesting.push(PURE);
49 } else if (isNestedInDescribeBlock()) {
50 reportCallExpression(node);
51 }
52 }
53
54 function isDescribe(node) {
55 return astUtils.isDescribe(node, additionalSuiteNames(settings));
56 }
57
58 function isParentDescribe(node) {
59 return isDescribe(node.parent);
60 }
61
62 return {
63 CallExpression(node) {
64 if (isDescribe(node)) {
65 nesting.push(DESCRIBE);
66 return;
67 }
68 // don't process anything else if the first describe hasn't been processed
69 if (!nesting.length) {
70 return;
71 }
72 handleCallExpressionInDescribe(node);
73 },
74
75 'CallExpression:exit'(node) {
76 if (isDescribe(node) || nesting.length && isPureNode(node)) {
77 nesting.pop();
78 }
79 },
80
81 MemberExpression(node) {
82 if (isNestedInDescribeBlock()) {
83 reportMemberExpression(node);
84 }
85 },
86
87 FunctionDeclaration() {
88 if (nesting.length) {
89 nesting.push(FUNCTION);
90 }
91 },
92 'FunctionDeclaration:exit'() {
93 if (nesting.length) {
94 nesting.pop();
95 }
96 },
97
98 ArrowFunctionExpression(node) {
99 if (nesting.length && !isParentDescribe(node)) {
100 nesting.push(FUNCTION);
101 }
102 },
103 'ArrowFunctionExpression:exit'(node) {
104 if (nesting.length && !isParentDescribe(node)) {
105 nesting.pop();
106 }
107 }
108 };
109};