Commit 3e41c7ba 3e41c7ba68f296cc009d2958448fde91068b02aa by Nicolas Perriault

Refactored tester module

Now all `assert*` methods returns an object containing informations about
the failure, if any.
1 parent f752b192
......@@ -83,30 +83,30 @@ var Tester = function Tester(casper, options) {
if (failure.details) {
this.comment(' details: ' + failure.details);
}
switch (failure.type) {
case 'assertEquals':
case 'assertEvalEquals':
this.comment(' got: ' + utils.serialize(failure.values.subject));
this.comment(' expected: ' + utils.serialize(failure.values.expected));
break;
case 'assertNotEquals':
this.comment(' got: ' + utils.serialize(failure.values.subject));
this.comment(' shouldnt: ' + utils.serialize(failure.values.shouldnt));
break;
if (failure.values && Object.keys(failure.values).length > 0) {
for (var name in failure.values) {
this.comment(' ' + name + ': ' + utils.serialize(failure.values[name]));
}
}
});
// methods
/**
* Asserts that a condition strictly resolves to true.
* Asserts that a condition strictly resolves to true. Also returns an
* "assertion object" containing useful informations about the test case
* results.
*
* This method is also used as the base one used for all other `assert*`
* family methods; supplementary informations are then passed using the
* `context` argument.
*
* @param Boolean subject The condition to test
* @param String message Test description
* @param Object|null context Assertion context object
* @param Object|null context Assertion context object (Optional)
* @return Object An assertion result object
*/
this.assert = this.assertTrue = function assert(subject, message, context) {
this.processAssertionResult(utils.mergeObjects({
return this.processAssertionResult(utils.mergeObjects({
success: subject === true,
type: "assert",
details: "Subject's not a strict boolean true",
......@@ -124,21 +124,17 @@ var Tester = function Tester(casper, options) {
* @param Mixed subject The value to test
* @param Mixed expected The expected value
* @param String message Test description (Optional)
* @param Object|null context Assertion context object (Optional)
* @return Object An assertion result object
*/
this.assertEquals = this.assertEqual = function assertEquals(subject, expected, message, context) {
return this.processAssertionResult(utils.mergeObjects({
success: this.testEquals(subject, expected),
this.assertEquals = this.assertEqual = function assertEquals(subject, expected, message) {
return this.assert(this.testEquals(subject, expected), message, {
type: "assertEquals",
details: "Subject didn't equal the expected value",
message: message,
file: this.currentTestFile,
values: {
subject: subject,
expected: expected
}
}, context || {}));
});
};
/**
......@@ -147,21 +143,17 @@ var Tester = function Tester(casper, options) {
* @param Mixed subject The value to test
* @param Mixed expected The unwanted value
* @param String|null message Test description (Optional)
* @param Object|null context Assertion context object (Optional)
* @return Object An assertion result object
*/
this.assertNotEquals = function assertNotEquals(subject, shouldnt, message, context) {
return this.processAssertionResult(utils.mergeObjects({
success: !this.testEquals(subject, shouldnt),
this.assertNotEquals = function assertNotEquals(subject, shouldnt, message) {
return this.assert(!this.testEquals(subject, shouldnt), message, {
type: "assertNotEquals",
details: "Subject actually equals to what it shouldn't be",
message: message,
file: this.currentTestFile,
values: {
subject: subject,
shouldnt: shouldnt
}
}, context || {}));
});
};
/**
......@@ -175,7 +167,11 @@ var Tester = function Tester(casper, options) {
this.assertEval = this.assertEvaluate = function assertEval(fn, message, params) {
return this.assert(casper.evaluate(fn, params), message, {
type: "assertEval",
details: "Function didn't evaluate to true"
details: "Function didn't evaluate to true",
values: {
fn: fn,
params: params
}
});
};
......@@ -191,10 +187,12 @@ var Tester = function Tester(casper, options) {
*/
this.assertEvalEquals = this.assertEvalEqual = function assertEvalEquals(fn, expected, message, params) {
var subject = casper.evaluate(fn, params);
return this.assertEquals(subject, expected, message, {
return this.assert(this.testEquals(subject, expected), message, {
type: "assertEvalEquals",
details: "Evaluated function didn't return the expected value",
values: {
fn: fn,
params: params,
subject: subject,
expected: expected
}
......@@ -209,7 +207,7 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this.assertExists = this.assertExist = function assertExists(selector, message) {
this.assertExists = this.assertExist = this.assertSelectorExists = this.assertSelectorExist = function assertExists(selector, message) {
return this.assert(casper.exists(selector), message, {
type: "assertExists",
details: f("No element matching selector %s was found", selector),
......@@ -228,7 +226,7 @@ var Tester = function Tester(casper, options) {
* @return Object An assertion result object
*/
this.assertDoesntExist = this.assertNotExists = function assertDoesntExist(selector, message) {
return this.assertNot(casper.exists(selector), message, {
return this.assert(!casper.exists(selector), message, {
type: "assertDoesntExist",
details: f("At least one element matching selector %s was found", selector),
values: {
......@@ -246,9 +244,9 @@ var Tester = function Tester(casper, options) {
*/
this.assertHttpStatus = function assertHttpStatus(status, message) {
var currentHTTPStatus = casper.currentHTTPStatus;
return this.assertEquals(casper.currentHTTPStatus, status, message, {
return this.assert(this.testEquals(casper.currentHTTPStatus, status), message, {
type: "assertHttpStatus",
details: f("HTTP status code is not %d, but %d", status, currentHTTPStatus),
details: f("HTTP status code is not %s, but %s", status, currentHTTPStatus),
values: {
current: currentHTTPStatus,
expected: status
......@@ -301,16 +299,16 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this.assertRaises = this.assertRaise = this.assertThrow = this.assertThrows = function assertRaises(fn, args, message) {
this.assertRaises = this.assertRaise = this.assertThrows = function assertRaises(fn, args, message) {
var context = {
type: "assertRaises",
details: "Function didn't raise any error"
};
try {
fn.apply(null, args);
this.fail(message, context);
this.assert(false, message, context);
} catch (error) {
this.pass(message, utils.mergeObjects(context, {
this.assert(true, message, utils.mergeObjects(context, {
values: {
error: error
}
......@@ -336,24 +334,6 @@ var Tester = function Tester(casper, options) {
};
/**
* Asserts that at least an element matching the provided selector expression
* exists in remote DOM.
*
* @param String selector A selector expression string
* @param String message Test description
* @return Object An assertion result object
*/
this.assertSelectorExists = this.assertSelectorExist = function assertSelectorExists(selector, message) {
return this.assert(casper.exists(selector), message, {
type: "assertSelectorExists",
details: f("No element matching selector %s was found", selector),
values: {
selector: selector
}
});
};
/**
* Asserts that given text exits in the document body.
*
* @param String text Text to be found
......@@ -382,31 +362,31 @@ var Tester = function Tester(casper, options) {
*/
this.assertTitle = function assertTitle(expected, message) {
var currentTitle = casper.getTitle();
return this.assertEquals(casper.getTitle(), expected, message, {
return this.assert(this.testEquals(currentTitle, expected), message, {
type: "assertTitle",
details: f("Page title is not %s", expected),
details: "Page title is not the one expected",
values: {
expected: expected,
current: currentTitle
subject: currentTitle,
expected: expected
}
});
};
/**
* Asserts that the provided input is of the given type.
* Asserts that the provided subject is of the given type.
*
* @param mixed input The value to test
* @param mixed subject The value to test
* @param String type The javascript type name
* @param String message Test description
* @return Object An assertion result object
*/
this.assertType = function assertType(input, type, message) {
var actual = utils.betterTypeOf(input);
return this.assertEquals(actual, type, message, {
this.assertType = function assertType(subject, type, message) {
var actual = utils.betterTypeOf(subject);
return this.assert(this.testEquals(actual, type), message, {
type: "assertType",
details: f("Expected type %s, got %s", typeof input, actual),
details: f("Expected type %s, got %s", typeof subject, actual),
values: {
input: input,
subject: subject,
type: type,
actual: actual
}
......@@ -423,7 +403,7 @@ var Tester = function Tester(casper, options) {
*/
this.assertUrlMatch = this.assertUrlMatches = function assertUrlMatch(pattern, message) {
var currentUrl = casper.getCurrentUrl();
return this.assertMatch(currentUrl, pattern, message, {
return this.assert(pattern.test(currentUrl), message, {
type: "assertUrlMatch",
details: "Current url did not match the provided pattern",
values: {
......@@ -504,14 +484,11 @@ var Tester = function Tester(casper, options) {
*
* @param String message
*/
this.fail = function fail(message, context) {
return this.processAssertionResult(utils.mergeObjects({
success: false,
this.fail = function fail(message) {
return this.assert(false, message, {
type: "fail",
details: "explicit call to fail()",
message: message,
file: this.currentTestFile
}, context || {}));
details: "explicit call to fail()"
});
};
/**
......@@ -567,14 +544,11 @@ var Tester = function Tester(casper, options) {
*
* @param String message
*/
this.pass = function pass(message, context) {
this.processAssertionResult(utils.mergeObjects({
success: true,
this.pass = function pass(message) {
return this.assert(true, message, {
type: "pass",
details: "explicit call to pass()",
message: message,
file: this.currentTestFile
}, context || {}));
details: "explicit call to pass()"
});
};
/**
......@@ -752,7 +726,7 @@ var Tester = function Tester(casper, options) {
* @param String file Test file where the error occured
*/
this.uncaughtError = function uncaughtError(error, file) {
this.processAssertionResult({
return this.processAssertionResult({
success: false,
type: "uncaughtError",
file: this.currentTestFile,
......
......@@ -2,6 +2,8 @@ var fs = require('fs');
var t = casper.test;
casper.start();
t.comment('Tester.testEquals()');
t.assert(t.testEquals(null, null), 'Tester.testEquals() null equality');
t.assertNot(t.testEquals(null, undefined), 'Tester.testEquals() null vs. undefined inequality');
......@@ -26,8 +28,6 @@ t.assertNot(t.testEquals({1:{name:"bob",age:28}, 2:{name:"john",age:26}}, {1:{na
t.assert(t.testEquals(function(x){return x;}, function(x){return x;}), 'Tester.testEquals() function equality');
t.assertNot(t.testEquals(function(x){return x;}, function(y){return y+2;}), 'Tester.testEquals() function inequality');
t.assertNotEquals(42, 43, 'Tester.assertNotEquals() works as expected');
t.comment('Tester.sortFiles()');
var testDirRoot = fs.pathJoin(phantom.casperPath, 'tests', 'testdir');
var files = t.findTestFiles(testDirRoot);
......@@ -44,11 +44,65 @@ var expected = [
});
t.assertEquals(files, expected, 'findTestFiles() find test files and sort them');
t.comment('Tester.assertTextExists()');
casper.start('tests/site/index.html', function() {
casper.thenOpen('tests/site/index.html', function() {
t.comment('Tester.assertTextExists()');
t.assertTextExists('form', 'Tester.assertTextExists() checks that page body contains text');
});
casper.then(function() {
t.comment('Tester.assert()');
t.assert(true, 'Tester.assert() works as expected');
t.comment('Tester.assertNot()');
t.assertNot(false, 'Tester.assertNot() works as expected');
t.comment('Tester.assertEquals()');
t.assertEquals(true, true, 'Tester.assertEquals() works as expected');
t.comment('Tester.assertNotEquals()');
t.assertNotEquals(true, false, 'Tester.assertNotEquals() works as expected');
t.comment('Tester.assertEval()');
t.assertEval(function() {
return true;
}, 'Tester.assertEval() works as expected');
t.comment('Tester.assertEvalEquals()');
t.assertEvalEquals(function() {
return 42;
}, 42, 'Tester.assertEvalEquals() works as expected');
t.comment('Tester.assertExists()');
t.assertExists('body', 'Tester.assertExists() works as expected');
t.comment('Tester.assertDoesntExist()');
t.assertDoesntExist('foobar', 'Tester.assertDoesntExist() works as expected');
t.comment('Tester.assertHttpStatus()');
// using file:// protocol, HTTP status is always null
t.assertHttpStatus(null, 'Tester.assertHttpStatus() works as expected');
t.comment('Tester.assertMatch()');
t.assertMatch("the lazy dog", /lazy/, 'Tester.assertMatch() works as expected');
t.comment('Tester.assertRaises()');
t.assertRaises(function() {
throw new Error('plop');
}, [], 'Tester.assertRaises() works as expected');
t.comment('Tester.assertResourceExists()');
t.assertResourceExists(/index\.html/, 'Tester.assertResourceExists() works as expected');
t.comment('Tester.assertTitle()');
t.assertTitle('CasperJS test index', 'Tester.assertTitle() works as expected');
t.comment('Tester.assertType()');
t.assertType("plop", "string", "Tester.assertType() works as expected");
t.comment('Tester.assertUrlMatch()');
t.assertUrlMatch(/index\.html$/, "Tester.assertUrlMatch() works as expected");
});
casper.run(function() {
t.done();
});
......