diff options
Diffstat (limited to 'spec')
23 files changed, 720 insertions, 271 deletions
diff --git a/spec/controllers/general_controller_spec.rb b/spec/controllers/general_controller_spec.rb index 8c86ad0be..7590a5b42 100644 --- a/spec/controllers/general_controller_spec.rb +++ b/spec/controllers/general_controller_spec.rb @@ -42,6 +42,17 @@ describe GeneralController, 'when getting the blog feed' do assigns[:blog_items].count.should == 1 end + context 'if no feed is configured' do + + before do + AlaveteliConfiguration.stub!(:blog_feed).and_return('') + end + + it 'should raise an ActiveRecord::RecordNotFound error' do + lambda{ get :blog }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end describe GeneralController, "when showing the frontpage" do @@ -73,11 +84,10 @@ describe GeneralController, "when showing the frontpage" do end it "should render the front page with default language" do - old_default_locale = I18n.default_locale - I18n.default_locale = "es" - get :frontpage - response.should have_selector('html[lang="es"]') - I18n.default_locale = old_default_locale + with_default_locale("es") do + get :frontpage + response.should have_selector('html[lang="es"]') + end end it "should render the front page with default language and ignore the browser setting" do @@ -85,11 +95,10 @@ describe GeneralController, "when showing the frontpage" do config['USE_DEFAULT_BROWSER_LANGUAGE'] = false accept_language = "en-GB,en-US;q=0.8,en;q=0.6" request.env['HTTP_ACCEPT_LANGUAGE'] = accept_language - old_default_locale = I18n.default_locale - I18n.default_locale = "es" - get :frontpage - response.should have_selector('html[lang="es"]') - I18n.default_locale = old_default_locale + with_default_locale("es") do + get :frontpage + response.should have_selector('html[lang="es"]') + end end it "should render the front page with browser-selected language when there's no default set" do @@ -118,49 +127,7 @@ describe GeneralController, "when showing the frontpage" do end end -describe GeneralController, "when showing the front page with fixture data" do - - describe 'when constructing the list of recent requests' do - before(:each) do - get_fixtures_xapian_index - end - - describe 'when there are fewer than five successful requests' do - - it 'should list the most recently sent and successful requests by the creation date of the - request event' do - # Make sure the newest response is listed first even if a request - # with an older response has a newer comment or was reclassified more recently: - # https://github.com/mysociety/alaveteli/issues/370 - # - # This is a deliberate behaviour change, in that the - # previous behaviour (showing more-recently-reclassified - # requests first) was intentional. - get :frontpage - - request_events = assigns[:request_events] - previous = nil - request_events.each do |event| - if previous - previous.created_at.should be >= event.created_at - end - ['sent', 'response'].include?(event.event_type).should be_true - if event.event_type == 'response' - ['successful', 'partially_successful'].include?(event.calculated_state).should be_true - end - previous = event - end - end - 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 - -end describe GeneralController, 'when using xapian search' do @@ -219,6 +186,17 @@ describe GeneralController, 'when using xapian search' do assigns[:xapian_bodies].should == nil end + it 'should highlight words for a user-only request' do + get :search, :combined => "bob/users" + assigns[:highlight_words].should == ['bob'] + end + + it 'should show spelling corrections for a user-only request' do + get :search, :combined => "rob/users" + assigns[:spelling_correction].should == 'bob' + response.body.should include('did_you_mean') + end + it "should filter results based on end of URL being 'requests'" do get :search, :combined => "bob/requests" assigns[:xapian_requests].results.map{|x|x[:model]}.should =~ [ @@ -238,6 +216,11 @@ describe GeneralController, 'when using xapian search' do assigns[:xapian_bodies].results.map{|x|x[:model]}.should == [public_bodies(:geraldine_public_body)] end + it 'should show "Browse all" link if there are no results for a search restricted to bodies' do + get :search, :combined => "noresultsshouldbefound/bodies" + response.body.should include('Browse all') + end + it "should show help when searching for nothing" do get :search_redirect, :query => nil response.should render_template('search') diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index 025ebfdba..63989baaa 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -82,21 +82,23 @@ describe PublicBodyController, "when listing bodies" do def make_single_language_example(locale) result = nil - I18n.with_locale(locale) do - case locale - when :en - result = PublicBody.new(:name => 'English only', - :short_name => 'EO') - when :es - result = PublicBody.new(:name => 'Español Solamente', - :short_name => 'ES') - else - raise StandardError.new "Unknown locale #{locale}" + with_default_locale(locale) do + I18n.with_locale(locale) do + case locale + when :en + result = PublicBody.new(:name => 'English only', + :short_name => 'EO') + when :es + result = PublicBody.new(:name => 'Español Solamente', + :short_name => 'ES') + else + raise StandardError.new "Unknown locale #{locale}" + end + result.request_email = "#{locale}@example.org" + result.last_edit_editor = 'test' + result.last_edit_comment = '' + result.save end - result.request_email = "#{locale}@example.org" - result.last_edit_editor = 'test' - result.last_edit_comment = '' - result.save end result end @@ -188,13 +190,13 @@ describe PublicBodyController, "when listing bodies" do end it "should list bodies in alphabetical order with different locale" do - I18n.default_locale = :es - get :list - response.should render_template('list') - assigns[:public_bodies].should == [ public_bodies(:geraldine_public_body), public_bodies(:humpadink_public_body) ] - assigns[:tag].should == "all" - assigns[:description].should == "" - I18n.default_locale = :en + with_default_locale(:es) do + get :list + response.should render_template('list') + assigns[:public_bodies].should == [ public_bodies(:geraldine_public_body), public_bodies(:humpadink_public_body) ] + assigns[:tag].should == "all" + assigns[:description].should == "" + end 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 @@ -273,41 +275,142 @@ describe PublicBodyController, "when showing JSON version for API" do end +describe PublicBodyController, "when asked to export public bodies as CSV" do + + it "should return a valid CSV file with the right number of rows" do + get :list_all_csv + all_data = CSV.parse response.body + all_data.length.should == 8 + # Check that the header has the right number of columns: + all_data[0].length.should == 11 + # And an actual line of data: + all_data[1].length.should == 11 + end + +end + describe PublicBodyController, "when showing public body statistics" do - it "should render the right template with the right data" do - config = MySociety::Config.load_default() - config['MINIMUM_REQUESTS_FOR_STATISTICS'] = 1 - config['PUBLIC_BODY_STATISTICS_PAGE'] = true - get :statistics - response.should render_template('public_body/statistics') - # There are 5 different graphs we're creating at the moment. - assigns[:graph_list].length.should == 5 - # The first is the only one with raw values, the rest are - # percentages with error bars: - assigns[:graph_list].each_with_index do |graph, index| - if index == 0 - graph['errorbars'].should be_false - graph['x_values'].length.should == 4 - graph['x_values'].should == [0, 1, 2, 3] - graph['y_values'].should == [1, 2, 2, 4] - else - graph['errorbars'].should be_true - # Just check the first one: - if index == 1 - graph['x_values'].should == [0, 1, 2, 3] - graph['y_values'].should == [0, 50, 100, 100] + it "should render the right template with the right data" do + config = MySociety::Config.load_default() + config['MINIMUM_REQUESTS_FOR_STATISTICS'] = 1 + config['PUBLIC_BODY_STATISTICS_PAGE'] = true + get :statistics + response.should render_template('public_body/statistics') + # There are 5 different graphs we're creating at the moment. + assigns[:graph_list].length.should == 5 + # The first is the only one with raw values, the rest are + # percentages with error bars: + assigns[:graph_list].each_with_index do |graph, index| + if index == 0 + graph['errorbars'].should be_false + graph['x_values'].length.should == 4 + graph['x_values'].should == [0, 1, 2, 3] + graph['y_values'].should == [1, 2, 2, 4] + else + graph['errorbars'].should be_true + # Just check the first one: + if index == 1 + graph['x_values'].should == [0, 1, 2, 3] + graph['y_values'].should == [0, 50, 100, 100] + end + # Check that at least every confidence interval value is + # a Float (rather than NilClass, say): + graph['cis_below'].each { |v| v.should be_instance_of(Float) } + graph['cis_above'].each { |v| v.should be_instance_of(Float) } + end end - # Check that at least every confidence interval value is - # a Float (rather than NilClass, say): - graph['cis_below'].each { |v| v.should be_instance_of(Float) } - graph['cis_above'].each { |v| v.should be_instance_of(Float) } - end end - end end +describe PublicBodyController, "when converting data for graphing" do + + before(:each) do + @raw_count_data = PublicBody.get_request_totals(n=3, + highest=true, + minimum_requests=1) + @percentages_data = PublicBody.get_request_percentages( + column='info_requests_successful_count', + n=3, + highest=false, + minimum_requests=1) + end + + it "should not include the real public body model instance" do + to_draw = controller.simplify_stats_for_graphs(@raw_count_data, + column='blah_blah', + percentages=false, + {} ) + to_draw['public_bodies'][0].class.should == Hash + to_draw['public_bodies'][0].has_key?('request_email').should be_false + end + + it "should generate the expected id" do + to_draw = controller.simplify_stats_for_graphs(@raw_count_data, + column='blah_blah', + percentages=false, + {:highest => true} ) + to_draw['id'].should == "blah_blah-highest" + to_draw = controller.simplify_stats_for_graphs(@raw_count_data, + column='blah_blah', + percentages=false, + {:highest => false} ) + to_draw['id'].should == "blah_blah-lowest" + end + + it "should have exactly the expected keys" do + to_draw = controller.simplify_stats_for_graphs(@raw_count_data, + column='blah_blah', + percentages=false, + {} ) + to_draw.keys.sort.should == ["errorbars", "id", "public_bodies", + "title", "tooltips", "totals", + "x_axis", "x_ticks", "x_values", + "y_axis", "y_max", "y_values"] + + to_draw = controller.simplify_stats_for_graphs(@percentages_data, + column='whatever', + percentages=true, + {}) + to_draw.keys.sort.should == ["cis_above", "cis_below", + "errorbars", "id", "public_bodies", + "title", "tooltips", "totals", + "x_axis", "x_ticks", "x_values", + "y_axis", "y_max", "y_values"] + end + + it "should have values of the expected class and length" do + [controller.simplify_stats_for_graphs(@raw_count_data, + column='blah_blah', + percentages=false, + {}), + controller.simplify_stats_for_graphs(@percentages_data, + column='whatever', + percentages=true, + {})].each do |to_draw| + per_pb_keys = ["cis_above", "cis_below", "public_bodies", + "tooltips", "totals", "x_ticks", "x_values", + "y_values"] + # These should be all be arrays with one element per public body: + per_pb_keys.each do |key| + if to_draw.has_key? key + to_draw[key].class.should == Array + to_draw[key].length.should eq(3), "for key #{key}" + end + end + # Just check that the rest aren't of class Array: + to_draw.keys.each do |key| + unless per_pb_keys.include? key + to_draw[key].class.should_not eq(Array), "for key #{key}" + end + end + end + end + +end + + describe PublicBodyController, "when doing type ahead searches" do render_views diff --git a/spec/controllers/track_controller_spec.rb b/spec/controllers/track_controller_spec.rb index a16024828..57d084f6b 100644 --- a/spec/controllers/track_controller_spec.rb +++ b/spec/controllers/track_controller_spec.rb @@ -55,6 +55,39 @@ describe TrackController, "when making a new track on a request" do end +describe TrackController, "when unsubscribing from a track" do + + before do + @track_thing = FactoryGirl.create(:track_thing) + end + + it 'should destroy the track thing' do + get :update, {:track_id => @track_thing.id, + :track_medium => 'delete', + :r => 'http://example.com'}, + {:user_id => @track_thing.tracking_user.id} + TrackThing.find(:first, :conditions => ['id = ? ', @track_thing.id]).should == nil + end + + it 'should redirect to a URL on the site' do + get :update, {:track_id => @track_thing.id, + :track_medium => 'delete', + :r => '/'}, + {:user_id => @track_thing.tracking_user.id} + response.should redirect_to('/') + end + + it 'should not redirect to a url on another site' do + track_thing = FactoryGirl.create(:track_thing) + get :update, {:track_id => @track_thing.id, + :track_medium => 'delete', + :r => 'http://example.com/'}, + {:user_id => @track_thing.tracking_user.id} + response.should redirect_to('/') + end + +end + describe TrackController, "when sending alerts for a track" do render_views diff --git a/spec/factories.rb b/spec/factories.rb index 653525920..7d8f94ac1 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -137,4 +137,11 @@ FactoryGirl.define do last_edit_comment "Making an edit" end + factory :track_thing do + association :tracking_user, :factory => :user + track_medium 'email_daily' + track_type 'search_query' + track_query 'Example Query' + end + end diff --git a/spec/fixtures/files/document-pdf.email b/spec/fixtures/files/document-pdf.email new file mode 100644 index 000000000..f4fc6f0fe --- /dev/null +++ b/spec/fixtures/files/document-pdf.email @@ -0,0 +1,110 @@ +From authority@example.org Tue Dec 3 11:13:02 2013 +Return-path: <authority@example.org> +Envelope-to: requester@example.org +Delivery-date: Tue, 03 Dec 2013 11:13:00 +0000 +From: Test Authority <authority@example.org> +To: requester@example.org +Subject: testing a PDF attachment with the wrong content-type +Date: Tue, 03 Dec 2013 11:12:45 +0000 +Message-ID: <87li09xuasdfasdfpoija@blahblah> +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="=-=-=" + +--=-=-= +Content-Type: text/plain + +Here's a PDF attachement which has a document/pdf content-type, +when it really should be application/pdf. + + +--=-=-= +Content-Type: application/pdf +Content-Disposition: attachment; filename=tiny-example.pdf +Content-Transfer-Encoding: base64 +Content-Description: a very small example PDF + +JVBERi0xLjUKJbXtrvsKMyAwIG9iago8PCAvTGVuZ3RoIDQgMCBSCiAgIC9GaWx0ZXIgL0ZsYXRl +RGVjb2RlCj4+CnN0cmVhbQp4nCvkMlAAwaJ0Bf1EA4X0Yi6nEC5DA1M9IwNLYzNjsBwS18hIz9TI +0tBSwdzIQs/Y3MLAzEQhJJdLP03XQBeoUCEkjStawyM1JydfUTM2xIvLNYQrkAsAJG8VmQplbmRz +dHJlYW0KZW5kb2JqCjQgMCBvYmoKICAgOTIKZW5kb2JqCjIgMCBvYmoKPDwKICAgL0V4dEdTdGF0 +ZSA8PAogICAgICAvYTAgPDwgL0NBIDEgL2NhIDEgPj4KICAgPj4KICAgL0ZvbnQgPDwKICAgICAg +L2YtMC0wIDUgMCBSCiAgID4+Cj4+CmVuZG9iago2IDAgb2JqCjw8IC9UeXBlIC9QYWdlCiAgIC9Q +YXJlbnQgMSAwIFIKICAgL01lZGlhQm94IFsgMCAwIDU5NS4yNzU1NzQgODQxLjg4OTc3MSBdCiAg +IC9Db250ZW50cyAzIDAgUgogICAvR3JvdXAgPDwKICAgICAgL1R5cGUgL0dyb3VwCiAgICAgIC9T +IC9UcmFuc3BhcmVuY3kKICAgICAgL0kgdHJ1ZQogICAgICAvQ1MgL0RldmljZVJHQgogICA+Pgog +ICAvUmVzb3VyY2VzIDIgMCBSCj4+CmVuZG9iago3IDAgb2JqCjw8IC9MZW5ndGggOCAwIFIKICAg +L0ZpbHRlciAvRmxhdGVEZWNvZGUKICAgL0xlbmd0aDEgMzcxNgo+PgpzdHJlYW0KeJzlVnt0lMUV +v/P9vtndZB/5drMbiUlww7ookJCQECCAzYJBBSrlETXYxgayxIjQJAQVTOOCFAREgwKLAtIUkSpE +mlIkG2OtVN4xrZXH8Y0gFGkjRouoa5j0btCe0/boOW3/6OnpzM58cx9z5/7ud+fuR4KI4mkBgbxl +s6dVvXnmiTlECBJpt5bdPddLd6TlE8mXiIQqr7p9dvXgu2cSmZmmbbfPml9etrfAzOtG1o9UzJgW +7O56fQSRZRbzhlQwwxYx3cL0ZqavrJg9d97lhs76lgNM95pVWTaNKM7N9HtMp86eNq9KrzFVM93F +tLdqzoyqEeaPeRmXyj5UkEblKqyXy83srZkuD9j0L8n0pbDIkKZT1p4jHYPIONJxpCM70Znu9Kc7 +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 +1pDjEjE2zS7HGrjBjusVrgtjTBiFCtdqmfLaKEa3YtR4BBQKFL5zjUt+x41rRibIa1wYOcIuRwa6 +EzDCjuEK+QrDhrrlsCiGDjHkUDeG5FnlEAN5VgzujVw7cgZZZY7CICuys6wy244sKwZmxsmBBjLj +kJGDAf39ckAQ/fu5ZH8/+rlw9VV+efUoXOVHX79V9k2A34orFXwKfRKQzjjTXfAGcUUUvRlC7yDS +7EjlCKYqpERx+WgkM5Gs0CuIyzhSlykk8aakZHgU3AqJCi5WcCk4GatzNIw6JAThULDbkqRdwcba +tiRYFeINxClYWM2iYHbDFITOQp0zwAPmQnGVNaSWCWGAFEREBBc/JAb8LzT6bzvwrS3tr1SHeSwK +ZW5kc3RyZWFtCmVuZG9iago4IDAgb2JqCiAgIDI0MDIKZW5kb2JqCjkgMCBvYmoKPDwgL0xlbmd0 +aCAxMCAwIFIKICAgL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnicXVAxbsQgEOx5xZZ3 +xQnbykUpkKXo0ri4JIqTB2BYHKQYEMaFf58FThcpBcwsuzOMll+Gl8HZBPw9ejViAmOdjrj6LSqE +CWfrWNuBtirdqnKrRQbGSTzua8JlcMYzIYB/UHNNcYfDs/YTHhkA8LeoMVo3w+HrMtancQvhBxd0 +CRrW96DRkN1Vhle5IPAiPg2a+jbtJ5L9TXzuAaErdVsjKa9xDVJhlG5GJpqmB2FMz9Dpf71zVUxG +fcvIxMMTTTYNAROP58IJiKvKVeamcvITXVs4Qfa+ueRf8jru8dUWIyUvOyuRc1jr8L7W4ENWlfML +jQ547AplbmRzdHJlYW0KZW5kb2JqCjEwIDAgb2JqCiAgIDI0NgplbmRvYmoKMTEgMCBvYmoKPDwg +L1R5cGUgL0ZvbnREZXNjcmlwdG9yCiAgIC9Gb250TmFtZSAvUlFaWlJTK0RlamFWdVNhbnMKICAg +L0ZvbnRGYW1pbHkgKERlamFWdSBTYW5zKQogICAvRmxhZ3MgMzIKICAgL0ZvbnRCQm94IFsgLTEw +MjAgLTQxNSAxNjgwIDExNjYgXQogICAvSXRhbGljQW5nbGUgMAogICAvQXNjZW50IDkyOAogICAv +RGVzY2VudCAtMjM1CiAgIC9DYXBIZWlnaHQgMTE2NgogICAvU3RlbVYgODAKICAgL1N0ZW1IIDgw +CiAgIC9Gb250RmlsZTIgNyAwIFIKPj4KZW5kb2JqCjUgMCBvYmoKPDwgL1R5cGUgL0ZvbnQKICAg +L1N1YnR5cGUgL1RydWVUeXBlCiAgIC9CYXNlRm9udCAvUlFaWlJTK0RlamFWdVNhbnMKICAgL0Zp +cnN0Q2hhciAzMgogICAvTGFzdENoYXIgMTExCiAgIC9Gb250RGVzY3JpcHRvciAxMSAwIFIKICAg +L0VuY29kaW5nIC9XaW5BbnNpRW5jb2RpbmcKICAgL1dpZHRocyBbIDAgNDAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCA3NTEgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCA2MTUgMCAwIDAgMCAwIDAgMjc3IDAgMCA2MTEgXQogICAgL1RvVW5pY29kZSA5 +IDAgUgo+PgplbmRvYmoKMSAwIG9iago8PCAvVHlwZSAvUGFnZXMKICAgL0tpZHMgWyA2IDAgUiBd +CiAgIC9Db3VudCAxCj4+CmVuZG9iagoxMiAwIG9iago8PCAvQ3JlYXRvciAoY2Fpcm8gMS4xMi4x +NiAoaHR0cDovL2NhaXJvZ3JhcGhpY3Mub3JnKSkKICAgL1Byb2R1Y2VyIChjYWlybyAxLjEyLjE2 +IChodHRwOi8vY2Fpcm9ncmFwaGljcy5vcmcpKQo+PgplbmRvYmoKMTMgMCBvYmoKPDwgL1R5cGUg +L0NhdGFsb2cKICAgL1BhZ2VzIDEgMCBSCj4+CmVuZG9iagp4cmVmCjAgMTQKMDAwMDAwMDAwMCA2 +NTUzNSBmIAowMDAwMDA0MDYyIDAwMDAwIG4gCjAwMDAwMDAyMDUgMDAwMDAgbiAKMDAwMDAwMDAx +NSAwMDAwMCBuIAowMDAwMDAwMTg0IDAwMDAwIG4gCjAwMDAwMDM2NzkgMDAwMDAgbiAKMDAwMDAw +MDMxNCAwMDAwMCBuIAowMDAwMDAwNTQyIDAwMDAwIG4gCjAwMDAwMDMwMzggMDAwMDAgbiAKMDAw +MDAwMzA2MSAwMDAwMCBuIAowMDAwMDAzMzg1IDAwMDAwIG4gCjAwMDAwMDM0MDggMDAwMDAgbiAK +MDAwMDAwNDEyNyAwMDAwMCBuIAowMDAwMDA0MjU3IDAwMDAwIG4gCnRyYWlsZXIKPDwgL1NpemUg +MTQKICAgL1Jvb3QgMTMgMCBSCiAgIC9JbmZvIDEyIDAgUgo+PgpzdGFydHhyZWYKNDMxMAolJUVP +Rgo= +--=-=-=-- + diff --git a/spec/fixtures/files/fake-authority-type.csv b/spec/fixtures/files/fake-authority-type.csv index cb25050c6..a320941c7 100644 --- a/spec/fixtures/files/fake-authority-type.csv +++ b/spec/fixtures/files/fake-authority-type.csv @@ -2,3 +2,5 @@ ,Scottish Fake Authority,scottish_foi@localhost ,Fake Authority of Northern Ireland,ni_foi@localhost ,Gobierno de Aragón,spain_foi@localhost +,Nordic æøå,no_foi@localhost + diff --git a/spec/fixtures/outgoing_messages.yml b/spec/fixtures/outgoing_messages.yml index 971ce0cc5..92de076c4 100644 --- a/spec/fixtures/outgoing_messages.yml +++ b/spec/fixtures/outgoing_messages.yml @@ -12,6 +12,8 @@ # last_sent_at :datetime # incoming_message_followup_id :integer # what_doing :string(255) not null +# prominence :string(255) default("normal"), not null +# prominence_reason :text # useless_outgoing_message: diff --git a/spec/fixtures/public_bodies.yml b/spec/fixtures/public_bodies.yml index 71fe0a379..d0eb572b3 100644 --- a/spec/fixtures/public_bodies.yml +++ b/spec/fixtures/public_bodies.yml @@ -2,23 +2,27 @@ # # Table name: public_bodies # -# id :integer not null, primary key -# name :text not null -# short_name :text not null -# request_email :text not null -# version :integer not null -# last_edit_editor :string(255) not null -# last_edit_comment :text not null -# created_at :datetime not null -# updated_at :datetime not null -# url_name :text not null -# home_page :text default(""), not null -# notes :text default(""), not null -# first_letter :string(255) not null -# publication_scheme :text default(""), not null -# api_key :string(255) not null -# info_requests_count :integer default(0), not null -# disclosure_log :text default(""), not null +# id :integer not null, primary key +# name :text not null +# short_name :text not null +# request_email :text not null +# version :integer not null +# last_edit_editor :string(255) not null +# last_edit_comment :text not null +# created_at :datetime not null +# updated_at :datetime not null +# url_name :text not null +# home_page :text default(""), not null +# notes :text default(""), not null +# first_letter :string(255) not null +# publication_scheme :text default(""), not null +# api_key :string(255) not null +# info_requests_count :integer default(0), not null +# disclosure_log :text default(""), not null +# info_requests_successful_count :integer +# info_requests_not_held_count :integer +# info_requests_overdue_count :integer +# info_requests_visible_classified_count :integer # geraldine_public_body: @@ -35,6 +39,7 @@ geraldine_public_body: created_at: 2007-10-24 10:51:01.161639 api_key: 1 info_requests_count: 4 + info_requests_visible_classified_count: 4 info_requests_successful_count: 0 info_requests_not_held_count: 0 info_requests_overdue_count: 3 @@ -53,6 +58,7 @@ humpadink_public_body: notes: An albatross told me!!! api_key: 2 info_requests_count: 2 + info_requests_visible_classified_count: 2 info_requests_successful_count: 1 info_requests_not_held_count: 0 info_requests_overdue_count: 1 @@ -71,6 +77,7 @@ forlorn_public_body: notes: A very lonely public body that no one has corresponded with api_key: 3 info_requests_count: 0 + info_requests_visible_classified_count: 0 info_requests_successful_count: 0 info_requests_not_held_count: 0 info_requests_overdue_count: 0 @@ -89,6 +96,7 @@ silly_walks_public_body: notes: You know the one. api_key: 4 info_requests_count: 2 + info_requests_visible_classified_count: 2 info_requests_successful_count: 2 info_requests_not_held_count: 0 info_requests_overdue_count: 0 @@ -107,6 +115,7 @@ sensible_walks_public_body: created_at: 2008-10-25 10:51:01.161639 api_key: 5 info_requests_count: 1 + info_requests_visible_classified_count: 1 info_requests_successful_count: 1 info_requests_not_held_count: 0 info_requests_overdue_count: 0 @@ -125,6 +134,7 @@ other_public_body: created_at: 2008-10-25 10:51:01.161639 api_key: 6 info_requests_count: 0 + info_requests_visible_classified_count: 0 info_requests_successful_count: 0 info_requests_not_held_count: 0 info_requests_overdue_count: 0 @@ -143,6 +153,7 @@ accented_public_body: created_at: 2008-10-25 10:51:01.161639 api_key: 7 info_requests_count: 0 + info_requests_visible_classified_count: 0 info_requests_successful_count: 0 info_requests_not_held_count: 0 info_requests_overdue_count: 0 diff --git a/spec/fixtures/public_body_translations.yml b/spec/fixtures/public_body_translations.yml index 2030804ac..225bd74e2 100644 --- a/spec/fixtures/public_body_translations.yml +++ b/spec/fixtures/public_body_translations.yml @@ -10,6 +10,8 @@ geraldine_es_public_body_translation: notes: "" publication_scheme: "" disclosure_log: "" + created_at: 2007-10-24 10:51:01.161639 + updated_at: 2007-10-24 10:51:01.161639 geraldine_en_public_body_translation: name: Geraldine Quango @@ -23,6 +25,8 @@ geraldine_en_public_body_translation: notes: "" publication_scheme: "" disclosure_log: "" + created_at: 2007-10-24 10:51:01.161639 + updated_at: 2007-10-24 10:51:01.161639 humpadink_es_public_body_translation: name: "El Department for Humpadinking" @@ -36,6 +40,8 @@ humpadink_es_public_body_translation: notes: Baguette publication_scheme: "" disclosure_log: "" + created_at: 2007-10-24 10:51:01.161639 + updated_at: 2007-10-24 10:51:01.161639 humpadink_en_public_body_translation: name: "Department for Humpadinking" @@ -49,6 +55,8 @@ humpadink_en_public_body_translation: notes: An albatross told me!!! publication_scheme: "" disclosure_log: "" + created_at: 2007-10-24 10:51:01.161639 + updated_at: 2007-10-24 10:51:01.161639 forlorn_en_public_body_translation: name: "Department of Loneliness" @@ -62,6 +70,8 @@ forlorn_en_public_body_translation: notes: A very lonely public body that no one has corresponded with publication_scheme: "" disclosure_log: "" + created_at: 2007-10-24 10:51:01.161639 + updated_at: 2007-10-24 10:51:01.161639 silly_walks_en_public_body_translation: id: 6 @@ -75,6 +85,8 @@ silly_walks_en_public_body_translation: notes: You know the one. publication_scheme: "" disclosure_log: "" + created_at: 2007-10-24 10:51:01.161639 + updated_at: 2007-10-24 10:51:01.161639 sensible_walks_en_public_body_translation: id: 7 @@ -88,6 +100,8 @@ sensible_walks_en_public_body_translation: notes: I bet you’ve never heard of it. publication_scheme: "" disclosure_log: "" + created_at: 2008-10-25 10:51:01.161639 + updated_at: 2008-10-25 10:51:01.161639 other_public_body_translation: id: 8 @@ -101,6 +115,8 @@ other_public_body_translation: notes: More notes publication_scheme: "" disclosure_log: "" + created_at: 2008-10-25 10:51:01.161639 + updated_at: 2008-10-25 10:51:01.161639 humpadink_he_IL_public_body_translation: name: "Hebrew Humpadinking" @@ -114,6 +130,8 @@ humpadink_he_IL_public_body_translation: notes: An albatross told me!!! publication_scheme: "" disclosure_log: "" + created_at: 2007-10-24 10:51:01.161639 + updated_at: 2007-10-24 10:51:01.161639 accented_public_body_translation: id: 10 @@ -127,3 +145,5 @@ accented_public_body_translation: notes: This is to test unicode handling in body names publication_scheme: "" disclosure_log: "" + created_at: 2008-10-25 10:51:01.161639 + updated_at: 2008-10-25 10:51:01.161639 diff --git a/spec/fixtures/users.yml b/spec/fixtures/users.yml index d996fd31e..9eb91ee9c 100644 --- a/spec/fixtures/users.yml +++ b/spec/fixtures/users.yml @@ -20,8 +20,6 @@ # email_bounce_message :text default(""), not null # no_limit :boolean default(FALSE), not null # receive_email_alerts :boolean default(TRUE), not null -# address :string(255) -# dob :date # bob_smith_user: 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/lib/mail_handler/mail_handler_spec.rb b/spec/lib/mail_handler/mail_handler_spec.rb index aa351bd94..49a65dade 100644 --- a/spec/lib/mail_handler/mail_handler_spec.rb +++ b/spec/lib/mail_handler/mail_handler_spec.rb @@ -235,7 +235,7 @@ describe 'when deriving a name, email and formatted address from a message from it 'should quote a name with quotes in it' do should_render_from_address('"FOI \" Person" <foiperson@localhost>', - ['FOI \" Person', + ['FOI " Person', 'foiperson@localhost', '"FOI \" Person" <foiperson@localhost>']) end @@ -409,6 +409,12 @@ describe 'when getting attachment attributes' do attributes[1][:body].length.should == 7769 end + it 'should treat a document/pdf attachment as application/pdf' do + mail = get_fixture_mail('document-pdf.email') + attributes = MailHandler.get_attachment_attributes(mail) + attributes[1][:content_type].should == "application/pdf" + end + it 'should produce a consistent set of url_part_numbers, content_types, within_rfc822_subjects and filenames from an example mail with lots of attachments' do mail = get_fixture_mail('many-attachments-date-header.email') diff --git a/spec/lib/sendmail_return_path_spec.rb b/spec/lib/sendmail_return_path_spec.rb deleted file mode 100644 index 83436c2bd..000000000 --- a/spec/lib/sendmail_return_path_spec.rb +++ /dev/null @@ -1,88 +0,0 @@ -# This is a test of the monkey patches in sendmail_return_path.rb - -# In Rails 3 the monkeypatches are not needed anymore because sendmail now has the "-f" flag -# set correctly. So, strictly these tests are testing the Rails internals. So, that means we really -# should delete them. Let's do that later when things have settled down. For the time being leave -# them in - -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') - -describe "when sending email with an altered return path" do - before(:each) { ActionMailer::Base.deliveries = [] } - - it "should default to delivery method test" do - ActionMailer::Base.delivery_method.should == :test - end - - it "should let the helper change the method" do - with_delivery_method :smtp do - ActionMailer::Base.delivery_method.should == :smtp - end - ActionMailer::Base.delivery_method.should == :test - end - - # Documentation for fancy mock functions: http://rspec.info/documentation/mocks/message_expectations.html - it "should set the return path when sending email using SMTP" do - mock_smtp = mock("smtp") - mock_smtp_session = mock("smtp_session") - - mock_smtp.should_receive(:start).once.and_yield(mock_smtp_session) - # the second parameter to the SMTP session is the sender (return path) - mock_smtp_session.should_receive(:sendmail).once.with(anything(), "test@localhost", anything()) - - Net::SMTP.stub!(:new).and_return(mock_smtp) - - with_delivery_method :smtp do - ContactMailer.to_admin_message( - "Mr. Test", "test@localhost", "Test script spec/lib/sendmail_return_path_spec.rb", - "This is just a test for a test script", nil, nil, nil - ).deliver - end - - deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 0 - end - - it "should set the return path when sending email using sendmail" do - with_stub_popen do - IO.should_receive(:popen).once.with('/usr/sbin/sendmail -i -t -f "test@localhost" postmaster@localhost', "w+") - with_delivery_method :sendmail do - ContactMailer.to_admin_message( - "Mr. Test", "test@localhost", "Test script spec/lib/sendmail_return_path_spec.rb", - "This is just a test for a test script", nil, nil, nil - ).deliver - end - end - - deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 0 - end - - - protected - # Change the way Rails delivers memory, just for current scope - def with_delivery_method(new_delivery_method) - old_delivery_method, ActionMailer::Base.delivery_method = ActionMailer::Base.delivery_method, new_delivery_method - yield - ensure - ActionMailer::Base.delivery_method = old_delivery_method - end - - # By default, we can't stub popen, presumably because it is a builtin written in C. - # Replace it entirely with a normal method that just calls the C one, so we can stub it - - # this leaves IO working afterwards (for other tests that run in the same instance). - def with_stub_popen() - IO.class_eval "@orig_popen = self.method(:popen); def self.popen(a, b, &c); @orig_popen.call(a, b, &c); end" - begin - yield - ensure - # in theory would undo the popen alterations and return IO to a pristine state, but - # don't know how to (much fiddling with alias bind and the like didn't help). It - # doesn't matter - the new popen should behave just the same. - end - end - - -end - - diff --git a/spec/lib/theme_spec.rb b/spec/lib/theme_spec.rb new file mode 100644 index 000000000..829c1a269 --- /dev/null +++ b/spec/lib/theme_spec.rb @@ -0,0 +1,25 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe "theme_url_to_theme_name" do + + it "should deal with a typical bare repo URL" do + url = 'git://wherever/blah-theme.git' + theme_url_to_theme_name(url).should == 'blah-theme' + end + + it "should deal with a typical bare repo URL with trailing slashes" do + url = 'ssh://wherever/blah-theme.git//' + theme_url_to_theme_name(url).should == 'blah-theme' + end + + it "should deal with a typical non-bare repo URL" do + url = '/home/whoever/themes/blah-theme' + theme_url_to_theme_name(url).should == 'blah-theme' + end + + it "should deal with a typical non-bare repo URL with a trailing slash" do + url = '/home/whoever/themes/blah-theme/' + theme_url_to_theme_name(url).should == 'blah-theme' + end + +end diff --git a/spec/lib/whatdotheyknow/strip_empty_sessions_spec.rb b/spec/lib/whatdotheyknow/strip_empty_sessions_spec.rb index 9bd5ccb93..fcd729b48 100644 --- a/spec/lib/whatdotheyknow/strip_empty_sessions_spec.rb +++ b/spec/lib/whatdotheyknow/strip_empty_sessions_spec.rb @@ -1,71 +1,71 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') describe WhatDoTheyKnow::StripEmptySessions do - + def make_response(session_data, response_headers) app = lambda do |env| env['rack.session'] = session_data - return [200, response_headers, ['content']] + return [200, response_headers, ['content']] end strip_empty_sessions = WhatDoTheyKnow::StripEmptySessions app = strip_empty_sessions.new(app, {:key => 'mykey', :path => '', :httponly => true}) response = Rack::MockRequest.new(app).get('/', 'HTTP_ACCEPT' => 'text/html') end - - it 'should not prevent a cookie being set if there is data in the session' do - session_data = { :some_real_data => 'important', - :session_id => 'my_session_id', - :_csrf_token => 'hi_there' } - application_response_headers = { 'Content-Type' => 'text/html', + + it 'should not prevent a cookie being set if there is data in the session' do + session_data = { 'some_real_data' => 'important', + 'session_id' => 'my_session_id', + '_csrf_token' => 'hi_there' } + application_response_headers = { 'Content-Type' => 'text/html', 'Set-Cookie' => 'mykey=f274c61a35320c52d45e9f8d7d4e2649; path=/; HttpOnly'} response = make_response(session_data, application_response_headers) response.headers['Set-Cookie'].should == 'mykey=f274c61a35320c52d45e9f8d7d4e2649; path=/; HttpOnly' end - describe 'if there is no meaningful data in the session' do + describe 'if there is no meaningful data in the session' do - before do - @session_data = { :session_id => 'my_session_id', - :_csrf_token => 'hi_there' } + before do + @session_data = { 'session_id' => 'my_session_id', + '_csrf_token' => 'hi_there' } end - - it 'should not strip any other header' do + + it 'should not strip any other header' do application_response_headers = { 'Content-Type' => 'text/html', 'Set-Cookie' => 'mykey=f274c61a35320c52d45e9f8d7d4e2649; path=/; HttpOnly'} response = make_response(@session_data, application_response_headers) response.headers['Content-Type'].should == 'text/html' end - - it 'should strip the session cookie setting header ' do - application_response_headers = { 'Content-Type' => 'text/html', + + it 'should strip the session cookie setting header ' do + application_response_headers = { 'Content-Type' => 'text/html', 'Set-Cookie' => 'mykey=f274c61a35320c52d45e9f8d7d4e2649; path=/; HttpOnly'} response = make_response(@session_data, application_response_headers) response.headers['Set-Cookie'].should == "" end - - it 'should strip the session cookie setting header even with a locale' do - @session_data[:locale] = 'en' - application_response_headers = { 'Content-Type' => 'text/html', + + it 'should strip the session cookie setting header even with a locale' do + @session_data['locale'] = 'en' + application_response_headers = { 'Content-Type' => 'text/html', 'Set-Cookie' => 'mykey=f274c61a35320c52d45e9f8d7d4e2649; path=/; HttpOnly'} response = make_response(@session_data, application_response_headers) response.headers['Set-Cookie'].should == "" end - it 'should not strip the session cookie setting for admins' do - @session_data[:using_admin] = 1 - application_response_headers = { 'Content-Type' => 'text/html', + it 'should not strip the session cookie setting for admins' do + @session_data['using_admin'] = 1 + application_response_headers = { 'Content-Type' => 'text/html', 'Set-Cookie' => 'mykey=f274c61a35320c52d45e9f8d7d4e2649; path=/; HttpOnly'} response = make_response(@session_data, application_response_headers) response.headers['Set-Cookie'].should == "mykey=f274c61a35320c52d45e9f8d7d4e2649; path=/; HttpOnly" end - - it 'should strip the session cookie setting header (but no other cookie setting header) if there is more than one' do - application_response_headers = { 'Content-Type' => 'text/html', + + it 'should strip the session cookie setting header (but no other cookie setting header) if there is more than one' do + application_response_headers = { 'Content-Type' => 'text/html', 'Set-Cookie' => ['mykey=f274c61a35320c52d45e9f8d7d4e2649; path=/; HttpOnly', 'other=mydata']} response = make_response(@session_data, application_response_headers) response.headers['Set-Cookie'].should == ['other=mydata'] end - + end end diff --git a/spec/mailers/application_mailer_spec.rb b/spec/mailers/application_mailer_spec.rb index d8993f78f..718ac47fb 100644 --- a/spec/mailers/application_mailer_spec.rb +++ b/spec/mailers/application_mailer_spec.rb @@ -13,7 +13,7 @@ describe ApplicationMailer do end def add_mail_methods(method_names) - method_names.each{ |method_name| ApplicationMailer.send(:define_method, method_name){} } + method_names.each{ |method_name| ApplicationMailer.send(:define_method, method_name){ mail() } } end def remove_mail_methods(method_names) diff --git a/spec/mailers/request_mailer_spec.rb b/spec/mailers/request_mailer_spec.rb index 4e0765921..516d13127 100644 --- a/spec/mailers/request_mailer_spec.rb +++ b/spec/mailers/request_mailer_spec.rb @@ -332,6 +332,27 @@ describe RequestMailer, 'when sending mail when someone has updated an old uncla end +describe RequestMailer, 'when generating a fake response for an upload' do + + before do + @foi_officer = mock_model(User, :name_and_email => "FOI officer's name and email") + @request_user = mock_model(User) + @public_body = mock_model(PublicBody, :name => 'Test public body') + @info_request = mock_model(InfoRequest, :user => @request_user, + :email_subject_followup => 'Re: Freedom of Information - Test request', + :incoming_name_and_email => 'Someone <someone@example.org>') + end + + it 'should should generate a "fake response" email with a reasonable subject line' do + fake_email = RequestMailer.fake_response(@info_request, + @foi_officer, + "The body of the email...", + "blah.txt", + "The content of blah.txt") + fake_email.subject.should == "Re: Freedom of Information - Test request" + end + +end describe RequestMailer, 'when sending a new response email' do diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb index 64ad1972e..dcc94e967 100644 --- a/spec/models/info_request_spec.rb +++ b/spec/models/info_request_spec.rb @@ -27,7 +27,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe InfoRequest do - describe 'when validating', :focus => true do + describe 'when validating' do it 'should accept a summary with ascii characters' do info_request = InfoRequest.new(:title => 'abcde') @@ -1030,7 +1030,7 @@ describe InfoRequest do end end - context "another series of events on a request", :focus => true do + context "another series of events on a request" do it "should have sensible event states" do # An initial request is sent request.log_event('sent', {}) @@ -1122,5 +1122,59 @@ describe InfoRequest do end + describe InfoRequest, 'when getting similar requests' do + + before(:each) do + get_fixtures_xapian_index + end + + it 'should return similar requests' do + similar, more = info_requests(:spam_1_request).similar_requests(1) + similar.results.first[:model].info_request.should == info_requests(:spam_2_request) + end + + it 'should return a flag set to true' do + similar, more = info_requests(:spam_1_request).similar_requests(1) + more.should be_true + end + + end + + describe InfoRequest, 'when constructing the list of recent requests' do + before(:each) do + get_fixtures_xapian_index + end + + describe 'when there are fewer than five successful requests' do + + it 'should list the most recently sent and successful requests by the creation date of the + request event' do + # Make sure the newest response is listed first even if a request + # with an older response has a newer comment or was reclassified more recently: + # https://github.com/mysociety/alaveteli/issues/370 + # + # This is a deliberate behaviour change, in that the + # previous behaviour (showing more-recently-reclassified + # requests first) was intentional. + request_events, request_events_all_successful = InfoRequest.recent_requests + previous = nil + request_events.each do |event| + if previous + previous.created_at.should be >= event.created_at + end + ['sent', 'response'].include?(event.event_type).should be_true + if event.event_type == 'response' + ['successful', 'partially_successful'].include?(event.calculated_state).should be_true + end + previous = event + end + end + end + + it 'should coalesce duplicate requests' do + request_events, request_events_all_successful = InfoRequest.recent_requests + request_events.map(&:info_request).select{|x|x.url_title =~ /^spam/}.length.should == 1 + end + end end diff --git a/spec/models/outgoing_message_spec.rb b/spec/models/outgoing_message_spec.rb index 8c000665b..bb270ca16 100644 --- a/spec/models/outgoing_message_spec.rb +++ b/spec/models/outgoing_message_spec.rb @@ -12,6 +12,8 @@ # last_sent_at :datetime # incoming_message_followup_id :integer # what_doing :string(255) not null +# prominence :string(255) default("normal"), not null +# prominence_reason :text # require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') diff --git a/spec/models/public_body_spec.rb b/spec/models/public_body_spec.rb index 0324e3f5a..ed24ced52 100644 --- a/spec/models/public_body_spec.rb +++ b/spec/models/public_body_spec.rb @@ -3,23 +3,27 @@ # # Table name: public_bodies # -# id :integer not null, primary key -# name :text not null -# short_name :text not null -# request_email :text not null -# version :integer not null -# last_edit_editor :string(255) not null -# last_edit_comment :text not null -# created_at :datetime not null -# updated_at :datetime not null -# url_name :text not null -# home_page :text default(""), not null -# notes :text default(""), not null -# first_letter :string(255) not null -# publication_scheme :text default(""), not null -# api_key :string(255) not null -# info_requests_count :integer default(0), not null -# disclosure_log :text default(""), not null +# id :integer not null, primary key +# name :text not null +# short_name :text not null +# request_email :text not null +# version :integer not null +# last_edit_editor :string(255) not null +# last_edit_comment :text not null +# created_at :datetime not null +# updated_at :datetime not null +# url_name :text not null +# home_page :text default(""), not null +# notes :text default(""), not null +# first_letter :string(255) not null +# publication_scheme :text default(""), not null +# api_key :string(255) not null +# info_requests_count :integer default(0), not null +# disclosure_log :text default(""), not null +# info_requests_successful_count :integer +# info_requests_not_held_count :integer +# info_requests_overdue_count :integer +# info_requests_visible_classified_count :integer # require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') @@ -209,6 +213,15 @@ describe PublicBody, " when saving" do public_body.name.should == "Mark's Public Body" end + it 'should update the right translation when in a locale with an underscore' do + AlaveteliLocalization.set_locales('he_IL', 'he_IL') + public_body = public_bodies(:humpadink_public_body) + translation_count = public_body.translations.size + public_body.name = 'Renamed' + public_body.save! + public_body.translations.size.should == translation_count + end + it 'should not create a new version when nothing has changed' do @public_body.versions.size.should == 0 set_default_attributes(@public_body) @@ -320,14 +333,15 @@ describe PublicBody, " when loading CSV files" do csv_contents = normalize_string_to_utf8(load_file_fixture("fake-authority-type.csv")) errors, notes = PublicBody.import_csv(csv_contents, '', 'replace', true, 'someadmin') # true means dry run errors.should == [] - notes.size.should == 5 - notes[0..3].should == [ + notes.size.should == 6 + notes[0..4].should == [ "line 1: creating new authority 'North West Fake Authority' (locale: en):\n\t\{\"name\":\"North West Fake Authority\",\"request_email\":\"north_west_foi@localhost\"\}", "line 2: creating new authority 'Scottish Fake Authority' (locale: en):\n\t\{\"name\":\"Scottish Fake Authority\",\"request_email\":\"scottish_foi@localhost\"\}", "line 3: creating new authority 'Fake Authority of Northern Ireland' (locale: en):\n\t\{\"name\":\"Fake Authority of Northern Ireland\",\"request_email\":\"ni_foi@localhost\"\}", "line 4: creating new authority 'Gobierno de Aragón' (locale: en):\n\t\{\"name\":\"Gobierno de Arag\\u00f3n\",\"request_email\":\"spain_foi@localhost\"}", + "line 5: creating new authority 'Nordic æøå' (locale: en):\n\t{\"name\":\"Nordic \\u00e6\\u00f8\\u00e5\",\"request_email\":\"no_foi@localhost\"}" ] - notes[4].should =~ /Notes: Some bodies are in database, but not in CSV file:\n( .+\n)*You may want to delete them manually.\n/ + notes[5].should =~ /Notes: Some bodies are in database, but not in CSV file:\n( .+\n)*You may want to delete them manually.\n/ PublicBody.count.should == original_count end @@ -338,16 +352,17 @@ describe PublicBody, " when loading CSV files" do csv_contents = normalize_string_to_utf8(load_file_fixture("fake-authority-type.csv")) errors, notes = PublicBody.import_csv(csv_contents, '', 'replace', false, 'someadmin') # false means real run errors.should == [] - notes.size.should == 5 - notes[0..3].should == [ + notes.size.should == 6 + notes[0..4].should == [ "line 1: creating new authority 'North West Fake Authority' (locale: en):\n\t\{\"name\":\"North West Fake Authority\",\"request_email\":\"north_west_foi@localhost\"\}", "line 2: creating new authority 'Scottish Fake Authority' (locale: en):\n\t\{\"name\":\"Scottish Fake Authority\",\"request_email\":\"scottish_foi@localhost\"\}", "line 3: creating new authority 'Fake Authority of Northern Ireland' (locale: en):\n\t\{\"name\":\"Fake Authority of Northern Ireland\",\"request_email\":\"ni_foi@localhost\"\}", "line 4: creating new authority 'Gobierno de Aragón' (locale: en):\n\t\{\"name\":\"Gobierno de Arag\\u00f3n\",\"request_email\":\"spain_foi@localhost\"}", + "line 5: creating new authority 'Nordic æøå' (locale: en):\n\t{\"name\":\"Nordic \\u00e6\\u00f8\\u00e5\",\"request_email\":\"no_foi@localhost\"}" ] - notes[4].should =~ /Notes: Some bodies are in database, but not in CSV file:\n( .+\n)*You may want to delete them manually.\n/ + notes[5].should =~ /Notes: Some bodies are in database, but not in CSV file:\n( .+\n)*You may want to delete them manually.\n/ - PublicBody.count.should == original_count + 4 + PublicBody.count.should == original_count + 5 end it "should do imports without a tag successfully" do @@ -356,15 +371,16 @@ describe PublicBody, " when loading CSV files" do csv_contents = normalize_string_to_utf8(load_file_fixture("fake-authority-type.csv")) errors, notes = PublicBody.import_csv(csv_contents, '', 'replace', false, 'someadmin') # false means real run errors.should == [] - notes.size.should == 5 - notes[0..3].should == [ + notes.size.should == 6 + notes[0..4].should == [ "line 1: creating new authority 'North West Fake Authority' (locale: en):\n\t\{\"name\":\"North West Fake Authority\",\"request_email\":\"north_west_foi@localhost\"\}", "line 2: creating new authority 'Scottish Fake Authority' (locale: en):\n\t\{\"name\":\"Scottish Fake Authority\",\"request_email\":\"scottish_foi@localhost\"\}", "line 3: creating new authority 'Fake Authority of Northern Ireland' (locale: en):\n\t\{\"name\":\"Fake Authority of Northern Ireland\",\"request_email\":\"ni_foi@localhost\"\}", "line 4: creating new authority 'Gobierno de Aragón' (locale: en):\n\t\{\"name\":\"Gobierno de Arag\\u00f3n\",\"request_email\":\"spain_foi@localhost\"}", + "line 5: creating new authority 'Nordic æøå' (locale: en):\n\t{\"name\":\"Nordic \\u00e6\\u00f8\\u00e5\",\"request_email\":\"no_foi@localhost\"}" ] - notes[4].should =~ /Notes: Some bodies are in database, but not in CSV file:\n( .+\n)*You may want to delete them manually.\n/ - PublicBody.count.should == original_count + 4 + notes[5].should =~ /Notes: Some bodies are in database, but not in CSV file:\n( .+\n)*You may want to delete them manually.\n/ + PublicBody.count.should == original_count + 5 end it "should handle a field list and fields out of order" do @@ -466,6 +482,20 @@ describe PublicBody, " when loading CSV files" do PublicBody.count.should == original_count end + + it "should be able to load CSV from a file as well as a string" do + # Essentially the same code is used for import_csv_from_file + # as import_csv, so this is just a basic check that + # import_csv_from_file can load from a file at all. (It would + # be easy to introduce a regression that broke this, because + # of the confusing change in behaviour of CSV.parse between + # Ruby 1.8 and 1.9.) + original_count = PublicBody.count + filename = file_fixture_name('fake-authority-type-with-field-names.csv') + PublicBody.import_csv_from_file(filename, '', 'replace', false, 'someadmin') + PublicBody.count.should == original_count + 3 + end + end describe PublicBody do @@ -523,3 +553,86 @@ describe PublicBody, " when override all public body request emails set" do @geraldine.request_email.should == "catch_all_test_email@foo.com" end end + +describe PublicBody, "when calculating statistics" do + + it "should not include unclassified or hidden requests in percentages" do + with_hidden_and_successful_requests do + totals_data = PublicBody.get_request_totals(n=3, + highest=true, + minimum_requests=1) + # For the total number of requests, we still include + # hidden or unclassified requests: + totals_data['public_bodies'][-1].name.should == "Geraldine Quango" + totals_data['totals'][-1].should == 4 + + # However, for percentages, don't include the hidden or + # unclassified requests. So, for the Geraldine Quango + # we've made sure that there are only two visible and + # classified requests, one of which is successful, so the + # percentage should be 50%: + + percentages_data = PublicBody.get_request_percentages(column='info_requests_successful_count', + n=3, + highest=false, + minimum_requests=1) + geraldine_index = percentages_data['public_bodies'].index do |pb| + pb.name == "Geraldine Quango" + end + + percentages_data['y_values'][geraldine_index].should == 50 + end + end + + it "should only return totals for those with at least a minimum number of requests" do + minimum_requests = 1 + with_enough_info_requests = PublicBody.where(["info_requests_count >= ?", + minimum_requests]).length + all_data = PublicBody.get_request_totals 4, true, minimum_requests + all_data['public_bodies'].length.should == with_enough_info_requests + end + + it "should only return percentages for those with at least a minimum number of requests" do + with_hidden_and_successful_requests do + # With minimum requests at 3, this should return nil + # (corresponding to zero public bodies) since the only + # public body with just more than 3 info requests (The + # Geraldine Quango) has a hidden and an unclassified + # request within this block: + minimum_requests = 3 + with_enough_info_requests = PublicBody.where(["info_requests_visible_classified_count >= ?", + minimum_requests]).length + all_data = PublicBody.get_request_percentages(column='info_requests_successful_count', + n=10, + true, + minimum_requests) + all_data.should be_nil + end + end + + it "should only return those with at least a minimum number of requests, but not tagged 'test'" do + hpb = PublicBody.find_by_name 'Department for Humpadinking' + + original_tag_string = hpb.tag_string + hpb.add_tag_if_not_already_present 'test' + + begin + minimum_requests = 1 + with_enough_info_requests = PublicBody.where(["info_requests_count >= ?", minimum_requests]) + all_data = PublicBody.get_request_totals 4, true, minimum_requests + all_data['public_bodies'].length.should == 3 + ensure + hpb.tag_string = original_tag_string + end + end + +end + +describe PublicBody, 'when asked for popular bodies' do + + it 'should return bodies correctly when passed the hyphenated version of the locale' do + AlaveteliConfiguration.stub!(:frontpage_publicbody_examples).and_return('') + PublicBody.popular_bodies('he-IL').should == [public_bodies(:humpadink_public_body)] + end + +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index f380f6f13..cbbf4b5ce 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -20,8 +20,6 @@ # email_bounce_message :text default(""), not null # no_limit :boolean default(FALSE), not null # receive_email_alerts :boolean default(TRUE), not null -# address :string(255) -# dob :date # require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') diff --git a/spec/models/xapian_spec.rb b/spec/models/xapian_spec.rb index 3c9fff784..a1e060d8e 100644 --- a/spec/models/xapian_spec.rb +++ b/spec/models/xapian_spec.rb @@ -370,7 +370,7 @@ describe PublicBody, " when only indexing selected things on a rebuild" do end end -# I would expect ActsAsXapian to have some tests under vendor/plugins/acts_as_xapian, but +# I would expect ActsAsXapian to have some tests under lib/acts_as_xapian, but # it looks like this is not the case. Putting a test here instead. describe ActsAsXapian::Search, "#words_to_highlight" do before(:each) do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6e65018f1..1eeb8603b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -13,6 +13,10 @@ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ SimpleCov.start('rails') do add_filter 'commonlib' add_filter 'vendor/plugins' + add_filter 'lib/strip_attributes' + add_filter 'lib/has_tag_string' + add_filter 'lib/acts_as_xapian' + add_filter 'lib/themes' end Spork.prefork do @@ -158,6 +162,39 @@ Spork.prefork do ActiveRecord::Base.default_timezone = old_zone end + # To test the statistics calculations, it's helpful to have the + # request fixtures in different states, but changing the fixtures + # themselves disrupts many other tests. This function takes a + # block, and runs that block with the info requests for the + # Geraldine Quango altered so that one is hidden and there's a + # successful one. + def with_hidden_and_successful_requests + external = info_requests(:external_request) + chicken = info_requests(:naughty_chicken_request) + old_external_prominence = external.prominence + old_chicken_described_state = chicken.described_state + begin + external.prominence = 'hidden' + external.save! + chicken.described_state = 'successful' + chicken.save! + yield + ensure + external.prominence = old_external_prominence + external.save! + chicken.described_state = old_chicken_described_state + chicken.save! + end + end + + def with_default_locale(locale) + original_default_locale = I18n.default_locale + I18n.default_locale = locale + yield + ensure + I18n.default_locale = original_default_locale + end + def load_test_categories PublicBodyCategories.add(:en, [ "Local and regional", |