diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 4f35d83e3..a419bccb0 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -43,18 +43,16 @@ class PhotosController < ApplicationController def create rescuing_photo_errors do if remotipart_submitted? - @photo = current_user.build_post(:photo, params[:photo]) - else - legacy_create - end - - if @photo.save - respond_to do |format| - format.json{ render(:layout => false , :json => {"success" => true, "data" => @photo}.to_json )} - format.html{ render(:layout => false , :json => {"success" => true, "data" => @photo}.to_json )} + @photo = current_user.build_post(:photo, params[:photo]) + if @photo.save + respond_to do |format| + format.json { render :json => {"success" => true, "data" => @photo.as_api_response(:backbone)} } + end + else + respond_with @photo, :location => photos_path, :error => message end else - respond_with @photo, :location => photos_path, :error => message + legacy_create end end end @@ -192,6 +190,13 @@ class PhotosController < ApplicationController :image_url_small => @photo.url(:thumb_small)} current_user.update_profile(profile_params) end + + respond_to do |format| + format.json{ render(:layout => false , :json => {"success" => true, "data" => @photo}.to_json )} + format.html{ render(:layout => false , :json => {"success" => true, "data" => @photo}.to_json )} + end + else + respond_with @photo, :location => photos_path, :error => message end end diff --git a/app/models/photo.rb b/app/models/photo.rb index fa76787c5..0f3f4aa92 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -9,8 +9,6 @@ class Photo < ActiveRecord::Base include Diaspora::Commentable include Diaspora::Shareable - - # NOTE API V1 to be extracted acts_as_api api_accessible :backbone do |t| diff --git a/features/step_definitions/trumpeter_steps.rb b/features/step_definitions/trumpeter_steps.rb index 89c1e57ba..5f7434193 100644 --- a/features/step_definitions/trumpeter_steps.rb +++ b/features/step_definitions/trumpeter_steps.rb @@ -1,22 +1,7 @@ -When /^I trumpet$/ do - visit new_post_path -end - -When /^I write "([^"]*)"$/ do |text| - fill_in :text, :with => text -end - -Then /I mention "([^"]*)"$/ do |text| - fill_in_autocomplete('textarea.text', '@a') - sleep(5) - find("li.active").click -end - def fill_in_autocomplete(selector, value) page.execute_script %Q{$('#{selector}').val('#{value}').keyup()} end - def aspects_dropdown find(".dropdown-toggle") end @@ -31,11 +16,39 @@ def select_from_dropdown(option_text, dropdown) #assert dropdown text is link end +When /^I trumpet$/ do + visit new_post_path +end + +When /^I write "([^"]*)"$/ do |text| + fill_in :text, :with => text +end + +Then /I mention "([^"]*)"$/ do |text| + fill_in_autocomplete('textarea.text', '@a') + sleep(5) + find("li.active").click +end + When /^I select "([^"]*)" in my aspects dropdown$/ do |title| within ".aspect_selector" do select_from_dropdown(title, aspects_dropdown) end end + Then /^"([^"]*)" should be a (limited|public) post in my stream$/ do |post_text, scope| find_post_by_text(post_text).find(".post_scope").text.should =~ /#{scope}/i +end + +When /^I upload a fixture picture with filename "([^"]*)"$/ do |file_name| + within ".new_photo" do + attach_file "photo[user_file]", Rails.root.join("spec", "fixtures", file_name) + click_button :submit + end + + @image_source = find(".photos img")["src"] +end + +Then /^"([^"]*)" should have my photo$/ do |status_text| + find_post_by_text(status_text).find(".photo_attachments img")["src"].should == @image_source end \ No newline at end of file diff --git a/features/trumpeter.feature b/features/trumpeter.feature index 68701d41c..eac163fc5 100644 --- a/features/trumpeter.feature +++ b/features/trumpeter.feature @@ -21,11 +21,17 @@ Feature: Creating a new post Then I should see "This is super skrunkle" as the first post in my stream Then "This is super skrunkle" should be a limited post in my stream - Scenario: Mention a contact - Given a user named "Alice Smith" with email "alice@alice.alice" - And a user with email "bob@bob.bob" is connected with "alice@alice.alice" - And I mention "alice@alice.alice" - And I press "Share" - And I go to "/stream" - Then I follow "Alice Smith" + Scenario: Mention a contact + Given a user named "Alice Smith" with email "alice@alice.alice" + And a user with email "bob@bob.bob" is connected with "alice@alice.alice" + And I mention "alice@alice.alice" + And I press "Share" + And I go to "/stream" + Then I follow "Alice Smith" + Scenario: Uploading a photo + When I write "check out this picture" + And I upload a fixture picture with filename "button.gif" + And I press "Share" + And I go to "/stream" + Then "check out this picture" should have my photo diff --git a/public/javascripts/app/forms.js b/public/javascripts/app/forms.js index cbfff963f..a9f3fe105 100644 --- a/public/javascripts/app/forms.js +++ b/public/javascripts/app/forms.js @@ -1,28 +1,14 @@ app.forms.Base = app.views.Base.extend({ - events :{ - 'submit form' : 'setModelAttributes' + formSelector : "form", + + initialize : function() { + this.setupFormEvents() }, - setModelAttributes : function(evt){ - if(evt){ evt.preventDefault(); } + setupFormEvents : function(){ + this.events = {} + this.events['submit ' + this.formSelector] = 'setModelAttributes'; + this.delegateEvents(); + }, - var form = this.$("form"); - - function setValueFromField(memo, attribute, selector){ - var selectors = form.find(selector); - - if(selectors.length > 1) { - memo[attribute] = _.map(selectors, function(selector){ - return $(selector).val() - }) - } else { - memo[attribute] = selectors.val(); - } - - return memo - } - - this.model.set(_.inject(this.formAttrs, setValueFromField, {})) - this.model.trigger("setFromForm") - } }) diff --git a/public/javascripts/app/forms/picture_form.js b/public/javascripts/app/forms/picture_form.js index 2fcc0707f..9e1e66c77 100644 --- a/public/javascripts/app/forms/picture_form.js +++ b/public/javascripts/app/forms/picture_form.js @@ -5,16 +5,31 @@ app.forms.Picture = app.forms.Base.extend({ 'ajax:complete .new_photo' : "photoUploaded" }, - postRenderTemplate : function(){ - this.$("input[name=authenticity_token]").val($("meta[name=csrf-token]").attr("content")) + initialize : function() { + this.photos = new Backbone.Collection() + this.photos.bind("add", this.render, this) }, photoUploaded : function(evt, xhr) { resp = JSON.parse(xhr.responseText) if(resp.success) { - console.log(new Backbone.Model(resp.data.photo)); + this.photos.add(new Backbone.Model(resp.data)) } else { - console.log(resp.error); - }; + alert("Upload failed! Please try again. " + resp.error); + } + }, + + postRenderTemplate : function(){ + this.$("input[name=authenticity_token]").val($("meta[name=csrf-token]").attr("content")) + this.$("input[name=photo_ids]").val(this.photos.pluck("id")) + this.renderPhotos(); + }, + + renderPhotos : function(){ + var photoContainer = this.$(".photos") + this.photos.each(function(photo){ + var photoView = new app.views.Photo({model : photo}).render().el + photoContainer.append(photoView) + }) } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/public/javascripts/app/forms/post_form.js b/public/javascripts/app/forms/post_form.js index 79edd754a..de519bf91 100644 --- a/public/javascripts/app/forms/post_form.js +++ b/public/javascripts/app/forms/post_form.js @@ -1,5 +1,6 @@ app.forms.Post = app.forms.Base.extend({ templateName : "post-form", + formSelector : ".new-post", subviews : { ".aspect_selector" : "aspectsDropdown", @@ -10,13 +11,37 @@ app.forms.Post = app.forms.Base.extend({ formAttrs : { "textarea#text_with_markup" : "text", "input.aspect_ids" : "aspect_ids", - 'input.service:checked' : 'services' + "input.service:checked" : "services" }, initialize : function() { this.aspectsDropdown = new app.views.AspectsDropdown(); this.servicesSelector = new app.views.ServicesSelector(); this.pictureForm = new app.forms.Picture(); + + this.setupFormEvents(); + }, + + setModelAttributes : function(evt){ + if(evt){ evt.preventDefault(); } + var form = this.$(this.formSelector); + + this.model.set(_.inject(this.formAttrs, setValueFromField, {})) + //pass collections across + this.model.photos = this.pictureForm.photos + this.model.trigger("setFromForm") + + function setValueFromField(memo, attribute, selector){ + var selectors = form.find(selector); + if(selectors.length > 1) { + memo[attribute] = _.map(selectors, function(selector){ + return $(selector).val() + }) + } else { + memo[attribute] = selectors.val(); + } + return memo + } }, postRenderTemplate : function() { diff --git a/public/javascripts/app/models/status_message.js b/public/javascripts/app/models/status_message.js index 8152db67f..fbd0c5405 100644 --- a/public/javascripts/app/models/status_message.js +++ b/public/javascripts/app/models/status_message.js @@ -7,6 +7,7 @@ app.models.StatusMessage = app.models.Post.extend({ var mungedAttrs = { status_message : _.clone(this.attributes), 'aspect_ids[]' : this.get("aspect_ids"), + photos : this.photos.pluck("id"), services : mungeServices(this.get("services")) } diff --git a/public/javascripts/app/templates/picture-form.handlebars b/public/javascripts/app/templates/picture-form.handlebars index f7f6f4a5a..d48d10a7b 100644 --- a/public/javascripts/app/templates/picture-form.handlebars +++ b/public/javascripts/app/templates/picture-form.handlebars @@ -3,7 +3,7 @@
+
- + - diff --git a/public/javascripts/rails.js b/public/javascripts/rails.js index 028b0fc62..06b4e0b53 100644 --- a/public/javascripts/rails.js +++ b/public/javascripts/rails.js @@ -139,7 +139,6 @@ return rails.fire(element, 'ajax:beforeSend', [xhr, settings]); }, success: function(data, status, xhr) { - alert("hella boner jamz") element.trigger('ajax:success', [data, status, xhr]); }, complete: function(xhr, status) { diff --git a/spec/javascripts/app/forms/picture_form_spec.js b/spec/javascripts/app/forms/picture_form_spec.js new file mode 100644 index 000000000..5890b89f1 --- /dev/null +++ b/spec/javascripts/app/forms/picture_form_spec.js @@ -0,0 +1,43 @@ +describe("app.forms.Picture", function(){ + beforeEach(function(){ + $("", { + "name" : "csrf-token", + "content" : "supersecrettokenlol" + }).prependTo("head") + + this.form = new app.forms.Picture().render() + }) + + it("sets the authenticity token from the meta tag", function(){ + expect(this.form.$("input[name='authenticity_token']").val()).toBe("supersecrettokenlol") + }) + + describe("when a photo is suceessfully submitted", function(){ + beforeEach(function(){ + this.photoAttrs = { name : "Obama rides a bicycle" } + this.respond = function() { + this.form.$(".new_photo").trigger("ajax:complete", { + responseText : JSON.stringify({success : true, data : this.photoAttrs}) + }) + } + }) + + it("adds a new model to the photos", function(){ + expect(this.form.$(".photos div").length).toBe(0); + this.respond() + expect(this.form.$(".photos div").length).toBeGreaterThan(0); + }) + }) + + describe("when a photo is unsuccessfully submitted", function(){ + beforeEach(function(){ + this.response = {responseText : JSON.stringify({success : false, message : "I like to eat basketballs"}) } + }) + + it("adds a new model to the photos", function(){ + spyOn(window, "alert") + this.form.$(".new_photo").trigger("ajax:complete", this.response) + expect(window.alert).toHaveBeenCalled(); + }) + }) +}); \ No newline at end of file diff --git a/spec/javascripts/app/forms/post_form_spec.js b/spec/javascripts/app/forms/post_form_spec.js index d9b6ef7af..2fbb3591f 100644 --- a/spec/javascripts/app/forms/post_form_spec.js +++ b/spec/javascripts/app/forms/post_form_spec.js @@ -15,14 +15,14 @@ describe("app.forms.Post", function(){ this.view.$("form .aspect_ids").val("public") /* appending checkboxes */ - this.view.$("form").append($("", { + this.view.$(".new-post").append($("", { value : "fakeBook", checked : "checked", "class" : "service", "type" : "checkbox" })) - this.view.$("form").append($("", { + this.view.$(".new-post").append($("", { value : "twitter", checked : "checked", "class" : "service", @@ -31,7 +31,7 @@ describe("app.forms.Post", function(){ }) it("instantiates a post on form submit", function(){ - this.view.$("form").submit() + this.view.$(".new-post").submit() expect(this.view.model.get("text")).toBe("Oh My") expect(this.view.model.get("aspect_ids")).toBe("public") expect(this.view.model.get("services").length).toBe(2) @@ -40,7 +40,7 @@ describe("app.forms.Post", function(){ it("triggers a 'setFromForm' event", function(){ var spy = jasmine.createSpy(); this.view.model.bind("setFromForm", spy); - this.view.$("form").submit(); + this.view.$(".new-post").submit(); expect(spy).toHaveBeenCalled(); }) })