Skip to content

Instantly share code, notes, and snippets.

@davemo
Created February 9, 2011 17:46
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davemo/818879 to your computer and use it in GitHub Desktop.
Save davemo/818879 to your computer and use it in GitHub Desktop.
A pattern for testing anonymous functions and asserting expected behaviour through nested calls using JasmineBDD.
// Notes: This is a way @Searls and I came up with that lets you
// test deeply nested anonymous functions and callbacks.
// We don't recommend nesting things this deep but we _do_ like the closure scoping in the tests.
// Any suggestions or improvements would be welcome :)
// The Codez, A little modal window framework
(function($, _) {
$.cil = $.cil || {};
$.cil.modals = {};
var m = $.cil.modals;
m.MODAL_LINK_TEMPLATE =
'<a href="<%= url %>" class="modal" data-controller="<%= controller %>" title="<%= title %>">' +
'<%= label %>' +
'</a>';
m.MODAL_TEMPLATE = '<div class="modal cil-template"></div>';
m.bind = function() {
$("body").delegate("a.modal", "click", m.open);
};
m.link = function(context) {
return _.template(m.MODAL_LINK_TEMPLATE, context);
};
m.hide = function() {
$("div.modal").dialog("close");
$('div.modal').remove();
};
m.open = function(e) {
var $modal = $(m.MODAL_TEMPLATE);
var $link = $(this);
var controller = m._extractController($link);
$modal.appendTo("body"); // level 1 specs test from here
$.cil.loadingIndicator.show();
$modal.load($link.attr("href"), function() { // level 2 specs test from here
$.cil.loadingIndicator.hide();
$modal.dialog({
modal: true,
minWidth: 450,
title: controller.title,
buttons: controller.buttons,
open: function(ev, ui) {
controller.onLoaded({ // level 3 specs test from here
link: $link,
container: $modal
});
}
});
});
e.preventDefault();
};
m._extractController = function($link) {
var ns = $link.attr("data-controller").split(".");
return $.cil[ns[0]][ns[1]];
};
$.subscribe('/cil/modals/action-complete', m.hide);
})(jQuery, _);
// The Tests
describe('Modal Window Generator', function() {
var sut = $.cil.modals,
support = $.jasmine, // requires https://github.com/searls/jasmine-fixture
$link,
linkMetaData;
beforeEach(function() {
// setup fixtures
linkMetaData = {
url: '/test/url',
controller: 'test.controller',
title: 'Test Link!',
label: 'Test Link Text'
};
$link = $(sut.link(linkMetaData));
});
// Level 1
describe('#open', function() {
var url, loadedCallback;
beforeEach(function() {
spyOn($.fn, 'load').andCallFake(function('/some/url', callback) {
loadedCallback = callback;
});
sut.open.call($link, { preventDefault: function() {} });
});
// Level 1 Assertions
it('loads remote content into the modal', function() {
expect($.fn.load).toHaveBeenCalledWith(linkMetaData.url, loadedCallback);
});
// ... *snip*
// Level 2
describe('$.load anonymous handler', function() {
var dialogParams;
beforeEach(function() {
spyOn($.fn, 'dialog').andCallFake(function(options) {
dialogParams = options;
});
// execute the callback passed in from our previous execution scope
loadedCallback();
});
// Level 2 Assertions
it('sets the modal flag to true', function() {
expect(dialogParams.modal).toBe(true);
});
// ... *snip*
// Level 3, feeling like inception all of a sudden...
describe('controller.onLoaded arguments', function() {
var onLoadedParams;
beforeEach(function() {
$.cil.test.controller.onLoaded = function() {};
spyOn($.cil.test.controller, 'onLoaded').andCallFake(function(options) {
onLoadedParams = options;
});
dialogParams.open();
});
it('passes the link', function() {
expect(onLoadedParams.link).toBe('a.modal');
});
it('passes the modal as container', function() {
expect(onLoadedParams.container).toBe('div.modal');
});
});
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment