Open dan-manges opened 15 years ago
In theory we could clone $('body').html() before each test and then restore it afterwards. Would this retain any events etc attached to all the DOM elements?
BTW, I see this issue as the only thing (and the Safari bug and acceptance of #14) stopping blue-ridge from being perfect.
I use this:
function fixture(element) { $('
').append(element).appendTo("body"); }function teardownFixtures() { $("#fixtures").remove(); }
Then I call the "fixture" function in my spec and "teardownFixtures" in an after block. I've been hesitating to include this as a standard BlueRidge component, though, as it's very jQuery specific. I might have to rethink that.
@karnowski what do you think about reloading the html fixture? Is that something you would welcome in blue-ridge?
@dan-manges: I'd definitely be interested.
I've found myself adding the following to many of my specs and writing my tests to operate only on DOM elements within a #fixtures div:
var bodyContent;
before(function() {
if (bodyContent == null) {
bodyContent = $("#fixture").html();
}
else {
$("#fixture").html(bodyContent);
}
});
I'll probably add that to my fixture and spec templates at some point but I'm not sure it makes sense to try to reload the fixture in all cases. I don't see how you could be certain to reload the fixture's state while still being able to run the tests by opening the fixture's html file. Would including the sort of reset I'm using in the default templates be useful to anyone else?
Hello, folks! The following gist is a proof of concept for automatic transactional fixtures (including events).
Is there interest in developing this into a patch?
There is a dependency on jQuery... $.fn.clone(true) is doing all the heavy lifting, but isn't this a moot point since Screw Unit depends on jQuery as well?
Just as an aside. I've recently found that the pain associated with the non-reloading of the fixture was actually my tests telling me something about my code. Usually, what I found was that I was trying to do too much manipulation of the dom deep down in my code. I started removing most of the dependencies on the fixture, itself, relying on a thing layer that grabbed the node, cloned it, then passed it to the javascript to manipulate.
My general rule has become that only a very thin layer of entry-point javascript functions should be allowed to do $(
HAHA! njackson's comment was actually made by me. Pairing station confusion. :)
I completely agree that most selectors should be given a context rather than allowed to search the entire dom but I don't think I want to start cloning nodes for all of my tests. I like that my tests do change the dom so that when they fail I can inspect the results.
If you completely agree, then not wanting to clone nodes for all your tests doesn't make much sense. :)
The inherent problem with having your tests manipulate the raw dom of the fixture is that they are no longer isolated from each other. If you create well-isolated, focused unit tests, then you should be able to figure out what happened without having to visually inspect the results.
The other thing I have noticed with my own stuff is that I have begun isolating most of my javascript from the dom for exactly this reason. So, my javascript is becoming more and more decoupled and, thus, ends up being a lot more reusable. If the majority of your javascript code touches the dom, there are some coupling and design issues that could be popping up unnoticed.
I am happy with this not being in blue ridge itself. Our "workaround" works great, and is only one line in your tests (or spec_helper). It is an evolution of what Jonah posted above: (http://gist.github.com/352871) // Reset the DOM between BlueRidge/ScrewUnit tests. // Supports multiple fixtures and allows introspection of DOM state after tests run. // Usage: // before(function() { $('#fixture).fixture(); }); jQuery.fn.fixture = function() { this.each(function() { if (this.original) { $(this).html(this.original); } else { this.original = $(this).html(); } }); }
Problem is, that still doesn't preserve bound events. Tests will behave differently based on which order you run them in.
Yes... that's kind of the point... it wipes out everything between tests... which is generally what I want.
But I like that this is not built-in behavior, then you can have fine grained control-- and have different fixtures for different describe blocks, resetting as appropriate.
Would it be possible to reload the HTML fixture before each spec? I'm having problems because one spec will modify the dom, affecting the state for all other specs.