diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/admin_holiday_imports_controller_spec.rb | 73 | ||||
-rw-r--r-- | spec/controllers/admin_holidays_controller_spec.rb | 192 | ||||
-rw-r--r-- | spec/controllers/general_controller_spec.rb | 29 | ||||
-rw-r--r-- | spec/controllers/request_controller_spec.rb | 2 | ||||
-rw-r--r-- | spec/factories/holidays.rb | 8 | ||||
-rw-r--r-- | spec/fixtures/files/ical-holidays.ics | 22 | ||||
-rw-r--r-- | spec/lib/alaveteli_text_masker_spec.rb | 146 | ||||
-rw-r--r-- | spec/mailers/outgoing_mailer_spec.rb | 12 | ||||
-rw-r--r-- | spec/models/holiday_import_spec.rb | 155 | ||||
-rw-r--r-- | spec/models/holiday_spec.rb | 133 | ||||
-rw-r--r-- | spec/models/incoming_message_spec.rb | 179 | ||||
-rw-r--r-- | spec/models/info_request_spec.rb | 2 |
12 files changed, 763 insertions, 190 deletions
diff --git a/spec/controllers/admin_holiday_imports_controller_spec.rb b/spec/controllers/admin_holiday_imports_controller_spec.rb new file mode 100644 index 000000000..dd23a022f --- /dev/null +++ b/spec/controllers/admin_holiday_imports_controller_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe AdminHolidayImportsController do + + describe :new do + + it 'renders the new template' do + get :new + expect(response).to render_template('new') + end + + it 'creates an import' do + get :new + assigns[:holiday_import].should be_instance_of(HolidayImport) + end + + describe 'if the import is valid' do + + it 'populates the import' do + mock_import = mock(HolidayImport, :valid? => true, + :populate => nil) + HolidayImport.stub!(:new).and_return(mock_import) + mock_import.should_receive(:populate) + get :new + end + + end + + end + + describe :create do + + it 'creates an import' do + post :create + assigns[:holiday_import].should be_instance_of(HolidayImport) + end + + describe 'if the import can be saved' do + + before do + mock_import = mock(HolidayImport, :save => true) + HolidayImport.stub!(:new).and_return(mock_import) + post :create + end + + it 'should show a success notice' do + flash[:notice].should == 'Holidays successfully imported' + end + + it 'should redirect to the index' do + response.should redirect_to(admin_holidays_path) + end + + end + + describe 'if the import cannot be saved' do + + before do + mock_import = mock(HolidayImport, :save => false) + HolidayImport.stub!(:new).and_return(mock_import) + post :create + end + + it 'should render the new template' do + expect(response).to render_template('new') + end + + end + + end + + +end diff --git a/spec/controllers/admin_holidays_controller_spec.rb b/spec/controllers/admin_holidays_controller_spec.rb new file mode 100644 index 000000000..21cb51d29 --- /dev/null +++ b/spec/controllers/admin_holidays_controller_spec.rb @@ -0,0 +1,192 @@ +require 'spec_helper' + +describe AdminHolidaysController do + + describe :index do + + before do + @holiday_one = FactoryGirl.create(:holiday, :day => Date.new(2010, 1, 1)) + @holiday_two = FactoryGirl.create(:holiday, :day => Date.new(2011, 2, 2)) + @holiday_three = FactoryGirl.create(:holiday, :day => Date.new(2011, 3, 3)) + end + + it 'gets a hash of holidays keyed by year' do + get :index + assigns(:holidays_by_year)[2010].should include(@holiday_one) + assigns(:holidays_by_year)[2011].should include(@holiday_two) + assigns(:holidays_by_year)[2011].should include(@holiday_three) + end + + it 'gets a list of years with holidays' do + get :index + assigns(:years).should include(2010) + assigns(:years).should include(2011) + end + + it 'renders the index template' do + get :index + expect(response).to render_template('index') + end + + end + + describe :new do + + + describe 'when not using ajax' do + + it 'renders the new template' do + get :new + expect(response).to render_template('new') + end + + end + + describe 'when using ajax' do + + it 'renders the new form partial' do + xhr :get, :new + expect(response).to render_template('new_form') + end + end + + it 'creates a new holiday' do + get :new + assigns[:holiday].should be_instance_of(Holiday) + end + + end + + describe :create do + + before do + @holiday_params = { :description => "New Year's Day", + 'day(1i)' => '2010', + 'day(2i)' => '1', + 'day(3i)' => '1' } + post :create, :holiday => @holiday_params + end + + it 'creates a new holiday' do + assigns(:holiday).description.should == @holiday_params[:description] + assigns(:holiday).day.should == Date.new(2010, 1, 1) + assigns(:holiday).should be_persisted + end + + it 'shows the admin a success message' do + flash[:notice].should == 'Holiday successfully created.' + end + + it 'redirects to the index' do + response.should redirect_to admin_holidays_path + end + + context 'when there are errors' do + + before do + Holiday.any_instance.stub(:save).and_return(false) + post :create, :holiday => @holiday_params + end + + it 'renders the new template' do + expect(response).to render_template('new') + end + end + + end + + describe :edit do + + before do + @holiday = FactoryGirl.create(:holiday) + end + + describe 'when not using ajax' do + + it 'renders the edit template' do + get :edit, :id => @holiday.id + expect(response).to render_template('edit') + end + + end + + describe 'when using ajax' do + + it 'renders the edit form partial' do + xhr :get, :edit, :id => @holiday.id + expect(response).to render_template('edit_form') + end + + end + + it 'gets the holiday in the id param' do + get :edit, :id => @holiday.id + assigns[:holiday].should == @holiday + end + + end + + describe :update do + + before do + @holiday = FactoryGirl.create(:holiday, :day => Date.new(2010, 1, 1), + :description => "Test Holiday") + put :update, :id => @holiday.id, :holiday => { :description => 'New Test Holiday' } + end + + it 'gets the holiday in the id param' do + assigns[:holiday].should == @holiday + end + + it 'updates the holiday' do + holiday = Holiday.find(@holiday.id).description.should == 'New Test Holiday' + end + + it 'shows the admin a success message' do + flash[:notice].should == 'Holiday successfully updated.' + end + + it 'redirects to the index' do + response.should redirect_to admin_holidays_path + end + + context 'when there are errors' do + + before do + Holiday.any_instance.stub(:update_attributes).and_return(false) + put :update, :id => @holiday.id, :holiday => { :description => 'New Test Holiday' } + end + + it 'renders the edit template' do + expect(response).to render_template('edit') + end + end + + end + + describe :destroy do + + before(:each) do + @holiday = FactoryGirl.create(:holiday) + delete :destroy, :id => @holiday.id + end + + it 'finds the holiday to destroy' do + assigns(:holiday).should == @holiday + end + + it 'destroys the holiday' do + assigns(:holiday).should be_destroyed + end + + it 'tells the admin the holiday has been destroyed' do + msg = "Holiday successfully destroyed" + flash[:notice].should == msg + end + + it 'redirects to the index action' do + expect(response).to redirect_to(admin_holidays_path) + end + end + + end diff --git a/spec/controllers/general_controller_spec.rb b/spec/controllers/general_controller_spec.rb index c0a9d57d3..4a7a0bb48 100644 --- a/spec/controllers/general_controller_spec.rb +++ b/spec/controllers/general_controller_spec.rb @@ -126,6 +126,35 @@ describe GeneralController, "when showing the frontpage" do end + describe 'when handling logged-in users' do + + before do + @user = FactoryGirl.create(:user) + session[:user_id] = @user.id + end + + it 'should set a time to live on a non "remember me" session' do + get :frontpage + response.body.should match @user.name + session[:ttl].should be_within(1).of(Time.now) + end + + it 'should not set a time to live on a "remember me" session' do + session[:remember_me] = true + get :frontpage + response.body.should match @user.name + session[:ttl].should be_nil + end + + it 'should end a logged-in session whose ttl has expired' do + session[:ttl] = Time.now - 4.hours + get :frontpage + response.should redirect_to signin_path + session[:user_id].should be_nil + end + + end + end diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 4d0070470..ba558cc93 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -2447,7 +2447,7 @@ describe RequestController, "when caching fragments" do :info_request_id => 132, :id => 44, :get_attachments_for_display => nil, - :html_mask_stuff! => nil, + :apply_masks! => nil, :user_can_view? => true, :all_can_view? => true) attachment = FactoryGirl.build(:body_text, :filename => long_name) diff --git a/spec/factories/holidays.rb b/spec/factories/holidays.rb new file mode 100644 index 000000000..531130c8a --- /dev/null +++ b/spec/factories/holidays.rb @@ -0,0 +1,8 @@ +FactoryGirl.define do + + factory :holiday do + day Date.new(2010, 1, 1) + description "New Year's Day" + end + +end diff --git a/spec/fixtures/files/ical-holidays.ics b/spec/fixtures/files/ical-holidays.ics new file mode 100644 index 000000000..6ccf31202 --- /dev/null +++ b/spec/fixtures/files/ical-holidays.ics @@ -0,0 +1,22 @@ +BEGIN:VCALENDAR +VERSION:2.0 +METHOD:PUBLISH +PRODID:-//uk.gov/GOVUK calendars//EN +CALSCALE:GREGORIAN +BEGIN:VEVENT +DTEND;VALUE=DATE:20140102 +DTSTART;VALUE=DATE:20140101 +SUMMARY:New Year's Day +UID:ca6af7456b0088abad9a69f9f620f5ac-17@gov.uk +SEQUENCE:0 +DTSTAMP:20140916T090346Z +END:VEVENT +BEGIN:VEVENT +DTEND;VALUE=DATE:20150102 +DTSTART;VALUE=DATE:20150101 +SUMMARY:New Year's Day +UID:ca6af7456b00a69f9f620f5ac-17@gov.uk +SEQUENCE:0 +DTSTAMP:20140916T090346Z +END:VEVENT +END:VCALENDAR diff --git a/spec/lib/alaveteli_text_masker_spec.rb b/spec/lib/alaveteli_text_masker_spec.rb new file mode 100644 index 000000000..1a4782a83 --- /dev/null +++ b/spec/lib/alaveteli_text_masker_spec.rb @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AlaveteliTextMasker do + include AlaveteliTextMasker + + describe :apply_masks! do + + describe 'when applying censor rules' do + + before do + @cheese_censor_rule = FactoryGirl.build(:censor_rule, :text => 'Stilton', + :replacement => 'Jarlsberg') + @colour_censor_rule = FactoryGirl.build(:censor_rule, :text => 'blue', + :replacement => 'yellow') + @regex_censor_rule = FactoryGirl.build(:censor_rule, :text => 'm[a-z][a-z][a-z]e', + :replacement => 'cat', + :regexp => true) + @censor_rules = [@cheese_censor_rule, @colour_censor_rule, @regex_censor_rule] + end + + it "should do nothing to a JPEG" do + data = "There was a mouse called Stilton, he wished that he was blue." + apply_masks!(data, "image/jpeg", :censor_rules => @censor_rules) + data.should == "There was a mouse called Stilton, he wished that he was blue." + end + + it "should replace censor text in Word documents" do + data = "There was a mouse called Stilton, he wished that he was blue." + apply_masks!(data, "application/vnd.ms-word", :censor_rules => @censor_rules) + data.should == "There was a xxxxx called xxxxxxx, he wished that he was xxxx." + end + + it 'should handle multibyte characters correctly' do + data = 'á mouse' + @regex_censor_rule.text = 'á' + apply_masks!(data, "application/octet-stream", :censor_rules => @censor_rules).should == 'x mouse' + end + + it "should apply censor rules to HTML files" do + data = "There was a mouse called Stilton, he wished that he was blue." + apply_masks!(data, 'text/html', :censor_rules => @censor_rules) + data.should == "There was a cat called Jarlsberg, he wished that he was yellow." + end + + end + + it "should replace ASCII email addresses in Word documents" do + data = "His email was foo@bar.com" + expected = "His email was xxx@xxx.xxx" + apply_masks!(data, "application/vnd.ms-word") + data.should == expected + end + + + it "should replace UCS-2 addresses in Word documents" do + data = "His email was f\000o\000o\000@\000b\000a\000r\000.\000c\000o\000m\000, indeed" + apply_masks!(data, "application/vnd.ms-word") + data.should == "His email was x\000x\000x\000@\000x\000x\000x\000.\000x\000x\000x\000, indeed" + 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/) + + apply_masks!(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 + apply_masks!(pdf, "application/pdf") + pdf.should_not == "" + end + + it "should apply hard-coded privacy rules to HTML files" do + data = "http://test.host/c/cheese" + apply_masks!(data, 'text/html') + data.should == "[Alaveteli login link]" + end + + it 'should replace a simple email address' do + expected = "the address is [email address]" + apply_masks!("the address is test@example.com", 'text/html', {}).should == expected + end + + it 'should replace a mobile phone number prefixed with "Mobile"' do + expected = "the mobile is [mobile number]" + apply_masks!("the mobile is Mobile 55555 555555", 'text/html', {}).should == expected + end + + it 'should replace a mobile phone number prefixed with "Mob Tel"' do + expected = "the mobile is [mobile number]" + apply_masks!("the mobile is Mob Tel: 55555 555 555", 'text/html', {}).should == expected + end + + it 'should replace a mobile phone number prefixed with "Mob/Fax:"' do + expected = "the mobile is [mobile number]" + apply_masks!("the mobile is Mob/Fax: 55555 555555", 'text/html', {}).should == expected + end + + it "should replace an Alaveteli login link" do + expected = "the login link is [Alaveteli login link]" + apply_masks!("the login link is http://test.host/c/ekfmsdfkm", 'text/html', {}).should == expected + end + + it "should replace a https Alaveteli login link" do + expected = "the login link is [Alaveteli login link]" + apply_masks!("the login link is https://test.host/c/ekfmsdfkm", 'text/html', {}).should == expected + end + + it "should apply censor rules to text" do + censor_rule = FactoryGirl.build(:censor_rule, :text => 'mouse', :replacement => 'cat') + expected = "here is a cat" + apply_masks!("here is a mouse", 'text/html', {:censor_rules => [ censor_rule ]}).should == expected + end + + it 'should apply extra masks to text' do + mask = {:to_replace => 'mouse', :replacement => 'cat'} + expected = "here is a cat" + apply_masks!("here is a mouse", 'text/html', {:masks => [ mask ]}).should == expected + end + + end + +end + diff --git a/spec/mailers/outgoing_mailer_spec.rb b/spec/mailers/outgoing_mailer_spec.rb index a11d56dd3..3df5018fe 100644 --- a/spec/mailers/outgoing_mailer_spec.rb +++ b/spec/mailers/outgoing_mailer_spec.rb @@ -75,14 +75,14 @@ describe OutgoingMailer, "when working out follow up subjects" do ir = info_requests(:fancy_dog_request) im = ir.incoming_messages[0] - ir.email_subject_request.should == "Freedom of Information request - Why do you have & such a fancy dog?" + ir.email_subject_request(:html => false).should == "Freedom of Information request - Why do you have & such a fancy dog?" end it "should use 'Re:' and inital request subject for followups which aren't replies to particular messages" do ir = info_requests(:fancy_dog_request) om = outgoing_messages(:useless_outgoing_message) - OutgoingMailer.subject_for_followup(ir, om).should == "Re: Freedom of Information request - Why do you have & such a fancy dog?" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "Re: Freedom of Information request - Why do you have & such a fancy dog?" end it "should prefix with Re: the subject of the message being replied to" do @@ -91,7 +91,7 @@ describe OutgoingMailer, "when working out follow up subjects" do om = outgoing_messages(:useless_outgoing_message) om.incoming_message_followup = im - OutgoingMailer.subject_for_followup(ir, om).should == "Re: Geraldine FOI Code AZXB421" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "Re: Geraldine FOI Code AZXB421" end it "should not add Re: prefix if there already is such a prefix" do @@ -101,7 +101,7 @@ describe OutgoingMailer, "when working out follow up subjects" do om.incoming_message_followup = im im.raw_email.data = im.raw_email.data.sub("Subject: Geraldine FOI Code AZXB421", "Subject: Re: Geraldine FOI Code AZXB421") - OutgoingMailer.subject_for_followup(ir, om).should == "Re: Geraldine FOI Code AZXB421" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "Re: Geraldine FOI Code AZXB421" end it "should not add Re: prefix if there already is a lower case re: prefix" do @@ -113,7 +113,7 @@ describe OutgoingMailer, "when working out follow up subjects" do im.raw_email.data = im.raw_email.data.sub("Subject: Geraldine FOI Code AZXB421", "Subject: re: Geraldine FOI Code AZXB421") im.parse_raw_email! true - OutgoingMailer.subject_for_followup(ir, om).should == "re: Geraldine FOI Code AZXB421" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "re: Geraldine FOI Code AZXB421" end it "should use 'Re:' and initial request subject when replying to failed delivery notifications" do @@ -126,7 +126,7 @@ describe OutgoingMailer, "when working out follow up subjects" do im.raw_email.data = im.raw_email.data.sub("Subject: Geraldine FOI Code AZXB421", "Subject: Delivery Failed") im.parse_raw_email! true - OutgoingMailer.subject_for_followup(ir, om).should == "Re: Freedom of Information request - Why do you have & such a fancy dog?" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "Re: Freedom of Information request - Why do you have & such a fancy dog?" end end diff --git a/spec/models/holiday_import_spec.rb b/spec/models/holiday_import_spec.rb new file mode 100644 index 000000000..d0be6fb98 --- /dev/null +++ b/spec/models/holiday_import_spec.rb @@ -0,0 +1,155 @@ +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 == 2014 + holiday_import.end_year.should == 2014 + 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') + 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 |