diff options
61 files changed, 905 insertions, 389 deletions
diff --git a/.gitignore b/.gitignore index 537a7abf2..a4ec2380e 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ webrat.log /db/development_structure.sql /db/structure.sql /public/assets +.vagrant diff --git a/Gemfile.lock b/Gemfile.lock index c3f994a51..81afea141 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -162,7 +162,7 @@ GEM rack (>= 0.4) rack-protection (1.5.0) rack - rack-ssl (1.3.3) + rack-ssl (1.3.4) rack rack-test (0.6.2) rack (>= 1.0) diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 000000000..dcdf1f433 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,87 @@ +# Welcome! Thanks for taking an interest in contributing to Alaveteli. +# This Vagrantfile should get you started with the minimum of fuss. +# +# Usage +# ===== +# +# Get a copy of Alaveteli from GitHub and create the Vagrant instance +# +# # Host +# $ git clone git@github.com:mysociety/alaveteli.git +# $ cd alaveteli +# $ git submodule update --init +# $ vagrant --no-color up +# +# You should now be able to ssh in to the guest and run the test suite +# +# # Host +# $ vagrant ssh +# +# # Guest +# $ cd /home/vagrant/alaveteli +# $ bundle exec rake spec +# +# Run the rails server and visit the application in your host browser +# at http://10.10.10.30:3000 +# +# # Guest +# bundle exec rails s +# +# Customizing the Vagrant instance +# ================================ +# +# This Vagrantfile allows customisation of some aspects of the virtaual machine +# See the customization options below for details. +# +# The options can be set either by prefixing the vagrant command, or by +# exporting to the environment. +# +# # Prefixing the command +# $ ALAVETELI_MEMORY=2048 vagrant up +# +# # Exporting to the environment +# $ export ALAVETELI_MEMORY=2048 +# $ vagrant up +# +# Both have the same effect, but exporting will retain the variable for the +# duration of your shell session. +# +# Customization Options +# ===================== +ALAVETELI_FQDN = ENV['ALAVETELI_VAGRANT_FQDN'] || "alaveteli.10.10.10.30.xip.io" +ALAVETELI_MEMORY = ENV['ALAVETELI_VAGRANT_MEMORY'] || 1536 +ALAVETELI_THEMES_DIR = ENV['ALAVETELI_THEMES_DIR'] || '../alaveteli-themes' + +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = "precise64" + config.vm.box_url = "http://files.vagrantup.com/precise64.box" + config.vm.network :private_network, :ip => "10.10.10.30" + + config.vm.synced_folder ".", "/home/vagrant/alaveteli", :owner => "vagrant", :group => "vagrant" + + if File.directory?(ALAVETELI_THEMES_DIR) + config.vm.synced_folder ALAVETELI_THEMES_DIR, + "/home/vagrant/alaveteli-themes", + :owner => "vagrant", + :group => "vagrant" + end + + config.ssh.forward_agent = true + + # The bundle install fails unless you have quite a large amount of + # memory; insist on 1.5GiB: + config.vm.provider "virtualbox" do |vb| + vb.customize ["modifyvm", :id, "--memory", ALAVETELI_MEMORY] + end + + # Fetch and run the install script: + config.vm.provision :shell, :inline => "wget -O install-site.sh https://raw.github.com/mysociety/commonlib/master/bin/install-site.sh" + config.vm.provision :shell, :inline => "chmod a+rx install-site.sh" + config.vm.provision :shell, :inline => "./install-site.sh " \ + "--dev " \ + "alaveteli " \ + "vagrant " \ + "#{ ALAVETELI_FQDN }" +end diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index d8aed6346..1b6c98535 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -1,6 +1,7 @@ // ... //= require jquery //= require jquery.ui.datepicker +//= require jquery.ui.position //= require jquery.cookie //= require general //= require ba-throttle-debounce diff --git a/app/assets/javascripts/general.js b/app/assets/javascripts/general.js index 529bbeb04..002eef760 100644 --- a/app/assets/javascripts/general.js +++ b/app/assets/javascripts/general.js @@ -27,8 +27,8 @@ $(document).ready(function() { return false; }); - // "link to this" widget - $('a.link_to_this').click(function() { + // "link to this" widget + $('a.link_to_this').click(function() { var box = $('div#link_box'); var location = window.location.protocol + "//" + window.location.hostname + $(this).attr('href'); box.width(location.length + " em"); @@ -36,12 +36,12 @@ $(document).ready(function() { box.show(); box.find('input').select(); box.position({ - my: "left top", + my: "right center", at: "left bottom", of: this, collision: "fit" }); return false; - }); + }); $('.close-button').click(function() { $(this).parent().hide() }); $('div#variety-filter a').each(function() { diff --git a/app/controllers/admin_user_controller.rb b/app/controllers/admin_user_controller.rb index 940a5fe8f..a6438e151 100644 --- a/app/controllers/admin_user_controller.rb +++ b/app/controllers/admin_user_controller.rb @@ -99,6 +99,12 @@ class AdminUserController < AdminController redirect_to admin_user_show_url(@admin_user) end + def modify_comment_visibility + @visibility_value = params.key?(:hide_selected) ? false : true + Comment.update_all(["visible=?", @visibility_value], :id => params[:comment_ids]) + redirect_to :back + end + private end diff --git a/app/controllers/comment_controller.rb b/app/controllers/comment_controller.rb index cda56a211..5e39c3a2c 100644 --- a/app/controllers/comment_controller.rb +++ b/app/controllers/comment_controller.rb @@ -6,34 +6,18 @@ class CommentController < ApplicationController before_filter :check_read_only, :only => [ :new ] + before_filter :find_info_request, :only => [ :new ] + before_filter :create_track_thing, :only => [ :new ] + before_filter :reject_unless_comments_allowed, :only => [ :new ] + before_filter :reject_if_user_banned, :only => [ :new ] protect_from_forgery :only => [ :new ] def new - if params[:type] == 'request' - @info_request = InfoRequest.find_by_url_title!(params[:url_title]) - @track_thing = TrackThing.create_track_for_request(@info_request) - if params[:comment] - @comment = Comment.new(params[:comment].merge({ - :comment_type => 'request', - :user => @user - })) - end - 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? - @details = authenticated_user.can_fail_html - render :template => 'user/banned' - return + if params[:comment] + @comment = Comment.new(params[:comment].merge({ + :comment_type => 'request', + :user => @user + })) end if params[:comment] @@ -92,5 +76,36 @@ class CommentController < ApplicationController end end -end + private + def find_info_request + if params[:type] == 'request' + @info_request = InfoRequest.find_by_url_title!(params[:url_title]) + else + raise "Unknown type #{ params[:type] }" + end + end + + def create_track_thing + @track_thing = TrackThing.create_track_for_request(@info_request) + 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 + def reject_unless_comments_allowed + unless @info_request.comments_allowed? + redirect_to request_url(@info_request), :notice => "Comments are not allowed on this request" + end + end + + # Banned from adding comments? + def reject_if_user_banned + if authenticated_user && !authenticated_user.can_make_comments? + @details = authenticated_user.can_fail_html + render :template => 'user/banned' + end + end + +end diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 9959df6d8..9033198a0 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -9,6 +9,7 @@ class HelpController < ApplicationController # we don't even have a control subroutine for most help pages, just see their templates before_filter :long_cache + before_filter :catch_spam, :only => [:contact] def unhappy @info_request = nil @@ -69,4 +70,12 @@ class HelpController < ApplicationController end + private + + def catch_spam + if request.post? && !params[:contact][:comment].empty? + redirect_to frontpage_url + end + end + end diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index a94461758..6445dd685 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -447,9 +447,9 @@ class RequestController < ApplicationController flash[:notice] = case info_request.calculate_status when 'waiting_response' _("<p>Thank you! Hopefully your wait isn't too long.</p> <p>By law, you should get a response promptly, and normally before the end of <strong> -{{date_response_required_by}}</strong>.</p>",:date_response_required_by=>simple_date(info_request.date_response_required_by)) +{{date_response_required_by}}</strong>.</p>",:date_response_required_by=>view_context.simple_date(info_request.date_response_required_by)) when 'waiting_response_overdue' - _("<p>Thank you! Hope you don't have to wait much longer.</p> <p>By law, you should have got a response promptly, and normally before the end of <strong>{{date_response_required_by}}</strong>.</p>",:date_response_required_by=>simple_date(info_request.date_response_required_by)) + _("<p>Thank you! Hope you don't have to wait much longer.</p> <p>By law, you should have got a response promptly, and normally before the end of <strong>{{date_response_required_by}}</strong>.</p>",:date_response_required_by=>view_context.simple_date(info_request.date_response_required_by)) when 'waiting_response_very_overdue' _("<p>Thank you! Your request is long overdue, by more than {{very_late_number_of_days}} working days. Most requests should be answered within {{late_number_of_days}} working days. You might like to complain about this, see below.</p>", :very_late_number_of_days => AlaveteliConfiguration::reply_very_late_after_days, :late_number_of_days => AlaveteliConfiguration::reply_late_after_days) when 'not_held' diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 78c494dba..97c47c448 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -17,8 +17,15 @@ class ServicesController < ApplicationController text = _("Hello! You can make Freedom of Information requests within {{country_name}} at {{link_to_website}}", :country_name => found_country[:country_name], :link_to_website => "<a href=\"#{found_country[:url]}\">#{found_country[:name]}</a>".html_safe) else - current_country = WorldFOIWebsites.by_code(iso_country_code)[:country_name] - text = _("Hello! We have an <a href=\"/help/alaveteli?country_name=#{CGI.escape(current_country)}\">important message</a> for visitors outside {{country_name}}", :country_name => current_country) + country_data = WorldFOIWebsites.by_code(iso_country_code) + if country_data + text = _("Hello! We have an <a href=\"{{url}}\">important message</a> for visitors outside {{country_name}}", + :country_name => country_data[:country_name], + :url => "/help/alaveteli?country_name=#{CGI.escape(country_data[:country_name])}") + else + text = _("Hello! We have an <a href=\"{{url}}\">important message</a> for visitors in other countries", + :url => "/help/alaveteli") + end end ensure FastGettext.locale = old_fgt_locale diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb index 059cebdfa..151e53758 100644 --- a/app/helpers/admin_helper.rb +++ b/app/helpers/admin_helper.rb @@ -33,5 +33,10 @@ module AdminHelper link_to(eye, user_path(user), :title => "view user's page on public website") + " " + link_to(h(user.name), admin_user_show_path(user), :title => "view full details") end + + def comment_visibility(comment) + comment.visible? ? 'Visible' : 'Hidden' + end + end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 154697377..33525cb3d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -136,5 +136,47 @@ module ApplicationHelper nil end end + + def event_description(event) + body_link = public_body_link_absolute(event.info_request.public_body) + user_link = request_user_link_absolute(event.info_request) + date = simple_date(event.created_at) + case event.event_type + when 'sent' + _('Request sent to {{public_body_name}} by {{info_request_user}} on {{date}}.', + :public_body_name => body_link, + :info_request_user => user_link, + :date => date) + when 'followup_sent' + case event.calculated_state + when 'internal_review' + _('Internal review request sent to {{public_body_name}} by {{info_request_user}} on {{date}}.', + :public_body_name => body_link, + :info_request_user => user_link, + :date => date) + when 'waiting_response' + _('Clarification sent to {{public_body_name}} by {{info_request_user}} on {{date}}.', + :public_body_name => body_link, + :info_request_user => user_link, + :date => date) + else + _('Follow up sent to {{public_body_name}} by {{info_request_user}} on {{date}}.', + :public_body_name => body_link, + :info_request_user => user_link, + :date => date) + end + when 'response' + _('Response by {{public_body_name}} to {{info_request_user}} on {{date}}.', + :public_body_name => body_link, + :info_request_user => user_link, + :date => date) + when 'comment' + _('Request to {{public_body_name}} by {{info_request_user}}. Annotated by {{event_comment_user}} on {{date}}.', + :public_body_name => body_link, + :info_request_user => user_link, + :event_comment_user => user_link_absolute(event.comment.user), + :date => date) + end + end end diff --git a/app/helpers/link_to_helper.rb b/app/helpers/link_to_helper.rb index 50ed3c339..dd6ffa805 100755 --- a/app/helpers/link_to_helper.rb +++ b/app/helpers/link_to_helper.rb @@ -279,13 +279,58 @@ module LinkToHelper end end - # Basic date format - def simple_date(date) + # Public: Usually-correct format for a DateTime-ish object + # To define a new new format define the `simple_date_{FORMAT}` method + # + # date - a DateTime, Date or Time + # opts - a Hash of options (default: { format: :html}) + # :format - :html returns a HTML <time> tag + # :text returns a plain String + # + # Examples + # + # simple_date(Time.now) + # # => "<time>..." + # + # simple_date(Time.now, :format => :text) + # # => "March 10, 2014" + # + # Returns a String + # Raises ArgumentError if the format is unrecognized + def simple_date(date, opts = {}) + opts = { :format => :html }.merge(opts) + date_formatter = "simple_date_#{ opts[:format] }" + + if respond_to?(date_formatter) + send(date_formatter, date) + else + raise ArgumentError, "Unrecognised format :#{ opts[:format] }" + end + end + + # Usually-correct HTML formatting of a DateTime-ish object + # Use LinkToHelper#simple_date with desired formatting options + # + # date - a DateTime, Date or Time + # + # Returns a String + def simple_date_html(date) + date = date.in_time_zone unless date.is_a? Date + time_tag date, simple_date_text(date), :title => date.to_s + end + + # Usually-correct plain text formatting of a DateTime-ish object + # Use LinkToHelper#simple_date with desired formatting options + # + # date - a DateTime, Date or Time + # + # Returns a String + def simple_date_text(date) date = date.in_time_zone.to_date unless date.is_a? Date date_format = _("simple_date_format") date_format = :long if date_format == "simple_date_format" - return I18n.l(date, :format => date_format) + I18n.l(date, :format => date_format) end def simple_time(date) diff --git a/app/models/contact_validator.rb b/app/models/contact_validator.rb index 65e539669..e9a6e491c 100644 --- a/app/models/contact_validator.rb +++ b/app/models/contact_validator.rb @@ -7,7 +7,7 @@ class ContactValidator include ActiveModel::Validations - attr_accessor :name, :email, :subject, :message + attr_accessor :name, :email, :subject, :message, :comment validates_presence_of :name, :message => N_("Please enter your name") validates_presence_of :email, :message => N_("Please enter your email address") diff --git a/app/views/admin_request/_some_annotations.html.erb b/app/views/admin_request/_some_annotations.html.erb index dfd46f828..7adcdc5bb 100644 --- a/app/views/admin_request/_some_annotations.html.erb +++ b/app/views/admin_request/_some_annotations.html.erb @@ -1,48 +1,61 @@ -<% if comments.size > 0 %> - <div class="accordion" id="comments"> - <% for comment in comments %> - <div class="accordion-group"> - <div class="accordion-heading"> - <a href="#comment_<%=comment.id%>" data-toggle="collapse" data-parent="#comments"><%= chevron_right %></a> - <%= link_to admin_request_edit_comment_path(comment) do %> - #<%=comment.id%> - -- - <%=h(comment.user.name)%> - <%=admin_value(comment.created_at)%> +<% if comments.any? %> + <%= form_tag admin_user_modify_comment_visibility_path do %> + <div class="accordion" id="comments"> + <% comments.each do |comment| %> + <div class="accordion-group"> + <div class="accordion-heading"> + <%= check_box_tag 'comment_ids[]', comment.id %> + + <a href="#comment_<%= comment.id %>" data-toggle="collapse" data-parent="#comments"><%= chevron_right %></a> + + <%= link_to admin_request_edit_comment_path(comment) do %> + #<%= comment.id %> + -- + <%= h(comment.user.name) %> + <%= admin_value(comment.created_at) %> <% end %> - <blockquote class="incoming-message"> - <%= truncate(comment.body, :length => 400) %> - </blockquote> - </div> - <div id="comment_<%=comment.id%>" class="accordion-body collapse"> - <table class="table table-striped table-condensed"> - <tbody> - <tr> - <td colspan="2"> - By <%= user_both_links(comment.user) %> - </td> - </tr> - <% comment.for_admin_column do |name, value, type, column_name |%> + + <%= comment_visibility(comment) %> + + <blockquote class="incoming-message"> + <%= truncate(comment.body, :length => 400) %> + </blockquote> + </div> + + <div id="comment_<%= comment.id %>" class="accordion-body collapse"> + <table class="table table-striped table-condensed"> + <tbody> <tr> - <td> - <b><%=name%></b> - </td> - <td> - <% if column_name == 'body' && !comment.visible %> - <s><%=h comment.send(column_name) %></s> - <% else %> - <%=h comment.send(column_name) %> - <% end %> + <td colspan="2"> + By <%= user_both_links(comment.user) %> </td> </tr> - <% end %> - </tbody> - </table> + <% comment.for_admin_column do |name, value, type, column_name |%> + <tr> + <td> + <b><%= name %></b> + </td> + <td> + <% if column_name == 'body' && !comment.visible %> + <s><%= h comment.send(column_name) %></s> + <% else %> + <%= h comment.send(column_name) %> + <% end %> + </td> + </tr> + <% end %> + </tbody> + </table> + </div> + </div> - </div> - <% end %> - </div> + <% end %> + </div> + + <%= submit_tag 'Hide selected', :name => 'hide_selected' %> + <%= submit_tag 'Unhide selected', :name => 'unhide_selected' %> + + <% end %> <% else %> <p>None yet.</p> -<% end %> - +<% end %> diff --git a/app/views/admin_request/show.html.erb b/app/views/admin_request/show.html.erb index 2589e52b4..9c04badeb 100644 --- a/app/views/admin_request/show.html.erb +++ b/app/views/admin_request/show.html.erb @@ -118,7 +118,7 @@ </label> <div class="controls"> <%= link_to 'Generate URL', admin_request_generate_upload_url_path(@info_request), :class => "btn" %> - <p class="help-block">(see also option to general URLs for individual incoming messages below)</p> + <p class="help-block">(see also option to generate URLs for individual incoming messages below)</p> </div> </div> <%= form_tag admin_request_hide_path(@info_request), :class => "form form-inline", :id => "hide_request_form", 'data-info-request-id' => @info_request.id.to_s do %> diff --git a/app/views/comment/_single_comment.text.erb b/app/views/comment/_single_comment.text.erb index 925e8b688..4932a7e4a 100644 --- a/app/views/comment/_single_comment.text.erb +++ b/app/views/comment/_single_comment.text.erb @@ -1,2 +1,2 @@ -<%= _("{{username}} left an annotation:", :username =>comment.user.name) %> (<%= simple_date(comment.created_at || Time.now) %>) +<%= _("{{username}} left an annotation:", :username =>comment.user.name) %> (<%= simple_date((comment.created_at || Time.now), :format => :text) %>) <%= comment.body.strip %> diff --git a/app/views/general/search.html.erb b/app/views/general/search.html.erb index 18f258444..45268d7f0 100644 --- a/app/views/general/search.html.erb +++ b/app/views/general/search.html.erb @@ -191,7 +191,7 @@ <div class="results_block"> <% for result in @xapian_requests.results %> - <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request } %> + <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model] } %> <% end %> </div> diff --git a/app/views/help/contact.html.erb b/app/views/help/contact.html.erb index ad89db9ec..e8a5fec8c 100644 --- a/app/views/help/contact.html.erb +++ b/app/views/help/contact.html.erb @@ -65,6 +65,11 @@ <%= f.text_area :message, :rows => 10, :cols => 60 %> </p> + <p style="display:none;"> + <%= f.label :comment, 'Do not fill in this field' %> + <%= f.text_field :comment %> + </p> + <% if !@last_request.nil? %> <p> <label class="form_label" for="contact_message">Include link to request:</label> diff --git a/app/views/info_request_batch/show.html.erb b/app/views/info_request_batch/show.html.erb index aaecdd45d..2c7e42072 100644 --- a/app/views/info_request_batch/show.html.erb +++ b/app/views/info_request_batch/show.html.erb @@ -5,7 +5,7 @@ <div class="results_section"> <div class="results_block"> <% @info_requests.each do |info_request| %> - <%= render :partial => 'request/request_listing_via_event', :locals => { :event => info_request.last_event_forming_initial_request, :info_request => info_request } %> + <%= render :partial => 'request/request_listing_via_event', :locals => { :event => info_request.last_event_forming_initial_request } %> <% end %> </div> <%= will_paginate WillPaginate::Collection.new(@page, @per_page, @info_request_batch.info_requests.visible.count) %> diff --git a/app/views/public_body/show.html.erb b/app/views/public_body/show.html.erb index c36396149..a9c50e657 100644 --- a/app/views/public_body/show.html.erb +++ b/app/views/public_body/show.html.erb @@ -119,7 +119,7 @@ <% if !@xapian_requests.nil? %> <% for result in @xapian_requests.results %> - <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request } %> + <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model] } %> <% end %> <%= will_paginate WillPaginate::Collection.new(@page, @per_page, @xapian_requests.matches_estimated) %> diff --git a/app/views/request/_list_results.html.erb b/app/views/request/_list_results.html.erb index 4da042816..9e6b07c79 100644 --- a/app/views/request/_list_results.html.erb +++ b/app/views/request/_list_results.html.erb @@ -5,7 +5,7 @@ <h2 class="foi_results"><%= _('{{count}} FOI requests found', :count => @results[:matches_estimated]) %></h2> <div class="results_block"> <% @results[:results].each do |result| %> - <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result, :info_request => result.info_request } %> + <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result } %> <% end %> </div> <% end %> diff --git a/app/views/request/_outgoing_correspondence.text.erb b/app/views/request/_outgoing_correspondence.text.erb index 5375ef81b..221e359e2 100644 --- a/app/views/request/_outgoing_correspondence.text.erb +++ b/app/views/request/_outgoing_correspondence.text.erb @@ -3,6 +3,6 @@ <%- else %> <%= _('From:') %> <% if @info_request.user_name %><%= @info_request.user_name %><% else %><%= "[#{_('An anonymous user')}]"%><% end %> <%= _('To:') %> <%= @info_request.public_body.name %> - <%= _('Date:') %> <%= simple_date(info_request_event.created_at) %> + <%= _('Date:') %> <%= simple_date(info_request_event.created_at, :format => :text) %> <%= outgoing_message.get_body_for_text_display %> <%- end %> diff --git a/app/views/request/_request_listing_via_event.html.erb b/app/views/request/_request_listing_via_event.html.erb index cc8bae8a9..20bc5b2c8 100644 --- a/app/views/request/_request_listing_via_event.html.erb +++ b/app/views/request/_request_listing_via_event.html.erb @@ -6,36 +6,21 @@ end %> <div class="request_left"> <span class="head"> <% if event.is_incoming_message? %> - <%= link_to highlight_words(info_request.title, @highlight_words), incoming_message_path(event.incoming_message_selective_columns("incoming_messages.id")) %> + <%= link_to highlight_words(event.info_request.title, @highlight_words), incoming_message_path(event.incoming_message_selective_columns("incoming_messages.id")) %> <% elsif event.is_outgoing_message? and event.event_type == 'followup_sent' %> - <%= link_to highlight_words(info_request.title, @highlight_words), outgoing_message_path(event.outgoing_message) %> + <%= link_to highlight_words(event.info_request.title, @highlight_words), outgoing_message_path(event.outgoing_message) %> <% elsif event.is_comment? %> - <%= link_to highlight_words(info_request.title, @highlight_words), comment_path(event.comment) %> + <%= link_to highlight_words(event.info_request.title, @highlight_words), comment_path(event.comment) %> <% else %> - <%= link_to highlight_words(info_request.title, @highlight_words), request_path(info_request) %> + <%= link_to highlight_words(event.info_request.title, @highlight_words), request_path(event.info_request) %> <% end %> </span> <div class="requester"> - <% if event.event_type == 'sent' %> - <%= _('Request sent to {{public_body_name}} by {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> - <% elsif event.event_type == 'followup_sent' %> - <%=event.display_status %> - <%= _('sent to {{public_body_name}} by {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> - <% elsif event.event_type == 'response' %> - <%=event.display_status %> - <%= _('by {{public_body_name}} to {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> - <% elsif event.event_type == 'comment' %> - <%= _('Request to {{public_body_name}} by {{info_request_user}}. Annotated by {{event_comment_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:event_comment_user=>user_link_absolute(event.comment.user),:date=>simple_date(event.created_at)) %> - <% else %> - <%# Events of other types will not be indexed: see InfoRequestEvent#indexed_by_search? - However, it can happen that we see other types of event transiently here in the period - between a change being made and the update-xapian-index job being run. %> - <!-- Event of type '<%= event.event_type %>', id=<%= event.id %> --> - <% end %> + <%= event_description(event) %> </div> - <span class="bottomline icon_<%= info_request.calculate_status %>"> + <span class="bottomline icon_<%= event.info_request.calculate_status %>"> <strong> - <%= info_request.display_status(cached_value_ok=true) %> + <%= event.info_request.display_status(cached_value_ok=true) %> </strong><br> </span> </div> diff --git a/app/views/request/_resent_outgoing_correspondence.text.erb b/app/views/request/_resent_outgoing_correspondence.text.erb index d645e9488..d39f8395b 100644 --- a/app/views/request/_resent_outgoing_correspondence.text.erb +++ b/app/views/request/_resent_outgoing_correspondence.text.erb @@ -1,2 +1,2 @@ -<%= _('Date:') %> <%= simple_date(info_request_event.created_at) %> +<%= _('Date:') %> <%= simple_date(info_request_event.created_at, :format => :text) %> Sent <% if outgoing_message.message_type == 'initial_request' %> request <% elsif outgoing_message.message_type == 'followup' %> a follow up <% else %> <% raise "unknown message_type" %><% end %> to <%= public_body_link(@info_request.public_body) %> again<% if not info_request_event.same_email_as_previous_send? %>, using a new contact address<% end %>. diff --git a/app/views/request/similar.html.erb b/app/views/request/similar.html.erb index 5bdefc494..4ce4bf9ba 100644 --- a/app/views/request/similar.html.erb +++ b/app/views/request/similar.html.erb @@ -22,7 +22,7 @@ --> <% for result in @xapian_object.results %> <% if result[:model].class.to_s == 'InfoRequestEvent' %> - <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request } %> + <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model] } %> <% else %> <p><strong><%= _('Unexpected search result type ')%><%=result[:model].class.to_s%></strong></p> <% end %> diff --git a/app/views/track/atom_feed.atom.erb b/app/views/track/atom_feed.atom.erb index be9c39e72..892727aef 100644 --- a/app/views/track/atom_feed.atom.erb +++ b/app/views/track/atom_feed.atom.erb @@ -9,7 +9,7 @@ # Get the HTML content from the same partial template as website search does content = '' if result[:model].class.to_s == 'InfoRequestEvent' - content += render :partial => 'request/request_listing_via_event', :formats => ['html'], :locals => { :event => result[:model], :info_request => result[:model].info_request } + content += render :partial => 'request/request_listing_via_event', :formats => ['html'], :locals => { :event => result[:model] } else content = "<p><strong>Unknown search result type " + result[:model].class.to_s + "</strong></p>" end diff --git a/app/views/track_mailer/event_digest.text.erb b/app/views/track_mailer/event_digest.text.erb index 8dbc7fe06..b83c184f0 100644 --- a/app/views/track_mailer/event_digest.text.erb +++ b/app/views/track_mailer/event_digest.text.erb @@ -32,7 +32,7 @@ else raise "unknown type in event_digest " + event.event_type end - main_text += " (" + simple_date(event.created_at) + ")\n" + main_text += " (" + simple_date(event.created_at, :format => :text) + ")\n" # Main text, wrapped, words highlighted with * and indented. if event.is_outgoing_message? diff --git a/app/views/user/river.html.erb b/app/views/user/river.html.erb index 9618e0aa8..7277e5ee5 100644 --- a/app/views/user/river.html.erb +++ b/app/views/user/river.html.erb @@ -4,8 +4,7 @@ <h1><%=@title%></h1> <% for result in @results %> - <%= render :partial => 'request/request_listing_via_event', :locals => { - :event => result[:model], :info_request => result[:model].info_request } %> + <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model] } %> <% end %> </div> diff --git a/app/views/user/show.html.erb b/app/views/user/show.html.erb index dafeebd63..8dd8c6b88 100644 --- a/app/views/user/show.html.erb +++ b/app/views/user/show.html.erb @@ -147,7 +147,7 @@ <% for result in @xapian_requests.results %> - <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request } %> + <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model] } %> <% end %> <%= will_paginate WillPaginate::Collection.new(@page, @per_page, @display_user.info_requests.size) %> @@ -175,7 +175,7 @@ </h2> <% for result in @xapian_comments.results %> - <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request } %> + <%= render :partial => 'request/request_listing_via_event', :locals => { :event => result[:model] } %> <% end %> <%= will_paginate WillPaginate::Collection.new(@page, @per_page, @display_user.visible_comments.size) %> diff --git a/config/Vagrantfile b/config/Vagrantfile deleted file mode 100644 index 4253215fc..000000000 --- a/config/Vagrantfile +++ /dev/null @@ -1,23 +0,0 @@ -# This Vagrantfile should be used with the --no-color option, e.g. -# vagrant --no-color up -# Then you should be able to visit the site at: -# http://alaveteli.10.10.10.30.xip.io - -Vagrant::Config.run do |config| - config.vm.box = "precise64" - config.vm.box_url = "http://files.vagrantup.com/precise64.box" - config.vm.network :hostonly, "10.10.10.30" - # The bundle install fails unless you have quite a large amount of - # memory; insist on 1.5GiB: - config.vm.customize ["modifyvm", :id, "--memory", 1536] - # Fetch and run the install script: - config.vm.provision :shell, :inline => "wget -O install-site.sh https://raw.github.com/mysociety/commonlib/master/bin/install-site.sh" - config.vm.provision :shell, :inline => "chmod a+rx install-site.sh" - # This is only needed before the install-script branch is merged to - # master: - config.vm.provision :shell, :inline => "sed -i -e 's/BRANCH=master/BRANCH=install-script/' install-site.sh" - config.vm.provision :shell, :inline => "./install-site.sh " \ - "alaveteli " \ - "alaveteli " \ - "alaveteli.10.10.10.30.xip.io" -end diff --git a/config/general.yml-example b/config/general.yml-example index 6140cfe73..ec9bdb6b5 100644 --- a/config/general.yml-example +++ b/config/general.yml-example @@ -172,7 +172,6 @@ VARNISH_HOST: localhost # Adding a value here will enable Google Analytics on all non-admin pages for non-admin users. GA_CODE: '' - # If you want to override *all* the public body request emails with your own # email so that request emails that would normally go to the public body # go to you, then uncomment below and fill in your email. @@ -216,6 +215,10 @@ USE_MAILCATCHER_IN_DEVELOPMENT: true # config.action_controller.perform_caching is set to true CACHE_FRAGMENTS: true +# The default bundle path is vendor/bundle; you can set this option to +# change it. +BUNDLE_PATH: vendor/bundle + # In some deployments of Alaveteli you may wish to install each newly # deployed version alongside the previous ones, in which case certain # files and resources should be shared between these installations: diff --git a/config/routes.rb b/config/routes.rb index 87a62c0bf..1079fbe14 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -233,6 +233,7 @@ Alaveteli::Application.routes.draw do match '/admin/user/destroy_track' => 'admin_user#destroy_track', :as => :admin_user_destroy_track match '/admin/user/login_as/:id' => 'admin_user#login_as', :as => :admin_user_login_as match '/admin/user/clear_profile_photo/:id' => 'admin_user#clear_profile_photo', :as => :admin_clear_profile_photo + match '/admin/user/modify_comment_visibility/:id' => 'admin_user#modify_comment_visibility', :as => 'admin_user_modify_comment_visibility' #### #### AdminTrack controller diff --git a/lib/normalize_string.rb b/lib/normalize_string.rb index f02b18ee0..3b6116970 100644 --- a/lib/normalize_string.rb +++ b/lib/normalize_string.rb @@ -1,4 +1,4 @@ -require 'iconv' unless RUBY_VERSION.to_f >= 1.9 +require 'iconv' unless String.method_defined?(:encode) require 'charlock_holmes' class EncodingNormalizationError < StandardError @@ -23,17 +23,16 @@ def normalize_string_to_utf8(s, suggested_character_encoding=nil) to_try.push guessed_encoding to_try.each do |from_encoding| - if RUBY_VERSION.to_f >= 1.9 + if String.method_defined?(:encode) begin s.force_encoding from_encoding return s.encode('UTF-8') if s.valid_encoding? - rescue ArgumentError + rescue ArgumentError, Encoding::UndefinedConversionError # We get this is there are invalid bytes when # interpreted as from_encoding at the point of # the encode('UTF-8'); move onto the next one... end else - to_encoding = 'UTF-8' begin converted = Iconv.conv 'UTF-8', from_encoding, s return converted @@ -45,7 +44,6 @@ def normalize_string_to_utf8(s, suggested_character_encoding=nil) end end raise EncodingNormalizationError, "Couldn't find a valid character encoding for the string" - end def convert_string_to_utf8_or_binary(s, suggested_character_encoding=nil) @@ -69,13 +67,13 @@ def convert_string_to_utf8_or_binary(s, suggested_character_encoding=nil) result = normalize_string_to_utf8 s, suggested_character_encoding rescue EncodingNormalizationError result = s - s.force_encoding 'ASCII-8BIT' if RUBY_VERSION.to_f >= 1.9 + s.force_encoding 'ASCII-8BIT' if String.method_defined?(:encode) end result end def log_text_details(message, text) - if RUBY_VERSION.to_f >= 1.9 + if String.method_defined?(:encode) STDERR.puts "#{message}, we have text: #{text}, of class #{text.class} and encoding #{text.encoding}" else STDERR.puts "#{message}, we have text: #{text}, of class #{text.class}" diff --git a/locale/cy/app.po b/locale/cy/app.po index ee1a95564..f6b48c94d 100644 --- a/locale/cy/app.po +++ b/locale/cy/app.po @@ -21,7 +21,6 @@ msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-02-27 09:52+0000\n" -"PO-Revision-Date: 2014-02-27 10:11+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Welsh (http://www.transifex.com/projects/p/alaveteli/language/cy/)\n" "Language: cy\n" diff --git a/script/install-as-user b/script/install-as-user index aaad52145..a6c267066 100755 --- a/script/install-as-user +++ b/script/install-as-user @@ -114,6 +114,7 @@ then -e "s,^( *DONATION_URL:).*,\\1 null," \ -e "s,^( *THEME_BRANCH:).*,\\1 'develop'," \ -e "s,^( *USE_MAILCATCHER_IN_DEVELOPMENT:).*,\\1 false," \ + -e "s,^( *BUNDLE_PATH:).*,\\1 $HOME/bundle/," \ config/general.yml-example > config/general.yml fi diff --git a/script/rails-deploy-before-down b/script/rails-deploy-before-down index ad1049e44..c157a8624 100755 --- a/script/rails-deploy-before-down +++ b/script/rails-deploy-before-down @@ -123,19 +123,24 @@ END echo "ENV['RAILS_ENV'] ||= 'production'" > config/rails_env.rb fi -bundle_install_options="" +BUNDLE_PATH="${OPTION_BUNDLE_PATH:-vendor/bundle}" + +bundle_install_options="--path $BUNDLE_PATH" + if [ "$OPTION_STAGING_SITE" = "0" ] then - bundle_install_options="--without development:test --deployment" + bundle_install_options="$bundle_install_options --without development:test --deployment" fi if [ "$OPTION_STAGING_SITE" = "1" ] then - bundle_install_options="--path vendor/bundle" + bundle_install_options="$bundle_install_options" fi if [ "$TRAVIS" = "true" ] then bundle_install_options="--without development develop --deployment" fi + +echo "Running bundle install with options: $bundle_install_options" bundle install $bundle_install_options bundle exec rake submodules:check diff --git a/spec/controllers/admin_user_controller_spec.rb b/spec/controllers/admin_user_controller_spec.rb index 99894a414..8b89506f9 100644 --- a/spec/controllers/admin_user_controller_spec.rb +++ b/spec/controllers/admin_user_controller_spec.rb @@ -44,3 +44,72 @@ describe AdminUserController, "when updating a user" do end end + +describe AdminUserController do + + describe :modify_comment_visibility do + + before(:each) do + @user = FactoryGirl.create(:user) + request.env["HTTP_REFERER"] = admin_user_show_path(@user) + end + + it 'redirects to the page the admin was previously on' do + comment = FactoryGirl.create(:visible_comment, :user => @user) + + post :modify_comment_visibility, { :id => @user.id, + :comment_ids => comment.id, + :hide_selected => 'hidden' } + + response.should redirect_to(admin_user_show_path(@user)) + end + + it 'sets the given comments visibility to hidden' do + comments = FactoryGirl.create_list(:visible_comment, 3, :user => @user) + comment_ids = comments.map(&:id) + + post :modify_comment_visibility, { :id => @user.id, + :comment_ids => comment_ids, + :hide_selected => 'hidden' } + + Comment.find(comment_ids).each { |comment| comment.should_not be_visible } + end + + it 'sets the given comments visibility to visible' do + comments = FactoryGirl.create_list(:hidden_comment, 3, :user => @user) + comment_ids = comments.map(&:id) + + post :modify_comment_visibility, { :id => @user.id, + :comment_ids => comment_ids, + :unhide_selected => 'visible' } + + Comment.find(comment_ids).each { |comment| comment.should be_visible } + end + + it 'only modifes the given list of comments' do + unaffected_comment = FactoryGirl.create(:hidden_comment, :user => @user) + affected_comment = FactoryGirl.create(:hidden_comment, :user => @user) + + post :modify_comment_visibility, { :id => @user.id, + :comment_ids => affected_comment.id, + :unhide_selected => 'visible' } + + Comment.find(unaffected_comment).should_not be_visible + Comment.find(affected_comment).should be_visible + end + + it 'preserves the visibility if a comment is already of the requested visibility' do + hidden_comment = FactoryGirl.create(:hidden_comment, :user => @user) + visible_comment = FactoryGirl.create(:visible_comment, :user => @user) + comment_ids = [hidden_comment.id, visible_comment.id] + + post :modify_comment_visibility, { :id => @user.id, + :comment_ids => comment_ids, + :unhide_selected => 'visible' } + + Comment.find(comment_ids).each { |c| c.should be_visible } + end + + end + +end diff --git a/spec/controllers/comment_controller_spec.rb b/spec/controllers/comment_controller_spec.rb index c03615ce2..5e250f689 100644 --- a/spec/controllers/comment_controller_spec.rb +++ b/spec/controllers/comment_controller_spec.rb @@ -53,16 +53,30 @@ 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") - + session[:user_id] = users(:silly_name_user).id + info_request = info_requests(:spam_1_request) + + post :new, :url_title => info_request.url_title, + :comment => { :body => "I demand to be heard!" }, + :type => 'request', :submitted_comment => 1, :preview => 0 + + response.should redirect_to(show_request_path(info_request.url_title)) + flash[:notice].should == 'Comments are not allowed on this request' + end + + it "should not allow comments from banned users" do + User.any_instance.stub(:ban_text).and_return('Banned from commenting') + + user = users(:silly_name_user) + session[:user_id] = user.id + + post :new, :url_title => info_requests(:fancy_dog_request).url_title, + :comment => { :body => comments(:silly_comment).body }, + :type => 'request', :submitted_comment => 1, :preview => 0 + + response.should render_template('user/banned') end describe 'when commenting on an external request' do diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb index cc024f840..f92323f50 100644 --- a/spec/controllers/help_controller_spec.rb +++ b/spec/controllers/help_controller_spec.rb @@ -1,48 +1,81 @@ # -*- coding: utf-8 -*- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -describe HelpController, "when using help" do +describe HelpController do render_views - it "shows the about page" do - get :about - end + describe :about do - it "shows contact form" do - get :contact - end + it 'shows the about page' do + get :about + response.should be_success + response.should render_template('help/about') + end - it "sends a contact message" do - post :contact, { :contact => { - :name => "Vinny Vanilli", - :email => "vinny@localhost", - :subject => "Why do I have such an ace name?", - :message => "You really should know!!!\n\nVinny", - }, :submitted_contact_form => 1 - } - response.should redirect_to(:controller => 'general', :action => 'frontpage') - - deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - deliveries[0].body.should include("really should know") - deliveries.clear end - describe 'when requesting a page in a supported locale ' do + describe 'GET contact' do - before do - # Prepend our fixture templates - fixture_theme_path = File.join(Rails.root, 'spec', 'fixtures', 'theme_views', 'theme_one') - controller.prepend_view_path fixture_theme_path + it 'shows contact form' do + get :contact + response.should be_success + response.should render_template('help/contact') end - it 'should render the locale-specific template if available' do - get :contact, {:locale => 'es'} - response.body.should match('contáctenos theme one') + describe 'when requesting a page in a supported locale' do + + before do + # Prepend our fixture templates + fixture_theme_path = File.join(Rails.root, 'spec', 'fixtures', 'theme_views', 'theme_one') + controller.prepend_view_path fixture_theme_path + end + + it 'should render the locale-specific template if available' do + get :contact, {:locale => 'es'} + response.body.should match('contáctenos theme one') + end + end end + describe 'POST contact' do + + it 'sends a contact message' do + post :contact, { :contact => { + :name => 'Vinny Vanilli', + :email => 'vinny@localhost', + :subject => 'Why do I have such an ace name?', + :comment => '', + :message => "You really should know!!!\n\nVinny", + }, :submitted_contact_form => 1 + } + response.should redirect_to(frontpage_path) + + deliveries = ActionMailer::Base.deliveries + deliveries.size.should == 1 + deliveries[0].body.should include('really should know') + deliveries.clear + end + + it 'has rudimentary spam protection' do + post :contact, { :contact => { + :name => 'Vinny Vanilli', + :email => 'vinny@localhost', + :subject => 'Why do I have such an ace name?', + :comment => 'I AM A SPAMBOT', + :message => "You really should know!!!\n\nVinny", + }, :submitted_contact_form => 1 + } + + response.should redirect_to(frontpage_path) + + deliveries = ActionMailer::Base.deliveries + deliveries.size.should == 0 + deliveries.clear + end + + end end diff --git a/spec/factories.rb b/spec/factories.rb deleted file mode 100644 index 7e6f0da99..000000000 --- a/spec/factories.rb +++ /dev/null @@ -1,185 +0,0 @@ -FactoryGirl.define do - - sequence(:email) { |n| "person#{n}@example.com" } - sequence(:name) { |n| "Example Public Body #{n}" } - sequence(:short_name) { |n| "Example Body #{n}" } - - factory :foi_attachment do - factory :body_text do - content_type 'text/plain' - body { 'hereisthetext' } - end - factory :pdf_attachment do - content_type 'application/pdf' - filename 'interesting.pdf' - body { load_file_fixture('interesting.pdf') } - end - end - - factory :incoming_message do - info_request - raw_email - last_parsed { 1.week.ago } - sent_at { 1.week.ago } - - after_create do |incoming_message, evaluator| - FactoryGirl.create(:body_text, - :incoming_message => incoming_message, - :url_part_number => 1) - end - - factory :plain_incoming_message do - last_parsed { nil } - sent_at { nil } - after_create do |incoming_message, evaluator| - data = load_file_fixture('incoming-request-plain.email') - data.gsub!('EMAIL_FROM', 'Bob Responder <bob@example.com>') - incoming_message.raw_email.data = data - incoming_message.raw_email.save! - end - end - - factory :incoming_message_with_attachments do - # foi_attachments_count is declared as an ignored attribute and available in - # attributes on the factory, as well as the callback via the evaluator - ignore do - foi_attachments_count 2 - end - - # the after(:create) yields two values; the incoming_message instance itself and the - # evaluator, which stores all values from the factory, including ignored - # attributes; - after_create do |incoming_message, evaluator| - evaluator.foi_attachments_count.times do |count| - FactoryGirl.create(:pdf_attachment, - :incoming_message => incoming_message, - :url_part_number => count+2) - end - end - end - end - - factory :raw_email - - factory :outgoing_message do - factory :initial_request do - ignore do - status 'ready' - message_type 'initial_request' - body 'Some information please' - what_doing 'normal_sort' - end - initialize_with { OutgoingMessage.new({ :status => status, - :message_type => message_type, - :body => body, - :what_doing => what_doing }) } - after_create do |outgoing_message| - outgoing_message.send_message - end - end - end - - factory :info_request do - title "Example Title" - public_body - user - - after_create do |info_request, evaluator| - FactoryGirl.create(:initial_request, :info_request => info_request) - end - - factory :info_request_with_incoming do - after_create do |info_request, evaluator| - incoming_message = FactoryGirl.create(:incoming_message, :info_request => info_request) - info_request.log_event("response", {:incoming_message_id => incoming_message.id}) - end - end - - factory :info_request_with_plain_incoming do - after_create do |info_request, evaluator| - incoming_message = FactoryGirl.create(:plain_incoming_message, :info_request => info_request) - info_request.log_event("response", {:incoming_message_id => incoming_message.id}) - end - end - - factory :info_request_with_incoming_attachments do - after_create do |info_request, evaluator| - incoming_message = FactoryGirl.create(:incoming_message_with_attachments, :info_request => info_request) - info_request.log_event("response", {:incoming_message_id => incoming_message.id}) - end - end - - factory :external_request do - user nil - external_user_name 'External User' - external_url 'http://www.example.org/request/external' - end - - end - - factory :user do - name 'Example User' - email - salt "-6116981980.392287733335677" - hashed_password '6b7cd45a5f35fd83febc0452a799530398bfb6e8' # jonespassword - email_confirmed true - ban_text "" - factory :admin_user do - name 'Admin User' - admin_level 'super' - end - end - - factory :public_body do - name - short_name - request_email 'request@example.com' - last_edit_editor "admin user" - last_edit_comment "Making an edit" - end - - factory :track_thing do - association :tracking_user, :factory => :user - factory :search_track do - track_medium 'email_daily' - track_type 'search_query' - track_query 'Example Query' - end - factory :user_track do - association :tracked_user, :factory => :user - track_type 'user_updates' - end - factory :public_body_track do - association :public_body, :factory => :public_body - track_type 'public_body_updates' - end - factory :request_update_track do - association :info_request, :factory => :info_request - track_type 'request_updates' - end - factory :successful_request_track do - track_type 'all_successful_requests' - end - factory :new_request_track do - track_type 'all_new_requests' - end - end - - factory :public_body_change_request do - user - source_url 'http://www.example.com' - notes 'Please' - public_body_email 'new@example.com' - factory :add_body_request do - public_body_name 'A New Body' - end - factory :update_body_request do - public_body - end - end - factory :info_request_batch do - title "Example title" - user - body "Some text" - end -end diff --git a/spec/factories/comments.rb b/spec/factories/comments.rb new file mode 100644 index 000000000..1e0861dad --- /dev/null +++ b/spec/factories/comments.rb @@ -0,0 +1,19 @@ +FactoryGirl.define do + + factory :comment do + user + info_request + + body 'This a wise and helpful annotation.' + comment_type 'request' + + factory :visible_comment do + visible true + end + + factory :hidden_comment do + visible false + end + end + +end diff --git a/spec/factories/foi_attchments.rb b/spec/factories/foi_attchments.rb new file mode 100644 index 000000000..d7a90efb8 --- /dev/null +++ b/spec/factories/foi_attchments.rb @@ -0,0 +1,15 @@ +FactoryGirl.define do + + factory :foi_attachment do + factory :body_text do + content_type 'text/plain' + body { 'hereisthetext' } + end + factory :pdf_attachment do + content_type 'application/pdf' + filename 'interesting.pdf' + body { load_file_fixture('interesting.pdf') } + end + end + +end diff --git a/spec/factories/incoming_messages.rb b/spec/factories/incoming_messages.rb new file mode 100644 index 000000000..38ad98394 --- /dev/null +++ b/spec/factories/incoming_messages.rb @@ -0,0 +1,46 @@ +FactoryGirl.define do + + factory :incoming_message do + info_request + raw_email + last_parsed { 1.week.ago } + sent_at { 1.week.ago } + + after_create do |incoming_message, evaluator| + FactoryGirl.create(:body_text, + :incoming_message => incoming_message, + :url_part_number => 1) + end + + factory :plain_incoming_message do + last_parsed { nil } + sent_at { nil } + after_create do |incoming_message, evaluator| + data = load_file_fixture('incoming-request-plain.email') + data.gsub!('EMAIL_FROM', 'Bob Responder <bob@example.com>') + incoming_message.raw_email.data = data + incoming_message.raw_email.save! + end + end + + factory :incoming_message_with_attachments do + # foi_attachments_count is declared as an ignored attribute and available in + # attributes on the factory, as well as the callback via the evaluator + ignore do + foi_attachments_count 2 + end + + # the after(:create) yields two values; the incoming_message instance itself and the + # evaluator, which stores all values from the factory, including ignored + # attributes; + after_create do |incoming_message, evaluator| + evaluator.foi_attachments_count.times do |count| + FactoryGirl.create(:pdf_attachment, + :incoming_message => incoming_message, + :url_part_number => count+2) + end + end + end + end + +end diff --git a/spec/factories/info_request_batches.rb b/spec/factories/info_request_batches.rb new file mode 100644 index 000000000..960db6ec5 --- /dev/null +++ b/spec/factories/info_request_batches.rb @@ -0,0 +1,9 @@ +FactoryGirl.define do + + factory :info_request_batch do + title "Example title" + user + body "Some text" + end + +end diff --git a/spec/factories/info_requests.rb b/spec/factories/info_requests.rb new file mode 100644 index 000000000..8052625cd --- /dev/null +++ b/spec/factories/info_requests.rb @@ -0,0 +1,47 @@ +FactoryGirl.define do + + factory :info_request do + title "Example Title" + public_body + user + + after_create do |info_request, evaluator| + FactoryGirl.create(:initial_request, :info_request => info_request) + end + + factory :info_request_with_incoming do + after_create do |info_request, evaluator| + incoming_message = FactoryGirl.create(:incoming_message, :info_request => info_request) + info_request.log_event("response", {:incoming_message_id => incoming_message.id}) + end + end + + factory :info_request_with_plain_incoming do + after_create do |info_request, evaluator| + incoming_message = FactoryGirl.create(:plain_incoming_message, :info_request => info_request) + info_request.log_event("response", {:incoming_message_id => incoming_message.id}) + end + end + + factory :info_request_with_incoming_attachments do + after_create do |info_request, evaluator| + incoming_message = FactoryGirl.create(:incoming_message_with_attachments, :info_request => info_request) + info_request.log_event("response", {:incoming_message_id => incoming_message.id}) + end + end + + factory :info_request_with_internal_review_request do + after_create do |info_request, evaluator| + outgoing_message = FactoryGirl.create(:internal_review_request, :info_request => info_request) + end + end + + factory :external_request do + user nil + external_user_name 'External User' + external_url 'http://www.example.org/request/external' + end + + end + +end diff --git a/spec/factories/outgoing_messages.rb b/spec/factories/outgoing_messages.rb new file mode 100644 index 000000000..d1ed25093 --- /dev/null +++ b/spec/factories/outgoing_messages.rb @@ -0,0 +1,29 @@ +FactoryGirl.define do + + factory :outgoing_message do + factory :initial_request do + ignore do + status 'ready' + message_type 'initial_request' + body 'Some information please' + what_doing 'normal_sort' + end + end + factory :internal_review_request do + ignore do + status 'ready' + message_type 'followup' + body 'I want a review' + what_doing 'internal_review' + end + end + initialize_with { OutgoingMessage.new({ :status => status, + :message_type => message_type, + :body => body, + :what_doing => what_doing }) } + after_create do |outgoing_message| + outgoing_message.send_message + end + end + +end diff --git a/spec/factories/public_bodies.rb b/spec/factories/public_bodies.rb new file mode 100644 index 000000000..44769f7c2 --- /dev/null +++ b/spec/factories/public_bodies.rb @@ -0,0 +1,12 @@ +FactoryGirl.define do + + factory :public_body do + sequence(:name) { |n| "Example Public Body #{n}" } + sequence(:short_name) { |n| "Example Body #{n}" } + request_email 'request@example.com' + last_edit_editor "admin user" + last_edit_comment "Making an edit" + end + + +end diff --git a/spec/factories/public_body_change_requests.rb b/spec/factories/public_body_change_requests.rb new file mode 100644 index 000000000..2bacb9b9b --- /dev/null +++ b/spec/factories/public_body_change_requests.rb @@ -0,0 +1,16 @@ +FactoryGirl.define do + + factory :public_body_change_request do + user + source_url 'http://www.example.com' + notes 'Please' + public_body_email 'new@example.com' + factory :add_body_request do + public_body_name 'A New Body' + end + factory :update_body_request do + public_body + end + end + +end diff --git a/spec/factories/raw_emails.rb b/spec/factories/raw_emails.rb new file mode 100644 index 000000000..30fb24c37 --- /dev/null +++ b/spec/factories/raw_emails.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + + factory :raw_email + +end diff --git a/spec/factories/track_things.rb b/spec/factories/track_things.rb new file mode 100644 index 000000000..cf76b00b3 --- /dev/null +++ b/spec/factories/track_things.rb @@ -0,0 +1,30 @@ +FactoryGirl.define do + + factory :track_thing do + association :tracking_user, :factory => :user + factory :search_track do + track_medium 'email_daily' + track_type 'search_query' + track_query 'Example Query' + end + factory :user_track do + association :tracked_user, :factory => :user + track_type 'user_updates' + end + factory :public_body_track do + association :public_body, :factory => :public_body + track_type 'public_body_updates' + end + factory :request_update_track do + association :info_request, :factory => :info_request + track_type 'request_updates' + end + factory :successful_request_track do + track_type 'all_successful_requests' + end + factory :new_request_track do + track_type 'all_new_requests' + end + end + +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb new file mode 100644 index 000000000..ab782fbf7 --- /dev/null +++ b/spec/factories/users.rb @@ -0,0 +1,16 @@ +FactoryGirl.define do + + factory :user do + name 'Example User' + sequence(:email) { |n| "person#{n}@example.com" } + salt "-6116981980.392287733335677" + hashed_password '6b7cd45a5f35fd83febc0452a799530398bfb6e8' # jonespassword + email_confirmed true + ban_text "" + factory :admin_user do + name 'Admin User' + admin_level 'super' + end + end + +end diff --git a/spec/helpers/admin_helper_spec.rb b/spec/helpers/admin_helper_spec.rb new file mode 100644 index 000000000..804fcc7fd --- /dev/null +++ b/spec/helpers/admin_helper_spec.rb @@ -0,0 +1,21 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AdminHelper do + + include AdminHelper + + describe :comment_visibility do + + it 'shows the status of a visible comment' do + comment = Factory.build(:visible_comment) + comment_visibility(comment).should == 'Visible' + end + + it 'shows the status of a hidden comment' do + comment = Factory.build(:hidden_comment) + comment_visibility(comment).should == 'Hidden' + end + + end + +end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb new file mode 100644 index 000000000..6407eaf3a --- /dev/null +++ b/spec/helpers/application_helper_spec.rb @@ -0,0 +1,34 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe ApplicationHelper do + + include ApplicationHelper + include LinkToHelper + + describe 'when creating an event description' do + + it 'should generate a description for a request' do + @info_request = FactoryGirl.create(:info_request) + @sent_event = @info_request.get_last_event + expected = "Request sent to #{public_body_link_absolute(@info_request.public_body)} by #{request_user_link_absolute(@info_request)}" + event_description(@sent_event).should match(expected) + + end + + it 'should generate a description for a response' do + @info_request_with_incoming = FactoryGirl.create(:info_request_with_incoming) + @response_event = @info_request_with_incoming.get_last_event + expected = "Response by #{public_body_link_absolute(@info_request_with_incoming.public_body)} to #{request_user_link_absolute(@info_request_with_incoming)}" + event_description(@response_event).should match(expected) + end + + it 'should generate a description for a request where an internal review has been requested' do + @info_request_with_internal_review_request = FactoryGirl.create(:info_request_with_internal_review_request) + @response_event = @info_request_with_internal_review_request.get_last_event + expected = "Internal review request sent to #{public_body_link_absolute(@info_request_with_internal_review_request.public_body)} by #{request_user_link_absolute(@info_request_with_internal_review_request)}" + event_description(@response_event).should match(expected) + end + + end + +end diff --git a/spec/helpers/link_to_helper_spec.rb b/spec/helpers/link_to_helper_spec.rb index 2259db6c2..4a01ec683 100644 --- a/spec/helpers/link_to_helper_spec.rb +++ b/spec/helpers/link_to_helper_spec.rb @@ -70,14 +70,50 @@ describe LinkToHelper do end describe 'simple_date' do + + it 'formats a date in html by default' do + time = Time.utc(2012, 11, 07, 21, 30, 26) + self.should_receive(:simple_date_html).with(time) + simple_date(time) + end + + it 'formats a date in the specified format' do + time = Time.utc(2012, 11, 07, 21, 30, 26) + self.should_receive(:simple_date_text).with(time) + simple_date(time, :format => :text) + end + + it 'raises an argument error if given an unrecognized format' do + time = Time.utc(2012, 11, 07, 21, 30, 26) + expect { simple_date(time, :format => :unknown) }.to raise_error(ArgumentError) + end + + end + + describe 'simple_date_html' do + + it 'formats a date in a time tag' do + Time.use_zone('London') do + time = Time.utc(2012, 11, 07, 21, 30, 26) + expected = "<time datetime=\"2012-11-07T21:30:26+00:00\" title=\"2012-11-07 21:30:26 +0000\">November 07, 2012</time>" + simple_date_html(time).should == expected + end + end + + end + + describe 'simple_date_text' do + it 'should respect time zones' do Time.use_zone('Australia/Sydney') do - simple_date(Time.utc(2012, 11, 07, 21, 30, 26)).should == 'November 08, 2012' + simple_date_text(Time.utc(2012, 11, 07, 21, 30, 26)).should == 'November 08, 2012' end end it 'should handle Date objects' do - simple_date(Date.new(2012, 11, 21)).should == 'November 21, 2012' + simple_date_text(Date.new(2012, 11, 21)).should == 'November 21, 2012' end + end + end diff --git a/spec/lib/alaveteli_external_command.rb b/spec/lib/alaveteli_external_command_spec.rb index 18afeda33..18afeda33 100644 --- a/spec/lib/alaveteli_external_command.rb +++ b/spec/lib/alaveteli_external_command_spec.rb diff --git a/spec/lib/basic_encoding_tests.rb b/spec/lib/basic_encoding_spec.rb index 35d35fd4a..43a65eab9 100644 --- a/spec/lib/basic_encoding_tests.rb +++ b/spec/lib/basic_encoding_spec.rb @@ -4,8 +4,8 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') def bytes_to_binary_string( bytes, claimed_encoding = nil ) claimed_encoding ||= 'ASCII-8BIT' bytes_string = bytes.pack('c*') - if RUBY_VERSION.to_f >= 1.9 - bytes_string.force_encoding! claimed_encoding + if String.method_defined?(:force_encoding) + bytes_string.force_encoding claimed_encoding end bytes_string end @@ -110,15 +110,15 @@ describe "convert_string_to_utf8_or_binary" do converted = convert_string_to_utf8_or_binary random_string converted.should == random_string - if RUBY_VERSION.to_f >= 1.9 - converted.encoding.should == 'ASCII-8BIT' + if String.method_defined?(:encode) + converted.encoding.to_s.should == 'ASCII-8BIT' end converted = convert_string_to_utf8_or_binary random_string,'UTF-8' converted.should == random_string - if RUBY_VERSION.to_f >= 1.9 - converted.encoding.should == 'ASCII-8BIT' + if String.method_defined?(:encode) + converted.encoding.to_s.should == 'ASCII-8BIT' end end @@ -132,8 +132,8 @@ describe "convert_string_to_utf8_or_binary" do converted.should == "DASH – DASH" - if RUBY_VERSION.to_f >= 1.9 - converted.encoding.should == 'UTF-8' + if String.method_defined?(:encode) + converted.encoding.to_s.should == 'UTF-8' end end @@ -147,8 +147,8 @@ describe "convert_string_to_utf8_or_binary" do converted.should start_with("贵公司负责人") - if RUBY_VERSION.to_f >= 1.9 - converted.encoding.should == 'UTF-8' + if String.method_defined?(:encode) + converted.encoding.to_s.should == 'UTF-8' end end diff --git a/spec/lib/confidence_intervals.rb b/spec/lib/confidence_intervals_spec.rb index cb8717f3d..cb8717f3d 100644 --- a/spec/lib/confidence_intervals.rb +++ b/spec/lib/confidence_intervals_spec.rb diff --git a/spec/lib/i18n_interpolation.rb b/spec/lib/i18n_interpolation_spec.rb index b07cf1e9a..47037ecdb 100644 --- a/spec/lib/i18n_interpolation.rb +++ b/spec/lib/i18n_interpolation_spec.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe "when using i18n" do diff --git a/spec/mailers/info_request_batch_mailer.rb b/spec/mailers/info_request_batch_mailer_spec.rb index 19791e163..19791e163 100644 --- a/spec/mailers/info_request_batch_mailer.rb +++ b/spec/mailers/info_request_batch_mailer_spec.rb diff --git a/spec/models/contact_validator_spec.rb b/spec/models/contact_validator_spec.rb index 9ea0fac49..0f5403967 100644 --- a/spec/models/contact_validator_spec.rb +++ b/spec/models/contact_validator_spec.rb @@ -1,8 +1,53 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -describe ContactValidator, " when blah" do - before do +describe ContactValidator do + + describe :new do + + let(:valid_params) do + { :name => "Vinny Vanilli", + :email => "vinny@localhost", + :subject => "Why do I have such an ace name?", + :message => "You really should know!!!\n\nVinny" } + end + + it 'validates specified attributes' do + ContactValidator.new(valid_params).should be_valid + end + + it 'validates name is present' do + valid_params.except!(:name) + validator = ContactValidator.new(valid_params) + expect(validator).to have(1).error_on(:name) + end + + it 'validates email is present' do + valid_params.except!(:email) + validator = ContactValidator.new(valid_params) + # We have 2 errors on email because of the format validator + expect(validator).to have(2).errors_on(:email) + end + + it 'validates email format' do + valid_params.merge!({:email => 'not-an-email'}) + validator = ContactValidator.new(valid_params) + expect(validator.errors_on(:email)).to include("Email doesn't look like a valid address") + end + + it 'validates subject is present' do + valid_params.except!(:subject) + validator = ContactValidator.new(valid_params) + expect(validator).to have(1).error_on(:subject) + end + + it 'validates message is present' do + valid_params.except!(:message) + validator = ContactValidator.new(valid_params) + expect(validator).to have(1).error_on(:message) + end + end + end |