diff options
Diffstat (limited to 'spec/integration')
-rw-r--r-- | spec/integration/admin_spec.rb | 79 | ||||
-rw-r--r-- | spec/integration/alaveteli_dsl.rb | 68 | ||||
-rw-r--r-- | spec/integration/cookie_stripping_spec.rb | 12 | ||||
-rw-r--r-- | spec/integration/create_request_spec.rb | 45 | ||||
-rw-r--r-- | spec/integration/download_request_spec.rb | 324 | ||||
-rw-r--r-- | spec/integration/errors_spec.rb | 159 | ||||
-rw-r--r-- | spec/integration/localisation_spec.rb | 88 | ||||
-rw-r--r-- | spec/integration/request_controller_spec.rb | 39 | ||||
-rw-r--r-- | spec/integration/search_request_spec.rb | 6 | ||||
-rw-r--r-- | spec/integration/view_request_spec.rb | 165 |
10 files changed, 891 insertions, 94 deletions
diff --git a/spec/integration/admin_spec.rb b/spec/integration/admin_spec.rb index e148ea3ca..8e6351d2c 100644 --- a/spec/integration/admin_spec.rb +++ b/spec/integration/admin_spec.rb @@ -1,21 +1,74 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') - -require "base64" +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') describe "When administering the site" do + + before do + AlaveteliConfiguration.stub!(:skip_admin_auth).and_return(false) + end + it "allows an admin to log in as another user" do # First log in as Joe Admin - admin_user = users(:admin_user) - admin_user.email_confirmed = true - admin_user.save! - post_via_redirect "/profile/sign_in", :user_signin => {:email => admin_user.email, :password => "jonespassword"} - response.should be_success - + confirm(:admin_user) + admin = login(:admin_user) + # Now fetch the "log in as" link to log in as Bob - get_via_redirect "/admin/user/login_as/#{users(:bob_smith_user).id}", nil, { - "Authorization" => "Basic " + Base64.encode64("#{Configuration::admin_username}:#{Configuration::admin_password}").strip - } - response.should be_success - session[:user_id].should == users(:bob_smith_user).id + admin.get_via_redirect "/en/admin/user/login_as/#{users(:bob_smith_user).id}" + admin.response.should be_success + admin.session[:user_id].should == users(:bob_smith_user).id + end + + it 'does not allow a non-admin user to login as another user' do + robin = login(:robin_user) + robin.get_via_redirect "/en/admin/user/login_as/#{users(:bob_smith_user).id}" + robin.response.should be_success + robin.session[:user_id].should_not == users(:bob_smith_user).id + end + + it "allows redelivery of an incoming message to a closed request" do + confirm(:admin_user) + admin = login(:admin_user) + ir = info_requests(:fancy_dog_request) + close_request(ir) + InfoRequest.holding_pen_request.incoming_messages.length.should == 0 + ir.incoming_messages.length.should == 1 + receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "frob@nowhere.com") + InfoRequest.holding_pen_request.incoming_messages.length.should == 1 + new_im = InfoRequest.holding_pen_request.incoming_messages[0] + ir.incoming_messages.length.should == 1 + post_params = {'redeliver_incoming_message_id' => new_im.id, + 'url_title' => ir.url_title} + admin.post '/en/admin/incoming/redeliver', post_params + admin.response.location.should == 'http://www.example.com/en/admin/request/show/101' + ir = InfoRequest.find_by_url_title(ir.url_title) + ir.incoming_messages.length.should == 2 + + InfoRequest.holding_pen_request.incoming_messages.length.should == 0 + end + + it "allows redelivery of an incoming message to more than one request" do + confirm(:admin_user) + admin = login(:admin_user) + + ir1 = info_requests(:fancy_dog_request) + close_request(ir1) + ir1.incoming_messages.length.should == 1 + ir2 = info_requests(:another_boring_request) + ir2.incoming_messages.length.should == 1 + + receive_incoming_mail('incoming-request-plain.email', ir1.incoming_email, "frob@nowhere.com") + InfoRequest.holding_pen_request.incoming_messages.length.should == 1 + + new_im = InfoRequest.holding_pen_request.incoming_messages[0] + post_params = {'redeliver_incoming_message_id' => new_im.id, + 'url_title' => "#{ir1.url_title},#{ir2.url_title}"} + admin.post '/en/admin/incoming/redeliver', post_params + ir1.reload + ir1.incoming_messages.length.should == 2 + ir2.reload + ir2.incoming_messages.length.should == 2 + admin.response.location.should == 'http://www.example.com/en/admin/request/show/106' + InfoRequest.holding_pen_request.incoming_messages.length.should == 0 end + end diff --git a/spec/integration/alaveteli_dsl.rb b/spec/integration/alaveteli_dsl.rb new file mode 100644 index 000000000..119bb05a0 --- /dev/null +++ b/spec/integration/alaveteli_dsl.rb @@ -0,0 +1,68 @@ +module AlaveteliDsl + + def browses_request(url_title) + get "/request/#{url_title}" + assert_response :success + end + + def creates_request_unregistered + params = { :info_request => { :public_body_id => public_bodies(:geraldine_public_body).id, + :title => "Why is your quango called Geraldine?", + :tag_string => "" }, + :outgoing_message => { :body => "This is a silly letter. It is too short to be interesting." }, + :submitted_new_request => 1, + :preview => 0 + } + + # Initially we are not logged in. Try to create a new request. + post "/new", params + # We expect to be redirected to the login page + post_redirect = PostRedirect.get_last_post_redirect + response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) + follow_redirect! + response.should render_template("user/sign") + response.body.should match(/To send your FOI request, please sign in or make a new account./) + end + +end + +def login(user) + open_session do |sess| + # Make sure we get a fresh empty session - there seems to be some + # problem with session leakage otherwise + sess.reset! + sess.extend(AlaveteliDsl) + + if user.is_a? User + u = user + else + u = users(user) + end + sess.visit signin_path + sess.fill_in "Your e-mail:", :with => u.email + sess.fill_in "Password:", :with => "jonespassword" + sess.click_button "Sign in" + assert sess.session[:user_id] == u.id + end +end + +def without_login + open_session do |sess| + sess.extend(AlaveteliDsl) + end +end + +def confirm(user) + u = users(user) + u.email_confirmed = true + u.save! +end + +def close_request(request) + request.allow_new_responses_from = 'nobody' + request.handle_rejected_responses = 'holding_pen' + request.save! +end + + + diff --git a/spec/integration/cookie_stripping_spec.rb b/spec/integration/cookie_stripping_spec.rb new file mode 100644 index 000000000..897899fd5 --- /dev/null +++ b/spec/integration/cookie_stripping_spec.rb @@ -0,0 +1,12 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') + +describe 'when making stripping cookies' do + + it 'should not set a cookie when no significant session data is set' do + get 'country_message' + response.headers['Set-Cookie'].should be_blank + end + +end + diff --git a/spec/integration/create_request_spec.rb b/spec/integration/create_request_spec.rb index 4efbf94ee..84fad12f9 100644 --- a/spec/integration/create_request_spec.rb +++ b/spec/integration/create_request_spec.rb @@ -1,51 +1,36 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') describe "When creating requests" do - def create_request_unregistered - params = { :info_request => { :public_body_id => public_bodies(:geraldine_public_body).id, - :title => "Why is your quango called Geraldine?", - :tag_string => "" }, - :outgoing_message => { :body => "This is a silly letter. It is too short to be interesting." }, - :submitted_new_request => 1, - :preview => 0 - } - - # Initially we are not logged in. Try to create a new request. - post "/new", params - # We expect to be redirected to the login page - post_redirect = PostRedirect.get_last_post_redirect - response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) - follow_redirect! - response.should render_template("user/sign") - response.body.should match(/To send your FOI request, please sign in or make a new account./) - end + it "should associate the request with the requestor, even if it is approved by an admin" do + + unregistered = without_login # This is a test for https://github.com/mysociety/alaveteli/issues/446 - create_request_unregistered + unregistered.creates_request_unregistered post_redirect = PostRedirect.get_last_post_redirect # Now log in as an unconfirmed user. - post "/profile/sign_in", :user_signin => {:email => users(:unconfirmed_user).email, :password => "jonespassword"}, :token => post_redirect.token + unregistered.post "/profile/sign_in", :user_signin => {:email => users(:unconfirmed_user).email, :password => "jonespassword"}, :token => post_redirect.token # This will trigger a confirmation mail. Get the PostRedirect for later. - response.should render_template("user/confirm") + unregistered.response.body.should match('Now check your email!') post_redirect = PostRedirect.get_last_post_redirect + # Now log in as an admin user, then follow the confirmation link in the email that was sent to the unconfirmed user - admin_user = users(:admin_user) - admin_user.email_confirmed = true - admin_user.save! - post_via_redirect "/profile/sign_in", :user_signin => {:email => admin_user.email, :password => "jonespassword"} - response.should be_success - get "/c/" + post_redirect.email_token - follow_redirect! - response.location.should =~ %r(/request/(.+)/new) - response.location =~ %r(/request/(.+)/new) + confirm(:admin_user) + admin = login(:admin_user) + admin.get "/c/" + post_redirect.email_token + admin.follow_redirect! + admin.response.location.should =~ %r(/request/(.+)/new) + admin.response.location =~ %r(/request/(.+)/new) url_title = $1 info_request = InfoRequest.find_by_url_title(url_title) info_request.should_not be_nil # Make sure the request is still owned by the user who made it, not the admin who confirmed it info_request.user_id.should == users(:unconfirmed_user).id + end end diff --git a/spec/integration/download_request_spec.rb b/spec/integration/download_request_spec.rb new file mode 100644 index 000000000..638198cde --- /dev/null +++ b/spec/integration/download_request_spec.rb @@ -0,0 +1,324 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') + +describe 'when making a zipfile available' do + + after do + FileUtils.rm_rf(InfoRequest.download_zip_dir) + end + + def inspect_zip_download(session, info_request) + session.get_via_redirect "request/#{info_request.url_title}/download" + session.response.should be_success + Tempfile.open('download') do |f| + f.binmode + f.write(session.response.body) + f.flush + Zip::ZipFile::open(f.path) do |zip| + yield zip + end + end + end + + def sleep_and_receive_mail(name, info_request) + # The path of the zip file is based on the hash of the timestamp of the last request + # in the thread, so we wait for a second to make sure this one will have a different + # timestamp than the previous. + sleep 1 + receive_incoming_mail(name, info_request.incoming_email) + end + + context 'when an html to pdf converter is supplied' do + + before do + # We want to test the contents of the pdf, and we don't know whether a particular + # instance will have a working html_to_pdf tool, so just copy the HTML rendered + # to the PDF file for the purposes of checking it doesn't contain anything that + # shouldn't be there. + AlaveteliConfiguration.stub!(:html_to_pdf_command).and_return('/bin/cp') + end + + context 'when an incoming message is made "requester_only"' do + + it 'should not include the incoming message or attachments in a download of the entire request + by a non-request owner but should retain them for owner and admin' do + + # Non-owner can download zip with incoming and attachments + non_owner = login(FactoryGirl.create(:user)) + info_request = FactoryGirl.create(:info_request_with_incoming_attachments) + + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.pdf').should match('hereisthetext') + end + + # Admin makes the incoming message requester only + admin = login(FactoryGirl.create(:admin_user)) + post_data = {:incoming_message => {:prominence => 'requester_only', + :prominence_reason => 'boring'}} + admin.post_via_redirect "/en/admin/incoming/update/#{info_request.incoming_messages.first.id}", post_data + admin.response.should be_success + + # Admin retains the requester only things + inspect_zip_download(admin, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.pdf').should match('hereisthetext') + end + + # Zip for non owner is now without requester_only things + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + correspondence_text = zip.read('correspondence.pdf') + correspondence_text.should_not match('hereisthetext') + expected_text = "This message has been hidden.\n boring" + correspondence_text.should match(expected_text) + end + + # Requester retains the requester only things + owner = login(info_request.user) + inspect_zip_download(owner, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.pdf').should match('hereisthetext') + end + + end + + end + + context 'when an outgoing message is made "requester_only"' do + + it 'should not include the outgoing message in a download of the entire request + by a non-request owner but should retain them for owner and admin' do + + # Non-owner can download zip with outgoing + non_owner = login(FactoryGirl.create(:user)) + info_request = FactoryGirl.create(:info_request) + + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.pdf').should match('Some information please') + end + + # Admin makes the incoming message requester only + admin = login(FactoryGirl.create(:admin_user)) + post_data = {:outgoing_message => {:prominence => 'requester_only', + :prominence_reason => 'boring', + :body => 'Some information please'}} + admin.post_via_redirect "/en/admin/outgoing/update/#{info_request.outgoing_messages.first.id}", post_data + admin.response.should be_success + + # Admin retains the requester only things + inspect_zip_download(admin, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.pdf').should match('Some information please') + end + + # Zip for non owner is now without requester_only things + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + correspondence_text = zip.read('correspondence.pdf') + correspondence_text.should_not match('Some information please') + expected_text = "This message has been hidden.\n boring" + correspondence_text.should match(expected_text) + end + + # Requester retains the requester only things + owner = login(info_request.user) + inspect_zip_download(owner, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.pdf').should match('Some information please') + end + + end + + end + + end + + context 'when no html to pdf converter is supplied' do + + before do + AlaveteliConfiguration.stub!(:html_to_pdf_command).and_return('') + end + + it "should update the contents of the zipfile when the request changes" do + + info_request = FactoryGirl.create(:info_request_with_incoming) + request_owner = login(info_request.user) + inspect_zip_download(request_owner, info_request) do |zip| + zip.count.should == 1 # just the message + expected = 'This is a plain-text version of the Freedom of Information request "Example Title"' + zip.read('correspondence.txt').should match expected + end + + sleep_and_receive_mail('incoming-request-two-same-name.email', info_request) + + inspect_zip_download(request_owner, info_request) do |zip| + zip.count.should == 3 # the message plus two "hello-world.txt" files + zip.read('2_2_hello world.txt').should match('Second hello') + zip.read('2_3_hello world.txt').should match('First hello') + end + + sleep_and_receive_mail('incoming-request-attachment-unknown-extension.email', info_request) + + inspect_zip_download(request_owner, info_request) do |zip| + zip.count.should == 4 # the message plus two "hello-world.txt" files, and the new attachment + zip.read('3_2_hello.qwglhm').should match('This is an unusual') + end + end + + context 'when a request is "requester_only"' do + + before do + @non_owner = login(FactoryGirl.create(:user)) + @info_request = FactoryGirl.create(:info_request_with_incoming, + :prominence => 'requester_only') + @request_owner = login(@info_request.user) + @admin = login(FactoryGirl.create(:admin_user)) + end + + + it 'should allow a download of the request by the request owner and admin only' do + # Requester can access the zip + inspect_zip_download(@request_owner, @info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('hereisthetext') + end + # Non-owner can't + @non_owner.get_via_redirect "request/#{@info_request.url_title}/download" + @non_owner.response.code.should == '403' + # Admin can + inspect_zip_download(@admin, @info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('hereisthetext') + end + end + end + + context 'when a request is "hidden"' do + + it 'should not allow a download of the request by an admin only' do + @non_owner = login(FactoryGirl.create(:user)) + @info_request = FactoryGirl.create(:info_request_with_incoming, + :prominence => 'hidden') + @request_owner = login(@info_request.user) + @admin = login(FactoryGirl.create(:admin_user)) + + # Requester can't access the zip + @request_owner.get_via_redirect "request/#{@info_request.url_title}/download" + @request_owner.response.code.should == '403' + # Non-owner can't + @non_owner.get_via_redirect "request/#{@info_request.url_title}/download" + @non_owner.response.code.should == '403' + # Admin can + inspect_zip_download(@admin, @info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('hereisthetext') + end + end + + end + + context 'when an incoming message is made "requester_only"' do + + it 'should not include the incoming message or attachments in a download of the entire request + by a non-request owner but should retain them for owner and admin' do + + # Non-owner can download zip with outgoing + non_owner = login(FactoryGirl.create(:user)) + info_request = FactoryGirl.create(:info_request_with_incoming_attachments) + + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.txt').should match('hereisthetext') + end + + # Admin makes the incoming message requester only + admin = login(FactoryGirl.create(:admin_user)) + post_data = {:incoming_message => {:prominence => 'requester_only', + :prominence_reason => 'boring'}} + admin.post_via_redirect "/en/admin/incoming/update/#{info_request.incoming_messages.first.id}", post_data + admin.response.should be_success + + # Admin retains the requester only things + inspect_zip_download(admin, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.txt').should match('hereisthetext') + end + + # Zip for non owner is now without requester_only things + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + correspondence_text = zip.read('correspondence.txt') + correspondence_text.should_not match('hereisthetext') + expected_text = 'This message has been hidden. boring' + correspondence_text.should match(expected_text) + end + + # Requester retains the requester only things + owner = login(info_request.user) + inspect_zip_download(owner, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.txt').should match('hereisthetext') + end + + end + + end + + context 'when an outgoing message is made "requester_only"' do + + it 'should not include the outgoing message in a download of the entire request + by a non-request owner but should retain them for owner and admin' do + + # Non-owner can download zip with incoming and attachments + non_owner = login(FactoryGirl.create(:user)) + info_request = FactoryGirl.create(:info_request) + + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('Some information please') + end + + # Admin makes the incoming message requester only + admin = login(FactoryGirl.create(:admin_user)) + post_data = {:outgoing_message => {:prominence => 'requester_only', + :prominence_reason => 'boring', + :body => 'Some information please'}} + admin.post_via_redirect "/en/admin/outgoing/update/#{info_request.outgoing_messages.first.id}", post_data + admin.response.should be_success + + # Admin retains the requester only things + inspect_zip_download(admin, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('Some information please') + end + + # Zip for non owner is now without requester_only things + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + correspondence_text = zip.read('correspondence.txt') + correspondence_text.should_not match('Some information please') + expected_text = 'This message has been hidden. boring' + correspondence_text.should match(expected_text) + end + + # Requester retains the requester only things + owner = login(info_request.user) + inspect_zip_download(owner, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('Some information please') + end + + end + + end + + it 'should successfully make a zipfile for an external request' do + external_request = FactoryGirl.create(:external_request) + user = login(FactoryGirl.create(:user)) + inspect_zip_download(user, external_request){ |zip| zip.count.should == 1 } + end + end + +end diff --git a/spec/integration/errors_spec.rb b/spec/integration/errors_spec.rb index a44ed7051..17a0153c2 100644 --- a/spec/integration/errors_spec.rb +++ b/spec/integration/errors_spec.rb @@ -1,53 +1,130 @@ +# -*- coding: utf-8 -*- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -describe "When rendering errors" do +describe "When errors occur" do - before(:each) do - load_raw_emails_data - ActionController::Base.consider_all_requests_local = false + def set_consider_all_requests_local(value) + @requests_local = Rails.application.config.consider_all_requests_local + Rails.application.config.consider_all_requests_local = value end - after(:each) do - ActionController::Base.consider_all_requests_local = true + def restore_consider_all_requests_local + Rails.application.config.consider_all_requests_local = @requests_local end - it "should render a 404 for unrouteable URLs" do - get("/frobsnasm") - response.body.should include("The page doesn't exist") - response.code.should == "404" - end - it "should render a 404 for users that don't exist" do - get("/user/wobsnasm") - response.body.should include("The page doesn't exist") - response.code.should == "404" - end - it "should render a 404 for bodies that don't exist" do - get("/body/wobsnasm") - response.body.should include("The page doesn't exist") - response.code.should == "404" + before(:each) do + # This should happen automatically before each test but doesn't with these integration + # tests for some reason. + ActionMailer::Base.deliveries = [] end - it "should render a 500 for general errors" do - ir = info_requests(:naughty_chicken_request) - # Set an invalid state for the request. Note that update_attribute doesn't run the validations - ir.update_attribute(:described_state, "crotchety") - get("/request/#{ir.url_title}") - response.code.should == "500" + + after(:each) do + restore_consider_all_requests_local end - it "should render a 403 for attempts at directory listing for attachments" do - # make a fake cache - foi_cache_path = File.expand_path(File.join(File.dirname(__FILE__), '../../cache')) - FileUtils.mkdir_p(File.join(foi_cache_path, "views/en/request/101/101/response/1/attach/html/1")) - get("/request/101/response/1/attach/html/1/" ) - response.body.should include("Directory listing not allowed") - response.code.should == "403" - get("/request/101/response/1/attach/html" ) - response.body.should include("Directory listing not allowed") - response.code.should == "403" + + context 'when considering all requests local (by default all in development)' do + + before(:each) { set_consider_all_requests_local(true) } + + it 'should show a full trace for general errors' do + InfoRequest.stub!(:find_by_url_title!).and_raise("An example error") + get("/request/example") + response.body.should have_selector('div[id=traces]') + response.body.should match('An example error') + end + end - it "should render a 404 for non-existent 'details' pages for requests" do - get("/details/request/wobble" ) - response.body.should include("The page doesn't exist") - response.code.should == "404" + + context 'when not considering all requests local' do + + before(:each) { set_consider_all_requests_local(false) } + + it "should render a 404 for unrouteable URLs using the general/exception_caught template" do + get("/frobsnasm") + response.should render_template('general/exception_caught') + response.code.should == "404" + end + + it "should render a 404 for users or bodies that don't exist using the general/exception_caught + template" do + ['/user/wobsnasm', '/body/wobsnasm'].each do |non_existent_url| + get(non_existent_url) + response.should render_template('general/exception_caught') + response.code.should == "404" + end + end + + it "should render a 500 for general errors using the general/exception_caught template" do + InfoRequest.stub!(:find_by_url_title!).and_raise("An example error") + get("/request/example") + response.should render_template('general/exception_caught') + response.body.should match('An example error') + response.code.should == "500" + end + + it 'should render a 500 for json errors' do + InfoRequest.stub!(:find_by_url_title!).and_raise("An example error") + get("/request/example.json") + response.code.should == '500' + end + + it 'should render a 404 for a non-found xml request' do + get("/frobsnasm.xml") + response.code.should == '404' + end + + it 'should notify of a general error' do + InfoRequest.stub!(:find_by_url_title!).and_raise("An example error") + get("/request/example") + deliveries = ActionMailer::Base.deliveries + deliveries.size.should == 1 + mail = deliveries[0] + mail.body.should =~ /An example error/ + end + + it 'should log a general error' do + Rails.logger.should_receive(:fatal) + InfoRequest.stub!(:find_by_url_title!).and_raise("An example error") + get("/request/example") + end + + it 'should assign the locale for the general/exception_caught template' do + InfoRequest.stub!(:find_by_url_title!).and_raise("An example error") + get("/es/request/example") + response.should render_template('general/exception_caught') + response.body.should match('Lo sentimos, hubo un problema procesando esta página') + response.body.should match('An example error') + end + + it "should render a 403 with text body for attempts at directory listing for attachments" do + # make a fake cache + foi_cache_path = File.expand_path(File.join(File.dirname(__FILE__), '../../cache')) + FileUtils.mkdir_p(File.join(foi_cache_path, "views/en/request/101/101/response/1/attach/html/1")) + get("/request/101/response/1/attach/html/1/" ) + response.body.should include("Directory listing not allowed") + response.code.should == "403" + get("/request/101/response/1/attach/html" ) + response.body.should include("Directory listing not allowed") + response.code.should == "403" + end + + it "return a 403 for a JSON PermissionDenied error" do + InfoRequest.stub!(:find_by_url_title!).and_raise(ApplicationController::PermissionDenied) + get("/request/example.json") + response.code.should == '403' + end + + context "in the admin interface" do + + it 'should show a full trace for general errors' do + InfoRequest.stub!(:find).and_raise("An example error") + get("/admin/request/show/333") + response.body.should have_selector('div[id=traces]') + response.body.should match('An example error') + end + + end + end -end +end diff --git a/spec/integration/localisation_spec.rb b/spec/integration/localisation_spec.rb new file mode 100644 index 000000000..4f6b61ae1 --- /dev/null +++ b/spec/integration/localisation_spec.rb @@ -0,0 +1,88 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe "when generating urls" do + + before do + @home_link_regex = /href=".*\/en\// + end + + it "should generate URLs that include the locale when using one that includes an underscore" do + get('/en_GB') + response.body.should match /href="\/en_GB\// + end + + it "should fall back to the language if the territory is unknown" do + AlaveteliLocalization.set_locales(available_locales='es en', default_locale='en') + get('/', {}, {'HTTP_ACCEPT_LANGUAGE' => 'en_US'}) + response.body.should match /href="\/en\// + response.body.should_not match /href="\/en_US\// + end + + it "should generate URLs without a locale prepended when there's only one locale set" do + AlaveteliLocalization.set_locales(available_locales='en', default_locale='en') + get('/') + response.should_not contain @home_link_regex + end + + it 'should redirect requests for a public body in a locale to the canonical name in that locale' do + get('/es/body/dfh') + response.should redirect_to "/es/body/edfh" + end + + it 'should remember a filter view when redirecting a public body request to the canonical name' do + get('/es/body/tgq/successful') + response.should redirect_to "/es/body/etgq/successful" + end + + describe 'when there is more than one locale' do + + before do + AlaveteliLocalization.set_locales(available_locales='es en', default_locale='en') + end + + it "should generate URLs with a locale prepended when there's more than one locale set" do + get('/') + response.body.should match @home_link_regex + end + + 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 = AlaveteliConfiguration::include_default_locale_in_urls + end + + describe 'when the config value INCLUDE_DEFAULT_LOCALE_IN_URLS is false' do + + before do + AlaveteliLocalization.set_default_locale_urls(false) + end + + it 'should generate URLs without a locale prepended' do + get '/' + response.should_not contain @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('/', {:locale => 'es'}) + response.should_not contain @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 + AlaveteliLocalization.set_default_locale_urls(true) + get '/' + response.body.should match /#{@default_lang_home_link}/ + end + + after do + AlaveteliLocalization.set_default_locale_urls(@old_include_default_locale_in_urls) + end + + end + end + +end diff --git a/spec/integration/request_controller_spec.rb b/spec/integration/request_controller_spec.rb new file mode 100644 index 000000000..f5de692b8 --- /dev/null +++ b/spec/integration/request_controller_spec.rb @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') + +describe RequestController, "when classifying an information request" do + + describe 'when the request is internal' do + + before(:each) do + load_raw_emails_data + @dog_request = info_requests(:fancy_dog_request) + # This should happen automatically before each test but doesn't with these integration + # tests for some reason. + ActionMailer::Base.deliveries = [] + end + + describe 'when logged in as the requestor' do + + before :each do + @bob = login(:bob_smith_user) + end + + it "should send an email including the message" do + @bob.visit describe_state_message_path(:url_title => @dog_request.url_title, + :described_state => "requires_admin") + @bob.fill_in "Please tell us more:", :with => "Okay. I don't quite understand." + @bob.click_button "Submit status and send message" + + @bob.response.should contain "Thank you! We'll look into what happened and try and fix it up." + + deliveries = ActionMailer::Base.deliveries + deliveries.size.should == 1 + mail = deliveries[0] + mail.body.should =~ /as needing admin/ + mail.body.should =~ /Okay. I don't quite understand./ + end + end + end +end diff --git a/spec/integration/search_request_spec.rb b/spec/integration/search_request_spec.rb index c564032a6..23a62e97b 100644 --- a/spec/integration/search_request_spec.rb +++ b/spec/integration/search_request_spec.rb @@ -13,10 +13,8 @@ describe "When searching" do end it "should redirect requests with search in query string to URL-based page" do - url = '/search/all?query=bob' - request_via_redirect("post", url) - response.request.url.should_not include(url) - response.request.url.should include("/search/bob/all") + post '/search/all?query=bob' + response.should redirect_to "/en/search/bob/all" end it "should correctly execute simple search" do diff --git a/spec/integration/view_request_spec.rb b/spec/integration/view_request_spec.rb index 442721890..814e20fb3 100644 --- a/spec/integration/view_request_spec.rb +++ b/spec/integration/view_request_spec.rb @@ -1,16 +1,169 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') describe "When viewing requests" do - before(:each) do - load_raw_emails_data + before do + @info_request = FactoryGirl.create(:info_request) + @unregistered = without_login end it "should not make endlessly recursive JSON <link>s" do - @dog_request = info_requests(:fancy_dog_request) - get "request/#{@dog_request.url_title}?unfold=1" - response.body.should_not include("dog?unfold=1.json") - response.body.should include("dog.json?unfold=1") + @unregistered.browses_request("#{@info_request.url_title}?unfold=1") + @unregistered.response.body.should_not include("#{@info_request.url_title}?unfold=1.json") + @unregistered.response.body.should include("#{@info_request.url_title}.json?unfold=1") + end + + it 'should not raise a routing error when making a json link for a request with an + "action" querystring param' do + @unregistered.browses_request("#{@info_request.url_title}?action=add") + end + + context 'when a response has prominence "normal"' do + + before do + @info_request = FactoryGirl.create(:info_request_with_incoming) + end + + it 'should show the message itself to any user' do + + # unregistered + unregistered = without_login + unregistered.browses_request(@info_request.url_title) + unregistered.response.body.should include("hereisthetext") + unregistered.response.body.should_not include("This message has been hidden.") + unregistered.response.body.should_not include("sign in</a> to view the message.") + + # requester + owner = login(@info_request.user) + owner.browses_request(@info_request.url_title) + owner.response.body.should include("hereisthetext") + owner.response.body.should_not include("This message has been hidden.") + + # admin + admin_user = login(FactoryGirl.create(:admin_user)) + admin_user.browses_request(@info_request.url_title) + admin_user.response.body.should include("hereisthetext") + admin_user.response.body.should_not include("This message has prominence \'hidden\'.") + + end + + end + + context 'when a response has prominence "hidden"' do + + before do + @info_request = FactoryGirl.create(:info_request_with_incoming) + message = @info_request.incoming_messages.first + message.prominence = 'hidden' + message.prominence_reason = 'It is too irritating.' + message.save! + end + + it 'should show a hidden notice, not the message, to an unregistered user or the requester and + the message itself to an admin ' do + + # unregistered + unregistered = without_login + unregistered.browses_request(@info_request.url_title) + unregistered.response.body.should include("This message has been hidden.") + unregistered.response.body.should include("It is too irritating.") + unregistered.response.body.should_not include("sign in</a> to view the message.") + unregistered.response.body.should_not include("hereisthetext") + + # requester + owner = login(@info_request.user) + owner.browses_request(@info_request.url_title) + owner.response.body.should include("This message has been hidden.") + owner.response.body.should include("It is too irritating") + owner.response.body.should_not include("hereisthetext") + + # admin + admin_user = login(FactoryGirl.create(:admin_user)) + admin_user.browses_request(@info_request.url_title) + admin_user.response.body.should include('hereisthetext') + admin_user.response.body.should include("This message has prominence \'hidden\'.") + admin_user.response.body.should include("It is too irritating.") + admin_user.response.body.should include("You can only see it because you are logged in as a super user.") + + end + + end + + context 'when a response has prominence "requester_only"' do + + before do + @info_request = FactoryGirl.create(:info_request_with_incoming) + message = @info_request.incoming_messages.first + message.prominence = 'requester_only' + message.prominence_reason = 'It is too irritating.' + message.save! + end + + it 'should show a hidden notice with login link to an unregistered user, and the message itself + with a hidden note to the requester or an admin' do + + # unregistered + unregistered = without_login + unregistered.browses_request(@info_request.url_title) + unregistered.response.body.should include("This message has been hidden.") + unregistered.response.body.should include("It is too irritating") + unregistered.response.body.should include("sign in</a> to view the message.") + unregistered.response.body.should_not include("hereisthetext") + + # requester + owner = login(@info_request.user) + owner.browses_request(@info_request.url_title) + owner.response.body.should include("hereisthetext") + owner.response.body.should include("This message is hidden, so that only you, the requester, can see it.") + owner.response.body.should include("It is too irritating.") + + # admin + admin_user = login(FactoryGirl.create(:admin_user)) + admin_user.browses_request(@info_request.url_title) + admin_user.response.body.should include('hereisthetext') + admin_user.response.body.should_not include("This message has been hidden.") + admin_user.response.body.should include("This message is hidden, so that only you, the requester, can see it.") + end + + end + + context 'when an outgoing message has prominence "requester_only"' do + + before do + @info_request = FactoryGirl.create(:info_request) + message = @info_request.outgoing_messages.first + message.prominence = 'requester_only' + message.prominence_reason = 'It is too irritating.' + message.save! + end + + it 'should show a hidden notice with login link to an unregistered user, and the message itself + with a hidden note to the requester or an admin' do + + # unregistered + unregistered = without_login + unregistered.browses_request(@info_request.url_title) + unregistered.response.body.should include("This message has been hidden.") + unregistered.response.body.should include("It is too irritating") + unregistered.response.body.should include("sign in</a> to view the message.") + unregistered.response.body.should_not include("Some information please") + + # requester + owner = login(@info_request.user) + owner.browses_request(@info_request.url_title) + owner.response.body.should include("Some information please") + owner.response.body.should include("This message is hidden, so that only you, the requester, can see it.") + owner.response.body.should include("It is too irritating.") + + # admin + admin_user = login(FactoryGirl.create(:admin_user)) + admin_user.browses_request(@info_request.url_title) + admin_user.response.body.should include('Some information please') + admin_user.response.body.should_not include("This message has been hidden.") + admin_user.response.body.should include("This message is hidden, so that only you, the requester, can see it.") + end + end end |