diff options
28 files changed, 428 insertions, 307 deletions
diff --git a/.travis.yml b/.travis.yml index 4fd2a59f7..4f19c9588 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: ruby branches: only: - - develop - master - rails-3-develop rvm: @@ -24,6 +24,21 @@ There's background information and a more documentation on of useful information (including a blog) on [the project website](http://alaveteli.org) +## How to contribute + +If you find what looks like a bug: + +* Check the [GitHub issue tracker](http://github.com/mysociety/alaveteli/issues/) + to see if anyone else has reported issue. +* If you don't see anything, create an issue with information on how to reproduce it. + +If you want to contribute an enhancement or a fix: + +* Fork the project on GitHub. +* Make your changes with tests. +* Commit the changes without making changes to any files that aren't related to your enhancement or fix. +* Send a pull request. + Looking for the latest stable release? It's on the [master branch](https://github.com/mysociety/alaveteli/tree/master). diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d1d702616..dffc16b63 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -361,12 +361,15 @@ class ApplicationController < ActionController::Base # Peform the search @per_page = per_page - if this_page.nil? - @page = get_search_page_from_params - else - @page = this_page - end - result = InfoRequest.full_search(models, @query, order, ascending, collapse, @per_page, @page) + @page = this_page || get_search_page_from_params + + result = ActsAsXapian::Search.new(models, @query, + :offset => (@page - 1) * @per_page, + :limit => @per_page, + :sort_by_prefix => order, + :sort_by_ascending => ascending, + :collapse_by_prefix => collapse + ) result.results # Touch the results to load them, otherwise accessing them from the view # might fail later if the database has subsequently been reopened. return result diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb index 9d0f91dda..52b4b3e0e 100644 --- a/app/controllers/general_controller.rb +++ b/app/controllers/general_controller.rb @@ -153,7 +153,7 @@ class GeneralController < ApplicationController # structured query which should show newest first, rather than a free text search # where we want most relevant as default. begin - dummy_query = ::ActsAsXapian::Search.new([InfoRequestEvent], @query, :limit => 1) + dummy_query = ActsAsXapian::Search.new([InfoRequestEvent], @query, :limit => 1) rescue => e flash[:error] = "Your query was not quite right. " + CGI.escapeHTML(e.to_str) redirect_to search_url("") @@ -169,10 +169,8 @@ class GeneralController < ApplicationController # Query each type separately for separate display (XXX we are calling # perform_search multiple times and it clobbers per_page for each one, # so set as separate var) - requests_per_page = 25 - if params[:requests_per_page] - requests_per_page = params[:requests_per_page].to_i - end + requests_per_page = params[:requests_per_page] ? params[:requests_per_page].to_i : 25 + @this_page_hits = @total_hits = @xapian_requests_hits = @xapian_bodies_hits = @xapian_users_hits = 0 if @requests @xapian_requests = perform_search([InfoRequestEvent], @query, @sortby, 'request_collapse', requests_per_page) @@ -211,12 +209,6 @@ class GeneralController < ApplicationController @feed_autodetect = [ { :url => do_track_url(@track_thing, 'feed'), :title => @track_thing.params[:title_in_rss], :has_json => true } ] end - # Jump to a random request - def random_request - info_request = InfoRequest.random - redirect_to request_url(info_request) - end - def custom_css long_cache @locale = self.locale_from_params() diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb new file mode 100644 index 000000000..a1dd53125 --- /dev/null +++ b/app/controllers/reports_controller.rb @@ -0,0 +1,31 @@ +class ReportsController < ApplicationController + def create + @info_request = InfoRequest.find_by_url_title!(params[:request_id]) + @reason = params[:reason] + @message = params[:message] + if @reason.empty? + flash[:error] = _("Please choose a reason") + render "new" + return + end + + if !authenticated_user + flash[:notice] = _("You need to be logged in to report a request for administrator attention") + elsif @info_request.attention_requested + flash[:notice] = _("This request has already been reported for administrator attention") + else + @info_request.report!(@reason, @message, @user) + flash[:notice] = _("This request has been reported for administrator attention") + end + redirect_to request_url(@info_request) + end + + def new + @info_request = InfoRequest.find_by_url_title!(params[:request_id]) + if authenticated?( + :web => _("To report this request"), + :email => _("Then you can report the request '{{title}}'", :title => @info_request.title), + :email_subject => _("Report an offensive or unsuitable request")) + end + end +end diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index a455d1725..880a7b4b4 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -100,7 +100,7 @@ class RequestController < ApplicationController # ... requests that have similar imporant terms begin limit = 10 - @xapian_similar = ::ActsAsXapian::Similar.new([InfoRequestEvent], @info_request.info_request_events, + @xapian_similar = ActsAsXapian::Similar.new([InfoRequestEvent], @info_request.info_request_events, :limit => limit, :collapse_by_prefix => 'request_collapse') @xapian_similar_more = (@xapian_similar.matches_estimated > limit) rescue @@ -146,7 +146,7 @@ class RequestController < ApplicationController if !@info_request.user_can_view?(authenticated_user) return render_hidden end - @xapian_object = ::ActsAsXapian::Similar.new([InfoRequestEvent], @info_request.info_request_events, + @xapian_object = ActsAsXapian::Similar.new([InfoRequestEvent], @info_request.info_request_events, :offset => (@page - 1) * @per_page, :limit => @per_page, :collapse_by_prefix => 'request_collapse') @matches_estimated = @xapian_object.matches_estimated @show_no_more_than = (@matches_estimated > MAX_RESULTS) ? MAX_RESULTS : @matches_estimated @@ -676,25 +676,6 @@ class RequestController < ApplicationController end end - def report_request - info_request = InfoRequest.find_by_url_title!(params[:url_title]) - return if !authenticated?( - :web => _("To report this FOI request"), - :email => _("Then you can report the request '{{title}}'", :title => info_request.title), - :email_subject => _("Report an offensive or unsuitable request") - ) - - if !info_request.attention_requested - info_request.set_described_state('attention_requested', @user) - info_request.attention_requested = true # tells us if attention has ever been requested - info_request.save! - flash[:notice] = _("This request has been reported for administrator attention") - else - flash[:notice] = _("This request has already been reported for administrator attention") - end - redirect_to request_url(info_request) - end - # special caching code so mime types are handled right around_filter :cache_attachments, :only => [ :get_attachment, :get_attachment_as_html ] def cache_attachments diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index b7912b528..1ccab3003 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -119,7 +119,11 @@ class UserController < ApplicationController @track_things = TrackThing.find(:all, :conditions => ["tracking_user_id = ? and track_medium = ?", @display_user.id, 'email_daily'], :order => 'created_at desc') for track_thing in @track_things # XXX factor out of track_mailer.rb - xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 20, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], track_thing.track_query, + :sort_by_prefix => 'described_at', + :sort_by_ascending => true, + :collapse_by_prefix => nil, + :limit => 20) feed_results += xapian_object.results.map {|x| x[:model]} end end diff --git a/app/mailers/track_mailer.rb b/app/mailers/track_mailer.rb index 391143214..1bd8a7e23 100644 --- a/app/mailers/track_mailer.rb +++ b/app/mailers/track_mailer.rb @@ -67,7 +67,11 @@ class TrackMailer < ApplicationMailer # Query for things in this track. We use described_at for the # ordering, so we catch anything new (before described), or # anything whose new status has been described. - xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], track_thing.track_query, + :sort_by_prefix => 'described_at', + :sort_by_ascending => true, + :collapse_by_prefix => nil, + :limit => 100) # Go through looking for unalerted things alert_results = [] for result in xapian_object.results diff --git a/app/models/info_request.rb b/app/models/info_request.rb index cf1af0e87..aaf171c4c 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -108,6 +108,12 @@ class InfoRequest < ActiveRecord::Base states end + # Possible reasons that a request could be reported for administrator attention + def report_reasons + ["Contains defamatory material", "Not a valid request", "Request for personal information", + "Contains personal information", "Vexatious", "Other"] + end + def must_be_valid_state errors.add(:described_state, "is not a valid state") if !InfoRequest.enumerate_states.include? described_state @@ -189,21 +195,6 @@ class InfoRequest < ActiveRecord::Base self.comments.find(:all, :conditions => 'visible') end - # Central function to do all searches - # (Not really the right place to put it, but everything can get it here, and it - # does *mainly* find info requests, via their events, so hey) - def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) - offset = (page - 1) * per_page - - return ::ActsAsXapian::Search.new( - models, query, - :offset => offset, :limit => per_page, - :sort_by_prefix => order, - :sort_by_ascending => ascending, - :collapse_by_prefix => collapse - ) - end - # If the URL name has changed, then all request: queries will break unless # we update index for every event. Also reindex if prominence changes. after_update :reindex_some_request_events @@ -232,17 +223,6 @@ class InfoRequest < ActiveRecord::Base end end - # For debugging - def InfoRequest.profile_search(query) - t = Time.now.usec - for i in (1..10) - t = Time.now.usec - t - secs = t / 1000000.0 - STDOUT.write secs.to_s + " query " + i.to_s + "\n" - results = InfoRequest.full_search([InfoRequestEvent], query, "created_at", true, nil, 25, 1).results - end - end - public # When name is changed, also change the url name def title=(title) @@ -351,7 +331,10 @@ public # copying an email, and that doesn't matter) def InfoRequest.find_by_incoming_email(incoming_email) id, hash = InfoRequest._extract_id_hash_from_email(incoming_email) - return self.find_by_magic_email(id, hash) + if hash_from_id(id) == hash + # Not using find(id) because we don't exception raised if nothing found + find_by_id(id) + end end # Return list of info requests which *might* be right given email address @@ -566,6 +549,15 @@ public ['requires_admin', 'error_message', 'attention_requested'].include?(described_state) end + # Report this request for administrator attention + def report!(reason, message, user) + ActiveRecord::Base.transaction do + set_described_state('attention_requested', user, "Reason: #{reason}\n\n#{message}") + self.attention_requested = true # tells us if attention has ever been requested + save! + end + end + # change status, including for last event for later historical purposes def set_described_state(new_state, set_by = nil, message = "") old_described_state = described_state @@ -913,24 +905,6 @@ public return Digest::SHA1.hexdigest(id.to_s + AlaveteliConfiguration::incoming_email_secret)[0,8] end - # Called by find_by_incoming_email - and used to be called by separate - # function for envelope from address, until we abandoned it. - def InfoRequest.find_by_magic_email(id, hash) - expected_hash = InfoRequest.hash_from_id(id) - #print "expected: " + expected_hash + "\nhash: " + hash + "\n" - if hash != expected_hash - return nil - else - begin - return self.find(id) - rescue ActiveRecord::RecordNotFound - # so error email is sent to admin, rather than the exception sending weird - # error to the public body. - return nil - end - end - end - # Used to find when event last changed def InfoRequest.last_event_time_clause(event_type=nil) event_type_clause = '' @@ -1081,25 +1055,6 @@ public InfoRequest.update_all "allow_new_responses_from = 'nobody' where updated_at < (now() - interval '1 year') and allow_new_responses_from in ('anybody', 'authority_only') and url_title <> 'holding_pen'" end - # Returns a random FOI request - def InfoRequest.random - max_id = InfoRequest.connection.select_value('select max(id) as a from info_requests').to_i - info_request = nil - count = 0 - while info_request.nil? - if count > 100 - return nil - end - id = rand(max_id) + 1 - begin - count += 1 - info_request = find(id, :conditions => ["prominence = 'normal'"]) - rescue ActiveRecord::RecordNotFound - end - end - return info_request - end - def json_for_api(deep) ret = { :id => self.id, diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb index dbe2cf1ca..aedfb9cad 100644 --- a/app/models/outgoing_message.rb +++ b/app/models/outgoing_message.rb @@ -23,6 +23,14 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class OutgoingMessage < ActiveRecord::Base + include Rails.application.routes.url_helpers + include LinkToHelper + self.default_url_options[:host] = AlaveteliConfiguration::domain + # https links in emails if forcing SSL + if AlaveteliConfiguration::force_ssl + self.default_url_options[:protocol] = "https" + end + strip_attributes! belongs_to :info_request @@ -80,15 +88,15 @@ class OutgoingMessage < ActiveRecord::Base end if self.what_doing == 'internal_review' - "Please pass this on to the person who conducts Freedom of Information reviews." + + _("Please pass this on to the person who conducts Freedom of Information reviews.") + "\n\n" + - "I am writing to request an internal review of " + - self.info_request.public_body.name + - "'s handling of my FOI request " + - "'" + self.info_request.title + "'." + + _("I am writing to request an internal review of {{public_body_name}}'s handling of my FOI request '{{info_request_title}}'.", + :public_body_name => self.info_request.public_body.name, + :info_request_title => self.info_request.title) + "\n\n\n\n [ " + self.get_internal_review_insert_here_note + " ] \n\n\n\n" + - "A full history of my FOI request and all correspondence is available on the Internet at this address:\n" + - "http://" + AlaveteliConfiguration::domain + "/request/" + self.info_request.url_title + _("A full history of my FOI request and all correspondence is available on the Internet at this address: {{url}}", + :url => request_url(self.info_request)) + + "\n" else "" end diff --git a/app/views/public_body/_search_ahead.html.erb b/app/views/public_body/_search_ahead.html.erb index b1af2464d..3d1dc8f93 100644 --- a/app/views/public_body/_search_ahead.html.erb +++ b/app/views/public_body/_search_ahead.html.erb @@ -1,4 +1,4 @@ -<div> + <% if !@xapian_requests.nil? %> <% if @xapian_requests.results.size > 0 %> <h3><%= _('Top search results:') %></h3> @@ -10,12 +10,11 @@ <% end %> <div id="authority_search_ahead_results"> <% for result in @xapian_requests.results %> - <%= render :partial => 'body_listing_single', :locals => { :public_body => result[:model] } %> + <%= render :partial => 'public_body/body_listing_single', :locals => { :public_body => result[:model] } %> <% end %> </div> <%= will_paginate WillPaginate::Collection.new(@page, @per_page, @xapian_requests.matches_estimated), :params => {:controller=>"request", :action => "select_authority"} %> <% end %> -</div> diff --git a/app/views/public_body/show.html.erb b/app/views/public_body/show.html.erb index fa6243b47..47075a1f5 100644 --- a/app/views/public_body/show.html.erb +++ b/app/views/public_body/show.html.erb @@ -56,12 +56,7 @@ <div id="stepwise_make_request"> <% if @public_body.is_requestable? || @public_body.not_requestable_reason == 'bad_contact' %> - <% if @public_body.eir_only? %> - <%= _('Make a new <strong>Environmental Information</strong> request')%> - <% else %> - <%= _('Make a new <strong>Freedom of Information</strong> request to {{public_body}}', :public_body => h(@public_body.name))%> - <% end %> - <%= link_to _("Start"), new_request_to_body_url(:url_name => @public_body.url_name), :class => "link_button_green" %> + <%= link_to _("Make a request to this authority"), new_request_to_body_path(:url_name => @public_body.url_name), :class => "link_button_green" %> <% elsif @public_body.has_notes? %> <%= @public_body.notes_as_html.html_safe %> <% elsif @public_body.not_requestable_reason == 'not_apply' %> diff --git a/app/views/reports/new.html.erb b/app/views/reports/new.html.erb new file mode 100644 index 000000000..7d558ab4e --- /dev/null +++ b/app/views/reports/new.html.erb @@ -0,0 +1,26 @@ +<h1>Report request: <%= @info_request.title %></h1> + +<% if @info_request.attention_requested %> + <p><%= _("This request has already been reported for administrator attention") %></p> +<% else %> + <p> + Reporting a request notifies the site administrators. They will respond as soon as possible. + </p> + <p>Why specifically do you consider this request unsuitable?</p> + + <%= form_tag request_report_path(:request_id => @info_request.url_title) do %> + <p> + <label class="form_label" for="reason">Reason:</label> + <%= select_tag :reason, options_for_select(@info_request.report_reasons, @reason), :prompt => "Choose a reason" %> + </p> + <p> + <label class="form_label" for="message">Please tell us more:</label> + <%= text_area_tag :message, @message, :rows => 10, :cols => 60 %> + </p> + + <div class="form_button"> + <%= submit_tag _("Report request") %> + </div> + + <% end %> +<% end %> diff --git a/app/views/request/_sidebar.html.erb b/app/views/request/_sidebar.html.erb index 4bc8826fd..aba5c2fb3 100644 --- a/app/views/request/_sidebar.html.erb +++ b/app/views/request/_sidebar.html.erb @@ -30,7 +30,7 @@ <% else %> <p><%= _('Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href="/help/about">read more</a>).') %></p> <p><%= _('If you believe this request is not suitable, you can report it for attention by the site administrators') %></p> - <%= button_to _("Report this request"), report_path(:url_title => @info_request.url_title), :class => "link_button_green" %> + <%= link_to _("Report this request"), new_request_report_path(:request_id => @info_request.url_title) %> <% end %> <% end %> <h2><%= _("Act on what you've learnt") %></h2> diff --git a/app/views/request/new_please_describe.html.erb b/app/views/request/new_please_describe.html.erb index 5a67d01f9..8da4eb555 100644 --- a/app/views/request/new_please_describe.html.erb +++ b/app/views/request/new_please_describe.html.erb @@ -1,4 +1,4 @@ -<% @title = "First, did your other requests succeed?" %> +<% @title = _("First, did your other requests succeed?") %> <h1><%=@title%></h1> diff --git a/app/views/request/select_authority.html.erb b/app/views/request/select_authority.html.erb index c01e2776f..75c51fc57 100644 --- a/app/views/request/select_authority.html.erb +++ b/app/views/request/select_authority.html.erb @@ -42,26 +42,9 @@ <%= submit_tag _('Search') %> </div> <% end %> - <div id="typeahead_response"> - <% if !@xapian_requests.nil? %> - <% if @xapian_requests.results.size > 0 %> - <h3><%= _('Top search results:') %></h3> - <p> - <%= _('Select one to see more information about the authority.')%> - </p> - <% else %> - <h3><%= _('No results found.') %></h3> - <% end %> - <div id="authority_search_ahead_results"> - <% for result in @xapian_requests.results %> - <%= render :partial => 'public_body/body_listing_single', :locals => { :public_body => result[:model] } %> - <% end %> - </div> - - <% end %> - - + <div id="typeahead_response"> + <%= render :partial => 'public_body/search_ahead' %> </div> </div> diff --git a/config/packages b/config/packages index fc67cda6b..f4d0a674c 100644 --- a/config/packages +++ b/config/packages @@ -20,7 +20,6 @@ gnuplot-nox php5-cli sharutils unzip -wdg-html-validator mutt tnef (>= 1.4.5) gettext diff --git a/config/packages_development b/config/packages_development new file mode 100644 index 000000000..14ca815a2 --- /dev/null +++ b/config/packages_development @@ -0,0 +1,9 @@ +# This is a list of packages needed on a fresh Ubuntu installation for +# development. +# +# It assumes you're using RVM or a similar Ruby manager and have already +# run `bundle install`. +# +# To install, paste this list after `sudo apt-get install` and run. + +postgresql sharutils pdftk elinks php5-cli tnef python-yaml diff --git a/config/routes.rb b/config/routes.rb index 1895543d7..56be975c3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,8 +24,6 @@ Alaveteli::Application.routes.draw do match '/search/*combined/all' => 'general#search', :as => :search_general, :view => 'all' match '/search(/*combined)' => 'general#search', :as => :search_general match '/advancedsearch' => 'general#search_redirect', :as => :advanced_search, :advanced => true - - match '/random' => 'general#random_request', :as => :random_request ##### ##### Request controller @@ -59,15 +57,12 @@ Alaveteli::Application.routes.draw do match '/upload/request/:url_title' => 'request#upload_response', :as => :upload_response match '/request/:url_title/download' => 'request#download_entire_request', :as => :download_entire_request - - # It would be nice to add :conditions => { :method => :post } to this next one, - # because it ought not really to be available as a GET request since it changes - # the server state. Unfortunately this doesn’t play well with the PostRedirect - # mechanism, which assumes all post-login actions are available via GET, so we - # refrain. - match '/request/:url_title/report' => 'request#report_request', :as => :report #### + resources :request, :only => [] do + resource :report, :only => [:new, :create] + end + #### User controller # Use /profile for things to do with the currently signed in user. # Use /user/XXXX for things that anyone can see about that user. diff --git a/lib/tasks/translation.rake b/lib/tasks/translation.rake index 351faef2c..6458d9268 100644 --- a/lib/tasks/translation.rake +++ b/lib/tasks/translation.rake @@ -142,13 +142,11 @@ namespace :translation do output_file) # track mailer - xapian_object = InfoRequest.full_search([InfoRequestEvent], - track_thing.track_query, - 'described_at', - true, - nil, - 100, - 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], track_thing.track_query, + :sort_by_prefix => 'described_at', + :sort_by_ascending => true, + :collapse_by_prefix => nil, + :limit => 100) event_digest_email = TrackMailer.event_digest(info_request.user, [[track_thing, xapian_object.results, diff --git a/public/stylesheets/main.css b/public/stylesheets/main.css index 2823f3978..6f6d7b365 100644 --- a/public/stylesheets/main.css +++ b/public/stylesheets/main.css @@ -183,16 +183,11 @@ margin:18px 0 36px; } #stepwise_make_request { -background-color:#BBB; -border:1px solid #222; -border-radius:5px; --moz-border-radius:5px; color:#222; font-size:1.1em; text-align:left; width:412px; margin:0 14em 40px 0; -padding:10px 12px; } #stepwise_make_request_view_email { diff --git a/spec/controllers/reports_controller_spec.rb b/spec/controllers/reports_controller_spec.rb new file mode 100644 index 000000000..fa8c72eaa --- /dev/null +++ b/spec/controllers/reports_controller_spec.rb @@ -0,0 +1,104 @@ +require 'spec_helper' + +describe ReportsController, "when reporting a request when not logged in" do + it "should only allow logged-in users to report requests" do + post :create, :request_id => info_requests(:badger_request).url_title, :reason => "my reason" + + flash[:notice].should =~ /You need to be logged in/ + response.should redirect_to show_request_path(:url_title => info_requests(:badger_request).url_title) + end +end + +describe ReportsController, "when reporting a request (logged in)" do + render_views + + before do + @user = users(:robin_user) + session[:user_id] = @user.id + end + + it "should 404 for non-existent requests" do + lambda { + post :create, :request_id => "hjksfdhjk_louytu_qqxxx" + }.should raise_error(ActiveRecord::RecordNotFound) + end + + it "should mark a request as having been reported" do + ir = info_requests(:badger_request) + title = ir.url_title + ir.attention_requested.should == false + + post :create, :request_id => title, :reason => "my reason" + response.should redirect_to show_request_path(:url_title => title) + + ir.reload + ir.attention_requested.should == true + ir.described_state.should == "attention_requested" + end + + it "should pass on the reason and message" do + info_request = mock_model(InfoRequest, :url_title => "foo", :attention_requested= => nil, :save! => nil) + InfoRequest.should_receive(:find_by_url_title!).with("foo").and_return(info_request) + info_request.should_receive(:report!).with("Not valid request", "It's just not", @user) + post :create, :request_id => "foo", :reason => "Not valid request", :message => "It's just not" + end + + it "should not allow a request to be reported twice" do + title = info_requests(:badger_request).url_title + + post :create, :request_id => title, :reason => "my reason" + response.should redirect_to show_request_url(:url_title => title) + + post :create, :request_id => title, :reason => "my reason" + response.should redirect_to show_request_url(:url_title => title) + flash[:notice].should =~ /has already been reported/ + end + + it "should send an email from the reporter to admins" do + ir = info_requests(:badger_request) + title = ir.url_title + post :create, :request_id => title, :reason => "my reason" + deliveries = ActionMailer::Base.deliveries + deliveries.size.should == 1 + mail = deliveries[0] + mail.subject.should =~ /attention_requested/ + mail.from.should include(@user.email) + mail.body.should include(@user.name) + end + + it "should force the user to pick a reason" do + info_request = mock_model(InfoRequest, :report! => nil, :url_title => "foo", + :report_reasons => ["Not FOIish enough"]) + InfoRequest.should_receive(:find_by_url_title!).with("foo").and_return(info_request) + + post :create, :request_id => "foo", :reason => "" + response.should render_template("new") + flash[:error].should == "Please choose a reason" + end +end + +describe ReportsController, "#new_report_request" do + let(:info_request) { mock_model(InfoRequest, :url_title => "foo") } + before :each do + InfoRequest.should_receive(:find_by_url_title!).with("foo").and_return(info_request) + end + + context "not logged in" do + it "should require the user to be logged in" do + get :new, :request_id => "foo" + response.should_not render_template("new") + end + end + + context "logged in" do + before :each do + session[:user_id] = users(:bob_smith_user).id + end + it "should show the form" do + get :new, :request_id => "foo" + response.should render_template("new") + end + end +end + + diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 83e2b1767..dedffde4f 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -93,8 +93,10 @@ describe RequestController, "when listing recent requests" do :results => (1..25).to_a.map { |m| { :model => m } }, :matches_estimated => 1000000) - InfoRequest.should_receive(:full_search). - with([InfoRequestEvent]," (variety:sent OR variety:followup_sent OR variety:response OR variety:comment)", "created_at", anything, anything, anything, anything). + ActsAsXapian::Search.should_receive(:new). + with([InfoRequestEvent]," (variety:sent OR variety:followup_sent OR variety:response OR variety:comment)", + :sort_by_prefix => "created_at", :offset => 0, :limit => 25, :sort_by_ascending => true, + :collapse_by_prefix => "request_collapse"). and_return(xap_results) get :list, :view => 'all' assigns[:list_results].size.should == 25 @@ -239,6 +241,36 @@ describe RequestController, "when showing one request" do end end + context "when the request has not yet been reported" do + it "should allow the user to report" do + title = info_requests(:badger_request).url_title + get :show, :url_title => title + response.should_not contain("This request has been reported") + response.should contain("Offensive?") + end + end + + context "when the request has been reported for admin attention" do + before :each do + info_requests(:fancy_dog_request).report!("", "", nil) + end + it "should inform the user" do + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' + response.should contain("This request has been reported") + response.should_not contain("Offensive?") + end + + context "and then deemed okay and left to complete" do + before :each do + info_requests(:fancy_dog_request).set_described_state("successful") + end + it "should let the user know that the administrators have not hidden this request" do + get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' + response.body.should =~ (/the site administrators.*have not hidden it/) + end + end + end + describe 'when the request is being viewed by an admin' do describe 'if the request is awaiting description' do @@ -2342,91 +2374,6 @@ describe RequestController, "when showing similar requests" do end - -describe RequestController, "when reporting a request when not logged in" do - it "should only allow logged-in users to report requests" do - get :report_request, :url_title => info_requests(:badger_request).url_title - post_redirect = PostRedirect.get_last_post_redirect - response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) - end -end - -describe RequestController, "when reporting a request (logged in)" do - render_views - - before do - @user = users(:robin_user) - session[:user_id] = @user.id - end - - it "should 404 for non-existent requests" do - lambda { - post :report_request, :url_title => "hjksfdhjk_louytu_qqxxx" - }.should raise_error(ActiveRecord::RecordNotFound) - end - - it "should mark a request as having been reported" do - ir = info_requests(:badger_request) - title = ir.url_title - get :show, :url_title => title - assigns[:info_request].attention_requested.should == false - - post :report_request, :url_title => title - response.should redirect_to(:action => :show, :url_title => title) - - get :show, :url_title => title - response.should be_success - assigns[:info_request].attention_requested.should == true - assigns[:info_request].described_state.should == "attention_requested" - end - - it "should not allow a request to be reported twice" do - title = info_requests(:badger_request).url_title - - post :report_request, :url_title => title - response.should redirect_to(:action => :show, :url_title => title) - get :show, :url_title => title - response.should be_success - response.body.should include("has been reported") - - post :report_request, :url_title => title - response.should redirect_to(:action => :show, :url_title => title) - get :show, :url_title => title - response.should be_success - response.body.should include("has already been reported") - end - - it "should let users know a request has been reported" do - title = info_requests(:badger_request).url_title - get :show, :url_title => title - response.body.should include("Offensive?") - - post :report_request, :url_title => title - response.should redirect_to(:action => :show, :url_title => title) - - get :show, :url_title => title - response.body.should_not include("Offensive?") - response.body.should include("This request has been reported") - - info_requests(:badger_request).set_described_state("successful") - get :show, :url_title => title - response.body.should_not include("This request has been reported") - response.body.should =~ (/the site administrators.*have not hidden it/) - end - - it "should send an email from the reporter to admins" do - ir = info_requests(:badger_request) - title = ir.url_title - post :report_request, :url_title => title - deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - mail = deliveries[0] - mail.subject.should =~ /attention_requested/ - mail.from.should include(@user.email) - mail.body.should include(@user.name) - end -end - describe RequestController, "when caching fragments" do it "should not fail with long filenames" do long_name = "blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah.txt" @@ -2454,4 +2401,3 @@ describe RequestController, "when caching fragments" do end - diff --git a/spec/mailers/track_mailer_spec.rb b/spec/mailers/track_mailer_spec.rb index a3b849980..509d08331 100644 --- a/spec/mailers/track_mailer_spec.rb +++ b/spec/mailers/track_mailer_spec.rb @@ -69,11 +69,15 @@ describe TrackMailer do @xapian_search = mock('xapian search', :results => []) @found_event = mock_model(InfoRequestEvent, :described_at => @track_thing.created_at + 1.day) @search_result = {:model => @found_event} - InfoRequest.stub!(:full_search).and_return(@xapian_search) + ActsAsXapian::Search.stub!(:new).and_return(@xapian_search) end it 'should ask for the events returned by the tracking query' do - InfoRequest.should_receive(:full_search).with([InfoRequestEvent], 'test query', 'described_at', true, nil, 100, 1).and_return(@xapian_search) + ActsAsXapian::Search.should_receive(:new).with([InfoRequestEvent], 'test query', + :sort_by_prefix => 'described_at', + :sort_by_ascending => true, + :collapse_by_prefix => nil, + :limit => 100).and_return(@xapian_search) TrackMailer.alert_tracks end diff --git a/spec/models/outgoing_message_spec.rb b/spec/models/outgoing_message_spec.rb index 51bb6fdf5..60164fb31 100644 --- a/spec/models/outgoing_message_spec.rb +++ b/spec/models/outgoing_message_spec.rb @@ -16,7 +16,7 @@ describe OutgoingMessage, " when making an outgoing message" do it "should not index the email addresses" do # also used for track emails @outgoing_message.get_text_for_indexing.should_not include("foo@bar.com") - end + end it "should not display email addresses on page" do @outgoing_message.get_body_for_html_display.should_not include("foo@bar.com") @@ -33,6 +33,23 @@ describe OutgoingMessage, " when making an outgoing message" do it "should work out a salutation" do @om.get_salutation.should == "Dear Geraldine Quango," end + + it 'should produce the expected text for an internal review request' do + public_body = mock_model(PublicBody, :name => 'A test public body') + info_request = mock_model(InfoRequest, :public_body => public_body, + :url_title => 'a_test_title', + :title => 'A test title', + :apply_censor_rules_to_text! => nil) + outgoing_message = OutgoingMessage.new({ + :status => 'ready', + :message_type => 'followup', + :what_doing => 'internal_review', + :info_request => info_request + }) + expected_text = "I am writing to request an internal review of A test public body's handling of my FOI request 'A test title'." + outgoing_message.body.should include(expected_text) + end + end diff --git a/spec/models/xapian_spec.rb b/spec/models/xapian_spec.rb index 8c99d550f..c40334142 100644 --- a/spec/models/xapian_spec.rb +++ b/spec/models/xapian_spec.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe User, " when indexing users with Xapian" do @@ -8,8 +9,7 @@ describe User, " when indexing users with Xapian" do end it "should search by name" do - # def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) - xapian_object = InfoRequest.full_search([User], "Silly", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([User], "Silly", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == users(:silly_name_user) end @@ -17,8 +17,7 @@ describe User, " when indexing users with Xapian" do it "should search by 'about me' text" do user = users(:bob_smith_user) - # def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) - xapian_object = InfoRequest.full_search([User], "stuff", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([User], "stuff", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == user @@ -26,10 +25,10 @@ describe User, " when indexing users with Xapian" do user.save! update_xapian_index - xapian_object = InfoRequest.full_search([User], "stuff", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([User], "stuff", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([User], "aardvark", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([User], "aardvark", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == user end @@ -42,26 +41,26 @@ describe PublicBody, " when indexing public bodies with Xapian" do end it "should search index the main name field" do - xapian_object = InfoRequest.full_search([PublicBody], "humpadinking", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "humpadinking", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == public_bodies(:humpadink_public_body) end it "should search index the notes field" do - xapian_object = InfoRequest.full_search([PublicBody], "albatross", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "albatross", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == public_bodies(:humpadink_public_body) end it "should delete public bodies from the index when they are destroyed" do - xapian_object = InfoRequest.full_search([PublicBody], "albatross", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "albatross", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == public_bodies(:humpadink_public_body) public_bodies(:forlorn_public_body).destroy update_xapian_index - xapian_object = InfoRequest.full_search([PublicBody], "lonely", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "lonely", :limit => 100) xapian_object.results.should == [] end @@ -75,13 +74,13 @@ describe PublicBody, " when indexing requests by body they are to" do end it "should find requests to the body" do - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_from:tgq", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_from:tgq", :limit => 100) xapian_object.results.size.should == PublicBody.find_by_url_name("tgq").info_requests.map(&:info_request_events).flatten.size end it "should update index correctly when URL name of body changes" do # initial search - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_from:tgq", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_from:tgq", :limit => 100) xapian_object.results.size.should == PublicBody.find_by_url_name("tgq").info_requests.map(&:info_request_events).flatten.size models_found_before = xapian_object.results.map { |x| x[:model] } @@ -93,9 +92,9 @@ describe PublicBody, " when indexing requests by body they are to" do update_xapian_index # check we get results expected - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_from:tgq", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_from:tgq", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_from:gq", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_from:gq", :limit => 100) xapian_object.results.size.should == PublicBody.find_by_url_name("gq").info_requests.map(&:info_request_events).flatten.size models_found_after = xapian_object.results.map { |x| x[:model] } @@ -113,11 +112,11 @@ describe PublicBody, " when indexing requests by body they are to" do update_xapian_index # check we get results expected - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_from:tgq", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_from:tgq", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_from:gq", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_from:gq", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_from:" + body.url_name, 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_from:#{body.url_name}", :limit => 100) xapian_object.results.size.should == public_bodies(:geraldine_public_body).info_requests.map(&:info_request_events).flatten.size models_found_after = xapian_object.results.map { |x| x[:model] } end @@ -130,13 +129,14 @@ describe User, " when indexing requests by user they are from" do end it "should find requests from the user" do - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_by:bob_smith", + :sort_by_prefix => 'created_at', :sort_by_ascending => true, :limit => 100) xapian_object.results.map{|x|x[:model]}.should =~ InfoRequestEvent.all(:conditions => "info_request_id in (select id from info_requests where user_id = #{users(:bob_smith_user).id})") end it "should find just the sent message events from a particular user" do - # def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith variety:sent", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_by:bob_smith variety:sent", + :sort_by_prefix => 'created_at', :sort_by_ascending => true, :limit => 100) xapian_object.results.map{|x|x[:model]}.should =~ InfoRequestEvent.all(:conditions => "info_request_id in (select id from info_requests where user_id = #{users(:bob_smith_user).id}) and event_type = 'sent'") xapian_object.results[2][:model].should == info_request_events(:useless_outgoing_message_event) xapian_object.results[1][:model].should == info_request_events(:silly_outgoing_message_event) @@ -150,8 +150,9 @@ describe User, " when indexing requests by user they are from" do update_xapian_index - # def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith", 'created_at', true, 'request_collapse', 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_by:bob_smith", + :sort_by_prefix => 'created_at', :sort_by_ascending => true, + :collapse_by_prefix => 'request_collapse', :limit => 100) xapian_object.results.map{|x|x[:model].info_request}.should =~ InfoRequest.all(:conditions => "user_id = #{users(:bob_smith_user).id}") end @@ -172,8 +173,7 @@ describe User, " when indexing requests by user they are from" do update_xapian_index - # def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:john_k", 'created_at', true, 'request_collapse', 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_by:john_k", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == info_request_events(:silly_outgoing_message_event) end @@ -181,7 +181,8 @@ describe User, " when indexing requests by user they are from" do it "should update index correctly when URL name of user changes" do # initial search - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_by:bob_smith", + :sort_by_prefix => 'created_at', :sort_by_ascending => true, :limit => 100) xapian_object.results.map{|x|x[:model]}.should =~ InfoRequestEvent.all(:conditions => "info_request_id in (select id from info_requests where user_id = #{users(:bob_smith_user).id})") models_found_before = xapian_object.results.map { |x| x[:model] } @@ -193,9 +194,10 @@ describe User, " when indexing requests by user they are from" do update_xapian_index # check we get results expected - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_by:bob_smith", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:robert_smith", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "requested_by:robert_smith", + :sort_by_prefix => 'created_at', :sort_by_ascending => true, :limit => 100) models_found_after = xapian_object.results.map { |x| x[:model] } models_found_before.should == models_found_after end @@ -208,13 +210,13 @@ describe User, " when indexing comments by user they are by" do end it "should find requests from the user" do - xapian_object = InfoRequest.full_search([InfoRequestEvent], "commented_by:silly_emnameem", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "commented_by:silly_emnameem", :limit => 100) xapian_object.results.size.should == 1 end it "should update index correctly when URL name of user changes" do # initial search - xapian_object = InfoRequest.full_search([InfoRequestEvent], "commented_by:silly_emnameem", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "commented_by:silly_emnameem", :limit => 100) xapian_object.results.size.should == 1 models_found_before = xapian_object.results.map { |x| x[:model] } @@ -226,9 +228,9 @@ describe User, " when indexing comments by user they are by" do update_xapian_index # check we get results expected - xapian_object = InfoRequest.full_search([InfoRequestEvent], "commented_by:silly_emnameem", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "commented_by:silly_emnameem", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([InfoRequestEvent], "commented_by:silly_name", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "commented_by:silly_name", :limit => 100) xapian_object.results.size.should == 1 models_found_after = xapian_object.results.map { |x| x[:model] } @@ -243,7 +245,7 @@ describe InfoRequest, " when indexing requests by their title" do end it "should find events for the request" do - xapian_object = InfoRequest.full_search([InfoRequestEvent], "request:how_much_public_money_is_wasted_o", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "request:how_much_public_money_is_wasted_o", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model] == info_request_events(:silly_outgoing_message_event) end @@ -257,9 +259,9 @@ describe InfoRequest, " when indexing requests by their title" do update_xapian_index # check we get results expected - xapian_object = InfoRequest.full_search([InfoRequestEvent], "request:how_much_public_money_is_wasted_o", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "request:how_much_public_money_is_wasted_o", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([InfoRequestEvent], "request:really_naughty", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "request:really_naughty", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model] == info_request_events(:silly_outgoing_message_event) end @@ -277,11 +279,11 @@ describe InfoRequest, " when indexing requests by tag" do ir.save! update_xapian_index - xapian_object = InfoRequest.full_search([InfoRequestEvent], "tag:bunnyrabbit", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "tag:bunnyrabbit", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model] == info_request_events(:silly_outgoing_message_event) - xapian_object = InfoRequest.full_search([InfoRequestEvent], "tag:orangeaardvark", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([InfoRequestEvent], "tag:orangeaardvark", :limit => 100) xapian_object.results.size.should == 0 end end @@ -298,14 +300,14 @@ describe PublicBody, " when indexing authorities by tag" do body.save! update_xapian_index - xapian_object = InfoRequest.full_search([PublicBody], "tag:mice", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "tag:mice", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model] == public_bodies(:geraldine_public_body) - xapian_object = InfoRequest.full_search([PublicBody], "tag:mice:3", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "tag:mice:3", :limit => 100) xapian_object.results.size.should == 1 xapian_object.results[0][:model] == public_bodies(:geraldine_public_body) - xapian_object = InfoRequest.full_search([PublicBody], "tag:orangeaardvark", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "tag:orangeaardvark", :limit => 100) xapian_object.results.size.should == 0 end end @@ -327,11 +329,11 @@ describe PublicBody, " when only indexing selected things on a rebuild" do values = false texts = false rebuild_xapian_index(terms, values, texts, dropfirst) - xapian_object = InfoRequest.full_search([PublicBody], "tag:mice", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "tag:mice", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([PublicBody], "frobzn", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "frobzn", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([PublicBody], "variety:authority", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "variety:authority", :limit => 100) xapian_object.results.map{|x|x[:model]}.should =~ PublicBody.all # only reindex 'tag' and text dropfirst = true @@ -339,32 +341,57 @@ describe PublicBody, " when only indexing selected things on a rebuild" do values = false texts = true rebuild_xapian_index(terms, values, texts, dropfirst) - xapian_object = InfoRequest.full_search([PublicBody], "tag:mice", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "tag:mice", :limit => 100) xapian_object.results.size.should == 1 - xapian_object = InfoRequest.full_search([PublicBody], "frobzn", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "frobzn", :limit => 100) xapian_object.results.size.should == 1 - xapian_object = InfoRequest.full_search([PublicBody], "variety:authority", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "variety:authority", :limit => 100) xapian_object.results.size.should == 0 # only reindex 'variety' term, but keeping the existing data in-place dropfirst = false terms = "V" texts = false rebuild_xapian_index(terms, values, texts, dropfirst) - xapian_object = InfoRequest.full_search([PublicBody], "tag:mice", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "tag:mice", :limit => 100) xapian_object.results.size.should == 1 - xapian_object = InfoRequest.full_search([PublicBody], "frobzn", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "frobzn", :limit => 100) xapian_object.results.size.should == 1 - xapian_object = InfoRequest.full_search([PublicBody], "variety:authority", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "variety:authority", :limit => 100) xapian_object.results.map{|x|x[:model]}.should =~ PublicBody.all # only reindex 'variety' term, blowing away existing data dropfirst = true rebuild_xapian_index(terms, values, texts, dropfirst) - xapian_object = InfoRequest.full_search([PublicBody], "tag:mice", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "tag:mice", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([PublicBody], "frobzn", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "frobzn", :limit => 100) xapian_object.results.size.should == 0 - xapian_object = InfoRequest.full_search([PublicBody], "variety:authority", 'created_at', true, nil, 100, 1) + xapian_object = ActsAsXapian::Search.new([PublicBody], "variety:authority", :limit => 100) xapian_object.results.map{|x|x[:model]}.should =~ PublicBody.all end end +# I would expect ActsAsXapian to have some tests under vendor/plugins/acts_as_xapian, but +# it looks like this is not the case. Putting a test here instead. +describe ActsAsXapian::Search, "#words_to_highlight" do + it "should return a list of words used in the search" do + s = ActsAsXapian::Search.new([PublicBody], "albatross words", :limit => 100) + s.words_to_highlight.should == ["albatross", "words"] + end + + it "should remove any operators" do + s = ActsAsXapian::Search.new([PublicBody], "albatross words tag:mice", :limit => 100) + s.words_to_highlight.should == ["albatross", "words"] + end + + # This is the current behaviour but it seems a little simplistic to me + it "should separate punctuation" do + s = ActsAsXapian::Search.new([PublicBody], "The doctor's patient", :limit => 100) + s.words_to_highlight.should == ["The", "doctor", "s", "patient"] + end + + it "should handle non-ascii characters" do + s = ActsAsXapian::Search.new([PublicBody], "adatigénylés words tag:mice", :limit => 100) + s.words_to_highlight.should == ["adatigénylés", "words"] + end + +end diff --git a/spec/views/reports/new.erb_spec.rb b/spec/views/reports/new.erb_spec.rb new file mode 100644 index 000000000..66b738261 --- /dev/null +++ b/spec/views/reports/new.erb_spec.rb @@ -0,0 +1,29 @@ +require File.expand_path(File.join('..', '..', '..', 'spec_helper'), __FILE__) + +describe 'reports/new.html.erb' do + let(:info_request) { mock_model(InfoRequest, :url_title => "foo", :report_reasons => ["Weird"]) } + before :each do + assign(:info_request, info_request) + end + + it "should show a form" do + render + rendered.should have_selector("form") + end + + context "request has already been reported" do + before :each do + info_request.stub!(:attention_requested).and_return(true) + end + + it "should not show a form" do + render + rendered.should_not have_selector("form") + end + + it "should say it's already been reported" do + render + rendered.should contain("This request has already been reported") + end + end +end diff --git a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb index 1e5df8de4..f2cd1075c 100644 --- a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb +++ b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 # acts_as_xapian/lib/acts_as_xapian.rb: # Xapian full text search in Ruby on Rails. # @@ -472,7 +473,9 @@ module ActsAsXapian # date ranges or similar. Use this for cheap highlighting with # TextHelper::highlight, and excerpt. def words_to_highlight - query_nopunc = self.query_string.gsub(/[^a-z0-9:\.\/_]/i, " ") + # TODO: In Ruby 1.9 we can do matching of any unicode letter with \p{L} + # But we still need to support ruby 1.8 for the time being so... + query_nopunc = self.query_string.gsub(/[^ёЁа-яА-Яa-zA-Zà-üÀ-Ü0-9:\.\/_]/iu, " ") query_nopunc = query_nopunc.gsub(/\s+/, " ") words = query_nopunc.split(" ") # Remove anything with a :, . or / in it |