diff --git a/examples/tests/htmlTests.js b/examples/tests/htmlTests.js
index 4e4730c..f2344f4 100644
--- a/examples/tests/htmlTests.js
+++ b/examples/tests/htmlTests.js
@@ -4,8 +4,8 @@ exports.tests = {
"Common HTML Tests" : {
urlPattern: "\.html$",
tests: {
- "All HTML responses should have a statusCode of 200": function(response) {
- "200".should.equal(response.statusCode)
+ "All HTML responses should have a statusCode of 200": function(spiderPayload) {
+ should.equal(spiderPayload.response.statusCode, 200)
}
}
}
diff --git a/lib/reporters/console.js b/lib/reporters/console.js
new file mode 100644
index 0000000..689b317
--- /dev/null
+++ b/lib/reporters/console.js
@@ -0,0 +1,116 @@
+var exceptions = require("exceptions");
+var formatErrors = require("formaterrors");
+var failTheme = new formatErrors.StackTheme();
+failTheme.messageLineHighlights = [" "];
+failTheme.stackHighlights = [" "];
+failTheme.stackHighlightPatterns = ["at"];
+
+var errorTheme = new formatErrors.StackTheme();
+errorTheme.messageLineHighlights = [" "];
+errorTheme.stackHighlights = [" "];
+errorTheme.stackHighlightPatterns = ["at"];
+
+// todo consider making these options configurable as implied by the name
+var options = {
+ "error_prefix": "\u001B[31m",
+ "error_suffix": "\u001B[39m",
+ "ok_prefix": "\u001B[32m",
+ "ok_suffix": "\u001B[39m",
+ "bold_prefix": "\u001B[1m",
+ "bold_suffix": "\u001B[22m",
+ "assertion_prefix": "\u001B[35m",
+ "assertion_suffix": "\u001B[39m"
+};
+
+exports.report = function(suites, Result) {
+
+ var error = function (str) {
+ return options.error_prefix + str + options.error_suffix;
+ };
+ var ok = function (str) {
+ return options.ok_prefix + str + options.ok_suffix;
+ };
+ var bold = function (str) {
+ return options.bold_prefix + str + options.bold_suffix;
+ };
+ var assertionMessage = function (str) {
+ return options.assertion_prefix + str + options.assertion_suffix;
+ };
+
+ var totalTests = 0;
+ var totalSuccess = 0;
+ var totalFailed = 0;
+ var totalErrors = 0;
+
+ for (var suiteName in suites) {
+ if (suites.hasOwnProperty(suiteName)) {
+ var suite = suites[suiteName];
+ var output = "\n" + suite.getName();
+ if (suite.getDescription()) {
+ output += " - " + suite.getDescription();
+ }
+ console.log(bold(output));
+ var topics = suite.getTopics();
+ for (var topicName in topics) {
+ if (topics.hasOwnProperty(topicName)) {
+ var topic = topics[topicName];
+ output = topic.getName();
+ if (topic.getDescription()) {
+ output += " - " + topic.getDescription();
+ }
+ if (topic.getResult() === Result.PASS) {
+ console.log(ok(bold('✔ ' + output)));
+ }
+ if (topic.getResult() === Result.FAIL) {
+ console.log(error(bold('✖ ' + output)));
+ }
+ if (topic.getResult() === Result.ERROR) {
+ console.log(error(bold('\u274e ' + output)));
+ }
+ if (topic.getResult() === Result.NO_TESTS) {
+ console.log(error(bold('? ' + output + " (NO TESTS FOUND)")));
+ }
+
+ var testResults = topic.getTestResults();
+ for (var i = 0; i < testResults.length; i += 1) {
+ var testResult = testResults[i];
+ if (testResult.getResult() === Result.PASS) {
+ console.log(' ✔ ' + testResult.getName());
+ } else if (testResult.getResult() === Result.FAIL) {
+ failTheme.stackFilters = [testResult.getTestFile()];
+ var failError = formatErrors.highlightError(testResult.getError(), failTheme);
+ console.log(' ✖ ' + testResult.getName());
+ console.log(failError.stack);
+// console.log(ae.stack + '\n');
+ } else if (testResult.getResult() === Result.ERROR) {
+ var formattedError = formatErrors.highlightError(testResult.getError(), errorTheme);
+ console.log(" \u274e " + testResult.getName() + '\n');
+ console.log(formattedError.stack);
+ } else {
+ exceptions.ILLEGAL_STATE.thro("Unknown test result: " + testResult);
+ }
+ var detail = testResults[i].getName() + ": " + testResults[i].getResult();
+ if (testResults[i].getError() !== null) {
+ detail += " - " + testResults[i].getError();
+ }
+ }
+ }
+ }
+
+ totalTests += suite.getTestCount();
+ totalSuccess += suite.getSuccessCount();
+ totalFailed += suite.getFailedCount();
+ totalErrors += suite.getErrorCount();
+ }
+ }
+
+
+ var summary = "\nTests: " + totalTests + ", Passed: " + totalSuccess +
+ ", Failed: " + totalFailed + ", Errors: " + totalErrors;
+
+ if (totalFailed === 0 && totalErrors === 0) {
+ console.log(bold(ok(summary)));
+ } else {
+ console.log(bold(error(summary)));
+ }
+}
\ No newline at end of file
diff --git a/lib/spiderTest.js b/lib/spiderTest.js
index e0d8df8..2bea6e5 100644
--- a/lib/spiderTest.js
+++ b/lib/spiderTest.js
@@ -1,11 +1,12 @@
var fs = require("fs");
var spider = require("./spider");
var spiderOptions = require("./spiderOptions");
+var suiteManager = require("./suiteManager");
var timers = require("timers");
var urlModule = require("url");
var util = require("util");
-var SPIDER_COMPLETED_TIMEOUT = 1500; // todo make configurable
+var SPIDER_COMPLETED_TIMEOUT = 1000; // todo make configurable
var timeout;
var autoSpiderAll = spider({
@@ -16,14 +17,20 @@ var autoSpiderAll = spider({
/**
* Run spider tests.
- * @param startUrl
- * @param testsDir
+ *
+ * @param startUrl the initial url from which to start spidering
+ * @param testsDir directory containing the test definitions - this should be absolute unless baseDir
+ * is also specifed
+ * @param {Function} callback optional callback function invoked when all tests are completed
* @param {String} baseDir optional working dir to change to if specified. If testsDir is relative then it is
* relative to this dir.
*/
-exports.runTests = function (startUrl, testsDir, baseDir) {
+exports.runTests = function (startUrl, testsDir, callback, baseDir) {
+
+ var origDir;
if(baseDir) {
+ origDir = process.cwd();
process.chdir(baseDir);
}
startUrl = resolveUrl(startUrl);
@@ -32,8 +39,13 @@ exports.runTests = function (startUrl, testsDir, baseDir) {
// todo handle case where there are no tests
var done = function() {
- if(base)
- console.log("DONE!!!");
+ if(origDir) {
+ process.chdir(origDir);
+ }
+ suiteManager.generateReport("console");
+ if(callback) {
+ callback();
+ }
};
// :-( cannot think of another to know when all the URLs have been spidered except to timeout
@@ -67,12 +79,35 @@ var executeMatchingTests = function (payload, $, testFiles) {
var tests = require(testFile).tests;
for (var topic in tests) {
if (tests.hasOwnProperty(topic)) {
- console.log(testFile + ": " + topic);
+// console.log(testFile + ": " + topic);
+ var topicName = topic;
+ topic = tests[topic];
+ var requestHref = payload.spider.currentUrl;
+ if(requestHref.match(topic.urlPattern)) {
+// console.log("matched " + requestHref + " with " + topic.urlPattern);
+ var topicTests = topic.tests;
+ for(var topicTest in topicTests) {
+ if(topicTests.hasOwnProperty(topicTest)) {
+ var testName = topicTest;
+ topicTest = topicTests[topicTest];
+ var testDetails = {
+ testName: testName,
+ topicName: topicName,
+ suiteName: requestHref,
+ test: topicTest,
+ testFile: testFile,
+ spiderPayload: payload,
+ $: $
+ };
+ suiteManager.runSuiteTest(testDetails);
+ }
+ }
+ }
}
}
});
- console.log(util.inspect(payload));
+// console.log(util.inspect(payload));
};
diff --git a/lib/suiteManager.js b/lib/suiteManager.js
index 9659a91..7c26475 100644
--- a/lib/suiteManager.js
+++ b/lib/suiteManager.js
@@ -92,8 +92,8 @@ var createSuite = function (name, description) {
function topicCountTotal(countFunction) {
var count = 0;
- for(var topic in topics) {
- if(topics.hasOwnProperty(topic)) {
+ for (var topic in topics) {
+ if (topics.hasOwnProperty(topic)) {
count += topics[topic][countFunction]();
}
}
@@ -144,7 +144,7 @@ var createSuite = function (name, description) {
var TestResult = function () {
};
-var createTestResult = function (name, result, error) {
+var createTestResult = function (name, result, error, testFile) {
if (result === Result.PASS && error) {
exceptions.ILLEGAL_ARGUMENT.thro("There should be no error when the test result is a PASS");
@@ -164,6 +164,10 @@ var createTestResult = function (name, result, error) {
return error;
};
+ o.getTestFile = function () {
+ return testFile;
+ };
+
return o;
};
@@ -173,155 +177,41 @@ var createNewSuite = function(name, description) {
return suite;
};
-var runSuiteTest = function (testName, topicName, suiteName, test) {
+var runSuiteTest = function (testDetails) {
var success = false;
- var suite = suites[suiteName];
+ var suite = suites[testDetails.suiteName];
if (!suite) {
- suite = createNewSuite(suiteName);
+ suite = createNewSuite(testDetails.suiteName);
}
- var topic = suite.getTopic(topicName);
+ var topic = suite.getTopic(testDetails.topicName);
if (!topic) {
- topic = createTopic(topicName);
+ topic = createTopic(testDetails.topicName);
suite.addTopic(topic);
}
try {
- success = test();
- topic.addTestResult(createTestResult(testName, Result.PASS));
+ success = testDetails.test(testDetails.spiderPayload, testDetails.$);
+ topic.addTestResult(createTestResult(testDetails.testName, Result.PASS, null, testDetails.testFile));
} catch (error) {
+ console.log("Caught error: " + error.name);
if (error.name === "AssertionError") {
- topic.addTestResult(createTestResult(testName, Result.FAIL, error));
+ topic.addTestResult(createTestResult(testDetails.testName, Result.FAIL, error, testDetails.testFile));
} else {
- topic.addTestResult(createTestResult(testName, Result.ERROR, error));
+ topic.addTestResult(createTestResult(testDetails.testName, Result.ERROR, error, testDetails.testFile));
}
}
};
-exports.Suite = Suite;
-exports.Result = Result;
-exports.createTestResult = createTestResult;
-exports.createSuite = createSuite;
exports.runSuiteTest = runSuiteTest;
-
exports.generateReport = function (reporter) {
- switch (reporter) {
- case "junit":
- generateJunitReport();
- break;
- case "console":
- generateDefaultReport();
- break;
- default:
- generateDefaultReport();
+ reporter = reporter || "console";
+ if (reporter.indexOf("/") === -1) {
+ reporter = "./reporters/" + reporter;
}
-
- return totalFailed;
+ reporter = require(reporter);
+ reporter.report(suites, Result);
};
-var options = {
- "error_prefix": "\u001B[31m",
- "error_suffix": "\u001B[39m",
- "ok_prefix": "\u001B[32m",
- "ok_suffix": "\u001B[39m",
- "bold_prefix": "\u001B[1m",
- "bold_suffix": "\u001B[22m",
- "assertion_prefix": "\u001B[35m",
- "assertion_suffix": "\u001B[39m"
-};
-
-function generateDefaultReport() {
-
- var error = function (str) {
- return options.error_prefix + str + options.error_suffix;
- };
- var ok = function (str) {
- return options.ok_prefix + str + options.ok_suffix;
- };
- var bold = function (str) {
- return options.bold_prefix + str + options.bold_suffix;
- };
- var assertion_message = function (str) {
- return options.assertion_prefix + str + options.assertion_suffix;
- };
-
- var totalTests = 0;
- var totalSuccess = 0;
- var totalFailed = 0;
- var totalErrors = 0;
-
- for (var suiteName in suites) {
- if (suites.hasOwnProperty(suiteName)) {
- var suite = suites[suiteName];
- var output = suite.getName();
- if (suite.getDescription()) {
- output += " - " + suite.getDescription();
- }
- console.log(bold(output));
- var topics = suite.getTopics();
- for (var topicName in topics) {
- if (topics.hasOwnProperty(topicName)) {
- var topic = topics[topicName];
- output = suite.getName();
- if (suite.getDescription()) {
- output += " - " + suite.getDescription();
- }
- if (topic.getResult() === Result.PASS) {
- console.log(ok(bold('✔ ' + output)));
- }
- if (topic.getResult() === Result.FAIL) {
- console.log(ok(bold('✖ ' + output)));
- }
- if (topic.getResult() === Result.ERROR) {
- console.log(ok(bold('\u274e ' + output)));
- }
- if (topic.getResult() === Result.NO_TESTS) {
- console.log(ok(bold('? ' + output + " (NO TESTS FOUND)")));
- }
-
- var testResults = topic.getTestResults();
- for (var i = 0; i < testResults.length; i += 1) {
- var testResult = testResults[i];
- if (testResult.getResult() === Result.PASS) {
- console.log(ok(' ✔ ' + testResult.getName()));
- }
- if (testResult.getResult() === Result.FAIL) {
- var ae = formatAssertionError(testResult.getError());
- console.log(error(' ✖ ' + testResult.getName() + ": " + assertion_message(ae.message)));
-// console.log(ae.stack + '\n');
- }
- if (testResult.getResult() === Result.ERROR) {
- console.log(error(" \u274e " + testResult.getName()) + '\n');
- console.log(testResult.getError());
- }
- var detail = testResults[i].getName() + ": " + testResults[i].getResult();
- if (testResults[i].getError() !== null) {
- detail += " - " + testResults[i].getError();
- }
- }
- }
- }
-
- totalTests += suite.getTestCount();
- totalSuccess += suite.getSuccessCount();
- totalFailed += suite.getFailedCount();
- totalErrors += suite.getErrorCount();
- }
- }
-
-
- var summary = "Tests: " + totalTests + ", Passed: " + totalSuccess +
- ", Failed: " + totalFailed + ", Errors: " + totalErrors;
-
- if (totalFailed === 0 && totalErrors === 0) {
- console.log(bold(ok(summary)));
- } else {
- console.log(bold(error(summary)));
- }
-}
-
-function generateJunitReport() {
-
-}
function formatAssertionError(e) {
diff --git a/package.json b/package.json
index 9289c60..3b0916a 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
},
"dependencies" : {
"exceptions" : "0.1.1",
+ "formaterrors" : "0.1.1",
"request" : ">= 2.2.9",
"routes" : ">= 0.1.0",
"cheerio": ">= 0.3.2"
diff --git a/test/testSpiderTest.js b/test/testSpiderTest.js
index 86d9d2c..cbc926c 100644
--- a/test/testSpiderTest.js
+++ b/test/testSpiderTest.js
@@ -5,17 +5,6 @@ var should = require("should");
var spiderTestModule = loadModule("./lib/spiderTest.js");
var spiderTest = require("../lib/spiderTest");
-var server = express.createServer();
-
-server.configure(function() {
-// server.use(express.logger());
- server.use(server.router);
- server.use(express["static"]("test/resources"));
-});
-
-server.listen();
-serverPort = server.address().port;
-
exports.testResolveUrl = function (test) {
var url = spiderTestModule.resolveUrl("http://nodejs.org");
"http:".should.equal(url.protocol);
@@ -24,7 +13,7 @@ exports.testResolveUrl = function (test) {
"/".should.equal(url.path);
"nodejs.org:80".should.equal(url.host);
"http://nodejs.org:80/".should.equal(url.href);
-
+
url = spiderTestModule.resolveUrl("hello");
"http:".should.equal(url.protocol);
@@ -39,7 +28,7 @@ exports.testResolveUrl = function (test) {
"80".should.equal(url.port);
"localhost:80".should.equal(url.host);
"http://localhost:80/".should.equal(url.href);
-
+
test.done();
};
@@ -54,8 +43,22 @@ exports.testPopulateTestFiles = function (test) {
};
exports.testRunTests = function (test) {
+ var server = express.createServer();
+
+ server.configure(function() {
+// server.use(express.logger());
+ server.use(server.router);
+ server.use(express["static"]("test/resources"));
+ });
+
+ server.listen();
+ var serverPort = server.address().port;
+
// For some reason "process" is not available inside modules that are tested by nodeunit
// this is why process is used here to establish the test directory
- spiderTest.runTests("http://localhost:" + serverPort + "/testIndex.html", process.cwd() + "/" + "examples/tests");
- test.done();
+ spiderTest.runTests("http://localhost:" + serverPort + "/testIndex.html",
+ process.cwd() + "/" + "examples/tests", function() {
+ server.close();
+ test.done();
+ });
};
\ No newline at end of file
diff --git a/test/testSuiteManager.js b/test/testSuiteManager.js
index 957e946..8dd14fa 100644
--- a/test/testSuiteManager.js
+++ b/test/testSuiteManager.js
@@ -4,11 +4,11 @@ var should = require("should");
var suiteManagerModule = loadModule("./lib/suiteManager.js");
var suiteManager = suiteManagerModule.module.exports;
-var Suite = suiteManager.Suite;
-var Result = suiteManager.Result;
+var Suite = suiteManagerModule.Suite;
+var Result = suiteManagerModule.Result;
exports.testCreateTestResult = function (test) {
- var testResult = suiteManager.createTestResult("testName", Result.PASS);
+ var testResult = suiteManagerModule.createTestResult("testName", Result.PASS);
should.exist(testResult);
should.equal("testName", testResult.getName());
should.equal(Result.PASS, testResult.getResult());
@@ -16,11 +16,11 @@ exports.testCreateTestResult = function (test) {
};
exports.testCreateSuite = function (test) {
- var suite = suiteManager.createSuite("suitename");
+ var suite = suiteManagerModule.createSuite("suitename");
should.exist(suite);
should.ok(suite instanceof Suite);
should.equal("suitename", suite.getName());
- suite = suiteManager.createSuite("suitename", "description");
+ suite = suiteManagerModule.createSuite("suitename", "description");
should.exist(suite);
should.equal("suitename", suite.getName());
should.equal("description", suite.getDescription());
@@ -36,7 +36,13 @@ exports.testRunSuiteTest = function (test) {
var test1 = function () {
};
- suiteManager.runSuiteTest("Test1", "Topic1", "Suite1", test1);
+ var testDetails = {
+ testName: "Test1",
+ topicName: "Topic1",
+ suiteName: "Suite1",
+ test: test1
+ };
+ suiteManager.runSuiteTest(testDetails);
var suites = suiteManagerModule.suites;
should.exist(suites.Suite1);
@@ -46,14 +52,14 @@ exports.testRunSuiteTest = function (test) {
results.length.should.equal(1);
results[0].getName().should.equal("Test1");
- results[0].getResult().should.equal(suiteManager.Result.PASS);
+ results[0].getResult().should.equal(suiteManagerModule.Result.PASS);
topic.getName().should.equal("Topic1");
topic.getTestCount().should.equal(1);
topic.getSuccessCount().should.equal(1);
topic.getFailedCount().should.equal(0);
topic.getErrorCount().should.equal(0);
- topic.getResult().should.equal(suiteManager.Result.PASS);
+ topic.getResult().should.equal(suiteManagerModule.Result.PASS);
suites.Suite1.getName().should.equal("Suite1");
suites.Suite1.getTestCount().should.equal(1);