2013-02-14 16:51:48 -05:00
# encoding: utf-8
2013-02-05 14:16:51 -05:00
require 'spec_helper'
2013-10-17 17:44:56 +11:00
require_dependency 'post_creator'
2013-02-05 14:16:51 -05:00
describe Category do
2013-02-19 21:24:38 -06:00
it { should validate_presence_of :user_id }
2013-02-05 14:16:51 -05:00
it { should validate_presence_of :name }
it 'validates uniqueness of name' do
Fabricate ( :category )
2014-05-26 15:33:51 -04:00
should validate_uniqueness_of ( :name ) . scoped_to ( :parent_category_id )
2013-02-05 14:16:51 -05:00
end
2014-08-11 16:55:26 -04:00
it 'validates uniqueness in case insensitive way' do
Fabricate ( :category , name : " Cats " )
c = Fabricate . build ( :category , name : " cats " )
c . should_not be_valid
c . errors [ :name ] . should be_present
end
2014-06-27 17:06:59 -04:00
describe " last_updated_at " do
it " returns a number value of when the category was last updated " do
last = Category . last_updated_at
last . should be_present
last . to_i . should == last
end
end
2013-07-14 11:24:16 +10:00
describe " resolve_permissions " do
it " can determine read_restricted " do
read_restricted , resolved = Category . resolve_permissions ( :everyone = > :full )
2014-09-25 17:44:48 +02:00
read_restricted . should == false
2013-07-14 11:24:16 +10:00
resolved . should == [ ]
end
end
describe " topic_create_allowed and post_create_allowed " do
it " works " do
2013-10-24 10:05:51 +11:00
# NOTE we also have the uncategorized category ... hence the increased count
2014-10-22 15:48:18 +11:00
_default_category = Fabricate ( :category )
2013-07-14 11:24:16 +10:00
full_category = Fabricate ( :category )
can_post_category = Fabricate ( :category )
can_read_category = Fabricate ( :category )
user = Fabricate ( :user )
group = Fabricate ( :group )
group . add ( user )
group . save
admin = Fabricate ( :admin )
full_category . set_permissions ( group = > :full )
full_category . save
can_post_category . set_permissions ( group = > :create_post )
can_post_category . save
can_read_category . set_permissions ( group = > :readonly )
can_read_category . save
guardian = Guardian . new ( admin )
2013-10-24 10:05:51 +11:00
Category . topic_create_allowed ( guardian ) . count . should == 5
Category . post_create_allowed ( guardian ) . count . should == 5
Category . secured ( guardian ) . count . should == 5
2013-07-14 11:24:16 +10:00
guardian = Guardian . new ( user )
2013-10-24 10:05:51 +11:00
Category . secured ( guardian ) . count . should == 5
Category . post_create_allowed ( guardian ) . count . should == 4
Category . topic_create_allowed ( guardian ) . count . should == 3 # explicitly allowed once, default allowed once
2013-07-16 15:44:07 +10:00
# everyone has special semantics, test it as well
can_post_category . set_permissions ( :everyone = > :create_post )
can_post_category . save
2013-10-24 10:05:51 +11:00
Category . post_create_allowed ( guardian ) . count . should == 4
2013-07-14 11:24:16 +10:00
2013-10-13 09:54:48 +11:00
# anonymous has permission to create no topics
guardian = Guardian . new ( nil )
Category . post_create_allowed ( guardian ) . count . should == 0
2013-07-14 11:24:16 +10:00
2013-10-13 09:54:48 +11:00
end
2013-07-14 11:24:16 +10:00
end
2013-04-29 16:33:24 +10:00
describe " security " do
2013-05-15 22:45:52 +02:00
let ( :category ) { Fabricate ( :category ) }
let ( :category_2 ) { Fabricate ( :category ) }
let ( :user ) { Fabricate ( :user ) }
let ( :group ) { Fabricate ( :group ) }
2013-04-29 16:33:24 +10:00
2013-05-15 22:45:52 +02:00
it " secures categories correctly " do
2014-09-25 17:44:48 +02:00
category . read_restricted? . should == false
2013-04-29 16:33:24 +10:00
2013-07-14 11:24:16 +10:00
category . set_permissions ( { } )
2014-09-25 17:44:48 +02:00
category . read_restricted? . should == true
2013-04-29 16:33:24 +10:00
2013-07-14 11:24:16 +10:00
category . set_permissions ( :everyone = > :full )
2014-09-25 17:44:48 +02:00
category . read_restricted? . should == false
2013-04-29 16:33:24 +10:00
2013-05-15 22:45:52 +02:00
user . secure_categories . should be_empty
2013-04-29 16:33:24 +10:00
group . add ( user )
group . save
2013-07-14 11:24:16 +10:00
category . set_permissions ( group . id = > :full )
2013-04-29 16:33:24 +10:00
category . save
user . reload
2013-05-15 22:45:52 +02:00
user . secure_categories . should == [ category ]
end
it " lists all secured categories correctly " do
2014-07-15 15:19:17 -04:00
uncategorized = Category . find ( SiteSetting . uncategorized_category_id )
2013-10-24 10:05:51 +11:00
2013-05-15 22:45:52 +02:00
group . add ( user )
2013-07-14 11:24:16 +10:00
category . set_permissions ( group . id = > :full )
category . save
category_2 . set_permissions ( group . id = > :full )
category_2 . save
2013-04-29 16:33:24 +10:00
2013-10-24 10:05:51 +11:00
Category . secured . should =~ [ uncategorized ]
Category . secured ( Guardian . new ( user ) ) . should =~ [ uncategorized , category , category_2 ]
2013-02-05 14:16:51 -05:00
end
end
2013-07-30 16:48:19 -04:00
it " strips leading blanks " do
Fabricate ( :category , name : " music " ) . name . should == " music "
end
it " strips trailing blanks " do
Fabricate ( :category , name : " bugs " ) . name . should == " bugs "
end
it " strips leading and trailing blanks " do
Fabricate ( :category , name : " blanks " ) . name . should == " blanks "
end
2014-08-18 11:07:32 -04:00
it " sets name_lower " do
Fabricate ( :category , name : " Not MySQL " ) . name_lower . should == " not mysql "
end
2014-04-25 15:14:05 +02:00
it " has custom fields " do
category = Fabricate ( :category , name : " music " )
category . custom_fields [ " a " ] . should == nil
category . custom_fields [ " bob " ] = " marley "
category . custom_fields [ " jack " ] = " black "
category . save
category = Category . find ( category . id )
category . custom_fields . should == { " bob " = > " marley " , " jack " = > " black " }
end
2013-02-05 14:16:51 -05:00
describe " short name " do
let! ( :category ) { Fabricate ( :category , name : 'xx' ) }
it " creates the category " do
category . should be_present
end
it 'has one topic' do
Topic . where ( category_id : category . id ) . count . should == 1
end
end
2013-02-14 16:51:48 -05:00
describe 'non-english characters' do
2014-09-16 19:15:05 +08:00
let ( :category ) { Fabricate ( :category , name : " 测试 " ) }
2013-02-14 16:51:48 -05:00
it " creates a blank slug, this is OK. " do
category . slug . should be_blank
2014-03-24 13:36:23 -04:00
category . slug_for_url . should == " #{ category . id } -category "
2013-02-14 16:51:48 -05:00
end
2014-09-16 19:15:05 +08:00
it " creates a localized slug if default locale is zh_CN " do
SiteSetting . default_locale = 'zh_CN'
category . slug . should_not be_blank
category . slug_for_url . should == " ce-shi "
end
2013-02-14 16:51:48 -05:00
end
2013-05-30 11:09:09 -04:00
describe 'slug would be a number' do
2014-09-16 19:15:05 +08:00
let ( :category ) { Fabricate ( :category , name : " 2 " ) }
2013-05-30 11:09:09 -04:00
it 'creates a blank slug' do
category . slug . should be_blank
2014-03-24 13:36:23 -04:00
category . slug_for_url . should == " #{ category . id } -category "
2013-05-30 11:09:09 -04:00
end
end
2014-10-22 15:48:18 +11:00
describe 'description_text' do
it 'correctly generates text description as needed' do
c = Category . new
c . description_text . should == nil
c . description = " <hello <a>test</a>. "
c . description_text . should == " <hello test. "
end
end
2013-02-05 14:16:51 -05:00
describe 'after create' do
before do
2013-05-07 15:52:45 -04:00
@category = Fabricate ( :category , name : 'Amazing Category' )
2013-02-05 14:16:51 -05:00
@topic = @category . topic
end
2013-04-29 16:33:24 +10:00
it 'is created correctly' do
2013-02-05 14:16:51 -05:00
@category . slug . should == 'amazing-category'
2014-03-24 13:36:23 -04:00
@category . slug_for_url . should == @category . slug
2013-02-05 14:16:51 -05:00
2013-02-21 18:09:56 -05:00
@category . description . should be_blank
2013-02-05 14:16:51 -05:00
Topic . where ( category_id : @category ) . count . should == 1
2013-02-25 19:42:20 +03:00
@topic . should be_present
2013-02-05 14:16:51 -05:00
@topic . category . should == @category
2013-03-07 12:45:49 -05:00
@topic . should be_visible
@topic . pinned_at . should be_present
2013-02-05 14:16:51 -05:00
2014-09-25 17:44:48 +02:00
Guardian . new ( @category . user ) . can_delete? ( @topic ) . should == false
2013-02-05 14:16:51 -05:00
@topic . posts . count . should == 1
@category . topic_url . should be_present
Default values for posts/topics fields on Category
When creating categories (or, at least, subcategories), certain integer
values are set to a default of NULL: topics_week, topics_month,
topics_year, posts_week, posts_month, and posts_year. This causes
consistent exceptions when trying to visit `/categories`, with the
offending line being in
`CategoryDetailedSerializer#count_with_subcategories`. This attempts to
coerce nil into Fixnum.
A fix could be to convert to 0 in the code, but these attributes should
really never be NULL. If there are no posts or topics, they should be 0
to maintain data integrity.
Signed-off-by: David Celis <me@davidcel.is>
2014-02-06 11:56:39 -08:00
@category . posts_week . should == 0
@category . posts_month . should == 0
@category . posts_year . should == 0
@category . topics_week . should == 0
@category . topics_month . should == 0
@category . topics_year . should == 0
2013-02-05 14:16:51 -05:00
end
2014-07-18 13:59:54 -04:00
it " renames the definition when renamed " do
@category . update_attributes ( name : 'Troutfishing' )
@topic . reload
@topic . title . should =~ / Troutfishing /
end
2014-07-25 16:36:16 -04:00
it " doesn't raise an error if there is no definition topic to rename (uncategorized) " do
- > { @category . update_attributes ( name : 'Troutfishing' , topic_id : nil ) } . should_not raise_error
end
2013-12-03 18:53:40 -05:00
it " should not set its description topic to auto-close " do
2013-12-06 16:39:35 -05:00
category = Fabricate ( :category , name : 'Closing Topics' , auto_close_hours : 1 )
2014-09-25 17:44:48 +02:00
category . topic . auto_close_at . should == nil
2013-12-03 18:53:40 -05:00
end
2013-04-01 12:26:51 -04:00
describe " creating a new category with the same slug " do
2014-08-13 14:45:25 -04:00
it " should have a blank slug if at the same level " do
2014-03-24 13:36:23 -04:00
category = Fabricate ( :category , name : " Amazing Categóry " )
category . slug . should be_blank
category . slug_for_url . should == " #{ category . id } -category "
2013-04-01 12:26:51 -04:00
end
2014-08-13 14:45:25 -04:00
it " doesn't have a blank slug if not at the same level " do
parent = Fabricate ( :category , name : 'Other parent' )
category = Fabricate ( :category , name : " Amazing Categóry " , parent_category_id : parent . id )
category . slug . should == 'amazing-category'
category . slug_for_url . should == " amazing-category "
end
2013-04-01 12:26:51 -04:00
end
2013-02-05 14:16:51 -05:00
describe " trying to change the category topic's category " do
before do
@new_cat = Fabricate ( :category , name : '2nd Category' , user : @category . user )
2014-07-16 15:39:39 -04:00
@topic . change_category_to_id ( @new_cat . id )
2013-02-05 14:16:51 -05:00
@topic . reload
@category . reload
end
2013-04-29 16:33:24 +10:00
it 'does not cause changes' do
2013-02-05 14:16:51 -05:00
@category . topic_count . should == 0
@topic . category . should == @category
@category . topic . should == @topic
end
end
end
describe 'destroy' do
before do
@category = Fabricate ( :category )
@category_id = @category . id
@topic_id = @category . topic_id
@category . destroy
end
2013-04-29 16:33:24 +10:00
it 'is deleted correctly' do
2014-09-25 17:44:48 +02:00
Category . exists? ( id : @category_id ) . should == false
Topic . exists? ( id : @topic_id ) . should == false
2013-02-05 14:16:51 -05:00
end
end
2013-10-17 17:44:56 +11:00
describe 'latest' do
it 'should be updated correctly' do
category = Fabricate ( :category )
post = create_post ( category : category . name )
category . reload
category . latest_post_id . should == post . id
category . latest_topic_id . should == post . topic_id
post2 = create_post ( category : category . name )
post3 = create_post ( topic_id : post . topic_id , category : category . name )
category . reload
category . latest_post_id . should == post3 . id
category . latest_topic_id . should == post2 . topic_id
2013-12-30 14:33:07 -08:00
post3 . reload
2013-10-17 17:44:56 +11:00
destroyer = PostDestroyer . new ( Fabricate ( :admin ) , post3 )
destroyer . destroy
category . reload
category . latest_post_id . should == post2 . id
end
end
2013-02-05 14:16:51 -05:00
describe 'update_stats' do
before do
@category = Fabricate ( :category )
2013-02-16 14:57:16 -06:00
end
2013-02-25 19:42:20 +03:00
2013-02-16 14:57:16 -06:00
context 'with regular topics' do
before do
2013-10-17 13:23:38 +11:00
create_post ( user : @category . user , category : @category . name )
2013-02-16 14:57:16 -06:00
Category . update_stats
@category . reload
end
2013-02-05 14:16:51 -05:00
2013-04-29 16:33:24 +10:00
it 'updates topic stats' do
2013-02-16 14:57:16 -06:00
@category . topics_week . should == 1
@category . topics_month . should == 1
@category . topics_year . should == 1
2013-03-31 13:22:05 +02:00
@category . topic_count . should == 1
2013-10-17 13:23:38 +11:00
@category . post_count . should == 1
2013-12-13 15:15:51 -05:00
@category . posts_year . should == 1
@category . posts_month . should == 1
@category . posts_week . should == 1
2013-03-31 13:22:05 +02:00
end
2013-04-29 16:33:24 +10:00
2013-02-05 14:16:51 -05:00
end
2013-02-25 19:42:20 +03:00
2013-02-16 14:57:16 -06:00
context 'with deleted topics' do
before do
2013-02-25 19:42:20 +03:00
@category . topics << Fabricate ( :deleted_topic ,
2013-02-16 14:57:16 -06:00
user : @category . user )
Category . update_stats
@category . reload
end
2013-04-29 16:33:24 +10:00
it 'does not count deleted topics' do
2013-02-16 14:57:16 -06:00
@category . topics_week . should == 0
2013-04-29 16:33:24 +10:00
@category . topic_count . should == 0
2013-02-16 14:57:16 -06:00
@category . topics_month . should == 0
@category . topics_year . should == 0
2013-10-17 13:23:38 +11:00
@category . post_count . should == 0
2013-12-13 15:15:51 -05:00
@category . posts_year . should == 0
@category . posts_month . should == 0
@category . posts_week . should == 0
end
end
context 'with revised post' do
before do
post = create_post ( user : @category . user , category : @category . name )
SiteSetting . stubs ( :ninja_edit_window ) . returns ( 1 . minute . to_i )
2014-10-27 22:06:43 +01:00
post . revise ( post . user , { raw : 'updated body' } , revised_at : post . updated_at + 2 . minutes )
2013-12-13 15:15:51 -05:00
Category . update_stats
@category . reload
2013-02-16 14:57:16 -06:00
end
2013-03-31 13:22:05 +02:00
2013-12-13 15:15:51 -05:00
it " doesn't count each version of a post " do
@category . post_count . should == 1
@category . posts_year . should == 1
@category . posts_month . should == 1
@category . posts_week . should == 1
end
2013-02-05 14:16:51 -05:00
end
2014-08-27 15:58:05 -04:00
context 'for uncategorized category' do
before do
@uncategorized = Category . find ( SiteSetting . uncategorized_category_id )
create_post ( user : Fabricate ( :user ) , category : @uncategorized . name )
Category . update_stats
@uncategorized . reload
end
it 'updates topic stats' do
@uncategorized . topics_week . should == 1
@uncategorized . topics_month . should == 1
@uncategorized . topics_year . should == 1
@uncategorized . topic_count . should == 1
@uncategorized . post_count . should == 1
@uncategorized . posts_year . should == 1
@uncategorized . posts_month . should == 1
@uncategorized . posts_week . should == 1
end
end
2013-02-05 14:16:51 -05:00
end
2013-10-23 12:58:11 -04:00
2014-02-16 12:45:00 -05:00
describe " # url " do
it " builds a url for normal categories " do
category = Fabricate ( :category , name : " cats " )
expect ( category . url ) . to eq " /category/cats "
end
describe " for subcategories " do
it " includes the parent category " do
parent_category = Fabricate ( :category , name : " parent " )
subcategory = Fabricate ( :category , name : " child " ,
parent_category_id : parent_category . id )
expect ( subcategory . url ) . to eq " /category/parent/child "
end
end
end
2013-10-23 12:58:11 -04:00
2014-07-15 15:19:17 -04:00
describe " uncategorized " do
let ( :cat ) { Category . where ( id : SiteSetting . uncategorized_category_id ) . first }
it " reports as `uncategorized?` " do
cat . should be_uncategorized
end
it " cannot have a parent category " do
cat . parent_category_id = Fabricate ( :category ) . id
cat . should_not be_valid
end
end
2013-10-23 12:58:11 -04:00
describe " parent categories " do
let ( :user ) { Fabricate ( :user ) }
let ( :parent_category ) { Fabricate ( :category , user : user ) }
it " can be associated with a parent category " do
sub_category = Fabricate . build ( :category , parent_category_id : parent_category . id , user : user )
sub_category . should be_valid
sub_category . parent_category . should == parent_category
end
it " cannot associate a category with itself " do
category = Fabricate ( :category , user : user )
category . parent_category_id = category . id
category . should_not be_valid
end
it " cannot have a category two levels deep " do
sub_category = Fabricate ( :category , parent_category_id : parent_category . id , user : user )
nested_sub_category = Fabricate . build ( :category , parent_category_id : sub_category . id , user : user )
nested_sub_category . should_not be_valid
end
2014-02-08 14:10:48 -08:00
describe " .query_parent_category " do
it " should return the parent category id given a parent slug " do
parent_category . name = " Amazing Category "
parent_category . id . should == Category . query_parent_category ( parent_category . slug )
end
end
describe " .query_category " do
it " should return the category " do
category = Fabricate ( :category , name : " Amazing Category " , parent_category_id : parent_category . id , user : user )
parent_category . name = " Amazing Parent Category "
category . should == Category . query_category ( category . slug , parent_category . id )
end
end
2013-10-23 12:58:11 -04:00
end
2014-07-14 10:16:24 -04:00
describe " find_by_email " do
it " is case insensitive " do
c1 = Fabricate ( :category , email_in : 'lower@example.com' )
c2 = Fabricate ( :category , email_in : 'UPPER@EXAMPLE.COM' )
c3 = Fabricate ( :category , email_in : 'Mixed.Case@Example.COM' )
Category . find_by_email ( 'LOWER@EXAMPLE.COM' ) . should == c1
Category . find_by_email ( 'upper@example.com' ) . should == c2
Category . find_by_email ( 'mixed.case@example.com' ) . should == c3
Category . find_by_email ( 'MIXED.CASE@EXAMPLE.COM' ) . should == c3
end
end
2013-02-05 14:16:51 -05:00
end