2015-10-11 10:41:23 +01:00
require 'rails_helper'
2013-02-09 10:33:07 -05:00
require 'post_revisor'
describe PostRevisor do
let ( :topic ) { Fabricate ( :topic ) }
2013-04-17 16:11:13 -07:00
let ( :newuser ) { Fabricate ( :newuser ) }
2015-05-29 20:08:39 +02:00
let ( :post_args ) { { user : newuser , topic : topic } }
2013-02-09 10:33:07 -05:00
2015-01-27 12:13:45 -05:00
context 'TopicChanges' do
let ( :tc ) {
topic . reload
PostRevisor :: TopicChanges . new ( topic , topic . user )
}
it 'provides a guardian' do
2015-04-25 11:18:35 -04:00
expect ( tc . guardian ) . to be_an_instance_of Guardian
2015-01-27 12:13:45 -05:00
end
it 'tracks changes properly' do
2015-04-25 11:18:35 -04:00
expect ( tc . diff ) . to eq ( { } )
2015-01-27 12:13:45 -05:00
# it remembers changes we tell it to
tc . record_change ( 'height' , '180cm' , '170cm' )
2015-04-25 11:18:35 -04:00
expect ( tc . diff [ 'height' ] ) . to eq ( [ '180cm' , '170cm' ] )
2015-01-27 12:13:45 -05:00
# it works with arrays of values
tc . record_change ( 'colors' , nil , [ 'red' , 'blue' ] )
2015-04-25 11:18:35 -04:00
expect ( tc . diff [ 'colors' ] ) . to eq ( [ nil , [ 'red' , 'blue' ] ] )
2015-01-27 12:13:45 -05:00
# it does not record changes to the same val
tc . record_change ( 'wat' , 'js' , 'js' )
2015-04-25 11:18:35 -04:00
expect ( tc . diff [ 'wat' ] ) . to be_nil
2015-01-27 12:13:45 -05:00
tc . record_change ( 'tags' , [ 'a' , 'b' ] , [ 'a' , 'b' ] )
2015-04-25 11:18:35 -04:00
expect ( tc . diff [ 'tags' ] ) . to be_nil
2015-01-27 12:13:45 -05:00
end
end
2015-02-02 12:44:21 -05:00
context 'revise wiki' do
before do
# There used to be a bug where wiki changes were considered posting "too similar"
# so this is enabled and checked
$redis . delete_prefixed ( 'unique-post' )
SiteSetting . unique_posts_mins = 10
end
it 'allows the user to change it to a wiki' do
pc = PostCreator . new ( newuser , topic_id : topic . id , raw : 'this is a post that will become a wiki' )
post = pc . create
2015-04-25 11:18:35 -04:00
expect ( post . revise ( post . user , wiki : true ) ) . to be_truthy
2015-02-02 12:44:21 -05:00
post . reload
2015-04-25 11:18:35 -04:00
expect ( post . wiki ) . to be_truthy
2015-02-02 12:44:21 -05:00
end
end
2013-02-09 10:33:07 -05:00
context 'revise' do
let ( :post ) { Fabricate ( :post , post_args ) }
let ( :first_version_at ) { post . last_version_at }
subject { described_class . new ( post ) }
describe 'with the same body' do
2013-12-12 03:41:34 +01:00
it " doesn't change version " do
2015-01-09 13:34:37 -03:00
expect {
expect ( subject . revise! ( post . user , { raw : post . raw } ) ) . to eq ( false )
2014-06-16 12:13:28 +10:00
post . reload
2015-01-09 13:34:37 -03:00
} . not_to change ( post , :version )
2013-02-09 10:33:07 -05:00
end
end
describe 'ninja editing' do
2014-06-16 12:13:28 +10:00
it 'correctly applies edits' do
2015-11-24 14:28:42 -05:00
SiteSetting . stubs ( :editing_grace_period ) . returns ( 1 . minute )
2015-05-29 20:08:39 +02:00
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : 'updated body' } , revised_at : post . updated_at + 10 . seconds )
2013-02-09 10:33:07 -05:00
post . reload
2015-01-09 13:34:37 -03:00
expect ( post . version ) . to eq ( 1 )
expect ( post . public_version ) . to eq ( 1 )
expect ( post . revisions . size ) . to eq ( 0 )
expect ( post . last_version_at ) . to eq ( first_version_at )
expect ( subject . category_changed ) . to be_blank
2013-02-21 18:09:56 -05:00
end
2015-05-29 20:08:39 +02:00
it " doesn't create a new version " do
2015-11-24 14:28:42 -05:00
SiteSetting . stubs ( :editing_grace_period ) . returns ( 1 . minute )
2015-05-29 20:08:39 +02:00
# making a revision
2015-11-24 14:28:42 -05:00
subject . revise! ( post . user , { raw : 'updated body' } , revised_at : post . updated_at + SiteSetting . editing_grace_period + 1 . seconds )
2015-05-29 20:08:39 +02:00
# "roll back"
2015-11-24 14:28:42 -05:00
subject . revise! ( post . user , { raw : 'Hello world' } , revised_at : post . updated_at + SiteSetting . editing_grace_period + 2 . seconds )
2015-05-29 20:08:39 +02:00
post . reload
expect ( post . version ) . to eq ( 1 )
expect ( post . public_version ) . to eq ( 1 )
expect ( post . revisions . size ) . to eq ( 0 )
end
2013-02-09 10:33:07 -05:00
end
describe 'revision much later' do
let! ( :revised_at ) { post . updated_at + 2 . minutes }
before do
2015-11-24 14:28:42 -05:00
SiteSetting . stubs ( :editing_grace_period ) . returns ( 1 . minute . to_i )
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : 'updated body' } , revised_at : revised_at )
2013-02-09 10:33:07 -05:00
post . reload
end
2013-02-21 18:09:56 -05:00
it " doesn't update a category " do
2015-01-09 13:34:37 -03:00
expect ( subject . category_changed ) . to be_blank
2013-02-21 18:09:56 -05:00
end
2014-10-27 22:06:43 +01:00
it 'updates the versions' do
2015-01-09 13:34:37 -03:00
expect ( post . version ) . to eq ( 2 )
expect ( post . public_version ) . to eq ( 2 )
2013-02-09 10:33:07 -05:00
end
2014-10-27 22:06:43 +01:00
it 'creates a new revision' do
2015-01-09 13:34:37 -03:00
expect ( post . revisions . size ) . to eq ( 1 )
2013-02-09 10:33:07 -05:00
end
it " updates the last_version_at " do
2015-01-09 13:34:37 -03:00
expect ( post . last_version_at . to_i ) . to eq ( revised_at . to_i )
2013-02-09 10:33:07 -05:00
end
describe " new edit window " do
before do
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : 'yet another updated body' } , revised_at : revised_at )
2013-02-09 10:33:07 -05:00
post . reload
end
it " doesn't create a new version if you do another " do
2015-01-09 13:34:37 -03:00
expect ( post . version ) . to eq ( 2 )
expect ( post . public_version ) . to eq ( 2 )
2013-02-09 10:33:07 -05:00
end
it " doesn't change last_version_at " do
2015-01-09 13:34:37 -03:00
expect ( post . last_version_at . to_i ) . to eq ( revised_at . to_i )
2013-02-09 10:33:07 -05:00
end
2013-02-21 18:09:56 -05:00
it " doesn't update a category " do
2015-01-09 13:34:37 -03:00
expect ( subject . category_changed ) . to be_blank
2013-02-21 18:09:56 -05:00
end
2013-02-09 10:33:07 -05:00
context " after second window " do
let! ( :new_revised_at ) { revised_at + 2 . minutes }
before do
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : 'yet another, another updated body' } , revised_at : new_revised_at )
2013-02-09 10:33:07 -05:00
post . reload
end
it " does create a new version after the edit window " do
2015-01-09 13:34:37 -03:00
expect ( post . version ) . to eq ( 3 )
expect ( post . public_version ) . to eq ( 3 )
2013-02-09 10:33:07 -05:00
end
it " does create a new version after the edit window " do
2015-01-09 13:34:37 -03:00
expect ( post . last_version_at . to_i ) . to eq ( new_revised_at . to_i )
2013-02-09 10:33:07 -05:00
end
end
end
end
2013-02-21 18:09:56 -05:00
describe 'category topic' do
2013-02-25 19:42:20 +03:00
let! ( :category ) do
2013-02-21 18:09:56 -05:00
category = Fabricate ( :category )
category . update_column ( :topic_id , topic . id )
category
end
let ( :new_description ) { " this is my new description. " }
2014-09-25 17:44:48 +02:00
it " should have no description by default " do
2015-01-09 13:34:37 -03:00
expect ( category . description ) . to be_blank
2013-02-21 18:09:56 -05:00
end
context " one paragraph description " do
before do
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : new_description } )
2013-02-21 18:09:56 -05:00
category . reload
end
2014-09-25 17:44:48 +02:00
it " returns the changed category info " do
2015-01-09 13:34:37 -03:00
expect ( subject . category_changed ) . to eq ( category )
2013-02-21 18:09:56 -05:00
end
it " updates the description of the category " do
2015-01-09 13:34:37 -03:00
expect ( category . description ) . to eq ( new_description )
2013-02-21 18:09:56 -05:00
end
end
context " multiple paragraph description " do
before do
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : " #{ new_description } \n \n Other content goes here. " } )
2013-02-21 18:09:56 -05:00
category . reload
end
it " returns the changed category info " do
2015-01-09 13:34:37 -03:00
expect ( subject . category_changed ) . to eq ( category )
2013-02-21 18:09:56 -05:00
end
it " updates the description of the category " do
2015-01-09 13:34:37 -03:00
expect ( category . description ) . to eq ( new_description )
2013-02-25 19:42:20 +03:00
end
2013-02-21 18:09:56 -05:00
end
context 'when updating back to the original paragraph' do
before do
category . update_column ( :description , 'this is my description' )
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : Category . post_template } )
2013-02-21 18:09:56 -05:00
category . reload
end
it " puts the description back to nothing " do
2015-01-09 13:34:37 -03:00
expect ( category . description ) . to be_blank
2013-02-21 18:09:56 -05:00
end
2014-09-25 17:44:48 +02:00
it " returns the changed category info " do
2015-01-09 13:34:37 -03:00
expect ( subject . category_changed ) . to eq ( category )
2013-02-21 18:09:56 -05:00
end
end
end
2013-02-09 10:33:07 -05:00
describe 'rate limiter' do
let ( :changed_by ) { Fabricate ( :coding_horror ) }
it " triggers a rate limiter " do
EditRateLimiter . any_instance . expects ( :performed! )
2014-10-27 22:06:43 +01:00
subject . revise! ( changed_by , { raw : 'updated body' } )
2013-02-09 10:33:07 -05:00
end
end
2013-04-17 16:11:13 -07:00
describe " admin editing a new user's post " do
2013-04-05 13:59:00 -04:00
let ( :changed_by ) { Fabricate ( :admin ) }
before do
2013-10-24 14:55:55 +11:00
SiteSetting . stubs ( :newuser_max_images ) . returns ( 0 )
2014-01-27 15:09:09 -05:00
url = " http://i.imgur.com/wfn7rgU.jpg "
Oneboxer . stubs ( :onebox ) . with ( url , anything ) . returns ( " <img src=' #{ url } '> " )
2014-10-27 22:06:43 +01:00
subject . revise! ( changed_by , { raw : " So, post them here! \n #{ url } " } )
2013-04-05 13:59:00 -04:00
end
2013-04-17 16:11:13 -07:00
it " allows an admin to insert images into a new user's post " do
2015-01-09 13:34:37 -03:00
expect ( post . errors ) . to be_blank
2013-04-05 13:59:00 -04:00
end
2013-11-06 11:43:40 +01:00
it " marks the admin as the last updater " do
2015-01-09 13:34:37 -03:00
expect ( post . last_editor_id ) . to eq ( changed_by . id )
2013-11-06 11:43:40 +01:00
end
2013-04-05 13:59:00 -04:00
end
2013-04-17 16:11:13 -07:00
describe " new user editing their own post " do
2013-04-05 13:59:00 -04:00
before do
2013-10-24 14:55:55 +11:00
SiteSetting . stubs ( :newuser_max_images ) . returns ( 0 )
url = " http://i.imgur.com/FGg7Vzu.gif "
2014-03-18 15:22:39 +11:00
Oneboxer . stubs ( :cached_onebox ) . with ( url , anything ) . returns ( " <img src=' #{ url } '> " )
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : " So, post them here! \n #{ url } " } )
2013-04-05 13:59:00 -04:00
end
2014-01-27 15:09:09 -05:00
it " doesn't allow images to be inserted " do
2015-01-09 13:34:37 -03:00
expect ( post . errors ) . to be_present
2013-04-05 13:59:00 -04:00
end
end
2013-02-09 10:33:07 -05:00
describe 'with a new body' do
let ( :changed_by ) { Fabricate ( :coding_horror ) }
2016-01-11 11:16:23 +01:00
let! ( :result ) { subject . revise! ( changed_by , { raw : " lets update the body. Здравствуйте " } ) }
2013-02-09 10:33:07 -05:00
it 'returns true' do
2015-01-09 13:34:37 -03:00
expect ( result ) . to eq ( true )
2013-02-09 10:33:07 -05:00
end
it 'updates the body' do
2016-01-11 11:16:23 +01:00
expect ( post . raw ) . to eq ( " lets update the body. Здравствуйте " )
2013-02-09 10:33:07 -05:00
end
it 'sets the invalidate oneboxes attribute' do
2015-01-09 13:34:37 -03:00
expect ( post . invalidate_oneboxes ) . to eq ( true )
2013-02-09 10:33:07 -05:00
end
2014-10-27 22:06:43 +01:00
it 'increased the versions' do
2015-01-09 13:34:37 -03:00
expect ( post . version ) . to eq ( 2 )
expect ( post . public_version ) . to eq ( 2 )
2013-02-09 10:33:07 -05:00
end
2013-12-12 03:41:34 +01:00
it 'has the new revision' do
2015-01-09 13:34:37 -03:00
expect ( post . revisions . size ) . to eq ( 1 )
2013-02-09 10:33:07 -05:00
end
2013-12-12 03:41:34 +01:00
it " saved the user who made the change in the revisions " do
2015-01-09 13:34:37 -03:00
expect ( post . revisions . first . user_id ) . to eq ( changed_by . id )
2013-02-09 10:33:07 -05:00
end
2013-12-10 13:47:07 -05:00
it " updates the word count " do
2016-01-11 11:16:23 +01:00
expect ( post . word_count ) . to eq ( 5 )
2013-12-10 13:47:07 -05:00
post . topic . reload
2016-01-11 11:16:23 +01:00
expect ( post . topic . word_count ) . to eq ( 5 )
2013-12-10 13:47:07 -05:00
end
2013-02-09 10:33:07 -05:00
context 'second poster posts again quickly' do
before do
2015-11-24 14:28:42 -05:00
SiteSetting . stubs ( :editing_grace_period ) . returns ( 1 . minute . to_i )
2014-10-27 22:06:43 +01:00
subject . revise! ( changed_by , { raw : 'yet another updated body' } , revised_at : post . updated_at + 10 . seconds )
2013-02-09 10:33:07 -05:00
post . reload
end
it 'is a ninja edit, because the second poster posted again quickly' do
2015-01-09 13:34:37 -03:00
expect ( post . version ) . to eq ( 2 )
expect ( post . public_version ) . to eq ( 2 )
expect ( post . revisions . size ) . to eq ( 1 )
2013-02-09 10:33:07 -05:00
end
end
2016-08-20 00:57:12 +05:30
context 'passing skip_revision as true' do
before do
SiteSetting . stubs ( :editing_grace_period ) . returns ( 1 . minute . to_i )
subject . revise! ( changed_by , { raw : 'yet another updated body' } , { revised_at : post . updated_at + 10 . hours , skip_revision : true } )
post . reload
end
it 'does not create new revision ' do
expect ( post . version ) . to eq ( 2 )
expect ( post . public_version ) . to eq ( 2 )
expect ( post . revisions . size ) . to eq ( 1 )
end
end
2013-02-09 10:33:07 -05:00
end
2014-03-18 13:40:40 -04:00
describe " topic excerpt " do
it " topic excerpt is updated only if first post is revised " do
revisor = described_class . new ( post )
first_post = topic . posts . by_post_number . first
expect {
2014-10-27 22:06:43 +01:00
revisor . revise! ( first_post . user , { raw : 'Edit the first post' } , revised_at : first_post . updated_at + 10 . seconds )
2014-03-18 13:40:40 -04:00
topic . reload
} . to change { topic . excerpt }
second_post = Fabricate ( :post , post_args . merge ( post_number : 2 , topic_id : topic . id ) )
expect {
2014-10-27 22:06:43 +01:00
described_class . new ( second_post ) . revise! ( second_post . user , { raw : 'Edit the 2nd post' } )
2014-03-18 13:40:40 -04:00
topic . reload
} . to_not change { topic . excerpt }
end
end
2014-09-02 01:18:06 +02:00
it " doesn't strip starting whitespaces " do
2014-10-27 22:06:43 +01:00
subject . revise! ( post . user , { raw : " <-- whitespaces --> " } )
2014-09-02 01:18:06 +02:00
post . reload
2015-01-09 13:34:37 -03:00
expect ( post . raw ) . to eq ( " <-- whitespaces --> " )
2014-09-02 01:18:06 +02:00
end
2016-04-07 22:29:01 +08:00
context " # publish_changes " do
let! ( :post ) { Fabricate ( :post , topic_id : topic . id ) }
it " should publish topic changes to clients " do
revisor = described_class . new ( topic . ordered_posts . first , topic )
messages = MessageBus . track_publish do
revisor . revise! ( newuser , { title : 'this is a test topic' } )
end
2016-06-08 16:08:41 -04:00
message = messages . find { | m | m . channel == " /topic/ #{ topic . id } " }
2016-04-07 22:29:01 +08:00
payload = message . data
expect ( payload [ :reload_topic ] ) . to eq ( true )
end
end
2016-05-04 14:02:47 -04:00
context " tagging " do
context " tagging disabled " do
before do
SiteSetting . tagging_enabled = false
end
it " doesn't add the tags " do
result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags : [ 'totally' , 'update' ] } )
expect ( result ) . to eq ( true )
post . reload
expect ( post . topic . tags . size ) . to eq ( 0 )
end
end
context " tagging enabled " do
before do
SiteSetting . tagging_enabled = true
end
context " can create tags " do
before do
SiteSetting . min_trust_to_create_tag = 0
SiteSetting . min_trust_level_to_tag_topics = 0
end
it " can create all tags if none exist " do
expect {
@result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags : [ 'totally' , 'update' ] } )
} . to change { Tag . count } . by ( 2 )
expect ( @result ) . to eq ( true )
post . reload
expect ( post . topic . tags . map ( & :name ) . sort ) . to eq ( [ 'totally' , 'update' ] )
end
it " creates missing tags if some exist " do
Fabricate ( :tag , name : 'totally' )
expect {
@result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags : [ 'totally' , 'update' ] } )
} . to change { Tag . count } . by ( 1 )
expect ( @result ) . to eq ( true )
post . reload
expect ( post . topic . tags . map ( & :name ) . sort ) . to eq ( [ 'totally' , 'update' ] )
end
it " can remove all tags " do
topic . tags = [ Fabricate ( :tag , name : " super " ) , Fabricate ( :tag , name : " stuff " ) ]
result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags : [ ] } )
expect ( result ) . to eq ( true )
post . reload
expect ( post . topic . tags . size ) . to eq ( 0 )
end
2016-06-09 12:04:34 -04:00
it " can remove all tags using tags_empty_array " do
topic . tags = [ Fabricate ( :tag , name : " stuff " ) ]
result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags_empty_array : " true " } )
expect ( result ) . to eq ( true )
post . reload
expect ( post . topic . tags . size ) . to eq ( 0 )
end
2016-05-04 14:02:47 -04:00
it " can't add staff-only tags " do
SiteSetting . staff_tags = " important "
result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags : [ 'important' , 'stuff' ] } )
expect ( result ) . to eq ( false )
expect ( post . topic . errors . present? ) . to eq ( true )
end
it " staff can add staff-only tags " do
SiteSetting . staff_tags = " important "
result = subject . revise! ( Fabricate ( :admin ) , { raw : " lets totally update the body " , tags : [ 'important' , 'stuff' ] } )
expect ( result ) . to eq ( true )
post . reload
expect ( post . topic . tags . map ( & :name ) . sort ) . to eq ( [ 'important' , 'stuff' ] )
end
context " with staff-only tags " do
before do
SiteSetting . staff_tags = " important "
topic = post . topic
topic . tags = [ Fabricate ( :tag , name : " super " ) , Fabricate ( :tag , name : " important " ) , Fabricate ( :tag , name : " stuff " ) ]
end
it " staff-only tags can't be removed " do
result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags : [ 'stuff' ] } )
expect ( result ) . to eq ( false )
expect ( post . topic . errors . present? ) . to eq ( true )
post . reload
expect ( post . topic . tags . map ( & :name ) . sort ) . to eq ( [ 'important' , 'stuff' , 'super' ] )
end
it " can't remove all tags if some are staff-only " do
result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags : [ ] } )
expect ( result ) . to eq ( false )
expect ( post . topic . errors . present? ) . to eq ( true )
post . reload
expect ( post . topic . tags . map ( & :name ) . sort ) . to eq ( [ 'important' , 'stuff' , 'super' ] )
end
it " staff-only tags can be removed by staff " do
result = subject . revise! ( Fabricate ( :admin ) , { raw : " lets totally update the body " , tags : [ 'stuff' ] } )
expect ( result ) . to eq ( true )
post . reload
expect ( post . topic . tags . map ( & :name ) ) . to eq ( [ 'stuff' ] )
end
it " staff can remove all tags " do
result = subject . revise! ( Fabricate ( :admin ) , { raw : " lets totally update the body " , tags : [ ] } )
expect ( result ) . to eq ( true )
post . reload
expect ( post . topic . tags . size ) . to eq ( 0 )
end
end
end
context " cannot create tags " do
before do
SiteSetting . min_trust_to_create_tag = 4
SiteSetting . min_trust_level_to_tag_topics = 0
end
it " only uses existing tags " do
Fabricate ( :tag , name : 'totally' )
expect {
@result = subject . revise! ( Fabricate ( :user ) , { raw : " lets totally update the body " , tags : [ 'totally' , 'update' ] } )
} . to_not change { Tag . count }
expect ( @result ) . to eq ( true )
post . reload
expect ( post . topic . tags . map ( & :name ) ) . to eq ( [ 'totally' ] )
end
end
end
end
2013-02-09 10:33:07 -05:00
end
end