diff options
Diffstat (limited to 'spec')
40 files changed, 1733 insertions, 577 deletions
diff --git a/spec/controllers/admin_censor_rule_controller_spec.rb b/spec/controllers/admin_censor_rule_controller_spec.rb index 8893a858b..c4860da3f 100644 --- a/spec/controllers/admin_censor_rule_controller_spec.rb +++ b/spec/controllers/admin_censor_rule_controller_spec.rb @@ -1,7 +1,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminCensorRuleController, "when making censor rules from the admin interface" do - integrate_views + render_views before { basic_auth_login @request } it "should create a censor rule and purge the corresponding request from varnish" do diff --git a/spec/controllers/admin_general_controller_spec.rb b/spec/controllers/admin_general_controller_spec.rb index dc1eb0d97..b0b65857f 100644 --- a/spec/controllers/admin_general_controller_spec.rb +++ b/spec/controllers/admin_general_controller_spec.rb @@ -4,7 +4,7 @@ describe AdminGeneralController do describe "when viewing front page of admin interface" do - integrate_views + render_views before { basic_auth_login @request } it "should render the front page" do diff --git a/spec/controllers/admin_public_body_controller_spec.rb b/spec/controllers/admin_public_body_controller_spec.rb index 504ddc5cc..c1d3f5014 100644 --- a/spec/controllers/admin_public_body_controller_spec.rb +++ b/spec/controllers/admin_public_body_controller_spec.rb @@ -1,7 +1,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminPublicBodyController, "when administering public bodies" do - integrate_views + render_views before do @old_filters = ActionController::Routing::Routes.filters @@ -154,7 +154,7 @@ end describe AdminPublicBodyController, "when administering public bodies and paying attention to authentication" do - integrate_views + render_views before do config = MySociety::Config.load_default() @@ -263,7 +263,7 @@ describe AdminPublicBodyController, "when administering public bodies and paying end describe AdminPublicBodyController, "when administering public bodies with i18n" do - integrate_views + render_views it "shows the index page" do get :index @@ -288,7 +288,7 @@ describe AdminPublicBodyController, "when administering public bodies with i18n" end it "saves edits to a public body" do - PublicBody.with_locale(:es) do + I18n.with_locale(:es) do pb = PublicBody.find(id=3) pb.name.should == "El Department for Humpadinking" post :update, { @@ -308,10 +308,10 @@ describe AdminPublicBodyController, "when administering public bodies with i18n" end pb = PublicBody.find(public_bodies(:humpadink_public_body).id) - PublicBody.with_locale(:es) do + I18n.with_locale(:es) do pb.name.should == "Renamed" end - PublicBody.with_locale(:en) do + I18n.with_locale(:en) do pb.name.should == "Department for Humpadinking" end end @@ -325,7 +325,7 @@ describe AdminPublicBodyController, "when administering public bodies with i18n" end describe AdminPublicBodyController, "when creating public bodies with i18n" do - integrate_views + render_views before do @old_filters = ActionController::Routing::Routes.filters @@ -357,12 +357,12 @@ describe AdminPublicBodyController, "when creating public bodies with i18n" do body = PublicBody.find_by_name("New Quango") body.translations.map {|t| t.locale.to_s}.sort.should == ["en", "es"] - PublicBody.with_locale(:en) do + I18n.with_locale(:en) do body.name.should == "New Quango" body.url_name.should == "new_quango" body.first_letter.should == "N" end - PublicBody.with_locale(:es) do + I18n.with_locale(:es) do body.name.should == "Mi Nuevo Quango" body.url_name.should == "mi_nuevo_quango" body.first_letter.should == "M" diff --git a/spec/controllers/admin_request_controller_spec.rb b/spec/controllers/admin_request_controller_spec.rb index 8a3934685..0709f6b0b 100644 --- a/spec/controllers/admin_request_controller_spec.rb +++ b/spec/controllers/admin_request_controller_spec.rb @@ -1,7 +1,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminRequestController, "when administering requests" do - integrate_views + render_views before { basic_auth_login @request } before(:each) do @@ -82,7 +82,7 @@ describe AdminRequestController, "when administering requests" do end describe AdminRequestController, "when administering the holding pen" do - integrate_views + render_views before(:each) do basic_auth_login @request load_raw_emails_data diff --git a/spec/controllers/admin_track_controller_spec.rb b/spec/controllers/admin_track_controller_spec.rb index 728c79f1f..f2de6c0d3 100644 --- a/spec/controllers/admin_track_controller_spec.rb +++ b/spec/controllers/admin_track_controller_spec.rb @@ -1,7 +1,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminTrackController, "when administering tracks" do - integrate_views + render_views it "shows the list page" do get :list diff --git a/spec/controllers/admin_user_controller_spec.rb b/spec/controllers/admin_user_controller_spec.rb index cf3665c9f..a6e5a0d7e 100644 --- a/spec/controllers/admin_user_controller_spec.rb +++ b/spec/controllers/admin_user_controller_spec.rb @@ -1,7 +1,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminUserController, "when administering users" do - integrate_views + render_views it "shows the index/list page" do get :index diff --git a/spec/controllers/api_controller_spec.rb b/spec/controllers/api_controller_spec.rb index 8d8a39950..1c320f85c 100644 --- a/spec/controllers/api_controller_spec.rb +++ b/spec/controllers/api_controller_spec.rb @@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') def normalise_whitespace(s) - s = s.gsub(/^\s+|\s+$/, "") + s = s.gsub(/\A\s+|\s+\Z/, "") s = s.gsub(/\s+/, " ") return s end @@ -14,23 +14,36 @@ Spec::Matchers.define :be_equal_modulo_whitespace_to do |expected| end describe ApiController, "when using the API" do - it "should check the API key" do - request_data = { + + describe 'checking API keys' do + before do + @number_of_requests = InfoRequest.count + @request_data = { "title" => "Tell me about your chickens", "body" => "Dear Sir,\n\nI should like to know about your chickens.\n\nYours in faith,\nBob\n", - + "external_url" => "http://www.example.gov.uk/foi/chickens_23", "external_user_name" => "Bob Smith", } - - number_of_requests = InfoRequest.count + end + + it 'should check that an API key is given as a param' do expect { - post :create_request, :k => "This is not really an API key", :request_json => request_data.to_json + post :create_request, :request_json => @request_data.to_json }.to raise_error ApplicationController::PermissionDenied - - InfoRequest.count.should == number_of_requests + InfoRequest.count.should == @number_of_requests + end + + it "should check the API key" do + expect { + post :create_request, + :k => "This is not really an API key", + :request_json => @request_data.to_json + }.to raise_error ApplicationController::PermissionDenied + InfoRequest.count.should == @number_of_requests + end end - + it "should create a new request from a POST" do number_of_requests = InfoRequest.count( :conditions => [ @@ -38,61 +51,61 @@ describe ApiController, "when using the API" do public_bodies(:geraldine_public_body).id ] ) - + request_data = { "title" => "Tell me about your chickens", "body" => "Dear Sir,\n\nI should like to know about your chickens.\n\nYours in faith,\nBob\n", - + "external_url" => "http://www.example.gov.uk/foi/chickens_23", "external_user_name" => "Bob Smith", } - + post :create_request, :k => public_bodies(:geraldine_public_body).api_key, :request_json => request_data.to_json response.should be_success response.content_type.should == "application/json" - + response_body = ActiveSupport::JSON.decode(response.body) response_body["errors"].should be_nil response_body["url"].should =~ /^http/ - + InfoRequest.count(:conditions => [ "public_body_id = ?", public_bodies(:geraldine_public_body).id] ).should == number_of_requests + 1 - + new_request = InfoRequest.find(response_body["id"]) new_request.user_id.should be_nil new_request.external_user_name.should == request_data["external_user_name"] new_request.external_url.should == request_data["external_url"] - + new_request.title.should == request_data["title"] new_request.last_event_forming_initial_request.outgoing_message.body.should == request_data["body"].strip - + new_request.public_body_id.should == public_bodies(:geraldine_public_body).id end - + def _create_request post :create_request, :k => public_bodies(:geraldine_public_body).api_key, :request_json => { "title" => "Tell me about your chickens", "body" => "Dear Sir,\n\nI should like to know about your chickens.\n\nYours in faith,\nBob\n", - + "external_url" => "http://www.example.gov.uk/foi/chickens_23", "external_user_name" => "Bob Smith", }.to_json response.content_type.should == "application/json" return ActiveSupport::JSON.decode(response.body)["id"] end - + it "should add a response to a request" do # First we need an external request request_id = info_requests(:external_request).id - + # Initially it has no incoming messages IncomingMessage.count(:conditions => ["info_request_id = ?", request_id]).should == 0 - + # Now add one sent_at = "2012-05-28T12:35:39+01:00" response_body = "Thank you for your request for information, which we are handling in accordance with the Freedom of Information Act 2000. You will receive a response within 20 working days or before the next full moon, whichever is sooner.\n\nYours sincerely,\nJohn Gandermulch,\nExample Council FOI Officer\n" @@ -104,13 +117,13 @@ describe ApiController, "when using the API" do "sent_at" => sent_at, "body" => response_body }.to_json - + # And make sure it worked response.should be_success incoming_messages = IncomingMessage.all(:conditions => ["info_request_id = ?", request_id]) incoming_messages.count.should == 1 incoming_message = incoming_messages[0] - + incoming_message.sent_at.should == Time.iso8601(sent_at) incoming_message.get_main_body_text_folded.should be_equal_modulo_whitespace_to(response_body) end @@ -118,10 +131,10 @@ describe ApiController, "when using the API" do it "should add a followup to a request" do # First we need an external request request_id = info_requests(:external_request).id - + # Initially it has one outgoing message OutgoingMessage.count(:conditions => ["info_request_id = ?", request_id]).should == 1 - + # Add another, as a followup sent_at = "2012-05-29T12:35:39+01:00" followup_body = "Pls answer ASAP.\nkthxbye\n" @@ -133,7 +146,7 @@ describe ApiController, "when using the API" do "sent_at" => sent_at, "body" => followup_body }.to_json - + # Make sure it worked response.should be_success followup_messages = OutgoingMessage.all( @@ -141,15 +154,15 @@ describe ApiController, "when using the API" do ) followup_messages.size.should == 1 followup_message = followup_messages[0] - + followup_message.last_sent_at.should == Time.iso8601(sent_at) followup_message.body.should == followup_body.strip end - + it "should not allow internal requests to be updated" do n_incoming_messages = IncomingMessage.count n_outgoing_messages = OutgoingMessage.count - + request_id = info_requests(:naughty_chicken_request).id post :add_correspondence, :k => public_bodies(:geraldine_public_body).api_key, @@ -159,20 +172,20 @@ describe ApiController, "when using the API" do "sent_at" => Time.now.iso8601, "body" => "xxx" }.to_json - + response.status.should == "500 Internal Server Error" ActiveSupport::JSON.decode(response.body)["errors"].should == [ "Request #{request_id} cannot be updated using the API"] - + IncomingMessage.count.should == n_incoming_messages OutgoingMessage.count.should == n_outgoing_messages end - + it "should not allow other people's requests to be updated" do request_id = _create_request n_incoming_messages = IncomingMessage.count n_outgoing_messages = OutgoingMessage.count - + post :add_correspondence, :k => public_bodies(:humpadink_public_body).api_key, :id => request_id, @@ -181,15 +194,15 @@ describe ApiController, "when using the API" do "sent_at" => Time.now.iso8601, "body" => "xxx" }.to_json - + response.status.should == "500 Internal Server Error" ActiveSupport::JSON.decode(response.body)["errors"].should == [ "You do not own request #{request_id}"] - + IncomingMessage.count.should == n_incoming_messages OutgoingMessage.count.should == n_outgoing_messages end - + it "should not allow files to be attached to a followup" do post :add_correspondence, :k => public_bodies(:geraldine_public_body).api_key, @@ -202,21 +215,21 @@ describe ApiController, "when using the API" do :attachments => [ fixture_file_upload("files/tfl.pdf") ] - - + + # Make sure it worked response.status.to_i.should == 500 errors = ActiveSupport::JSON.decode(response.body)["errors"] errors.should == ["You cannot attach files to messages in the 'request' direction"] end - + it "should allow files to be attached to a response" do # First we need an external request request_id = info_requests(:external_request).id - + # Initially it has no incoming messages IncomingMessage.count(:conditions => ["info_request_id = ?", request_id]).should == 0 - + # Now add one sent_at = "2012-05-28T12:35:39+01:00" response_body = "Thank you for your request for information, which we are handling in accordance with the Freedom of Information Act 2000. You will receive a response within 20 working days or before the next full moon, whichever is sooner.\n\nYours sincerely,\nJohn Gandermulch,\nExample Council FOI Officer\n" @@ -231,34 +244,33 @@ describe ApiController, "when using the API" do :attachments => [ fixture_file_upload("files/tfl.pdf") ] - + # And make sure it worked response.should be_success incoming_messages = IncomingMessage.all(:conditions => ["info_request_id = ?", request_id]) incoming_messages.count.should == 1 incoming_message = incoming_messages[0] - + incoming_message.sent_at.should == Time.iso8601(sent_at) incoming_message.get_main_body_text_folded.should be_equal_modulo_whitespace_to(response_body) - + # Get the attachment attachments = incoming_message.get_attachments_for_display attachments.size.should == 1 attachment = attachments[0] - attachment.filename.should == "tfl.pdf" - attachment.body.should == load_file_fixture("tfl.pdf") + attachment.body.should == load_file_fixture("tfl.pdf", as_binary=true) end - + it "should show information about a request" do info_request = info_requests(:naughty_chicken_request) get :show_request, :k => public_bodies(:geraldine_public_body).api_key, :id => info_request.id - + response.should be_success assigns[:request].id.should == info_request.id - + r = ActiveSupport::JSON.decode(response.body) r["title"].should == info_request.title # Let’s not test all the fields here, because it would @@ -266,13 +278,13 @@ describe ApiController, "when using the API" do # assigns them and changing assignment to an equality # check, which does not really test anything at all. end - + it "should show an Atom feed of new request events" do get :body_request_events, :id => public_bodies(:geraldine_public_body).id, :k => public_bodies(:geraldine_public_body).api_key, :feed_type => "atom" - + response.should be_success response.should render_template("api/request_events.atom") assigns[:events].size.should > 0 @@ -288,7 +300,7 @@ describe ApiController, "when using the API" do :id => public_bodies(:geraldine_public_body).id, :k => public_bodies(:geraldine_public_body).api_key, :feed_type => "json" - + response.should be_success assigns[:events].size.should > 0 assigns[:events].each do |event| @@ -296,13 +308,13 @@ describe ApiController, "when using the API" do event.outgoing_message.should_not be_nil event.event_type.should satisfy {|x| ['sent', 'followup_sent', 'resent', 'followup_resent'].include?(x)} end - + assigns[:event_data].size.should == assigns[:events].size assigns[:event_data].each do |event_record| event_record[:event_type].should satisfy {|x| ['sent', 'followup_sent', 'resent', 'followup_resent'].include?(x)} end end - + it "should honour the since_event_id parameter" do get :body_request_events, :id => public_bodies(:geraldine_public_body).id, @@ -311,7 +323,7 @@ describe ApiController, "when using the API" do response.should be_success first_event = assigns[:event_data][0] second_event_id = assigns[:event_data][1][:event_id] - + get :body_request_events, :id => public_bodies(:geraldine_public_body).id, :k => public_bodies(:geraldine_public_body).api_key, @@ -320,14 +332,14 @@ describe ApiController, "when using the API" do response.should be_success assigns[:event_data].should == [first_event] end - + it "should honour the since_date parameter for the Atom feed" do get :body_request_events, :id => public_bodies(:humpadink_public_body).id, :k => public_bodies(:humpadink_public_body).api_key, :since_date => "2010-01-01", :feed_type => "atom" - + response.should be_success response.should render_template("api/request_events.atom") assigns[:events].size.should > 0 @@ -335,7 +347,7 @@ describe ApiController, "when using the API" do event.created_at.should >= Date.new(2010, 1, 1) end end - + it "should return a JSON 404 error for non-existent requests" do request_id = 123459876 # Let's hope this doesn't exist! sent_at = "2012-05-28T12:35:39+01:00" @@ -351,7 +363,7 @@ describe ApiController, "when using the API" do response.status.should == "404 Not Found" ActiveSupport::JSON.decode(response.body)["errors"].should == ["Could not find request 123459876"] end - + it "should return a JSON 500 error if we try to add correspondence to a request we don't own" do request_id = info_requests(:naughty_chicken_request).id sent_at = "2012-05-28T12:35:39+01:00" diff --git a/spec/controllers/comment_controller_spec.rb b/spec/controllers/comment_controller_spec.rb index 4a7acee23..c03615ce2 100644 --- a/spec/controllers/comment_controller_spec.rb +++ b/spec/controllers/comment_controller_spec.rb @@ -1,7 +1,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe CommentController, "when commenting on a request" do - integrate_views + render_views it "should give an error and render 'new' template when body text is just some whitespace" do post :new, :url_title => info_requests(:naughty_chicken_request).url_title, diff --git a/spec/controllers/general_controller_spec.rb b/spec/controllers/general_controller_spec.rb index 830486493..9684732a5 100644 --- a/spec/controllers/general_controller_spec.rb +++ b/spec/controllers/general_controller_spec.rb @@ -35,7 +35,7 @@ end describe GeneralController, "when showing the frontpage" do - integrate_views + render_views before do public_body = mock_model(PublicBody, :name => "Example Public Body", @@ -97,8 +97,57 @@ describe GeneralController, "when showing the frontpage" do response.should be_success end + describe 'when there is more than one locale' do + + describe 'when using the default locale' do + + before do + @default_lang_home_link = /href=".*\/en\// + @other_lang_home_link = /href=".*\/es\// + @old_include_default_locale_in_urls = Configuration::include_default_locale_in_urls + end + + def set_default_locale_in_urls(value) + Configuration.stub!(:include_default_locale_in_urls).and_return(value) + load Rails.root.join("config/initializers/fast_gettext.rb") + end + + describe 'when the config value INCLUDE_DEFAULT_LOCALE_IN_URLS is false' do + + before do + set_default_locale_in_urls(false) + end + + it 'should generate URLs without a locale prepended' do + get :frontpage + response.should_not have_text(@default_lang_home_link) + end + + it 'should render the front page in the default language when no locale param + is present and the session locale is not the default' do + get(:frontpage, {}, {:locale => 'es'}) + response.should_not have_text(@other_lang_home_link) + end + end + + it 'should generate URLs with a locale prepended when the config value + INCLUDE_DEFAULT_LOCALE_IN_URLS is true' do + set_default_locale_in_urls(true) + get :frontpage + response.should have_text(@default_lang_home_link) + end + + after do + set_default_locale_in_urls(@old_include_default_locale_in_urls) + end + + end + end + + describe "when using different locale settings" do home_link_regex = /href=".*\/en\// + it "should generate URLs with a locale prepended when there's more than one locale set" do get :frontpage response.should have_text(home_link_regex) @@ -137,6 +186,7 @@ describe GeneralController, "when showing the frontpage" do FastGettext.default_available_locales = old_fgt_available_locales I18n.available_locales = old_i18n_available_locales end + end end describe GeneralController, "when showing the front page with fixture data" do @@ -185,7 +235,7 @@ end describe GeneralController, 'when using xapian search' do - integrate_views + render_views # rebuild xapian index after fixtures loaded before(:each) do diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb index 28fd08c80..0f6f75eb9 100644 --- a/spec/controllers/help_controller_spec.rb +++ b/spec/controllers/help_controller_spec.rb @@ -1,7 +1,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe HelpController, "when using help" do - integrate_views + render_views it "shows the about page" do get :about diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index 29ece18cb..a0841b621 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe PublicBodyController, "when showing a body" do - integrate_views + render_views before(:each) do load_raw_emails_data @@ -44,14 +44,14 @@ describe PublicBodyController, "when showing a body" do end it "should assign the body using different locale from that used for url_name" do - PublicBody.with_locale(:es) do + I18n.with_locale(:es) do get :show, {:url_name => "dfh", :view => 'all'} assigns[:public_body].notes.should == "Baguette" end end it "should assign the body using same locale as that used in url_name" do - PublicBody.with_locale(:es) do + I18n.with_locale(:es) do get :show, {:url_name => "edfh", :view => 'all'} assigns[:public_body].notes.should == "Baguette" end @@ -79,7 +79,7 @@ describe PublicBodyController, "when showing a body" do end describe PublicBodyController, "when listing bodies" do - integrate_views + render_views it "should be successful" do get :list @@ -87,7 +87,7 @@ describe PublicBodyController, "when listing bodies" do end it "should list all bodies from default locale, even when there are no translations for selected locale" do - PublicBody.with_locale(:en) do + I18n.with_locale(:en) do @english_only = PublicBody.new(:name => 'English only', :short_name => 'EO', :request_email => 'english@flourish.org', @@ -95,7 +95,7 @@ describe PublicBodyController, "when listing bodies" do :last_edit_comment => '') @english_only.save end - PublicBody.with_locale(:es) do + I18n.with_locale(:es) do get :list assigns[:public_bodies].include?(@english_only).should == true end @@ -193,7 +193,7 @@ end describe PublicBodyController, "when doing type ahead searches" do - integrate_views + render_views before(:each) do load_raw_emails_data diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index e898fb91b..9e14153a7 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -59,19 +59,6 @@ describe RequestController, "when listing recent requests" do :conditions => "id in (select info_request_id from info_request_events where created_at between '2007-10-13'::date and '2007-11-01'::date)") end - it "should make a sane-sized cache tag" do - get :list, :view => 'all', :request_date_after => '13/10/2007', :request_date_before => '01/11/2007' - assigns[:cache_tag].size.should <= 32 - end - - it "should vary the cache tag with locale" do - get :list, :view => 'all', :request_date_after => '13/10/2007', :request_date_before => '01/11/2007' - en_tag = assigns[:cache_tag] - session[:locale] = :es - get :list, :view => 'all', :request_date_after => '13/10/2007', :request_date_before => '01/11/2007' - assigns[:cache_tag].should_not == en_tag - end - it "should list internal_review requests as unresolved ones" do get :list, :view => 'awaiting' @@ -134,7 +121,7 @@ end describe RequestController, "when changing things that appear on the request page" do - integrate_views + render_views it "should purge the downstream cache when mail is received" do ir = info_requests(:fancy_dog_request) @@ -200,7 +187,7 @@ describe RequestController, "when changing things that appear on the request pag end describe RequestController, "when showing one request" do - integrate_views + render_views before(:each) do load_raw_emails_data @@ -458,7 +445,7 @@ describe RequestController, "when showing one request" do describe 'when handling incoming mail' do - integrate_views + render_views it "should receive incoming messages, send email to creator, and show them" do ir = info_requests(:fancy_dog_request) @@ -757,7 +744,7 @@ describe RequestController, "when showing one request" do assigns[:url_path].should_not == old_path response.location.should have_text(/#{assigns[:url_path]}/) zipfile = Zip::ZipFile.open(File.join(File.dirname(__FILE__), "../../cache/zips", assigns[:url_path])) { |zipfile| - zipfile.count.should == 5 # the message, two hello.txt, the unknown attachment, and its empty message + zipfile.count.should == 4 # the message, two hello.txt plus the unknown attachment } end @@ -908,7 +895,7 @@ describe RequestController, "when searching for an authority" do end describe RequestController, "when creating a new request" do - integrate_views + render_views before do @user = users(:bob_smith_user) @@ -1144,7 +1131,7 @@ describe RequestController, "when making a new request" do end describe RequestController, "when viewing an individual response for reply/followup" do - integrate_views + render_views before(:each) do load_raw_emails_data @@ -1577,7 +1564,7 @@ describe RequestController, "when classifying an information request" do end describe RequestController, "when sending a followup message" do - integrate_views + render_views before(:each) do load_raw_emails_data @@ -1659,7 +1646,7 @@ end # it can't check the URLs in the emails I don't think, ugh. describe RequestController, "sending overdue request alerts" do - integrate_views + render_views before(:each) do load_raw_emails_data @@ -1804,7 +1791,7 @@ describe RequestController, "sending overdue request alerts" do end describe RequestController, "sending unclassified new response reminder alerts" do - integrate_views + render_views before(:each) do load_raw_emails_data @@ -1834,7 +1821,7 @@ describe RequestController, "sending unclassified new response reminder alerts" end describe RequestController, "clarification required alerts" do - integrate_views + render_views before(:each) do load_raw_emails_data end @@ -1887,7 +1874,7 @@ describe RequestController, "clarification required alerts" do end describe RequestController, "comment alerts" do - integrate_views + render_views before(:each) do load_raw_emails_data end @@ -1966,7 +1953,7 @@ describe RequestController, "comment alerts" do end describe RequestController, "when viewing comments" do - integrate_views + render_views before(:each) do load_raw_emails_data end @@ -1989,7 +1976,7 @@ end describe RequestController, "authority uploads a response from the web interface" do - integrate_views + render_views before(:each) do # domain after the @ is used for authentication of FOI officers, so to test it @@ -2099,7 +2086,7 @@ end describe RequestController, "when doing type ahead searches" do - integrate_views + render_views it "should return nothing for the empty query string" do get :search_typeahead, :q => "" @@ -2157,7 +2144,7 @@ describe RequestController, "when doing type ahead searches" do end describe RequestController, "when showing similar requests" do - integrate_views + render_views it "should work" do get :similar, :url_title => info_requests(:badger_request).url_title @@ -2191,7 +2178,7 @@ describe RequestController, "when reporting a request when not logged in" do end describe RequestController, "when reporting a request (logged in)" do - integrate_views + render_views before do @user = users(:robin_user) diff --git a/spec/controllers/services_controller_spec.rb b/spec/controllers/services_controller_spec.rb index a701ae247..d2d22826a 100644 --- a/spec/controllers/services_controller_spec.rb +++ b/spec/controllers/services_controller_spec.rb @@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe ServicesController, "when using web services" do - integrate_views + render_views # store and restore the locale in the context of the test suite to isolate # changes made in these tests @@ -40,4 +40,4 @@ describe ServicesController, "when using web services" do FastGettext.set_locale(@old_locale) end -end
\ No newline at end of file +end diff --git a/spec/controllers/track_controller_spec.rb b/spec/controllers/track_controller_spec.rb index c785960b5..cd7932e90 100644 --- a/spec/controllers/track_controller_spec.rb +++ b/spec/controllers/track_controller_spec.rb @@ -56,7 +56,7 @@ describe TrackController, "when making a new track on a request" do end describe TrackController, "when sending alerts for a track" do - integrate_views + render_views include LinkToHelper # for main_url before(:each) do @@ -134,7 +134,7 @@ describe TrackController, "when sending alerts for a track" do end describe TrackController, "when viewing RSS feed for a track" do - integrate_views + render_views before(:each) do load_raw_emails_data @@ -164,7 +164,7 @@ end describe TrackController, "when viewing JSON version of a track feed" do - integrate_views + render_views before(:each) do load_raw_emails_data @@ -206,7 +206,7 @@ end describe TrackController, "when tracking a public body" do - integrate_views + render_views before(:each) do load_raw_emails_data diff --git a/spec/controllers/user_controller_spec.rb b/spec/controllers/user_controller_spec.rb index 23006803b..db64bdcaf 100644 --- a/spec/controllers/user_controller_spec.rb +++ b/spec/controllers/user_controller_spec.rb @@ -5,7 +5,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') # http://rspec.rubyforge.org/rspec-rails/1.1.12/classes/Spec/Rails/Example/ControllerExampleGroup.html describe UserController, "when showing a user" do - integrate_views + render_views before(:each) do load_raw_emails_data get_fixtures_xapian_index @@ -64,7 +64,7 @@ describe UserController, "when showing a user" do end describe UserController, "when signing in" do - integrate_views + render_views def get_last_postredirect post_redirects = PostRedirect.find_by_sql("select * from post_redirects order by id desc limit 1") @@ -228,7 +228,7 @@ describe UserController, "when signing in" do end describe UserController, "when signing up" do - integrate_views + render_views it "should be an error if you type the password differently each time" do post :signup, { :user_signup => { :email => 'new@localhost', :name => 'New Person', @@ -285,7 +285,7 @@ describe UserController, "when signing up" do end describe UserController, "when signing out" do - integrate_views + render_views it "should log you out and redirect to the home page" do session[:user_id] = users(:bob_smith_user).id @@ -309,7 +309,7 @@ describe UserController, "when signing out" do end describe UserController, "when sending another user a message" do - integrate_views + render_views it "should redirect to signin page if you go to the contact form and aren't signed in" do get :contact, :id => users(:silly_name_user) @@ -346,7 +346,7 @@ describe UserController, "when sending another user a message" do end describe UserController, "when changing password" do - integrate_views + render_views it "should show the email form when not logged in" do get :signchangepassword @@ -416,7 +416,7 @@ describe UserController, "when changing password" do end describe UserController, "when changing email address" do - integrate_views + render_views it "should require login" do get :signchangeemail @@ -561,7 +561,7 @@ describe UserController, "when changing email address" do end describe UserController, "when using profile photos" do - integrate_views + render_views before do @user = users(:bob_smith_user) @@ -631,7 +631,7 @@ describe UserController, "when showing JSON version for API" do end describe UserController, "when viewing the wall" do - integrate_views + render_views before(:each) do get_fixtures_xapian_index diff --git a/spec/fixtures/files/dos-linebreaks.email b/spec/fixtures/files/dos-linebreaks.email new file mode 100644 index 000000000..1f5f1473f --- /dev/null +++ b/spec/fixtures/files/dos-linebreaks.email @@ -0,0 +1,31 @@ +From email@example.com Wed Mar 12 14:58:26 2008 +Return-path: email@example.com> +Envelope-to: request-xxx-xxxxxx@whatdotheyknow.com +Delivery-date: Wed, 12 Mar 2008 14:58:26 +0000 +Received: from example.com ([0.0.0.0]:1368 helo=example.com) + by tea.ukcod.org.uk with esmtp (Exim 4.50) + id 1JZSPS-0002yK-Rq + for request-60-3548031c@whatdotheyknow.com; Wed, 12 Mar 2008 14:58:26 +0000 +X-MimeOLE: Produced By Microsoft Exchange V0.0.0.0 +Content-class: urn:content-classes:message +MIME-Version: 1.0 +Content-Type: text/plain; + charset="us-ascii" +Content-Transfer-Encoding: quoted-printable +Disposition-Notification-To: "A Person" email@example.com> +Subject: RE: Freedom of Information request - Plans for the East Oxford Community Centre +Date: Wed, 12 Mar 2008 14:59:04 -0000 +Message-ID: <3D8BEC617D49EF45A9E6D103A83FD30331BF84@local> +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +Thread-Topic: Freedom of Information request +Thread-Index: AciDziuIcYirFQ7GT36VyP2ABE14qgAg1c0w +From: "A Person" email@example.com> +To: FOI Person <EMAIL_TO> +X-OriginalArrivalTime: 12 Mar 2008 14:59:04.0368 (UTC) FILETIME=[9D245300:01C88451] +X-SEF-7853D99-ADF1-478E-8894-213D316B8FFA: 1 +X-SEF-Processed: 6_0_1_111__2008_03_12_14_59_05 + +Thank you for your Freedom of Information request. I have forwarded it=0D=0A= +to the relevant department for their reply.=0D=0A=0D=0A + diff --git a/spec/fixtures/files/humberside-police-odd-mime-type.email b/spec/fixtures/files/humberside-police-odd-mime-type.email index 5514b29da..ae4ceeffe 100644 --- a/spec/fixtures/files/humberside-police-odd-mime-type.email +++ b/spec/fixtures/files/humberside-police-odd-mime-type.email @@ -3,19 +3,20 @@ Return-path: <> Envelope-to: request-5335-xxxxxxxx@whatdotheyknow.com Delivery-date: Thu, 01 Jan 2009 15:56:20 +0000 Received: from earth.karoo.kcom.com ([212.50.160.55]:62894) - by sandwich.ukcod.org.uk with esmtp (Exim 4.63) - id 1LIPuG-0004AJ-B3 - for request-5335-xxxxxxxx@whatdotheyknow.com; Thu, 01 Jan 2009 15:56:20 +0000 + by sandwich.ukcod.org.uk with esmtp (Exim 4.63) + id 1LIPuG-0004AJ-B3 + for request-5335-xxxxxxxx@whatdotheyknow.com; Thu, 01 Jan 2009 15:56:20 +0000 Received: from unknown (HELO smtp-in.karoo.kcom.com) ([10.102.8.11]) by earth.karoo.kcom.com with ESMTP; 01 Jan 2009 15:44:42 +0000 Received: from exim by smtp-in.karoo.kcom.comwith local (Exim 4.30) - id 1LIPu0-0004fg-G6 server-id smtp-in4 - for request-5335-xxxxxxxx@whatdotheyknow.com; Thu, 01 Jan 2009 15:56:04 +0000 + id 1LIPu0-0004fg-G6 server-id smtp-in4 + for request-5335-xxxxxxxx@whatdotheyknow.com; Thu, 01 Jan 2009 15:56:04 +0000 X-Failed-Recipients: clerk@humberside-pa.karoo.co.uk Reply-To: Postmaster <postmaster@karoo.kcom.com> Auto-Submitted: auto-generated From: Mail Delivery System <Mailer-Daemon@karoo.co.uk> To: request-5335-xxxxxxxx@whatdotheyknow.com +Cc: request-5335-xxxxxxxx@whatdotheyknow.com Subject: Mail delivery failed : returning message to sender X-Mailer: Karoo Mailcore [version 2.0-IB] MIME-Version: 1.0 @@ -52,19 +53,19 @@ Content-Transfer-Encoding: 8bit Return-path: <request-5335-xxxxxxxx@whatdotheyknow.com> Received: from [212.50.160.60] (helo=venus.karoo.kcom.com) - by smtp-in.karoo.kcom.comwith esmtp (Exim 4.30) - id 1LIPu0-0004fc-FM server-id smtp-in4 - for clerk@humberside-pa.karoo.co.uk; Thu, 01 Jan 2009 15:56:04 +0000 + by smtp-in.karoo.kcom.comwith esmtp (Exim 4.30) + id 1LIPu0-0004fc-FM server-id smtp-in4 + for clerk@humberside-pa.karoo.co.uk; Thu, 01 Jan 2009 15:56:04 +0000 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnECAF9nXElSb+bUmWdsb2JhbACMZQGHFQEBAQEBCAsKBxG2eIVy -X-IronPort-AV: E=Sophos;i="4.36,313,1228089600"; +X-IronPort-AV: E=Sophos;i="4.36,313,1228089600"; d="scan'208";a="465483300" Received: from sandwich.ukcod.org.uk ([82.111.230.212]) by venus.karoo.kcom.com with ESMTP; 01 Jan 2009 15:46:44 +0000 Received: from foi by sandwich.ukcod.org.uk with local (Exim 4.63) - (envelope-from <request-5335-xxxxxxxx@whatdotheyknow.com>) - id 1LIPtz-0004AG-OC - for clerk@humberside-pa.karoo.co.uk; Thu, 01 Jan 2009 15:56:03 +0000 + (envelope-from <request-5335-xxxxxxxx@whatdotheyknow.com>) + id 1LIPtz-0004AG-OC + for clerk@humberside-pa.karoo.co.uk; Thu, 01 Jan 2009 15:56:03 +0000 From: John Jarman <request-5335-xxxxxxxx@whatdotheyknow.com> To: FOI requests at Humberside Police Authority <clerk@humberside-pa.karoo.co.uk> Subject: Freedom of Information request - Police Injury Award Pensions diff --git a/spec/fixtures/files/incoming-request-attachment-headers.email b/spec/fixtures/files/incoming-request-attachment-headers.email new file mode 100644 index 000000000..80e71556d --- /dev/null +++ b/spec/fixtures/files/incoming-request-attachment-headers.email @@ -0,0 +1,50 @@ +From foi@example.com Mon Oct 06 13:45:38 2008 +Return-path: <foi@example.com> +Envelope-to: foi@sandwich.ukcod.org.uk +Delivery-date: Mon, 06 Oct 2008 13:45:38 +0100 +Message-Id: <s8ea1156.098@example.com> +X-Mailer: Novell GroupWise Internet Agent 6.5.4 +Date: Mon, 06 Oct 2008 13:23:00 +0100 +From: "Steve Knight" <foi@example.com> +To: <request-xxxx-xxxxx@whatdotheyknow.com> +Subject: FOI request +Mime-Version: 1.0 +Content-Type: multipart/mixed; boundary="=__PartFDD45234.0__=" +X-Proofpoint-Virus-Version: vendor=nai engine=5.2.00 definitions=5398 signatures=473327 +X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 classifier= adjust=0 reason=limit engine=3.1.0-0805090000 definitions=main-0810060054 + +This is a MIME message. If you are reading this text, you may want to +consider changing to a mail reader or gateway that understands how to +properly handle MIME multipart messages. +--=__PartFDD45234.0__= +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline + +Dear Mr Requester, + +Here is some information. + +--=__PartFDD45234.0__= +Content-Type: message/rfc822 + +Date: Fri, 23 May 2008 17:02:11 +0100 +From: "David Bishop" <foi2@example.com> +To: "foi" <foi3@example.com> +Subject: Foi request +Mime-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline + +Extra info. + +--=__PartFDD45234.0__= +Content-Type: image/jpeg; name="info.jpg" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="info.jpg" + +xxxx + +--=__PartFDD45234.0__=-- + diff --git a/spec/fixtures/files/incoming-request-attachment-unknown-extension.email b/spec/fixtures/files/incoming-request-attachment-unknown-extension.email index b3485ec2d..aecd9a52c 100644 --- a/spec/fixtures/files/incoming-request-attachment-unknown-extension.email +++ b/spec/fixtures/files/incoming-request-attachment-unknown-extension.email @@ -4,17 +4,16 @@ Subject: Same attachment twice Content-Type: multipart/mixed; boundary="Q68bSM7Ycu6FN28Q" Content-Disposition: inline - --Q68bSM7Ycu6FN28Q Content-Type: text/plain; charset=utf-8 Content-Disposition: inline - --Q68bSM7Ycu6FN28Q Content-Type: application/x-nonsense Content-Disposition: attachment; filename="hello.qwglhm" This is an unusual sort of file. ---Q68bSM7Ycu6FN28Q +--Q68bSM7Ycu6FN28Q-- + diff --git a/spec/fixtures/files/many-attachments-date-header.email b/spec/fixtures/files/many-attachments-date-header.email new file mode 100644 index 000000000..a241e2456 --- /dev/null +++ b/spec/fixtures/files/many-attachments-date-header.email @@ -0,0 +1,451 @@ +From email@example.com Wed Apr 14 11:23:08 2010 +Return-path: <email@example.com> +Envelope-to: email@example.com +Delivery-date: Wed, 14 Apr 2010 11:23:08 +0100 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from example.com ([0.0.0.0]) by example.com ([0.0.0.0]) with ESMTP (TREND IMSS SMTP Service 7.0) id 1ec0f7ac0002a77f ; Wed, 14 Apr 2010 11:22:52 +0100 +Received: from GWGATE-MTA by example.com + with Novell_GroupWise; Wed, 14 Apr 2010 11:22:53 +0100 +Message-Id: <email@example.com> +X-Mailer: Novell GroupWise Internet Agent 8.0.1 +Date: Wed, 14 Apr 2010 11:22:47 +0100 +From: "A Person" <email@example.com> +To: <email@example.com> +Cc: "FOI FOI" <email@example.com>, + "A Person" <email@example.com> +Subject: Fwd: Re: Freedom of Information request +References: <email@example.com> + <email@example.com> +Mime-Version: 1.0 +Content-Type: multipart/mixed; boundary="=__Part163C9567.0__=" + +This is a MIME message. If you are reading this text, you may want to +consider changing to a mail reader or gateway that understands how to +properly handle MIME multipart messages. + +--=__Part163C9567.0__= +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline + +Some information + + +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Date: Wed, 10 Mar 2010 14:17:52 +0000 +From: "A Person" <email@example.com> +To: "A Person" <email@example.com> +Subject: Re: xxx +Mime-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline + +2 + +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Tue, 24 Nov 2009 10:45:58 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from example.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 00660acd00000f42 ; Tue, 24 Nov 2009 10:45:55 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob115.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Tue, 24 Nov 2009 10:45:56 UTC +Received: from example.com ([::1]) by + example.com ([::1]) with mapi; Tue, 24 Nov 2009 + 10:45:53 +0000 +From: A Person <email@example.com> +To: email@example.com <email@example.com> +Date: Tue, 24 Nov 2009 10:45:52 +0000 +Subject: example +Thread-Topic: example +Thread-Index: AcpnbI2i+XAmfHFVTFy0eGDpVJhXoQFhVeZw +Message-ID: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: yes +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: multipart/mixed; + boundary="_006_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_" +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17028.005 +X-TM-AS-Result: No--19.329-5.0-31-1 +X-imss-scan-details: No--19.329-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: multipart/related; + boundary="_005_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_"; + type="multipart/alternative" + +--_005_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: multipart/alternative; + boundary="_000_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_" + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: text/plain; charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + + +3 + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: text/html; charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + +4 + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_-- + +--_005_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: image/gif; name="image001.gif" +Content-Description: image001.gif +Content-Disposition: inline; filename="image001.gif"; size=5445; + creation-date="Tue, 17 Nov 2009 09:58:46 GMT"; + modification-date="Tue, 17 Nov 2009 09:58:46 GMT" +Content-ID: <email@example.com> +Content-Transfer-Encoding: base64 + +5 +--_005_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_-- + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: application/vnd.ms-excel; + name="particpant list.xls" +Content-Description: particpant list.xls +Content-Disposition: attachment; + filename="particpant list.xls"; size=21504; + creation-date="Mon, 02 Nov 2009 09:42:37 GMT"; + modification-date="Tue, 24 Nov 2009 10:45:52 GMT" +Content-Transfer-Encoding: base64 + +6 + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_-- +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Thu, 03 Dec 2009 09:29:07 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog116.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 0ac1bf1b0001116e ; Thu, 3 Dec 2009 09:29:04 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob116.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Thu, 03 Dec 2009 09:29:06 UTC +Received: from example.com ([::1]) by + example.com ([::1]) with mapi; Thu, 3 Dec 2009 09:29:03 + +0000 +From: A Person <email@example.com> +To: 'A Person' <email@example.com> +Date: Thu, 3 Dec 2009 09:29:03 +0000 +Subject: RE: example +Thread-Topic: example +Thread-Index: AcpuoEyRvzM8fXw+THuj/617pjnvCgFWqZdQ +Message-ID: <email@example.com> +References: <email@example.com> + <email@example.com> +In-Reply-To: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: base64 +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17046.004 +X-TM-AS-Result: No--16.791-5.0-31-1 +X-imss-scan-details: No--16.791-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + + +7 +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Wed, 25 Nov 2009 22:26:23 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog105.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 034354c900007016 ; Wed, 25 Nov 2009 22:26:19 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob105.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Wed, 25 Nov 2009 22:26:21 UTC +Received: from example.com ([::1]) by + example.com ([::1]) with mapi; Wed, 25 Nov 2009 + 22:26:15 +0000 +From: A Person <email@example.com> +To: email@example.com <email@example.com> +CC: A Person <email@example.com> +Date: Wed, 25 Nov 2009 22:26:12 +0000 +Subject: As promised - Masterclass info (example) +Thread-Topic: As promised - Masterclass info (example) +Thread-Index: AcpuHcJ4yrR8PBHZTVCU/RLGzwqsDAAACGwQ +Message-ID: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: yes +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: multipart/mixed; + boundary="_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_" +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17032.000 +X-TM-AS-Result: No--26.167-5.0-31-1 +X-imss-scan-details: No--26.167-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + + +--_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: multipart/related; + boundary="_006_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_"; + type="multipart/alternative" + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: multipart/alternative; + boundary="_000_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_" + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: base64 + +8 +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: base64 + +9 +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_-- + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: image/gif; name="image001.gif" +Content-Description: image001.gif +Content-Disposition: inline; filename="image001.gif"; size=5445; + creation-date="Wed, 25 Nov 2009 22:26:14 GMT"; + modification-date="Wed, 25 Nov 2009 22:26:14 GMT" +Content-ID: <email@example.com> +Content-Transfer-Encoding: base64 + + +10 + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_-- + +--_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: application/msword; + name= "Participant List.doc" +Content-Description: Participant List.doc +Content-Disposition: attachment; + filename="Participant List.doc"; size=112640; + creation-date="Wed, 25 Nov 2009 22:17:24 GMT"; + modification-date="Wed, 25 Nov 2009 11:43:48 GMT" +Content-Transfer-Encoding: base64 + +11 +--_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: application/msword; name="Information & Booking Form.doc" +Content-Description: Information & Booking Form.doc +Content-Disposition: attachment; filename="Information & Booking Form.doc"; size=84480; + creation-date="Wed, 25 Nov 2009 22:17:40 GMT"; + modification-date="Wed, 04 Nov 2009 14:42:54 GMT" +Content-Transfer-Encoding: base64 + +12 + +--_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_-- +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Fri, 04 Dec 2009 10:00:05 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog109.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 100473260001a476 ; Fri, 4 Dec 2009 10:00:01 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob109.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Fri, 04 Dec 2009 10:00:04 UTC +Received: from example.com ([::1]) by + example.com ([::1]) with mapi; Fri, 4 Dec 2009 10:00:01 + +0000 +From: A Person <email@example.com> +To: email@example.com <email@example.com> +Date: Fri, 4 Dec 2009 10:00:01 +0000 +Subject: Re: As promised - info (example) +Thread-Topic: As promised - info (example) +Thread-Index: AcpzhLeBjBId8eZATYudOfBgN6CPXQBQ9Pok +Message-ID: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: base64 +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17048.005 +X-TM-AS-Result: No--24.171-5.0-31-1 +X-imss-scan-details: No--24.171-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + +13 +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Sun, 21 Mar 2010 21:53:38 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog117.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 1e3611c1000d37df ; Sun, 21 Mar 2010 21:53:32 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob117.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Sun, 21 Mar 2010 21:53:37 UTC +Received: from example.com ([::1]) by exchhub01 + ([0.0.0.0]) with mapi; Sun, 21 Mar 2010 21:53:34 +0000 +From: A Person <email@example.com> +To: email@example.com <email@example.com> +CC: A Person <email@example.com> +Date: Sun, 21 Mar 2010 21:53:32 +0000 +Subject: Thank you from example +Thread-Topic: Thank you from example +Thread-Index: AcrJQPL4xb9zjXMHRJGTjAxo3X/kfA== +Message-ID: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: yes +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: multipart/related; + boundary="_004_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_"; + type="multipart/alternative" +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17266.002 +X-TM-AS-Result: No--26.373-5.0-31-1 +X-imss-scan-details: No--26.373-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + + +--_004_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_ +Content-Type: multipart/alternative; + boundary="_000_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_" + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_ +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: quoted-printable + +14 + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_ +Content-Type: text/html; charset="us-ascii" +Content-Transfer-Encoding: quoted-printable + +15 + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_-- + +--_004_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_ +Content-Type: image/gif; name="image001.gif" +Content-Description: image001.gif +Content-Disposition: inline; filename="image001.gif"; size=5445; + creation-date="Sun, 21 Mar 2010 21:53:33 GMT"; + modification-date="Sun, 21 Mar 2010 21:53:33 GMT" +Content-ID: <email@example.com> +Content-Transfer-Encoding: base64 + +16 +--_004_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_-- +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Tue, 23 Feb 2010 15:33:48 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog112.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 96f54043000f2e72 ; Tue, 23 Feb 2010 15:33:48 +0000 +Received: from source ([0.0.0.0]) by eu1sys200aob112.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Tue, 23 Feb 2010 15:33:47 UTC +Received: from gla-002561-lap ([0.0.0.0]) by example.com with Microsoft SMTPSVC(0.0.0.0); + Tue, 23 Feb 2010 15:33:46 +0000 +Reply-To: email@example.com +From: email@example.com +To: email@example.com +Subject: example - Meeting - Tuesday 2nd March +Date: 23 February 2010 15:33 +X-Mailer: Internet Professional v1.15 +Return-Path: email@example.com +Message-ID: <email@example.com> +X-OriginalArrivalTime: 23 Feb 2010 15:33:46.0648 (UTC) FILETIME=[96CEC980:01CAB49D] +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17212.000 +X-TM-AS-Result: No--16.146-5.0-31-1 +X-imss-scan-details: No--16.146-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + +17 + +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Mon, 08 Mar 2010 09:21:42 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog117.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id d8931aff001580d6 ; Mon, 8 Mar 2010 09:21:40 +0000 +Received: from source ([0.0.0.0]) by eu1sys200aob117.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Mon, 08 Mar 2010 09:21:39 UTC +Received: from gla-002561-lap ([0.0.0.0]) by example.com with Microsoft SMTPSVC(0.0.0.0); + Mon, 8 Mar 2010 09:21:36 +0000 +Reply-To: email@example.com +From: email@example.com +To: email@example.com +Subject: example - Help needed +Date: 08 March 2010 09:21 +X-Mailer: Internet Professional v1.15 +MIME-Version: 1.0 +Content-Type: multipart/mixed;boundary="_NextPart_00009D35-00000F3C-00271781-26DF" +Return-Path: email@example.com +Message-ID: <email@example.com> +X-OriginalArrivalTime: 08 Mar 2010 09:21:36.0283 (UTC) FILETIME=[C03E3EB0:01CABEA0] +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17236.006 +X-TM-AS-Result: No--32.111-5.0-31-1 +X-imss-scan-details: No--32.111-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + +This message is in MIME format. Since your mail reader does not +understand this format, some or all of this message may not be legible. +--_NextPart_00009D35-00000F3C-00271781-26DF +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +18 + +--_NextPart_00009D35-00000F3C-00271781-26DF +Content-Type: application/octet-stream;name="Information Pack.pdf" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment;filename="Information Pack.pdf";size=106688 + +19 +--_NextPart_00009D35-00000F3C-00271781-26DF-- +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Date: Wed, 02 Dec 2009 19:21:27 +0000 +From: "A Person" <email@example.com> +To: "A Person" <email@example.com> +Subject: Re: As promised - info (example) +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-Disposition: inline + +20 +--=__Part163C9567.0__=-- + diff --git a/spec/fixtures/files/rfc822-attachment.email b/spec/fixtures/files/rfc822-attachment.email new file mode 100644 index 000000000..ae58a06af --- /dev/null +++ b/spec/fixtures/files/rfc822-attachment.email @@ -0,0 +1,147 @@ +From foi.officer@example.com Fri Mar 14 08:39:57 2008 +Return-path: <foi.officer@example.com> +Envelope-to: request-bounce-xx-xxxxx@whatdotheyknow.com +Delivery-date: Fri, 14 Mar 2008 08:39:57 +0000 +Received: from service27.mimecast.com ([213.235.63.79]:55305) + by tea.ukcod.org.uk with smtp (Exim 4.50) + id 1Ja5SH-0005iP-Jm + for xxx@whatdotheyknow.com; Fri, 14 Mar 2008 08:39:57 +0000 +Received: from mailscan.ad.example.com (mailgate.example.com [194.70.143.2]) + by service27.mimecast.com; + Fri, 14 Mar 2008 08:38:47 +0000 +Received: from exch2serv.ad.example.com ([201.234.62.4]) by mailscan.ad.example.com with InterScan Message Security Suite; Fri, 14 Mar 2008 08:38:47 -0000 +X-MIMEOLE: Produced By Microsoft Exchange V6.0.6603.0 +content-class: urn:content-classes:message +MIME-Version: 1.0 +Subject: +Date: Fri, 14 Mar 2008 08:38:46 -0000 +Message-ID: <0F3951EA9DCFB246827E1F6513F6C79D096DDADB@exch2serv.ad.example.com> +X-MS-Has-Attach: yes +X-MS-TNEF-Correlator: +Thread-Index: AciFrtIeS9pyMOhuQdyxkm5305zs9g== +From: "An FOI Officer" <foi.officer@example.com> +To: "On" <request-bounce-xx-xxxxx@whatdotheyknow.com> +X-MC-Unique: 108031408384702301 +Content-Type: multipart/mixed; + boundary="----_=_NextPart_001_01C885AE.D1BF23AC" + +This is a multi-part message in MIME format. + +------_=_NextPart_001_01C885AE.D1BF23AC +Content-Type: multipart/alternative; + boundary="MCBoundary=_108031408384800401" + +--MCBoundary=_108031408384800401 +Content-Type: text/plain; charset=WINDOWS-1252 +Content-Transfer-Encoding: quoted-printable + + + <<Freedom of Information request >>=20 + + +e-mail: foi.officer@example.com=20 + + + + +***************************************************************************= +******** +The information in this Email and any attachments is personal to the +sender and the views of the author may not necessarily reflect those +of Borough Council. The information is strictly confidential +and is intended only for the named person or organisation to whom it is +addressed as it may contain privileged and confidential information. If +you are not the intended recipient do not copy, distribute or use this +Email, and please notify the sender. Please note that we cannot +guarantee that this message or any attachment is virus free or has not +been intercepted and amended. +***************************************************************************= +******** + +Disclaimer=20 +---------------------------------------------------------------------------= +---------------- +This email message has been scanned for viruses by Mimecast. +Mimecast delivers a complete managed email solution from a single web based= + platform. +For more information please visit www.mimecast.com +---------------------------------------------------------------------------= +---------------- +--MCBoundary=_108031408384800401 +Content-Type: text/html; charset=WINDOWS-1252 +Content-Transfer-Encoding: quoted-printable + +<HTML><BODY> =20 + <BR> + <<Freedom of Information request >> <BR> +<BR> +e-mail: <a href=3D"mailto:foi.officer@example.com">foi.officer@example.com</a> <BR> +<BR> +<BR> +<BR> +<BR> +***************************************************************************= +********<BR> +The information in this Email and any attachments is personal to the<B= +R> +sender and the views of the author may not necessarily reflect those<BR= +> +of Borough Council. The information is strictly confidential<B= +R> +and is intended only for the named person or organisation to whom it is<BR> +addressed as it may contain privileged and confidential information. If<B= +R> +you are not the intended recipient do not copy, distribute or use this= +<BR> +Email, and please notify the sender. Please note that we cannot<B= +R> +guarantee that this message or any attachment is virus free or has not<BR> +been intercepted and amended.<BR> +***************************************************************************= +********<BR> + + <BR> + <BR> + <span style=3D"font-family:Arial; Font-size:10.0pt"> + Disclaimer <p> + <hr width=3D"100%"> + This email message has been scanned for viruses by Mimecast.<BR> + Mimecast delivers a complete managed email solution from a single we= +b based platform.<BR> + For more information please visit <a href=3D"http://www.mimecast.com= +">http://www.mimecast.com</a> + <hr width=3D"100%"> + </span> + </BODY></HTML> + + +--MCBoundary=_108031408384800401-- +------_=_NextPart_001_01C885AE.D1BF23AC +Content-Type: message/rfc822 +Content-Transfer-Encoding: 7bit + +X-MIMEOLE: Produced By Microsoft Exchange V6.0.6603.0 +content-class: urn:content-classes:message +MIME-Version: 1.0 +Subject: Freedom of Information request +Date: Thu, 13 Mar 2008 16:57:33 -0000 +Message-ID: <0F3951EA9DCFB246827E1F6513F6C79D098AC8C5@exch2serv.ad.example.com> +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +Thread-Topic: Freedom of Information request +Thread-Index: AciE9w0L7QnQlahDQS+Zjrz40mr8KAAD5KuQAADg+1AABjC9wAAAXtJgAAEHJvAAAHTxwA== +X-Priority: 1 +Priority: Urgent +Importance: high +From: "An FOI Officer" <foi.officer@example.com> +To: <request-bounce-xx-xxxxx@whatdotheyno.com> +Content-Type: text/plain; + charset="utf-8" +Content-Transfer-Encoding: base64 + +c29tZSBleGFtcGxlIHRleHQ= + +------_=_NextPart_001_01C885AE.D1BF23AC-- + + + diff --git a/spec/lib/i18n_interpolation.rb b/spec/lib/i18n_interpolation.rb index 8c86413ad..6b745059c 100644 --- a/spec/lib/i18n_interpolation.rb +++ b/spec/lib/i18n_interpolation.rb @@ -1,6 +1,3 @@ -# This is a test of the set_content_type monkey patch in -# lib/tmail_extensions.rb - require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe "when using i18n" do diff --git a/spec/lib/mail_handler/mail_handler_spec.rb b/spec/lib/mail_handler/mail_handler_spec.rb index a3fba0698..ae65210f2 100644 --- a/spec/lib/mail_handler/mail_handler_spec.rb +++ b/spec/lib/mail_handler/mail_handler_spec.rb @@ -1,6 +1,12 @@ # coding: utf-8 require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper') +def create_message_from(from_field) + mail_data = load_file_fixture('incoming-request-plain.email') + mail_data.gsub!('EMAIL_FROM', from_field) + mail = MailHandler.mail_from_raw_email(mail_data) +end + describe 'when creating a mail object from raw data' do it 'should correctly parse a multipart email with a linebreak in the boundary' do @@ -17,7 +23,361 @@ describe 'when creating a mail object from raw data' do it 'should convert an iso8859 email to utf8' do mail = get_fixture_mail('iso8859_2_raw_email.email') mail.subject.should have_text(/gjatë/u) - mail.body.is_utf8?.should == true + MailHandler.get_part_body(mail).is_utf8?.should == true + end + +end + +describe 'when asked for the from name' do + + it 'should return nil if there is a blank "From" field' do + mail = create_message_from('') + MailHandler.get_from_name(mail).should == nil + end + + it 'should correctly return an encoded name from the from field' do + mail = get_fixture_mail('quoted-subject-iso8859-1.email') + MailHandler.get_from_name(mail).should == 'Coordenação de Relacionamento, Pesquisa e Informação/CEDI' + end + + it 'should get a name from a "From" field with a name and address' do + mail = get_fixture_mail('incoming-request-oft-attachments.email') + MailHandler.get_from_name(mail).should == 'Public Authority' + end + + it 'should return nil from a "From" field that is just a name'do + mail = get_fixture_mail('track-response-webshield-bounce.email') + MailHandler.get_from_name(mail).should == nil + end + +end + +describe 'when asked for the from address' do + + it 'should return nil if there is a blank "From" field' do + mail = create_message_from('') + MailHandler.get_from_address(mail).should == nil + end + + it 'should correctly return an address from a mail that has an encoded name in the from field' do + mail = get_fixture_mail('quoted-subject-iso8859-1.email') + MailHandler.get_from_address(mail).should == 'geraldinequango@localhost' + end + + it 'should return nil if there is no address in the "From" field' do + mail = get_fixture_mail('track-response-webshield-bounce.email') + MailHandler.get_from_address(mail).should == nil + end + + it 'should return the "From" email address if there is one' do + mail = get_fixture_mail('track-response-abcmail-oof.email') + MailHandler.get_from_address(mail).should == 'Name.Removed@example.gov.uk' + end + + it 'should get an address from a "From" field with a name and address' do + mail = get_fixture_mail('incoming-request-oft-attachments.email') + MailHandler.get_from_address(mail).should == 'public@authority.gov.uk' + end +end + +describe 'when asked for all the addresses a mail has been sent to' do + + it 'should return an array containing the envelope-to address and the to address, and the cc address if there is one' do + mail_data = load_file_fixture('humberside-police-odd-mime-type.email') + mail_data.gsub!('Envelope-to: request-5335-xxxxxxxx@whatdotheyknow.com', + 'Envelope-to: request-5555-xxxxxxxx@whatdotheyknow.com') + mail_data.gsub!('Cc: request-5335-xxxxxxxx@whatdotheyknow.com', + 'Cc: request-3333-xxxxxxxx@whatdotheyknow.com') + mail = MailHandler.mail_from_raw_email(mail_data) + MailHandler.get_all_addresses(mail).should == ['request-5335-xxxxxxxx@whatdotheyknow.com', + 'request-3333-xxxxxxxx@whatdotheyknow.com', + 'request-5555-xxxxxxxx@whatdotheyknow.com'] + end + + it 'should only return unique values' do + # envelope-to and to fields are the same + mail = get_fixture_mail('humberside-police-odd-mime-type.email') + MailHandler.get_all_addresses(mail).should == ['request-5335-xxxxxxxx@whatdotheyknow.com'] + end + + it 'should handle the absence of an envelope-to or cc field' do + mail_data = load_file_fixture('autoresponse-header.email') + mail_data.gsub!('To: FOI Person <EMAIL_TO>', + 'To: FOI Person <request-5555-xxxxxxxx@whatdotheyknow.com>') + mail = MailHandler.mail_from_raw_email(mail_data) + MailHandler.get_all_addresses(mail).should == ["request-5555-xxxxxxxx@whatdotheyknow.com"] + end +end + +describe 'when asked for auto_submitted' do + + it 'should return a string value for an email with an auto-submitted header' do + mail = get_fixture_mail('autoresponse-header.email') + MailHandler.get_auto_submitted(mail).should == 'auto-replied' + end + + it 'should return a nil value for an email with no auto-submitted header' do + mail = get_fixture_mail('incoming-request-plain.email') + MailHandler.get_auto_submitted(mail).should == nil + end + +end + +describe 'when asked if there is an empty return path' do + + it 'should return true if there is an empty return-path specified' do + mail = get_fixture_mail('empty-return-path.email') + MailHandler.empty_return_path?(mail).should == true + end + + it 'should return false if there is no return-path header' do + mail = get_fixture_mail('incoming-request-attach-attachments.email') + MailHandler.empty_return_path?(mail).should == false + end + + it 'should return false if there is a return path address' do + mail = get_fixture_mail('autoresponse-header.email') + MailHandler.empty_return_path?(mail).should == false + end +end + +describe 'when deriving a name, email and formatted address from a message from a line' do + + def should_render_from_address(from_line, expected_result) + mail = create_message_from(from_line) + name = MailHandler.get_from_name(mail) + email = MailHandler.get_from_address(mail) + address = MailHandler.address_from_name_and_email(name, email).to_s + [name, email, address].should == expected_result + end + + it 'should correctly render a name with quoted commas' do + should_render_from_address('"Clare College, Cambridge" <test@test.test>', + ['Clare College, Cambridge', + 'test@test.test', + '"Clare College, Cambridge" <test@test.test>']) end + it 'should correctly reproduce a simple name and email that does not need quotes' do + should_render_from_address('"FOI Person" <foiperson@localhost>', + ['FOI Person', + 'foiperson@localhost', + 'FOI Person <foiperson@localhost>']) + end + + it 'should render an address with no name' do + should_render_from_address("foiperson@localhost", + [nil, + "foiperson@localhost", + "foiperson@localhost"]) + end + + it 'should quote a name with a square bracked in it' do + should_render_from_address('"FOI [ Person" <foiperson@localhost>', + ['FOI [ Person', + 'foiperson@localhost', + '"FOI [ Person" <foiperson@localhost>']) + end + + it 'should quote a name with an @ in it' do + should_render_from_address('"FOI @ Person" <foiperson@localhost>', + ['FOI @ Person', + 'foiperson@localhost', + '"FOI @ Person" <foiperson@localhost>']) + end + + + it 'should quote a name with quotes in it' do + should_render_from_address('"FOI \" Person" <foiperson@localhost>', + ['FOI " Person', + 'foiperson@localhost', + '"FOI \" Person" <foiperson@localhost>']) + end + +end + +describe 'when getting the content type of a mail part' do + + def expect_content_type(fixture_file, content_type) + mail = get_fixture_mail(fixture_file) + MailHandler.get_content_type(mail).should == content_type + end + + it 'should correctly return a type of "multipart/report"' do + expect_content_type('track-response-multipart-report.email', 'multipart/report') + end + + it 'should correctly return a type of "text/plain"' do + expect_content_type('track-response-abcmail-oof.email', 'text/plain') + end + + it 'should correctly return a type of "multipart/mixed"' do + expect_content_type('track-response-messageclass-oof.email', 'multipart/mixed') + end + + it 'should correctly return the types in an example bounce report' do + mail = get_fixture_mail('track-response-ms-bounce.email') + report = mail.parts.detect{ |part| MailHandler.get_content_type(part) == 'multipart/report'} + MailHandler.get_content_type(report.parts[0]).should == 'text/plain' + MailHandler.get_content_type(report.parts[1]).should == 'message/delivery-status' + MailHandler.get_content_type(report.parts[2]).should == 'message/rfc822' + end + +end + +describe 'when getting header strings' do + + def expect_header_string(fixture_file, header, header_string) + mail = get_fixture_mail(fixture_file) + MailHandler.get_header_string(header, mail).should == header_string + end + + it 'should return the contents of a "Subject" header' do + expect_header_string('track-response-ms-bounce.email', + 'Subject', + 'Delivery Status Notification (Delay)') + end + + it 'should return the contents of an "X-Failed-Recipients" header' do + expect_header_string('autoresponse-header.email', + 'X-Failed-Recipients', + 'enquiries@cheese.com') + end + + it 'should return the contents of an example "" header' do + expect_header_string('track-response-messageclass-oof.email', + 'X-POST-MessageClass', + '9; Autoresponder') + end + +end + +describe "when parsing HTML mail" do + it "should display UTF-8 characters in the plain text version correctly" do + html = "<html><b>foo</b> është" + plain_text = MailHandler.get_attachment_text_one_file('text/html', html) + plain_text.should match(/është/) + end + +end + +describe "when getting the attachment text" do + it "should not raise an error if the expansion of a zip file raises an error" do + mock_entry = mock('ZipFile entry', :file? => true) + mock_entries = [mock_entry] + mock_entries.stub!(:close) + mock_entry.stub!(:get_input_stream).and_raise("invalid distance too far back") + Zip::ZipFile.stub!(:open).and_return(mock_entries) + MailHandler.get_attachment_text_one_file('application/zip', "some string") + end + +end + +describe 'when getting attachment attributes' do + + it 'should get two attachment parts from a multipart mail with text and html alternatives + and an image' do + mail = get_fixture_mail('quoted-subject-iso8859-1.email') + attributes = MailHandler.get_attachment_attributes(mail) + attributes.size.should == 2 + end + + it 'should expand a mail attached as text' do + mail = get_fixture_mail('rfc822-attachment.email') + attributes = MailHandler.get_attachment_attributes(mail) + attributes.size.should == 2 + rfc_attachment = attributes[1] + rfc_attachment[:within_rfc822_subject].should == 'Freedom of Information request' + headers = ['Date: Thu, 13 Mar 2008 16:57:33 +0000', + 'Subject: Freedom of Information request', + 'From: An FOI Officer <foi.officer@example.com>', + 'To: request-bounce-xx-xxxxx@whatdotheyno.com'] + rfc_attachment[:body].should == "#{headers.join("\n")}\n\nsome example text" + end + + it 'should handle a mail which causes Tmail to generate a blank header value' do + mail = get_fixture_mail('many-attachments-date-header.email') + attributes = MailHandler.get_attachment_attributes(mail) + end + + it 'should produce a consistent set of url_part_numbers, content_types, within_rfc822_subjects + and filenames from an example mail with lots of attachments' do + mail = get_fixture_mail('many-attachments-date-header.email') + attributes = MailHandler.get_attachment_attributes(mail) + + expected_attributes = [ { :content_type=>"text/plain", + :url_part_number=>1, + :within_rfc822_subject=>nil, + :filename=>nil}, + { :content_type=>"text/plain", + :url_part_number=>2, + :within_rfc822_subject=>"Re: xxx", + :filename=>nil}, + { :content_type=>"text/html", + :url_part_number=>4, + :within_rfc822_subject=>"example", + :filename=>nil}, + { :content_type=>"image/gif", :url_part_number=>5, + :within_rfc822_subject=>"example", + :filename=>"image001.gif"}, + { :content_type=>"application/vnd.ms-excel", + :url_part_number=>6, + :within_rfc822_subject=>"example", + :filename=>"particpant list.xls"}, + { :content_type=>"text/plain", + :url_part_number=>7, + :within_rfc822_subject=>"RE: example", + :filename=>nil}, + { :content_type=>"text/html", + :url_part_number=>9, + :within_rfc822_subject=>"As promised - Masterclass info (example)", + :filename=>nil}, + { :content_type=>"image/gif", + :url_part_number=>10, + :within_rfc822_subject=>"As promised - Masterclass info (example)", + :filename=>"image001.gif"}, + { :content_type=>"application/vnd.ms-word", + :url_part_number=>11, + :within_rfc822_subject=>"As promised - Masterclass info (example)", + :filename=>"Participant List.doc"}, + { :content_type=>"application/vnd.ms-word", + :url_part_number=>12, + :within_rfc822_subject=>"As promised - Masterclass info (example)", + :filename=>"Information & Booking Form.doc"}, + { :content_type=>"text/plain", + :url_part_number=>13, + :within_rfc822_subject=>"Re: As promised - info (example)", + :filename=>nil}, + { :content_type=>"text/html", + :url_part_number=>15, + :within_rfc822_subject=>"Thank you from example", + :filename=>nil}, + { :content_type=>"image/gif", + :url_part_number=>16, + :within_rfc822_subject=>"Thank you from example", + :filename=>"image001.gif"}, + { :content_type=>"text/plain", + :url_part_number=>17, + :within_rfc822_subject=>"example - Meeting - Tuesday 2nd March", + :filename=>nil}, + { :content_type=>"text/plain", + :url_part_number=>18, + :within_rfc822_subject=>"example - Help needed", + :filename=>nil}, + { :content_type=>"application/pdf", + :url_part_number=>19, + :within_rfc822_subject=>"example - Help needed", + :filename=>"Information Pack.pdf"}, + { :content_type=>"text/plain", + :url_part_number=>20, + :within_rfc822_subject=>"Re: As promised - info (example)", + :filename=>nil} ] + + attributes.each_with_index do |attr, index| + attr.delete(:charset) + attr.delete(:body) + attr.delete(:hexdigest) + attr.should == expected_attributes[index] + end + end end diff --git a/spec/models/incoming_message_spec.rb b/spec/models/incoming_message_spec.rb index fdbcd1e23..97bf78cb6 100644 --- a/spec/models/incoming_message_spec.rb +++ b/spec/models/incoming_message_spec.rb @@ -26,13 +26,8 @@ describe IncomingMessage, " when dealing with incoming mail" do @im.sent_at.should == @im.mail.date end - it "should be able to parse emails with quoted commas in" do - em = "\"Clare College, Cambridge\" <test@test.test>" - TMail::Address.parse(em) - end - it "should correctly fold various types of footer" do - Dir.glob(File.join(Spec::Runner.configuration.fixture_path, "files", "email-folding-example-*.txt")).each do |file| + Dir.glob(File.join(RSpec.configuration.fixture_path, "files", "email-folding-example-*.txt")).each do |file| message = File.read(file) parsed = IncomingMessage.remove_quoted_sections(message) expected = File.read("#{file}.expected") @@ -73,6 +68,14 @@ describe IncomingMessage, " when dealing with incoming mail" do message.get_main_body_text_internal.should include("The above text was badly encoded") end + it 'should convert DOS-style linebreaks to Unix style' do + ir = info_requests(:fancy_dog_request) + receive_incoming_mail('dos-linebreaks.email', ir.incoming_email) + message = ir.incoming_messages[1] + message.parse_raw_email! + message.get_main_body_text_internal.should_not match(/\r\n/) + end + it "should fold multiline sections" do { "foo\n--------\nconfidential" => "foo\nFOLDED_QUOTED_SECTION\n", # basic test @@ -107,27 +110,6 @@ describe IncomingMessage, " when dealing with incoming mail" do end -describe IncomingMessage, "when parsing HTML mail" do - it "should display UTF-8 characters in the plain text version correctly" do - html = "<html><b>foo</b> është" - plain_text = IncomingMessage._get_attachment_text_internal_one_file('text/html', html) - plain_text.should match(/është/) - end - -end - -describe IncomingMessage, "when getting the attachment text" do - - it "should not raise an error if the expansion of a zip file raises an error" do - mock_entry = mock('ZipFile entry', :file? => true) - mock_entry.stub!(:get_input_stream).and_raise("invalid distance too far back") - Zip::ZipFile.stub!(:open).and_return([mock_entry]) - IncomingMessage._get_attachment_text_internal_one_file('application/zip', "some string") - end - -end - - describe IncomingMessage, " display attachments" do it "should not show slashes in filenames" do @@ -143,7 +125,7 @@ describe IncomingMessage, " display attachments" do # http://www.whatdotheyknow.com/request/post_commercial_manager_librarie#incoming-17233 foi_attachment.within_rfc822_subject = "FOI/09/066 RESPONSE TO FOI REQUEST RECEIVED 21st JANUARY 2009" foi_attachment.content_type = 'text/plain' - foi_attachment.ensure_filename! + foi_attachment.ensure_filename! expected_display_filename = foi_attachment.within_rfc822_subject.gsub(/\//, " ") + ".txt" foi_attachment.display_filename.should == expected_display_filename end @@ -194,59 +176,50 @@ describe IncomingMessage, " folding quoted parts of emails" do end describe IncomingMessage, " checking validity to reply to" do - def test_email(result, email, return_path, autosubmitted = nil) - @address = mock(TMail::Address) - @address.stub!(:spec).and_return(email) - - @return_path = mock(TMail::ReturnPathHeader) - @return_path.stub!(:addr).and_return(return_path) - if !autosubmitted.nil? - @autosubmitted = TMail::UnstructuredHeader.new("auto-submitted", autosubmitted) - end - @mail = mock(TMail::Mail) - @mail.stub!(:from_addrs).and_return( [ @address ] ) - @mail.stub!(:[]).with("return-path").and_return(@return_path) - @mail.stub!(:[]).with("auto-submitted").and_return(@autosubmitted) - + def test_email(result, email, empty_return_path, autosubmitted = nil) + @mail = mock('mail') + MailHandler.stub!(:get_from_address).and_return(email) + MailHandler.stub!(:empty_return_path?).with(@mail).and_return(empty_return_path) + MailHandler.stub!(:get_auto_submitted).with(@mail).and_return(autosubmitted) @incoming_message = IncomingMessage.new() @incoming_message.stub!(:mail).and_return(@mail) @incoming_message._calculate_valid_to_reply_to.should == result end it "says a valid email is fine" do - test_email(true, "team@mysociety.org", nil) + test_email(true, "team@mysociety.org", false) end it "says postmaster email is bad" do - test_email(false, "postmaster@mysociety.org", nil) + test_email(false, "postmaster@mysociety.org", false) end it "says Mailer-Daemon email is bad" do - test_email(false, "Mailer-Daemon@mysociety.org", nil) + test_email(false, "Mailer-Daemon@mysociety.org", false) end it "says case mangled MaIler-DaemOn email is bad" do - test_email(false, "MaIler-DaemOn@mysociety.org", nil) + test_email(false, "MaIler-DaemOn@mysociety.org", false) end it "says Auto_Reply email is bad" do - test_email(false, "Auto_Reply@mysociety.org", nil) + test_email(false, "Auto_Reply@mysociety.org", false) end it "says DoNotReply email is bad" do - test_email(false, "DoNotReply@tube.tfl.gov.uk", nil) + test_email(false, "DoNotReply@tube.tfl.gov.uk", false) end it "says a filled-out return-path is fine" do - test_email(true, "team@mysociety.org", "Return-path: <foo@baz.com>") + test_email(true, "team@mysociety.org", false) end it "says an empty return-path is bad" do - test_email(false, "team@mysociety.org", "<>") + test_email(false, "team@mysociety.org", true) end it "says an auto-submitted keyword is bad" do - test_email(false, "team@mysociety.org", nil, "auto-replied") + test_email(false, "team@mysociety.org", false, "auto-replied") end end @@ -340,12 +313,12 @@ describe IncomingMessage, " when censoring data" do orig_pdf = load_file_fixture('tfl.pdf') pdf = orig_pdf.dup - orig_text = IncomingMessage._get_attachment_text_internal_one_file('application/pdf', pdf) + 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 = IncomingMessage._get_attachment_text_internal_one_file('application/pdf', 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 @@ -455,6 +428,24 @@ end describe IncomingMessage, "when messages are attached to messages" do + it 'should expand an RFC822 attachment' do + mail_body = load_file_fixture('rfc822-attachment.email') + mail = MailHandler.mail_from_raw_email(mail_body) + + im = incoming_messages(:useless_incoming_message) + im.stub!(:mail).and_return(mail) + + attachments = im.get_attachments_for_display + attachments.size.should == 1 + attachment = attachments.first + + attachment.content_type.should == 'text/plain' + attachment.filename.should == "Freedom of Information request.txt" + attachment.charset.should == "utf-8" + attachment.within_rfc822_subject.should == "Freedom of Information request" + attachment.hexdigest.should == 'f10fe56e4f2287685a58b71329f09639' + end + it "should flatten all the attachments out" do mail = get_fixture_mail('incoming-request-attach-attachments.email') @@ -470,6 +461,19 @@ describe IncomingMessage, "when messages are attached to messages" do 'hello.txt', ] end + + it 'should add headers to attached plain text message bodies' do + mail_body = load_file_fixture('incoming-request-attachment-headers.email') + mail = MailHandler.mail_from_raw_email(mail_body) + + im = incoming_messages(:useless_incoming_message) + im.stub!(:mail).and_return(mail) + + attachments = im.get_attachments_for_display + attachments.size.should == 2 + attachments[0].body.should match('Date: Fri, 23 May 2008') + end + end describe IncomingMessage, "when Outlook messages are attached to messages" do diff --git a/spec/models/info_request_event_spec.rb b/spec/models/info_request_event_spec.rb index 796f8b840..842246fd8 100644 --- a/spec/models/info_request_event_spec.rb +++ b/spec/models/info_request_event_spec.rb @@ -21,7 +21,7 @@ describe InfoRequestEvent do :event_type => 'sent', :params => {}) event.should_receive(:xapian_mark_needs_index) - event.run_callbacks(:after_save) + event.run_callbacks(:save) end end diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb index 2aeac2fec..a1a6e6c27 100644 --- a/spec/models/info_request_spec.rb +++ b/spec/models/info_request_spec.rb @@ -2,6 +2,22 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe InfoRequest do + describe 'when generating a user name slug' do + + before do + @public_body = mock_model(PublicBody, :url_name => 'example_body', + :eir_only? => false) + @info_request = InfoRequest.new(:external_url => 'http://www.example.com', + :external_user_name => 'Example User', + :public_body => @public_body) + end + + it 'should generate a slug for an example user name' do + @info_request.user_name_slug.should == 'example_body_example_user' + end + + end + describe "guessing a request from an email" do before(:each) do @@ -410,8 +426,8 @@ describe InfoRequest do before do Time.stub!(:now).and_return(Time.utc(2007, 11, 9, 23, 59)) - @mock_comment_event = safe_mock_model(InfoRequestEvent, :created_at => Time.now - 23.days, :event_type => 'comment') - @mock_response_event = safe_mock_model(InfoRequestEvent, :created_at => Time.now - 22.days, :event_type => 'response') + @mock_comment_event = mock_model(InfoRequestEvent, :created_at => Time.now - 23.days, :event_type => 'comment') + @mock_response_event = mock_model(InfoRequestEvent, :created_at => Time.now - 22.days, :event_type => 'response') @info_request = InfoRequest.new(:prominence => 'normal', :awaiting_description => true, :info_request_events => [@mock_response_event, @mock_comment_event]) @@ -441,16 +457,16 @@ describe InfoRequest do describe 'when applying censor rules' do before do - @global_rule = safe_mock_model(CensorRule, :apply_to_text! => nil, + @global_rule = mock_model(CensorRule, :apply_to_text! => nil, :apply_to_binary! => nil) - @user_rule = safe_mock_model(CensorRule, :apply_to_text! => nil, + @user_rule = mock_model(CensorRule, :apply_to_text! => nil, :apply_to_binary! => nil) - @request_rule = safe_mock_model(CensorRule, :apply_to_text! => nil, + @request_rule = mock_model(CensorRule, :apply_to_text! => nil, :apply_to_binary! => nil) - @body_rule = safe_mock_model(CensorRule, :apply_to_text! => nil, + @body_rule = mock_model(CensorRule, :apply_to_text! => nil, :apply_to_binary! => nil) - @user = safe_mock_model(User, :censor_rules => [@user_rule]) - @body = safe_mock_model(PublicBody, :censor_rules => [@body_rule]) + @user = mock_model(User, :censor_rules => [@user_rule]) + @body = mock_model(PublicBody, :censor_rules => [@body_rule]) @info_request = InfoRequest.new(:prominence => 'normal', :awaiting_description => true, :title => 'title') diff --git a/spec/models/public_body_spec.rb b/spec/models/public_body_spec.rb index c2e0a6353..f247f561c 100644 --- a/spec/models/public_body_spec.rb +++ b/spec/models/public_body_spec.rb @@ -210,7 +210,7 @@ describe PublicBody, "when searching" do end it "should cope with same url_name across multiple locales" do - PublicBody.with_locale(:es) do + I18n.with_locale(:es) do # use the unique spanish name to retrieve and edit body = PublicBody.find_by_url_name_with_historic('etgq') body.short_name = 'tgq' # Same as english version @@ -231,7 +231,7 @@ end describe PublicBody, " when dealing public body locales" do it "shouldn't fail if it internal_admin_body was created in a locale other than the default" do # first time, do it with the non-default locale - PublicBody.with_locale(:es) do + I18n.with_locale(:es) do PublicBody.internal_admin_body end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index e31c3f1b5..651ba4b65 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -152,10 +152,10 @@ end describe User, "when reindexing referencing models" do before do - @request_event = safe_mock_model(InfoRequestEvent, :xapian_mark_needs_index => true) - @request = safe_mock_model(InfoRequest, :info_request_events => [@request_event]) - @comment_event = safe_mock_model(InfoRequestEvent, :xapian_mark_needs_index => true) - @comment = safe_mock_model(Comment, :info_request_events => [@comment_event]) + @request_event = mock_model(InfoRequestEvent, :xapian_mark_needs_index => true) + @request = mock_model(InfoRequest, :info_request_events => [@request_event]) + @comment_event = mock_model(InfoRequestEvent, :xapian_mark_needs_index => true) + @comment = mock_model(Comment, :info_request_events => [@comment_event]) @user = User.new(:comments => [@comment], :info_requests => [@request]) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d4dad591d..3c170ed16 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,35 +1,26 @@ -# This file is copied to ~/spec when you run 'ruby script/generate rspec' -# from the project root directory. -ENV["RAILS_ENV"] = 'test' -require File.expand_path(File.join('..', '..', 'config', 'environment'), __FILE__) -require 'spec/autorun' -require 'spec/rails' +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV["RAILS_ENV"] ||= 'test' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' +require 'rspec/autorun' -# set a default username and password so we can test -config = MySociety::Config.load_default() -config['ADMIN_USERNAME'] = 'foo' -config['ADMIN_PASSWORD'] = 'baz' +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} -# tests assume 20 days -config['REPLY_LATE_AFTER_DAYS'] = 20 - -# register a fake Varnish server -require 'fakeweb' -FakeWeb.register_uri(:purge, %r|varnish.localdomain|, :body => "OK") - -# Uncomment the next line to use webrat's matchers -#require 'webrat/integrations/rspec-rails' +RSpec.configure do |config| + # ## Mock Framework + # + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr -# Use test-specific translations -FastGettext.add_text_domain 'app', :path => File.join(File.dirname(__FILE__), 'fixtures', 'locale'), :type => :po -FastGettext.default_text_domain = 'app' -Spec::Runner.configure do |config| - # If you're not using ActiveRecord you should remove these - # lines, delete config/database.yml and disable :active_record - # in your config/boot.rb + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" - # fixture_path must end in a separator - config.fixture_path = File.join(Rails.root, 'spec', 'fixtures') + File::SEPARATOR + # The order (!) of this is important thanks to foreign keys config.global_fixtures = :users, :public_bodies, :public_body_translations, @@ -46,213 +37,19 @@ Spec::Runner.configure do |config| :holidays, :track_things_sent_emails - - # == Fixtures - # - # You can declare fixtures for each example_group like this: - # describe "...." do - # fixtures :table_a, :table_b - # - # Alternatively, if you prefer to declare them only once, you can - # do so right here. Just uncomment the next line and replace the fixture - # names with your fixtures. - # - # config.global_fixtures = :table_a, :table_b - # - # If you declare global fixtures, be aware that they will be declared - # for all of your examples, even those that don't use them. - # - # You can also declare which fixtures to use (for example fixtures for test/fixtures): - # - # config.fixture_path = Rails.root + '/spec/fixtures/' - # - # == Mock Framework - # - # RSpec uses its own mocking framework by default. If you prefer to - # use mocha, flexmock or RR, uncomment the appropriate line: - # - # config.mock_with :mocha - # config.mock_with :flexmock - # config.mock_with :rr - # - # == Notes - # - # For more information take a look at Spec::Runner::Configuration and Spec::Runner -end - -# XXX No idea what namespace/class/module to put this in -def receive_incoming_mail(email_name, email_to, email_from = 'geraldinequango@localhost') - email_name = file_fixture_name(email_name) - content = File.read(email_name) - content.gsub!('EMAIL_TO', email_to) - content.gsub!('EMAIL_FROM', email_from) - RequestMailer.receive(content) -end - -def file_fixture_name(file_name) - return File.join(Spec::Runner.configuration.fixture_path, "files", file_name) -end - -def load_file_fixture(file_name) - file_name = file_fixture_name(file_name) - content = File.read(file_name) - return content -end - -def parse_all_incoming_messages - IncomingMessage.find(:all).each{ |x| x.parse_raw_email! } -end - -def load_raw_emails_data - raw_emails_yml = File.join(Spec::Runner.configuration.fixture_path, "raw_emails.yml") - for raw_email_id in YAML::load_file(raw_emails_yml).map{|k,v| v["id"]} do - raw_email = RawEmail.find(raw_email_id) - raw_email.data = load_file_fixture("raw_emails/%d.email" % [raw_email_id]) - end -end - -# Rebuild the current xapian index -def rebuild_xapian_index(terms = true, values = true, texts = true, dropfirst = true) - if dropfirst - begin - ActsAsXapian.readable_init - FileUtils.rm_r(ActsAsXapian.db_path) - rescue RuntimeError - end - ActsAsXapian.writable_init - ActsAsXapian.writable_db.close - end - parse_all_incoming_messages - # safe_rebuild=true, which involves forking to avoid memory leaks, doesn't work well with rspec. - # unsafe is significantly faster, and we can afford possible memory leaks while testing. - models = [PublicBody, User, InfoRequestEvent] - ActsAsXapian.rebuild_index(models, verbose=false, terms, values, texts, safe_rebuild=false) -end - -# Create a clean xapian index based on the fixture files and the raw_email data. -def create_fixtures_xapian_index - load_raw_emails_data - rebuild_xapian_index -end - -def update_xapian_index - ActsAsXapian.update_index(flush_to_disk=false, verbose=false) -end - -# Copy the xapian index created in create_fixtures_xapian_index to a temporary -# copy at the same level and point xapian at the copy -def get_fixtures_xapian_index() - # Create a base index for the fixtures if not already created - $existing_xapian_db ||= create_fixtures_xapian_index - # Store whatever the xapian db path is originally - $original_xapian_path ||= ActsAsXapian.db_path - path_array = $original_xapian_path.split(File::Separator) - path_array.pop - temp_path = File.join(path_array, 'test.temp') - FileUtils.remove_entry_secure(temp_path, force=true) - FileUtils.cp_r($original_xapian_path, temp_path) - ActsAsXapian.db_path = temp_path -end - -# Validate an entire HTML page -def validate_html(html) - $tempfilecount = $tempfilecount + 1 - tempfilename = File.join(Dir::tmpdir, "railshtmlvalidate."+$$.to_s+"."+$tempfilecount.to_s+".html") - File.open(tempfilename, "w+") do |f| - f.puts html - end - if not system($html_validation_script, *($html_validation_script_options +[tempfilename])) - raise "HTML validation error in " + tempfilename + " HTTP status: " + @response.response_code.to_s - end - File.unlink(tempfilename) - return true -end - -# Validate HTML fragment by wrapping it as the <body> of a page -def validate_as_body(html) - validate_html('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' + - "<html><head><title>Test</title></head><body>#{html}</body></html>") -end - -def basic_auth_login(request, username = nil, password = nil) - username = Configuration::admin_username if username.nil? - password = Configuration::admin_password if password.nil? - request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{username}:#{password}") -end - -# Monkeypatch! Validate HTML in tests. -$html_validation_script_found = false -Configuration::utility_search_path.each do |d| - $html_validation_script = File.join(d, "validate") - $html_validation_script_options = ["--charset=utf-8"] - if File.file? $html_validation_script and File.executable? $html_validation_script - $html_validation_script_found = true - break - end -end -if $tempfilecount.nil? - $tempfilecount = 0 - if $html_validation_script_found - module ActionController - module TestProcess - # Hook into the process function, so can automatically get HTML after each request - alias :original_process :process - def is_fragment - # XXX there must be a better way of doing this! - return @request.query_parameters["action"] == "search_typeahead" - end - def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') - self.original_process(action, parameters, session, flash, http_method) - # don't validate auto-generated HTML - return if @request.query_parameters["action"] == "get_attachment_as_html" - # XXX Is there a better way to check this than calling a private method? - return unless @response.template.controller.instance_eval { integrate_views? } - # And then if HTML, not a redirect (302, 301) - if @response.content_type == "text/html" && ! [301,302,401].include?(@response.response_code) - if !is_fragment - validate_html(@response.body) - else - # it's a partial - validate_as_body(@response.body) - end - end - end - end - end - else - puts "WARNING: HTML validation script " + $html_validation_script + " not found" - end -end - -# to_ary differs in Ruby 1.8 and 1.9 -# @see http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/ -def safe_mock_model(model, args = {}) - mock = mock_model(model, args) - mock.should_receive(:to_ary).any_number_of_times - mock -end - -def get_fixture_mail(filename) - MailHandler.mail_from_raw_email(load_file_fixture(filename)) -end - -def load_test_categories - PublicBodyCategories.add(:en, [ - "Local and regional", - [ "local_council", "Local councils", "a local council" ], - "Miscellaneous", - [ "other", "Miscellaneous", "miscellaneous" ],]) -end - - -# Monkeypatch applicationcontroller because the `render_to_string` -# method in the original breaks all the rspec test assertions such as -# `should render_template('foo')`. Same problem as -# http://stackoverflow.com/questions/8174415/is-it-possible-to-assert-template-or-render-template-against-the-same-partial-wi -# - a bug in either Rails or Rspec I don't have the time to fix :( - -class ApplicationController < ActionController::Base - def set_popup_banner - @popup_banner = nil - end + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # If true, the base class of anonymous controllers will be inferred + # automatically. This will be the default behavior in future versions of + # rspec-rails. + config.infer_base_class_for_anonymous_controllers = false + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + #config.order = "random" end diff --git a/spec/spec_helper.rb.rails2 b/spec/spec_helper.rb.rails2 new file mode 100644 index 000000000..3be11c0c7 --- /dev/null +++ b/spec/spec_helper.rb.rails2 @@ -0,0 +1,152 @@ +# This file is copied to ~/spec when you run 'ruby script/generate rspec' +# from the project root directory. +ENV["RAILS_ENV"] = 'test' +require File.expand_path(File.join('..', '..', 'config', 'environment'), __FILE__) +require 'spec/autorun' +require 'spec/rails' + +# set a default username and password so we can test +config = MySociety::Config.load_default() +config['ADMIN_USERNAME'] = 'foo' +config['ADMIN_PASSWORD'] = 'baz' + +# tests assume 20 days +config['REPLY_LATE_AFTER_DAYS'] = 20 + +# register a fake Varnish server +require 'fakeweb' +FakeWeb.register_uri(:purge, %r|varnish.localdomain|, :body => "OK") + +# Uncomment the next line to use webrat's matchers +#require 'webrat/integrations/rspec-rails' + +# Use test-specific translations +FastGettext.add_text_domain 'app', :path => File.join(File.dirname(__FILE__), 'fixtures', 'locale'), :type => :po +FastGettext.default_text_domain = 'app' +Spec::Runner.configure do |config| + # If you're not using ActiveRecord you should remove these + # lines, delete config/database.yml and disable :active_record + # in your config/boot.rb + + # fixture_path must end in a separator + config.fixture_path = File.join(Rails.root, 'spec', 'fixtures') + File::SEPARATOR + config.global_fixtures = :users, + :public_bodies, + :public_body_translations, + :public_body_versions, + :info_requests, + :raw_emails, + :incoming_messages, + :outgoing_messages, + :comments, + :info_request_events, + :track_things, + :foi_attachments, + :has_tag_string_tags, + :holidays, + :track_things_sent_emails + + # This section makes the garbage collector run less often to speed up tests + last_gc_run = Time.now + + config.before(:each) do + GC.disable + end + + config.after(:each) do + if Time.now - last_gc_run > 4 + GC.enable + GC.start + last_gc_run = Time.now + end + end + + # == Fixtures + # + # You can declare fixtures for each example_group like this: + # describe "...." do + # fixtures :table_a, :table_b + # + # Alternatively, if you prefer to declare them only once, you can + # do so right here. Just uncomment the next line and replace the fixture + # names with your fixtures. + # + # config.global_fixtures = :table_a, :table_b + # + # If you declare global fixtures, be aware that they will be declared + # for all of your examples, even those that don't use them. + # + # You can also declare which fixtures to use (for example fixtures for test/fixtures): + # + # config.fixture_path = Rails.root + '/spec/fixtures/' + # + # == Mock Framework + # + # RSpec uses its own mocking framework by default. If you prefer to + # use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr + # + # == Notes + # + # For more information take a look at Spec::Runner::Configuration and Spec::Runner +end + +# XXX No idea what namespace/class/module to put this in +# Create a clean xapian index based on the fixture files and the raw_email data. +def create_fixtures_xapian_index + load_raw_emails_data + rebuild_xapian_index +end + +# Copy the xapian index created in create_fixtures_xapian_index to a temporary +# copy at the same level and point xapian at the copy +def get_fixtures_xapian_index() + # Create a base index for the fixtures if not already created + $existing_xapian_db ||= create_fixtures_xapian_index + # Store whatever the xapian db path is originally + $original_xapian_path ||= ActsAsXapian.db_path + path_array = $original_xapian_path.split(File::Separator) + path_array.pop + temp_path = File.join(path_array, 'test.temp') + FileUtils.remove_entry_secure(temp_path, force=true) + FileUtils.cp_r($original_xapian_path, temp_path) + ActsAsXapian.db_path = temp_path +end + +def basic_auth_login(request, username = nil, password = nil) + username = Configuration::admin_username if username.nil? + password = Configuration::admin_password if password.nil? + request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{username}:#{password}") +end + +# to_ary differs in Ruby 1.8 and 1.9 +# @see http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/ +def safe_mock_model(model, args = {}) + mock = mock_model(model, args) + mock.should_receive(:to_ary).any_number_of_times + mock +end + +def load_test_categories + PublicBodyCategories.add(:en, [ + "Local and regional", + [ "local_council", "Local councils", "a local council" ], + "Miscellaneous", + [ "other", "Miscellaneous", "miscellaneous" ],]) +end + + +# Monkeypatch applicationcontroller because the `render_to_string` +# method in the original breaks all the rspec test assertions such as +# `should render_template('foo')`. Same problem as +# http://stackoverflow.com/questions/8174415/is-it-possible-to-assert-template-or-render-template-against-the-same-partial-wi +# - a bug in either Rails or Rspec I don't have the time to fix :( + +class ApplicationController < ActionController::Base + def set_popup_banner + @popup_banner = nil + end +end diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb new file mode 100644 index 000000000..7e98c39f6 --- /dev/null +++ b/spec/support/email_helpers.rb @@ -0,0 +1,23 @@ +def load_raw_emails_data + raw_emails_yml = File.join(RSpec.configuration.fixture_path, "raw_emails.yml") + for raw_email_id in YAML::load_file(raw_emails_yml).map{|k,v| v["id"]} do + raw_email = RawEmail.find(raw_email_id) + raw_email.data = load_file_fixture("raw_emails/%d.email" % [raw_email_id]) + end +end + +def receive_incoming_mail(email_name, email_to, email_from = 'geraldinequango@localhost') + email_name = file_fixture_name(email_name) + content = File.read(email_name) + content.gsub!('EMAIL_TO', email_to) + content.gsub!('EMAIL_FROM', email_from) + RequestMailer.receive(content) +end + +def get_fixture_mail(filename) + MailHandler.mail_from_raw_email(load_file_fixture(filename)) +end + +def parse_all_incoming_messages + IncomingMessage.find(:all).each{ |x| x.parse_raw_email! } +end diff --git a/spec/support/load_file_fixtures.rb b/spec/support/load_file_fixtures.rb new file mode 100644 index 000000000..08079f654 --- /dev/null +++ b/spec/support/load_file_fixtures.rb @@ -0,0 +1,14 @@ +def file_fixture_name(file_name) + return File.join(RSpec.configuration.fixture_path, "files", file_name) +end + +def load_file_fixture(file_name, as_binary=false) + file_name = file_fixture_name(file_name) + content = File.open(file_name, 'r') do |file| + if as_binary + file.set_encoding(Encoding::BINARY) if file.respond_to?(:set_encoding) + end + file.read + end + return content +end diff --git a/spec/support/validate_html.rb b/spec/support/validate_html.rb new file mode 100644 index 000000000..ba40b395a --- /dev/null +++ b/spec/support/validate_html.rb @@ -0,0 +1,65 @@ +# Validate an entire HTML page +def validate_html(html) + $tempfilecount = $tempfilecount + 1 + tempfilename = File.join(Dir::tmpdir, "railshtmlvalidate."+$$.to_s+"."+$tempfilecount.to_s+".html") + File.open(tempfilename, "w+") do |f| + f.puts html + end + if not system($html_validation_script, *($html_validation_script_options +[tempfilename])) + raise "HTML validation error in " + tempfilename + " HTTP status: " + @response.response_code.to_s + end + File.unlink(tempfilename) + return true +end + +# Validate HTML fragment by wrapping it as the <body> of a page +def validate_as_body(html) + validate_html('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' + + "<html><head><title>Test</title></head><body>#{html}</body></html>") +end + +# Monkeypatch! Validate HTML in tests. +$html_validation_script_found = false +Configuration::utility_search_path.each do |d| + $html_validation_script = File.join(d, "validate") + $html_validation_script_options = ["--charset=utf-8"] + if File.file? $html_validation_script and File.executable? $html_validation_script + $html_validation_script_found = true + break + end +end +if $tempfilecount.nil? + $tempfilecount = 0 + if $html_validation_script_found + module ActionController + class TestCase + module Behavior + # Hook into the process function, so can automatically get HTML after each request + alias :original_process :process + def is_fragment + # XXX there must be a better way of doing this! + return @request.query_parameters["action"] == "search_typeahead" + end + def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') + self.original_process(action, parameters, session, flash, http_method) + # don't validate auto-generated HTML + return if @request.query_parameters["action"] == "get_attachment_as_html" + # XXX Is there a better way to check this than calling a private method? + return unless @response.template.controller.instance_eval { render_views? } + # And then if HTML, not a redirect (302, 301) + if @response.content_type == "text/html" && ! [301,302,401].include?(@response.response_code) + if !is_fragment + validate_html(@response.body) + else + # it's a partial + validate_as_body(@response.body) + end + end + end + end + end + end + else + puts "WARNING: HTML validation script " + $html_validation_script + " not found" + end +end diff --git a/spec/support/xapian_index.rb b/spec/support/xapian_index.rb new file mode 100644 index 000000000..21f6192ef --- /dev/null +++ b/spec/support/xapian_index.rb @@ -0,0 +1,21 @@ +# Rebuild the current xapian index +def rebuild_xapian_index(terms = true, values = true, texts = true, dropfirst = true) + if dropfirst + begin + ActsAsXapian.readable_init + FileUtils.rm_r(ActsAsXapian.db_path) + rescue RuntimeError + end + ActsAsXapian.writable_init + ActsAsXapian.writable_db.close + end + parse_all_incoming_messages + # safe_rebuild=true, which involves forking to avoid memory leaks, doesn't work well with rspec. + # unsafe is significantly faster, and we can afford possible memory leaks while testing. + models = [PublicBody, User, InfoRequestEvent] + ActsAsXapian.rebuild_index(models, verbose=false, terms, values, texts, safe_rebuild=false) +end + +def update_xapian_index + ActsAsXapian.update_index(flush_to_disk=false, verbose=false) +end diff --git a/spec/views/public_body/show.rhtml_spec.rb b/spec/views/public_body/show.rhtml_spec.rb index b68b3f43b..1a972a661 100644 --- a/spec/views/public_body/show.rhtml_spec.rb +++ b/spec/views/public_body/show.rhtml_spec.rb @@ -1,6 +1,6 @@ require File.expand_path(File.join('..', '..', '..', 'spec_helper'), __FILE__) -describe "when viewing a body" do +describe "public_body/show" do before do @pb = mock_model(PublicBody, :name => 'Test Quango', @@ -17,64 +17,62 @@ describe "when viewing a body" do @pb.stub!(:is_requestable?).and_return(true) @pb.stub!(:has_notes?).and_return(false) @pb.stub!(:has_tag?).and_return(false) - @xap = mock_model(ActsAsXapian::Search, :matches_estimated => 2) + @xap = mock(ActsAsXapian::Search, :matches_estimated => 2) @xap.stub!(:results).and_return([ { :model => mock_event }, { :model => mock_event } ]) - assigns[:public_body] = @pb - assigns[:track_thing] = mock_model(TrackThing, - :track_type => 'public_body_updates', :public_body => @pb, :params => {}) - assigns[:xapian_requests] = @xap - assigns[:page] = 1 - assigns[:per_page] = 10 - # work round a bug in ActionController::TestRequest; allows request.query_string to work in the template - request.env["REQUEST_URI"] = "" + assign(:public_body, @pb) + assign(:track_thing, mock_model(TrackThing, + :track_type => 'public_body_updates', :public_body => @pb, :params => {})) + assign(:xapian_requests, @xap) + assign(:page, 1) + assign(:per_page, 10) end it "should be successful" do - render "public_body/show" - response.should be_success + render + controller.response.should be_success end it "should be valid HTML" do - render "public_body/show" + render validate_as_body response.body end it "should show the body's name" do - render "public_body/show" - response.should have_tag("h1", "Test Quango") + render + response.should have_selector('h1', :content => "Test Quango") end it "should tell total number of requests" do - render "public_body/show" - response.should include_text("4 Freedom of Information requests") + render + response.should match "4 Freedom of Information requests" end it "should cope with no results" do @pb.stub!(:info_requests).and_return([]) - render "public_body/show" - response.should have_tag("p", /Nobody has made any Freedom of Information requests/m) + render + response.should have_selector('p', :content => "Nobody has made any Freedom of Information requests") end it "should cope with Xapian being down" do - assigns[:xapian_requests] = nil - render "public_body/show" - response.should have_tag("p", /The search index is currently offline/m) + assign(:xapian_requests, nil) + render + response.should match "The search index is currently offline" end it "should link to Charity Commission site if we have numbers to do so" do @pb.stub!(:has_tag?).and_return(true) @pb.stub!(:get_tag_values).and_return(['98765', '12345']) - render "public_body/show" - response.should have_tag("div#header_right") do - with_tag("a[href*=?]", /charity-commission.gov.uk.*RegisteredCharityNumber=98765$/) + render + response.should have_selector("div#header_right") do + have_selector "a", :href => /charity-commission.gov.uk.*RegisteredCharityNumber=98765$/ end - response.should have_tag("div#header_right") do - with_tag("a[href*=?]", /charity-commission.gov.uk.*RegisteredCharityNumber=12345$/) + response.should have_selector("div#header_right") do + have_selector "a", :href => /www.charity-commission.gov.uk.*RegisteredCharityNumber=12345$/ end end @@ -82,17 +80,17 @@ describe "when viewing a body" do @pb.stub!(:has_tag?).and_return(true) @pb.stub!(:get_tag_values).and_return(['SC1234']) - render "public_body/show" - response.should have_tag("div#header_right") do - with_tag("a[href*=?]", /www.oscr.org.uk.*id=SC1234$/) + render + response.should have_selector("div#header_right") do + have_selector "a", :href => /www.oscr.org.uk.*id=SC1234$/ end end it "should not link to Charity Commission site if we don't have number" do - render "public_body/show" - response.should have_tag("div#header_right") do - without_tag("a[href*=?]", /charity-commission.gov.uk/) + render + response.should have_selector("div#header_right") do + have_selector "a", :href => /charity-commission.gov.uk/ end end diff --git a/spec/views/request/_after_actions.rhtml_spec.rb b/spec/views/request/_after_actions.rhtml_spec.rb index 5b4734c52..54fef8cab 100644 --- a/spec/views/request/_after_actions.rhtml_spec.rb +++ b/spec/views/request/_after_actions.rhtml_spec.rb @@ -14,51 +14,27 @@ describe 'when displaying actions that can be taken with regard to a request' do :public_body => @mock_body, :comments_allowed? => true, :url_title => 'test_request') - assigns[:info_request] = @mock_request - end - - def do_render - render :partial => 'request/after_actions' - end - - def expect_owner_div - do_render - response.should have_tag('div#owner_actions'){ yield } - end - - def expect_anyone_div - do_render - response.should have_tag('div#anyone_actions'){ yield } - end - - def expect_owner_link(text) - expect_owner_div{ with_tag('a', :text => text) } - end - - def expect_no_owner_link(text) - expect_owner_div{ without_tag('a', :text => text) } - end - - def expect_anyone_link(text) - expect_anyone_div{ with_tag('a', :text => text) } - end - - def expect_no_anyone_link(text) - expect_anyone_div{ without_tag('a', :text => text) } + assign :info_request, @mock_request end describe 'if the request is old and unclassified' do before do - assigns[:old_unclassified] = true + assign :old_unclassified, true end it 'should not display a link for the request owner to update the status of the request' do - expect_no_owner_link('Update the status of this request') + render :partial => 'request/after_actions' + response.should have_selector('div#owner_actions') do |div| + div.should_not have_selector('a', :content => 'Update the status of this request') + end end it 'should display a link for anyone to update the status of the request' do - expect_anyone_link('Update the status of this request') + render :partial => 'request/after_actions' + response.should have_selector('div#anyone_actions') do |div| + div.should have_selector('a', :content => 'Update the status of this request') + end end end @@ -66,21 +42,30 @@ describe 'when displaying actions that can be taken with regard to a request' do describe 'if the request is not old and unclassified' do before do - assigns[:old_unclassified] = false + assign :old_unclassified, false end it 'should display a link for the request owner to update the status of the request' do - expect_owner_link('Update the status of this request') + render :partial => 'request/after_actions' + response.should have_selector('div#owner_actions') do |div| + div.should have_selector('a', :content => 'Update the status of this request') + end end it 'should not display a link for anyone to update the status of the request' do - expect_no_anyone_link('Update the status of this request') + render :partial => 'request/after_actions' + response.should have_selector('div#anyone_actions') do |div| + div.should_not have_selector('a', :content => 'Update the status of this request') + end end end it 'should display a link for the request owner to request a review' do - expect_owner_link('Request an internal review') + render :partial => 'request/after_actions' + response.should have_selector('div#owner_actions') do |div| + div.should have_selector('a', :content => 'Request an internal review') + end end end diff --git a/spec/views/request/_describe_state.rhtml_spec.rb b/spec/views/request/_describe_state.rhtml_spec.rb index 18778d5d2..41b308d75 100644 --- a/spec/views/request/_describe_state.rhtml_spec.rb +++ b/spec/views/request/_describe_state.rhtml_spec.rb @@ -4,12 +4,12 @@ describe 'when showing the form for describing the state of a request' do def expect_radio_button(value) do_render - response.should have_tag("input[type=radio][value=#{value}]") + response.should have_selector('input', :type => 'radio', :value => value) end def expect_no_radio_button(value) do_render - response.should_not have_tag("input[type=radio][value=#{value}]") + response.should_not have_selector('input', :type => 'radio', :value => value) end def do_render @@ -24,25 +24,25 @@ describe 'when showing the form for describing the state of a request' do :user_name => @mock_user.name, :is_external? => false ) - assigns[:info_request] = @mock_request + assign :info_request, @mock_request end describe 'if the user is a regular user (not the request owner)' do before do - assigns[:is_owning_user] = false + assign :is_owning_user, false end describe 'if the request is not old and unclassified' do it 'should not show the form' do do_render - response.should_not have_tag('h2', :text => 'What best describes the status of this request now?') + response.should_not have_selector('h2', :content => 'What best describes the status of this request now?') end it 'should give a link to login' do do_render - response.should have_tag('a', :text => 'sign in') + response.should have_selector('a', :content => 'sign in') end end @@ -50,22 +50,22 @@ describe 'when showing the form for describing the state of a request' do describe 'if the request is old and unclassified' do before do - assigns[:old_unclassified] = true + assign :old_unclassified, true end it 'should not show the form' do do_render - response.should_not have_tag('h2', :text => 'What best describes the status of this request now?') + response.should_not have_selector('h2', :content => 'What best describes the status of this request now?') end it 'should show the form for someone else to classify the request' do do_render - response.should have_tag('h2', :text => /We need your help/) + response.should have_selector('h2', :content => /We need your help/) end it 'should not give a link to login' do do_render - response.should_not have_tag('a', :text => 'sign in') + response.should_not have_selector('a', :content => 'sign in') end end @@ -74,7 +74,7 @@ describe 'when showing the form for describing the state of a request' do describe 'if showing the form to the user owning the request' do before do - assigns[:is_owning_user] = true + assign :is_owning_user, true end describe 'when the request is not in internal review' do @@ -100,7 +100,7 @@ describe 'when showing the form for describing the state of a request' do describe 'when the user has asked to update the status of the request' do before do - assigns[:update_status] = true + assign :update_status, true end it 'should show a radio button to set the status to "internal_review"' do @@ -129,7 +129,7 @@ describe 'when showing the form for describing the state of a request' do it 'should show the text "The review has finished and overall:"' do do_render - response.should have_tag('p', :text => 'The review has finished and overall:') + response.should have_selector('p', :content => 'The review has finished and overall:') end end @@ -170,4 +170,4 @@ describe 'when showing the form for describing the state of a request' do end end -end
\ No newline at end of file +end diff --git a/spec/views/request/list.rhtml_spec.rb b/spec/views/request/list.rhtml_spec.rb index 94ece5e76..8e34147b5 100644 --- a/spec/views/request/list.rhtml_spec.rb +++ b/spec/views/request/list.rhtml_spec.rb @@ -1,14 +1,10 @@ require File.expand_path(File.join('..', '..', '..', 'spec_helper'), __FILE__) -describe "when listing recent requests" do +describe "request/list" do before do - assigns[:page] = 1 - assigns[:per_page] = 10 - # work round a bug in ActionController::TestRequest; allows request.query_string to work in the template - request.env["REQUEST_URI"] = "" - # we're not testing the interlock plugin's cache - template.stub!(:view_cache).and_yield + assign :page, 1 + assign :per_page, 10 end def make_mock_event @@ -31,22 +27,22 @@ describe "when listing recent requests" do ) end - it "should be successful" do - assigns[:list_results] = [ make_mock_event, make_mock_event ] - assigns[:matches_estimated] = 2 - assigns[:show_no_more_than] = 100 - render "request/list" - response.should have_tag("div.request_listing") - response.should_not have_tag("p", /No requests of this sort yet/m) + it "should be successful", :focus => true do + assign :list_results, [ make_mock_event, make_mock_event ] + assign :matches_estimated, 2 + assign :show_no_more_than, 100 + render + response.should have_selector("div.request_listing") + response.should_not have_selector("p", :content => "No requests of this sort yet") end it "should cope with no results" do - assigns[:list_results] = [ ] - assigns[:matches_estimated] = 0 - assigns[:show_no_more_than] = 0 - render "request/list" - response.should have_tag("p", /No requests of this sort yet/m) - response.should_not have_tag("div.request_listing") + assign :list_results, [ ] + assign :matches_estimated, 0 + assign :show_no_more_than, 0 + render + response.should have_selector("p", :content => "No requests of this sort yet") + response.should_not have_selector("div.request_listing") end end diff --git a/spec/views/request/show.rhtml_spec.rb b/spec/views/request/show.rhtml_spec.rb index 4429e9e58..6e36a7ab6 100644 --- a/spec/views/request/show.rhtml_spec.rb +++ b/spec/views/request/show.rhtml_spec.rb @@ -23,32 +23,32 @@ describe 'when viewing an information request' do end def request_page - assigns[:info_request] = @mock_request - assigns[:info_request_events] = [] - assigns[:status] = @mock_request.calculate_status - template.stub!(:render_partial) + assign :info_request, @mock_request + assign :info_request_events, [] + assign :status, @mock_request.calculate_status + view.stub!(:render_partial) render 'request/show' end it 'should show the sidebar' do - template.should_receive(:render_partial).with(:partial => 'sidebar', :locals => {}) + view.should_receive(:render_partial).with(:partial => 'sidebar', :locals => {}) request_page end it 'should show the actions people can take' do - template.should_receive(:render_partial).with(:partial => 'after_actions', :locals => {}) + view.should_receive(:render_partial).with(:partial => 'after_actions', :locals => {}) request_page end describe 'when a status update has been requested' do before do - assigns[:update_status] = true + assign :update_status, true end it 'should show the first form for describing the state of the request' do request_page - response.should have_tag("div.describe_state_form#describe_state_form_1") + response.should have_selector("div.describe_state_form#describe_state_form_1") end end @@ -61,12 +61,12 @@ describe 'when viewing an information request' do it 'should show the first form for describing the state of the request' do request_page - response.should have_tag("div.describe_state_form#describe_state_form_1") + response.should have_selector("div.describe_state_form#describe_state_form_1") end it 'should show the second form for describing the state of the request' do request_page - response.should have_tag("div.describe_state_form#describe_state_form_2") + response.should have_selector("div.describe_state_form#describe_state_form_2") end end @@ -74,7 +74,7 @@ describe 'when viewing an information request' do describe 'when the user is the request owner' do before do - assigns[:is_owning_user] = true + assign :is_owning_user, true end describe 'when the request status is "waiting clarification"' do @@ -99,7 +99,7 @@ describe 'when viewing an information request' do it 'should show a link to follow up the last response with clarification' do request_page expected_url = "http://test.host/request/#{@mock_request.id}/response/#{@mock_response.id}#followup" - response.should have_tag("a[href=#{expected_url}]", :text => 'send a follow up message') + response.should have_selector("a[href=#{expected_url}]", :content => 'send a follow up message') end end @@ -119,7 +119,7 @@ describe 'when viewing an information request' do it 'should show a link to follow up the request without reference to a specific response' do request_page expected_url = "http://test.host/request/#{@mock_request.id}/response#followup" - response.should have_tag("a[href=#{expected_url}]", :text => 'send a follow up message') + response.should have_selector("a[href=#{expected_url}]", :content => 'send a follow up message') end end end diff --git a/spec/views/request_game/play.rhtml_spec.rb b/spec/views/request_game/play.rhtml_spec.rb index 24fb6d75d..0353f25b5 100644 --- a/spec/views/request_game/play.rhtml_spec.rb +++ b/spec/views/request_game/play.rhtml_spec.rb @@ -22,10 +22,10 @@ describe 'when viewing the request game' do :initial_request_text => 'hi there', :display_status => 'Awaiting categorisation', :created_at => Time.now) - assigns[:league_table_28_days] = [] - assigns[:league_table_all_time] = [] - assigns[:requests] = [@mock_request] - assigns[:play_urls] = true + assign :league_table_28_days, [] + assign :league_table_all_time, [] + assign :requests, [@mock_request] + assign :play_urls, true end it 'should show the correct url for a request' do |