-
Notifications
You must be signed in to change notification settings - Fork 3
/
throws-helper.js
69 lines (60 loc) · 1.8 KB
/
throws-helper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
module.exports = babelCore => {
const t = babelCore.types;
const wrapArg = babelCore.template('(START(t, ASSERTION, FILE, LINE), END(t, ARG))');
const helpers = babelCore.template(`function START(t, assertion, file, line) {
if (t._throwsArgStart) {
t._throwsArgStart(assertion, file, line);
}
}
function END(t, arg) {
if (t._throwsArgEnd) {
t._throwsArgEnd();
}
return arg;
}`);
const assertionVisitor = {
CallExpression(path, state) {
const callee = path.get('callee');
if (!callee.isMemberExpression() || !callee.get('object').isIdentifier({name: 't'}) || !callee.get('property').isIdentifier()) {
return;
}
const assertion = callee.get('property').get('name').node;
if (assertion !== 'throws' && assertion !== 'notThrows') {
return;
}
const [arg0] = path.node.arguments;
if (!(arg0 && arg0.loc && (typeof arg0.start === 'number') && (typeof arg0.end === 'number'))) {
return;
}
// Wrap the argument expression, so that the stack trace of the assertion
// isn't affected.
path.node.arguments[0] = wrapArg({
ARG: arg0,
ASSERTION: t.stringLiteral(assertion),
FILE: t.stringLiteral(state.file.opts.filename),
LINE: t.numericLiteral(arg0.loc.start.line),
...this.installHelper()
}).expression;
}
};
return {
visitor: {
Program(path, state) {
const START = t.identifier(path.scope.generateUid('avaThrowsHelperStart'));
const END = t.identifier(path.scope.generateUid('avaThrowsHelperEnd'));
const helperIdentifiers = {START, END};
let created = false;
path.traverse(assertionVisitor, {
installHelper() {
if (!created) {
created = true;
path.unshiftContainer('body', helpers(helperIdentifiers));
}
return helperIdentifiers;
},
file: state.file
});
}
}
};
};