Skip to content

Commit

Permalink
Created the composite addon.
Browse files Browse the repository at this point in the history
  • Loading branch information
Wesley Walser authored and wwalser committed Aug 15, 2011
1 parent 75dae0b commit 8e321e6
Show file tree
Hide file tree
Showing 9 changed files with 385 additions and 0 deletions.
7 changes: 7 additions & 0 deletions addons/composite/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Composite - A QUnit Addon For Running Multiple Test Files
================================

Composite is a QUnit addon that, when handed an array of files, will
open each of those files inside of an iframe, run the tests and
display the results as a single suite of QUnit tests.

13 changes: 13 additions & 0 deletions addons/composite/composite.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
iframe.qunit-subsuite{
position: fixed;
bottom: 0;
left: 0;

margin: 0;
padding: 0;
border-width: 1px 0 0;
height: 45%;
width: 100%;

background: #fff;
}
82 changes: 82 additions & 0 deletions addons/composite/composite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
(function( QUnit ) {

var subsuiteFrame;

QUnit.extend( QUnit, {
testSuites: function( suites ) {
for ( var i = 0; i < suites.length; i++ ) {
(function( suite ) {
asyncTest( suite, function() {
QUnit.runSuite( suite );
});
}( suites[i] ) );
}
QUnit.done = function() {
subsuiteFrame.style.display = "none";
};
},

testStart: function( data ) {
// update the test status to show which test suite is running
QUnit.id( "qunit-testresult" ).innerHTML = "Running " + data.name + "...<br>&nbsp;";
},

testDone: function() {
var current = QUnit.id( this.config.current.id ),
children = current.children;

// undo the auto-expansion of failed tests
for ( var i = 0; i < children.length; i++ ) {
if ( children[i].nodeName === "OL" ) {
children[i].style.display = "none";
}
}
},

runSuite: function( suite ) {
var body = document.getElementsByTagName( "body" )[0],
iframe = subsuiteFrame = document.createElement( "iframe" ),
iframeWin;

iframe.className = "qunit-subsuite";
body.appendChild( iframe );

function onIframeLoad() {
var module, test,
count = 0;

QUnit.extend( iframeWin.QUnit, {
moduleStart: function( data ) {
// capture module name for messages
module = data.name;
},

testStart: function( data ) {
// capture test name for messages
test = data.name;
},

log: function( data ) {
// pass all test details through to the main page
var message = module + ": " + test + ": " + data.message;
expect( ++count );
QUnit.push( data.result, data.actual, data.expected, message );
},

done: function() {
// start the wrapper test from the main page
start();
}
});
}
QUnit.addEvent( iframe, "load", onIframeLoad );

iframeWin = iframe.contentWindow;
iframe.setAttribute( "src", suite );

this.runSuite = function( suite ) {
iframe.setAttribute( "src", suite );
};
}
});
}( QUnit ) );
19 changes: 19 additions & 0 deletions addons/composite/dummy-qunit-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>QUnit Core Test Suite</title>
<link rel="stylesheet" href="../../qunit/qunit.css" type="text/css" media="screen">
<script src="../../qunit/qunit.js"></script>

<script src="../../test/test.js"></script>
</head>
<body>
<h1 id="qunit-header">QUnit Core Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup</div>
</body>
</html>
19 changes: 19 additions & 0 deletions addons/composite/dummy-same-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>QUnit Same Test Suite</title>
<link rel="stylesheet" href="../../qunit/qunit.css" type="text/css" media="screen">
<script src="../../qunit/qunit.js"></script>

<script src="../../test/same.js"></script>
</head>
<body>
<h1 id="qunit-header">QUnit Same Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup</div>
</body>
</html>
35 changes: 35 additions & 0 deletions addons/composite/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Composite</title>
</head>
<body>
<h1>Composite</h1>
<h3>A QUnit Addon For Running Multiple Test Files</h3>
<p>Composite is a QUnit addon that, when handed an array of
files, will open each of those files inside of an iframe, run
the tests and display the results as a single suite of QUnit
tests.</p>
<h4>Using Composite</h4>
<p>To use Composite, setup a standard QUnit html page as you
would with other QUnit tests. Remember to include composite.js
and composite.css. Then, inside of either an external js file,
or a script block call the only new method that Composite
exposes, QUnit.testSuites().</p><p>QUnit.testSuites() is
passed an array of test files to run as follows:</p>
<pre>
QUnit.testSuites([
"test-file-1.html",
"test-file-2.html",
"test-file-3.html"
]);
</pre>
<h4>Tests</h4>
<p>Composite has tests of it's own.</p>
<p>
<a href="qunit-composite-test.html">Composite Test</a>: A suite which tests the implementation of composite.<br>
<a href="qunit-composite-demo-test.html">Composite Demo</a>: A suite which demoes how Compisite is bootstrapped and run.
</p>
</body>
</html>
31 changes: 31 additions & 0 deletions addons/composite/qunit-composite-demo-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>QUnit SubsuiteRunner Test Suite</title>

<link rel="stylesheet" href="../../qunit/qunit.css" type="text/css" media="screen">
<link rel="stylesheet" href="composite.css">
<script src="../../qunit/qunit.js"></script>
<script src="composite.js"></script>

<script>
QUnit.testSuites([
"dummy-qunit-test.html",
"dummy-same-test.html",
"qunit-composite-test.html"
]);
</script>
</head>
<body>

<h1 id="qunit-header">QUnit SubsuiteRunner Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">

</div>
</body>
</html>
20 changes: 20 additions & 0 deletions addons/composite/qunit-composite-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>QUnit Core Test Suite</title>
<link rel="stylesheet" href="../../qunit/qunit.css" type="text/css" media="screen">
<script src="../../qunit/qunit.js"></script>

<script src="composite.js"></script>
<script src="qunit-composite-test.js"></script>
</head>
<body>
<h1 id="qunit-header">QUnit Core Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup</div>
</body>
</html>
159 changes: 159 additions & 0 deletions addons/composite/qunit-composite-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
module( "testSuites tests", (function(){
var asyncTest = QUnit.asyncTest,
runSuite = QUnit.runSuite;

return {
setup: function(){
//proxy asyncTest and runSuite
QUnit.asyncTest = window.asyncTest = function( name, callback ){
ok( true, "asyncTestCalled for each suite" );
callback(); //don't acutally create tests, just call callback
};
QUnit.runSuite = window.runSuite = function(){
ok( true, "runSuite called for each suite" );
};
//ensure that subsuite's done doesn't run
this.oldDone = QUnit.done;
},
teardown: function(){
//restore
QUnit.asyncTest = window.asyncTest = asyncTest;
QUnit.runSuite = window.runSuite = runSuite;
QUnit.done = this.oldDone;
}
};
})());

test( "proper number of asyncTest and runSuite calls", function(){
expect( 6 );
QUnit.testSuites( ["one.html", "two.html", "three.html"] );
});

test( "done callback changed", function(){
QUnit.testSuites( ["dummy.html"] );
notEqual( this.oldDone, QUnit.done, "done callback should be set" );
});

module( "testStart tests", (function(){
var id = QUnit.id;
return {
setup: function(){
//proxy id
var fakeElem = this.fakeElem = document.createElement( "div" );

QUnit.id = function(){
return fakeElem;
}
},
teardown: function(){
QUnit.id = id;
}
};
})());

test( "running message printed", function(){
var hello = "hello world",
expected = "Running " + hello + "...<br>&nbsp;";
QUnit.testStart( {name: hello} );
equal( this.fakeElem.innerHTML, expected, "innerHTML was set correctly by testStart" );
});

module( "testDone tests", (function(){
var id = QUnit.id;
return {
setup: function(){
//proxy id
var fakeElem = this.fakeElem = document.createElement( "div" );
fakeElem.appendChild( document.createElement( "ol" ) );
fakeElem.appendChild( document.createElement( "ol" ) );
QUnit.id = function(){
return fakeElem;
}
},
teardown: function(){
QUnit.id = id;
}
};
})());

test( "test expansions are hidden", function(){
QUnit.testDone();
equal( this.fakeElem.children[0].style.display, "none", "first ol display is none" );
equal( this.fakeElem.children[1].style.display, "none", "second ol display is none" );
});

test( "non-ol elements aren't hidden", function(){
this.fakeElem.appendChild( document.createElement( "span" ) );

QUnit.testDone();
notEqual( this.fakeElem.children[2].style.display, "none", "first ol display is none" );
});

module( "runSuite tests", (function(){
var getElementsByTagName = document.getElementsByTagName,
createElement = document.createElement,
runSuite = QUnit.runSuite;

return {
setup: function(){
//proxy getElementsByTagName and createElement
var setAttributeCall = this.setAttributeCall = {},
appendChildCall = this.appendChildCall = {called: 0},
iframeLoad = this.iframeLoad = {},
iframeQUnitObject = this.iframeQUnitObject = {},
fakeElement = {
appendChild: function(){appendChildCall.called++},
setAttribute: function(){setAttributeCall.args = arguments},
addEventListener: function( type, callback ){iframeLoad.callback = callback;},
contentWindow: {QUnit: iframeQUnitObject},
className: "",
};

document.getElementsByTagName = function(){
return [fakeElement];
};
document.createElement = function(){
return fakeElement;
}

},
teardown: function(){
document.getElementsByTagName = getElementsByTagName;
document.createElement = createElement;
//must restore even though we didn't proxy; the runner overwrites upon first call
QUnit.runSuite = runSuite;
}
};
})());

test( "runSuite different after first run", function(){
var before = QUnit.runSuite,
after;
QUnit.runSuite();
after = QUnit.runSuite;
notEqual( before, after, "runSuite changed after initial run" );
});

test( "iframe only created once", function(){
QUnit.runSuite();
equal( this.appendChildCall.called, 1, "append child called once" );
QUnit.runSuite();
equal( this.appendChildCall.called, 1, "append child only ever called once" );
});

test( "iframe's QUnit object is modified when iframe source loads", function(){
var before = this.iframeQUnitObject,
after;
QUnit.runSuite();
this.iframeLoad.callback();
notEqual( before, after, "iframe's qunit object is modified upon load");
});

test( "iframe src set to suite passed", function(){
var pages = ["testing.html", "subsuiteRunner.html"];
QUnit.runSuite( pages[0] );
equal( this.setAttributeCall.args[0], "src", "src attribute set" );
equal( this.setAttributeCall.args[1], pages[0], "src attribute set" );
QUnit.runSuite( pages[1] );
equal( this.setAttributeCall.args[1], pages[1], "src attribute set" );
});

0 comments on commit 8e321e6

Please sign in to comment.