| /** |
| * 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*/ |
| |
| var JSHINT = require('../../../src/stable/jshint.js').JSHINT; |
| |
| if (exports.setup === undefined || exports.setup === null) { |
| exports.setup = {}; |
| } |
| |
| exports.setup.testRun = function (test, name) { |
| var initCounter = 0, runCounter = 0, seq = 0, checked = [], 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.filter(function (er) { |
| return er && er.id === "(error)"; |
| }); |
| |
| 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; |
| }); |
| |
| // 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, |
| |
| (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") + "\n" |
| ); |
| } |
| }; |
| |
| return helperObj; |
| }; |