2013-02-05 13:16:51 -06:00
require 'spec_helper'
require 'post_creator'
2013-04-16 15:56:18 -05:00
require 'topic_subtype'
2013-02-05 13:16:51 -06:00
describe PostCreator do
2013-05-13 20:59:55 -05:00
before do
ActiveRecord :: Base . observers . enable :all
end
2013-02-05 13:16:51 -06:00
let ( :user ) { Fabricate ( :user ) }
2013-07-07 21:44:55 -05:00
context " new topic " do
2013-02-05 13:16:51 -06:00
let ( :category ) { Fabricate ( :category , user : user ) }
2013-03-18 13:45:05 -05:00
let ( :topic ) { Fabricate ( :topic , user : user ) }
2013-07-07 21:44:55 -05:00
let ( :basic_topic_params ) { { title : " hello world topic " , raw : " my name is fred " , archetype_id : 1 } }
let ( :image_sizes ) { { 'http://an.image.host/image.jpg' = > { " width " = > 111 , " height " = > 222 } } }
2013-02-05 13:16:51 -06:00
let ( :creator ) { PostCreator . new ( user , basic_topic_params ) }
2013-07-17 17:58:25 -05:00
let ( :creator_with_category ) { PostCreator . new ( user , basic_topic_params . merge ( category : category . id ) ) }
2013-07-07 21:44:55 -05:00
let ( :creator_with_meta_data ) { PostCreator . new ( user , basic_topic_params . merge ( meta_data : { hello : " world " } ) ) }
2013-02-05 13:16:51 -06:00
let ( :creator_with_image_sizes ) { PostCreator . new ( user , basic_topic_params . merge ( image_sizes : image_sizes ) ) }
2013-07-21 20:40:39 -05:00
it " can be created with auto tracking disabled " do
p = PostCreator . create ( user , basic_topic_params . merge ( auto_track : false ) )
2013-07-22 00:06:53 -05:00
# must be 0 otherwise it will think we read the topic which is clearly untrue
TopicUser . where ( user_id : p . user_id , topic_id : p . topic_id ) . count . should == 0
2013-07-21 20:40:39 -05:00
end
2013-07-07 21:44:55 -05:00
it " ensures the user can create the topic " do
2013-02-05 13:16:51 -06:00
Guardian . any_instance . expects ( :can_create? ) . with ( Topic , nil ) . returns ( false )
lambda { creator . create } . should raise_error ( Discourse :: InvalidAccess )
end
2013-06-07 11:36:37 -05:00
context " invalid title " do
let ( :creator_invalid_title ) { PostCreator . new ( user , basic_topic_params . merge ( title : 'a' ) ) }
it " has errors " do
creator_invalid_title . create
expect ( creator_invalid_title . errors ) . to be_present
end
end
2013-10-22 20:14:31 -05:00
context " invalid raw " do
let ( :creator_invalid_raw ) { PostCreator . new ( user , basic_topic_params . merge ( raw : '' ) ) }
it " has errors " do
creator_invalid_raw . create
expect ( creator_invalid_raw . errors ) . to be_present
end
end
2013-07-07 21:44:55 -05:00
context " success " do
2013-02-05 13:16:51 -06:00
2013-05-10 15:58:23 -05:00
it " doesn't return true for spam " do
creator . create
creator . spam? . should be_false
end
2013-07-07 21:44:55 -05:00
it " does not notify on system messages " do
admin = Fabricate ( :admin )
messages = MessageBus . track_publish do
p = PostCreator . create ( admin , basic_topic_params . merge ( post_type : Post . types [ :moderator_action ] ) )
PostCreator . create ( admin , basic_topic_params . merge ( topic_id : p . topic_id , post_type : Post . types [ :moderator_action ] ) )
end
# don't notify on system messages they introduce too much noise
channels = messages . map ( & :channel )
channels . find { | s | s =~ / unread / } . should be_nil
channels . find { | s | s =~ / new / } . should be_nil
end
it " generates the correct messages for a secure topic " do
2013-05-16 00:03:03 -05:00
admin = Fabricate ( :admin )
cat = Fabricate ( :category )
2013-07-13 20:24:16 -05:00
cat . set_permissions ( :admins = > :full )
2013-05-16 00:03:03 -05:00
cat . save
created_post = nil
reply = nil
messages = MessageBus . track_publish do
2013-07-17 17:58:25 -05:00
created_post = PostCreator . new ( admin , basic_topic_params . merge ( category : cat . id ) ) . create
2013-07-07 21:44:55 -05:00
reply = PostCreator . new ( admin , raw : " this is my test reply 123 testing " , topic_id : created_post . topic_id ) . create
2013-05-16 00:03:03 -05:00
end
2014-06-24 19:55:50 -05:00
# 2 for topic, one to notify of new topic another for tracking state
2013-06-03 02:07:44 -05:00
messages . map { | m | m . channel } . sort . should == [ " /new " ,
2013-05-16 00:03:03 -05:00
" /users/ #{ admin . username } " ,
" /users/ #{ admin . username } " ,
2013-06-03 02:07:44 -05:00
" /unread/ #{ admin . id } " ,
" /unread/ #{ admin . id } " ,
2014-06-24 19:55:50 -05:00
" /topic/ #{ created_post . topic_id } " ,
2013-06-03 02:07:44 -05:00
" /topic/ #{ created_post . topic_id } "
2013-05-16 00:03:03 -05:00
] . sort
admin_ids = [ Group [ :admins ] . id ]
2013-06-03 02:07:44 -05:00
messages . any? { | m | m . group_ids != admin_ids && m . user_ids != [ admin . id ] } . should be_false
2013-02-05 13:16:51 -06:00
end
2013-06-03 02:07:44 -05:00
it 'generates the correct messages for a normal topic' do
2013-05-16 00:03:03 -05:00
p = nil
messages = MessageBus . track_publish do
p = creator . create
end
2013-06-03 02:07:44 -05:00
latest = messages . find { | m | m . channel == " /new " }
2013-05-16 00:03:03 -05:00
latest . should_not be_nil
2013-06-03 02:07:44 -05:00
read = messages . find { | m | m . channel == " /unread/ #{ p . user_id } " }
read . should_not be_nil
2013-05-16 00:03:03 -05:00
user_action = messages . find { | m | m . channel == " /users/ #{ p . user . username } " }
user_action . should_not be_nil
2014-06-24 19:55:50 -05:00
messages . length . should == 4
2013-03-18 13:45:05 -05:00
end
2013-05-16 00:03:03 -05:00
it 'extracts links from the post' do
TopicLink . expects ( :extract_from ) . with ( instance_of ( Post ) )
2013-03-18 12:55:34 -05:00
creator . create
end
it 'queues up post processing job when saved' do
2013-05-16 00:03:03 -05:00
Jobs . expects ( :enqueue ) . with ( :feature_topic_users , has_key ( :topic_id ) )
2013-03-18 12:55:34 -05:00
Jobs . expects ( :enqueue ) . with ( :process_post , has_key ( :post_id ) )
2014-03-04 21:26:42 -06:00
Jobs . expects ( :enqueue ) . with ( :notify_mailing_list_subscribers , has_key ( :post_id ) )
2013-03-18 12:55:34 -05:00
creator . create
end
it 'passes the invalidate_oneboxes along to the job if present' do
Jobs . stubs ( :enqueue ) . with ( :feature_topic_users , has_key ( :topic_id ) )
2014-03-04 21:26:42 -06:00
Jobs . expects ( :enqueue ) . with ( :notify_mailing_list_subscribers , has_key ( :post_id ) )
2013-03-18 12:55:34 -05:00
Jobs . expects ( :enqueue ) . with ( :process_post , has_key ( :invalidate_oneboxes ) )
creator . opts [ :invalidate_oneboxes ] = true
creator . create
end
it 'passes the image_sizes along to the job if present' do
Jobs . stubs ( :enqueue ) . with ( :feature_topic_users , has_key ( :topic_id ) )
2014-03-04 21:26:42 -06:00
Jobs . expects ( :enqueue ) . with ( :notify_mailing_list_subscribers , has_key ( :post_id ) )
2013-03-18 12:55:34 -05:00
Jobs . expects ( :enqueue ) . with ( :process_post , has_key ( :image_sizes ) )
creator . opts [ :image_sizes ] = { 'http://an.image.host/image.jpg' = > { 'width' = > 17 , 'height' = > 31 } }
creator . create
end
2013-02-05 13:16:51 -06:00
it 'assigns a category when supplied' do
creator_with_category . create . topic . category . should == category
end
it 'adds meta data from the post' do
creator_with_meta_data . create . topic . meta_data [ 'hello' ] . should == 'world'
end
it 'passes the image sizes through' do
Post . any_instance . expects ( :image_sizes = ) . with ( image_sizes )
creator_with_image_sizes . create
2013-02-25 10:42:20 -06:00
end
2013-04-04 23:29:46 -05:00
it 'increases topic response counts' do
first_post = creator . create
2013-07-22 00:06:53 -05:00
# ensure topic user is correct
2014-05-06 08:41:59 -05:00
topic_user = first_post . user . topic_users . find_by ( topic_id : first_post . topic_id )
2013-07-22 00:06:53 -05:00
topic_user . should be_present
topic_user . should be_posted
topic_user . last_read_post_number . should == first_post . post_number
topic_user . seen_post_count . should == first_post . post_number
user2 = Fabricate ( :coding_horror )
2013-10-03 22:28:49 -05:00
user2 . user_stat . topic_reply_count . should == 0
first_post . user . user_stat . reload . topic_reply_count . should == 0
2013-04-04 23:29:46 -05:00
PostCreator . new ( user2 , topic_id : first_post . topic_id , raw : " this is my test post 123 " ) . create
2013-10-03 22:28:49 -05:00
first_post . user . user_stat . reload . topic_reply_count . should == 0
user2 . user_stat . reload . topic_reply_count . should == 1
2013-04-04 23:29:46 -05:00
end
2014-03-18 12:40:40 -05:00
it 'sets topic excerpt if first post, but not second post' do
first_post = creator . create
topic = first_post . topic . reload
topic . excerpt . should be_present
expect {
PostCreator . new ( first_post . user , topic_id : first_post . topic_id , raw : " this is the second post " ) . create
topic . reload
} . to_not change { topic . excerpt }
end
2013-02-25 10:42:20 -06:00
end
2013-02-05 13:16:51 -06:00
2013-05-07 13:25:41 -05:00
context 'when auto-close param is given' do
2013-11-28 10:06:04 -06:00
it 'ensures the user can auto-close the topic, but ignores auto-close param silently' do
2013-05-07 13:25:41 -05:00
Guardian . any_instance . stubs ( :can_moderate? ) . returns ( false )
2013-11-28 10:06:04 -06:00
post = PostCreator . new ( user , basic_topic_params . merge ( auto_close_time : 2 ) ) . create
post . topic . auto_close_at . should be_nil
2013-05-07 13:25:41 -05:00
end
end
2013-02-05 13:16:51 -06:00
end
2013-03-18 12:55:34 -05:00
context 'uniqueness' do
let! ( :topic ) { Fabricate ( :topic , user : user ) }
let ( :basic_topic_params ) { { raw : 'test reply' , topic_id : topic . id , reply_to_post_number : 4 } }
let ( :creator ) { PostCreator . new ( user , basic_topic_params ) }
context " disabled " do
before do
SiteSetting . stubs ( :unique_posts_mins ) . returns ( 0 )
creator . create
end
it " returns true for another post with the same content " do
new_creator = PostCreator . new ( user , basic_topic_params )
new_creator . create . should be_present
end
end
context 'enabled' do
let ( :new_post_creator ) { PostCreator . new ( user , basic_topic_params ) }
before do
SiteSetting . stubs ( :unique_posts_mins ) . returns ( 10 )
creator . create
end
it " returns blank for another post with the same content " do
new_post_creator . create
new_post_creator . errors . should be_present
end
it " returns a post for admins " do
user . admin = true
new_post_creator . create
new_post_creator . errors . should be_blank
end
it " returns a post for moderators " do
2013-03-19 23:05:19 -05:00
user . moderator = true
2013-03-18 12:55:34 -05:00
new_post_creator . create
new_post_creator . errors . should be_blank
end
end
end
2013-05-10 15:58:23 -05:00
context " host spam " do
let! ( :topic ) { Fabricate ( :topic , user : user ) }
let ( :basic_topic_params ) { { raw : 'test reply' , topic_id : topic . id , reply_to_post_number : 4 } }
let ( :creator ) { PostCreator . new ( user , basic_topic_params ) }
before do
Post . any_instance . expects ( :has_host_spam? ) . returns ( true )
end
it " does not create the post " do
2013-06-10 12:17:09 -05:00
GroupMessage . stubs ( :create )
2013-05-10 15:58:23 -05:00
creator . create
creator . errors . should be_present
creator . spam? . should be_true
end
2013-06-10 12:17:09 -05:00
it " sends a message to moderators " do
GroupMessage . expects ( :create ) . with do | group_name , msg_type , params |
group_name == Group [ :moderators ] . name and msg_type == :spam_post_blocked and params [ :user ] . id == user . id
end
creator . create
end
2013-05-10 15:58:23 -05:00
end
2013-04-17 02:33:34 -05:00
# more integration testing ... maximise our testing
2013-02-05 13:16:51 -06:00
context 'existing topic' do
let! ( :topic ) { Fabricate ( :topic , user : user ) }
let ( :creator ) { PostCreator . new ( user , raw : 'test reply' , topic_id : topic . id , reply_to_post_number : 4 ) }
it 'ensures the user can create the post' do
Guardian . any_instance . expects ( :can_create? ) . with ( Post , topic ) . returns ( false )
lambda { creator . create } . should raise_error ( Discourse :: InvalidAccess )
end
context 'success' do
2013-04-17 02:33:34 -05:00
it 'create correctly' do
post = creator . create
Post . count . should == 1
Topic . count . should == 1
post . reply_to_post_number . should == 4
2013-02-05 13:16:51 -06:00
end
end
end
2013-06-21 10:36:33 -05:00
context " cooking options " do
let ( :raw ) { " this is my awesome message body hello world " }
it " passes the cooking options through correctly " do
creator = PostCreator . new ( user ,
title : 'hi there welcome to my topic' ,
raw : raw ,
cooking_options : { traditional_markdown_linebreaks : true } )
Post . any_instance . expects ( :cook ) . with ( raw , has_key ( :traditional_markdown_linebreaks ) ) . returns ( raw )
creator . create
end
end
2013-04-17 02:33:34 -05:00
# integration test ... minimise db work
2013-02-05 13:16:51 -06:00
context 'private message' do
let ( :target_user1 ) { Fabricate ( :coding_horror ) }
let ( :target_user2 ) { Fabricate ( :moderator ) }
2013-04-17 02:33:34 -05:00
let ( :unrelated ) { Fabricate ( :user ) }
let ( :post ) do
PostCreator . create ( user , title : 'hi there welcome to my topic' ,
raw : " this is my awesome message @ #{ unrelated . username_lower } " ,
archetype : Archetype . private_message ,
2014-01-24 05:57:48 -06:00
target_usernames : [ target_user1 . username , target_user2 . username ] . join ( ',' ) ,
category : 1 )
2013-04-17 02:33:34 -05:00
end
2013-02-05 13:16:51 -06:00
2013-04-17 02:33:34 -05:00
it 'acts correctly' do
post . topic . archetype . should == Archetype . private_message
post . topic . topic_allowed_users . count . should == 3
2013-02-05 13:16:51 -06:00
2014-01-24 05:57:48 -06:00
# PMs can't have a category
post . topic . category . should be_nil
2013-04-17 02:33:34 -05:00
# does not notify an unrelated user
unrelated . notifications . count . should == 0
post . topic . subtype . should == TopicSubtype . user_to_user
2013-09-05 23:07:23 -05:00
2014-05-12 14:26:36 -05:00
# if an admin replies they should be added to the allowed user list
admin = Fabricate ( :admin )
PostCreator . create ( admin , raw : 'hi there welcome topic, I am a mod' ,
2013-09-05 23:07:23 -05:00
topic_id : post . topic_id )
post . topic . reload
2014-05-12 14:26:36 -05:00
post . topic . topic_allowed_users . where ( user_id : admin . id ) . count . should == 1
2013-02-05 13:16:51 -06:00
end
end
2013-05-02 00:15:17 -05:00
context 'private message to group' do
let ( :target_user1 ) { Fabricate ( :coding_horror ) }
let ( :target_user2 ) { Fabricate ( :moderator ) }
let ( :group ) do
g = Fabricate . build ( :group )
g . add ( target_user1 )
g . add ( target_user2 )
g . save
g
end
let ( :unrelated ) { Fabricate ( :user ) }
let ( :post ) do
PostCreator . create ( user , title : 'hi there welcome to my topic' ,
raw : " this is my awesome message @ #{ unrelated . username_lower } " ,
archetype : Archetype . private_message ,
target_group_names : group . name )
end
it 'acts correctly' do
post . topic . archetype . should == Archetype . private_message
post . topic . topic_allowed_users . count . should == 1
post . topic . topic_allowed_groups . count . should == 1
# does not notify an unrelated user
unrelated . notifications . count . should == 0
post . topic . subtype . should == TopicSubtype . user_to_user
target_user1 . notifications . count . should == 1
target_user2 . notifications . count . should == 1
end
end
2013-05-18 14:24:29 -05:00
context 'setting created_at' do
created_at = 1 . week . ago
let ( :topic ) do
PostCreator . create ( user ,
raw : 'This is very interesting test post content' ,
title : 'This is a very interesting test post title' ,
created_at : created_at )
end
let ( :post ) do
PostCreator . create ( user ,
raw : 'This is very interesting test post content' ,
topic_id : Topic . last ,
created_at : created_at )
end
it 'acts correctly' do
topic . created_at . should be_within ( 10 . seconds ) . of ( created_at )
post . created_at . should be_within ( 10 . seconds ) . of ( created_at )
end
end
2013-07-01 21:22:56 -05:00
context 'disable validations' do
it 'can save a post' do
creator = PostCreator . new ( user , raw : 'q' , title : 'q' , skip_validations : true )
2014-03-07 02:00:09 -06:00
creator . create
2013-07-01 21:22:56 -05:00
creator . errors . should be_nil
end
end
2013-12-10 12:47:07 -06:00
describe " word_count " do
it " has a word count " do
creator = PostCreator . new ( user , title : 'some inspired poetry for a rainy day' , raw : 'mary had a little lamb, little lamb, little lamb. mary had a little lamb' )
post = creator . create
post . word_count . should == 14
post . topic . reload
post . topic . word_count . should == 14
end
end
2014-04-03 13:42:26 -05:00
describe " embed_url " do
let ( :embed_url ) { " http://eviltrout.com/stupid-url " }
it " creates the topic_embed record " do
creator = PostCreator . new ( user ,
embed_url : embed_url ,
title : 'Reviews of Science Ovens' ,
raw : 'Did you know that you can use microwaves to cook your dinner? Science!' )
2014-06-03 20:41:42 -05:00
creator . create
2014-04-03 13:42:26 -05:00
TopicEmbed . where ( embed_url : embed_url ) . exists? . should be_true
end
end
2014-06-03 20:41:42 -05:00
describe " read credit for creator " do
it " should give credit to creator " do
post = create_post
PostTiming . find_by ( topic_id : post . topic_id ,
post_number : post . post_number ,
user_id : post . user_id ) . msecs . should be > 0
TopicUser . find_by ( topic_id : post . topic_id ,
user_id : post . user_id ) . last_read_post_number . should == 1
end
end
2013-02-05 13:16:51 -06:00
end