diff --git a/Gemfile b/Gemfile index ef35abc6e..882f14c92 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source 'http://rubygems.org' gem 'rails', '>= 3.0.0' gem 'bundler', '>= 1.0.0' -#gem "chef" +gem "chef", :require => false #Security gem 'devise', '1.1.3' diff --git a/Gemfile.lock b/Gemfile.lock index 3a4976383..bd4190fe3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: git://github.com/Empact/roxml.git - revision: d411519add92e0cd5a985253f376d25c26884324 + revision: 7ea9a9ffd2338aaef5b04cb792060ae8c98f346a specs: roxml (3.1.6) activesupport (>= 2.3.0) @@ -39,7 +39,7 @@ GIT GIT remote: git://github.com/jnunemaker/mongomapper.git - revision: fd59b0ab068be7321f8e84b9dc12fb4fa6b8535d + revision: b24db29c236f239d6a5a821fb6a444430e89f9d6 branch: rails3 specs: mongo_mapper (0.8.4) @@ -117,6 +117,7 @@ GEM bson (1.1) bson_ext (1.1) builder (2.1.2) + bunny (0.6.0) capistrano (2.5.19) highline net-scp (>= 1.0.0) @@ -131,6 +132,20 @@ GEM rack-test (>= 0.5.4) selenium-webdriver (>= 0.0.3) cgi_multipart_eof_fix (2.5.0) + chef (0.9.12) + bunny (>= 0.6.0) + erubis + extlib + highline + json (>= 1.4.4, <= 1.4.6) + mixlib-authentication (>= 1.1.0) + mixlib-cli (>= 1.1.0) + mixlib-config (>= 1.1.2) + mixlib-log (>= 1.2.0) + moneta + ohai (>= 0.5.7) + rest-client (>= 1.0.4, < 1.7.0) + uuidtools childprocess (0.1.3) ffi (~> 0.6.3) columnize (0.3.1) @@ -150,7 +165,7 @@ GEM devise (1.1.3) bcrypt-ruby (~> 2.1.2) warden (~> 0.10.7) - devise_invitable (0.3.4) + devise_invitable (0.3.5) devise (~> 1.1.0) diff-lcs (1.1.2) em-websocket (0.1.4) @@ -159,6 +174,7 @@ GEM erubis (2.6.6) abstract (>= 1.0.0) eventmachine (0.12.10) + extlib (0.9.15) factory_girl (1.3.2) factory_girl_rails (1.0) factory_girl (~> 1.3) @@ -174,7 +190,7 @@ GEM gherkin (2.2.9) json (~> 1.4.6) term-ansicolor (~> 1.0.5) - haml (3.0.22) + haml (3.0.23) hashie (0.4.0) highline (1.6.1) http_connection (1.4.0) @@ -193,13 +209,19 @@ GEM mime-types (~> 1.16) treetop (~> 1.4.8) mime-types (1.16) - mini_fb (1.1.3) + mini_fb (1.1.4) hashie rest-client mini_magick (3.0) subexec (~> 0.0.4) + mixlib-authentication (1.1.4) + mixlib-log + mixlib-cli (1.2.0) + mixlib-config (1.1.2) + mixlib-log (1.2.0) mocha (0.9.9) rake + moneta (0.6.0) mongo (1.1) bson (>= 1.0.5) mongrel (1.1.5) @@ -241,10 +263,17 @@ GEM oa-core (= 0.1.6) rack-openid (~> 1.2.0) ruby-openid-apps-discovery - oauth (0.4.3) + oauth (0.4.4) oauth2 (0.1.0) faraday (~> 0.5.0) multi_json (~> 0.0.4) + ohai (0.5.8) + extlib + json (>= 1.4.4, <= 1.4.6) + mixlib-cli + mixlib-config + mixlib-log + systemu omniauth (0.1.6) oa-basic (= 0.1.6) oa-core (= 0.1.6) @@ -313,6 +342,7 @@ GEM json_pure rubyzip subexec (0.0.4) + systemu (1.2.0) term-ansicolor (1.0.5) thin (1.2.7) daemons (>= 1.0.9) @@ -330,7 +360,7 @@ GEM uuidtools (2.1.1) warden (0.10.7) rack (>= 1.0.0) - webmock (1.4.0) + webmock (1.5.0) addressable (>= 2.2.2) crack (>= 0.1.7) will_paginate (3.0.pre2) @@ -347,6 +377,7 @@ DEPENDENCIES bundler (>= 1.0.0) capybara (~> 0.3.9) carrierwave! + chef cucumber-rails (= 0.3.2) database_cleaner (= 0.5.2) devise (= 1.1.3) diff --git a/public/javascripts/aspect-edit.js b/public/javascripts/aspect-edit.js index 8346bb7dd..17c0c673d 100644 --- a/public/javascripts/aspect-edit.js +++ b/public/javascripts/aspect-edit.js @@ -27,11 +27,15 @@ var AspectEdit = { $(".aspect h3").live('focus', AspectEdit.changeName); }, - startDrag: function(event, ui) { - $(this).children("img").animate({'height':80, 'width':80, 'opacity':0.8}, 200) - .tipsy("hide"); + startDrag: function() { + AspectEdit.animateImage($(this).children("img").first()); $(".draggable_info").fadeIn(100); }, + + animateImage: function(image) { + image.animate({'height':80, 'width':80, 'opacity':0.8}, 200); + image.tipsy("hide"); + }, duringDrag: function(event, ui) { $(this).children("img").tipsy("hide"); //ensure this is hidden diff --git a/spec/javascripts/aspect-edit-spec.js b/spec/javascripts/aspect-edit-spec.js index 9c2da4621..e71f2dbf2 100644 --- a/spec/javascripts/aspect-edit-spec.js +++ b/spec/javascripts/aspect-edit-spec.js @@ -1,8 +1,38 @@ describe("AspectEdit", function() { -// describe("initialize", function() { -// -// }); + describe("initialize", function() { + it("calls draggable on ul .person", function() { + spyOn($.fn, "draggable"); + AspectEdit.initialize(); + expect($.fn.draggable).toHaveBeenCalledWith( + {revert: true, start: AspectEdit.startDrag, + drag: AspectEdit.duringDrag, stop: AspectEdit.stopDrag}); + expect($.fn.draggable.mostRecentCall.object.selector).toEqual("ul .person"); + }); + it("calls droppable on .aspect ul.dropzone", function() { + spyOn($.fn, "droppable"); + AspectEdit.initialize(); + expect($.fn.droppable).toHaveBeenCalledWith({hoverClass: 'active', drop: AspectEdit.onDropMove}); + expect($.fn.droppable.calls[0].object.selector).toEqual(".aspect ul.dropzone"); +// This would be AWESOME: +// expect($.fn.droppable) +// .toHaveBeenCalled() +// .on(".aspect ul.dropzone") +// .with({}); + }); + }); + + describe("startDrag", function() { + it("animates the image", function() { + $('#jasmine_content').html(''); + spyOn(AspectEdit, "animateImage"); + $.proxy(AspectEdit.startDrag, $('.person.ui-draggable'))(); + expect(AspectEdit.animateImage).toHaveBeenCalled(); + expect(AspectEdit.animateImage.mostRecentCall.args[0]).toHaveClass("avatar"); + }); + }); describe("decrementRequestsCounter", function() { describe("when there is one request", function() { diff --git a/spec/javascripts/helpers/jasmine-jquery.js b/spec/javascripts/helpers/jasmine-jquery.js new file mode 100644 index 000000000..0096c4fc5 --- /dev/null +++ b/spec/javascripts/helpers/jasmine-jquery.js @@ -0,0 +1,203 @@ +var readFixtures = function() { + return jasmine.getFixtures().proxyCallTo_('read', arguments); +}; + +var loadFixtures = function() { + jasmine.getFixtures().proxyCallTo_('load', arguments); +}; + +var setFixtures = function(html) { + jasmine.getFixtures().set(html); +} + +var sandbox = function(attributes) { + return jasmine.getFixtures().sandbox(attributes); +}; + +jasmine.getFixtures = function() { + return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures(); +}; + +jasmine.Fixtures = function() { + this.containerId = 'jasmine-fixtures'; + this.fixturesCache_ = {}; +}; + +jasmine.Fixtures.prototype.set = function(html) { + this.cleanUp(); + this.createContainer_(html); +}; + +jasmine.Fixtures.prototype.load = function() { + this.cleanUp(); + this.createContainer_(this.read.apply(this, arguments)); +}; + +jasmine.Fixtures.prototype.read = function() { + var htmlChunks = []; + + var fixtureUrls = arguments; + for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { + htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])); + } + + return htmlChunks.join(''); +}; + +jasmine.Fixtures.prototype.clearCache = function() { + this.fixturesCache_ = {}; +}; + +jasmine.Fixtures.prototype.cleanUp = function() { + $('#' + this.containerId).remove(); +}; + +jasmine.Fixtures.prototype.sandbox = function(attributes) { + var attributesToSet = attributes || {}; + return $('
').attr(attributesToSet); +}; + +jasmine.Fixtures.prototype.createContainer_ = function(html) { + var container = $('
'); + container.html(html); + $('body').append(container); +}; + +jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) { + if (typeof this.fixturesCache_[url] == 'undefined') { + this.loadFixtureIntoCache_(url); + } + return this.fixturesCache_[url]; +}; + +jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(url) { + var self = this; + $.ajax({ + async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded + cache: false, + dataType: 'html', + url: url, + success: function(data) { + self.fixturesCache_[url] = data; + } + }); +}; + +jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) { + return this[methodName].apply(this, passedArguments); +}; + + +jasmine.JQuery = function() {}; + +jasmine.JQuery.browserTagCaseIndependentHtml = function(html) { + return $('
').append(html).html(); +}; + +jasmine.JQuery.elementToString = function(element) { + return $('
').append(element.clone()).html(); +}; + +jasmine.JQuery.matchersClass = {}; + + +(function(){ + var jQueryMatchers = { + toHaveClass: function(className) { + return this.actual.hasClass(className); + }, + + toBeVisible: function() { + return this.actual.is(':visible'); + }, + + toBeHidden: function() { + return this.actual.is(':hidden'); + }, + + toBeSelected: function() { + return this.actual.is(':selected'); + }, + + toBeChecked: function() { + return this.actual.is(':checked'); + }, + + toBeEmpty: function() { + return this.actual.is(':empty'); + }, + + toExist: function() { + return this.actual.size() > 0; + }, + + toHaveAttr: function(attributeName, expectedAttributeValue) { + return hasProperty(this.actual.attr(attributeName), expectedAttributeValue); + }, + + toHaveId: function(id) { + return this.actual.attr('id') == id; + }, + + toHaveHtml: function(html) { + return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html); + }, + + toHaveText: function(text) { + return this.actual.text() == text; + }, + + toHaveValue: function(value) { + return this.actual.val() == value; + }, + + toHaveData: function(key, expectedValue) { + return hasProperty(this.actual.data(key), expectedValue); + }, + + toBe: function(selector) { + return this.actual.is(selector); + }, + + toContain: function(selector) { + return this.actual.find(selector).size() > 0; + } + }; + + var hasProperty = function(actualValue, expectedValue) { + if (expectedValue === undefined) { + return actualValue !== undefined; + } + return actualValue == expectedValue; + }; + + var bindMatcher = function(methodName) { + var builtInMatcher = jasmine.Matchers.prototype[methodName]; + + jasmine.JQuery.matchersClass[methodName] = function() { + if (this.actual instanceof jQuery) { + var result = jQueryMatchers[methodName].apply(this, arguments); + this.actual = jasmine.JQuery.elementToString(this.actual); + return result; + } + + if (builtInMatcher) { + return builtInMatcher.apply(this, arguments); + } + + return false; + }; + }; + + for(var methodName in jQueryMatchers) { + bindMatcher(methodName); + } +})(); + +beforeEach(function() { + this.addMatchers(jasmine.JQuery.matchersClass); +}); + +afterEach(function() { + jasmine.getFixtures().cleanUp(); +}); \ No newline at end of file