diff options
Diffstat (limited to 'spec/controllers')
-rw-r--r-- | spec/controllers/admin_public_body_controller_spec.rb | 83 | ||||
-rw-r--r-- | spec/controllers/admin_request_controller_spec.rb | 18 | ||||
-rw-r--r-- | spec/controllers/admin_track_controller_spec.rb | 1 | ||||
-rw-r--r-- | spec/controllers/admin_user_controller_spec.rb | 1 | ||||
-rw-r--r-- | spec/controllers/application_controller_spec.rb | 49 | ||||
-rw-r--r-- | spec/controllers/comment_controller_spec.rb | 1 | ||||
-rw-r--r-- | spec/controllers/general_controller_spec.rb | 97 | ||||
-rw-r--r-- | spec/controllers/public_body_controller_spec.rb | 82 | ||||
-rw-r--r-- | spec/controllers/request_controller_spec.rb | 432 | ||||
-rw-r--r-- | spec/controllers/request_game_controller_spec.rb | 4 | ||||
-rw-r--r-- | spec/controllers/track_controller_spec.rb | 16 | ||||
-rw-r--r-- | spec/controllers/user_controller_spec.rb | 87 |
12 files changed, 653 insertions, 218 deletions
diff --git a/spec/controllers/admin_public_body_controller_spec.rb b/spec/controllers/admin_public_body_controller_spec.rb index 22af3df80..1e82a0ba4 100644 --- a/spec/controllers/admin_public_body_controller_spec.rb +++ b/spec/controllers/admin_public_body_controller_spec.rb @@ -2,14 +2,19 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminPublicBodyController, "when administering public bodies" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before do username = MySociety::Config.get('ADMIN_USERNAME', '') password = MySociety::Config.get('ADMIN_PASSWORD', '') basic_auth_login @request + + @old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new end + after do + ActionController::Routing::Routes.filters = @old_filters + end it "shows the index page" do get :index @@ -25,9 +30,9 @@ describe AdminPublicBodyController, "when administering public bodies" do end it "creates a new public body" do - PublicBody.count.should == 2 + n = PublicBody.count post :create, { :public_body => { :name => "New Quango", :short_name => "", :tag_string => "blah", :request_email => 'newquango@localhost', :last_edit_comment => 'From test code' } } - PublicBody.count.should == 3 + PublicBody.count.should == n + 1 end it "edits a public body" do @@ -42,29 +47,45 @@ describe AdminPublicBodyController, "when administering public bodies" do pb.name.should == "Renamed" end + it "does not destroy a public body that has associated requests" do + id = public_bodies(:humpadink_public_body).id + n = PublicBody.count + post :destroy, { :id => id } + response.should redirect_to(:controller=>'admin_public_body', :action=>'show', :id => id) + PublicBody.count.should == n + end + it "destroys a public body" do - PublicBody.count.should == 2 - post :destroy, { :id => 3 } - PublicBody.count.should == 1 + n = PublicBody.count + post :destroy, { :id => public_bodies(:forlorn_public_body).id } + response.should redirect_to(:controller=>'admin_public_body', :action=>'list') + PublicBody.count.should == n - 1 end it "sets a using_admin flag" do get :show, :id => 2 session[:using_admin].should == 1 end + + it "mass assigns tags" do + n = PublicBody.count + post :mass_tag_add, { :new_tag => "department", :table_name => "substring" } + response.flash[:notice].should == "Added tag to table of bodies." + response.should redirect_to(:action=>'list') + PublicBody.find_by_tag("department").count.should == n + end end describe AdminPublicBodyController, "when administering public bodies and paying attention to authentication" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things it "disallows non-authenticated users to do anything" do @request.env["HTTP_AUTHORIZATION"] = "" - PublicBody.count.should == 2 + n = PublicBody.count post :destroy, { :id => 3 } response.code.should == "401" - PublicBody.count.should == 2 + PublicBody.count.should == n session[:using_admin].should == nil end @@ -73,19 +94,22 @@ describe AdminPublicBodyController, "when administering public bodies and paying config['ADMIN_USERNAME'] = '' config['ADMIN_PASSWORD'] = '' @request.env["HTTP_AUTHORIZATION"] = "" - PublicBody.count.should == 2 - post :destroy, { :id => 3 } - PublicBody.count.should == 1 + + n = PublicBody.count + post :destroy, { :id => public_bodies(:forlorn_public_body).id } + PublicBody.count.should == n - 1 session[:using_admin].should == 1 end + it "skips admin authorisation when no username set" do config = MySociety::Config.load_default() config['ADMIN_USERNAME'] = '' config['ADMIN_PASSWORD'] = 'fuz' @request.env["HTTP_AUTHORIZATION"] = "" - PublicBody.count.should == 2 - post :destroy, { :id => 3 } - PublicBody.count.should == 1 + + n = PublicBody.count + post :destroy, { :id => public_bodies(:forlorn_public_body).id } + PublicBody.count.should == n - 1 session[:using_admin].should == 1 end it "forces authorisation when password and username set" do @@ -93,11 +117,11 @@ describe AdminPublicBodyController, "when administering public bodies and paying config['ADMIN_USERNAME'] = 'biz' config['ADMIN_PASSWORD'] = 'fuz' @request.env["HTTP_AUTHORIZATION"] = "" - PublicBody.count.should == 2 + n = PublicBody.count basic_auth_login(@request, "baduser", "badpassword") - post :destroy, { :id => 3 } + post :destroy, { :id => public_bodies(:forlorn_public_body).id } response.code.should == "401" - PublicBody.count.should == 2 + PublicBody.count.should == n session[:using_admin].should == nil end @@ -107,7 +131,6 @@ end describe AdminPublicBodyController, "when administering public bodies with i18n" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before do username = MySociety::Config.get('ADMIN_USERNAME', '') @@ -167,43 +190,47 @@ describe AdminPublicBodyController, "when administering public bodies with i18n" end it "destroy a public body" do - PublicBody.count.should == 2 - post :destroy, { :id => 3 } - PublicBody.count.should == 1 + n = PublicBody.count + post :destroy, { :id => public_bodies(:forlorn_public_body).id } + PublicBody.count.should == n - 1 end end describe AdminPublicBodyController, "when creating public bodies with i18n" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before do username = MySociety::Config.get('ADMIN_USERNAME', '') password = MySociety::Config.get('ADMIN_PASSWORD', '') basic_auth_login @request - ActionController::Routing::Routes.filters.clear # don't auto-insert locale, complicates assertions + @old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + end + + after do + ActionController::Routing::Routes.filters = @old_filters end it "creates a new public body in one locale" do - PublicBody.count.should == 2 + n = PublicBody.count post :create, { :public_body => { :name => "New Quango", :short_name => "", :tag_string => "blah", :request_email => 'newquango@localhost', :last_edit_comment => 'From test code' } } - PublicBody.count.should == 3 + PublicBody.count.should == n + 1 body = PublicBody.find_by_name("New Quango") response.should redirect_to(:controller=>'admin_public_body', :action=>'show', :id=>body.id) end it "creates a new public body with multiple locales" do - PublicBody.count.should == 2 + n = PublicBody.count post :create, { :public_body => { :name => "New Quango", :short_name => "", :tag_string => "blah", :request_email => 'newquango@localhost', :last_edit_comment => 'From test code', :translated_versions => [{ :locale => "es", :name => "Mi Nuevo Quango", :short_name => "", :request_email => 'newquango@localhost' }] } } - PublicBody.count.should == 3 + PublicBody.count.should == n + 1 body = PublicBody.find_by_name("New Quango") body.translations.map {|t| t.locale.to_s}.sort.should == ["en", "es"] diff --git a/spec/controllers/admin_request_controller_spec.rb b/spec/controllers/admin_request_controller_spec.rb index 635d73b9e..ece1fe389 100644 --- a/spec/controllers/admin_request_controller_spec.rb +++ b/spec/controllers/admin_request_controller_spec.rb @@ -2,9 +2,17 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminRequestController, "when administering requests" do integrate_views - fixtures :users, :public_bodies, :public_body_translations, :public_body_versions, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before { basic_auth_login @request } + before(:each) do + load_raw_emails_data + @old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + end + after do + ActionController::Routing::Routes.filters = @old_filters + end + it "shows the index/list page" do get :index end @@ -41,10 +49,14 @@ end describe AdminRequestController, "when administering the holding pen" do integrate_views - fixtures :users, :public_bodies, :public_body_translations, :public_body_versions, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before(:each) do basic_auth_login @request - load_raw_emails_data(raw_emails) + load_raw_emails_data + @old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + end + after do + ActionController::Routing::Routes.filters = @old_filters end it "shows a rejection reason for an incoming message from an invalid address" do diff --git a/spec/controllers/admin_track_controller_spec.rb b/spec/controllers/admin_track_controller_spec.rb index b87ee9f0e..728c79f1f 100644 --- a/spec/controllers/admin_track_controller_spec.rb +++ b/spec/controllers/admin_track_controller_spec.rb @@ -2,7 +2,6 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminTrackController, "when administering tracks" do integrate_views - fixtures :users, :info_requests, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things 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 b2b2d0626..65ecbc37d 100644 --- a/spec/controllers/admin_user_controller_spec.rb +++ b/spec/controllers/admin_user_controller_spec.rb @@ -2,7 +2,6 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminUserController, "when administering users" do integrate_views - fixtures :users, :info_requests, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before { basic_auth_login @request } it "shows the index/list page" do diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 875d7d224..f16cee312 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -1,10 +1,47 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'fakeweb' + +describe ApplicationController, "when accessing third party services" do + before (:each) do + FakeWeb.clean_registry + end + after (:each) do + FakeWeb.clean_registry + end + it "should succeed if the service responds OK" do + config = MySociety::Config.load_default() + config['GAZE_URL'] = 'http://denmark.com' + FakeWeb.register_uri(:get, %r|denmark.com|, :body => "DK") + country = self.controller.send :country_from_ip + country.should == "DK" + end + it "should fail silently if the country_from_ip domain doesn't exist" do + config = MySociety::Config.load_default() + config['GAZE_URL'] = 'http://12123sdf14qsd.com' + country = self.controller.send :country_from_ip + country.should == config['ISO_COUNTRY_CODE'] + end + it "should fail silently if the country_from_ip service doesn't exist" do + config = MySociety::Config.load_default() + config['GAZE_URL'] = 'http://www.google.com' + country = self.controller.send :country_from_ip + country.should == config['ISO_COUNTRY_CODE'] + end + it "should fail silently if the country_from_ip service returns an error" do + FakeWeb.register_uri(:get, %r|500.com|, :body => "Error", :status => ["500", "Error"]) + config = MySociety::Config.load_default() + config['GAZE_URL'] = 'http://500.com' + country = self.controller.send :country_from_ip + country.should == config['ISO_COUNTRY_CODE'] + end +end + +describe ApplicationController, "when caching fragments" do + it "should not fail with long filenames" do + long_name = "blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah.txt" + path = self.controller.send(:foi_fragment_cache_path, long_name) + self.controller.send(:foi_fragment_cache_write, path, "whassap") + end -describe ApplicationController, "when authenticating user" do - integrate_views - fixtures :users - -# it "blah" do -# end end diff --git a/spec/controllers/comment_controller_spec.rb b/spec/controllers/comment_controller_spec.rb index 4c14b8d24..93752537c 100644 --- a/spec/controllers/comment_controller_spec.rb +++ b/spec/controllers/comment_controller_spec.rb @@ -2,7 +2,6 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe CommentController, "when commenting on a request" do integrate_views - fixtures :users, :public_bodies, :public_body_translations, :public_body_versions, :info_requests, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things 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 40a676d61..7fc019c64 100644 --- a/spec/controllers/general_controller_spec.rb +++ b/spec/controllers/general_controller_spec.rb @@ -1,23 +1,28 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'fakeweb' + +describe GeneralController, "when trying to show the blog" do + before (:each) do + FakeWeb.clean_registry + end + after (:each) do + FakeWeb.clean_registry + end + + it "should fail silently if the blog is returning an error" do + FakeWeb.register_uri(:get, %r|.*|, :body => "Error", :status => ["500", "Error"]) + get :blog + response.status.should == "200 OK" + assigns[:blog_items].count.should == 0 + end +end describe GeneralController, "when searching" do integrate_views - fixtures [ - :public_bodies, - :public_body_translations, - :public_body_versions, - :users, - :info_requests, - :raw_emails, - :incoming_messages, - :outgoing_messages, - :comments, - :info_request_events, - :track_things, - ] before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data + rebuild_xapian_index end it "should render the front page successfully" do @@ -68,36 +73,58 @@ describe GeneralController, "when searching" do it "should redirect from search query URL to pretty URL" do post :search_redirect, :query => "mouse" # query hidden in POST parameters - response.should redirect_to(:action => 'search', :combined => "mouse", :view => "requests") # URL /search/:query/all + response.should redirect_to(:action => 'search', :combined => "mouse", :view => "all") # URL /search/:query/all 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 - ActionController::Routing::Routes.add_filters('conditionallyprependlocale') get :frontpage response.should have_text(home_link_regex) end it "should generate URLs without a locale prepended when there's only one locale set" do - ActionController::Routing::Routes.add_filters('conditionallyprependlocale') - old_available_locales = FastGettext.default_available_locales - available_locales = ['en'] - FastGettext.default_available_locales = available_locales - I18n.available_locales = available_locales + old_fgt_available_locales = FastGettext.default_available_locales + old_i18n_available_locales = I18n.available_locales + FastGettext.default_available_locales = I18n.available_locales = ['en'] get :frontpage response.should_not have_text(home_link_regex) - FastGettext.default_available_locales = old_available_locales - I18n.available_locales = old_available_locales + FastGettext.default_available_locales = old_fgt_available_locales + I18n.available_locales = old_i18n_available_locales + end + end + + describe 'when constructing the list of recent requests' do + before(:each) do + load_raw_emails_data + rebuild_xapian_index + end + + it 'should list the newest successful request first' do + # Make sure the newest is listed first even if an older one + # has a newer comment or was reclassified more recently: + # https://github.com/sebbacon/alaveteli/issues/370 + # + # This is a deliberate behaviour change, in that the + # previous behaviour (showing more-recently-reclassified + # requests first) was intentional. + get :frontpage + assigns[:request_events].first.info_request.should == info_requests(:another_boring_request) + end + + it 'should coalesce duplicate requests' do + get :frontpage + assigns[:request_events].map(&:info_request).select{|x|x.url_title =~ /^spam/}.length.should == 1 end end describe 'when using xapian search' do # rebuild xapian index after fixtures loaded - before(:all) do + before(:each) do + load_raw_emails_data rebuild_xapian_index end @@ -128,21 +155,31 @@ describe GeneralController, "when searching" do it "should filter results based on end of URL being 'all'" do get :search, :combined => ['"bob"', "all"] - assigns[:xapian_requests].results.size.should == 2 - assigns[:xapian_users].results.size.should == 1 - assigns[:xapian_bodies].results.size.should == 0 + assigns[:xapian_requests].results.map{|x| x[:model]}.should =~ [ + info_request_events(:useless_outgoing_message_event), + info_request_events(:silly_outgoing_message_event), + info_request_events(:useful_incoming_message_event), + info_request_events(:another_useful_incoming_message_event), + ] + assigns[:xapian_users].results.map{|x| x[:model]}.should == [users(:bob_smith_user)] + assigns[:xapian_bodies].results.should == [] end it "should filter results based on end of URL being 'users'" do get :search, :combined => ['"bob"', "users"] assigns[:xapian_requests].should == nil - assigns[:xapian_users].results.size.should == 1 + assigns[:xapian_users].results.map{|x| x[:model]}.should == [users(:bob_smith_user)] assigns[:xapian_bodies].should == nil end it "should filter results based on end of URL being 'requests'" do get :search, :combined => ['"bob"', "requests"] - assigns[:xapian_requests].results.size.should == 2 + assigns[:xapian_requests].results.map{|x|x[:model]}.should =~ [ + info_request_events(:useless_outgoing_message_event), + info_request_events(:silly_outgoing_message_event), + info_request_events(:useful_incoming_message_event), + info_request_events(:another_useful_incoming_message_event), + ] assigns[:xapian_users].should == nil assigns[:xapian_bodies].should == nil end @@ -151,7 +188,7 @@ describe GeneralController, "when searching" do get :search, :combined => ['"quango"', "bodies"] assigns[:xapian_requests].should == nil assigns[:xapian_users].should == nil - assigns[:xapian_bodies].results.size.should == 1 + assigns[:xapian_bodies].results.map{|x|x[:model]}.should == [public_bodies(:geraldine_public_body)] end it "should show help when searching for nothing" do diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index 8182e1331..e6eca0781 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -4,7 +4,11 @@ require 'json' describe PublicBodyController, "when showing a body" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things + + before(:each) do + load_raw_emails_data + rebuild_xapian_index + end it "should be successful" do get :show, :url_name => "dfh", :view => 'all' @@ -21,11 +25,23 @@ describe PublicBodyController, "when showing a body" do assigns[:public_body].should == public_bodies(:humpadink_public_body) end - it "should assign the requests" do + it "should assign the requests (1)" do get :show, :url_name => "tgq", :view => 'all' - assigns[:xapian_requests].results.count.should == 2 + assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ InfoRequest.all( + :conditions => ["public_body_id = ?", public_bodies(:geraldine_public_body).id]) + end + + it "should assign the requests (2)" do get :show, :url_name => "tgq", :view => 'successful' - assigns[:xapian_requests].results.count.should == 0 + assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ InfoRequest.all( + :conditions => ["described_state = ? and public_body_id = ?", + "successful", public_bodies(:geraldine_public_body).id]) + end + + it "should assign the requests (3)" do + get :show, :url_name => "dfh", :view => 'all' + assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ InfoRequest.all( + :conditions => ["public_body_id = ?", public_bodies(:humpadink_public_body).id]) end it "should assign the body using different locale from that used for url_name" do @@ -43,9 +59,13 @@ describe PublicBodyController, "when showing a body" do end it "should redirect use to the relevant locale even when url_name is for a different locale" do - ActionController::Routing::Routes.filters.clear + old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + get :show, {:url_name => "edfh", :view => 'all'} response.should redirect_to "http://test.host/body/dfh" + + ActionController::Routing::Routes.filters = old_filters end it "should redirect to newest name if you use historic name of public body in URL" do @@ -61,7 +81,6 @@ end describe PublicBodyController, "when listing bodies" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things it "should be successful" do get :list @@ -70,25 +89,28 @@ describe PublicBodyController, "when listing bodies" do it "should list all bodies from default locale, even when there are no translations for selected locale" do PublicBody.with_locale(:en) do - english_only = PublicBody.new(:name => 'English only', + @english_only = PublicBody.new(:name => 'English only', :short_name => 'EO', :request_email => 'english@flourish.org', :last_edit_editor => 'test', :last_edit_comment => '') - english_only.save + @english_only.save end PublicBody.with_locale(:es) do get :list - assigns[:public_bodies].length.should == 3 + assigns[:public_bodies].include?(@english_only).should == true end end it "should list bodies in alphabetical order" do + # Note that they are alphabetised by localised name get :list response.should render_template('list') - assigns[:public_bodies].should == [ public_bodies(:humpadink_public_body), public_bodies(:geraldine_public_body) ] + assigns[:public_bodies].should == PublicBody.all( + :conditions => "id <> #{PublicBody.internal_admin_body.id}", + :order => "(select name from public_body_translations where public_body_id=public_bodies.id and locale='en')") assigns[:tag].should == "all" assigns[:description].should == "" end @@ -114,22 +136,23 @@ describe PublicBodyController, "when listing bodies" do end it "should list a tagged thing on the appropriate list page, and others on the other page, and all still on the all page" do + load_test_categories + public_bodies(:humpadink_public_body).tag_string = "foo local_council" get :list, :tag => "local_council" response.should render_template('list') assigns[:public_bodies].should == [ public_bodies(:humpadink_public_body) ] assigns[:tag].should == "local_council" - assigns[:description].should == "Local councils" + assigns[:description].should == "in the category ‘Local councils’" get :list, :tag => "other" response.should render_template('list') - assigns[:public_bodies].should == [ public_bodies(:geraldine_public_body) ] + assigns[:public_bodies].should =~ PublicBody.all(:conditions => "id not in (#{public_bodies(:humpadink_public_body).id}, #{PublicBody.internal_admin_body.id})") get :list response.should render_template('list') - assigns[:public_bodies].count.should == 2 - + assigns[:public_bodies].should =~ PublicBody.all(:conditions => "id <> #{PublicBody.internal_admin_body.id}") end it "should list a machine tagged thing, should get it in both ways" do @@ -157,8 +180,6 @@ end describe PublicBodyController, "when showing JSON version for API" do - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things - it "should be successful" do get :show, :url_name => "dfh", :format => "json", :view => 'all' @@ -172,38 +193,45 @@ describe PublicBodyController, "when showing JSON version for API" do end describe PublicBodyController, "when doing type ahead searches" do - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things + + integrate_views + + before(:each) do + load_raw_emails_data + rebuild_xapian_index + end it "should return nothing for the empty query string" do - get :search_typeahead, :q => "" + get :search_typeahead, :query => "" response.should render_template('public_body/_search_ahead') assigns[:xapian_requests].should be_nil end it "should return a body matching the given keyword, but not users with a matching description" do - get :search_typeahead, :q => "Geraldine" + get :search_typeahead, :query => "Geraldine" response.should render_template('public_body/_search_ahead') + response.body.should include('search_ahead') assigns[:xapian_requests].results.size.should == 1 assigns[:xapian_requests].results[0][:model].name.should == public_bodies(:geraldine_public_body).name end it "should return all requests matching any of the given keywords" do - get :search_typeahead, :q => "Geraldine Humpadinking" + get :search_typeahead, :query => "Geraldine Humpadinking" response.should render_template('public_body/_search_ahead') - assigns[:xapian_requests].results.size.should == 2 - assigns[:xapian_requests].results[0][:model].name.should == public_bodies(:humpadink_public_body).name - assigns[:xapian_requests].results[1][:model].name.should == public_bodies(:geraldine_public_body).name + assigns[:xapian_requests].results.map{|x|x[:model]}.should =~ [ + public_bodies(:humpadink_public_body), + public_bodies(:geraldine_public_body), + ] end it "should return requests matching the given keywords in any of their locales" do - get :search_typeahead, :q => "baguette" # part of the spanish notes + get :search_typeahead, :query => "baguette" # part of the spanish notes response.should render_template('public_body/_search_ahead') - assigns[:xapian_requests].results.size.should == 1 - assigns[:xapian_requests].results[0][:model].name.should == public_bodies(:humpadink_public_body).name + assigns[:xapian_requests].results.map{|x|x[:model]}.should =~ [public_bodies(:humpadink_public_body)] end it "should not return matches for short words" do - get :search_typeahead, :q => "b" + get :search_typeahead, :query => "b" response.should render_template('public_body/_search_ahead') assigns[:xapian_requests].should be_nil end diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 4994c2a8f..25dce3f22 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -4,58 +4,125 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') require 'json' describe RequestController, "when listing recent requests" do - fixtures :users, :public_bodies, :public_body_translations, :public_body_versions, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data rebuild_xapian_index end it "should be successful" do - get :list, :view => 'recent' + get :list, :view => 'all' response.should be_success end it "should render with 'list' template" do - get :list, :view => 'recent' + get :list, :view => 'all' response.should render_template('list') end it "should filter requests" do get :list, :view => 'all' - assigns[:list_results].size.should == 2 + assigns[:list_results].map(&:info_request).should =~ InfoRequest.all + + # default sort order is the request with the most recently created event first + assigns[:list_results].map(&:info_request).should == InfoRequest.all( + :order => "(select max(info_request_events.created_at) from info_request_events where info_request_events.info_request_id = info_requests.id) DESC") + get :list, :view => 'successful' - assigns[:list_results].size.should == 0 + assigns[:list_results].map(&:info_request).should =~ InfoRequest.all( + :conditions => "id in ( + select info_request_id + from info_request_events + where not exists ( + select * + from info_request_events later_events + where later_events.created_at > info_request_events.created_at + and later_events.info_request_id = info_request_events.info_request_id + and later_events.described_state is not null + ) + and info_request_events.described_state in ('successful', 'partially_successful') + )") end it "should filter requests by date" do + # The semantics of the search are that it finds any InfoRequest + # that has any InfoRequestEvent created in the specified range + get :list, :view => 'all', :request_date_before => '13/10/2007' - assigns[:list_results].size.should == 1 + assigns[:list_results].map(&:info_request).should =~ InfoRequest.all( + :conditions => "id in (select info_request_id from info_request_events where created_at < '2007-10-13'::date)") + get :list, :view => 'all', :request_date_after => '13/10/2007' - assigns[:list_results].size.should == 1 - get :list, :view => 'all', :request_date_after => '10/10/2007', :request_date_before => '01/01/2010' - assigns[:list_results].size.should == 2 + assigns[:list_results].map(&:info_request).should =~ InfoRequest.all( + :conditions => "id in (select info_request_id from info_request_events where created_at > '2007-10-13'::date)") + + get :list, :view => 'all', :request_date_after => '13/10/2007', :request_date_before => '01/11/2007' + assigns[:list_results].map(&:info_request).should =~ InfoRequest.all( + :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 list internal_review requests as unresolved ones" do + get :list, :view => 'awaiting' + + # This doesn’t precisely duplicate the logic of the actual + # query, but it is close enough to give the same result with + # the current set of test data. + assigns[:list_results].should =~ InfoRequestEvent.all( + :conditions => "described_state in ( + 'waiting_response', 'waiting_clarification', + 'internal_review', 'gone_postal', 'error_message', 'requires_admin' + ) and not exists ( + select * + from info_request_events later_events + where later_events.created_at > info_request_events.created_at + and later_events.info_request_id = info_request_events.info_request_id + )") + + + get :list, :view => 'awaiting' + assigns[:list_results].map(&:info_request).include?(info_requests(:fancy_dog_request)).should == false + + event = info_request_events(:useless_incoming_message_event) + event.described_state = event.calculated_state = "internal_review" + event.save! + rebuild_xapian_index + + get :list, :view => 'awaiting' + assigns[:list_results].map(&:info_request).include?(info_requests(:fancy_dog_request)).should == true end it "should assign the first page of results" do xap_results = mock_model(ActsAsXapian::Search, :results => (1..25).to_a.map { |m| { :model => m } }, - :matches_estimated => 103) + :matches_estimated => 1000000) InfoRequest.should_receive(:full_search). - with([InfoRequestEvent]," variety:sent", "created_at", anything, anything, anything, anything). + with([InfoRequestEvent]," (variety:sent OR variety:followup_sent OR variety:response OR variety:comment)", "created_at", anything, anything, anything, anything). and_return(xap_results) - get :list, :view => 'recent' + get :list, :view => 'all' assigns[:list_results].size.should == 25 + assigns[:show_no_more_than].should == RequestController::MAX_RESULTS end + it "should return 404 for pages we don't want to serve up" do + xap_results = mock_model(ActsAsXapian::Search, + :results => (1..25).to_a.map { |m| { :model => m } }, + :matches_estimated => 1000000) + lambda { + get :list, :view => 'all', :page => 100 + }.should raise_error(ActiveRecord::RecordNotFound) + end + end describe RequestController, "when showing one request" do - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views - before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should be successful" do @@ -80,24 +147,40 @@ describe RequestController, "when showing one request" do describe 'when handling an update_status parameter' do - - before do - mock_request = mock_model(InfoRequest, :url_title => 'test_title', - :title => 'test title', - :null_object => true) - InfoRequest.stub!(:find_by_url_title).and_return(mock_request) - end - it 'should assign the "update status" flag to the view as true if the parameter is present' do - get :show, :url_title => 'test_title', :update_status => 1 + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog', :update_status => 1 assigns[:update_status].should be_true end - it 'should assign the "update status" flag to the view as true if the parameter is present' do - get :show, :url_title => 'test_title' + it 'should assign the "update status" flag to the view as false if the parameter is not present' do + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' assigns[:update_status].should be_false end + it 'should require login' do + session[:user_id] = nil + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog', :update_status => 1 + post_redirect = PostRedirect.get_last_post_redirect + response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) + end + + it 'should work if logged in as the requester' do + session[:user_id] = users(:bob_smith_user).id + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog', :update_status => 1 + response.should render_template "request/show" + end + + it 'should not work if logged in as not the requester' do + session[:user_id] = users(:silly_name_user).id + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog', :update_status => 1 + response.should render_template "user/wrong_user" + end + + it 'should work if logged in as an admin user' do + session[:user_id] = users(:admin_user).id + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog', :update_status => 1 + response.should render_template "request/show" + end end describe 'when handling incoming mail' do @@ -123,7 +206,8 @@ describe RequestController, "when showing one request" do it "should download attachments" do ir = info_requests(:fancy_dog_request) - ir.incoming_messages.each { |x| x.parse_raw_email! } + ir.incoming_messages.each { |x| x.parse_raw_email!(true) } + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' response.content_type.should == "text/html" size_before = assigns[:info_request_events].size @@ -134,10 +218,12 @@ describe RequestController, "when showing one request" do get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' (assigns[:info_request_events].size - size_before).should == 1 ir.reload - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :file_name => ['hello.txt'] + + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :file_name => ['hello.txt'], :skip_cache => 1 response.content_type.should == "text/plain" response.should have_text(/Second hello/) - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 3, :file_name => ['hello.txt'] + + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 3, :file_name => ['hello.txt'], :skip_cache => 1 response.content_type.should == "text/plain" response.should have_text(/First hello/) end @@ -149,7 +235,7 @@ describe RequestController, "when showing one request" do response.should have_text(/tënde/u) end - it "should generate valid HTML verson of plain text attachments " do + it "should generate valid HTML verson of plain text attachments" do ir = info_requests(:fancy_dog_request) receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) ir.reload @@ -158,6 +244,71 @@ describe RequestController, "when showing one request" do response.should have_text(/Second hello/) end + # This is a regression test for a bug where URLs of this form were causing 500 errors + # instead of 404s. + # + # (Note that in fact only the integer-prefix of the URL part is used, so there are + # *some* “ugly URLs containing a request id that isn't an integer” that actually return + # a 200 response. The point is that IDs of this sort were triggering an error in the + # error-handling path, causing the wrong sort of error response to be returned in the + # case where the integer prefix referred to the wrong request.) + # + # https://github.com/sebbacon/alaveteli/issues/351 + it "should return 404 for ugly URLs containing a request id that isn't an integer" do + ir = info_requests(:fancy_dog_request) + receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) + ir.reload + ugly_id = "55195" + lambda { + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ugly_id, :part => 2, :file_name => ['hello.txt.html'], :skip_cache => 1 + }.should raise_error(ActiveRecord::RecordNotFound) + + lambda { + get :get_attachment_as_html, :incoming_message_id => ir.incoming_messages[1].id, :id => ugly_id, :part => 2, :file_name => ['hello.txt'], :skip_cache => 1 + }.should raise_error(ActiveRecord::RecordNotFound) + end + it "should return 404 when incoming message and request ids don't match" do + ir = info_requests(:fancy_dog_request) + wrong_id = info_requests(:naughty_chicken_request).id + receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) + ir.reload + lambda { + get :get_attachment_as_html, :incoming_message_id => ir.incoming_messages[1].id, :id => wrong_id, :part => 2, :file_name => ['hello.txt.html'], :skip_cache => 1 + }.should raise_error(ActiveRecord::RecordNotFound) + end + it "should return 404 for ugly URLs contain a request id that isn't an integer, even if the integer prefix refers to an actual request" do + ir = info_requests(:fancy_dog_request) + receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) + ir.reload + ugly_id = "%d95" % [info_requests(:naughty_chicken_request).id] + + lambda { + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ugly_id, :part => 2, :file_name => ['hello.txt.html'], :skip_cache => 1 + }.should raise_error(ActiveRecord::RecordNotFound) + + lambda { + get :get_attachment_as_html, :incoming_message_id => ir.incoming_messages[1].id, :id => ugly_id, :part => 2, :file_name => ['hello.txt'], :skip_cache => 1 + }.should raise_error(ActiveRecord::RecordNotFound) + end + it "should return 404 when incoming message and request ids don't match" do + ir = info_requests(:fancy_dog_request) + wrong_id = info_requests(:naughty_chicken_request).id + receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) + ir.reload + lambda { + get :get_attachment_as_html, :incoming_message_id => ir.incoming_messages[1].id, :id => wrong_id, :part => 2, :file_name => ['hello.txt.html'], :skip_cache => 1 + }.should raise_error(ActiveRecord::RecordNotFound) + end + + it "should generate valid HTML verson of PDF attachments " do + ir = info_requests(:fancy_dog_request) + receive_incoming_mail('incoming-request-pdf-attachment.email', ir.incoming_email) + ir.reload + get :get_attachment_as_html, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :file_name => ['fs_50379341.pdf.html'], :skip_cache => 1 + response.content_type.should == "text/html" + response.should have_text(/Walberswick Parish Council/) + end + it "should not cause a reparsing of the raw email, even when the result would be a 404 " do ir = info_requests(:fancy_dog_request) receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) @@ -205,7 +356,7 @@ describe RequestController, "when showing one request" do receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) lambda { - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :file_name => ['http://trying.to.hack'] }.should raise_error(ActiveRecord::RecordNotFound) end @@ -219,12 +370,16 @@ describe RequestController, "when showing one request" do censor_rule.last_edit_editor = "unknown" censor_rule.last_edit_comment = "none" ir.censor_rules << censor_rule - - receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) - - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :file_name => ['hello.txt'] - response.content_type.should == "text/plain" - response.should have_text(/xxxxxx hello/) + + begin + receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) + + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :file_name => ['hello.txt'], :skip_cache => 1 + response.content_type.should == "text/plain" + response.should have_text(/xxxxxx hello/) + ensure + ir.censor_rules.clear + end end it "should censor with rules on the user (rather than the request)" do @@ -237,12 +392,16 @@ describe RequestController, "when showing one request" do censor_rule.last_edit_comment = "none" ir.user.censor_rules << censor_rule - receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) - ir.reload + begin + receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) + ir.reload - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :file_name => ['hello.txt'], :skip_cache => 1 - response.content_type.should == "text/plain" - response.should have_text(/xxxxxx hello/) + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :file_name => ['hello.txt'], :skip_cache => 1 + response.content_type.should == "text/plain" + response.should have_text(/xxxxxx hello/) + ensure + ir.user.censor_rules.clear + end end it "should censor attachment names" do @@ -273,9 +432,12 @@ describe RequestController, "when showing one request" do censor_rule.last_edit_editor = "unknown" censor_rule.last_edit_comment = "none" ir.censor_rules << censor_rule - - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' - response.body.should have_tag("p.attachment strong", /goodbye.txt/m) + begin + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' + response.body.should have_tag("p.attachment strong", /goodbye.txt/m) + ensure + ir.censor_rules.clear + end end it "should make a zipfile available, which has a different URL when it changes" do @@ -287,7 +449,7 @@ describe RequestController, "when showing one request" do old_path = assigns[:url_path] response.location.should have_text(/#{assigns[:url_path]}$/) zipfile = Zip::ZipFile.open(File.join(File.dirname(__FILE__), "../../cache/zips", old_path)) { |zipfile| - zipfile.count.should == 2 + zipfile.count.should == 1 # just the message } receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) get :download_entire_request, :url_title => title @@ -295,25 +457,29 @@ describe RequestController, "when showing one request" do old_path = assigns[:url_path] response.location.should have_text(/#{assigns[:url_path]}$/) zipfile = Zip::ZipFile.open(File.join(File.dirname(__FILE__), "../../cache/zips", old_path)) { |zipfile| - zipfile.count.should == 2 + zipfile.count.should == 3 # the message plus two "hello.txt" files } + + # 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('incoming-request-attachment-unknown-extension.email', ir.incoming_email) get :download_entire_request, :url_title => title assigns[:url_path].should have_text(/#{title}.zip$/) + 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 == 4 + zipfile.count.should == 5 # the message, two hello.txt, the unknown attachment, and its empty message } - assigns[:url_path].should_not == old_path end end end describe RequestController, "when changing prominence of a request" do - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :info_request_events, :track_things # all needed as integrating views before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should not show hidden requests" do @@ -379,11 +545,11 @@ describe RequestController, "when changing prominence of a request" do ir.save! receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2 + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :skip_cache => 1 response.content_type.should == "text/html" response.should_not have_text(/Second hello/) response.should render_template('request/hidden') - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 3 + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 3, :skip_cache => 1 response.content_type.should == "text/html" response.should_not have_text(/First hello/) response.should render_template('request/hidden') @@ -398,7 +564,6 @@ end # end describe RequestController, "when searching for an authority" do - fixtures :public_bodies, :users # Whether or not sign-in is required for this step is configurable, # so we make sure we're logged in, just in case @@ -411,7 +576,7 @@ describe RequestController, "when searching for an authority" do get :select_authority, :query => "" response.should render_template('select_authority') - assigns[:xapian_requests].results.size == 0 + assigns[:xapian_requests].should == nil end it "should return matching bodies" do @@ -422,11 +587,24 @@ describe RequestController, "when searching for an authority" do assigns[:xapian_requests].results.size == 1 assigns[:xapian_requests].results[0][:model].name.should == public_bodies(:geraldine_public_body).name end + + it "should not give an error when user users unintended search operators" do + for phrase in ["Marketing/PR activities - Aldborough E-Act Free Schoo", + "Request for communications between DCMS/Ed Vaizey and ICO from Jan 1st 2011 - May ", + "Bellevue Road Ryde Isle of Wight PO33 2AR - what is the", + "NHS Ayrshire & Arran", + " cardiff", + "Foo * bax", + "qux ~ quux"] + lambda { + get :select_authority, :query => phrase + }.should_not raise_error(StandardError) + end + end end describe RequestController, "when creating a new request" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before do @user = users(:bob_smith_user) @@ -555,6 +733,58 @@ describe RequestController, "when creating a new request" do response.should redirect_to(:action => 'show', :url_title => ir2.url_title) end + + it 'should respect the rate limit' do + # Try to create three requests in succession. + # (The limit set in config/test.yml is two.) + session[:user_id] = users(:robin_user) + + post :new, :info_request => { :public_body_id => @body.id, + :title => "What is the answer to the ultimate question?", :tag_string => "" }, + :outgoing_message => { :body => "Please supply the answer from your files." }, + :submitted_new_request => 1, :preview => 0 + response.should redirect_to(:action => 'show', :url_title => 'what_is_the_answer_to_the_ultima') + + + post :new, :info_request => { :public_body_id => @body.id, + :title => "Why did the chicken cross the road?", :tag_string => "" }, + :outgoing_message => { :body => "Please send me all the relevant documents you hold." }, + :submitted_new_request => 1, :preview => 0 + response.should redirect_to(:action => 'show', :url_title => 'why_did_the_chicken_cross_the_ro') + + post :new, :info_request => { :public_body_id => @body.id, + :title => "What's black and white and red all over?", :tag_string => "" }, + :outgoing_message => { :body => "Please send all minutes of meetings and email records that address this question." }, + :submitted_new_request => 1, :preview => 0 + response.should render_template('user/rate_limited') + end + + it 'should ignore the rate limit for specified users' do + # Try to create three requests in succession. + # (The limit set in config/test.yml is two.) + session[:user_id] = users(:robin_user) + users(:robin_user).no_limit = true + users(:robin_user).save! + + post :new, :info_request => { :public_body_id => @body.id, + :title => "What is the answer to the ultimate question?", :tag_string => "" }, + :outgoing_message => { :body => "Please supply the answer from your files." }, + :submitted_new_request => 1, :preview => 0 + response.should redirect_to(:action => 'show', :url_title => 'what_is_the_answer_to_the_ultima') + + + post :new, :info_request => { :public_body_id => @body.id, + :title => "Why did the chicken cross the road?", :tag_string => "" }, + :outgoing_message => { :body => "Please send me all the relevant documents you hold." }, + :submitted_new_request => 1, :preview => 0 + response.should redirect_to(:action => 'show', :url_title => 'why_did_the_chicken_cross_the_ro') + + post :new, :info_request => { :public_body_id => @body.id, + :title => "What's black and white and red all over?", :tag_string => "" }, + :outgoing_message => { :body => "Please send all minutes of meetings and email records that address this question." }, + :submitted_new_request => 1, :preview => 0 + response.should redirect_to(:action => 'show', :url_title => 'whats_black_and_white_and_red_al') + end end @@ -600,6 +830,7 @@ describe RequestController, "when making a new request" do it "should fail if user is banned" do @user.stub!(:can_file_requests?).and_return(false) + @user.stub!(:exceeded_limit?).and_return(false) @user.should_receive(:can_fail_html).and_return('FAIL!') session[:user_id] = @user.id get :new, :public_body_id => @body.id @@ -610,10 +841,9 @@ end describe RequestController, "when viewing an individual response for reply/followup" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should ask for login if you are logged in as wrong person" do @@ -657,13 +887,11 @@ end describe RequestController, "when classifying an information request" do - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views - before(:each) do @dog_request = info_requests(:fancy_dog_request) @dog_request.stub!(:is_old_unclassified?).and_return(false) InfoRequest.stub!(:find).and_return(@dog_request) - load_raw_emails_data(raw_emails) + load_raw_emails_data end def post_status(status) @@ -901,7 +1129,11 @@ describe RequestController, "when classifying an information request" do session[:user_id] = @request_owner.id @dog_request = info_requests(:fancy_dog_request) InfoRequest.stub!(:find).and_return(@dog_request) - ActionController::Routing::Routes.filters.clear + @old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + end + after do + ActionController::Routing::Routes.filters = @old_filters end def request_url @@ -993,10 +1225,9 @@ end describe RequestController, "when sending a followup message" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should require login" do @@ -1076,10 +1307,9 @@ end describe RequestController, "sending overdue request alerts" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should send an overdue alert mail to creators of overdue requests" do @@ -1090,8 +1320,8 @@ describe RequestController, "sending overdue request alerts" do RequestMailer.alert_overdue_requests deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - mail = deliveries[0] + deliveries.size.should == 2 + mail = deliveries[1] mail.body.should =~ /promptly, as normally/ mail.to_addrs.first.to_s.should == info_requests(:naughty_chicken_request).user.name_and_email @@ -1118,8 +1348,8 @@ describe RequestController, "sending overdue request alerts" do RequestMailer.alert_overdue_requests deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - mail = deliveries[0] + deliveries.size.should == 2 + mail = deliveries[1] mail.body.should =~ /promptly, as normally/ mail.to_addrs.first.to_s.should == info_requests(:naughty_chicken_request).user.name_and_email end @@ -1143,8 +1373,8 @@ describe RequestController, "sending overdue request alerts" do RequestMailer.alert_overdue_requests deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - mail = deliveries[0] + deliveries.size.should == 2 + mail = deliveries[1] mail.body.should =~ /required by law/ mail.to_addrs.first.to_s.should == info_requests(:naughty_chicken_request).user.name_and_email @@ -1164,10 +1394,9 @@ end describe RequestController, "sending unclassified new response reminder alerts" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should send an alert" do @@ -1195,9 +1424,8 @@ end describe RequestController, "clarification required alerts" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should send an alert" do @@ -1249,9 +1477,8 @@ end describe RequestController, "comment alerts" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should send an alert (once and once only)" do @@ -1324,9 +1551,8 @@ end describe RequestController, "when viewing comments" do integrate_views - fixtures :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should link to the user who submitted it" do @@ -1348,7 +1574,6 @@ end describe RequestController, "authority uploads a response from the web interface" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before(:each) do # domain after the @ is used for authentication of FOI officers, so to test it @@ -1434,11 +1659,9 @@ describe RequestController, "authority uploads a response from the web interface end describe RequestController, "when showing JSON version for API" do - - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should return data in JSON form" do @@ -1455,7 +1678,8 @@ describe RequestController, "when showing JSON version for API" do end describe RequestController, "when doing type ahead searches" do - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things + + integrate_views it "should return nothing for the empty query string" do get :search_typeahead, :q => "" @@ -1473,16 +1697,44 @@ describe RequestController, "when doing type ahead searches" do it "should return all requests matching any of the given keywords" do get :search_typeahead, :q => "money dog" response.should render_template('request/_search_ahead.rhtml') - assigns[:xapian_requests].results.size.should == 2 - assigns[:xapian_requests].results[0][:model].title.should == info_requests(:fancy_dog_request).title - assigns[:xapian_requests].results[1][:model].title.should == info_requests(:naughty_chicken_request).title + assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ [ + info_requests(:fancy_dog_request), + info_requests(:naughty_chicken_request), + info_requests(:another_boring_request), + ] end - it "should not return matches for short words" do + it "should not return matches for short words" do get :search_typeahead, :q => "a" response.should render_template('request/_search_ahead.rhtml') assigns[:xapian_requests].should be_nil end + + it "should do partial matches for longer words" do + get :search_typeahead, :q => "chick" + response.should render_template('request/_search_ahead.rhtml') + assigns[:xapian_requests].results.size.should ==1 + end + + it "should not give an error when user users unintended search operators" do + for phrase in ["Marketing/PR activities - Aldborough E-Act Free Schoo", + "Request for communications between DCMS/Ed Vaizey and ICO from Jan 1st 2011 - May ", + "Bellevue Road Ryde Isle of Wight PO33 2AR - what is the", + "NHS Ayrshire & Arran", + "uda ( units of dent", + "frob * baz", + "bar ~ qux"] + lambda { + get :search_typeahead, :q => phrase + }.should_not raise_error(StandardError) + end + end + + it "should return all requests matching any of the given keywords" do + get :search_typeahead, :q => "dog -chicken" + assigns[:xapian_requests].results.size.should == 1 + end + end diff --git a/spec/controllers/request_game_controller_spec.rb b/spec/controllers/request_game_controller_spec.rb index cc0808ef3..7247cd388 100644 --- a/spec/controllers/request_game_controller_spec.rb +++ b/spec/controllers/request_game_controller_spec.rb @@ -1,10 +1,8 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe RequestGameController, "when playing the game" do - - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things # all needed as integrating views before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data end it "should show the game homepage" do diff --git a/spec/controllers/track_controller_spec.rb b/spec/controllers/track_controller_spec.rb index 90d13495f..38a447640 100644 --- a/spec/controllers/track_controller_spec.rb +++ b/spec/controllers/track_controller_spec.rb @@ -36,17 +36,18 @@ end describe TrackController, "when sending alerts for a track" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things, :track_things_sent_emails include LinkToHelper # for main_url before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data rebuild_xapian_index end it "should send alerts" do # Don't do clever locale-insertion-unto-URL stuff - ActionController::Routing::Routes.filters.clear + old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + # set the time the comment event happened at to within the last week ire = info_request_events(:silly_comment_event) ire.created_at = Time.now - 3.days @@ -91,6 +92,9 @@ describe TrackController, "when sending alerts for a track" do TrackMailer.alert_tracks deliveries = ActionMailer::Base.deliveries deliveries.size.should == 0 + + # Restore the routing filters + ActionController::Routing::Routes.filters = old_filters end it "should send localised alerts" do @@ -110,10 +114,9 @@ end describe TrackController, "when viewing RSS feed for a track" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data rebuild_xapian_index end @@ -136,10 +139,9 @@ end describe TrackController, "when viewing JSON version of a track feed" do integrate_views - fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data rebuild_xapian_index end diff --git a/spec/controllers/user_controller_spec.rb b/spec/controllers/user_controller_spec.rb index 399b275a7..1a701ad43 100644 --- a/spec/controllers/user_controller_spec.rb +++ b/spec/controllers/user_controller_spec.rb @@ -8,9 +8,9 @@ require 'json' describe UserController, "when showing a user" do integrate_views - fixtures :users, :public_bodies, :public_body_translations, :public_body_versions, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things before(:each) do - load_raw_emails_data(raw_emails) + load_raw_emails_data + rebuild_xapian_index end it "should be successful" do @@ -28,6 +28,16 @@ describe UserController, "when showing a user" do response.should render_template('show') end + it "should distinguish between 'my profile' and 'my requests' for logged in users" do + session[:user_id] = users(:bob_smith_user).id + get :show, :url_name => "bob_smith", :view => 'requests' + response.body.should_not include("Change your password") + response.body.should match(/Your [0-9]+ Freedom of Information requests/) + get :show, :url_name => "bob_smith", :view => 'profile' + response.body.should include("Change your password") + response.body.should_not match(/Your [0-9]+ Freedom of Information requests/) + end + it "should assign the user" do get :show, :url_name => "bob_smith" assigns[:display_user].should == users(:bob_smith_user) @@ -35,22 +45,28 @@ describe UserController, "when showing a user" do it "should search the user's contributions" do get :show, :url_name => "bob_smith" - assigns[:xapian_requests].results.count.should == 2 + assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ InfoRequest.all( + :conditions => "user_id = #{users(:bob_smith_user).id}") + get :show, :url_name => "bob_smith", :user_query => "money" - assigns[:xapian_requests].results.count.should == 1 + assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ [ + info_requests(:naughty_chicken_request), + info_requests(:another_boring_request), + ] end -# Error handling not quite good enough for this yet -# it "should not show unconfirmed users" do -# get :show, :url_name => "silly_emnameem" -# assigns[:display_users].should == [ users(:silly_name_user) ] -# end + it "should not show unconfirmed users" do + begin + get :show, :url_name => "unconfirmed_user" + rescue => e + end + e.should be_an_instance_of(ActiveRecord::RecordNotFound) + end end describe UserController, "when signing in" do integrate_views - fixtures :users def get_last_postredirect post_redirects = PostRedirect.find_by_sql("select * from post_redirects order by id desc limit 1") @@ -86,7 +102,9 @@ describe UserController, "when signing in" do end it "should log in when you give right email/password, and redirect to where you were" do - ActionController::Routing::Routes.filters.clear + old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + get :signin, :r => "/list" response.should render_template('sign') post_redirect = get_last_postredirect @@ -97,6 +115,26 @@ describe UserController, "when signing in" do # response doesn't contain /en/ but redirect_to does... response.should redirect_to(:controller => 'request', :action => 'list', :post_redirect => 1) response.should_not send_email + + ActionController::Routing::Routes.filters = old_filters + end + + it "should not log you in if you use an invalid PostRedirect token, and shouldn't give 500 error either" do + old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + + post_redirect = "something invalid" + lambda { + post :signin, { :user_signin => { :email => 'bob@localhost', :password => 'jonespassword' }, + :token => post_redirect + } + }.should_not raise_error(NoMethodError) + post :signin, { :user_signin => { :email => 'bob@localhost', :password => 'jonespassword' }, + :token => post_redirect } + response.should render_template('sign') + assigns[:post_redirect].should == nil + + ActionController::Routing::Routes.filters = old_filters end # No idea how to test this in the test framework :( @@ -120,7 +158,9 @@ describe UserController, "when signing in" do end it "should confirm your email, log you in and redirect you to where you were after you click an email link" do - ActionController::Routing::Routes.filters.clear + old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + get :signin, :r => "/list" post_redirect = get_last_postredirect @@ -146,13 +186,14 @@ describe UserController, "when signing in" do get :confirm, :email_token => post_redirect.email_token session[:user_id].should == users(:unconfirmed_user).id response.should redirect_to(:controller => 'request', :action => 'list', :post_redirect => 1) + + ActionController::Routing::Routes.filters = old_filters end end describe UserController, "when signing up" do integrate_views - fixtures :users it "should be an error if you type the password differently each time" do post :signup, { :user_signup => { :email => 'new@localhost', :name => 'New Person', @@ -210,7 +251,6 @@ end describe UserController, "when signing out" do integrate_views - fixtures :users it "should log you out and redirect to the home page" do session[:user_id] = users(:bob_smith_user).id @@ -220,18 +260,21 @@ describe UserController, "when signing out" do end it "should log you out and redirect you to where you were" do - ActionController::Routing::Routes.filters.clear + old_filters = ActionController::Routing::Routes.filters + ActionController::Routing::Routes.filters = RoutingFilter::Chain.new + session[:user_id] = users(:bob_smith_user).id get :signout, :r => '/list' session[:user_id].should be_nil response.should redirect_to(:controller => 'request', :action => 'list') + + ActionController::Routing::Routes.filters = old_filters end end describe UserController, "when sending another user a message" do integrate_views - fixtures :users 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) @@ -269,7 +312,6 @@ end describe UserController, "when changing password" do integrate_views - fixtures :users it "should show the email form when not logged in" do get :signchangepassword @@ -340,7 +382,6 @@ end describe UserController, "when changing email address" do integrate_views - fixtures :users it "should require login" do get :signchangeemail @@ -486,7 +527,6 @@ end describe UserController, "when using profile photos" do integrate_views - fixtures :users before do @user = users(:bob_smith_user) @@ -502,6 +542,13 @@ describe UserController, "when using profile photos" do post :set_profile_photo, { :id => @user.id, :file => @uploadedfile, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } end + it "should return a 404 not a 500 when a profile photo has not been set" do + @user.profile_photo.should be_nil + lambda { + get :get_profile_photo, {:url_name => @user.url_name } + }.should raise_error(ActiveRecord::RecordNotFound) + end + it "should let you change profile photo if you're logged in as the user" do @user.profile_photo.should be_nil session[:user_id] = @user.id @@ -535,8 +582,6 @@ describe UserController, "when using profile photos" do end describe UserController, "when showing JSON version for API" do - - fixtures :users it "should be successful" do get :show, :url_name => "bob_smith", :format => "json" |