forked from uxsolutions/bootstrap-datepicker
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add phantomjs support to unit tests (CLI-capable!)
- Loading branch information
1 parent
619a0c2
commit e4128ee
Showing
4 changed files
with
144 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
Unit tests, written with [QUnit](http://docs.jquery.com/QUnit), are used to | ||
expose bugs for squashing, prevent bugs from respawning, and suppress new | ||
bugs when adding new features and making changes. | ||
|
||
# Running the tests | ||
|
||
The simplest way to run the tests is to open `tests/tests.html` in your browser. | ||
The test suites will automatically run themselves and present their results. | ||
|
||
To run the tests from the command line, download and install | ||
[PhantomJS](http://phantomjs.org/), and run `run-qunit.js` with it: | ||
|
||
$ cd tests/ | ||
$ phantomjs run-qunit.js tests.html | ||
|
||
Failed tests and their failed assertions will be printed to the console. A | ||
results summary will be printed at the end. | ||
|
||
# Shout-out | ||
|
||
Thanks to Rod @ While One Fork for the | ||
[CIS guide](http://whileonefork.blogspot.com/2011/10/integrating-javascript-tests-into-cli.html) | ||
on putting the above together. | ||
|
||
# Adding tests | ||
|
||
Tests go in js files in the `tests/suites/` directory tree. QUnit organizes | ||
tests into suites called "modules"; there is one module per js file. If the | ||
tests you are adding do not fit into an existing module, create a new one at | ||
`tests/suites/<new module>.js`, where `<new module>` is a broad yet | ||
descriptive name for the suite. If tests have many year-specific cases (ie, | ||
behave differently in leap years vs normal years, or have specific buggy | ||
behavior in a certain year), create the module in a new directory, | ||
`tests/suites/<new module>/<year>.js`, where `<new module>` is the decriptive | ||
name and `<year>` is the four-digit year the tests pertain to. | ||
|
||
In order for new tests to be run, they must be imported into `tests/tests.html`. | ||
Find the script includes headed by the html comment `<!-- Test suites -->`, and | ||
add a new one to the list which includes the new js files. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Dummy logging calls (ie, if tests are run in IE) | ||
window.console = window.console || {}; | ||
window.console.log = window.console.log || function(){}; | ||
window.console.debug = window.console.debug || function(){}; | ||
window.console.info = window.console.info || function(){}; | ||
window.console.warn = window.console.warn || function(){}; | ||
window.console.error = window.console.error || function(){}; | ||
|
||
(function() { | ||
var testName; | ||
|
||
//arg: { name } | ||
QUnit.testStart = function(t) { | ||
testName = t.name; | ||
}; | ||
|
||
//arg: { name, failed, passed, total } | ||
QUnit.testDone = function(t) { | ||
if (t.failed) | ||
console.log('Test "' + t.name + '" completed: ' + (0 === t.failed ? 'pass' : 'FAIL') + '\n') | ||
}; | ||
|
||
//{ result, actual, expected, message } | ||
QUnit.log = function(t) { | ||
if (!t.result) | ||
console.log('Test "' + testName + '" assertion failed. Expected <' + t.expected + '> Actual <' + t.actual + '>' + (t.message ? ': \'' + t.message + '\'' : '')); | ||
}; | ||
}()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
var system = require('system'); | ||
|
||
/** | ||
* Wait until the test condition is true or a timeout occurs. Useful for waiting | ||
* on a server response or for a ui change (fadeIn, etc.) to occur. | ||
* | ||
* @param testFx javascript condition that evaluates to a boolean, | ||
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or | ||
* as a callback function. | ||
* @param onReady what to do when testFx condition is fulfilled, | ||
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or | ||
* as a callback function. | ||
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used. | ||
*/ | ||
function waitFor(testFx, onReady, timeOutMillis) { | ||
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s | ||
start = new Date().getTime(), | ||
condition = false, | ||
interval = setInterval(function() { | ||
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { | ||
// If not time-out yet and condition not yet fulfilled | ||
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code | ||
} else { | ||
if(!condition) { | ||
// If condition still not fulfilled (timeout but condition is 'false') | ||
console.log("'waitFor()' timeout"); | ||
phantom.exit(1); | ||
} else { | ||
// Condition fulfilled (timeout and/or condition is 'true') | ||
//console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); | ||
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled | ||
clearInterval(interval); //< Stop this interval | ||
} | ||
} | ||
}, 100); //< repeat check every 100ms | ||
}; | ||
|
||
|
||
if (system.args.length !== 2) { | ||
console.log('Usage: run-qunit.js URL'); | ||
phantom.exit(1); | ||
} | ||
|
||
var page = require('webpage').create(); | ||
|
||
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") | ||
page.onConsoleMessage = function(msg) { | ||
console.log(msg); | ||
}; | ||
|
||
page.open(system.args[1], function(status){ | ||
if (status !== "success") { | ||
console.log("Unable to access network"); | ||
phantom.exit(1); | ||
} else { | ||
waitFor(function(){ | ||
return page.evaluate(function(){ | ||
var el = document.getElementById('qunit-testresult'); | ||
if (el && el.innerText.match('completed')) { | ||
return true; | ||
} | ||
return false; | ||
}); | ||
}, function(){ | ||
var failedNum = page.evaluate(function(){ | ||
var el = document.getElementById('qunit-testresult'); | ||
console.log(el.innerText); | ||
try { | ||
return el.getElementsByClassName('failed')[0].innerHTML; | ||
} catch (e) { } | ||
return 10000; | ||
}); | ||
phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0); | ||
}); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters