Commit 0e598374 0e5983746b8712b06cf7de06fce4709513b43d97 by Nicolas Perriault

merged PR #405

2 parents 82863faf b9351bc0
......@@ -1608,6 +1608,73 @@ Casper.prototype.thenOpen = function thenOpen(location, settings, then) {
};
/**
* Skip `nb` steps.
*
* @param Integer nb number of tests to skip
* @param String message message to display
*/
Casper.prototype.skip = function skip(nb, message) {
"use strict";
var step = this.step,
steps = this.steps,
last = steps.length;
this.checkStarted();
this.step = Math.min(step + nb, last);
return this;
};
/**
* Skip `nb` steps.
*
* @param Integer nb number of tests to skip
* @param String message message to display
*/
Casper.prototype.thenSkip = function (nb, message) {
return this.then(function () {
this.skip(nb, message);
});
};
/**
* Skip `nb` steps if condition is true.
*
* @param Mixed condition number of tests to skip
* @param Integer nb number of tests to skip
* @param String message message to display
*/
Casper.prototype.thenSkipIf = function (condition, nb, message) {
return this.then(function () {
if (utils.isFunction(condition)) {
condition = condition();
}
if (utils.isTruthy(condition)) {
this.skip(nb, message);
}
});
};
/**
* Skip `nb` steps if condition is true.
*
* @param Mixed condition number of tests to skip
* @param Integer nb number of tests to skip
* @param String message message to display
*/
Casper.prototype.thenSkipUnless = function (condition, nb, message) {
return this.then(function () {
if (utils.isFunction(condition)) {
condition = condition();
}
if (utils.isFalsy(condition)) {
this.skip(nb, message);
}
});
};
/**
* Adds a new navigation step for opening and evaluate an expression
* against the DOM retrieved from the provided location.
*
......
......@@ -66,7 +66,9 @@ var Colorizer = function Colorizer() {
'GREEN_BAR': { fg: 'white', bg: 'green', bold: true },
'RED_BAR': { fg: 'white', bg: 'red', bold: true },
'INFO_BAR': { bg: 'cyan', fg: 'white', bold: true },
'WARN_BAR': { bg: 'yellow', fg: 'white', bold: true }
'WARN_BAR': { bg: 'yellow', fg: 'white', bold: true },
'SKIP': { fg: 'magenta', bold: true },
'SKIP_BAR': { bg: 'magenta', fg: 'white', bold: true }
};
/**
......
......@@ -111,8 +111,9 @@ var Tester = function Tester(casper, options) {
this.options = utils.mergeObjects({
concise: false, // concise output?
failFast: false, // terminates a suite as soon as a test fails?
failText: "FAIL", // text to use for a succesful test
passText: "PASS", // text to use for a failed test
failText: "FAIL", // text to use for a failed test
passText: "PASS", // text to use for a succesful test
skipText: "SKIP", // text to use for a skipped test
pad: 80 , // maximum number of chars for a result line
warnText: "WARN" // text to use for a dubious test
}, options);
......@@ -127,6 +128,12 @@ var Tester = function Tester(casper, options) {
this.lastAssertTime = timeElapsed;
});
this.on('skipped', function onSkipped(skipped) {
var timeElapsed = new Date() - this.currentTestStartTime;
this.currentSuite.addSkipped(skipped, timeElapsed - this.lastAssertTime);
this.lastAssertTime = timeElapsed;
});
this.on('fail', function onFail(failure) {
// export
var valueKeys = Object.keys(failure.values),
......@@ -227,6 +234,27 @@ Tester.prototype.abort = function abort(message) {
};
/**
* Skip `nb` tests.
*
* @param Integer nb number of tests to skip
* @param String message message to display
*/
Tester.prototype.skip = function skip(nb, message) {
"use strict";
this.casper.skip(nb, message);
return this.processAssertionResult({
success: null,
standard: f("Skipping %d tests", nb),
message: message,
type: "skip",
number: nb,
skipped: true
});
};
/**
* Asserts that a condition strictly resolves to true. Also returns an
* "assertion object" containing useful informations about the test case
* results.
......@@ -1148,7 +1176,11 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result
message = result.message || result.standard,
style = 'INFO',
status = this.options.passText;
if (!result.success) {
if (null === result.success) {
eventName = 'skipped';
style = 'SKIP';
status = this.options.skipText;
}else if (!result.success) {
eventName = 'fail';
style = 'RED_BAR';
status = this.options.failText;
......@@ -1235,12 +1267,13 @@ Tester.prototype.renderFailureDetails = function renderFailureDetails() {
*/
Tester.prototype.renderResults = function renderResults(exit, status, save) {
"use strict";
/*jshint maxstatements:20*/
/*jshint maxstatements:25*/
save = save || this.options.save;
var dubious = this.suiteResults.countDubious(),
failed = this.suiteResults.countFailed(),
passed = this.suiteResults.countPassed(),
total = this.suiteResults.countExecuted(),
skipped = this.suiteResults.countSkipped(),
statusText,
style,
result,
......@@ -1253,17 +1286,21 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) {
if (failed > 0) {
statusText = this.options.failText;
style = 'RED_BAR';
} else if (skipped > 0) {
statusText = this.options.skipText;
style = 'SKIP_BAR';
} else {
statusText = this.options.passText;
style = 'GREEN_BAR';
}
result = f('%s %s tests executed in %ss, %d passed, %d failed%s.',
result = f('%s %s tests executed in %ss, %d passed, %d failed%s, %d skipped.',
statusText,
total,
utils.ms2seconds(this.suiteResults.calculateDuration()),
passed,
failed,
dubious ? f(' (%d dubious)', dubious) : '');
dubious ? f(' (%d dubious)', dubious) : '',
skipped);
}
this.casper.echo(result, style, this.options.pad);
if (failed > 0) {
......@@ -1494,6 +1531,20 @@ TestSuiteResult.prototype.countPassed = function countPassed() {
};
/**
* Returns the number of skipped tests.
*
* @return Number
*/
TestSuiteResult.prototype.countSkipped = function countSkipped() {
"use strict";
return this.map(function(result) {
return result.skipped;
}).reduce(function(a, b) {
return a + b;
}, 0);
};
/**
* Returns the number of warnings.
*
* @return Number
......@@ -1518,6 +1569,16 @@ TestSuiteResult.prototype.isFailed = function isFailed() {
};
/**
* Checks if the suite has skipped tests.
*
* @return Number
*/
TestSuiteResult.prototype.isSkipped = function isFailed() {
"use strict";
return this.countSkipped() > 0;
};
/**
* Returns all failures from this suite.
*
* @return Array
......@@ -1546,6 +1607,20 @@ TestSuiteResult.prototype.getAllPasses = function getAllPasses() {
};
/**
* Returns all skipped tests from this suite.
*
* @return Array
*/
TestSuiteResult.prototype.getAllSkipped = function getAllSkipped() {
"use strict";
var skipped = [];
this.forEach(function(result) {
skipped = skipped.concat(result.skipped);
});
return skipped;
};
/**
* Returns all results from this suite.
*
* @return Array
......@@ -1583,6 +1658,7 @@ function TestCaseResult(options) {
this.errors = [];
this.failures = [];
this.passes = [];
this.skip = [];
this.warnings = [];
this.config = options && options.config;
this.__defineGetter__("assertions", function() {
......@@ -1602,6 +1678,9 @@ function TestCaseResult(options) {
this.__defineGetter__("passed", function() {
return this.passes.length;
});
this.__defineGetter__("skipped", function() {
return this.skip.length;
});
}
exports.TestCaseResult = TestCaseResult;
......@@ -1643,6 +1722,20 @@ TestCaseResult.prototype.addSuccess = function addSuccess(success, time) {
};
/**
* Adds a success record and its execution time.
*
* @param Object success
* @param Number time
*/
TestCaseResult.prototype.addSkipped = function addSkipped(skipped, time) {
"use strict";
skipped.suite = this.name;
skipped.time = time;
this.skip.push(skipped);
};
/**
* Adds a warning record.
*
* @param Object warning
......
/*global casper*/
/*jshint strict:false*/
casper.test.begin('Skip tests', 1, function(test) {
casper.start('tests/site/index.html');
casper.
then(function () {
test.skip(1);
}).
then(function () {
test.fail("This test should be skipped.");
}).
then(function () {
test.pass("This test should be executed.");
});
casper.run(function() {
test.done();
});
});
casper.test.begin('Skip multiple', 1, function(test) {
casper.
then(function () {
test.skip(2);
}).
then(function () {
test.fail("This test should be skipped.");
}).
then(function () {
test.fail("This test should be skipped.");
}).
then(function () {
test.pass("This test should be executed.");
});
casper.run(function() {
test.done();
});
});
casper.test.begin('Skip more than there is', 0, function(test) {
casper.
then(function () {
test.skip(2);
});
casper.run(function() {
test.done();
});
});
casper.test.begin('Skip does not polluate next suite', 1, function(test) {
casper.
then(function () {
test.pass("This test should be executed.");
});
casper.run(function() {
test.done();
});
});
casper.test.begin('Casper.thenSkip', 1, function(test) {
casper.
thenSkip(1).
then(function () {
test.fail("This test should be skipped.");
}).
then(function () {
test.pass("This test should be executed.");
});
casper.run(function() {
test.done();
});
});
casper.test.begin('Casper.thenSkipIf', 3, function(test) {
casper.
thenSkipIf(true, 1, "Skip if with function").
then(function () {
test.fail("This test should be skipped.");
}).
then(function () {
test.pass("This test should be executed.");
}).
thenSkipIf(function () {
return true;
}, 1, "Skip if with function").
then(function () {
test.fail("This test should be skipped.");
}).
then(function () {
test.pass("This test should be executed.");
}).
thenSkipIf(function () {
return false;
}, 1, "Do not skip if with function").
then(function () {
test.pass("This test should be executed.");
});
casper.run(function() {
test.done();
});
});
casper.test.begin('Casper.thenSkipUnless', 3, function(test) {
casper.
thenSkipUnless(false, 1, "Skip unless with function").
then(function () {
test.fail("This test should be skipped.");
}).
then(function () {
test.pass("This test should be executed.");
}).
thenSkipUnless(function () {
return false;
}, 1, "Skip unless with function").
then(function () {
test.fail("This test should be skipped.");
}).
then(function () {
test.pass("This test should be executed.");
}).
thenSkipUnless(function () {
return true;
}, 1, "Do not skip unless with function").
then(function () {
test.pass("This test should be executed.");
});
casper.run(function() {
test.done();
});
});