diff options
32 files changed, 684 insertions, 162 deletions
@@ -29,7 +29,6 @@ then \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true if [[ $- == *i* ]] # check for interactive shells then echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green - else echo "Using: $GEM_HOME" # don't use colors in non-interactive shells fi else # If the environment file has not yet been created, use the RVM CLI to select. diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb index 7cf23e61e..53ff2957b 100644 --- a/app/controllers/admin_request_controller.rb +++ b/app/controllers/admin_request_controller.rb @@ -71,6 +71,7 @@ class AdminRequestController < AdminController old_allow_new_responses_from = @info_request.allow_new_responses_from old_handle_rejected_responses = @info_request.handle_rejected_responses old_tag_string = @info_request.tag_string + old_comments_allowed = @info_request.comments_allowed @info_request.title = params[:info_request][:title] @info_request.prominence = params[:info_request][:prominence] @@ -81,6 +82,7 @@ class AdminRequestController < AdminController @info_request.allow_new_responses_from = params[:info_request][:allow_new_responses_from] @info_request.handle_rejected_responses = params[:info_request][:handle_rejected_responses] @info_request.tag_string = params[:info_request][:tag_string] + @info_request.comments_allowed = params[:info_request][:comments_allowed] == "true" ? true : false if @info_request.valid? @info_request.save! @@ -92,7 +94,8 @@ class AdminRequestController < AdminController :old_awaiting_description => old_awaiting_description, :awaiting_description => @info_request.awaiting_description, :old_allow_new_responses_from => old_allow_new_responses_from, :allow_new_responses_from => @info_request.allow_new_responses_from, :old_handle_rejected_responses => old_handle_rejected_responses, :handle_rejected_responses => @info_request.handle_rejected_responses, - :old_tag_string => old_tag_string, :tag_string => @info_request.tag_string + :old_tag_string => old_tag_string, :tag_string => @info_request.tag_string, + :old_comments_allowed => old_comments_allowed, :tag_string => @info_request.comments_allowed }) # expire cached files expire_for_request(@info_request) diff --git a/app/controllers/comment_controller.rb b/app/controllers/comment_controller.rb index 1552017c2..988a8a6f8 100644 --- a/app/controllers/comment_controller.rb +++ b/app/controllers/comment_controller.rb @@ -23,6 +23,13 @@ class CommentController < ApplicationController else raise "Unknown type " + params[:type] end + + # Are comments disabled on this request? + # + # There is no “add comment” link when comments are disabled, so users should + # not usually hit this unless they are explicitly attempting to avoid the comment + # block, so we just raise an exception. + raise "Comments are not allowed on this request" if !@info_request.comments_allowed? # Banned from adding comments? if !authenticated_user.nil? && !authenticated_user.can_make_comments? diff --git a/app/controllers/holiday_controller.rb b/app/controllers/holiday_controller.rb index 7f62aa26d..9430c0756 100644 --- a/app/controllers/holiday_controller.rb +++ b/app/controllers/holiday_controller.rb @@ -14,7 +14,9 @@ class HolidayController < ApplicationController def due_date if params[:holiday] @request_date = Date.strptime(params[:holiday]) or raise "Invalid date" - @due_date = Holiday.due_date_from(@request_date, 20) + days_later = MySociety::Config.get('REPLY_LATE_AFTER_DAYS', 20) + working_or_calendar_days = MySociety::Config.get('WORKING_OR_CALENDAR_DAYS', 'working') + @due_date = Holiday.due_date_from(@request_date, days_later, working_or_calendar_days) @skipped = Holiday.all( :conditions => [ 'day >= ? AND day <= ?', @request_date.strftime("%F"), @due_date.strftime("%F") diff --git a/app/models/application_mailer.rb b/app/models/application_mailer.rb index 044006f7c..b6cd5a4bf 100644 --- a/app/models/application_mailer.rb +++ b/app/models/application_mailer.rb @@ -5,7 +5,7 @@ # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # # $Id: application_mailer.rb,v 1.8 2009-02-09 10:37:12 francis Exp $ - +require 'action_mailer/version' class ApplicationMailer < ActionMailer::Base # Include all the functions views get, as emails call similar things. helper :application @@ -26,5 +26,126 @@ class ApplicationMailer < ActionMailer::Base # Site-wide access to configuration settings include ConfigHelper + + # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer + # will be initialized according to the named method. If not, the mailer will + # remain uninitialized (useful when you only need to invoke the "receive" + # method, for instance). + def initialize(method_name=nil, *parameters) #:nodoc: + create!(method_name, *parameters) if method_name + end + + # For each multipart template (e.g. "the_template_file.text.html.erb") available, + # add the one from the view path with the highest priority as a part to the mail + def render_multipart_templates + added_content_types = {} + self.view_paths.each do |view_path| + Dir.glob("#{view_path}/#{mailer_name}/#{@template}.*").each do |path| + template = view_path["#{mailer_name}/#{File.basename(path)}"] + + # Skip unless template has a multipart format + next unless template && template.multipart? + next if added_content_types[template.content_type] == true + @parts << Part.new( + :content_type => template.content_type, + :disposition => "inline", + :charset => charset, + :body => render_message(template, @body) + ) + added_content_types[template.content_type] = true + end + end + end + + # Look for the current template in each element of view_paths in order, + # return the first + def find_template + self.view_paths.each do |view_path| + if template = view_path["#{mailer_name}/#{@template}"] + return template + end + end + return nil + end + + if ActionMailer::VERSION::MAJOR == 2 + + # This method is a customised version of ActionMailer::Base.create! + # modified to allow templates to be selected correctly for multipart + # mails when themes have added to the view_paths. The problem from our + # point of view with ActionMailer::Base is that it sets template_root to + # the first element of the view_paths array and then uses only that (directly + # and via template_path, which is created from it) in the create! method when + # looking for templates. Our modified version looks for templates in the view_paths + # in order. + # Changed lines marked with *** + + # Initialize the mailer via the given +method_name+. The body will be + # rendered and a new TMail::Mail object created. + def create!(method_name, *parameters) #:nodoc: + initialize_defaults(method_name) + __send__(method_name, *parameters) + + # If an explicit, textual body has not been set, we check assumptions. + unless String === @body + # First, we look to see if there are any likely templates that match, + # which include the content-type in their file name (i.e., + # "the_template_file.text.html.erb", etc.). Only do this if parts + # have not already been specified manually. + if @parts.empty? + # *** render_multipart_templates replaces the following code + # Dir.glob("#{template_path}/#{@template}.*").each do |path| + # template = template_root["#{mailer_name}/#{File.basename(path)}"] + # + # # Skip unless template has a multipart format + # next unless template && template.multipart? + # + # @parts << Part.new( + # :content_type => template.content_type, + # :disposition => "inline", + # :charset => charset, + # :body => render_message(template, @body) + # ) + # end + render_multipart_templates + + unless @parts.empty? + @content_type = "multipart/alternative" if @content_type !~ /^multipart/ + @parts = sort_parts(@parts, @implicit_parts_order) + end + end + + # Then, if there were such templates, we check to see if we ought to + # also render a "normal" template (without the content type). If a + # normal template exists (or if there were no implicit parts) we render + # it. + template_exists = @parts.empty? + + # *** find_template replaces template_root call + # template_exists ||= template_root["#{mailer_name}/#{@template}"] + template_exists ||= find_template + + @body = render_message(@template, @body) if template_exists + + # Finally, if there are other message parts and a textual body exists, + # we shift it onto the front of the parts and set the body to nil (so + # that create_mail doesn't try to render it in addition to the parts). + if !@parts.empty? && String === @body + @parts.unshift ActionMailer::Part.new(:charset => charset, :body => @body) + @body = nil + end + end + + # If this is a multipart e-mail add the mime_version if it is not + # already set. + @mime_version ||= "1.0" if !@parts.empty? + + # build the mail object itself + @mail = create_mail + end + else + raise "ApplicationMailer.create! is obsolete - find another way to ensure that themes can override mail templates for multipart mails" + end + end diff --git a/app/models/censor_rule.rb b/app/models/censor_rule.rb index da3f49760..a74fdcb24 100644 --- a/app/models/censor_rule.rb +++ b/app/models/censor_rule.rb @@ -1,5 +1,5 @@ # == Schema Information -# Schema version: 114 +# Schema version: 20120919140404 # # Table name: censor_rules # @@ -9,11 +9,11 @@ # public_body_id :integer # text :text not null # replacement :text not null -# regexp :boolean # last_edit_editor :string(255) not null # last_edit_comment :text not null # created_at :datetime not null # updated_at :datetime not null +# regexp :boolean # # models/censor_rule.rb: diff --git a/app/models/holiday.rb b/app/models/holiday.rb index debd88dec..1072f6a70 100644 --- a/app/models/holiday.rb +++ b/app/models/holiday.rb @@ -25,18 +25,34 @@ class Holiday < ActiveRecord::Base - # Calculate the date on which a request made on a given date falls due. + def Holiday.weekend_or_holiday?(date) + # TODO only fetch holidays after the start_date + holidays = self.all.collect { |h| h.day }.to_set + + date.wday == 0 || date.wday == 6 || holidays.include?(date) + end + + def Holiday.due_date_from(start_date, days, type_of_days) + case type_of_days + when "working" + Holiday.due_date_from_working_days(start_date, days) + when "calendar" + Holiday.due_date_from_calendar_days(start_date, days) + else + raise "Unexpected value for type_of_days: #{type_of_days}" + end + end + + # Calculate the date on which a request made on a given date falls due when + # days are given in working days # i.e. it is due by the end of that day. - def Holiday.due_date_from(start_date, working_days) + def Holiday.due_date_from_working_days(start_date, working_days) # convert date/times into dates start_date = start_date.to_date - # TODO only fetch holidays after the start_date - holidays = self.all.collect { |h| h.day }.to_set - - # Count forward (20) working days. We start with today as "day zero". The - # first of the twenty full working days is the next day. We return the - # date of the last of the twenty. + # Count forward the number of working days. We start with today as "day zero". The + # first of the full working days is the next day. We return the + # date of the last of the number of working days. # This response for example of a public authority complains that we had # it wrong. We didn't (even thought I changed the code for a while, @@ -46,15 +62,27 @@ class Holiday < ActiveRecord::Base days_passed = 0 response_required_by = start_date - # Now step forward into each of the 20 days. + # Now step forward into each of the working days. while days_passed < working_days - response_required_by += 1.day - next if response_required_by.wday == 0 || response_required_by.wday == 6 # weekend - next if holidays.include?(response_required_by) - days_passed += 1 + response_required_by += 1 + days_passed += 1 unless weekend_or_holiday?(response_required_by) end - return response_required_by + response_required_by end + # Calculate the date on which a request made on a given date falls due when + # the days are given in calendar days (rather than working days) + # If the due date falls on a weekend or a holiday then the due date is the next + # weekday that isn't a holiday. + def Holiday.due_date_from_calendar_days(start_date, days) + # convert date/times into dates + start_date = start_date.to_date + + response_required_by = start_date + days + while weekend_or_holiday?(response_required_by) + response_required_by += 1 + end + response_required_by + end end diff --git a/app/models/info_request.rb b/app/models/info_request.rb index 2e16d0f58..141440c6d 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -1,4 +1,5 @@ # == Schema Information +# Schema version: 20120919140404 # # Table name: info_requests # @@ -19,6 +20,7 @@ # external_user_name :string(255) # external_url :string(255) # attention_requested :boolean default(FALSE) +# comments_allowed :boolean default(TRUE), not null # require 'digest/sha1' @@ -688,7 +690,8 @@ public # things, e.g. fees, not properly covered. def date_response_required_by days_later = MySociety::Config.get('REPLY_LATE_AFTER_DAYS', 20) - return Holiday.due_date_from(self.date_initial_request_last_sent_at, days_later) + working_or_calendar_days = MySociety::Config.get('WORKING_OR_CALENDAR_DAYS', 'working') + return Holiday.due_date_from(self.date_initial_request_last_sent_at, days_later, working_or_calendar_days) end # This is a long stop - even with UK public interest test extensions, 40 # days is a very long time. @@ -696,12 +699,13 @@ public last_sent = last_event_forming_initial_request very_late_days_later = MySociety::Config.get('REPLY_VERY_LATE_AFTER_DAYS', 40) school_very_late_days_later = MySociety::Config.get('SPECIAL_REPLY_VERY_LATE_AFTER_DAYS', 60) + working_or_calendar_days = MySociety::Config.get('WORKING_OR_CALENDAR_DAYS', 'working') if self.public_body.is_school? # schools have 60 working days maximum (even over a long holiday) - return Holiday.due_date_from(self.date_initial_request_last_sent_at, 60) + return Holiday.due_date_from(self.date_initial_request_last_sent_at, school_very_late_days_later, working_or_calendar_days) else # public interest test ICO guidance gives 40 working maximum - return Holiday.due_date_from(self.date_initial_request_last_sent_at, 40) + return Holiday.due_date_from(self.date_initial_request_last_sent_at, very_late_days_later, working_or_calendar_days) end end diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 77da81d4c..2cf1ce8a2 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -1,32 +1,27 @@ -# -*- coding: utf-8 -*- # == Schema Information +# Schema version: 20120919140404 # # 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 -# -# models/public_body.rb: -# A public body, from which information can be requested. +# 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) +# info_requests_count :integer default(0), not null # -# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. -# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ -# -# $Id: public_body.rb,v 1.160 2009-10-02 22:56:35 francis Exp $ +# -*- coding: utf-8 -*- require 'csv' require 'securerandom' require 'set' diff --git a/app/models/request_classification.rb b/app/models/request_classification.rb index 678b6cd16..f5a1b4bee 100644 --- a/app/models/request_classification.rb +++ b/app/models/request_classification.rb @@ -1,3 +1,15 @@ +# == Schema Information +# Schema version: 20120919140404 +# +# Table name: request_classifications +# +# id :integer not null, primary key +# user_id :integer +# info_request_event_id :integer +# created_at :datetime +# updated_at :datetime +# + class RequestClassification < ActiveRecord::Base belongs_to :user @@ -13,4 +25,4 @@ class RequestClassification < ActiveRecord::Base :include => :user) end -end
\ No newline at end of file +end diff --git a/app/models/user.rb b/app/models/user.rb index 657ea2a4a..bb1b54d70 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,5 @@ # == Schema Information +# Schema version: 20120919140404 # # Table name: users # @@ -21,13 +22,6 @@ # no_limit :boolean default(FALSE), not null # receive_email_alerts :boolean default(TRUE), not null # -# models/user.rb: -# Model of people who use the site to file requests, make comments etc. -# -# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. -# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ -# -# $Id: user.rb,v 1.106 2009-10-01 01:43:36 francis Exp $ require 'digest/sha1' diff --git a/app/views/admin_request/edit.rhtml b/app/views/admin_request/edit.rhtml index 808028b47..8fa2a1fe2 100644 --- a/app/views/admin_request/edit.rhtml +++ b/app/views/admin_request/edit.rhtml @@ -28,6 +28,10 @@ <br/>(don't forget to change 'awaiting description' when you set described state)<br/> </p> + <p><label for="info_request_comments_allowed"><strong>Are comments allowed?</strong></label> + <%= select('info_request', "comments_allowed", [["Yes – comments allowed", true], ["No – comments disabled", false]]) %> + </p> + <p><label for="info_request_tag_string"><strong>Tags</strong> <small>(space separated, can use key:value)</small></label><br/> <%= text_field 'info_request', 'tag_string', :size => 60 %></p> diff --git a/app/views/request/_after_actions.rhtml b/app/views/request/_after_actions.rhtml index 15ca6302e..580ff0e87 100644 --- a/app/views/request/_after_actions.rhtml +++ b/app/views/request/_after_actions.rhtml @@ -5,9 +5,11 @@ <div id="anyone_actions"> <strong><%= _('Anyone:') %></strong> <ul> - <li> - <%= _('<a href="%s">Add an annotation</a> (to help the requester or others)') % [new_comment_url(:url_title => @info_request.url_title)] %> - </li> + <% if @info_request.comments_allowed? %> + <li> + <%= _('<a href="%s">Add an annotation</a> (to help the requester or others)') % [new_comment_url(:url_title => @info_request.url_title)] %> + </li> + <% end %> <% if @old_unclassified %> <li> <%= link_to _('Update the status of this request'), '#describe_state_form_1' %> diff --git a/app/views/request/_sidebar.rhtml b/app/views/request/_sidebar.rhtml index 731bfb34e..dc0d2eb31 100644 --- a/app/views/request/_sidebar.rhtml +++ b/app/views/request/_sidebar.rhtml @@ -24,7 +24,7 @@ <% end %> <% 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> + <p><%= _('If you believe this request is not suitable, you can report it for attention by the site administrators') %></p> <%= link_to _("Report this request"), report_path, :class => "link_button_green", :method => "POST" %> <% end %> <% end %> @@ -32,11 +32,11 @@ <div class="act_link"> <% tweet_link = "https://twitter.com/share?url=#{h(request.url)}&via=#{h(MySociety::Config.get('TWITTER_USERNAME', ''))}&text='#{h(@info_request.title)}'&related=#{_('alaveteli_foi:The software that runs {{site_name}}', :site_name => h(site_name))}" %> - <%= link_to '<img src="/images/twitter-16.png" alt="twitter icon">', tweet_link %> - <%= link_to _("Tweet this request"), tweet_link %> + <%= link_to '<img src="/images/twitter-16.png" alt="twitter icon">', tweet_link %> + <%= link_to _("Tweet this request"), tweet_link %> </div> <div class="act_link"> - <%= link_to '<img src="/images/wordpress.png" alt="" class="rss">', "http://wordpress.com/"%> + <%= link_to '<img src="/images/wordpress.png" alt="" class="rss">', "http://wordpress.com/"%> <%= link_to _("Start your own blog"), "http://wordpress.com/"%> </div> diff --git a/app/views/track/_tracking_links.rhtml b/app/views/track/_tracking_links.rhtml index 39f346eff..3ba9d15e2 100644 --- a/app/views/track/_tracking_links.rhtml +++ b/app/views/track/_tracking_links.rhtml @@ -4,12 +4,12 @@ end %> -<% if own_request %> +<% if own_request %> <p><%= _('This is your own request, so you will be automatically emailed when new responses arrive.')%></p> -<% elsif existing_track %> +<% elsif existing_track %> <p><%= track_thing.params[:verb_on_page_already] %></p> <div class="feed_link feed_link_<%=location%>"> - <%= link_to "Unsubscribe", {:controller => 'track', :action => 'update', :track_id => existing_track.id, :track_medium => "delete", :r => request.request_uri}, :class => "link_button_green" %> + <%= link_to _("Unsubscribe"), {:controller => 'track', :action => 'update', :track_id => existing_track.id, :track_medium => "delete", :r => request.request_uri}, :class => "link_button_green" %> </div> <% elsif track_thing %> <div class="feed_link feed_link_<%=location%>"> @@ -19,9 +19,9 @@ <%= link_to _("Follow"), do_track_url(track_thing), :class => "link_button_green" %> <% end %> </div> - + <div class="feed_link feed_link_<%=location%>"> - <%= link_to '<img src="/images/feed-16.png" alt="">', do_track_url(track_thing, 'feed') %> + <%= link_to '<img src="/images/feed-16.png" alt="">', do_track_url(track_thing, 'feed') %> <%= link_to (location == 'sidebar' ? _('RSS feed of updates') : _('RSS feed')), do_track_url(track_thing, 'feed') %> </div> <% end %> diff --git a/config/alert-tracks-debian.ugly b/config/alert-tracks-debian.ugly index 5bd146061..2b52ad840 100644 --- a/config/alert-tracks-debian.ugly +++ b/config/alert-tracks-debian.ugly @@ -4,7 +4,7 @@ # Provides: alert-tracks # Required-Start: $local_fs $syslog # Required-Stop: $local_fs $syslog -# Default-Start: 2 3 4 5 +# Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: alert-tracks is a daemon running the Alaveteli email alerts # Description: alert-tracks send Alaveteli email alerts as required @@ -13,11 +13,14 @@ # !!(*= $daemon_name *)!! Start the Alaveteli email alert daemon NAME=!!(*= $daemon_name *)!! -DAEMON=/data/vhost/!!(*= $vhost *)!!/alaveteli/script/runner +DAEMON=!!(*= $vhost_dir *)!!/alaveteli/script/runner DAEMON_ARGS="--daemon TrackMailer.alert_tracks_loop" -PIDFILE=/data/vhost/!!(*= $vhost *)!!/alert-tracks.pid -LOGFILE=/data/vhost/!!(*= $vhost *)!!/logs/alert-tracks.log +PIDFILE=!!(*= $vhost_dir *)!!/alert-tracks.pid +LOGFILE=!!(*= $vhost_dir *)!!/logs/alert-tracks.log DUSER=!!(*= $user *)!! +# Set RAILS_ENV - not needed if using config/rails_env.rb +# RAILS_ENV=your_rails_env +# export RAILS_ENV trap "" 1 @@ -48,17 +51,17 @@ case "$1" in exit 0 fi ;; - + start) echo -n "Starting Alaveteli alert daemon: $NAME" start_daemon ;; - + stop) echo -n "Stopping Alaveteli alert daemon: $NAME" stop_daemon ;; - + restart) echo -n "Restarting Alaveteli alert daemon: $NAME" stop_daemon diff --git a/config/deploy.rb b/config/deploy.rb index 888710f83..f82379df0 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -48,6 +48,9 @@ namespace :deploy do links = { "#{release_path}/config/database.yml" => "#{shared_path}/database.yml", "#{release_path}/config/general.yml" => "#{shared_path}/general.yml", + "#{release_path}/config/rails_env.rb" => "#{shared_path}/rails_env.rb", + "#{release_path}/public/foi-live-creation.png" => "#{shared_path}/foi-live-creation.png", + "#{release_path}/public/foi-user-use.png" => "#{shared_path}/foi-user-use.png", "#{release_path}/files" => "#{shared_path}/files", "#{release_path}/cache" => "#{shared_path}/cache", "#{release_path}/vendor/plugins/acts_as_xapian/xapiandbs" => "#{shared_path}/xapiandbs", diff --git a/config/general.yml-example b/config/general.yml-example index a6f657d96..fd27b151a 100644 --- a/config/general.yml-example +++ b/config/general.yml-example @@ -30,6 +30,9 @@ REPLY_LATE_AFTER_DAYS: 20 REPLY_VERY_LATE_AFTER_DAYS: 40 # We give some types of authority like schools a bit longer than everyone else SPECIAL_REPLY_VERY_LATE_AFTER_DAYS: 60 +# Whether the days above are given in working or calendar days. Value can be "working" or "calendar". +# Default is "working". +WORKING_OR_CALENDAR_DAYS: working # example public bodies for the home page, semicolon delimited - short_names FRONTPAGE_PUBLICBODY_EXAMPLES: 'tgq' diff --git a/config/purge-varnish-debian.ugly b/config/purge-varnish-debian.ugly index 1a9259da8..af32650a8 100644 --- a/config/purge-varnish-debian.ugly +++ b/config/purge-varnish-debian.ugly @@ -4,7 +4,7 @@ # Provides: purge-varnish # Required-Start: $local_fs $syslog # Required-Stop: $local_fs $syslog -# Default-Start: 2 3 4 5 +# Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: purge-varnish is a daemon purging the Alaveteli varnish cache # Description: purge-varnish purge the Alaveteli varnish cache @@ -13,11 +13,14 @@ # !!(*= $daemon_name *)!! Start the Alaveteli email purge-varnish daemon NAME=!!(*= $daemon_name *)!! -DAEMON=/data/vhost/!!(*= $vhost *)!!/alaveteli/script/runner +DAEMON=!!(*= $vhost_dir *)!!/alaveteli/script/runner DAEMON_ARGS="--daemon PurgeRequest.purge_all_loop" -PIDFILE=/data/vhost/!!(*= $vhost *)!!/purge-varnish.pid -LOGFILE=/data/vhost/!!(*= $vhost *)!!/logs/purge-varnish.log +PIDFILE=!!(*= $vhost_dir *)!!/purge-varnish.pid +LOGFILE=!!(*= $vhost_dir *)!!/logs/purge-varnish.log DUSER=!!(*= $user *)!! +# Set RAILS_ENV - not needed if using config/rails_env.rb +# RAILS_ENV=your_rails_env +# export RAILS_ENV trap "" 1 @@ -48,17 +51,17 @@ case "$1" in exit 0 fi ;; - + start) echo -n "Starting Alaveteli purge-varnish daemon: $NAME" start_daemon ;; - + stop) echo -n "Stopping Alaveteli purge-varnish daemon: $NAME" stop_daemon ;; - + restart) echo -n "Restarting Alaveteli purge-varnish daemon: $NAME" stop_daemon diff --git a/db/migrate/20120919140404_add_comments_allowed_to_info_request.rb b/db/migrate/20120919140404_add_comments_allowed_to_info_request.rb new file mode 100644 index 000000000..4ae0bce18 --- /dev/null +++ b/db/migrate/20120919140404_add_comments_allowed_to_info_request.rb @@ -0,0 +1,9 @@ +class AddCommentsAllowedToInfoRequest < ActiveRecord::Migration + def self.up + add_column :info_requests, :comments_allowed, :boolean, :null => false, :default => true + end + + def self.down + remove_column :info_requests, :comments_allowed + end +end diff --git a/doc/INSTALL.md b/doc/INSTALL.md index 62c5071ca..b805ee0c5 100644 --- a/doc/INSTALL.md +++ b/doc/INSTALL.md @@ -25,6 +25,18 @@ master branch (which always contains the latest stable release): git checkout master +# Package pinning + +You need to configure [apt-pinning](http://wiki.debian.org/AptPreferences#Pinning-1) preferences in order to prevent packages being pulled from the debian testing distribution in preference to the stable distribution once you have added the testing repository as described below. + +In order to configure apt-pinning and to keep most packages coming from the Debian stable repository while installing the ones required from testing and the mySociety repository you need to run the following commands: + + echo "Package: *" >> /tmp/preferences + echo "Pin: release a=testing">> /tmp/preferences + echo "Pin-Priority: 50" >> /tmp/preferences + sudo cp /tmp/preferences /etc/apt/ + rm /tmp/preferences + # Install system dependencies These are packages that the software depends on: third-party software @@ -39,7 +51,7 @@ If you are running Debian, add the following repositories to deb http://ftp.debian.org/debian/ testing main non-free contrib The repositories above allow us to install the packages -`wkthmltopdf-static` and `bundler` using `apt`; so if you're running +`wkhtmltopdf-static` and `bundler` using `apt`; so if you're running Ubuntu, you won't be able to use the above repositories, and you will need to comment out those two lines in `config/packages` before following the next step (and install bundler manually). @@ -296,7 +308,7 @@ in the front end. It is possible completely to override the administrator authentication by setting `SKIP_ADMIN_AUTH` to `true` in `general.yml`. -# Cron jobs +# Cron jobs and init scripts `config/crontab.ugly` contains the cronjobs run on WhatDoTheyKnow. It's in a strange templating format they use in mySociety. mySociety @@ -311,6 +323,10 @@ like `!!(*= $this *)!!`. The variables are: `/data/vhost/!!(*= $vhost *)!!` -- you should replace that whole port with a path to the directory where your Alaveteli software installation lives, e.g. `/var/www/` +* `vhost_dir`: the entire path to the directory where the software is + served from. -- you should replace this with a path to the + directory where your Alaveteli software installation lives, + e.g. `/var/www/` * `vcspath`: the name of the alaveteli checkout, e.g. `alaveteli`. Thus, `/data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!` might be replaced with `/var/www/alaveteli` in your cron tab @@ -324,14 +340,22 @@ One of the cron jobs refers to a script at `/etc/init.d/foi-alert-tracks`. This is an init script, a copy of which lives in `config/alert-tracks-debian.ugly`. As with the cron jobs above, replace the variables (and/or bits near the variables) -with paths to your software. `config/purge-varnish-debian.ugly` is a +with paths to your software. You can use the rake task `rake +config_files:convert_init_script` to do this. +`config/purge-varnish-debian.ugly` is a similar init script, which is optional and not required if you choose -not to run your site behind Varnish (see below). +not to run your site behind Varnish (see below). Either tweak the file +permissions to make the scripts executable by your deploy user, or add the +following line to your sudoers file to allow these to be run by your deploy +user (named `deploy` in this case): + + deploy ALL = NOPASSWD: /etc/init.d/foi-alert-tracks, /etc/init.d/foi-purge-varnish The cron jobs refer to a program `run-with-lockfile`. See [this issue](https://github.com/mysociety/alaveteli/issues/112) for a discussion of where to find this program, and how you might replace -it. +it. This [one line script](https://gist.github.com/3741194) can install +this program system-wide. # Set up production web server diff --git a/doc/THEMES.md b/doc/THEMES.md index 6c22764fc..c5e4a3eee 100644 --- a/doc/THEMES.md +++ b/doc/THEMES.md @@ -123,7 +123,7 @@ do this in the `alavetelitheme`. To do add states, create two modules in your theme, `InfoRequestCustomStates` and `RequestControllerCustomStates`. The -former must have these two methods: +former must have these methods: * `theme_calculate_status`: return a tag to identify the current state of the request * `theme_extra_states`: return a list of tags which identify the extra states you'd like to support diff --git a/lib/tasks/config_files.rake b/lib/tasks/config_files.rake new file mode 100644 index 000000000..1dcdde79a --- /dev/null +++ b/lib/tasks/config_files.rake @@ -0,0 +1,76 @@ +namespace :config_files do + + def usage_message message + puts '' + puts message + puts '' + exit 0 + end + + def check_for_env_vars(env_vars, example) + missing = [] + env_vars.each do |env_var| + unless ENV[env_var] + missing << env_var + end + end + if !missing.empty? + usage = "Usage: This task requires #{env_vars.to_sentence} - missing #{missing.to_sentence}" + if example + usage += "\nExample: #{example}" + end + usage_message usage + end + end + + def convert_ugly(file, replacements) + converted_lines = [] + ugly_var = /\!\!\(\*= \$([^ ]+) \*\)\!\!/ + File.open(file, 'r').each do |line| + line = line.gsub(ugly_var) do |match| + var = $1.to_sym + replacement = replacements[var] + if replacement == nil + if ! (skip[var] == true) + raise "Unhandled variable in .ugly file: $#{var}" + else + match + end + else + replacements[var] + end + end + converted_lines << line + end + converted_lines + end + + desc 'Convert Debian .ugly init script in config to a form suitable for installing in /etc/init.d' + task :convert_init_script => :environment do + example = 'rake config_files:convert_init_script DEPLOY_USER=deploy VHOST_DIR=/dir/above/alaveteli SCRIPT_FILE=config/alert-tracks-debian.ugly ' + check_for_env_vars(['DEPLOY_USER', 'VHOST_DIR', 'SCRIPT_FILE'], example) + + deploy_user = ENV['DEPLOY_USER'] + vhost_dir = ENV['VHOST_DIR'] + script_file = ENV['SCRIPT_FILE'] + + replacements = { :user => deploy_user, + :vhost_dir => vhost_dir } + + daemon_name = File.basename(script_file, '-debian.ugly') + replacements.update(:daemon_name => "foi-#{daemon_name}") + converted = convert_ugly(script_file, replacements) + rails_env_file = File.expand_path(File.join(Rails.root, 'config', 'rails_env.rb')) + if !File.exists?(rails_env_file) + converted.each do |line| + line.gsub!(/^#\s*RAILS_ENV=your_rails_env/, "RAILS_ENV=#{Rails.env}") + line.gsub!(/^#\s*export RAILS_ENV/, "export RAILS_ENV") + end + end + converted.each do |line| + puts line + end + end + + +end
\ No newline at end of file diff --git a/locale/cs/app.po b/locale/cs/app.po index 2bd0e61ad..e9f50dc19 100644 --- a/locale/cs/app.po +++ b/locale/cs/app.po @@ -12,7 +12,7 @@ msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" "POT-Creation-Date: 2012-09-19 09:37+0100\n" -"PO-Revision-Date: 2012-09-19 08:48+0000\n" +"PO-Revision-Date: 2012-09-24 15:30+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -1065,7 +1065,7 @@ msgid "Freedom of Information" msgstr "Svobodný přístup k informacím" msgid "Freedom of Information Act" -msgstr "Zákon o svobodném přístupu k informacím" +msgstr "zákona č. 106/1999 Sb." msgid "" "Freedom of Information law does not apply to this authority, so you cannot make\n" @@ -3639,7 +3639,7 @@ msgid "sign in" msgstr "přihlásit se" msgid "simple_date_format" -msgstr "simple_date_format ??" +msgstr "simple_date_format" msgid "successful" msgstr "úspěšné" @@ -3714,7 +3714,7 @@ msgid "{{info_request_user_name}} only:" msgstr "Pouze {{info_request_user_name}}:" msgid "{{law_used_full}} request - {{title}}" -msgstr "{{law_used_full}} dotaz - {{title}}" +msgstr "Dotaz podle {{law_used_full}} - {{title}}" msgid "{{law_used_full}} request GQ - {{title}}" msgstr "{{law_used_full}} žádejte GQ - {{title}} ??" diff --git a/spec/controllers/comment_controller_spec.rb b/spec/controllers/comment_controller_spec.rb index b71bc0aea..4a7acee23 100644 --- a/spec/controllers/comment_controller_spec.rb +++ b/spec/controllers/comment_controller_spec.rb @@ -53,6 +53,17 @@ describe CommentController, "when commenting on a request" do response.should render_template('new') end + + it "should not allow comments if comments are not allowed" do + session[:user_id] = users(:silly_name_user).id + + expect { + post :new, :url_title => info_requests(:spam_1_request).url_title, + :comment => { :body => "I demand to be heard!" }, + :type => 'request', :submitted_comment => 1, :preview => 0 + }.to raise_error("Comments are not allowed on this request") + + end describe 'when commenting on an external request' do diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 95737a250..77f43b618 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -238,6 +238,22 @@ describe RequestController, "when showing one request" do response.should have_tag('div#owner_actions') end + describe 'when the request does allow comments' do + it 'should have a comment link' do + get :show, { :url_title => 'why_do_you_have_such_a_fancy_dog' }, + { :user_id => users(:admin_user).id } + response.should have_tag('#anyone_actions', /Add an annotation/) + end + end + + describe 'when the request does not allow comments' do + it 'should not have a comment link' do + get :show, { :url_title => 'spam_1' }, + { :user_id => users(:admin_user).id } + response.should_not have_tag('#anyone_actions', /Add an annotation/) + end + end + describe 'when the request is being viewed by an admin' do describe 'if the request is awaiting description' do diff --git a/spec/fixtures/info_requests.yml b/spec/fixtures/info_requests.yml index 079a44cd0..9361ec486 100644 --- a/spec/fixtures/info_requests.yml +++ b/spec/fixtures/info_requests.yml @@ -8,6 +8,7 @@ fancy_dog_request: user_id: 1 described_state: waiting_response awaiting_description: true + comments_allowed: true idhash: 50929748 naughty_chicken_request: id: 103 @@ -19,6 +20,7 @@ naughty_chicken_request: user_id: 1 described_state: waiting_response awaiting_description: false + comments_allowed: true idhash: e8d18c84 badger_request: id: 104 @@ -30,6 +32,7 @@ badger_request: user_id: 1 described_state: waiting_response awaiting_description: false + comments_allowed: true idhash: e8d18c84 boring_request: id: 105 @@ -41,6 +44,7 @@ boring_request: user_id: 1 described_state: successful awaiting_description: false + comments_allowed: true idhash: 173fd003 another_boring_request: id: 106 @@ -52,6 +56,7 @@ another_boring_request: user_id: 1 described_state: successful awaiting_description: false + comments_allowed: true idhash: 173fd004 # A pair of identical requests (with url_title differing only in the numeric suffix) @@ -66,6 +71,7 @@ spam_1_request: user_id: 5 described_state: successful awaiting_description: false + comments_allowed: false idhash: 173fd005 spam_2_request: id: 108 @@ -77,6 +83,7 @@ spam_2_request: user_id: 5 described_state: successful awaiting_description: false + comments_allowed: true idhash: 173fd005 external_request: id: 109 @@ -87,6 +94,7 @@ external_request: public_body_id: 2 described_state: waiting_response awaiting_description: false + comments_allowed: true idhash: a1234567 anonymous_external_request: id: 110 @@ -97,4 +105,5 @@ anonymous_external_request: public_body_id: 2 described_state: waiting_response awaiting_description: false - idhash: 7654321a
\ No newline at end of file + comments_allowed: true + idhash: 7654321a diff --git a/spec/models/application_mailer_spec.rb b/spec/models/application_mailer_spec.rb index 12527c6e8..11fdd2889 100644 --- a/spec/models/application_mailer_spec.rb +++ b/spec/models/application_mailer_spec.rb @@ -1,8 +1,161 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -describe ApplicationMailer, " when blah" do - before do + +describe ApplicationMailer do + + context 'when using plugins' do + + def set_base_views + ApplicationMailer.class_eval do + @previous_view_paths = self.view_paths.dup + self.view_paths.clear + self.view_paths << File.join(Rails.root, 'spec', 'fixtures', 'theme_views', 'core') + end + end + + def add_mail_methods(method_names) + method_names.each{ |method_name| ApplicationMailer.send(:define_method, method_name){} } + end + + def remove_mail_methods(method_names) + method_names.each do |method_name| + if ApplicationMailer.respond_to?(method_name) + ApplicationMailer.send(:remove_method, method_name) + end + end + end + + def prepend_theme_views(theme_name) + ApplicationMailer.class_eval do + view_paths.unshift File.join(Rails.root, 'spec', 'fixtures', 'theme_views', theme_name) + end + end + + def append_theme_views(theme_name) + ApplicationMailer.class_eval do + view_paths << File.join(Rails.root, 'spec', 'fixtures', 'theme_views', theme_name) + end + end + + def reset_views + ApplicationMailer.class_eval do + self.view_paths = @previous_view_paths + end + end + + def create_multipart_method(method_name) + ApplicationMailer.send(:define_method, method_name) do + puts "in multipart" + attachment :content_type => 'message/rfc822', + :body => 'xxx', + :filename => "original.eml", + :transfer_encoding => '7bit', + :content_disposition => 'inline' + end + end + + before do + set_base_views + add_mail_methods(['simple', 'theme_only', 'core_only', 'neither']) + end + + describe 'when a plugin prepends its mail templates to the view paths' do + + it 'should render a theme template in preference to a core template' do + prepend_theme_views('theme_one') + @mail = ApplicationMailer.create_simple() + @mail.body.should match('Theme simple') + end + + it 'should render the template provided by the theme if no template is available in core' do + prepend_theme_views('theme_one') + @mail = ApplicationMailer.create_theme_only() + @mail.body.should match('Theme only') + end + + it 'should render the template provided by core if there is no theme template' do + prepend_theme_views('theme_one') + @mail = ApplicationMailer.create_core_only() + @mail.body.should match('Core only') + end + + it 'should raise an error if the template is in neither core nor theme' do + prepend_theme_views('theme_one') + lambda{ ApplicationMailer.create_neither() }.should raise_error('Missing template application_mailer/neither.erb in view path spec/fixtures/theme_views/theme_one:spec/fixtures/theme_views/core') + end + + it 'should render a multipart email using a theme template' do + prepend_theme_views('theme_one') + create_multipart_method('multipart_theme_only') + @mail = ApplicationMailer.create_multipart_theme_only() + @mail.parts.size.should == 2 + message_part = @mail.parts[0].to_s + message_part.should match("Theme multipart") + end + + it 'should render a multipart email using a core template' do + prepend_theme_views('theme_one') + create_multipart_method('multipart_core_only') + @mail = ApplicationMailer.create_multipart_core_only() + @mail.parts.size.should == 2 + message_part = @mail.parts[0].to_s + message_part.should match("Core multipart") + end + + end + + describe 'when a plugin appends its mail templates to the view paths' do + + it 'should render a core template in preference to a theme template' do + append_theme_views('theme_one') + @mail = ApplicationMailer.create_simple() + @mail.body.should match('Core simple') + end + + it 'should render the template provided by the theme if no template is available in core' do + append_theme_views('theme_one') + @mail = ApplicationMailer.create_theme_only() + @mail.body.should match('Theme only') + end + + it 'should render the template provided by core if there is no theme template' do + append_theme_views('theme_one') + @mail = ApplicationMailer.create_core_only() + @mail.body.should match('Core only') + end + + it 'should raise an error if the template is in neither core nor theme' do + append_theme_views('theme_one') + lambda{ ApplicationMailer.create_neither() }.should raise_error('Missing template application_mailer/neither.erb in view path spec/fixtures/theme_views/core:spec/fixtures/theme_views/theme_one') + end + + it 'should render a multipart email using a core template' do + append_theme_views('theme_one') + create_multipart_method('multipart_core_only') + @mail = ApplicationMailer.create_multipart_core_only() + @mail.parts.size.should == 2 + message_part = @mail.parts[0].to_s + message_part.should match("Core multipart") + end + + it 'should render a multipart email using a theme template' do + append_theme_views('theme_one') + create_multipart_method('multipart_theme_only') + @mail = ApplicationMailer.create_multipart_theme_only() + @mail.parts.size.should == 2 + message_part = @mail.parts[0].to_s + message_part.should match("Theme multipart") + end + + end + + after do + reset_views + remove_mail_methods(['simple', 'theme_only', 'core_only', 'neither', 'multipart']) + end end + end + diff --git a/spec/models/customstates.rb b/spec/models/customstates.rb index 3488e6730..bffbe86fb 100644 --- a/spec/models/customstates.rb +++ b/spec/models/customstates.rb @@ -13,7 +13,7 @@ module InfoRequestCustomStates return 'deadline_extended' if Time.now.strftime("%Y-%m-%d") < self.date_deadline_extended.strftime("%Y-%m-%d") return 'waiting_response_very_overdue' if - Time.now.strftime("%Y-%m-%d") > Holiday.due_date_from(self.date_deadline_extended, 15).strftime("%Y-%m-%d") + Time.now.strftime("%Y-%m-%d") > Holiday.due_date_from_working_days(self.date_deadline_extended, 15).strftime("%Y-%m-%d") return 'waiting_response_overdue' end return 'waiting_response_very_overdue' if @@ -27,7 +27,7 @@ module InfoRequestCustomStates # XXX shouldn't this be 15 days after the date the status was # changed to "deadline extended"? Or perhaps 15 days ater the # initial request due date? - return Holiday.due_date_from(self.date_response_required_by, 15) + return Holiday.due_date_from_working_days(self.date_response_required_by, 15) end module ClassMethods diff --git a/spec/models/holiday_spec.rb b/spec/models/holiday_spec.rb index 00ebc7279..5d3f76d24 100644 --- a/spec/models/holiday_spec.rb +++ b/spec/models/holiday_spec.rb @@ -3,47 +3,84 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe Holiday, " when calculating due date" do def due_date(ymd) - return Holiday.due_date_from(Date.strptime(ymd), 20).strftime("%F") + return Holiday.due_date_from_working_days(Date.strptime(ymd), 20).strftime("%F") end - it "handles no holidays" do - due_date('2008-10-01').should == '2008-10-29' - end + context "in working days" do + it "handles no holidays" do + due_date('2008-10-01').should == '2008-10-29' + end - it "handles non leap years" do - due_date('2007-02-01').should == '2007-03-01' - end + it "handles non leap years" do + due_date('2007-02-01').should == '2007-03-01' + end - it "handles leap years" do - due_date('2008-02-01').should == '2008-02-29' - end + it "handles leap years" do + due_date('2008-02-01').should == '2008-02-29' + end - it "handles Thursday start" do - due_date('2009-03-12').should == '2009-04-14' - end + it "handles Thursday start" do + due_date('2009-03-12').should == '2009-04-14' + end - it "handles Friday start" do - due_date('2009-03-13').should == '2009-04-15' - end + it "handles Friday start" do + due_date('2009-03-13').should == '2009-04-15' + end - # Delivery at the weekend ends up the same due day as if it had arrived on - # the Friday before. This is because the next working day (Monday) counts - # as day 1. - # See http://www.whatdotheyknow.com/help/officers#days - it "handles Saturday start" do - due_date('2009-03-14').should == '2009-04-15' - end - it "handles Sunday start" do - due_date('2009-03-15').should == '2009-04-15' - end + # Delivery at the weekend ends up the same due day as if it had arrived on + # the Friday before. This is because the next working day (Monday) counts + # as day 1. + # See http://www.whatdotheyknow.com/help/officers#days + it "handles Saturday start" do + due_date('2009-03-14').should == '2009-04-15' + end + it "handles Sunday start" do + due_date('2009-03-15').should == '2009-04-15' + end - it "handles Monday start" do - due_date('2009-03-16').should == '2009-04-16' - end + it "handles Monday start" do + due_date('2009-03-16').should == '2009-04-16' + end - it "handles Time objects" do - Holiday.due_date_from(Time.utc(2009, 03, 16, 12, 0, 0), 20).strftime('%F').should == '2009-04-16' + it "handles Time objects" do + Holiday.due_date_from_working_days(Time.utc(2009, 03, 16, 12, 0, 0), 20).strftime('%F').should == '2009-04-16' + end end + context "in calendar days" do + it "handles no holidays" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 1), 20).should == Date.new(2008, 10, 21) + end + + it "handles the due date falling on a Friday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 4), 20).should == Date.new(2008, 10, 24) + end + + # If the due date would fall on a Saturday it should in fact fall on the next day that isn't a weekend + # or a holiday + it "handles the due date falling on a Saturday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 5), 20).should == Date.new(2008, 10, 27) + end + + it "handles the due date falling on a Sunday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 6), 20).should == Date.new(2008, 10, 27) + end + + it "handles the due date falling on a Monday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 7), 20).should == Date.new(2008, 10, 27) + end + + it "handles the due date falling on a day before a Holiday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 12, 4), 20).should == Date.new(2008, 12, 24) + end + + it "handles the due date falling on a Holiday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 12, 5), 20).should == Date.new(2008, 12, 29) + end + + it "handles Time objects" do + Holiday.due_date_from_calendar_days(Time.utc(2009, 03, 17, 12, 0, 0), 20).should == Date.new(2009, 4, 6) + end + end end diff --git a/spec/models/request_mailer_spec.rb b/spec/models/request_mailer_spec.rb index 98681a9e9..eec362ad3 100644 --- a/spec/models/request_mailer_spec.rb +++ b/spec/models/request_mailer_spec.rb @@ -97,10 +97,12 @@ describe RequestMailer, " when receiving incoming mail" do # check attached bounce is good copy of incoming-request-plain.email mail.multipart?.should == true mail.parts.size.should == 2 + message_part = mail.parts[0].to_s bounced_mail = TMail::Mail.parse(mail.parts[1].body) bounced_mail.to.should == [ ir.incoming_email ] bounced_mail.from.should == [ 'geraldinequango@localhost' ] - bounced_mail.body.include?("That's so totally a rubbish question") + bounced_mail.body.include?("That's so totally a rubbish question").should be_true + message_part.include?("marked to no longer receive responses").should be_true deliveries.clear end @@ -324,3 +326,4 @@ describe RequestMailer, 'when sending mail when someone has updated an old uncla end end + diff --git a/spec/views/request/_after_actions.rhtml_spec.rb b/spec/views/request/_after_actions.rhtml_spec.rb index d04db3fc2..5b4734c52 100644 --- a/spec/views/request/_after_actions.rhtml_spec.rb +++ b/spec/views/request/_after_actions.rhtml_spec.rb @@ -1,85 +1,86 @@ require File.expand_path(File.join('..', '..', '..', 'spec_helper'), __FILE__) -describe 'when displaying actions that can be taken with regard to a request' do - - before do - @mock_body = mock_model(PublicBody, :name => 'test public body', +describe 'when displaying actions that can be taken with regard to a request' do + + before do + @mock_body = mock_model(PublicBody, :name => 'test public body', :url_name => 'test_public_body') - @mock_user = mock_model(User, :name => 'test user', + @mock_user = mock_model(User, :name => 'test user', :url_name => 'test_user') - @mock_request = mock_model(InfoRequest, :title => 'test request', - :user => @mock_user, - :user_name => @mock_user.name, + @mock_request = mock_model(InfoRequest, :title => 'test request', + :user => @mock_user, + :user_name => @mock_user.name, :is_external? => false, - :public_body => @mock_body, + :public_body => @mock_body, + :comments_allowed? => true, :url_title => 'test_request') assigns[:info_request] = @mock_request end - + def do_render render :partial => 'request/after_actions' end - + def expect_owner_div do_render response.should have_tag('div#owner_actions'){ yield } end - + def expect_anyone_div do_render response.should have_tag('div#anyone_actions'){ yield } end - + def expect_owner_link(text) expect_owner_div{ with_tag('a', :text => text) } end - + def expect_no_owner_link(text) expect_owner_div{ without_tag('a', :text => text) } end - + def expect_anyone_link(text) expect_anyone_div{ with_tag('a', :text => text) } end - + def expect_no_anyone_link(text) expect_anyone_div{ without_tag('a', :text => text) } end - - describe 'if the request is old and unclassified' do - - before do + + describe 'if the request is old and unclassified' do + + before do assigns[:old_unclassified] = true end - - it 'should not display a link for the request owner to update the status of the request' do + + it 'should not display a link for the request owner to update the status of the request' do expect_no_owner_link('Update the status of this request') end - - it 'should display a link for anyone to update the status of the request' do + + it 'should display a link for anyone to update the status of the request' do expect_anyone_link('Update the status of this request') end - + end - - describe 'if the request is not old and unclassified' do - - before do + + describe 'if the request is not old and unclassified' do + + before do assigns[:old_unclassified] = false end - - it 'should display a link for the request owner to update the status of the request' do + + it 'should display a link for the request owner to update the status of the request' do expect_owner_link('Update the status of this request') end - - it 'should not display a link for anyone to update the status of the request' do + + it 'should not display a link for anyone to update the status of the request' do expect_no_anyone_link('Update the status of this request') end - + end it 'should display a link for the request owner to request a review' do expect_owner_link('Request an internal review') end - + end |