Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

added jquery-jasmine plugin. change the special case for data-bind to…

… use jquery's native show/hide methods. fixes #30
  • Loading branch information...
commit 02c1eccef5b0a82ebd6f9ea7438a135734855ced 1 parent 6a05460
Derick Bailey derickbailey authored
4 backbone.modelbinding.js
@@ -380,10 +380,10 @@ Backbone.ModelBinding = (function(Backbone, _, $){
380 380 element.attr("disabled", !val);
381 381 break;
382 382 case "displayed":
383   - element.css("display", val ? 'block' : 'none' );
  383 + element[val? "show" : "hide"]();
384 384 break;
385 385 case "hidden":
386   - element.css("display", val ? 'none' : 'block' );
  386 + element[val? "hide" : "show"]();
387 387 break;
388 388 default:
389 389 element.attr(attr, val);
6 spec/javascripts/dataBindConvention.spec.js
@@ -117,7 +117,7 @@ describe("data-bind conventions", function(){
117 117
118 118 it("should set the element's disabled value when the model's value is changed", function(){
119 119 this.model.set({isValid: true});
120   - expect(this.el.css("display")).toBe("block");
  120 + expect(this.el).toBeHidden();
121 121 });
122 122 });
123 123
@@ -128,12 +128,12 @@ describe("data-bind conventions", function(){
128 128 });
129 129
130 130 it("should set the element's disabled value to the model's value, immediately", function(){
131   - expect(this.el.css("display")).toBe("block");
  131 + expect(this.el.css("display")).not.toBe("none");
132 132 });
133 133
134 134 it("should set the element's disabled value when the model's value is changed", function(){
135 135 this.model.set({isValid: true});
136   - expect(this.el.css("display")).toBe("none");
  136 + expect(this.el).toBeHidden();
137 137 });
138 138 });
139 139 });
288 spec/javascripts/helpers/jasmine-jquery.js
... ... @@ -0,0 +1,288 @@
  1 +var readFixtures = function() {
  2 + return jasmine.getFixtures().proxyCallTo_('read', arguments);
  3 +};
  4 +
  5 +var preloadFixtures = function() {
  6 + jasmine.getFixtures().proxyCallTo_('preload', arguments);
  7 +};
  8 +
  9 +var loadFixtures = function() {
  10 + jasmine.getFixtures().proxyCallTo_('load', arguments);
  11 +};
  12 +
  13 +var setFixtures = function(html) {
  14 + jasmine.getFixtures().set(html);
  15 +};
  16 +
  17 +var sandbox = function(attributes) {
  18 + return jasmine.getFixtures().sandbox(attributes);
  19 +};
  20 +
  21 +var spyOnEvent = function(selector, eventName) {
  22 + jasmine.JQuery.events.spyOn(selector, eventName);
  23 +}
  24 +
  25 +jasmine.getFixtures = function() {
  26 + return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures();
  27 +};
  28 +
  29 +jasmine.Fixtures = function() {
  30 + this.containerId = 'jasmine-fixtures';
  31 + this.fixturesCache_ = {};
  32 + this.fixturesPath = 'spec/javascripts/fixtures';
  33 +};
  34 +
  35 +jasmine.Fixtures.prototype.set = function(html) {
  36 + this.cleanUp();
  37 + this.createContainer_(html);
  38 +};
  39 +
  40 +jasmine.Fixtures.prototype.preload = function() {
  41 + this.read.apply(this, arguments);
  42 +};
  43 +
  44 +jasmine.Fixtures.prototype.load = function() {
  45 + this.cleanUp();
  46 + this.createContainer_(this.read.apply(this, arguments));
  47 +};
  48 +
  49 +jasmine.Fixtures.prototype.read = function() {
  50 + var htmlChunks = [];
  51 +
  52 + var fixtureUrls = arguments;
  53 + for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
  54 + htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]));
  55 + }
  56 +
  57 + return htmlChunks.join('');
  58 +};
  59 +
  60 +jasmine.Fixtures.prototype.clearCache = function() {
  61 + this.fixturesCache_ = {};
  62 +};
  63 +
  64 +jasmine.Fixtures.prototype.cleanUp = function() {
  65 + jQuery('#' + this.containerId).remove();
  66 +};
  67 +
  68 +jasmine.Fixtures.prototype.sandbox = function(attributes) {
  69 + var attributesToSet = attributes || {};
  70 + return jQuery('<div id="sandbox" />').attr(attributesToSet);
  71 +};
  72 +
  73 +jasmine.Fixtures.prototype.createContainer_ = function(html) {
  74 + var container;
  75 + if(html instanceof jQuery) {
  76 + container = jQuery('<div id="' + this.containerId + '" />');
  77 + container.html(html);
  78 + } else {
  79 + container = '<div id="' + this.containerId + '">' + html + '</div>'
  80 + }
  81 + jQuery('body').append(container);
  82 +};
  83 +
  84 +jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) {
  85 + if (typeof this.fixturesCache_[url] == 'undefined') {
  86 + this.loadFixtureIntoCache_(url);
  87 + }
  88 + return this.fixturesCache_[url];
  89 +};
  90 +
  91 +jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
  92 + var self = this;
  93 + var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl;
  94 + jQuery.ajax({
  95 + async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
  96 + cache: false,
  97 + dataType: 'html',
  98 + url: url,
  99 + success: function(data) {
  100 + self.fixturesCache_[relativeUrl] = data;
  101 + },
  102 + error: function(jqXHR, status, errorThrown) {
  103 + throw Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')');
  104 + }
  105 + });
  106 +};
  107 +
  108 +jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {
  109 + return this[methodName].apply(this, passedArguments);
  110 +};
  111 +
  112 +
  113 +jasmine.JQuery = function() {};
  114 +
  115 +jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
  116 + return jQuery('<div/>').append(html).html();
  117 +};
  118 +
  119 +jasmine.JQuery.elementToString = function(element) {
  120 + return jQuery('<div />').append(element.clone()).html();
  121 +};
  122 +
  123 +jasmine.JQuery.matchersClass = {};
  124 +
  125 +(function(namespace) {
  126 + var data = {
  127 + spiedEvents: {},
  128 + handlers: []
  129 + };
  130 +
  131 + namespace.events = {
  132 + spyOn: function(selector, eventName) {
  133 + var handler = function(e) {
  134 + data.spiedEvents[[selector, eventName]] = e;
  135 + };
  136 + jQuery(selector).bind(eventName, handler);
  137 + data.handlers.push(handler);
  138 + },
  139 +
  140 + wasTriggered: function(selector, eventName) {
  141 + return !!(data.spiedEvents[[selector, eventName]]);
  142 + },
  143 +
  144 + cleanUp: function() {
  145 + data.spiedEvents = {};
  146 + data.handlers = [];
  147 + }
  148 + }
  149 +})(jasmine.JQuery);
  150 +
  151 +(function(){
  152 + var jQueryMatchers = {
  153 + toHaveClass: function(className) {
  154 + return this.actual.hasClass(className);
  155 + },
  156 +
  157 + toBeVisible: function() {
  158 + return this.actual.is(':visible');
  159 + },
  160 +
  161 + toBeHidden: function() {
  162 + return this.actual.is(':hidden');
  163 + },
  164 +
  165 + toBeSelected: function() {
  166 + return this.actual.is(':selected');
  167 + },
  168 +
  169 + toBeChecked: function() {
  170 + return this.actual.is(':checked');
  171 + },
  172 +
  173 + toBeEmpty: function() {
  174 + return this.actual.is(':empty');
  175 + },
  176 +
  177 + toExist: function() {
  178 + return this.actual.size() > 0;
  179 + },
  180 +
  181 + toHaveAttr: function(attributeName, expectedAttributeValue) {
  182 + return hasProperty(this.actual.attr(attributeName), expectedAttributeValue);
  183 + },
  184 +
  185 + toHaveId: function(id) {
  186 + return this.actual.attr('id') == id;
  187 + },
  188 +
  189 + toHaveHtml: function(html) {
  190 + return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html);
  191 + },
  192 +
  193 + toHaveText: function(text) {
  194 + if (text && jQuery.isFunction(text.test)) {
  195 + return text.test(this.actual.text());
  196 + } else {
  197 + return this.actual.text() == text;
  198 + }
  199 + },
  200 +
  201 + toHaveValue: function(value) {
  202 + return this.actual.val() == value;
  203 + },
  204 +
  205 + toHaveData: function(key, expectedValue) {
  206 + return hasProperty(this.actual.data(key), expectedValue);
  207 + },
  208 +
  209 + toBe: function(selector) {
  210 + return this.actual.is(selector);
  211 + },
  212 +
  213 + toContain: function(selector) {
  214 + return this.actual.find(selector).size() > 0;
  215 + },
  216 +
  217 + toBeDisabled: function(selector){
  218 + return this.actual.is(':disabled');
  219 + },
  220 +
  221 + // tests the existence of a specific event binding
  222 + toHandle: function(eventName) {
  223 + var events = this.actual.data("events");
  224 + return events && events[eventName].length > 0;
  225 + },
  226 +
  227 + // tests the existence of a specific event binding + handler
  228 + toHandleWith: function(eventName, eventHandler) {
  229 + var stack = this.actual.data("events")[eventName];
  230 + var i;
  231 + for (i = 0; i < stack.length; i++) {
  232 + if (stack[i].handler == eventHandler) {
  233 + return true;
  234 + }
  235 + }
  236 + return false;
  237 + }
  238 + };
  239 +
  240 + var hasProperty = function(actualValue, expectedValue) {
  241 + if (expectedValue === undefined) {
  242 + return actualValue !== undefined;
  243 + }
  244 + return actualValue == expectedValue;
  245 + };
  246 +
  247 + var bindMatcher = function(methodName) {
  248 + var builtInMatcher = jasmine.Matchers.prototype[methodName];
  249 +
  250 + jasmine.JQuery.matchersClass[methodName] = function() {
  251 + if (this.actual instanceof jQuery) {
  252 + var result = jQueryMatchers[methodName].apply(this, arguments);
  253 + this.actual = jasmine.JQuery.elementToString(this.actual);
  254 + return result;
  255 + }
  256 +
  257 + if (builtInMatcher) {
  258 + return builtInMatcher.apply(this, arguments);
  259 + }
  260 +
  261 + return false;
  262 + };
  263 + };
  264 +
  265 + for(var methodName in jQueryMatchers) {
  266 + bindMatcher(methodName);
  267 + }
  268 +})();
  269 +
  270 +beforeEach(function() {
  271 + this.addMatchers(jasmine.JQuery.matchersClass);
  272 + this.addMatchers({
  273 + toHaveBeenTriggeredOn: function(selector) {
  274 + this.message = function() {
  275 + return [
  276 + "Expected event " + this.actual + " to have been triggered on" + selector,
  277 + "Expected event " + this.actual + " not to have been triggered on" + selector
  278 + ];
  279 + };
  280 + return jasmine.JQuery.events.wasTriggered(selector, this.actual);
  281 + }
  282 + })
  283 +});
  284 +
  285 +afterEach(function() {
  286 + jasmine.getFixtures().cleanUp();
  287 + jasmine.JQuery.events.cleanUp();
  288 +});

0 comments on commit 02c1ecc

Please sign in to comment.
Something went wrong with that request. Please try again.