/
testhelper.js
160 lines (141 loc) · 4.95 KB
/
testhelper.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/**
* Helper for JSHint-tests.
* Export itself as function in setup.testhelper to
* prevent expresso to use it as test...
*
* Use it with method chaining, so you get something like
*
* var TestRun = require("./testhelper").setup.testRun;
*
* TestRun(test, name)
* .addError(line, errorMessage)
* .test(source, options);
*
* TestRun(test, name)
* test: nodeunit test object
* name: optional. name of the test run
* with a name, it's easier to identify a test run
*
* .addError(line, errorMessage)
* line: line of the error message
* errorMessage: the message of the reported error
*
* .test(source, options)
* starts the test run
* source: source of the test file
* options: optional. the options for jshint
*/
/*jshint node: true, eqnull: true*/
'use strict';
var JSHINT = require("../..").JSHINT;
if (exports.setup === undefined || exports.setup === null) {
exports.setup = {};
}
exports.setup.testRun = function (test, name) {
var definedErrors = [];
var helperObj = {
addError: function (line, message, extras) {
definedErrors.push({
line: line,
message: message,
extras: extras
});
return helperObj;
},
test: function (source, options, globals) {
var ret = !!JSHINT(source, options, globals);
var errors = JSHINT.errors;
if (errors.length === 0 && definedErrors.length === 0) {
return;
}
// filter all thrown errors
var undefinedErrors = errors.filter(function (er) {
return !definedErrors.some(function (def) {
var result = def.line === er.line &&
def.message === er.reason;
if (!result) {
return result;
}
if (def.extras) {
for (var extra in def.extras) {
if (def.extras.hasOwnProperty(extra) &&
er.hasOwnProperty(extra)) {
result = (def.extras[extra] === er[extra]);
if (!result) {
return result;
}
}
}
}
return result;
});
});
// filter all defined errors
var unthrownErrors = definedErrors.filter(function (def) {
return !errors.some(function (er) {
return def.line === er.line &&
def.message === er.reason;
});
});
// elements that only differs in line number
var wrongLineNumbers = undefinedErrors.map(function (er) {
var lines = unthrownErrors.filter(function (def) {
return def.line !== er.line &&
def.message === er.reason;
}).map(function (def) {
return def.line;
});
if (lines.length) {
return {
line: er.line,
message: er.reason,
definedIn: lines
};
}
return null;
}).filter(function (er) {
return !!er;
});
var duplicateErrors = errors.filter(function (er) {
return errors.filter(function (other) {
return er.line === other.line && er.character === other.character &&
er.reason === other.reason;
}).length > 1;
});
// remove undefined errors, if there is a definition with wrong line number
undefinedErrors = undefinedErrors.filter(function (er) {
return !wrongLineNumbers.some(function (def) {
return def.message === er.reason;
});
});
unthrownErrors = unthrownErrors.filter(function (er) {
return !wrongLineNumbers.some(function (def) {
return def.message === er.message;
});
});
test.ok(
undefinedErrors.length === 0
&& unthrownErrors.length === 0 && wrongLineNumbers.length === 0
&& duplicateErrors.length === 0,
(name === null ? "" : "\n TestRun: [bold]{" + name + "}") +
unthrownErrors.map(function (el, idx) {
return (idx === 0 ? "\n [yellow]{Errors defined, but not thrown by JSHINT}\n" : "") +
" [bold]{Line " + el.line + ", Char " + el.character + "} " + el.message;
}).join("\n") +
undefinedErrors.map(function (el, idx) {
return (idx === 0 ? "\n [yellow]{Errors thrown by JSHINT, but not defined in test run}\n" : "") +
" [bold]{Line " + el.line + ", Char " + el.character + "} " + el.reason;
}).join("\n") +
wrongLineNumbers.map(function (el, idx) {
return (idx === 0 ? "\n [yellow]{Errors with wrong line number}\n" : "") +
" [bold]{Line " + el.line + "} " + el.message + " [red]{not in line(s)} [bold]{" + el.definedIn.join(", ") + "}";
}).join("\n") +
duplicateErrors.map(function (el, idx) {
return (idx === 0 ? "\n [yellow]{Duplicated errors}\n": "") +
" [bold]{Line " + el.line + ", Char " + el.character + "} " + el.reason;
}).join("\n") + "\n"
);
}
};
return helperObj;
};