cucumber for comment retractions, modified views
This commit is contained in:
parent
fef226156c
commit
aed190dc6d
16 changed files with 159 additions and 71 deletions
|
|
@ -34,7 +34,7 @@ class CommentsController < ApplicationController
|
||||||
render(:json => json, :status => 201)
|
render(:json => json, :status => 201)
|
||||||
}
|
}
|
||||||
format.html{ render :nothing => true, :status => 201 }
|
format.html{ render :nothing => true, :status => 201 }
|
||||||
format.mobile{ redirect_to status_message_path(@comment.post_id) }
|
format.mobile{ redirect_to @comment.post }
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
render :nothing => true, :status => 422
|
render :nothing => true, :status => 422
|
||||||
|
|
@ -44,4 +44,23 @@ class CommentsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if @comment = Comment.where(:id => params[:id]).first
|
||||||
|
if current_user.owns?(@comment) || current_user.owns?(@comment.parent)
|
||||||
|
current_user.retract(@comment)
|
||||||
|
respond_to do |format|
|
||||||
|
format.mobile{ redirect_to @comment.post }
|
||||||
|
format.js {render :nothing => true, :status => 204}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
respond_to do |format|
|
||||||
|
format.mobile {redirect_to :back}
|
||||||
|
format.js {render :nothing => true, :status => 401}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
render :nothing => true, :status => 404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ module SocketsHelper
|
||||||
v = render_to_string(:partial => 'people/person', :locals => person_hash)
|
v = render_to_string(:partial => 'people/person', :locals => person_hash)
|
||||||
|
|
||||||
elsif object.is_a? Comment
|
elsif object.is_a? Comment
|
||||||
v = render_to_string(:partial => 'comments/comment', :locals => {:comment => object, :person => object.author})
|
v = render_to_string(:partial => 'comments/comment', :locals => {:comment => object, :person => object.author, :current_user => user})
|
||||||
|
|
||||||
elsif object.is_a? Like
|
elsif object.is_a? Like
|
||||||
v = render_to_string(:partial => 'likes/likes', :locals => {:likes => object.post.likes, :dislikes => object.post.dislikes})
|
v = render_to_string(:partial => 'likes/likes', :locals => {:likes => object.post.likes, :dislikes => object.post.dislikes})
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ class RelayableRetraction
|
||||||
include Diaspora::Webhooks
|
include Diaspora::Webhooks
|
||||||
include Diaspora::Encryptable
|
include Diaspora::Encryptable
|
||||||
|
|
||||||
|
xml_name :relayable_retraction
|
||||||
xml_attr :target_guid
|
xml_attr :target_guid
|
||||||
xml_attr :target_type
|
xml_attr :target_type
|
||||||
xml_attr :sender_handle
|
xml_attr :sender_handle
|
||||||
|
|
@ -37,6 +38,10 @@ class RelayableRetraction
|
||||||
@sender.diaspora_handle
|
@sender.diaspora_handle
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def diaspora_handle
|
||||||
|
self.sender_handle
|
||||||
|
end
|
||||||
|
|
||||||
def subscribers(user)
|
def subscribers(user)
|
||||||
self.target.subscribers(user)
|
self.target.subscribers(user)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@
|
||||||
-# the COPYRIGHT file.
|
-# the COPYRIGHT file.
|
||||||
|
|
||||||
%li.comment.posted{:data=>{:guid => comment.id}, :class => ("hidden" if(defined? hidden))}
|
%li.comment.posted{:data=>{:guid => comment.id}, :class => ("hidden" if(defined? hidden))}
|
||||||
|
- if current_user.owns?(comment) || current_user.owns?(comment.post)
|
||||||
|
.right.controls
|
||||||
|
= link_to image_tag('deletelabel.png'), comment_path(comment), :confirm => t('are_you_sure'), :method => :delete, :remote => true, :class => "delete comment_delete", :title => t('delete')
|
||||||
= person_image_link(comment.author)
|
= person_image_link(comment.author)
|
||||||
.content
|
.content
|
||||||
.from
|
.from
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
.right
|
.right
|
||||||
%span.time
|
%span.time
|
||||||
= comment.created_at ? time_ago_in_words(comment.created_at) : time_ago_in_words(Time.now)
|
= comment.created_at ? time_ago_in_words(comment.created_at) : time_ago_in_words(Time.now)
|
||||||
|
.controls
|
||||||
|
= link_to image_tag('deletelabel.png'), comment, :confirm => t('are_you_sure'), :method => :delete, :class => "delete comment_delete", :title => t('delete')
|
||||||
|
|
||||||
|
|
||||||
= person_image_link(comment.author)
|
= person_image_link(comment.author)
|
||||||
.content
|
.content
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
-# licensed under the Affero General Public License version 3 or later. See
|
-# licensed under the Affero General Public License version 3 or later. See
|
||||||
-# the COPYRIGHT file.
|
-# the COPYRIGHT file.
|
||||||
|
|
||||||
= form_tag( comments_path, :id => "new_comment_on_#{post_id}", :class => 'new_comment', :remote => true) do
|
= form_tag( comments_path, :id => "new_comment_on_#{post_id}", :class => 'new_comment') do
|
||||||
= hidden_field_tag :post_id, post_id, :id => "post_id_on_#{post_id}"
|
= hidden_field_tag :post_id, post_id, :id => "post_id_on_#{post_id}"
|
||||||
= text_area_tag :text, nil, :rows => 2, :class => "comment_box",:id => "comment_text_on_#{post_id}"
|
= text_area_tag :text, nil, :rows => 2, :class => "comment_box",:id => "comment_text_on_#{post_id}"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
|
|
||||||
.stream_element{:data=>{:guid=>post.id}}
|
.stream_element{:data=>{:guid=>post.id}}
|
||||||
- if current_user && post.author.owner_id == current_user.id
|
- if current_user && post.author.owner_id == current_user.id
|
||||||
.right.hidden.controls
|
.right.controls
|
||||||
- reshare_aspects = aspects_without_post(all_aspects, post)
|
- reshare_aspects = aspects_without_post(all_aspects, post)
|
||||||
- unless reshare_aspects.empty?
|
- unless reshare_aspects.empty?
|
||||||
= render 'shared/reshare', :aspects => reshare_aspects, :post => post
|
= render 'shared/reshare', :aspects => reshare_aspects, :post => post
|
||||||
= link_to image_tag('deletelabel.png'), status_message_path(post), :confirm => t('are_you_sure'), :method => :delete, :remote => true, :class => "delete", :title => t('delete')
|
= link_to image_tag('deletelabel.png'), status_message_path(post), :confirm => t('are_you_sure'), :method => :delete, :remote => true, :class => "delete stream_element_delete", :title => t('delete')
|
||||||
|
|
||||||
= person_image_link(post.author, :size => :thumb_small)
|
= person_image_link(post.author, :size => :thumb_small)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
Diaspora::Application.routes.draw do
|
Diaspora::Application.routes.draw do
|
||||||
resources :status_messages, :only => [:new, :create, :destroy, :show]
|
resources :status_messages, :only => [:new, :create, :destroy, :show]
|
||||||
resources :comments, :only => [:create]
|
resources :comments, :only => [:create, :destroy]
|
||||||
resources :requests, :only => [:destroy, :create]
|
resources :requests, :only => [:destroy, :create]
|
||||||
resource :likes, :only => [:create]
|
resource :likes, :only => [:create]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,3 +47,17 @@ Feature: commenting
|
||||||
And I press "comment"
|
And I press "comment"
|
||||||
Then I should see "hahaha" within "li.comment div.content"
|
Then I should see "hahaha" within "li.comment div.content"
|
||||||
And I should see "less than a minute ago" within "li.comment time"
|
And I should see "less than a minute ago" within "li.comment time"
|
||||||
|
|
||||||
|
Scenario: delete a post
|
||||||
|
When I sign in as "bob@bob.bob"
|
||||||
|
And I am on "alice@alice.alice"'s page
|
||||||
|
Then I should see "Look at this dog"
|
||||||
|
When I focus the comment field
|
||||||
|
And I fill in "comment" with "is that a poodle?"
|
||||||
|
And I press "comment"
|
||||||
|
And I wait for the ajax to finish
|
||||||
|
When I hover over the comment
|
||||||
|
And I preemptively confirm the alert
|
||||||
|
And I click to delete the first comment
|
||||||
|
And I wait for the ajax to finish
|
||||||
|
Then I should not see "is that a poodle?"
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,12 @@ Feature: posting
|
||||||
Given I expand the publisher
|
Given I expand the publisher
|
||||||
When I fill in "status_message_fake_text" with "I am eating a yogurt"
|
When I fill in "status_message_fake_text" with "I am eating a yogurt"
|
||||||
And I press "Share"
|
And I press "Share"
|
||||||
|
And I wait for the ajax to finish
|
||||||
And I follow "All aspects"
|
And I follow "All aspects"
|
||||||
And I hover over the post
|
And I hover over the post
|
||||||
And I preemptively confirm the alert
|
And I preemptively confirm the alert
|
||||||
And I click to delete the first post
|
And I click to delete the first post
|
||||||
|
And I wait for the ajax to finish
|
||||||
And I follow "All aspects"
|
And I follow "All aspects"
|
||||||
Then I should not see "I am eating a yogurt"
|
Then I should not see "I am eating a yogurt"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,21 @@ When /^I append "([^"]*)" to the publisher$/ do |stuff|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
And /^I hover over the post$/ do
|
And /^I hover over the (\w*)$/ do |element|
|
||||||
page.execute_script('$(".stream_element").first().mouseover()')
|
if element == 'post'
|
||||||
|
name = 'stream_element'
|
||||||
|
elsif element == 'comment'
|
||||||
|
name = 'comment.posted'
|
||||||
|
end
|
||||||
|
page.execute_script("$(\".#{name}\").first().mouseover()")
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I click to delete the first post$/ do
|
When /^I click to delete the first post$/ do
|
||||||
page.execute_script('$(".stream_element").first().find(".delete").click()')
|
page.execute_script('$(".stream_element").first().find(".stream_element_delete").click()')
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I click to delete the first comment$/ do
|
||||||
|
page.execute_script('$(".comment.posted").first().find(".comment_delete").click()')
|
||||||
end
|
end
|
||||||
|
|
||||||
And /^I click "([^"]*)" button$/ do |arg1|
|
And /^I click "([^"]*)" button$/ do |arg1|
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,24 @@ var Stream = {
|
||||||
Diaspora.widgets.alert.alert('Failed to post message!');
|
Diaspora.widgets.alert.alert('Failed to post message!');
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".stream").find(".delete").live('ajax:success', function(data, html, xhr) {
|
$(".stream").find(".stream_element_delete", ".stream_element").live('ajax:success', function(data, html, xhr) {
|
||||||
$(this).parents(".stream_element").hide('blind', { direction: 'vertical' }, 300);
|
var target = $(this).parents(".stream_element");
|
||||||
|
target.hide('blind', { direction: 'vertical' }, 300, function(){ $(this).remove() });
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".stream").find(".comment_delete", ".comment").live('ajax:success', function(data, html, xhr) {
|
||||||
|
var element = $(this),
|
||||||
|
target = element.parents(".comment"),
|
||||||
|
post = element.closest('.stream_element'),
|
||||||
|
toggler = post.find('.show_post_comments');
|
||||||
|
|
||||||
|
target.hide('blind', { direction: 'vertical' }, 300, function(){
|
||||||
|
$(this).remove();
|
||||||
|
toggler.html(
|
||||||
|
toggler.html().replace(/\d+/,$('.comments', post).find('li').length -1)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@ var WebSocketReceiver = {
|
||||||
var post = $("*[data-guid='"+postId+"']'"),
|
var post = $("*[data-guid='"+postId+"']'"),
|
||||||
prevComments = $('.comment.posted', post);
|
prevComments = $('.comment.posted', post);
|
||||||
|
|
||||||
|
|
||||||
if(prevComments.length > 0) {
|
if(prevComments.length > 0) {
|
||||||
prevComments.last().after(
|
prevComments.last().after(
|
||||||
$(html).fadeIn("fast", function(){})
|
$(html).fadeIn("fast", function(){})
|
||||||
|
|
|
||||||
|
|
@ -249,13 +249,6 @@ header
|
||||||
:bottom 1px solid #ddd
|
:bottom 1px solid #ddd
|
||||||
:top 1px solid #fff
|
:top 1px solid #fff
|
||||||
|
|
||||||
&:hover
|
|
||||||
.right
|
|
||||||
:display inline
|
|
||||||
.from
|
|
||||||
a
|
|
||||||
:color $blue
|
|
||||||
|
|
||||||
.youtube-player, .vimeo-player
|
.youtube-player, .vimeo-player
|
||||||
:border none
|
:border none
|
||||||
:height 370px
|
:height 370px
|
||||||
|
|
@ -398,7 +391,6 @@ header
|
||||||
:margin
|
:margin
|
||||||
:top -1px
|
:top -1px
|
||||||
|
|
||||||
|
|
||||||
.delete
|
.delete
|
||||||
@include opacity(0.6)
|
@include opacity(0.6)
|
||||||
:padding 5px
|
:padding 5px
|
||||||
|
|
@ -406,6 +398,27 @@ header
|
||||||
&:hover
|
&:hover
|
||||||
@include opacity(1)
|
@include opacity(1)
|
||||||
|
|
||||||
|
.right
|
||||||
|
:position absolute
|
||||||
|
:right 12px
|
||||||
|
|
||||||
|
.controls
|
||||||
|
:display none
|
||||||
|
:z-index 6
|
||||||
|
:color #999
|
||||||
|
a
|
||||||
|
:color #999
|
||||||
|
:font
|
||||||
|
:weight normal
|
||||||
|
|
||||||
|
&:hover, .comment:hover
|
||||||
|
> .controls
|
||||||
|
:display inline
|
||||||
|
|
||||||
|
.from
|
||||||
|
a
|
||||||
|
:color $blue
|
||||||
|
|
||||||
.time,
|
.time,
|
||||||
.timeago
|
.timeago
|
||||||
:color #999
|
:color #999
|
||||||
|
|
@ -595,6 +608,9 @@ div.dislikes
|
||||||
a
|
a
|
||||||
:color #444
|
:color #444
|
||||||
|
|
||||||
|
.right
|
||||||
|
:right 4px
|
||||||
|
|
||||||
form
|
form
|
||||||
:margin
|
:margin
|
||||||
:top -5px
|
:top -5px
|
||||||
|
|
@ -635,9 +651,6 @@ div.dislikes
|
||||||
:min-height 2.4em
|
:min-height 2.4em
|
||||||
|
|
||||||
.comments
|
.comments
|
||||||
time
|
|
||||||
:margin
|
|
||||||
:right -15px
|
|
||||||
.timeago
|
.timeago
|
||||||
:color #999
|
:color #999
|
||||||
|
|
||||||
|
|
@ -691,32 +704,6 @@ a.paginate, #infscr-loading
|
||||||
#main_stream .pagination
|
#main_stream .pagination
|
||||||
:display none
|
:display none
|
||||||
|
|
||||||
.stream_element
|
|
||||||
.right
|
|
||||||
:position absolute
|
|
||||||
:right 12px
|
|
||||||
|
|
||||||
&.controls
|
|
||||||
:z-index 6
|
|
||||||
:background
|
|
||||||
:color $background
|
|
||||||
:font
|
|
||||||
:size 12px
|
|
||||||
:color #999
|
|
||||||
:padding
|
|
||||||
:left 100px
|
|
||||||
a
|
|
||||||
:color #999
|
|
||||||
:font
|
|
||||||
:weight normal
|
|
||||||
&:hover
|
|
||||||
.controls
|
|
||||||
:display inline
|
|
||||||
|
|
||||||
.stream_element:hover
|
|
||||||
.right
|
|
||||||
:display inline
|
|
||||||
|
|
||||||
.request_buttons
|
.request_buttons
|
||||||
:position absolute
|
:position absolute
|
||||||
:right 0
|
:right 0
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,11 @@ describe CommentsController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@user1 = alice
|
@aspect1 = alice.aspects.first
|
||||||
@user2 = bob
|
@aspect2 = bob.aspects.first
|
||||||
|
|
||||||
@aspect1 = @user1.aspects.first
|
@controller.stub(:current_user).and_return(alice)
|
||||||
@aspect2 = @user2.aspects.first
|
sign_in :user, alice
|
||||||
|
|
||||||
sign_in :user, @user1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#create' do
|
describe '#create' do
|
||||||
|
|
@ -24,7 +22,7 @@ describe CommentsController do
|
||||||
}
|
}
|
||||||
context "on my own post" do
|
context "on my own post" do
|
||||||
before do
|
before do
|
||||||
@post = @user1.post :status_message, :text => 'GIANTS', :to => @aspect1.id
|
@post = alice.post :status_message, :text => 'GIANTS', :to => @aspect1.id
|
||||||
end
|
end
|
||||||
it 'responds to format js' do
|
it 'responds to format js' do
|
||||||
post :create, comment_hash.merge(:format => 'js')
|
post :create, comment_hash.merge(:format => 'js')
|
||||||
|
|
@ -35,7 +33,7 @@ describe CommentsController do
|
||||||
|
|
||||||
context "on a post from a contact" do
|
context "on a post from a contact" do
|
||||||
before do
|
before do
|
||||||
@post = @user2.post :status_message, :text => 'GIANTS', :to => @aspect2.id
|
@post = bob.post :status_message, :text => 'GIANTS', :to => @aspect2.id
|
||||||
end
|
end
|
||||||
it 'comments' do
|
it 'comments' do
|
||||||
post :create, comment_hash
|
post :create, comment_hash
|
||||||
|
|
@ -45,10 +43,10 @@ describe CommentsController do
|
||||||
new_user = Factory.create(:user)
|
new_user = Factory.create(:user)
|
||||||
comment_hash[:author_id] = new_user.person.id.to_s
|
comment_hash[:author_id] = new_user.person.id.to_s
|
||||||
post :create, comment_hash
|
post :create, comment_hash
|
||||||
Comment.find_by_text(comment_hash[:text]).author_id.should == @user1.person.id
|
Comment.find_by_text(comment_hash[:text]).author_id.should == alice.person.id
|
||||||
end
|
end
|
||||||
it "doesn't overwrite id" do
|
it "doesn't overwrite id" do
|
||||||
old_comment = @user1.comment("hello", :on => @post)
|
old_comment = alice.comment("hello", :on => @post)
|
||||||
comment_hash[:id] = old_comment.id
|
comment_hash[:id] = old_comment.id
|
||||||
post :create, comment_hash
|
post :create, comment_hash
|
||||||
old_comment.reload.text.should == 'hello'
|
old_comment.reload.text.should == 'hello'
|
||||||
|
|
@ -59,10 +57,53 @@ describe CommentsController do
|
||||||
@post = eve.post :status_message, :text => 'GIANTS', :to => eve.aspects.first.id
|
@post = eve.post :status_message, :text => 'GIANTS', :to => eve.aspects.first.id
|
||||||
end
|
end
|
||||||
it 'posts no comment' do
|
it 'posts no comment' do
|
||||||
@user1.should_not_receive(:comment)
|
alice.should_not_receive(:comment)
|
||||||
post :create, comment_hash
|
post :create, comment_hash
|
||||||
response.code.should == '422'
|
response.code.should == '422'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#destroy' do
|
||||||
|
context 'your post' do
|
||||||
|
before do
|
||||||
|
@message = alice.post(:status_message, :text => "hey", :to => @aspect1.id)
|
||||||
|
@comment = alice.comment("hey", :on => @message)
|
||||||
|
@comment2 = bob.comment("hey", :on => @message)
|
||||||
|
@comment3 = eve.comment("hey", :on => @message)
|
||||||
|
end
|
||||||
|
it 'lets the user delete his comment' do
|
||||||
|
alice.should_receive(:retract).with(@comment)
|
||||||
|
delete :destroy, :format => "js", :id => @comment.id
|
||||||
|
response.status.should == 204
|
||||||
|
end
|
||||||
|
|
||||||
|
it "lets the user destroy other people's comments" do
|
||||||
|
alice.should_receive(:retract).with(@comment2)
|
||||||
|
delete :destroy, :format => "js", :id => @comment2.id
|
||||||
|
response.status.should == 204
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "another user's post" do
|
||||||
|
before do
|
||||||
|
@message = bob.post(:status_message, :text => "hey", :to => bob.aspects.first.id)
|
||||||
|
@comment = alice.comment("hey", :on => @message)
|
||||||
|
@comment2 = bob.comment("hey", :on => @message)
|
||||||
|
@comment3 = eve.comment("hey", :on => @message)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'let the user delete his comment' do
|
||||||
|
alice.should_receive(:retract).with(@comment)
|
||||||
|
delete :destroy, :format => "js", :id => @comment.id
|
||||||
|
response.status.should == 204
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not let the user destroy comments he does not own' do
|
||||||
|
alice.should_not_receive(:retract).with(@comment2)
|
||||||
|
delete :destroy, :format => "js", :id => @comment3.id
|
||||||
|
response.status.should == 401
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -44,14 +44,4 @@ describe Retraction do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'dispatching' do
|
|
||||||
it 'should dispatch a retraction on delete' do
|
|
||||||
Factory.create(:person)
|
|
||||||
m = mock()
|
|
||||||
m.should_receive(:post)
|
|
||||||
Postzord::Dispatch.should_receive(:new).with(instance_of(User), instance_of(Retraction)).and_return(m)
|
|
||||||
post.destroy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue