aboutsummaryrefslogtreecommitdiffstats
path: root/spec/models
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models')
-rw-r--r--spec/models/about_me_validator_spec.rb53
-rw-r--r--spec/models/holiday_import_spec.rb157
-rw-r--r--spec/models/holiday_spec.rb133
-rw-r--r--spec/models/incoming_message_spec.rb179
-rw-r--r--spec/models/info_request_spec.rb2
-rw-r--r--spec/models/public_body_category_link_spec.rb9
-rw-r--r--spec/models/public_body_category_spec.rb177
-rw-r--r--spec/models/public_body_heading_spec.rb132
-rw-r--r--spec/models/public_body_spec.rb603
-rw-r--r--spec/models/user_spec.rb18
10 files changed, 1116 insertions, 347 deletions
diff --git a/spec/models/about_me_validator_spec.rb b/spec/models/about_me_validator_spec.rb
new file mode 100644
index 000000000..5610cead8
--- /dev/null
+++ b/spec/models/about_me_validator_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+describe AboutMeValidator do
+
+ describe :new do
+
+ it 'sets each supported attribute on the instance' do
+ params = { :about_me => 'My description' }
+ validator = AboutMeValidator.new(params)
+ expect(validator.about_me).to eq('My description')
+ end
+
+ end
+
+ describe :valid? do
+
+ it 'is valid if about_me is =< 500' do
+ params = { :about_me => 'a'*500 }
+ validator = AboutMeValidator.new(params)
+ expect(validator).to be_valid
+ end
+
+ it 'is valid if about_me is blank' do
+ params = { :about_me => '' }
+ validator = AboutMeValidator.new(params)
+ expect(validator).to be_valid
+ end
+
+ it 'is valid if about_me is nil' do
+ params = { :about_me => nil }
+ validator = AboutMeValidator.new(params)
+ expect(validator).to be_valid
+ end
+
+ it 'is invalid if about_me is > 500' do
+ params = { :about_me => 'a'*501 }
+ validator = AboutMeValidator.new(params)
+ expect(validator).to have(1).error_on(:about_me)
+ end
+
+ end
+
+ describe :about_me do
+
+ it 'has an attribute accessor' do
+ params = { :about_me => 'My description' }
+ validator = AboutMeValidator.new(params)
+ expect(validator.about_me).to eq('My description')
+ end
+
+ end
+
+end
diff --git a/spec/models/holiday_import_spec.rb b/spec/models/holiday_import_spec.rb
new file mode 100644
index 000000000..21061f63f
--- /dev/null
+++ b/spec/models/holiday_import_spec.rb
@@ -0,0 +1,157 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+describe HolidayImport do
+
+ it 'validates the presence of a feed if the source is a feed' do
+ holiday_import = HolidayImport.new(:source => 'feed')
+ holiday_import.valid?.should be_false
+ holiday_import.errors[:ical_feed_url].should == ["can't be blank"]
+ end
+
+ it 'does not validate the presence of a feed if the source is suggestions' do
+ holiday_import = HolidayImport.new(:source => 'suggestions')
+ holiday_import.valid?.should be_true
+ end
+
+ it 'validates that the source is either "feed" or "suggestions"' do
+ holiday_import = HolidayImport.new(:source => 'something')
+ holiday_import.valid?.should be_false
+ holiday_import.errors[:source].should == ["is not included in the list"]
+ end
+
+ it 'validates that all holidays create from attributes are valid' do
+ holiday_import = HolidayImport.new(:source => 'suggestions',
+ :holidays_attributes => {"0" => {:description => '',
+ "day(1i)"=>"",
+ "day(2i)"=>"",
+ "day(3i)"=>""}})
+ holiday_import.valid?.should be_false
+ holiday_import.errors[:base].should == ["These holidays could not be imported"]
+ end
+
+ it 'validates that all holidays to import are valid' do
+ holiday_import = HolidayImport.new
+ holiday_import.holidays = [ Holiday.new ]
+ holiday_import.valid?.should be_false
+ holiday_import.errors[:base].should == ['These holidays could not be imported']
+ end
+
+ it 'defaults to importing holidays for the current year' do
+ holiday_import = HolidayImport.new
+ holiday_import.start_year.should == Time.now.year
+ holiday_import.end_year.should == Time.now.year
+ end
+
+ it 'allows the start and end year to be set' do
+ holiday_import = HolidayImport.new(:start_year => 2011, :end_year => 2012)
+ holiday_import.start_year.should == 2011
+ holiday_import.end_year.should == 2012
+ end
+
+ it 'sets the start and end dates to the beginning and end of the year' do
+ holiday_import = HolidayImport.new(:start_year => 2011, :end_year => 2012)
+ holiday_import.start_date.should == Date.new(2011, 1, 1)
+ holiday_import.end_date.should == Date.new(2012, 12, 31)
+ end
+
+ it 'sets a default source of suggestions' do
+ holiday_import = HolidayImport.new
+ holiday_import.source.should == 'suggestions'
+ end
+
+ it 'allows the source to be set' do
+ holiday_import = HolidayImport.new(:source => 'feed')
+ holiday_import.source.should == 'feed'
+ end
+
+ it 'allows an iCal feed URL to be set' do
+ holiday_import = HolidayImport.new(:ical_feed_url => 'http://www.example.com')
+ holiday_import.ical_feed_url.should == 'http://www.example.com'
+ end
+
+ it 'sets a default populated flag to false' do
+ holiday_import = HolidayImport.new
+ holiday_import.populated.should == false
+ end
+
+ it 'returns a readable description of the period for multiple years' do
+ HolidayImport.new(:start_year => 2011, :end_year => 2012).period.should == '2011-2012'
+ end
+
+ it 'returns a readable description of the period for a single year' do
+ HolidayImport.new(:start_year => 2011, :end_year => 2011).period.should == '2011'
+ end
+
+ it 'returns the country name for which suggestions are generated' do
+ HolidayImport.new.suggestions_country_name.should == 'Germany'
+ end
+
+ describe 'when populating a set of holidays to import from suggestions' do
+
+ before do
+ holidays = [ { :date => Date.new(2014, 1, 1), :name => "New Year's Day", :regions => [:gb] } ]
+ Holidays.stub!(:between).and_return(holidays)
+ @holiday_import = HolidayImport.new(:source => 'suggestions')
+ @holiday_import.populate
+ end
+
+ it 'should populate holidays from the suggestions' do
+ @holiday_import.holidays.size.should == 1
+ holiday = @holiday_import.holidays.first
+ holiday.description.should == "New Year's Day"
+ holiday.day.should == Date.new(2014, 1, 1)
+ end
+
+ it 'should return a flag that it has been populated' do
+ @holiday_import.populated.should == true
+ end
+
+ end
+
+ describe 'when populating a set of holidays to import from a feed' do
+
+ before do
+ @holiday_import = HolidayImport.new(:source => 'feed',
+ :ical_feed_url => 'http://www.example.com',
+ :start_year => 2014,
+ :end_year => 2014)
+ end
+
+ it 'should populate holidays from the feed that are between the dates' do
+ @holiday_import.stub!(:open).and_return(load_file_fixture('ical-holidays.ics'))
+ @holiday_import.populate
+ @holiday_import.holidays.size.should == 1
+ holiday = @holiday_import.holidays.first
+ holiday.description.should == "New Year's Day"
+ holiday.day.should == Date.new(2014, 1, 1)
+ end
+
+ it 'should add an error if the calendar cannot be parsed' do
+ @holiday_import.stub!(:open).and_return('some invalid data')
+ @holiday_import.populate
+ expected = ["Sorry, there's a problem with the format of that feed."]
+ @holiday_import.errors[:ical_feed_url].should == expected
+ end
+
+ it 'should add an error if the calendar cannot be found' do
+ @holiday_import.stub!(:open).and_raise Errno::ENOENT.new('No such file or directory')
+ @holiday_import.populate
+ expected = ["Sorry we couldn't find that feed."]
+ @holiday_import.errors[:ical_feed_url].should == expected
+ end
+
+ end
+
+ describe 'when saving' do
+
+ it 'saves all holidays' do
+ holiday = Holiday.new
+ holiday_import = HolidayImport.new
+ holiday_import.holidays = [ holiday ]
+ holiday.should_receive(:save)
+ holiday_import.save
+ end
+
+ end
+
+end
diff --git a/spec/models/holiday_spec.rb b/spec/models/holiday_spec.rb
index 89849abb7..2f8eeabd9 100644
--- a/spec/models/holiday_spec.rb
+++ b/spec/models/holiday_spec.rb
@@ -9,87 +9,98 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-describe Holiday, " when calculating due date" do
+describe Holiday do
- def due_date(ymd)
- return Holiday.due_date_from_working_days(Date.strptime(ymd), 20).strftime("%F")
- end
+ describe :new do
- context "in working days" do
- it "handles no holidays" do
- due_date('2008-10-01').should == '2008-10-29'
+ it 'should require a day' do
+ holiday = Holiday.new
+ holiday.valid?.should be_false
+ holiday.errors[:day].should == ["can't be blank"]
end
+ end
- it "handles non leap years" do
- due_date('2007-02-01').should == '2007-03-01'
- end
+ describe " when calculating due date" do
- it "handles leap years" do
- due_date('2008-02-01').should == '2008-02-29'
+ def due_date(ymd)
+ return Holiday.due_date_from_working_days(Date.strptime(ymd), 20).strftime("%F")
end
- it "handles Thursday start" do
- due_date('2009-03-12').should == '2009-04-14'
- end
+ context "in working days" do
+ it "handles no holidays" do
+ due_date('2008-10-01').should == '2008-10-29'
+ end
- it "handles Friday start" do
- due_date('2009-03-13').should == '2009-04-15'
- end
+ it "handles non leap years" do
+ due_date('2007-02-01').should == '2007-03-01'
+ end
- # Delivery at the weekend ends up the same due day as if it had arrived on
- # the Friday before. This is because the next working day (Monday) counts
- # as day 1.
- # See http://www.whatdotheyknow.com/help/officers#days
- it "handles Saturday start" do
- due_date('2009-03-14').should == '2009-04-15'
- end
- it "handles Sunday start" do
- due_date('2009-03-15').should == '2009-04-15'
- end
+ it "handles leap years" do
+ due_date('2008-02-01').should == '2008-02-29'
+ end
- it "handles Monday start" do
- due_date('2009-03-16').should == '2009-04-16'
- end
+ it "handles Thursday start" do
+ due_date('2009-03-12').should == '2009-04-14'
+ end
- it "handles Time objects" do
- Holiday.due_date_from_working_days(Time.utc(2009, 03, 16, 12, 0, 0), 20).strftime('%F').should == '2009-04-16'
- end
- end
+ it "handles Friday start" do
+ due_date('2009-03-13').should == '2009-04-15'
+ end
- context "in calendar days" do
- it "handles no holidays" do
- Holiday.due_date_from_calendar_days(Date.new(2008, 10, 1), 20).should == Date.new(2008, 10, 21)
- end
+ # Delivery at the weekend ends up the same due day as if it had arrived on
+ # the Friday before. This is because the next working day (Monday) counts
+ # as day 1.
+ # See http://www.whatdotheyknow.com/help/officers#days
+ it "handles Saturday start" do
+ due_date('2009-03-14').should == '2009-04-15'
+ end
+ it "handles Sunday start" do
+ due_date('2009-03-15').should == '2009-04-15'
+ end
- it "handles the due date falling on a Friday" do
- Holiday.due_date_from_calendar_days(Date.new(2008, 10, 4), 20).should == Date.new(2008, 10, 24)
- end
+ it "handles Monday start" do
+ due_date('2009-03-16').should == '2009-04-16'
+ end
- # If the due date would fall on a Saturday it should in fact fall on the next day that isn't a weekend
- # or a holiday
- it "handles the due date falling on a Saturday" do
- Holiday.due_date_from_calendar_days(Date.new(2008, 10, 5), 20).should == Date.new(2008, 10, 27)
+ it "handles Time objects" do
+ Holiday.due_date_from_working_days(Time.utc(2009, 03, 16, 12, 0, 0), 20).strftime('%F').should == '2009-04-16'
+ end
end
- it "handles the due date falling on a Sunday" do
- Holiday.due_date_from_calendar_days(Date.new(2008, 10, 6), 20).should == Date.new(2008, 10, 27)
- end
+ context "in calendar days" do
+ it "handles no holidays" do
+ Holiday.due_date_from_calendar_days(Date.new(2008, 10, 1), 20).should == Date.new(2008, 10, 21)
+ end
- it "handles the due date falling on a Monday" do
- Holiday.due_date_from_calendar_days(Date.new(2008, 10, 7), 20).should == Date.new(2008, 10, 27)
- end
+ it "handles the due date falling on a Friday" do
+ Holiday.due_date_from_calendar_days(Date.new(2008, 10, 4), 20).should == Date.new(2008, 10, 24)
+ end
- it "handles the due date falling on a day before a Holiday" do
- Holiday.due_date_from_calendar_days(Date.new(2008, 12, 4), 20).should == Date.new(2008, 12, 24)
- end
+ # If the due date would fall on a Saturday it should in fact fall on the next day that isn't a weekend
+ # or a holiday
+ it "handles the due date falling on a Saturday" do
+ Holiday.due_date_from_calendar_days(Date.new(2008, 10, 5), 20).should == Date.new(2008, 10, 27)
+ end
- it "handles the due date falling on a Holiday" do
- Holiday.due_date_from_calendar_days(Date.new(2008, 12, 5), 20).should == Date.new(2008, 12, 29)
- end
+ it "handles the due date falling on a Sunday" do
+ Holiday.due_date_from_calendar_days(Date.new(2008, 10, 6), 20).should == Date.new(2008, 10, 27)
+ end
+
+ it "handles the due date falling on a Monday" do
+ Holiday.due_date_from_calendar_days(Date.new(2008, 10, 7), 20).should == Date.new(2008, 10, 27)
+ end
+
+ it "handles the due date falling on a day before a Holiday" do
+ Holiday.due_date_from_calendar_days(Date.new(2008, 12, 4), 20).should == Date.new(2008, 12, 24)
+ end
- it "handles Time objects" do
- Holiday.due_date_from_calendar_days(Time.utc(2009, 03, 17, 12, 0, 0), 20).should == Date.new(2009, 4, 6)
+ it "handles the due date falling on a Holiday" do
+ Holiday.due_date_from_calendar_days(Date.new(2008, 12, 5), 20).should == Date.new(2008, 12, 29)
+ end
+
+ it "handles Time objects" do
+ Holiday.due_date_from_calendar_days(Time.utc(2009, 03, 17, 12, 0, 0), 20).should == Date.new(2009, 4, 6)
+ end
end
end
end
-
diff --git a/spec/models/incoming_message_spec.rb b/spec/models/incoming_message_spec.rb
index 3b6887f76..f6e524de3 100644
--- a/spec/models/incoming_message_spec.rb
+++ b/spec/models/incoming_message_spec.rb
@@ -423,127 +423,50 @@ describe IncomingMessage, " checking validity to reply to with real emails" do
end
-describe IncomingMessage, " when censoring data" do
-
- before(:each) do
- @test_data = "There was a mouse called Stilton, he wished that he was blue."
-
- @im = incoming_messages(:useless_incoming_message)
-
- @censor_rule_1 = CensorRule.new()
- @censor_rule_1.text = "Stilton"
- @censor_rule_1.replacement = "Jarlsberg"
- @censor_rule_1.last_edit_editor = "unknown"
- @censor_rule_1.last_edit_comment = "none"
- @im.info_request.censor_rules << @censor_rule_1
-
- @censor_rule_2 = CensorRule.new()
- @censor_rule_2.text = "blue"
- @censor_rule_2.replacement = "yellow"
- @censor_rule_2.last_edit_editor = "unknown"
- @censor_rule_2.last_edit_comment = "none"
- @im.info_request.censor_rules << @censor_rule_2
-
- @regex_censor_rule = CensorRule.new()
- @regex_censor_rule.text = 'm[a-z][a-z][a-z]e'
- @regex_censor_rule.regexp = true
- @regex_censor_rule.replacement = 'cat'
- @regex_censor_rule.last_edit_editor = 'unknown'
- @regex_censor_rule.last_edit_comment = 'none'
- @im.info_request.censor_rules << @regex_censor_rule
- load_raw_emails_data
- end
-
- it "should do nothing to a JPEG" do
- data = @test_data.dup
- @im.binary_mask_stuff!(data, "image/jpeg")
- data.should == @test_data
- end
-
- it "should replace censor text in Word documents" do
- data = @test_data.dup
- @im.binary_mask_stuff!(data, "application/vnd.ms-word")
- data.should == "There was a xxxxx called xxxxxxx, he wished that he was xxxx."
- end
-
- it "should replace ASCII email addresses in Word documents" do
- orig_data = "His email was foo@bar.com"
- data = orig_data.dup
- @im.binary_mask_stuff!(data, "application/vnd.ms-word")
- data.should == "His email was xxx@xxx.xxx"
- end
-
- it "should replace UCS-2 addresses in Word documents" do
- orig_data = "His email was f\000o\000o\000@\000b\000a\000r\000.\000c\000o\000m\000, indeed"
- data = orig_data.dup
- @im.binary_mask_stuff!(data, "application/vnd.ms-word")
- data.should == "His email was x\000x\000x\000@\000x\000x\000x\000.\000x\000x\000x\000, indeed"
- end
-
- it 'should handle multibyte characters correctly' do
- orig_data = 'á'
- data = orig_data.dup
- @regex_censor_rule = CensorRule.new()
- @regex_censor_rule.text = 'á'
- @regex_censor_rule.regexp = true
- @regex_censor_rule.replacement = 'cat'
- @regex_censor_rule.last_edit_editor = 'unknown'
- @regex_censor_rule.last_edit_comment = 'none'
- @im.info_request.censor_rules << @regex_censor_rule
- lambda{ @im.binary_mask_stuff!(data, "text/plain") }.should_not raise_error
- end
- def pdf_replacement_test(use_ghostscript_compression)
- config = MySociety::Config.load_default()
- previous = config['USE_GHOSTSCRIPT_COMPRESSION']
- config['USE_GHOSTSCRIPT_COMPRESSION'] = use_ghostscript_compression
- orig_pdf = load_file_fixture('tfl.pdf')
- pdf = orig_pdf.dup
-
- orig_text = MailHandler.get_attachment_text_one_file('application/pdf', pdf)
- orig_text.should match(/foi@tfl.gov.uk/)
-
- @im.binary_mask_stuff!(pdf, "application/pdf")
-
- masked_text = MailHandler.get_attachment_text_one_file('application/pdf', pdf)
- masked_text.should_not match(/foi@tfl.gov.uk/)
- masked_text.should match(/xxx@xxx.xxx.xx/)
- config['USE_GHOSTSCRIPT_COMPRESSION'] = previous
- end
-
- it "should replace everything in PDF files using pdftk" do
- pdf_replacement_test(false)
- end
-
- it "should replace everything in PDF files using ghostscript" do
- pdf_replacement_test(true)
- end
-
- it "should not produce zero length output if pdftk silently fails" do
- orig_pdf = load_file_fixture('psni.pdf')
- pdf = orig_pdf.dup
- @im.binary_mask_stuff!(pdf, "application/pdf")
- pdf.should_not == ""
- end
-
- it "should apply censor rules to HTML files" do
- data = @test_data.dup
- @im.html_mask_stuff!(data)
- data.should == "There was a cat called Jarlsberg, he wished that he was yellow."
- end
-
- it "should apply hard-coded privacy rules to HTML files" do
- data = "http://#{AlaveteliConfiguration::domain}/c/cheese"
- @im.html_mask_stuff!(data)
- data.should == "[WDTK login link]"
- end
+describe IncomingMessage, " when censoring data" do
- it "should apply censor rules to From: addresses" do
- @im.stub!(:mail_from).and_return("Stilton Mouse")
- @im.stub!(:last_parsed).and_return(Time.now)
- safe_mail_from = @im.safe_mail_from
- safe_mail_from.should == "Jarlsberg Mouse"
- end
+ before(:each) do
+ @test_data = "There was a mouse called Stilton, he wished that he was blue."
+
+ @im = incoming_messages(:useless_incoming_message)
+
+ @censor_rule_1 = CensorRule.new()
+ @censor_rule_1.text = "Stilton"
+ @censor_rule_1.replacement = "Jarlsberg"
+ @censor_rule_1.last_edit_editor = "unknown"
+ @censor_rule_1.last_edit_comment = "none"
+ @im.info_request.censor_rules << @censor_rule_1
+
+ @censor_rule_2 = CensorRule.new()
+ @censor_rule_2.text = "blue"
+ @censor_rule_2.replacement = "yellow"
+ @censor_rule_2.last_edit_editor = "unknown"
+ @censor_rule_2.last_edit_comment = "none"
+ @im.info_request.censor_rules << @censor_rule_2
+
+ @regex_censor_rule = CensorRule.new()
+ @regex_censor_rule.text = 'm[a-z][a-z][a-z]e'
+ @regex_censor_rule.regexp = true
+ @regex_censor_rule.replacement = 'cat'
+ @regex_censor_rule.last_edit_editor = 'unknown'
+ @regex_censor_rule.last_edit_comment = 'none'
+ @im.info_request.censor_rules << @regex_censor_rule
+ load_raw_emails_data
+ end
+
+ it "should replace censor text" do
+ data = "There was a mouse called Stilton, he wished that he was blue."
+ @im.apply_masks!(data, "application/vnd.ms-word")
+ data.should == "There was a xxxxx called xxxxxxx, he wished that he was xxxx."
+ end
+
+ it "should apply censor rules to From: addresses" do
+ @im.stub!(:mail_from).and_return("Stilton Mouse")
+ @im.stub!(:last_parsed).and_return(Time.now)
+ safe_mail_from = @im.safe_mail_from
+ safe_mail_from.should == "Jarlsberg Mouse"
+ end
end
@@ -565,15 +488,16 @@ describe IncomingMessage, " when censoring whole users" do
it "should apply censor rules to HTML files" do
data = @test_data.dup
- @im.html_mask_stuff!(data)
+ @im.apply_masks!(data, 'text/html')
data.should == "There was a mouse called Gorgonzola, he wished that he was blue."
end
it "should replace censor text to Word documents" do
data = @test_data.dup
- @im.binary_mask_stuff!(data, "application/vnd.ms-word")
+ @im.apply_masks!(data, "application/vnd.ms-word")
data.should == "There was a mouse called xxxxxxx, he wished that he was blue."
end
+
end
@@ -770,3 +694,16 @@ describe IncomingMessage, "when extracting attachments" do
end
end
+
+describe IncomingMessage, 'when getting the body of a message for html display' do
+
+ it 'should replace any masked email addresses with a link to the help page' do
+ incoming_message = IncomingMessage.new
+ body_text = 'there was an [email address] here'
+ incoming_message.stub!(:get_main_body_text_folded).and_return(body_text)
+ incoming_message.stub!(:get_main_body_text_unfolded).and_return(body_text)
+ expected = 'there was an [<a href="/help/officers#mobiles">email address</a>] here'
+ incoming_message.get_body_for_html_display.should == expected
+ end
+
+end
diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb
index 9ad616ea5..70947584b 100644
--- a/spec/models/info_request_spec.rb
+++ b/spec/models/info_request_spec.rb
@@ -824,7 +824,7 @@ describe InfoRequest do
im = mock_model(IncomingMessage,
:subject => nil,
:valid_to_reply_to? => true)
- subject = ir.email_subject_followup im
+ subject = ir.email_subject_followup(:incoming_message => im, :html => false)
subject.should match(/^Re: Freedom of Information request.*fancy dog/)
end
diff --git a/spec/models/public_body_category_link_spec.rb b/spec/models/public_body_category_link_spec.rb
index 8d91f02d5..fd5608480 100644
--- a/spec/models/public_body_category_link_spec.rb
+++ b/spec/models/public_body_category_link_spec.rb
@@ -1,10 +1,11 @@
# == Schema Information
#
-# Table name: public_body_category_link
+# Table name: public_body_category_links
#
-# public_body_category_id :integer not null
-# public_body_heading_id :integer not null
-# category_display_order :integer
+# public_body_category_id :integer not null
+# public_body_heading_id :integer not null
+# category_display_order :integer
+# id :integer not null, primary key
#
require 'spec_helper'
diff --git a/spec/models/public_body_category_spec.rb b/spec/models/public_body_category_spec.rb
index c185a3169..297bd096a 100644
--- a/spec/models/public_body_category_spec.rb
+++ b/spec/models/public_body_category_spec.rb
@@ -2,46 +2,13 @@
#
# Table name: public_body_categories
#
-# id :integer not null, primary key
-# locale :string
-# title :text not null
-# category_tag :text not null
-# description :text not null
-# display_order :integer
+# id :integer not null, primary key
+# category_tag :text not null
#
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe PublicBodyCategory do
- describe 'when loading the data' do
- it 'should use the display_order field to preserve the original data order' do
- PublicBodyCategory.add(:en, [
- "Local and regional",
- [ "local_council", "Local councils", "a local council" ],
- "Miscellaneous",
- [ "other", "Miscellaneous", "miscellaneous" ],
- [ "aardvark", "Aardvark", "daft test"],])
-
- headings = PublicBodyHeading.all
- cat_group1 = headings[0].public_body_categories
- cat_group1.count.should eq 1
- cat_group1[0].title.should eq "Local councils"
-
- cat_group2 = headings[1].public_body_categories
- cat_group2.count.should eq 2
- cat_group2[0].title.should eq "Miscellaneous"
- cat_group2[0].public_body_category_links.where(
- :public_body_heading_id => headings[1].id).
- first.
- category_display_order.should eq 0
-
- cat_group2[1].title.should eq "Aardvark"
- cat_group2[1].public_body_category_links.where(
- :public_body_heading_id => headings[1].id).
- first.
- category_display_order.should eq 1
- end
- end
context 'when validating' do
@@ -67,5 +34,145 @@ describe PublicBodyCategory do
category.should_not be_valid
category.errors[:description].should == ["Description can't be blank"]
end
+
+ it 'validates the translations' do
+ category = FactoryGirl.build(:public_body_category)
+ translation = category.translations.build
+ expect(category).to_not be_valid
+ end
+
+ it 'uses the base model validation for the default locale' do
+ category = PublicBodyCategory.new
+ translation = category.translations.build(:locale => 'en',
+ :description => 'No title')
+ category.valid?
+ translation.valid?
+
+ expect(category).to have(1).error_on(:title)
+ expect(translation).to have(0).errors_on(:title)
+ end
+
+ end
+
+ describe :save do
+
+ it 'saves translations' do
+ category = FactoryGirl.build(:public_body_category)
+ category.translations_attributes = { :es => { :locale => 'es',
+ :title => 'El Category',
+ :description => 'Spanish description' } }
+
+ category.save
+ expect(PublicBodyCategory.find(category.id).translations.size).to eq(2)
+ end
+
end
+
+ describe :translations_attributes= do
+
+ context 'translation_attrs is a Hash' do
+
+ it 'does not persist translations' do
+ category = FactoryGirl.create(:public_body_category)
+ category.translations_attributes = { :es => { :locale => 'es',
+ :title => 'El Category',
+ :description => 'Spanish description' } }
+
+ expect(PublicBodyCategory.find(category.id).translations.size).to eq(1)
+ end
+
+ it 'creates a new translation' do
+ category = FactoryGirl.create(:public_body_category)
+ category.translations_attributes = { :es => { :locale => 'es',
+ :title => 'El Category',
+ :description => 'Spanish description' } }
+ category.save
+ category.reload
+ expect(category.title(:es)).to eq('El Category')
+ end
+
+ it 'updates an existing translation' do
+ category = FactoryGirl.create(:public_body_category)
+ category.translations_attributes = { 'es' => { :locale => 'es',
+ :title => 'Name',
+ :description => 'Desc' } }
+ category.save
+
+ category.translations_attributes = { 'es' => { :id => category.translation_for(:es).id,
+ :locale => 'es',
+ :title => 'Renamed',
+ :description => 'Desc' } }
+ category.save
+ expect(category.title(:es)).to eq('Renamed')
+ end
+
+ it 'updates an existing translation and creates a new translation' do
+ category = FactoryGirl.create(:public_body_category)
+ category.translations.create(:locale => 'es',
+ :title => 'Los Category',
+ :description => 'ES Description')
+
+ expect(category.translations.size).to eq(2)
+
+ category.translations_attributes = {
+ 'es' => { :id => category.translation_for(:es).id,
+ :locale => 'es',
+ :title => 'Renamed' },
+ 'fr' => { :locale => 'fr',
+ :title => 'Le Category' }
+ }
+
+ expect(category.translations.size).to eq(3)
+ I18n.with_locale(:es) { expect(category.title).to eq('Renamed') }
+ I18n.with_locale(:fr) { expect(category.title).to eq('Le Category') }
+ end
+
+ it 'skips empty translations' do
+ category = FactoryGirl.create(:public_body_category)
+ category.translations.create(:locale => 'es',
+ :title => 'Los Category',
+ :description => 'ES Description')
+
+ expect(category.translations.size).to eq(2)
+
+ category.translations_attributes = {
+ 'es' => { :id => category.translation_for(:es).id,
+ :locale => 'es',
+ :title => 'Renamed' },
+ 'fr' => { :locale => 'fr' }
+ }
+
+ expect(category.translations.size).to eq(2)
+ end
+
+ end
+ end
+
+end
+
+describe PublicBodyCategory::Translation do
+
+ it 'requires a locale' do
+ translation = PublicBodyCategory::Translation.new
+ translation.valid?
+ expect(translation.errors[:locale]).to eq(["can't be blank"])
+ end
+
+ it 'is valid if no required attributes are assigned' do
+ translation = PublicBodyCategory::Translation.new(:locale => I18n.default_locale)
+ expect(translation).to be_valid
+ end
+
+ it 'requires a title if another required attribute is assigned' do
+ translation = PublicBodyCategory::Translation.new(:description => 'spec')
+ translation.valid?
+ expect(translation.errors[:title]).to eq(["Title can't be blank"])
+ end
+
+ it 'requires a description if another required attribute is assigned' do
+ translation = PublicBodyCategory::Translation.new(:title => 'spec')
+ translation.valid?
+ expect(translation.errors[:description]).to eq(["Description can't be blank"])
+ end
+
end
diff --git a/spec/models/public_body_heading_spec.rb b/spec/models/public_body_heading_spec.rb
index add2cac60..be3e7c7d2 100644
--- a/spec/models/public_body_heading_spec.rb
+++ b/spec/models/public_body_heading_spec.rb
@@ -2,9 +2,7 @@
#
# Table name: public_body_headings
#
-# id :integer not null, primary key
-# locale :string
-# name :text not null
+# id :integer not null, primary key
# display_order :integer
#
@@ -12,26 +10,6 @@ require 'spec_helper'
describe PublicBodyHeading do
- context 'when loading the data' do
-
- before do
- PublicBodyCategory.add(:en, [
- "Local and regional",
- [ "local_council", "Local councils", "a local council" ],
- "Miscellaneous",
- [ "other", "Miscellaneous", "miscellaneous" ],])
- end
-
- it 'should use the display_order field to preserve the original data order' do
- headings = PublicBodyHeading.all
- headings[0].name.should eq 'Local and regional'
- headings[0].display_order.should eq 0
- headings[1].name.should eq 'Miscellaneous'
- headings[1].display_order.should eq 1
- end
-
- end
-
context 'when validating' do
it 'should require a name' do
@@ -52,6 +30,13 @@ describe PublicBodyHeading do
heading.valid?
heading.display_order.should == PublicBodyHeading.next_display_order
end
+
+ it 'validates the translations' do
+ heading = FactoryGirl.build(:public_body_heading)
+ translation = heading.translations.build
+ expect(heading).to_not be_valid
+ end
+
end
context 'when setting a display order' do
@@ -65,4 +50,105 @@ describe PublicBodyHeading do
PublicBodyHeading.next_display_order.should == 1
end
end
+
+ describe :save do
+
+ it 'saves translations' do
+ heading = FactoryGirl.build(:public_body_heading)
+ heading.translations_attributes = { :es => { :locale => 'es',
+ :name => 'El Heading' } }
+
+ heading.save
+ expect(PublicBodyHeading.find(heading.id).translations.size).to eq(2)
+ end
+
+ end
+
+ describe :translations_attributes= do
+
+ context 'translation_attrs is a Hash' do
+
+ it 'does not persist translations' do
+ heading = FactoryGirl.create(:public_body_heading)
+ heading.translations_attributes = { :es => { :locale => 'es',
+ :name => 'El Heading' } }
+
+ expect(PublicBodyHeading.find(heading.id).translations.size).to eq(1)
+ end
+
+ it 'creates a new translation' do
+ heading = FactoryGirl.create(:public_body_heading)
+ heading.translations_attributes = { :es => { :locale => 'es',
+ :name => 'El Heading' } }
+ heading.save
+ heading.reload
+ expect(heading.name(:es)).to eq('El Heading')
+ end
+
+ it 'updates an existing translation' do
+ heading = FactoryGirl.create(:public_body_heading)
+ heading.translations_attributes = { 'es' => { :locale => 'es',
+ :name => 'Name' } }
+ heading.save
+
+ heading.translations_attributes = { 'es' => { :id => heading.translation_for(:es).id,
+ :locale => 'es',
+ :name => 'Renamed' } }
+ heading.save
+ expect(heading.name(:es)).to eq('Renamed')
+ end
+
+ it 'updates an existing translation and creates a new translation' do
+ heading = FactoryGirl.create(:public_body_heading)
+ heading.translations.create(:locale => 'es',
+ :name => 'Los Heading')
+
+ expect(heading.translations.size).to eq(2)
+
+ heading.translations_attributes = {
+ 'es' => { :id => heading.translation_for(:es).id,
+ :locale => 'es',
+ :name => 'Renamed' },
+ 'fr' => { :locale => 'fr',
+ :name => 'Le Heading' }
+ }
+
+ expect(heading.translations.size).to eq(3)
+ I18n.with_locale(:es) { expect(heading.name).to eq('Renamed') }
+ I18n.with_locale(:fr) { expect(heading.name).to eq('Le Heading') }
+ end
+
+ it 'skips empty translations' do
+ heading = FactoryGirl.create(:public_body_heading)
+ heading.translations.create(:locale => 'es',
+ :name => 'Los Heading')
+
+ expect(heading.translations.size).to eq(2)
+
+ heading.translations_attributes = {
+ 'es' => { :id => heading.translation_for(:es).id,
+ :locale => 'es',
+ :name => 'Renamed' },
+ 'fr' => { :locale => 'fr' }
+ }
+
+ expect(heading.translations.size).to eq(2)
+ end
+ end
+ end
+end
+
+describe PublicBodyHeading::Translation do
+
+ it 'requires a locale' do
+ translation = PublicBodyHeading::Translation.new
+ translation.valid?
+ expect(translation.errors[:locale]).to eq(["can't be blank"])
+ end
+
+ it 'is valid if all required attributes are assigned' do
+ translation = PublicBodyHeading::Translation.new(:locale => I18n.default_locale)
+ expect(translation).to be_valid
+ end
+
end
diff --git a/spec/models/public_body_spec.rb b/spec/models/public_body_spec.rb
index f12582f21..7b55efda1 100644
--- a/spec/models/public_body_spec.rb
+++ b/spec/models/public_body_spec.rb
@@ -30,106 +30,81 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe PublicBody do
- describe :translations_attributes= do
-
- context 'translation_attrs is a Hash' do
-
- it 'takes the correct code path for a Hash' do
- attrs = {}
- attrs.should_receive(:each_value)
- PublicBody.new().translations_attributes = attrs
- end
-
- it 'updates an existing translation' do
- body = public_bodies(:geraldine_public_body)
- translation = body.translation_for(:es)
- params = { 'es' => { :locale => 'es',
- :name => 'Renamed' } }
-
- body.translations_attributes = params
- I18n.with_locale(:es) { expect(body.name).to eq('Renamed') }
- end
-
- it 'updates an existing translation and creates a new translation' do
- body = public_bodies(:geraldine_public_body)
- translation = body.translation_for(:es)
-
- expect(body.translations.size).to eq(2)
-
- body.translations_attributes = {
- 'es' => { :locale => 'es',
- :name => 'Renamed' },
- 'fr' => { :locale => 'fr',
- :name => 'Le Geraldine Quango' }
- }
-
- expect(body.translations.size).to eq(3)
- I18n.with_locale(:es) { expect(body.name).to eq('Renamed') }
- I18n.with_locale(:fr) { expect(body.name).to eq('Le Geraldine Quango') }
- end
-
- it 'skips empty translations' do
- body = public_bodies(:geraldine_public_body)
- translation = body.translation_for(:es)
-
- expect(body.translations.size).to eq(2)
-
- body.translations_attributes = {
- 'es' => { :locale => 'es',
- :name => 'Renamed' },
- 'fr' => { :locale => 'fr' }
- }
-
- expect(body.translations.size).to eq(2)
- end
-
- end
-
- context 'translation_attrs is an Array' do
-
- it 'takes the correct code path for an Array' do
- attrs = []
- attrs.should_receive(:each)
- PublicBody.new().translations_attributes = attrs
- end
-
- it 'creates a new translation' do
- body = public_bodies(:geraldine_public_body)
- body.translation_for(:es).destroy
- body.reload
-
- expect(body.translations.size).to eq(1)
-
- body.translations_attributes = [ {
- :locale => 'es',
- :name => 'Renamed'
- }
- ]
-
- expect(body.translations.size).to eq(2)
- I18n.with_locale(:es) { expect(body.name).to eq('Renamed') }
- end
-
- it 'skips empty translations' do
- body = public_bodies(:geraldine_public_body)
- body.translation_for(:es).destroy
- body.reload
-
- expect(body.translations.size).to eq(1)
-
- body.translations_attributes = [
- { :locale => 'empty' }
- ]
-
- expect(body.translations.size).to eq(1)
- end
-
- end
-
- end
-
+ describe :translations_attributes= do
+
+ context 'translation_attrs is a Hash' do
+
+ it 'does not persist translations' do
+ body = FactoryGirl.create(:public_body)
+ body.translations_attributes = { :es => { :locale => 'es',
+ :name => 'El Body' } }
+
+ expect(PublicBody.find(body.id).translations.size).to eq(1)
+ end
+
+ it 'creates a new translation' do
+ body = FactoryGirl.create(:public_body)
+ body.translations_attributes = { :es => { :locale => 'es',
+ :name => 'El Body' } }
+ body.save
+ body.reload
+ expect(body.name(:es)).to eq('El Body')
+ end
+
+ it 'updates an existing translation' do
+ body = FactoryGirl.create(:public_body)
+ body.translations_attributes = { 'es' => { :locale => 'es',
+ :name => 'El Body' } }
+ body.save
+
+ body.translations_attributes = { 'es' => { :id => body.translation_for(:es).id,
+ :locale => 'es',
+ :name => 'Renamed' } }
+ body.save
+ expect(body.name(:es)).to eq('Renamed')
+ end
+
+ it 'updates an existing translation and creates a new translation' do
+ body = FactoryGirl.create(:public_body)
+ body.translations.create(:locale => 'es',
+ :name => 'El Body')
+
+ expect(body.translations.size).to eq(2)
+
+ body.translations_attributes = {
+ 'es' => { :id => body.translation_for(:es).id,
+ :locale => 'es',
+ :name => 'Renamed' },
+ 'fr' => { :locale => 'fr',
+ :name => 'Le Body' }
+ }
+
+ expect(body.translations.size).to eq(3)
+ I18n.with_locale(:es) { expect(body.name).to eq('Renamed') }
+ I18n.with_locale(:fr) { expect(body.name).to eq('Le Body') }
+ end
+
+ it 'skips empty translations' do
+ body = FactoryGirl.create(:public_body)
+ body.translations.create(:locale => 'es',
+ :name => 'El Body')
+
+ expect(body.translations.size).to eq(2)
+
+ body.translations_attributes = {
+ 'es' => { :id => body.translation_for(:es).id,
+ :locale => 'es',
+ :name => 'Renamed' },
+ 'fr' => { :locale => 'fr' }
+ }
+
+ expect(body.translations.size).to eq(2)
+ end
+ end
+ end
end
+
describe PublicBody, " using tags" do
before do
@public_body = PublicBody.new(:name => 'Aardvark Monitoring Service',
@@ -548,7 +523,7 @@ describe PublicBody, " when loading CSV files" do
PublicBody.find_by_name('Fake Authority of Northern Ireland').tag_array_for_search.should == ['aTag', 'fake']
# Import again to check the 'add' tag functionality works
- new_tags_file = load_file_fixture('fake-authority-add-tags.rb')
+ new_tags_file = load_file_fixture('fake-authority-add-tags.csv')
errors, notes = PublicBody.import_csv(new_tags_file, '', 'add', false, 'someadmin') # false means real run
# Check tags were added successfully
@@ -567,15 +542,284 @@ describe PublicBody, " when loading CSV files" do
PublicBody.find_by_name('Fake Authority of Northern Ireland').tag_array_for_search.should == ['aTag', 'fake']
# Import again to check the 'replace' tag functionality works
- new_tags_file = load_file_fixture('fake-authority-add-tags.rb')
+ new_tags_file = load_file_fixture('fake-authority-add-tags.csv')
errors, notes = PublicBody.import_csv(new_tags_file, 'fake', 'replace', false, 'someadmin') # false means real run
# Check tags were added successfully
- PublicBody.find_by_name('North West Fake Authority').tag_array_for_search.should == ['aTag']
- PublicBody.find_by_name('Scottish Fake Authority').tag_array_for_search.should == ['aTag']
+ PublicBody.find_by_name('North West Fake Authority').tag_array_for_search.should == ['aTag', 'fake']
+ PublicBody.find_by_name('Scottish Fake Authority').tag_array_for_search.should == ['aTag', 'fake']
PublicBody.find_by_name('Fake Authority of Northern Ireland').tag_array_for_search.should == ['aTag', 'fake']
end
+
+ context 'when the import tag is set' do
+
+ context 'with a new body' do
+
+ it 'appends the import tag when no tag_string is specified' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ ,q@localhost,Quango,,http://example.org
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, 'imported', 'add', false, 'someadmin')
+
+ expected = %W(imported)
+ expect(PublicBody.find_by_name('Quango').tag_array_for_search).to eq(expected)
+ end
+
+ it 'appends the import tag when a tag_string is specified' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ ,q@localhost,Quango,first_tag second_tag,http://example.org
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, 'imported', 'add', false, 'someadmin')
+
+ expected = %W(first_tag imported second_tag)
+ expect(PublicBody.find_by_name('Quango').tag_array_for_search).to eq(expected)
+ end
+
+ it 'replaces with the import tag when no tag_string is specified' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ ,q@localhost,Quango,,http://example.org
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, 'imported', 'replace', false, 'someadmin')
+
+ expected = %W(imported)
+ expect(PublicBody.find_by_name('Quango').tag_array_for_search).to eq(expected)
+ end
+
+ it 'replaces with the import tag and tag_string when a tag_string is specified' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ ,q@localhost,Quango,first_tag second_tag,http://example.org
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, 'imported', 'replace', false, 'someadmin')
+
+ expected = %W(first_tag imported second_tag)
+ expect(PublicBody.find_by_name('Quango').tag_array_for_search).to eq(expected)
+ end
+
+ end
+
+ context 'an existing body without tags' do
+
+ before do
+ @body = FactoryGirl.create(:public_body, :name => 'Existing Body')
+ end
+
+ it 'will not import if there is an existing body without the tag' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }",,#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ errors, notes = PublicBody.import_csv(csv, 'imported', 'add', false, 'someadmin')
+
+ expected = %W(imported)
+ errors.should include("error: line 2: Name Name is already taken for authority 'Existing Body'")
+ end
+
+ end
+
+ context 'an existing body with tags' do
+
+ before do
+ @body = FactoryGirl.create(:public_body, :tag_string => 'imported first_tag second_tag')
+ end
+
+ it 'created with tags, different tags in csv, add import tag' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }","first_tag new_tag",#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, 'imported', 'add', false, 'someadmin')
+ expected = %W(first_tag imported new_tag second_tag)
+ expect(PublicBody.find(@body.id).tag_array_for_search).to eq(expected)
+ end
+
+ it 'created with tags, different tags in csv, replace import tag' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }","first_tag new_tag",#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, 'imported', 'replace', false, 'someadmin')
+
+ expected = %W(first_tag imported new_tag)
+ expect(PublicBody.find(@body.id).tag_array_for_search).to eq(expected)
+ end
+
+ end
+
+ end
+
+ context 'when the import tag is not set' do
+
+ context 'with a new body' do
+
+ it 'it is empty if no tag_string is set' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ ,q@localhost,Quango,,http://example.org
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'add', false, 'someadmin')
+
+ expected = []
+ expect(PublicBody.find_by_name('Quango').tag_array_for_search).to eq(expected)
+ end
+
+ it 'uses the specified tag_string' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ ,q@localhost,Quango,first_tag,http://example.org
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'add', false, 'someadmin')
+
+ expected = %W(first_tag)
+ expect(PublicBody.find_by_name('Quango').tag_array_for_search).to eq(expected)
+ end
+
+ it 'replaces with empty if no tag_string is set' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ ,q@localhost,Quango,,http://example.org
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'replace', false, 'someadmin')
+
+ expected = []
+ expect(PublicBody.find_by_name('Quango').tag_array_for_search).to eq(expected)
+ end
+
+ it 'replaces with the specified tag_string' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ ,q@localhost,Quango,first_tag,http://example.org
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'replace', false, 'someadmin')
+
+ expected = %W(first_tag)
+ expect(PublicBody.find_by_name('Quango').tag_array_for_search).to eq(expected)
+ end
+
+ end
+
+ context 'with an existing body without tags' do
+
+ before do
+ @body = FactoryGirl.create(:public_body)
+ end
+
+ it 'appends when no tag_string is specified' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }",,#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'add', false, 'someadmin')
+
+ expected = []
+ expect(PublicBody.find(@body.id).tag_array_for_search).to eq(expected)
+ end
+
+ it 'appends when a tag_string is specified' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }",new_tag,#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'add', false, 'someadmin')
+
+ expected = %W(new_tag)
+ expect(PublicBody.find(@body.id).tag_array_for_search).to eq(expected)
+ end
+
+ it 'replaces when no tag_string is specified' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }",,#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'replace', false, 'someadmin')
+
+ expected = []
+ expect(PublicBody.find(@body.id).tag_array_for_search).to eq(expected)
+ end
+
+ it 'replaces when a tag_string is specified' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }",new_tag,#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'replace', false, 'someadmin')
+
+ expected = %W(new_tag)
+ expect(PublicBody.find(@body.id).tag_array_for_search).to eq(expected)
+ end
+
+ end
+
+ describe 'with an existing body with tags' do
+
+ before do
+ @body = FactoryGirl.create(:public_body, :tag_string => 'first_tag second_tag')
+ end
+
+ it 'created with tags, different tags in csv, add tags' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }","first_tag new_tag",#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'add', false, 'someadmin')
+
+ expected = %W(first_tag new_tag second_tag)
+ expect(PublicBody.find(@body.id).tag_array_for_search).to eq(expected)
+ end
+
+ it 'created with tags, different tags in csv, replace' do
+ csv = <<-CSV.strip_heredoc
+ #id,request_email,name,tag_string,home_page
+ #{ @body.id },#{ @body.request_email },"#{ @body.name }","first_tag new_tag",#{ @body.home_page }
+ CSV
+
+ # csv, tag, tag_behaviour, dry_run, editor
+ PublicBody.import_csv(csv, '', 'replace', false, 'someadmin')
+
+ expected = %W(first_tag new_tag)
+ expect(PublicBody.find(@body.id).tag_array_for_search).to eq(expected)
+ end
+
+ end
+
+ end
+
it "should create bodies with names in multiple locales" do
original_count = PublicBody.count
@@ -700,6 +944,22 @@ CSV
PublicBody.csv_import_fields = old_csv_import_fields
end
+ it "should import translations for fields whose values are the same as the default locale's" do
+ original_count = PublicBody.count
+
+ csv_contents = load_file_fixture("multiple-locales-same-name.csv")
+
+ errors, notes = PublicBody.import_csv(csv_contents, '', 'replace', true, 'someadmin', ['en', 'es']) # true means dry run
+ errors.should == []
+ notes.size.should == 3
+ notes[0..1].should == [
+ "line 2: creating new authority 'Test' (locale: en):\n\t{\"name\":\"Test\",\"request_email\":\"test@test.es\",\"home_page\":\"http://www.test.es/\",\"tag_string\":\"37\"}",
+ "line 2: creating new authority 'Test' (locale: es):\n\t{\"name\":\"Test\"}",
+ ]
+ notes[2].should =~ /Notes: Some bodies are in database, but not in CSV file:\n( .+\n)*You may want to delete them manually.\n/
+
+ PublicBody.count.should == original_count
+ end
end
describe PublicBody do
@@ -762,6 +1022,53 @@ describe PublicBody do
end
+ describe :has_request_email? do
+
+ before do
+ @body = PublicBody.new(:request_email => 'test@example.com')
+ end
+
+ it 'should return false if request_email is nil' do
+ @body.request_email = nil
+ @body.has_request_email?.should == false
+ end
+
+ it 'should return false if the request email is "blank"' do
+ @body.request_email = 'blank'
+ @body.has_request_email?.should == false
+ end
+
+ it 'should return false if the request email is an empty string' do
+ @body.request_email = ''
+ @body.has_request_email?.should == false
+ end
+
+ it 'should return true if the request email is an email address' do
+ @body.has_request_email?.should == true
+ end
+ end
+
+ describe :special_not_requestable_reason do
+
+ before do
+ @body = PublicBody.new
+ end
+
+ it 'should return true if the body is defunct' do
+ @body.stub!(:defunct?).and_return(true)
+ @body.special_not_requestable_reason?.should == true
+ end
+
+ it 'should return true if FOI does not apply' do
+ @body.stub!(:not_apply?).and_return(true)
+ @body.special_not_requestable_reason?.should == true
+ end
+
+ it 'should return false if the body is not defunct and FOI applies' do
+ @body.special_not_requestable_reason?.should == false
+ end
+ end
+
end
describe PublicBody, " when override all public body request emails set" do
@@ -854,3 +1161,95 @@ describe PublicBody, 'when asked for popular bodies' do
end
end
+
+describe PublicBody do
+
+ describe :is_requestable? do
+
+ before do
+ @body = PublicBody.new(:request_email => 'test@example.com')
+ end
+
+ it 'should return false if the body is defunct' do
+ @body.stub!(:defunct?).and_return true
+ @body.is_requestable?.should == false
+ end
+
+ it 'should return false if FOI does not apply' do
+ @body.stub!(:not_apply?).and_return true
+ @body.is_requestable?.should == false
+ end
+
+ it 'should return false there is no request_email' do
+ @body.stub!(:has_request_email?).and_return false
+ @body.is_requestable?.should == false
+ end
+
+ it 'should return true if the request email is an email address' do
+ @body.is_requestable?.should == true
+ end
+
+ end
+
+ describe :is_followupable? do
+
+ before do
+ @body = PublicBody.new(:request_email => 'test@example.com')
+ end
+
+ it 'should return false there is no request_email' do
+ @body.stub!(:has_request_email?).and_return false
+ @body.is_followupable?.should == false
+ end
+
+ it 'should return true if the request email is an email address' do
+ @body.is_followupable?.should == true
+ end
+
+ end
+
+ describe :not_requestable_reason do
+
+ before do
+ @body = PublicBody.new(:request_email => 'test@example.com')
+ end
+
+ it 'should return "defunct" if the body is defunct' do
+ @body.stub!(:defunct?).and_return true
+ @body.not_requestable_reason.should == 'defunct'
+ end
+
+ it 'should return "not_apply" if FOI does not apply' do
+ @body.stub!(:not_apply?).and_return true
+ @body.not_requestable_reason.should == 'not_apply'
+ end
+
+
+ it 'should return "bad_contact" there is no request_email' do
+ @body.stub!(:has_request_email?).and_return false
+ @body.not_requestable_reason.should == 'bad_contact'
+ end
+
+ it 'should raise an error if the body is not defunct, FOI applies and has an email address' do
+ expected_error = "not_requestable_reason called with type that has no reason"
+ lambda{ @body.not_requestable_reason }.should raise_error(expected_error)
+ end
+
+ end
+
+end
+
+describe PublicBody::Translation do
+
+ it 'requires a locale' do
+ translation = PublicBody::Translation.new
+ translation.valid?
+ expect(translation.errors[:locale]).to eq(["can't be blank"])
+ end
+
+ it 'is valid if all required attributes are assigned' do
+ translation = PublicBody::Translation.new(:locale => I18n.default_locale)
+ expect(translation).to be_valid
+ end
+
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 7dcd3ab8a..2245a024f 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -369,3 +369,21 @@ describe User, "when calculating if a user has exceeded the request limit" do
end
+
+describe User do
+
+ describe :banned? do
+
+ it 'is banned if the user has ban_text' do
+ user = FactoryGirl.build(:user, :ban_text => 'banned')
+ expect(user).to be_banned
+ end
+
+ it 'is not banned if the user has no ban_text' do
+ user = FactoryGirl.build(:user, :ban_text => '')
+ expect(user).to_not be_banned
+ end
+
+ end
+
+end