diff --git a/app/views/templates/_templates.haml b/app/views/templates/_templates.haml index 3c2f9e3a2..33292f5ea 100644 --- a/app/views/templates/_templates.haml +++ b/app/views/templates/_templates.haml @@ -5,6 +5,9 @@ %script{:id => "header-template", :type => 'text/template'} != File.read("#{Rails.root}/app/views/templates/header.ujs") +%script{:id => "feedback-template", :type => 'text/template'} + != File.read("#{Rails.root}/app/views/templates/feedback.ujs") + %script{:id => "stream-element-template", :type => 'text/template'} != File.read("#{Rails.root}/app/views/templates/stream_element.ujs") diff --git a/app/views/templates/feedback.ujs b/app/views/templates/feedback.ujs new file mode 100644 index 000000000..bded74e90 --- /dev/null +++ b/app/views/templates/feedback.ujs @@ -0,0 +1,13 @@ +
+ <% if(like) { %> + + Unlike + + <% } else { %> + + Like + + <% } %> + · +
+ diff --git a/app/views/templates/stream_element.ujs b/app/views/templates/stream_element.ujs index 1ad9f5991..aeb91c8e5 100644 --- a/app/views/templates/stream_element.ujs +++ b/app/views/templates/stream_element.ujs @@ -46,59 +46,7 @@ <% } %> -
- <% if(provider_display_name != null) { %> - - via <%= provider_display_name %> - - - - <% } %> - - - <%= public ? "Public" : "Limited" %> - - - - - <% if(user_like) { %> - - Unlike - - <% } else { %> - - Like - - <% } %> - · - - <% if(public && author.id != current_user.id) { %> - <% if(root) { - var rootGuid = root.guid; - } else { - var rootGuid = guid; - } %> - - Reshare - - · - <% } %> - - - Comment - -
- -
-
- <% if(likes_count > 0){ %> - Heart - - <%= likes_count %> like - - <% } %> -
-
- -
+
diff --git a/public/javascripts/app/views/feedback_view.js b/public/javascripts/app/views/feedback_view.js new file mode 100644 index 000000000..3b89fcf56 --- /dev/null +++ b/public/javascripts/app/views/feedback_view.js @@ -0,0 +1,30 @@ +App.Views.Feedback = App.Views.StreamObject.extend({ + template_name: "#feedback-template", + + events: { + "click .like_action": "toggleLike", + }, + + initialize : function() { + var user_like = this.model.get("user_like") + this.like = user_like && this.model.likes.get(user_like.id); + + this.model.likes.bind("change", this.render, this); + this.model.likes.bind("remove", this.render, this); + this.model.likes.bind("add", this.render, this); + }, + + presenter : function(){ + return _.extend(this.defaultPresenter, {like : this.like}); + }, + + toggleLike: function(evt) { + if(evt) { evt.preventDefault(); } + + if(this.like){ + this.like.destroy(); + } else { + this.like = this.model.likes.create(); + } + }, +}) diff --git a/public/javascripts/app/views/post_view.js b/public/javascripts/app/views/post_view.js index e2ecabe80..abc0ee614 100644 --- a/public/javascripts/app/views/post_view.js +++ b/public/javascripts/app/views/post_view.js @@ -6,7 +6,6 @@ App.Views.Post = App.Views.StreamObject.extend({ "click .focus_comment_textarea": "focusCommentTextarea", "click .shield a": "removeNsfwShield", "click .remove_post": "destroyModel", - "click .like_action": "toggleLike", "click .expand_likes": "expandLikes", "click .block_user": "blockUser" }, @@ -58,33 +57,6 @@ App.Views.Post = App.Views.StreamObject.extend({ return this; }, - toggleLike: function(evt) { - if(evt) { evt.preventDefault(); } - - var link = $(evt.target); - var post = this.model; - - if(link.hasClass('like')) { - var like = this.model.likes.create(); - if(like) { - this.model.set({ - user_like : like, - likes_count : post.get("likes_count") + 1 - }); - } - } else { - this.model.likes.get(link.data("id")).destroy({ - success : function(){ - post.set({ - user_like : null, - likes_count : post.get("likes_count") - 1 - }); - } - }); - } - - return this; - }, expandLikes: function(evt){ if(evt) { evt.preventDefault(); } diff --git a/public/javascripts/app/views/stream_object_view.js b/public/javascripts/app/views/stream_object_view.js index 4d6eb82f1..c8ec672bf 100644 --- a/public/javascripts/app/views/stream_object_view.js +++ b/public/javascripts/app/views/stream_object_view.js @@ -1,6 +1,5 @@ App.Views.StreamObject = Backbone.View.extend({ initialize: function(options) { - this.model = options.model; this.model.bind('remove', this.remove, this); this.model.bind('change', this.render, this); }, @@ -10,18 +9,22 @@ App.Views.StreamObject = Backbone.View.extend({ this.model.destroy(); }, - context : function(){ - var modelJson = this.model ? this.model.toJSON() : {} - return $.extend(modelJson, App.user()); + presenter : function(){ + return this.defaultPresenter() }, - renderTemplate : function(){ - this.template = _.template($(this.template_name).html()); - $(this.el).html(this.template(this.context())); - return this; + defaultPresenter : function(){ + var modelJson = this.model ? this.model.toJSON() : {} + return _.extend(modelJson, App.user()); }, render : function() { return this.renderTemplate() + }, + + renderTemplate : function(){ + this.template = _.template($(this.template_name).html()); + $(this.el).html(this.template(this.presenter())); + return this; } }); diff --git a/spec/controllers/jasmine_fixtures/stream_spec.rb b/spec/controllers/jasmine_fixtures/stream_spec.rb new file mode 100644 index 000000000..89a5f42b5 --- /dev/null +++ b/spec/controllers/jasmine_fixtures/stream_spec.rb @@ -0,0 +1,25 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require 'spec_helper' + +describe MultisController do + describe '#index' do + before do + sign_in :user, alice + end + + it 'generates the multti_stream_json fixture' do + alice.post(:status_message, :text => "hella infos yo!", :to => alice.aspects.first.id) + alice.post(:reshare, :root_guid => Factory(:status_message, :public => true).guid, :to => 'all') + post_to_be_liked = alice.post(:status_message, :text => "you're gonna love this.'", :to => alice.aspects.first.id) + + alice.like(1, :target => post_to_be_liked) + + get :index, :format => :json + response.should be_success + save_fixture(response.body, "multi_stream_json") + end + end +end diff --git a/spec/jasmine_fixtures/template_spec.rb b/spec/controllers/jasmine_fixtures/template_spec.rb similarity index 100% rename from spec/jasmine_fixtures/template_spec.rb rename to spec/controllers/jasmine_fixtures/template_spec.rb diff --git a/spec/javascripts/app/views/feedback_view_spec.js b/spec/javascripts/app/views/feedback_view_spec.js new file mode 100644 index 000000000..5bcbabc6e --- /dev/null +++ b/spec/javascripts/app/views/feedback_view_spec.js @@ -0,0 +1,71 @@ +describe("App.views.Feedback", function(){ + beforeEach(function(){ + window.current_user = App.user({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + + var posts = $.parseJSON(spec.readFixture("multi_stream_json"))["posts"]; + + this.post = new App.Models.Post(posts[2]); + this.view = new App.Views.Feedback({model: this.post}); + }); + + it("has a like from the post", function(){ + var like = this.post.likes.models[0]; + + expect(like).toBeDefined(); + expect(this.view.like).toBe(like); + }) + + it("rerends when the post is liked", function(){ + spyOn(this.view, "render") + this.post.likes.trigger("add"); + expect(this.view.render); + }) + + it("rerends when the post is unliked", function(){ + spyOn(this.view, "render") + this.view.like.trigger("destroy"); + expect(this.view.render); + }) + + describe(".render", function(){ + beforeEach(function(){ + this.link = function(){ return this.view.$(".like_action"); } + }) + + context("when the user likes the post", function(){ + beforeEach(function(){ + this.view.render(); + }) + + it("the like action should be 'Unlike'", function(){ + expect(this.link().text()).toContain('Unlike'); + }) + + it("destroys ths like when Unlike is clicked", function(){ + spyOn(this.view.like, "destroy") + this.link().click(); + expect(this.view.like.destroy).toHaveBeenCalled() + }); + + }) + + context("when the user doesn't yet like the post", function(){ + beforeEach(function(){ + this.view.like = null; + this.view.render(); + }) + + it("the like action should be 'Like'", function(){ + expect(this.link().text()).toContain('Like'); + }) + + it("likes the post when the link is clicked", function(){ + var like = { party : "time"} + spyOn(this.post.likes, "create").andReturn(like); + this.link().click() + expect(this.view.like).toBe(like); + }) + }) + }) +}) + diff --git a/spec/javascripts/app/views/header_view_spec.js b/spec/javascripts/app/views/header_view_spec.js index 70509b489..3a35cffb2 100644 --- a/spec/javascripts/app/views/header_view_spec.js +++ b/spec/javascripts/app/views/header_view_spec.js @@ -1,15 +1,10 @@ describe("App.Views.Header", function() { beforeEach(function() { // should be jasmine helper - window.current_user = App.user({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); spec.loadFixture("aspects_index"); - this.view = new App.Views.Header().render(); - - console.log(this.view); - }); describe("#toggleDropdown", function() { diff --git a/spec/javascripts/app/views/post_view_spec.js b/spec/javascripts/app/views/post_view_spec.js index 2ae8eb60b..11ff8f56c 100644 --- a/spec/javascripts/app/views/post_view_spec.js +++ b/spec/javascripts/app/views/post_view_spec.js @@ -6,7 +6,6 @@ describe("App.views.Post", function(){ window.current_user = App.user({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); var posts = $.parseJSON(spec.readFixture("multi_stream_json"))["posts"][0]; - spec.loadFixture("underscore_templates"); this.collection = new App.Collections.Stream(posts); this.statusMessage = this.collection.models[0]; @@ -51,32 +50,5 @@ describe("App.views.Post", function(){ expect(statusElement.find(".reshare_action").html()).toBeNull(); }) }) - - context("Like link", function(){ - beforeEach(function(){ - this.view = new App.Views.Post({model : this.statusMessage}) - this.link = function(){ return this.view.$(".like_action"); } - }) - - it("clicking 'Like' toggles appropriately", function(){ - this.statusMessage.set({user_like : null}); - this.view.render(); - - expect(this.link().text()).toContain('Like'); - this.link().click(); - expect(this.link().text()).toContain('Unlike'); - expect($(this.view.el).html()).toContain('1 like'); - }) - - it("clicking 'Unlike' toggles appropriately", function(){ - this.statusMessage.set({user_like : { id : 1 }}); - this.view.render(); - - expect(this.link().text()).toContain('Unlike'); - this.link().click(); - expect(this.link().text()).toContain('Like'); - expect($(this.view.el).html()).toNotContain('1 Like'); - }) - }) }) }) diff --git a/spec/javascripts/app/views/stream_view_spec.js b/spec/javascripts/app/views/stream_view_spec.js index b1fcda671..e36d1841e 100644 --- a/spec/javascripts/app/views/stream_view_spec.js +++ b/spec/javascripts/app/views/stream_view_spec.js @@ -6,7 +6,6 @@ describe("App.views.Stream", function(){ window.current_user = App.user({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); var posts = $.parseJSON(spec.readFixture("multi_stream_json"))["posts"]; - spec.loadFixture("underscore_templates"); this.collection = new App.Collections.Stream(posts); this.statusMessage = this.collection.models[0]; diff --git a/spec/javascripts/helpers/SpecHelper.js b/spec/javascripts/helpers/SpecHelper.js index ccb456878..547aeee4d 100644 --- a/spec/javascripts/helpers/SpecHelper.js +++ b/spec/javascripts/helpers/SpecHelper.js @@ -10,7 +10,8 @@ //}); beforeEach(function() { - $('#jasmine_content').empty(); + $('#jasmine_content').html(spec.readFixture("underscore_templates")); + // NOTE Commented (as well as in afterEach) to keep the listeners from rails.js alive. //spec.clearLiveEventBindings(); jasmine.Clock.useMock(); @@ -22,7 +23,7 @@ beforeEach(function() { self.directionDetector = self.instantiate("DirectionDetector"); }); }; - + var Page = Diaspora.Pages["TestPage"]; $.extend(Page.prototype, Diaspora.EventBroker.extend(Diaspora.BaseWidget)); @@ -97,6 +98,6 @@ spec.retrieveFixture = function(fixtureName) { return xhr.responseText; }; + spec.loadFixtureCount = 0; spec.cachedFixtures = {}; -