Sometimes you just have to try crazy stuff. Yesterday I added Dart unittest support into my Backbone.js-powered calendar application.
Today, I start with a failing test:
test("populates the calendar with appointments", (){
// js.context.Backbone.history.loadUrl();
new js.Proxy(js.context.Cal, query('#calendar'));
var _id = iso8601.format(fifteenth);
var cell = queryAll('td').
where((el)=> el.id == _id).
first;
print('Contents (${_id}): ${cell.text}');
expect(cell.text, matches("Get Funky"));
});
In there, I create an instance of the Backbone application, Cal
, via Dart's js-interop. Then find the 15th of the month in the generated calendar. Finally, I check my expectations—that the calendar contains the correct, “funky” appointment.Amazingly, that test actually runs:
Sure, it fails, but it fails in a useful way—with the expectation that a record that should exist on the 15th of the month is not on the Backbone calendar.
Looking closer at the network tab of Chrome's Developer tools, it seems that my “real fake” test server is missing a CORS allowed request header:
That must be a jQuery (used by Backbone) thing. Since my test is running from a
file://
URL and my “real fake” test server is running on port 31337 of my localhost, I need that header. Fortunately, that is easy enough—made easier since I am using Dart, naturally. I switch my project from depending on the published version of plummbur_kruk (the “real fake” server), to my local repository:name: funky_calendar dependencies: unittest: any plummbur_kruk: path: /home/chris/repos/plummbur-kruk intl: any js: anyAfter a quick
pub update
, my Dart packages are switched over. In my local plummbur_kruk, I add another Access-Control-Allow-Headers
: HttpResponse res = req.response;
res.headers
..add('Access-Control-Allow-Origin', 'null')
..add('Access-Control-Allow-Headers', 'Content-Type')
..add('Access-Control-Allow-Headers', 'X-Requested-With')
..add('Access-Control-Allow-Methods', 'GET,DELETE,PUT');
Now, when I run my test, I get just the test failure and no network errors:FAIL: the initial view populates the calendar with appointments Expected: match 'Get Funky' Actual: '15'This turns out to be a simple matter of timing. The expectations in my test are being checked before the Backbone application has a change to layout all of its elements. The easiest fix is to add a minimal delay before checking the expectation:
test("populates the calendar with appointments", (){
// js.context.Backbone.history.loadUrl();
new js.Proxy(js.context.Cal, query('#calendar'));
var _id = iso8601.format(fifteenth);
var cell = queryAll('td').
where((el)=> el.id == _id).
first;
print('Contents (${_id}): ${cell.text}');
new Timer(
new Duration(milliseconds: 10),
expectAsync0((){
expect(cell.text, matches("Get Funky"));
})
);
});
And with that, I actually have a passing test:unittest-suite-wait-for-done Contents (2013-09-15): 15 PASS: the initial view populates the calendar with appointments All 1 tests passed. unittest-suite-successThe tests pass and (if I comment out the teardown), I can even see the unstyled calendar on the test page:
Insanely enough, I can run a legitimate test for Backbone code with Dart unit testing. The benefits are obvious: easier setup, better support for running under continuous integration, nicer test syntax, better async support. There are more questions than answers at this point, but I'm pretty sure I have the makings of another recipe for Recipes with Backbone on my hands.
I kid! Or do I…?
Day #880
No comments:
Post a Comment