diff options
-rw-r--r-- | app/controllers/admin_general_controller.rb | 33 | ||||
-rw-r--r-- | app/mailers/request_mailer.rb | 3 | ||||
-rw-r--r-- | app/models/censor_rule.rb | 5 | ||||
-rw-r--r-- | app/models/incoming_message.rb | 2 | ||||
-rw-r--r-- | app/models/info_request.rb | 34 | ||||
-rw-r--r-- | app/models/outgoing_message.rb | 47 | ||||
-rw-r--r-- | app/views/admin_general/index.html.erb | 99 | ||||
-rw-r--r-- | config/initializers/alaveteli.rb | 2 | ||||
-rwxr-xr-x | script/request-creation-graph | 6 | ||||
-rw-r--r-- | spec/factories/info_requests.rb | 2 | ||||
-rw-r--r-- | spec/integration/download_request_spec.rb | 3 | ||||
-rw-r--r-- | spec/mailers/request_mailer_spec.rb | 21 | ||||
-rw-r--r-- | spec/models/censor_rule_spec.rb | 36 | ||||
-rw-r--r-- | spec/models/incoming_message_spec.rb | 12 | ||||
-rw-r--r-- | spec/models/info_request_spec.rb | 29 | ||||
-rw-r--r-- | spec/models/outgoing_message_spec.rb | 109 |
16 files changed, 335 insertions, 108 deletions
diff --git a/app/controllers/admin_general_controller.rb b/app/controllers/admin_general_controller.rb index 17c54476e..8efe0c7b9 100644 --- a/app/controllers/admin_general_controller.rb +++ b/app/controllers/admin_general_controller.rb @@ -8,28 +8,29 @@ class AdminGeneralController < AdminController def index - # Overview counts of things - @public_body_count = PublicBody.count - - @info_request_count = InfoRequest.count - @outgoing_message_count = OutgoingMessage.count - @incoming_message_count = IncomingMessage.count - - @user_count = User.count - @track_thing_count = TrackThing.count - - @comment_count = Comment.count - # Tasks to do @requires_admin_requests = InfoRequest.find_in_state('requires_admin') @error_message_requests = InfoRequest.find_in_state('error_message') @attention_requests = InfoRequest.find_in_state('attention_requested') - @blank_contacts = PublicBody.where(:request_email => "").order(:updated_at).select { |pb| !pb.defunct? } + @blank_contacts = PublicBody. + includes(:tags, :translations). + where(:request_email => ""). + order(:updated_at). + select { |pb| !pb.defunct? } @old_unclassified = InfoRequest.find_old_unclassified(:limit => 20, :conditions => ["prominence = 'normal'"]) - @holding_pen_messages = InfoRequest.holding_pen_request.incoming_messages - @new_body_requests = PublicBodyChangeRequest.new_body_requests.open - @body_update_requests = PublicBodyChangeRequest.body_update_requests.open + @holding_pen_messages = InfoRequest. + includes(:incoming_messages => :raw_email). + holding_pen_request. + incoming_messages + @new_body_requests = PublicBodyChangeRequest. + includes(:public_body, :user). + new_body_requests. + open + @body_update_requests = PublicBodyChangeRequest. + includes(:public_body, :user). + body_update_requests. + open end def timeline diff --git a/app/mailers/request_mailer.rb b/app/mailers/request_mailer.rb index fc824ebe3..f97556915 100644 --- a/app/mailers/request_mailer.rb +++ b/app/mailers/request_mailer.rb @@ -235,8 +235,9 @@ class RequestMailer < ApplicationMailer def requests_matching_email(email) # We deliberately don't use Envelope-to here, so ones that are BCC # drop into the holding pen for checking. + addresses = ((email.to || []) + (email.cc || [])).compact reply_info_requests = [] # TODO: should be set? - for address in (email.to || []) + (email.cc || []) + addresses.each do |address| reply_info_request = InfoRequest.find_by_incoming_email(address) reply_info_requests.push(reply_info_request) if reply_info_request end diff --git a/app/models/censor_rule.rb b/app/models/censor_rule.rb index 3b7aaf7fa..0ef5d18bd 100644 --- a/app/models/censor_rule.rb +++ b/app/models/censor_rule.rb @@ -43,6 +43,11 @@ class CensorRule < ActiveRecord::Base :user_id => nil, :public_body_id => nil } } + def apply_to_text(text_to_censor) + return nil if text_to_censor.nil? + text_to_censor.gsub(to_replace, replacement) + end + def apply_to_text!(text_to_censor) return nil if text_to_censor.nil? text_to_censor.gsub!(to_replace, replacement) diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index cc8088352..a74056b5d 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -654,7 +654,7 @@ class IncomingMessage < ActiveRecord::Base # Save clipped version for snippets if self.cached_attachment_text_clipped.nil? - self.cached_attachment_text_clipped = text[0..MAX_ATTACHMENT_TEXT_CLIPPED] + self.cached_attachment_text_clipped = text.mb_chars[0..MAX_ATTACHMENT_TEXT_CLIPPED] self.save! end diff --git a/app/models/info_request.rb b/app/models/info_request.rb index 275c39746..65099b1c4 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -428,6 +428,7 @@ public # A new incoming email to this request def receive(email, raw_email_data, override_stop_new_responses = false, rejected_reason = "") + # Is this request allowing responses? if !override_stop_new_responses allow = nil reason = nil @@ -458,9 +459,15 @@ public raise "Unknown allow_new_responses_from '" + self.allow_new_responses_from + "'" end + # If its not allowing responses, handle the message if !allow if self.handle_rejected_responses == 'bounce' - RequestMailer.stopped_responses(self, email, raw_email_data).deliver if !is_external? + if MailHandler.get_from_address(email).nil? + # do nothing – can't bounce the mail as there's no + # address to send it to + else + RequestMailer.stopped_responses(self, email, raw_email_data).deliver if !is_external? + end elsif self.handle_rejected_responses == 'holding_pen' InfoRequest.holding_pen_request.receive(email, raw_email_data, false, reason) elsif self.handle_rejected_responses == 'blackhole' @@ -777,7 +784,14 @@ public end def public_response_events - self.info_request_events.select{|e| e.response? && e.incoming_message.all_can_view? } + condition = <<-SQL + info_request_events.event_type = ? + AND incoming_messages.prominence = ? + SQL + + info_request_events. + joins(:incoming_message). + where(condition, 'response', 'normal') end # The last public response is the default one people might want to reply to @@ -804,8 +818,9 @@ public # Text from the the initial request, for use in summary display def initial_request_text - return '' if outgoing_messages.empty? # mainly for use with incomplete fixtures - outgoing_messages.first.get_text_for_indexing + return '' if outgoing_messages.empty? + body_opts = { :censor_rules => applicable_censor_rules } + outgoing_messages.first.try(:get_text_for_indexing, true, body_opts) or '' end # Returns index of last event which is described or nil if none described. @@ -925,7 +940,7 @@ public # Called by incoming_email - and used to be called to generate separate # envelope from address until we abandoned it. def magic_email(prefix_part) - raise "id required to make magic" if not self.id + raise "id required to create a magic email" if not self.id return InfoRequest.magic_email_for_id(prefix_part, self.id) end @@ -1383,6 +1398,15 @@ public end end + # The DateTime of the last InfoRequestEvent belonging to the InfoRequest + # Only available if the last_event_time attribute has been set. This is + # currentlt only set through .find_in_state + # + # Returns a DateTime + def last_event_time + attributes['last_event_time'].try(:to_datetime) + end + private def set_defaults diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb index ab26fb89a..7bb8ce8be 100644 --- a/app/models/outgoing_message.rb +++ b/app/models/outgoing_message.rb @@ -141,22 +141,28 @@ class OutgoingMessage < ActiveRecord::Base end end - def body - ret = read_attribute(:body) - if ret.nil? - return ret + # Public: The body text of the OutgoingMessage. The text is cleaned and + # CensorRules are applied. + # + # options - Hash of options + # :censor_rules - Array of CensorRules to apply. Defaults to the + # applicable_censor_rules of the associated + # InfoRequest. (optional) + # + # Returns a String + def body(options = {}) + text = raw_body.dup + return text if text.nil? + + text = clean_text(text) + + # Use the given censor_rules; otherwise fetch them from the associated + # info_request + censor_rules = options.fetch(:censor_rules) do + info_request.try(:applicable_censor_rules) or [] end - ret = ret.dup - ret.strip! - ret.gsub!(/(?:\n\s*){2,}/, "\n\n") # remove excess linebreaks that unnecessarily space it out - - # Remove things from censor rules - unless info_request.nil? - self.info_request.apply_censor_rules_to_text!(ret) - end - - ret + censor_rules.reduce(text) { |text, rule| rule.apply_to_text(text) } end def raw_body @@ -228,8 +234,12 @@ class OutgoingMessage < ActiveRecord::Base end # Returns text for indexing / text display - def get_text_for_indexing(strip_salutation = true) - text = body.strip + def get_text_for_indexing(strip_salutation = true, opts = {}) + if opts.empty? + text = body.strip + else + text = body(opts).strip + end # Remove salutation text.sub!(/Dear .+,/, "") if strip_salutation @@ -333,6 +343,11 @@ class OutgoingMessage < ActiveRecord::Base errors.add(:what_doing_dummy, _('Please choose what sort of reply you are making.')) end end + + # remove excess linebreaks that unnecessarily space it out + def clean_text(text) + text.strip.gsub(/(?:\n\s*){2,}/, "\n\n") + end end diff --git a/app/views/admin_general/index.html.erb b/app/views/admin_general/index.html.erb index ba0563bb6..8840bce74 100644 --- a/app/views/admin_general/index.html.erb +++ b/app/views/admin_general/index.html.erb @@ -2,17 +2,10 @@ <div class="row"> <div class="span12"> - <h1><%=@title%></h1> - - <ul> - <li><%=@public_body_count%> public authorities</li> - <li> - <%=@info_request_count%> requests, <%=@outgoing_message_count%> outgoing messages, - <%=@incoming_message_count%> incoming messages - </li> - <li><%=@user_count%> users, <%=@track_thing_count%> tracked things</li> - <li><%=@comment_count%> annotations</li> - </ul> + <h1><%= @title %></h1> + <p> + <%= link_to 'Summary stats have moved →', admin_stats_path %> + </p> </div> </div> @@ -28,8 +21,14 @@ <% if @holding_pen_messages.size > 0 %> <div class="accordion-group"> <div class="accordion-heading"> - <a class="accordion-toggle" href="#holding-pen" data-toggle="collapse" data-parent="things-to-do"><span class="label label-important"><%=@holding_pen_messages.size%></span><%= chevron_right %> Put misdelivered responses with the right request</a> + <a class="accordion-toggle" href="#holding-pen" data-toggle="collapse" data-parent="things-to-do"> + <span class="label label-important"> + <%= @holding_pen_messages.size %> + </span> + <%= chevron_right %> Put misdelivered responses with the right request + </a> </div> + <div id="holding-pen" class="accordion-body collapse"> <table class="table table-striped table-condensed"> <tbody> @@ -39,11 +38,13 @@ <% if message.get_body_for_quoting.strip.size == 0 %> <%= link_to "(no body)", admin_raw_email_path(message.raw_email_id) %> <% else %> - <%= link_to excerpt(message.get_body_for_quoting, "", :radius => 60), admin_raw_email_path(message.raw_email_id) %> + <%= link_to admin_raw_email_path(message.raw_email_id) do %> + <%= excerpt(message.get_body_for_quoting, "", :radius => 60) %> + <% end %> <% end %> </td> <td class="span2"> - <%=simple_date(message.sent_at)%> + <%= simple_date(message.sent_at) %> </td> </tr> <% end %> @@ -67,7 +68,7 @@ <%= request_both_links(@request) %> </td> <td class="span2"> - <%=simple_date(@request.info_request_events.last.created_at)%> + <%= simple_date(@request.last_event_time) %> </td> </tr> <% end %> @@ -92,7 +93,7 @@ <%= request_both_links(@request) %> </td> <td class="span2"> - <%=simple_date(@request.info_request_events.last.created_at)%> + <%= simple_date(@request.last_event_time) %> </td> </tr> <% end %> @@ -116,7 +117,7 @@ <%= request_both_links(@request) %> </td> <td class="span2"> - <%=simple_date(@request.info_request_events.last.created_at)%> + <%= simple_date(@request.last_event_time) %> </td> </tr> <% end %> @@ -178,18 +179,33 @@ <% if @new_body_requests.size > 0 %> <div class="accordion-group"> <div class="accordion-heading"> - <a class="accordion-toggle" href="#new-authorities" data-toggle="collapse" data-parent="things-to-do"><span class="label label-important"><%= @new_body_requests.size %></span><%= chevron_right %> Add new authorities</a> + <a class="accordion-toggle" href="#new-authorities" data-toggle="collapse" data-parent="things-to-do"> + <span class="label label-important"> + <%= @new_body_requests.size %> + </span> + <%= chevron_right %> Add new authorities + </a> </div> + <div id="new-authorities" class="accordion-body collapse"> - <% for @change_request in @new_body_requests %> - <%= render :partial => 'change_request_summary'%> - <%= form_tag admin_change_request_path(@change_request), :method => 'put', :class => "form form-horizontal" do %> - <%= submit_tag 'Close', :class => "btn btn-danger" %> - <%= link_to("Close and respond", edit_admin_change_request_path(@change_request), :class => 'btn') %> - <%= link_to("Add authority", new_admin_body_path(:change_request_id => @change_request.id), :class => 'btn btn-primary') %> - <% end %> + <% for @change_request in @new_body_requests %> + <%= render :partial => 'change_request_summary'%> - <% end %> + <%= form_tag admin_change_request_path(@change_request), + :method => 'put', + :class => "form form-horizontal" do %> + + <%= submit_tag 'Close', :class => "btn btn-danger" %> + + <%= link_to "Close and respond", + edit_admin_change_request_path(@change_request), + :class => 'btn' %> + + <%= link_to "Add authority", + new_admin_body_path(:change_request_id => @change_request.id), + :class => 'btn btn-primary' %> + <% end %> + <% end %> </div> </div> <% end %> @@ -197,17 +213,34 @@ <% if @body_update_requests.size > 0 %> <div class="accordion-group"> <div class="accordion-heading"> - <a class="accordion-toggle" href="#update-authorities" data-toggle="collapse" data-parent="things-to-do"><span class="label label-important"><%= @body_update_requests.size %></span><%= chevron_right %> Update authorities</a> + <a class="accordion-toggle" href="#update-authorities" data-toggle="collapse" data-parent="things-to-do"> + <span class="label label-important"> + <%= @body_update_requests.size %> + </span> + <%= chevron_right %> Update authorities + </a> </div> + <div id="update-authorities" class="accordion-body collapse"> <% for @change_request in @body_update_requests %> - <%= render :partial => 'change_request_summary' %> - <%= form_tag admin_change_request_path(@change_request), :class => "form form-horizontal", :method => 'put' do %> - <%= submit_tag 'Close', :class => "btn btn-danger" %> - <%= link_to("Close and respond", edit_admin_change_request_path(@change_request), :class => 'btn') %> - <%= link_to("Make update", edit_admin_body_path(@change_request.public_body, :change_request_id => @change_request.id), :class => 'btn btn-primary') %> - <% end %> + <%= render :partial => 'change_request_summary' %> + + <%= form_tag admin_change_request_path(@change_request), + :class => "form form-horizontal", + :method => 'put' do %> + + <%= submit_tag 'Close', :class => "btn btn-danger" %> + + <%= link_to "Close and respond", + edit_admin_change_request_path(@change_request), + :class => 'btn' %> + + <%= link_to "Make update", + edit_admin_body_path(@change_request.public_body, + :change_request_id => @change_request.id), + :class => 'btn btn-primary' %> <% end %> + <% end %> </div> </div> <% end %> diff --git a/config/initializers/alaveteli.rb b/config/initializers/alaveteli.rb index 4facd1fd2..f4def4c2a 100644 --- a/config/initializers/alaveteli.rb +++ b/config/initializers/alaveteli.rb @@ -11,7 +11,7 @@ load "debug_helpers.rb" load "util.rb" # Application version -ALAVETELI_VERSION = '0.21.0.27' +ALAVETELI_VERSION = '0.21.0.30' # Add new inflection rules using the following format # (all these examples are active by default): diff --git a/script/request-creation-graph b/script/request-creation-graph index 7d347a7d2..f3baa2326 100755 --- a/script/request-creation-graph +++ b/script/request-creation-graph @@ -51,6 +51,12 @@ function grab_data { # rather nastily, work out the cumulative heights in reverse, so can plot impulses on top of each other grab_data "where (1 = 1)" $SOURCEA +if [ ! -s $SOURCEA ] ; then + # No data yet, skip graphing + echo "warning: no data to graph, skipping task" + exit +fi + grab_data "where described_state not in ('waiting_response')" $SOURCEB grab_data "where described_state not in ('waiting_response', 'waiting_clarification')" $SOURCEC grab_data "where described_state not in ('waiting_response', 'waiting_clarification', 'not_held')" $SOURCED diff --git a/spec/factories/info_requests.rb b/spec/factories/info_requests.rb index 45485c435..084712243 100644 --- a/spec/factories/info_requests.rb +++ b/spec/factories/info_requests.rb @@ -2,7 +2,7 @@ FactoryGirl.define do factory :info_request do - title "Example Title" + sequence(:title) { |n| "Example Title #{n}" } public_body user diff --git a/spec/integration/download_request_spec.rb b/spec/integration/download_request_spec.rb index 4b3d11d13..1050e6792 100644 --- a/spec/integration/download_request_spec.rb +++ b/spec/integration/download_request_spec.rb @@ -144,7 +144,8 @@ describe 'when making a zipfile available' do it "should update the contents of the zipfile when the request changes" do - info_request = FactoryGirl.create(:info_request_with_incoming) + info_request = FactoryGirl.create(:info_request_with_incoming, + :title => 'Example Title') request_owner = login(info_request.user) inspect_zip_download(request_owner, info_request) do |zip| zip.count.should == 1 # just the message diff --git a/spec/mailers/request_mailer_spec.rb b/spec/mailers/request_mailer_spec.rb index 7dcb47b50..5c8b8a3de 100644 --- a/spec/mailers/request_mailer_spec.rb +++ b/spec/mailers/request_mailer_spec.rb @@ -40,6 +40,12 @@ describe RequestMailer, " when receiving incoming mail" do deliveries.clear end + it "puts messages with a malformed To: in the holding pen" do + request = FactoryGirl.create(:info_request) + receive_incoming_mail('incoming-request-plain.email', 'asdfg') + expect(InfoRequest.holding_pen_request.incoming_messages).to have(1).item + end + it "should parse attachments from mails sent with apple mail" do ir = info_requests(:fancy_dog_request) ir.incoming_messages.size.should == 1 @@ -180,6 +186,21 @@ describe RequestMailer, " when receiving incoming mail" do deliveries.clear end + it "discards rejected responses with a malformed From: when set to bounce" do + ir = info_requests(:fancy_dog_request) + ir.allow_new_responses_from = 'nobody' + ir.handle_rejected_responses = 'bounce' + ir.save! + ir.incoming_messages.size.should == 1 + + receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "") + ir.incoming_messages.size.should == 1 + + deliveries = ActionMailer::Base.deliveries + deliveries.size.should == 0 + deliveries.clear + end + it "should send all new responses to holding pen if a request is marked to do so" do # mark request as anti-spam ir = info_requests(:fancy_dog_request) diff --git a/spec/models/censor_rule_spec.rb b/spec/models/censor_rule_spec.rb index 888650a3a..314b060d2 100644 --- a/spec/models/censor_rule_spec.rb +++ b/spec/models/censor_rule_spec.rb @@ -18,6 +18,42 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +describe CensorRule do + + describe :apply_to_text do + + it 'applies the rule to the text' do + rule = FactoryGirl.build(:censor_rule, :text => 'secret') + text = 'Some secret text' + expect(rule.apply_to_text(text)).to eq('Some [REDACTED] text') + end + + it 'does not mutate the input' do + rule = FactoryGirl.build(:censor_rule, :text => 'secret') + text = 'Some secret text' + rule.apply_to_text(text) + expect(text).to eq('Some secret text') + end + + it 'returns the text if the rule is unmatched' do + rule = FactoryGirl.build(:censor_rule, :text => 'secret') + text = 'Some text' + expect(rule.apply_to_text(text)).to eq('Some text') + end + end + + describe :apply_to_text! do + + it 'mutates the input' do + rule = FactoryGirl.build(:censor_rule, :text => 'secret') + text = 'Some secret text' + rule.apply_to_text!(text) + expect(text).to eq('Some [REDACTED] text') + end + + end +end + describe CensorRule, "substituting things" do describe 'when using a text rule' do diff --git a/spec/models/incoming_message_spec.rb b/spec/models/incoming_message_spec.rb index 6651deb61..f4b450370 100644 --- a/spec/models/incoming_message_spec.rb +++ b/spec/models/incoming_message_spec.rb @@ -707,3 +707,15 @@ describe IncomingMessage, 'when getting the body of a message for html display' end end + +describe IncomingMessage, 'when getting clipped attachment text' do + + it 'should clip to characters not bytes' do + incoming_message = FactoryGirl.build(:incoming_message) + # This character is 2 bytes so the string should get sliced unless + # we are handling multibyte chars correctly + multibyte_string = "å" * 500002 + incoming_message.stub!(:_get_attachment_text_internal).and_return(multibyte_string) + incoming_message.get_attachment_text_clipped.length.should == 500002 + end +end
\ No newline at end of file diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb index 075bc2607..cddf1f880 100644 --- a/spec/models/info_request_spec.rb +++ b/spec/models/info_request_spec.rb @@ -658,17 +658,22 @@ describe InfoRequest do before do Time.stub!(:now).and_return(Time.utc(2007, 11, 9, 23, 59)) - @mock_comment_event = mock_model(InfoRequestEvent, :created_at => Time.now - 23.days, - :event_type => 'comment', - :response? => false) - mock_incoming_message = mock_model(IncomingMessage, :all_can_view? => true) - @mock_response_event = mock_model(InfoRequestEvent, :created_at => Time.now - 22.days, - :event_type => 'response', - :response? => true, - :incoming_message => mock_incoming_message) - @info_request = InfoRequest.new(:prominence => 'normal', - :awaiting_description => true, - :info_request_events => [@mock_response_event, @mock_comment_event]) + @info_request = FactoryGirl.create(:info_request, + :prominence => 'normal', + :awaiting_description => true) + @comment_event = FactoryGirl.create(:info_request_event, + :created_at => Time.now - 23.days, + :event_type => 'comment', + :info_request => @info_request) + @incoming_message = FactoryGirl.create(:incoming_message, + :prominence => 'normal', + :info_request => @info_request) + @response_event = FactoryGirl.create(:info_request_event, + :info_request => @info_request, + :created_at => Time.now - 22.days, + :event_type => 'response', + :incoming_message => @incoming_message) + @info_request.update_attribute(:awaiting_description, true) end it 'should return false if it is the holding pen' do @@ -682,7 +687,7 @@ describe InfoRequest do end it 'should return false if its last response event occurred less than 21 days ago' do - @mock_response_event.stub!(:created_at).and_return(Time.now - 20.days) + @response_event.update_attribute(:created_at, Time.now - 20.days) @info_request.is_old_unclassified?.should be_false end diff --git a/spec/models/outgoing_message_spec.rb b/spec/models/outgoing_message_spec.rb index 44644c9d8..336e5a605 100644 --- a/spec/models/outgoing_message_spec.rb +++ b/spec/models/outgoing_message_spec.rb @@ -19,6 +19,93 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +describe OutgoingMessage do + + describe :initialize do + + it 'does not censor the #body' do + attrs = { :status => 'ready', + :message_type => 'initial_request', + :body => 'abc', + :what_doing => 'normal_sort' } + + message = FactoryGirl.create(:outgoing_message, attrs) + + OutgoingMessage.any_instance.should_not_receive(:body).and_call_original + OutgoingMessage.find(message.id) + end + + end + + describe :body do + + it 'returns the body attribute' do + attrs = { :status => 'ready', + :message_type => 'initial_request', + :body => 'abc', + :what_doing => 'normal_sort' } + + message = FactoryGirl.build(:outgoing_message, attrs) + expect(message.body).to eq('abc') + end + + it 'strips the body of leading and trailing whitespace' do + attrs = { :status => 'ready', + :message_type => 'initial_request', + :body => ' abc ', + :what_doing => 'normal_sort' } + + message = FactoryGirl.build(:outgoing_message, attrs) + expect(message.body).to eq('abc') + end + + it 'removes excess linebreaks that unnecessarily space it out' do + attrs = { :status => 'ready', + :message_type => 'initial_request', + :body => "ab\n\nc\n\n", + :what_doing => 'normal_sort' } + + message = FactoryGirl.build(:outgoing_message, attrs) + expect(message.body).to eq("ab\n\nc") + end + + it "applies the associated request's censor rules to the text" do + attrs = { :status => 'ready', + :message_type => 'initial_request', + :body => 'This sensitive text contains secret info!', + :what_doing => 'normal_sort' } + message = FactoryGirl.build(:outgoing_message, attrs) + + rules = [FactoryGirl.build(:censor_rule, :text => 'secret'), + FactoryGirl.build(:censor_rule, :text => 'sensitive')] + InfoRequest.any_instance.stub(:censor_rules).and_return(rules) + + expected = 'This [REDACTED] text contains [REDACTED] info!' + expect(message.body).to eq(expected) + end + + it "applies the given censor rules to the text" do + attrs = { :status => 'ready', + :message_type => 'initial_request', + :body => 'This sensitive text contains secret info!', + :what_doing => 'normal_sort' } + message = FactoryGirl.build(:outgoing_message, attrs) + + request_rules = [FactoryGirl.build(:censor_rule, :text => 'secret'), + FactoryGirl.build(:censor_rule, :text => 'sensitive')] + InfoRequest.any_instance.stub(:censor_rules).and_return(request_rules) + + censor_rules = [FactoryGirl.build(:censor_rule, :text => 'text'), + FactoryGirl.build(:censor_rule, :text => 'contains')] + + expected = 'This sensitive [REDACTED] [REDACTED] secret info!' + expect(message.body(:censor_rules => censor_rules)).to eq(expected) + end + + end + +end + describe OutgoingMessage, " when making an outgoing message" do before do @@ -58,6 +145,7 @@ describe OutgoingMessage, " when making an outgoing message" do info_request = mock_model(InfoRequest, :public_body => public_body, :url_title => 'a_test_title', :title => 'A test title', + :applicable_censor_rules => [], :apply_censor_rules_to_text! => nil, :is_batch_request_template? => false) outgoing_message = OutgoingMessage.new({ @@ -156,27 +244,6 @@ describe OutgoingMessage, " when making an outgoing message" do end end - -describe OutgoingMessage, " when censoring data" do - - before do - @om = outgoing_messages(:useless_outgoing_message) - - @censor_rule = CensorRule.new() - @censor_rule.text = "dog" - @censor_rule.replacement = "cat" - @censor_rule.last_edit_editor = "unknown" - @censor_rule.last_edit_comment = "none" - - @om.info_request.censor_rules << @censor_rule - end - - it "should apply censor rules to outgoing messages" do - @om.read_attribute(:body).should match(/fancy dog/) - @om.body.should match(/fancy cat/) - end -end - describe OutgoingMessage, "when validating the format of the message body" do it 'should handle a salutation with a bracket in it' do |