Reputation: 3302
I am just getting started with QUnit for ui testing, so I'm sure I am missing some fundamental use case for qunit-fixture. I thought it would be useful for testing DOM manipulation, but then I realized none of my DOM manipulating functions know anything about qunit-fixture (nor should they?).
Example:
<div id="container">
<form id="my-form">
<input type="hidden" name="field1" id="field1">
<input type="hidden" name="field2" id="field2">
</form>
</div>
<div id="qunit-fixture"></div>
I am passing URL parameters to a function to populate this form. If those params do not exist, I wish to remove the field so that JQuery.serialize()
does not bundle up an empty field.
function populate(params){
if( params.field1 ){
$("#field1").val(params.field1);
} else {
$("#field1").remove();
}
if( params.field2 ){
$("#field2").val(params.field2);
} else {
$("#field2").remove();
}
}
My original thought was "oh, cool. I can use qunit-fixture
to repeatedly emulate my form!" like so:
QUnit.test("populate - field1=text", function(assert){
$("#qunit-fixture").html($("#container").html());
populate( {field1: "text"} );
assert.deepEqual($("#field1").val(), "text");
assert.deepEqual($("#field2").val(), undefined);
});
QUnit.test("populate - field1="text", function(assert){
$("#qunit-fixture").html($("#container").html());
populate( {field1: "text", field2: "text"} );
assert.deepEqual($("#field1").val(), "text");
assert.deepEqual($("#field2").val(), "text");
});
This of course fails, because the first test's call to populate()
alters the DOM and removes #field2
from the pages's main form in addition to the copy that was placed into qunit-fixture
(non-unique IDs.. yikes).
So what am I missing? I am really like the ability to test logic modules with QUnit and am finally starting to see the merits of a more test driven development style. I would love to be able to test my DOM manipulation as well.
NOTE: This is a dumbed down example. The actual DOM manipulation in my project is significantly more complex, hence the desire to test it.
Upvotes: 4
Views: 3069
Reputation: 64959
The qunit-fixture
element is a container for some HTML that your tests can assert against. After each test, QUnit will reset it back to what it was before the test started, so that the next test can run without having to worry about what the previous test added or removed.
Of course, if your tests start making modifications to elements outside qunit-fixture
, then you will start to see tests affecting other tests, so try not to do this.
In your case, you are creating an empty qunit-fixture
div and copying the contents in from another div. A better approach would be to use the qunit-fixture
element to contain the HTML that you want to test against, for example:
<div id="qunit-fixture">
<div id="container">
<form id="my-form">
<input type="hidden" name="field1" id="field1">
<input type="hidden" name="field2" id="field2">
</form>
</div>
</div>
(I don't know if you need the container div. I've kept it in the example above, but if it's not necessary, feel free to get rid of it.)
As you no longer need to copy the HTML from the container div into the qunit-fixture
div, you can delete these lines from your tests:
$("#qunit-fixture").html($("#container").html());
You also no longer have the problem of duplicate IDs, and as QUnit would be resetting the qunit-fixture
after each test, you shouldn't have the problem of one of your tests affecting another.
The intention with QUnit is that you run it from a page you've created for specifically for testing purposes. This page should look like the following:
<html>
<head>
<!-- load various JS and CSS files -->
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<!-- sample markup for testing against -->
</div>
</body>
As there's no markup outside qunit-fixture
, other than the qunit
div, which QUnit will use for the test results, there's no "portion of the page outside qunit-fixture
", as you write in your comment, nor is there any duplication of IDs.
Upvotes: 7