UNPKG

2.65 kBJavaScriptView Raw
1'use strict';
2
3const isNil = require('ramda/src/isNil');
4const find = require('ramda/src/find');
5const astUtil = require('../util/ast');
6
7const asyncMethods = [ 'async', 'callback', 'promise' ];
8
9function hasAsyncCallback(functionExpression) {
10 return functionExpression.params.length === 1;
11}
12
13function isAsyncFunction(functionExpression) {
14 return functionExpression.async === true;
15}
16
17function findPromiseReturnStatement(nodes) {
18 return find(function (node) {
19 return node.type === 'ReturnStatement' && node.argument && node.argument.type !== 'Literal';
20 }, nodes);
21}
22
23function doesReturnPromise(functionExpression) {
24 const bodyStatement = functionExpression.body;
25 let returnStatement = null;
26
27 if (bodyStatement.type === 'BlockStatement') {
28 returnStatement = findPromiseReturnStatement(functionExpression.body.body);
29 } else if (bodyStatement.type !== 'Literal') {
30 // allow arrow statements calling a promise with implicit return.
31 returnStatement = bodyStatement;
32 }
33
34 return returnStatement !== null &&
35 typeof returnStatement !== 'undefined';
36}
37
38module.exports = function (context) {
39 const options = context.options[0] || {};
40 const allowedAsyncMethods = isNil(options.allowed) ? asyncMethods : options.allowed;
41
42 function check(node) {
43 if (astUtil.hasParentMochaFunctionCall(node)) {
44 // For each allowed async test method, check if it is used in the test
45 const testAsyncMethods = allowedAsyncMethods.map(function (method) {
46 switch (method) {
47 case 'async':
48 return isAsyncFunction(node);
49
50 case 'callback':
51 return hasAsyncCallback(node);
52
53 default:
54 return doesReturnPromise(node);
55 }
56 });
57
58 // Check that at least one allowed async test method is used in the test
59 const isAsyncTest = testAsyncMethods.some(function (value) {
60 return value === true;
61 });
62
63 if (!isAsyncTest) {
64 context.report(node, 'Unexpected synchronous test.');
65 }
66 }
67 }
68
69 return {
70 FunctionExpression: check,
71 ArrowFunctionExpression: check
72 };
73};
74
75module.exports.schema = [
76 {
77 type: 'object',
78 properties: {
79 allowed: {
80 type: 'array',
81 items: {
82 type: 'string',
83 enum: asyncMethods
84 },
85 minItems: 1,
86 uniqueItems: true
87 }
88 }
89 }
90];