diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 072caad09..373bb213c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,12 +1,12 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2017-07-07 21:23:30 +0200 using RuboCop version 0.49.1. +# on 2017-10-17 22:05:23 +0200 using RuboCop version 0.49.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 45 +# Offense count: 40 # Cop supports --auto-correct. # Configuration parameters: EnforcedHashRocketStyle, SupportedHashRocketStyles, EnforcedColonStyle, SupportedColonStyles, EnforcedLastArgumentHashStyle, SupportedLastArgumentHashStyles. # SupportedHashRocketStyles: key, separator, table @@ -14,11 +14,10 @@ # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit Layout/AlignHash: Exclude: - - 'app/controllers/officing/results_controller.rb' - 'spec/controllers/legislation/annotations_controller_spec.rb' - 'spec/features/admin/banners_spec.rb' -# Offense count: 50 +# Offense count: 52 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: with_first_parameter, with_fixed_indentation @@ -33,7 +32,7 @@ Layout/ClosingParenthesisIndentation: - 'spec/models/legislation/annotation_spec.rb' - 'spec/rails_helper.rb' -# Offense count: 51 +# Offense count: 37 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: leading, trailing @@ -68,11 +67,10 @@ Layout/EmptyLines: Exclude: - 'app/controllers/admin/budget_investment_milestones_controller.rb' -# Offense count: 2 +# Offense count: 1 # Cop supports --auto-correct. Layout/EmptyLinesAroundMethodBody: Exclude: - - 'app/models/abilities/administrator.rb' - 'lib/graph_ql/api_types_creator.rb' # Offense count: 2 @@ -126,13 +124,13 @@ Layout/IndentationConsistency: - 'spec/models/legislation/draft_version_spec.rb' - 'spec/models/proposal_spec.rb' -# Offense count: 23 +# Offense count: 48 # Cop supports --auto-correct. # Configuration parameters: Width, IgnoredPatterns. Layout/IndentationWidth: Enabled: false -# Offense count: 7 +# Offense count: 6 # Cop supports --auto-correct. Layout/LeadingCommentSpace: Exclude: @@ -140,7 +138,6 @@ Layout/LeadingCommentSpace: - 'app/controllers/budgets/ballot/lines_controller.rb' - 'spec/features/budgets/ballots_spec.rb' - 'spec/features/comments/poll_questions_spec.rb' - - 'spec/features/officing/voters_spec.rb' - 'spec/support/common_actions.rb' # Offense count: 3 @@ -181,7 +178,7 @@ Layout/MultilineMethodCallBraceLayout: - 'spec/models/legislation/annotation_spec.rb' - 'spec/rails_helper.rb' -# Offense count: 71 +# Offense count: 59 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: aligned, indented, indented_relative_to_receiver @@ -201,7 +198,7 @@ Layout/MultilineMethodCallIndentation: - 'spec/models/proposal_spec.rb' - 'spec/models/user_spec.rb' -# Offense count: 8 +# Offense count: 7 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: aligned, indented @@ -264,22 +261,7 @@ Lint/LiteralInCondition: Exclude: - 'app/models/budget/investment.rb' -# Offense count: 51 -Lint/ParenthesesAsGroupedExpression: - Exclude: - - 'spec/factories.rb' - - 'spec/features/admin/organizations_spec.rb' - - 'spec/features/budgets/investments_spec.rb' - - 'spec/features/campaigns_spec.rb' - - 'spec/features/debates_spec.rb' - - 'spec/features/management/managed_users_spec.rb' - - 'spec/features/management/proposals_spec.rb' - - 'spec/features/management/spending_proposals_spec.rb' - - 'spec/features/management/users_spec.rb' - - 'spec/features/proposals_spec.rb' - - 'spec/models/debate_spec.rb' - -# Offense count: 13 +# Offense count: 3 # Cop supports --auto-correct. Lint/StringConversionInInterpolation: Exclude: @@ -308,7 +290,7 @@ Lint/UnusedMethodArgument: - 'app/mailers/mailer.rb' - 'app/models/abilities/everyone.rb' -# Offense count: 278 +# Offense count: 325 Lint/UselessAssignment: Enabled: false @@ -317,35 +299,46 @@ Lint/Void: Exclude: - 'app/controllers/polls_controller.rb' -# Offense count: 74 +# Offense count: 86 Metrics/AbcSize: - Max: 54 + Max: 64 -# Offense count: 454 +# Offense count: 487 # Configuration parameters: CountComments, ExcludedMethods. Metrics/BlockLength: - Max: 1071 - -# Offense count: 8 -# Configuration parameters: CountComments. -Metrics/ClassLength: - Max: 256 + Max: 1227 # Offense count: 10 +# Configuration parameters: CountComments. +Metrics/ClassLength: + Max: 262 + +# Offense count: 13 Metrics/CyclomaticComplexity: Max: 10 -# Offense count: 53 +# Offense count: 25 +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# URISchemes: http, https +Metrics/LineLength: + Max: 248 + +# Offense count: 67 # Configuration parameters: CountComments. Metrics/MethodLength: - Max: 49 + Max: 56 # Offense count: 1 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 214 + Max: 242 -# Offense count: 7 +# Offense count: 3 +# Configuration parameters: CountKeywordArgs. +Metrics/ParameterLists: + Max: 7 + +# Offense count: 8 Metrics/PerceivedComplexity: Max: 11 @@ -399,20 +392,20 @@ Rails/HttpPositionalArguments: - 'spec/controllers/pages_controller_spec.rb' - 'spec/controllers/users/registrations_controller_spec.rb' -# Offense count: 20 +# Offense count: 18 Rails/OutputSafety: Exclude: - 'app/controllers/admin/legislation/draft_versions_controller.rb' - 'app/controllers/admin/legislation/processes_controller.rb' - 'app/controllers/admin/legislation/questions_controller.rb' - 'app/controllers/budgets/investments_controller.rb' + - 'app/controllers/direct_uploads_controller.rb' - 'app/controllers/spending_proposals_controller.rb' - 'app/helpers/application_helper.rb' - 'app/helpers/text_with_links_helper.rb' - - 'app/helpers/users_helper.rb' - 'app/helpers/valuation_helper.rb' -# Offense count: 70 +# Offense count: 71 # Configuration parameters: Blacklist. # Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters Rails/SkipsModelValidations: @@ -428,7 +421,7 @@ Style/AccessorMethodName: - 'app/controllers/proposals_controller.rb' - 'lib/merged_comment_tree.rb' -# Offense count: 1 +# Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: braces, no_braces, context_dependent @@ -438,7 +431,7 @@ Style/BracesAroundHashParameters: - 'spec/features/budgets/investments_spec.rb' - 'spec/features/proposals_spec.rb' -# Offense count: 119 +# Offense count: 123 # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: @@ -451,14 +444,13 @@ Style/ClassVars: - 'app/models/organization.rb' - 'app/models/user.rb' -# Offense count: 12 +# Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, SingleLineConditionsOnly, IncludeTernaryExpressions. # SupportedStyles: assign_to_condition, assign_inside_condition Style/ConditionalAssignment: Exclude: - 'app/controllers/admin/poll/booth_assignments_controller.rb' - - 'app/controllers/admin/poll/officer_assignments_controller.rb' - 'app/controllers/admin/poll/questions_controller.rb' - 'app/controllers/comments_controller.rb' - 'app/controllers/management/spending_proposals_controller.rb' @@ -484,7 +476,7 @@ Style/FileName: Style/GuardClause: Enabled: false -# Offense count: 12 +# Offense count: 11 # Cop supports --auto-correct. # Configuration parameters: MaxLineLength. Style/IfUnlessModifier: @@ -495,19 +487,19 @@ Style/IfUnlessModifier: - 'app/controllers/legislation/annotations_controller.rb' - 'app/controllers/valuation/budget_investments_controller.rb' - 'app/controllers/verification/letter_controller.rb' - - 'app/controllers/welcome_controller.rb' - 'app/helpers/embed_videos_helper.rb' - 'app/mailers/mailer.rb' - 'app/models/proposal.rb' - 'app/models/spending_proposal.rb' -# Offense count: 4 +# Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: line_count_dependent, lambda, literal Style/Lambda: Exclude: - 'app/models/comment.rb' + - 'app/models/concerns/followable.rb' - 'app/models/direct_message.rb' - 'app/models/vote.rb' - 'lib/graph_ql/api_types_creator.rb' @@ -523,7 +515,7 @@ Style/MultilineIfThen: Exclude: - 'app/controllers/management/users_controller.rb' -# Offense count: 15 +# Offense count: 13 # Cop supports --auto-correct. Style/MutableConstant: Exclude: @@ -546,7 +538,7 @@ Style/MutableConstant: Style/NumericLiterals: MinDigits: 9 -# Offense count: 19 +# Offense count: 20 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles. # SupportedStyles: predicate, comparison @@ -574,7 +566,7 @@ Style/ParallelAssignment: - 'lib/active_model/dates.rb' - 'spec/support/common_actions.rb' -# Offense count: 11 +# Offense count: 10 # Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist. # NamePrefix: is_, has_, have_ # NamePrefixBlacklist: is_, has_, have_ @@ -588,7 +580,6 @@ Style/PredicateName: - 'app/helpers/debates_helper.rb' - 'app/models/budget/ballot.rb' - 'app/models/user.rb' - - 'lib/census_api.rb' # Offense count: 4 # Cop supports --auto-correct. @@ -608,13 +599,14 @@ Style/RedundantBegin: - 'app/controllers/graphql_controller.rb' - 'app/models/legislation/annotation.rb' -# Offense count: 3 +# Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. # SupportedStyles: slashes, percent_r, mixed Style/RegexpLiteral: Exclude: - 'app/helpers/embed_videos_helper.rb' + - 'app/models/poll/question/answer/video.rb' - 'spec/customization_engine_spec.rb' # Offense count: 6 @@ -633,22 +625,16 @@ Style/SafeNavigation: Exclude: - 'app/models/signature.rb' -# Offense count: 9 -# Configuration parameters: SupportedStyles. -# SupportedStyles: snake_case, camelCase -Style/VariableName: - EnforcedStyle: snake_case - -# Offense count: 107 +# Offense count: 93 # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: snake_case, normalcase, non_integer Style/VariableNumber: Enabled: false -# Offense count: 31 +# Offense count: 34 # Cop supports --auto-correct. # Configuration parameters: SupportedStyles, WordRegex. # SupportedStyles: percent, brackets Style/WordArray: EnforcedStyle: percent - MinSize: 9 + MinSize: 8 diff --git a/app/controllers/admin/poll/polls_controller.rb b/app/controllers/admin/poll/polls_controller.rb index cce880ed4..5103275fb 100644 --- a/app/controllers/admin/poll/polls_controller.rb +++ b/app/controllers/admin/poll/polls_controller.rb @@ -54,7 +54,7 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController end def poll_params - params.require(:poll).permit(:name, :starts_at, :ends_at, :geozone_restricted, :summary, :description, + params.require(:poll).permit(:name, :starts_at, :ends_at, :geozone_restricted, :summary, :description, geozone_ids: [], image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]) end diff --git a/app/controllers/admin/poll/questions/answers/images_controller.rb b/app/controllers/admin/poll/questions/answers/images_controller.rb index 1bf30907d..030e177a1 100644 --- a/app/controllers/admin/poll/questions/answers/images_controller.rb +++ b/app/controllers/admin/poll/questions/answers/images_controller.rb @@ -5,7 +5,7 @@ class Admin::Poll::Questions::Answers::ImagesController < Admin::Poll::BaseContr end def new - @answer = ::Poll::Question::Answer.find(params[:answer_id]) + @answer = ::Poll::Question::Answer.find(params[:answer_id]) end def create diff --git a/app/controllers/admin/poll/questions/answers/videos_controller.rb b/app/controllers/admin/poll/questions/answers/videos_controller.rb index a231c1a20..e9262b6dd 100644 --- a/app/controllers/admin/poll/questions/answers/videos_controller.rb +++ b/app/controllers/admin/poll/questions/answers/videos_controller.rb @@ -33,11 +33,11 @@ class Admin::Poll::Questions::Answers::VideosController < Admin::Poll::BaseContr end def destroy - if @video.destroy - notice = t("flash.actions.destroy.poll_question_answer_video") - else - notice = t("flash.actions.destroy.error") - end + notice = if @video.destroy + t("flash.actions.destroy.poll_question_answer_video") + else + t("flash.actions.destroy.error") + end redirect_to :back, notice: notice end diff --git a/app/controllers/admin/poll/questions_controller.rb b/app/controllers/admin/poll/questions_controller.rb index 5cf587735..64ecf4009 100644 --- a/app/controllers/admin/poll/questions_controller.rb +++ b/app/controllers/admin/poll/questions_controller.rb @@ -15,7 +15,6 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController def new @polls = Poll.all - @question.valid_answers = I18n.t('poll_questions.default_valid_answers') proposal = Proposal.find(params[:proposal_id]) if params[:proposal_id].present? @question.copy_attributes_from_proposal(proposal) end @@ -56,7 +55,7 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController private def question_params - params.require(:poll_question).permit(:poll_id, :title, :question, :proposal_id, :valid_answers, :video_url) + params.require(:poll_question).permit(:poll_id, :title, :question, :proposal_id, :video_url) end def search_params diff --git a/app/controllers/admin/poll/shifts_controller.rb b/app/controllers/admin/poll/shifts_controller.rb index 1f60b2b4e..89bb68999 100644 --- a/app/controllers/admin/poll/shifts_controller.rb +++ b/app/controllers/admin/poll/shifts_controller.rb @@ -49,7 +49,7 @@ class Admin::Poll::ShiftsController < Admin::Poll::BaseController end def shift_params - shift_params = params.require(:shift).permit(:booth_id, :officer_id, :task, date:[:vote_collection_date, :recount_scrutiny_date]) + shift_params = params.require(:shift).permit(:booth_id, :officer_id, :task, date: [:vote_collection_date, :recount_scrutiny_date]) shift_params.merge(date: shift_params[:date]["#{shift_params[:task]}_date".to_sym]) end end diff --git a/app/controllers/direct_uploads_controller.rb b/app/controllers/direct_uploads_controller.rb index ade7d631f..a067a5d04 100644 --- a/app/controllers/direct_uploads_controller.rb +++ b/app/controllers/direct_uploads_controller.rb @@ -18,8 +18,7 @@ class DirectUploadsController < ApplicationController render json: { cached_attachment: @direct_upload.relation.cached_attachment, filename: @direct_upload.relation.attachment.original_filename, destroy_link: render_destroy_upload_link(@direct_upload).html_safe, - attachment_url: @direct_upload.relation.attachment.url - } + attachment_url: @direct_upload.relation.attachment.url} else @direct_upload.destroy_attachment render json: { errors: @direct_upload.errors[:attachment].join(", ") }, @@ -28,7 +27,7 @@ class DirectUploadsController < ApplicationController end def destroy - @direct_upload = DirectUpload.new(direct_upload_params.merge(user: current_user) ) + @direct_upload = DirectUpload.new(direct_upload_params.merge(user: current_user)) @direct_upload.relation.set_attachment_from_cached_attachment if @direct_upload.destroy_attachment diff --git a/app/controllers/officing/results_controller.rb b/app/controllers/officing/results_controller.rb index 23ef0b038..39adcc7ed 100644 --- a/app/controllers/officing/results_controller.rb +++ b/app/controllers/officing/results_controller.rb @@ -5,7 +5,7 @@ class Officing::ResultsController < Officing::BaseController before_action :load_partial_results, only: :new before_action :load_officer_assignment, only: :create - before_action :check_booth_and_date, only: :create + before_action :check_officer_assignment, only: :create before_action :build_results, only: :create def new @@ -32,13 +32,9 @@ class Officing::ResultsController < Officing::BaseController private - def check_booth_and_date + def check_officer_assignment if @officer_assignment.blank? go_back_to_new(t("officing.results.flash.error_wrong_booth")) - elsif results_params[:date].blank? || - Date.parse(results_params[:date]) < @poll.starts_at.to_date || - Date.parse(results_params[:date]) > @poll.ends_at.to_date - go_back_to_new(t("officing.results.flash.error_wrong_date")) end end @@ -51,11 +47,11 @@ class Officing::ResultsController < Officing::BaseController results.each_pair do |answer_index, count| next if count.blank? - answer = question.valid_answers[answer_index.to_i] + answer = question.question_answers.where(given_order: answer_index.to_i + 1).first.title go_back_to_new if question.blank? partial_result = ::Poll::PartialResult.find_or_initialize_by(booth_assignment_id: @officer_assignment.booth_assignment_id, - date: results_params[:date], + date: Date.current, question_id: question_id, answer: answer) partial_result.officer_assignment_id = @officer_assignment.id @@ -71,7 +67,7 @@ class Officing::ResultsController < Officing::BaseController def build_recounts recount = ::Poll::Recount.find_or_initialize_by(booth_assignment_id: @officer_assignment.booth_assignment_id, - date: results_params[:date]) + date: Date.current) recount.officer_assignment_id = @officer_assignment.id recount.author = current_user recount.origin = 'booth' @@ -84,7 +80,7 @@ class Officing::ResultsController < Officing::BaseController end def go_back_to_new(alert = nil) - params[:d] = results_params[:date] + params[:d] = Date.current params[:oa] = results_params[:officer_assignment_id] flash.now[:alert] = (alert || t("officing.results.flash.error_create")) load_officer_assignments @@ -108,7 +104,7 @@ class Officing::ResultsController < Officing::BaseController final. where(id: current_user.poll_officer.officer_assignment_ids). where("poll_booth_assignments.poll_id = ?", @poll.id). - order(date: :asc) + where(date: Date.current) end def load_partial_results @@ -119,7 +115,7 @@ class Officing::ResultsController < Officing::BaseController end def results_params - params.permit(:officer_assignment_id, :date, :questions, :whites, :nulls, :total) + params.permit(:officer_assignment_id, :questions, :whites, :nulls, :total) end def index_params diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 834c9950d..4dce3bc81 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -25,6 +25,8 @@ class PollsController < ApplicationController @commentable = @poll @comment_tree = CommentTree.new(@commentable, params[:page], @current_order) + + @stats = Poll::Stats.new(@poll).generate end def results diff --git a/app/helpers/documentables_helper.rb b/app/helpers/documentables_helper.rb index 8d9f85578..3fe56abd2 100644 --- a/app/helpers/documentables_helper.rb +++ b/app/helpers/documentables_helper.rb @@ -24,8 +24,8 @@ module DocumentablesHelper def documentable_humanized_accepted_content_types(documentable_class) documentable_class.accepted_content_types - .collect{ |content_type| content_type.split("/").last } - .join(", ") + .collect{ |content_type| content_type.split("/").last } + .join(", ") end def documentables_note(documentable) diff --git a/app/helpers/documents_helper.rb b/app/helpers/documents_helper.rb index d7e8d1dea..70eb6a27f 100644 --- a/app/helpers/documents_helper.rb +++ b/app/helpers/documents_helper.rb @@ -33,7 +33,7 @@ module DocumentsHelper def render_attachment(builder, document) klass = document.errors[:attachment].any? ? "error" : "" - klass = document.persisted? || document.cached_attachment.present? ? " hide" : "" + klass = document.persisted? || document.cached_attachment.present? ? " hide" : "" html = builder.label :attachment, t("documents.form.attachment_label"), class: "button hollow #{klass}" diff --git a/app/helpers/imageables_helper.rb b/app/helpers/imageables_helper.rb index b1c8059ce..8cae1b989 100644 --- a/app/helpers/imageables_helper.rb +++ b/app/helpers/imageables_helper.rb @@ -9,10 +9,10 @@ module ImageablesHelper end def imageable_max_file_size - bytesToMeg(Image::MAX_IMAGE_SIZE) + bytes_to_megabytes(Image::MAX_IMAGE_SIZE) end - def bytesToMeg(bytes) + def bytes_to_megabytes(bytes) bytes / Numeric::MEGABYTE end @@ -22,19 +22,19 @@ module ImageablesHelper def imageable_accepted_content_types_extensions Image::ACCEPTED_CONTENT_TYPE - .collect{ |content_type| ".#{content_type.split("/").last}" } - .join(",") + .collect{ |content_type| ".#{content_type.split('/').last}" } + .join(",") end def imageable_humanized_accepted_content_types Image::ACCEPTED_CONTENT_TYPE - .collect{ |content_type| content_type.split("/").last } - .join(", ") + .collect{ |content_type| content_type.split("/").last } + .join(", ") end - def imageables_note(imageable) + def imageables_note(_imageable) t "images.form.note", accepted_content_types: imageable_humanized_accepted_content_types, max_file_size: imageable_max_file_size end -end \ No newline at end of file +end diff --git a/app/helpers/images_helper.rb b/app/helpers/images_helper.rb index 4e2bdff0e..208ccf5ab 100644 --- a/app/helpers/images_helper.rb +++ b/app/helpers/images_helper.rb @@ -22,7 +22,7 @@ module ImagesHelper image.errors[:attachment].join(', ') if image.errors.key?(:attachment) end - def image_bytesToMeg(bytes) + def image_bytes_to_megabytes(bytes) bytes / Numeric::MEGABYTE end diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb index dd4018be7..0d5b0a605 100644 --- a/app/helpers/polls_helper.rb +++ b/app/helpers/polls_helper.rb @@ -44,7 +44,7 @@ module PollsHelper def poll_voter_token(poll, user) Poll::Voter.where(poll: poll, user: user, origin: "web").first&.token || '' end - + def voted_before_sign_in(question) question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at >= vote.updated_at } end diff --git a/app/helpers/welcome_helper.rb b/app/helpers/welcome_helper.rb index fe1c5f450..0b483468f 100644 --- a/app/helpers/welcome_helper.rb +++ b/app/helpers/welcome_helper.rb @@ -1,11 +1,11 @@ module WelcomeHelper def active_class(index) - "is-active is-in" if index == 0 + "is-active is-in" if index.zero? end def slide_display(index) - "display: none;" if index > 0 + "display: none;" if index.positive? end def recommended_path(recommended) @@ -46,12 +46,12 @@ module WelcomeHelper end def calculate_offset(debates, proposals, apply_offset) - if (debates.any? && proposals.any?) - if apply_offset - offset = "medium-offset-2 large-offset-2" - else - offset = "end" - end + if debates.any? && proposals.any? + offset = if apply_offset + "medium-offset-2 large-offset-2" + else + "end" + end end end diff --git a/app/models/abilities/everyone.rb b/app/models/abilities/everyone.rb index 2a6eaf4aa..e2529f72a 100644 --- a/app/models/abilities/everyone.rb +++ b/app/models/abilities/everyone.rb @@ -23,6 +23,7 @@ module Abilities can [:read], Legislation::Question can [:create], Legislation::Answer can [:search, :comments, :read, :create, :new_comment], Legislation::Annotation + can :read_stats, Poll end end end diff --git a/app/models/concerns/followable.rb b/app/models/concerns/followable.rb index fee1ebd7f..d635cadda 100644 --- a/app/models/concerns/followable.rb +++ b/app/models/concerns/followable.rb @@ -5,7 +5,7 @@ module Followable has_many :follows, as: :followable, dependent: :destroy has_many :followers, through: :follows, source: :user - scope :followed_by_user, -> (user){ + scope :followed_by_user, ->(user){ joins(:follows).where("follows.user_id = ?", user.id) } end diff --git a/app/models/debate.rb b/app/models/debate.rb index eb424c308..65c06345d 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -48,8 +48,8 @@ class Debate < ActiveRecord::Base attr_accessor :link_required def self.recommendations(user) - tagged_with(user.interests, any: true). - where("author_id != ?", user.id) + tagged_with(user.interests, any: true) + .where("author_id != ?", user.id) end def searchable_values diff --git a/app/models/direct_upload.rb b/app/models/direct_upload.rb index e597f9f12..6681aa7be 100644 --- a/app/models/direct_upload.rb +++ b/app/models/direct_upload.rb @@ -7,7 +7,7 @@ class DirectUpload :relation, :resource_relation, :attachment, :cached_attachment, :user - validates_presence_of :attachment, :resource_type, :resource_relation, :user + validates :attachment, :resource_type, :resource_relation, :user, presence: true validate :parent_resource_attachment_validations, if: -> { attachment.present? && resource_type.present? && resource_relation.present? && user.present? } @@ -19,15 +19,15 @@ class DirectUpload if @resource_type.present? && @resource_relation.present? && (@attachment.present? || @cached_attachment.present?) @resource = @resource_type.constantize.find_or_initialize_by(id: @resource_id) - #Refactor - if @resource.respond_to?(:images) && - ((@attachment.present? && !@attachment.content_type.match(/pdf/)) || @cached_attachment.present?) - @relation = @resource.images.send("build", relation_attributtes) - elsif @resource.class.reflections[@resource_relation].macro == :has_one - @relation = @resource.send("build_#{resource_relation}", relation_attributtes) - else - @relation = @resource.send(@resource_relation).build(relation_attributtes) - end + # Refactor + @relation = if @resource.respond_to?(:images) && + ((@attachment.present? && !@attachment.content_type.match(/pdf/)) || @cached_attachment.present?) + @resource.images.send("build", relation_attributtes) + elsif @resource.class.reflections[@resource_relation].macro == :has_one + @resource.send("build_#{resource_relation}", relation_attributtes) + else + @resource.send(@resource_relation).build(relation_attributtes) + end @relation.user = user end @@ -50,7 +50,7 @@ class DirectUpload def parent_resource_attachment_validations @relation.valid? - if @relation.errors.has_key? :attachment + if @relation.errors.key? :attachment errors[:attachment] = @relation.errors[:attachment] end end diff --git a/app/models/document.rb b/app/models/document.rb index f680bc04e..8843bbed9 100644 --- a/app/models/document.rb +++ b/app/models/document.rb @@ -44,7 +44,7 @@ class Document < ActiveRecord::Base attachment.instance.prefix(attachment, style) end - def prefix(attachment, style) + def prefix(attachment, _style) if !attachment.instance.persisted? "cached_attachments/user/#{attachment.instance.user_id}" else diff --git a/app/models/image.rb b/app/models/image.rb index 84b38dd4a..99061f6f1 100644 --- a/app/models/image.rb +++ b/app/models/image.rb @@ -5,7 +5,7 @@ class Image < ActiveRecord::Base TITLE_LEGHT_RANGE = 4..80 MIN_SIZE = 475 MAX_IMAGE_SIZE = 1.megabyte - ACCEPTED_CONTENT_TYPE = %w(image/jpeg image/jpg) + ACCEPTED_CONTENT_TYPE = %w(image/jpeg image/jpg).freeze has_attached_file :attachment, styles: { large: "x#{MIN_SIZE}", medium: "300x300#", thumb: "140x245#" }, url: "/system/:class/:prefix/:style/:hash.:extension", @@ -52,7 +52,7 @@ class Image < ActiveRecord::Base attachment.instance.prefix(attachment, style) end - def prefix(attachment, style) + def prefix(attachment, _style) if !attachment.instance.persisted? "cached_attachments/user/#{attachment.instance.user_id}" else @@ -103,8 +103,8 @@ class Image < ActiveRecord::Base def remove_cached_attachment image = Image.new(imageable: imageable, - cached_attachment: cached_attachment, - user: user) + cached_attachment: cached_attachment, + user: user) image.set_attachment_from_cached_attachment image.attachment.destroy end diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb index 4484060dd..78122188a 100644 --- a/app/models/poll/answer.rb +++ b/app/models/poll/answer.rb @@ -9,9 +9,8 @@ class Poll::Answer < ActiveRecord::Base validates :author, presence: true validates :answer, presence: true - # temporary skipping validation, review when removing valid_answers - # validates :answer, inclusion: { in: ->(a) { a.question.valid_answers }}, - # unless: ->(a) { a.question.blank? } + validates :answer, inclusion: { in: ->(a) { a.question.question_answers.pluck(:title) }}, + unless: ->(a) { a.question.blank? } scope :by_author, ->(author_id) { where(author_id: author_id) } scope :by_question, ->(question_id) { where(question_id: question_id) } diff --git a/app/models/poll/partial_result.rb b/app/models/poll/partial_result.rb index 12b16aa3a..0550650a5 100644 --- a/app/models/poll/partial_result.rb +++ b/app/models/poll/partial_result.rb @@ -10,8 +10,9 @@ class Poll::PartialResult < ActiveRecord::Base validates :question, presence: true validates :author, presence: true validates :answer, presence: true - validates :answer, inclusion: {in: ->(a) { a.question.valid_answers }} - validates :origin, inclusion: {in: VALID_ORIGINS} + validates :answer, inclusion: { in: ->(a) { a.question.question_answers.pluck(:title) }}, + unless: ->(a) { a.question.blank? } + validates :origin, inclusion: { in: VALID_ORIGINS } scope :by_author, ->(author_id) { where(author_id: author_id) } scope :by_question, ->(question_id) { where(question_id: question_id) } diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index 94a68b806..6be729757 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -39,17 +39,12 @@ class Poll::Question < ActiveRecord::Base author_visible_name => 'C' } end - def valid_answers - (super.try(:split, ',')&.compact || []).map(&:strip) - end - def copy_attributes_from_proposal(proposal) if proposal.present? self.author = proposal.author self.author_visible_name = proposal.author.name self.proposal_id = proposal.id self.title = proposal.title - self.valid_answers = I18n.t('poll_questions.default_valid_answers') end end diff --git a/app/models/poll/stats.rb b/app/models/poll/stats.rb new file mode 100644 index 000000000..1df281434 --- /dev/null +++ b/app/models/poll/stats.rb @@ -0,0 +1,125 @@ +class Poll + class Stats + + def initialize(poll) + @poll = poll + end + + def generate + stats = %w[total_participants total_participants_web total_web_valid total_web_white total_web_null + total_participants_booth total_booth_valid total_booth_white total_booth_null + total_valid_votes total_white_votes total_null_votes valid_percentage_web valid_percentage_booth + total_valid_percentage white_percentage_web white_percentage_booth total_white_percentage + null_percentage_web null_percentage_booth total_null_percentage total_participants_web_percentage + total_participants_booth_percentage] + stats.map { |stat_name| [stat_name.to_sym, send(stat_name)] }.to_h + end + + private + + def total_participants + total_participants_web + total_participants_booth + end + + def total_participants_web + total_web_valid + total_web_white + total_web_null + end + + def total_participants_web_percentage + (total_participants) == 0 ? 0 : total_participants_web * 100 / total_participants + end + + def total_participants_booth + voters.where(origin: 'booth').count + end + + def total_participants_booth_percentage + (total_participants) == 0 ? 0 : total_participants_booth * 100 / total_participants.to_f + end + + def total_web_valid + voters.where(origin: 'web').count + end + + def valid_percentage_web + (total_valid_votes) == 0 ? 0 : total_web_valid * 100 / total_valid_votes.to_f + end + + def total_web_white + 0 + end + + def white_percentage_web + 0 + end + + def total_web_null + 0 + end + + def null_percentage_web + 0 + end + + def total_booth_valid + recounts.sum(:total_amount) + end + + def valid_percentage_booth + (total_valid_votes) == 0 ? 0 : total_booth_valid * 100 / total_valid_votes.to_f + end + + def total_booth_white + recounts.sum(:white_amount) + end + + def white_percentage_booth + (total_white_votes) == 0 ? 0 : total_booth_white * 100 / total_white_votes.to_f + end + + def total_booth_null + recounts.sum(:null_amount) + end + + def null_percentage_booth + (total_null_votes == 0) ? 0 : total_booth_null * 100 / total_null_votes.to_f + end + + def total_valid_votes + total_web_valid + total_booth_valid + end + + def total_valid_percentage + (total_participants) == 0 ? 0 : total_valid_votes * 100 / total_participants.to_f + end + + def total_white_votes + total_web_white + total_booth_white + end + + def total_white_percentage + (total_participants) == 0 ? 0 : total_white_votes * 100 / total_participants.to_f + end + + def total_null_votes + total_web_null + total_booth_null + end + + def total_null_percentage + (total_participants) == 0 ? 0 : total_null_votes * 100 / total_participants.to_f + end + + def voters + @poll.voters + end + + def recounts + @poll.recounts + end + + def stats_cache(key, &block) + Rails.cache.fetch("polls_stats/#{@poll.id}/#{key}/v7", &block) + end + + end +end \ No newline at end of file diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb index bc0118a88..778a5d88a 100644 --- a/app/models/poll/voter.rb +++ b/app/models/poll/voter.rb @@ -1,7 +1,7 @@ class Poll class Voter < ActiveRecord::Base - VALID_ORIGINS = %w{ web booth } + VALID_ORIGINS = %w{web booth}.freeze belongs_to :poll belongs_to :user diff --git a/app/models/proposal.rb b/app/models/proposal.rb index 1a688ab30..3b0696d26 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -69,10 +69,10 @@ class Proposal < ActiveRecord::Base scope :public_for_api, -> { all } def self.recommendations(user) - tagged_with(user.interests, any: true). - where("author_id != ?", user.id). - unsuccessful. - not_followed_by_user(user) + tagged_with(user.interests, any: true) + .where("author_id != ?", user.id) + .unsuccessful + .not_followed_by_user(user) end def self.not_followed_by_user(user) diff --git a/app/views/admin/poll/results/index.html.erb b/app/views/admin/poll/results/index.html.erb index c65b3ead7..ab4e94857 100644 --- a/app/views/admin/poll/results/index.html.erb +++ b/app/views/admin/poll/results/index.html.erb @@ -37,11 +37,11 @@ - <% question.valid_answers.each_with_index do |answer, i| %> + <% question.question_answers.each_with_index do |answer, i| %> <% by_answer = by_question[question.id].present? ? by_question[question.id].group_by(&:answer) : {} %> - <%= answer %> - <%= by_answer[answer].present? ? by_answer[answer].sum(&:amount) : 0 %> + <%= answer.title %> + <%= by_answer[answer.title].present? ? by_answer[answer.title].sum(&:amount) : 0 %> <% end %> diff --git a/app/views/officing/results/index.html.erb b/app/views/officing/results/index.html.erb index 924d7fc13..67b6ece0f 100644 --- a/app/views/officing/results/index.html.erb +++ b/app/views/officing/results/index.html.erb @@ -40,11 +40,11 @@ - <% question.valid_answers.each_with_index do |answer, i| %> + <% question.question_answers.each_with_index do |answer, i| %> <% by_answer = by_question[question.id].present? ? by_question[question.id].group_by(&:answer) : {} %> - <%= answer %> - <%= by_answer[answer].present? ? by_answer[answer].first.amount : 0 %> + <%= answer.title %> + <%= by_answer[answer.title].present? ? by_answer[answer.title].first.amount : 0 %> <% end %> diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb index fa5f449fb..a6355ae11 100644 --- a/app/views/officing/results/new.html.erb +++ b/app/views/officing/results/new.html.erb @@ -12,24 +12,14 @@ -
-
- - <%= select_tag :date, - poll_dates_select_options(@poll), - { prompt: t("officing.results.new.select_date"), - label: false } %> -
-
- <% @poll.questions.each do |question| %>

<%= question.title %>

- <% question.valid_answers.each_with_index do |answer, i| %> + <% question.question_answers.each_with_index do |answer, i| %>
- + <%= text_field_tag "questions[#{question.id}][#{i}]", answer_result_value(question.id, i), placeholder: "0" %>
<% end %> @@ -101,4 +91,3 @@ <% end %> - diff --git a/app/views/officing/voters/_already_voted.html.erb b/app/views/officing/voters/_already_voted.html.erb index 1af002b3f..cc144eb09 100644 --- a/app/views/officing/voters/_already_voted.html.erb +++ b/app/views/officing/voters/_already_voted.html.erb @@ -3,6 +3,5 @@ <%= t("officing.voters.show.error_already_voted") %>

- - <%= t("officing.voters.show.no_actions") %> + diff --git a/app/views/polls/_results_subnavigation.html.erb b/app/views/polls/_results_subnavigation.html.erb new file mode 100644 index 000000000..9c2a7e8b0 --- /dev/null +++ b/app/views/polls/_results_subnavigation.html.erb @@ -0,0 +1,20 @@ +
+
+
    +
  • + <%= link_to "#tab-stats" do %> +

    + <%= t("polls.show.stats_menu") %> +

    + <% end %> +
  • +
  • + <%= link_to "#tab-information" do %> +

    + <%= t("polls.show.info_menu") %> +

    + <% end %> +
  • +
+
+
\ No newline at end of file diff --git a/app/views/polls/_show.html.erb b/app/views/polls/_show.html.erb new file mode 100644 index 000000000..ee75ea5e3 --- /dev/null +++ b/app/views/polls/_show.html.erb @@ -0,0 +1,126 @@ +
+
+ <%= render "callout" %> + + <% if @poll.voted_in_booth?(current_user) %> +
+ <%= t("polls.show.already_voted_in_booth") %> +
+ <% else %> + + <% if current_user && @poll.voted_in_web?(current_user) %> +
+ <%= t("polls.show.already_voted_in_web") %> +
+ <% end %> + <% end %> + + <% @questions.each do |question| %> + <%= render 'polls/questions/question', question: question, token: @token %> + <% end %> + + <% if poll_voter_token(@poll, current_user).empty? %> + + <% end %> + + <%= link_to t("polls.show.participate_in_other_polls"), polls_path, class: "button hollow" %> +
+
+ +
+
+
+

<%= t("polls.show.more_info_title") %>

+ <%= safe_html_with_links simple_format(@poll.description) %> +
+ + <% if false %> + + <% end %> +
+
+ +
+
+ + <% @poll_questions_answers.each do |answer| %> +
+ + <% if answer.description.present? %> +

<%= answer.title %>

+ <% end %> + + <% if answer.images.any? %> + <%= render "gallery", answer: answer %> + <% end %> + + <% if answer.description.present? %> + + <% end %> + + <% if answer.documents.present? %> + + <% end %> + + <% if answer.videos.present? %> + + <% end %> +
+ <% end %> +
+ +
+ +
+ <%= render "filter_subnav" %> + +
+ <%= render "comments" %> +
+
\ No newline at end of file diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index f2ad579d4..880d0d421 100644 --- a/app/views/polls/show.html.erb +++ b/app/views/polls/show.html.erb @@ -28,131 +28,17 @@
+ +
+ <%= render "results_subnavigation" %> -
-
- <%= render "callout" %> - - <% if @poll.voted_in_booth?(current_user) %> -
- <%= t("polls.show.already_voted_in_booth") %> -
- <% else %> - - <% if current_user && @poll.voted_in_web?(current_user) %> -
- <%= t("polls.show.already_voted_in_web") %> -
- <% end %> - <% end %> - - <% @questions.each do |question| %> - <%= render 'polls/questions/question', question: question, token: @token %> - <% end %> - - <% if poll_voter_token(@poll, current_user).empty? %> - - <% end %> - - <%= link_to t("polls.show.participate_in_other_polls"), polls_path, class: "button hollow" %> +
+ <%= render "polls/stats/show" %>
-
- -
-
-
-

<%= t("polls.show.more_info_title") %>

- <%= safe_html_with_links simple_format(@poll.description) %> -
- - <% if false %> - - <% end %> -
-
- -
-
- - <% @poll_questions_answers.each do |answer| %> -
- - <% if answer.description.present? %> -

<%= answer.title %>

- <% end %> - - <% if answer.images.any? %> - <%= render "gallery", answer: answer %> - <% end %> - - <% if answer.description.present? %> - - <% end %> - - <% if answer.documents.present? %> - - <% end %> - - <% if answer.videos.present? %> - - <% end %> -
- <% end %> -
- + +
+ <%= render "show" %> +
-
- <%= render "filter_subnav" %> - -
- <%= render "comments" %> -
-
diff --git a/app/views/polls/stats/_show.html.erb b/app/views/polls/stats/_show.html.erb new file mode 100644 index 000000000..1aeb7cf69 --- /dev/null +++ b/app/views/polls/stats/_show.html.erb @@ -0,0 +1,85 @@ +
+ +
+

<%= t("polls.show.stats.total_participation") %>

+ +

+ <%= t("polls.show.stats.total_votes") %>
+ <%= @stats[:total_participants] %> +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
<%= t("polls.show.stats.votes") %><%= t("polls.show.stats.web") %><%= t("polls.show.stats.booth") %><%= t("polls.show.stats.total") %>
<%= t("polls.show.stats.valid") %><%= @stats[:total_web_valid] %> + (<%= number_to_percentage(@stats[:valid_percentage_web], + strip_insignificant_zeros: true, + precision: 2) %>)<%= @stats[:total_booth_valid] %> + (<%= number_to_percentage(@stats[:valid_percentage_booth], + strip_insignificant_zeros: true, + precision: 2) %>)<%= @stats[:total_valid_votes] %> + (<%= number_to_percentage(@stats[:total_valid_percentage], + strip_insignificant_zeros: true, + precision: 2) %>)
<%= t("polls.show.stats.white") %><%= @stats[:total_web_white] %> + (<%= number_to_percentage(@stats[:white_percentage_web], + strip_insignificant_zeros: true, + precision: 2) %>)<%= @stats[:total_booth_white] %> + (<%= number_to_percentage(@stats[:white_percentage_booth], + strip_insignificant_zeros: true, + precision: 2) %>)<%= @stats[:total_white_votes] %> + (<%= number_to_percentage(@stats[:total_white_percentage], + strip_insignificant_zeros: true, + precision: 2) %>)
<%= t("polls.show.stats.null_votes") %><%= @stats[:total_web_null] %> + (<%= number_to_percentage(@stats[:null_percentage_web], + strip_insignificant_zeros: true, + precision: 2) %>)<%= @stats[:total_booth_null] %> + (<%= number_to_percentage(@stats[:null_percentage_booth], + strip_insignificant_zeros: true, + precision: 2) %>)<%= @stats[:total_null_votes] %> + (<%= number_to_percentage(@stats[:total_null_percentage], + strip_insignificant_zeros: true, + precision: 2) %>)
<%= t("polls.show.stats.total") %><%= @stats[:total_participants_web] %> + (<%= number_to_percentage(@stats[:total_participants_web_percentage], + strip_insignificant_zeros: true, + precision: 2) %>)<%= @stats[:total_participants_booth] %> + (<%= number_to_percentage(@stats[:total_participants_booth_percentage], + strip_insignificant_zeros: true, + precision: 2) %>)<%= @stats[:total_participants_web] + @stats[:total_participants_booth] %>
+
+
\ No newline at end of file diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml index bf2cbb712..8ef98b4d1 100644 --- a/config/locales/en/activerecord.yml +++ b/config/locales/en/activerecord.yml @@ -156,7 +156,6 @@ en: description: "Description" poll/question: title: "Question" - valid_answers: "Posibles answers" summary: "Summary" description: "Description" external_url: "Link to additional documentation" diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml index 7b3766471..85bfbe699 100644 --- a/config/locales/en/general.yml +++ b/config/locales/en/general.yml @@ -498,9 +498,21 @@ en: read_less: "Read less about %{answer}" participate_in_other_polls: Participate in other polls videos: "External video" + info_menu: "Information" + stats_menu: "Participation statistics" + stats: + title: "Participation data" + total_participation: "Total participation" + total_votes: "Total amount of given votes" + votes: "VOTES" + web: "WEB" + booth: "BOOTH" + total: "TOTAL" + valid: "Valid" + white: "White votes" + null_votes: "Invalid" poll_questions: create_question: "Create question" - default_valid_answers: "Yes, No" show: vote_answer: "Vote %{answer}" voted: "You have voted %{answer}" diff --git a/config/locales/en/officing.yml b/config/locales/en/officing.yml index bb9ef6bd2..2275bfeb4 100644 --- a/config/locales/en/officing.yml +++ b/config/locales/en/officing.yml @@ -21,14 +21,12 @@ en: create: "Results saved" error_create: "Results NOT saved. Error in data." error_wrong_booth: "Wrong booth. Results NOT saved." - error_wrong_date: "Wrong date. Results NOT saved." new: title: "%{poll} - Add results" not_allowed: "You are allowed to add results for this poll" booth: "Booth" date: "Date" select_booth: "Select booth" - select_date: "Select date" ballots_white: "Totally blank ballots" ballots_null: "Invalid ballots" ballots_total: "Total ballots" @@ -63,7 +61,6 @@ en: show: can_vote: Can vote error_already_voted: Has already participated in this poll - no_actions: There is no available actions submit: Confirm vote success: "Vote introduced!" can_vote: diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml index f61e3bd53..03de3965d 100644 --- a/config/locales/es/activerecord.yml +++ b/config/locales/es/activerecord.yml @@ -150,7 +150,6 @@ es: description: "Descripción" poll/question: title: "Pregunta" - valid_answers: "Posibles respuestas" summary: "Resumen" description: "Descripción" external_url: "Enlace a documentación adicional" diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index 0d2d11a52..a15952cc9 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -498,9 +498,21 @@ es: read_less: "Leer menos sobre %{answer}" participate_in_other_polls: Participar en otras votaciones videos: "Vídeo externo" + info_menu: "Información" + stats_menu: "Estadísticas de participación" + stats: + title: "Datos de participación" + total_participation: "Participación total" + total_votes: "Nº total de votos emitidos" + votes: "VOTOS" + web: "WEB" + booth: "URNAS" + total: "TOTAL" + valid: "Válidos" + white: "En blanco" + null_votes: "Nulos" poll_questions: create_question: "Crear pregunta para votación" - default_valid_answers: "Sí, No" show: vote_answer: "Votar %{answer}" voted: "Has votado %{answer}" diff --git a/config/locales/es/officing.yml b/config/locales/es/officing.yml index 86d6982fc..f9c3213fa 100644 --- a/config/locales/es/officing.yml +++ b/config/locales/es/officing.yml @@ -21,14 +21,12 @@ es: create: "Datos guardados" error_create: "Resultados NO añadidos. Error en los datos" error_wrong_booth: "Urna incorrecta. Resultados NO guardados." - error_wrong_date: "Fecha incorrecta. Resultados NO guardados." new: title: "%{poll} - Añadir resultados" not_allowed: "No tienes permiso para introducir resultados" booth: "Urna" date: "Día" select_booth: "Elige urna" - select_date: "Elige día" ballots_white: "Papeletas totalmente en blanco" ballots_null: "Papeletas nulas" ballots_total: "Papeletas totales" @@ -63,8 +61,7 @@ es: show: can_vote: Puede votar error_already_voted: "Ya ha participado en esta votación" - no_actions: No hay acciones disponibles submit: Confirmar voto success: "¡Voto introducido!" can_vote: - submit_disable_with: "Espera, confirmando voto..." \ No newline at end of file + submit_disable_with: "Espera, confirmando voto..." diff --git a/config/routes.rb b/config/routes.rb index 3a7c1dcae..5ab529a87 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -111,7 +111,7 @@ Rails.application.routes.draw do resources :annotations do get :search, on: :collection end - + resources :polls, only: [:show, :index] do get :results resources :questions, controller: 'polls/questions', shallow: true do diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb index 6b80a0ec5..18bfe0dcb 100644 --- a/db/dev_seeds.rb +++ b/db/dev_seeds.rb @@ -73,7 +73,7 @@ def create_user(email, username = Faker::Name.name) confirmed_at: Time.current, terms_of_service: "1", gender: ['Male', 'Female'].sample, - date_of_birth: rand((Time.current - 80.years) .. (Time.current - 16.years)), + date_of_birth: rand((Time.current - 80.years)..(Time.current - 16.years)), public_activity: (rand(1..100) > 30) ) end @@ -127,7 +127,7 @@ end user = create_user("user#{i}@consul.dev") level = [1, 2, 3].sample if level >= 2 - user.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_number: Faker::Number.number(10), document_type: "1", geozone: Geozone.reorder("RANDOM()").first) + user.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_number: Faker::Number.number(10), document_type: "1", geozone: Geozone.reorder("RANDOM()").first) end if level == 3 user.update(verified_at: Time.current, document_number: Faker::Number.number(10)) @@ -319,7 +319,7 @@ end end 100.times do - voter = not_org_users.level_two_or_three_verified.reorder("RANDOM()").first + voter = not_org_users.level_two_or_three_verified.reorder("RANDOM()").first proposal = Proposal.reorder("RANDOM()").first proposal.vote_by(voter: voter, vote: true) end @@ -504,7 +504,7 @@ Proposal.last(3).each do |proposal| "banner-img banner-img-three"].sample, target_url: Rails.application.routes.url_helpers.proposal_path(proposal), post_started_at: rand((Time.current - 1.week)..(Time.current - 1.day)), - post_ended_at: rand((Time.current - 1.day)..(Time.current + 1.week)), + post_ended_at: rand((Time.current - 1.day)..(Time.current + 1.week)), created_at: rand((Time.current - 1.week)..Time.current)) end @@ -561,13 +561,11 @@ print "Creating Poll Questions" author = User.reorder("RANDOM()").first description = "

#{Faker::Lorem.paragraphs.join('

')}

" open_at = rand(2.months.ago..2.months.from_now) - answers = Faker::Lorem.words((2..4).to_a.sample).map { |answer| answer.capitalize } question = Poll::Question.create!(author: author, title: Faker::Lorem.sentence(3).truncate(60), - valid_answers: answers.join(', '), poll: poll) - answers.each do |answer| - Poll::Question::Answer.create!(question: question, title: answer, description: Faker::ChuckNorris.fact) + Faker::Lorem.words((2..4).to_a.sample).each do |answer| + Poll::Question::Answer.create!(question: question, title: answer.capitalize, description: Faker::ChuckNorris.fact) end end @@ -599,7 +597,10 @@ print "Creating Poll Questions from Proposals" 3.times do proposal = Proposal.reorder("RANDOM()").first poll = Poll.current.first - question = Poll::Question.create(valid_answers: "Yes, No", poll: poll) + question = Poll::Question.create(poll: poll) + Faker::Lorem.words((2..4).to_a.sample).each do |answer| + Poll::Question::Answer.create!(question: question, title: answer.capitalize, description: Faker::ChuckNorris.fact) + end question.copy_attributes_from_proposal(proposal) question.save! end @@ -610,7 +611,10 @@ print "Creating Successful Proposals" 10.times do proposal = Proposal.reorder("RANDOM()").first poll = Poll.current.first - question = Poll::Question.create(valid_answers: "Yes, No", poll: poll) + question = Poll::Question.create(poll: poll) + Faker::Lorem.words((2..4).to_a.sample).each do |answer| + Poll::Question::Answer.create!(question: question, title: answer.capitalize, description: Faker::ChuckNorris.fact) + end question.copy_attributes_from_proposal(proposal) question.save! end @@ -656,8 +660,7 @@ print "Creating legislation processes" allegations_phase_enabled: true, draft_publication_enabled: true, result_publication_enabled: true, - published: true - ) + published: true) end ::Legislation::Process.all.each do |process| diff --git a/lib/census_api.rb b/lib/census_api.rb index 931781c6d..4fdbd37cb 100644 --- a/lib/census_api.rb +++ b/lib/census_api.rb @@ -84,7 +84,7 @@ class CensusApi end def stubbed_response(document_type, document_number) - if document_number == "12345678Z" && document_type == "1" + if (document_number == "12345678Z" || document_number == "12345678Y") && document_type == "1" stubbed_valid_response else stubbed_invalid_response diff --git a/spec/factories.rb b/spec/factories.rb index f7b10bba1..b98fc7adb 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -503,7 +503,13 @@ FactoryGirl.define do poll association :author, factory: :user sequence(:title) { |n| "Question title #{n}" } - valid_answers { Faker::Lorem.words(3).join(', ') } + + trait :with_answers do + after(:create) do |question, _evaluator| + create(:poll_question_answer, question: question, title: "Yes") + create(:poll_question_answer, question: question, title: "No") + end + end end factory :poll_question_answer, class: 'Poll::Question::Answer' do @@ -574,16 +580,16 @@ FactoryGirl.define do end factory :poll_answer, class: 'Poll::Answer' do - association :question, factory: :poll_question + association :question, factory: [:poll_question, :with_answers] association :author, factory: [:user, :level_two] - answer { question.valid_answers.sample } + answer { question.question_answers.sample.title } end factory :poll_partial_result, class: 'Poll::PartialResult' do - association :question, factory: :poll_question + association :question, factory: [:poll_question, :with_answers] association :author, factory: :user origin { 'web' } - answer { question.valid_answers.sample } + answer { question.question_answers.sample.title } end factory :poll_recount, class: 'Poll::Recount' do diff --git a/spec/features/admin/poll/officer_assignments_spec.rb b/spec/features/admin/poll/officer_assignments_spec.rb index 20be138b9..48d10ad39 100644 --- a/spec/features/admin/poll/officer_assignments_spec.rb +++ b/spec/features/admin/poll/officer_assignments_spec.rb @@ -30,9 +30,9 @@ feature 'Officer Assignments' do expect(page).to have_content officer2.name expect(page).to_not have_content officer3.name end - end + end - scenario "Search", :js do + scenario "Search", :js do poll = create(:poll) booth = create(:poll_booth) @@ -62,7 +62,6 @@ feature 'Officer Assignments' do expect(page).to have_content officer2.name expect(page).to_not have_content officer3.name end - end - + end end \ No newline at end of file diff --git a/spec/features/admin/poll/polls_spec.rb b/spec/features/admin/poll/polls_spec.rb index a9a33447f..9c2d3fcf1 100644 --- a/spec/features/admin/poll/polls_spec.rb +++ b/spec/features/admin/poll/polls_spec.rb @@ -261,8 +261,13 @@ feature 'Admin polls' do booth_assignment_2 = create(:poll_booth_assignment, poll: poll) booth_assignment_3 = create(:poll_booth_assignment, poll: poll) - question_1 = create(:poll_question, poll: poll, valid_answers: "Yes,No") - question_2 = create(:poll_question, poll: poll, valid_answers: "Today,Tomorrow") + question_1 = create(:poll_question, poll: poll) + create(:poll_question_answer, title: 'Yes', question: question_1) + create(:poll_question_answer, title: 'No', question: question_1) + + question_2 = create(:poll_question, poll: poll) + create(:poll_question_answer, title: 'Today', question: question_2) + create(:poll_question_answer, title: 'Tomorrow', question: question_2) [booth_assignment_1, booth_assignment_2, booth_assignment_3].each do |ba| create(:poll_partial_result, @@ -279,30 +284,32 @@ feature 'Admin polls' do create(:poll_recount, booth_assignment: booth_assignment_1, white_amount: 21, - null_amount: 44) + null_amount: 44, + total_amount: 66) visit admin_poll_path(poll) click_link "Results" expect(page).to have_content(question_1.title) - question_1.valid_answers.each_with_index do |answer, i| + question_1.question_answers.each_with_index do |answer, i| within("#question_#{question_1.id}_#{i}_result") do - expect(page).to have_content(answer) + expect(page).to have_content(answer.title) expect(page).to have_content([33, 0][i]) end end expect(page).to have_content(question_2.title) - question_2.valid_answers.each_with_index do |answer, i| + question_2.question_answers.each_with_index do |answer, i| within("#question_#{question_2.id}_#{i}_result") do - expect(page).to have_content(answer) + expect(page).to have_content(answer.title) expect(page).to have_content([0, 15][i]) end end within('#white_results') { expect(page).to have_content('21') } within('#null_results') { expect(page).to have_content('44') } + within('#total_results') { expect(page).to have_content('66') } end end end diff --git a/spec/features/admin/poll/shifts_spec.rb b/spec/features/admin/poll/shifts_spec.rb index 35df2e20e..bddd1b6b1 100644 --- a/spec/features/admin/poll/shifts_spec.rb +++ b/spec/features/admin/poll/shifts_spec.rb @@ -102,11 +102,11 @@ feature 'Admin shifts' do shift2 = create(:poll_shift, :recount_scrutiny_task, officer: officer, booth: booth, date: Time.zone.tomorrow) vote_collection_dates = (Date.current..poll.ends_at.to_date).to_a - .reject { |date| date == Time.zone.today } - .map { |date| I18n.l(date, format: :long) } + .reject { |date| date == Time.zone.today } + .map { |date| I18n.l(date, format: :long) } recount_scrutiny_dates = (poll.ends_at.to_date..poll.ends_at.to_date + 1.week).to_a - .reject { |date| date == Time.zone.tomorrow } - .map { |date| I18n.l(date, format: :long) } + .reject { |date| date == Time.zone.tomorrow } + .map { |date| I18n.l(date, format: :long) } visit available_admin_booths_path diff --git a/spec/features/admin/settings_spec.rb b/spec/features/admin/settings_spec.rb index 73d190cb9..40baf6423 100644 --- a/spec/features/admin/settings_spec.rb +++ b/spec/features/admin/settings_spec.rb @@ -87,7 +87,6 @@ feature 'Admin settings' do expect(page).to have_content "Map configuration updated succesfully" end - end end diff --git a/spec/features/comments/polls_spec.rb b/spec/features/comments/polls_spec.rb index 8ef528cd3..0fe01cf06 100644 --- a/spec/features/comments/polls_spec.rb +++ b/spec/features/comments/polls_spec.rb @@ -21,7 +21,7 @@ feature 'Commenting polls' do end scenario 'Show' do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" parent_comment = create(:comment, commentable: poll) first_child = create(:comment, commentable: poll, parent: parent_comment) @@ -243,7 +243,7 @@ feature 'Commenting polls' do end scenario "Flagging as inappropriate", :js do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" comment = create(:comment, commentable: poll) @@ -261,7 +261,7 @@ feature 'Commenting polls' do end scenario "Undoing flagging as inappropriate", :js do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" comment = create(:comment, commentable: poll) Flag.flag(user, comment) @@ -280,7 +280,7 @@ feature 'Commenting polls' do end scenario "Flagging turbolinks sanity check", :js do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" poll = create(:poll, title: "Should we change the world?") comment = create(:comment, commentable: poll) @@ -310,7 +310,7 @@ feature 'Commenting polls' do feature "Moderators" do scenario "can create comment as a moderator", :js do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" moderator = create(:moderator) @@ -330,7 +330,7 @@ feature 'Commenting polls' do end scenario "can create reply as a moderator", :js do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" citizen = create(:user, username: "Ana") manuela = create(:user, username: "Manuela") @@ -359,7 +359,7 @@ feature 'Commenting polls' do end scenario "can not comment as an administrator" do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" moderator = create(:moderator) @@ -372,7 +372,7 @@ feature 'Commenting polls' do feature "Administrators" do scenario "can create comment as an administrator", :js do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" admin = create(:administrator) @@ -392,7 +392,7 @@ feature 'Commenting polls' do end scenario "can create reply as an administrator", :js do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" citizen = create(:user, username: "Ana") manuela = create(:user, username: "Manuela") @@ -421,7 +421,7 @@ feature 'Commenting polls' do end scenario "can not comment as a moderator" do - skip "Feature not implemented yet, review soon" + skip "Feature not implemented yet, review soon" admin = create(:administrator) diff --git a/spec/features/debates_spec.rb b/spec/features/debates_spec.rb index 3d7c6acf8..39cd84760 100644 --- a/spec/features/debates_spec.rb +++ b/spec/features/debates_spec.rb @@ -394,7 +394,7 @@ feature 'Debates' do end scenario 'Debates are ordered by recommendations when there is a user logged', :js do - proposal = create(:proposal, tag_list: "Sport" ) + proposal = create(:proposal, tag_list: "Sport") user = create(:user) create(:follow, followable: proposal, user: user) login_as(user) @@ -830,7 +830,7 @@ feature 'Debates' do debate2 = create(:debate, title: "Show what you got", cached_votes_total: 1, tag_list: "Sport") debate3 = create(:debate, title: "Do not display with same tag", cached_votes_total: 100, tag_list: "Sport") debate4 = create(:debate, title: "Do not display", cached_votes_total: 1) - proposal1 = create(:proposal, tag_list: "Sport") + proposal1 = create(:proposal, tag_list: "Sport") create(:follow, followable: proposal1, user: user) visit debates_path diff --git a/spec/features/emails_spec.rb b/spec/features/emails_spec.rb index a26e8ce11..74b608ed6 100644 --- a/spec/features/emails_spec.rb +++ b/spec/features/emails_spec.rb @@ -408,7 +408,6 @@ feature 'Emails' do end expect(page).to have_content 'It will be done next week.' - email = open_last_email expect(email).to have_subject('Someone has responded to your comment') expect(email).to deliver_to(user1) diff --git a/spec/features/home_spec.rb b/spec/features/home_spec.rb index cb5349814..4854fff4d 100644 --- a/spec/features/home_spec.rb +++ b/spec/features/home_spec.rb @@ -27,7 +27,7 @@ feature "Home" do background do Setting['feature.user.recommendations'] = true user = create(:user) - proposal = create(:proposal, tag_list: "Sport" ) + proposal = create(:proposal, tag_list: "Sport") create(:follow, followable: proposal, user: user) login_as(user) end diff --git a/spec/features/officing/results_spec.rb b/spec/features/officing/results_spec.rb index f7e1ad8ef..252d4edd6 100644 --- a/spec/features/officing/results_spec.rb +++ b/spec/features/officing/results_spec.rb @@ -7,8 +7,13 @@ feature 'Officing Results' do @officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer) @poll = @officer_assignment.booth_assignment.poll @poll.update(ends_at: 1.day.ago) - @question_1 = create(:poll_question, poll: @poll, valid_answers: "Yes,No") - @question_2 = create(:poll_question, poll: @poll, valid_answers: "Today,Tomorrow") + @question_1 = create(:poll_question, poll: @poll) + create(:poll_question_answer, title: 'Yes', question: @question_1) + create(:poll_question_answer, title: 'No', question: @question_1) + @question_2 = create(:poll_question, poll: @poll) + create(:poll_question_answer, title: 'Today', question: @question_2) + create(:poll_question_answer, title: 'Tomorrow', question: @question_2) + login_as(@poll_officer.user) end @@ -53,9 +58,7 @@ feature 'Officing Results' do expect(page).to_not have_content('Your results') booth_name = @officer_assignment.booth_assignment.booth.name - date = I18n.l(@poll.starts_at.to_date, format: :long) select booth_name, from: 'officer_assignment_id' - select date, from: 'date' fill_in "questions[#{@question_1.id}][0]", with: '100' fill_in "questions[#{@question_1.id}][1]", with: '200' @@ -71,8 +74,8 @@ feature 'Officing Results' do expect(page).to have_content('Your results') - within("#results_#{@officer_assignment.booth_assignment_id}_#{@poll.starts_at.to_date.strftime('%Y%m%d')}") do - expect(page).to have_content(date) + within("#results_#{@officer_assignment.booth_assignment_id}_#{Date.current.strftime('%Y%m%d')}") do + expect(page).to have_content(I18n.l(Date.current, format: :long)) expect(page).to have_content(booth_name) end end @@ -81,9 +84,9 @@ feature 'Officing Results' do partial_result = create(:poll_partial_result, officer_assignment: @officer_assignment, booth_assignment: @officer_assignment.booth_assignment, - date: @poll.starts_at, + date: Date.current, question: @question_1, - answer: @question_1.valid_answers[0], + answer: @question_1.question_answers.first.title, author: @poll_officer.user, amount: 7777) @@ -94,9 +97,7 @@ feature 'Officing Results' do visit new_officing_poll_result_path(@poll) booth_name = partial_result.booth_assignment.booth.name - date = I18n.l(partial_result.date, format: :long) select booth_name, from: 'officer_assignment_id' - select date, from: 'date' fill_in "questions[#{@question_1.id}][0]", with: '5555' fill_in "questions[#{@question_1.id}][1]", with: '200' @@ -143,13 +144,13 @@ feature 'Officing Results' do expect(page).to have_content(@officer_assignment.booth_assignment.booth.name) expect(page).to have_content(@question_1.title) - @question_1.valid_answers.each_with_index do |answer, i| - within("#question_#{@question_1.id}_#{i}_result") { expect(page).to have_content(answer) } + @question_1.question_answers.each_with_index do |answer, i| + within("#question_#{@question_1.id}_#{i}_result") { expect(page).to have_content(answer.title) } end expect(page).to have_content(@question_2.title) - @question_2.valid_answers.each_with_index do |answer, i| - within("#question_#{@question_2.id}_#{i}_result") { expect(page).to have_content(answer) } + @question_2.question_answers.each_with_index do |answer, i| + within("#question_#{@question_2.id}_#{i}_result") { expect(page).to have_content(answer.title) } end within('#white_results') { expect(page).to have_content('21') } diff --git a/spec/features/officing_spec.rb b/spec/features/officing_spec.rb index 2a54bbff1..338b416ea 100644 --- a/spec/features/officing_spec.rb +++ b/spec/features/officing_spec.rb @@ -107,7 +107,7 @@ feature 'Poll Officing' do expect(page).to_not have_css('#moderation_menu') end - scenario 'Officing dashboard available for multiple sessions' do + scenario 'Officing dashboard available for multiple sessions', :js do poll = create(:poll) booth = create(:poll_booth) booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) @@ -117,6 +117,9 @@ feature 'Poll Officing' do officer1 = create(:poll_officer, user: user1) officer2 = create(:poll_officer, user: user2) + create(:poll_shift, officer: officer1, booth: booth, date: Date.current, task: :vote_collection) + create(:poll_shift, officer: officer2, booth: booth, date: Date.current, task: :vote_collection) + officer_assignment_1 = create(:poll_officer_assignment, booth_assignment: booth_assignment, officer: officer1) officer_assignment_2 = create(:poll_officer_assignment, booth_assignment: booth_assignment, officer: officer2) @@ -134,7 +137,14 @@ feature 'Poll Officing' do page.should have_content("Here you can validate user documents and store voting results") visit new_officing_residence_path - page.should have_content("Validate document") + select 'DNI', from: 'residence_document_type' + fill_in 'residence_document_number', with: "12345678Z" + fill_in 'residence_year_of_birth', with: '1980' + click_button 'Validate document' + expect(page).to have_content 'Document verified with Census' + click_button "Confirm vote" + expect(page).to have_content "Vote introduced!" + expect(Poll::Voter.where(document_number: '12345678Z', poll_id: poll, origin: 'booth', officer_id: officer1).count).to be(1) visit final_officing_polls_path page.should have_content("Polls ready for final recounting") @@ -144,7 +154,14 @@ feature 'Poll Officing' do page.should have_content("Here you can validate user documents and store voting results") visit new_officing_residence_path - page.should have_content("Validate document") + select 'DNI', from: 'residence_document_type' + fill_in 'residence_document_number', with: "12345678Y" + fill_in 'residence_year_of_birth', with: '1980' + click_button 'Validate document' + expect(page).to have_content 'Document verified with Census' + click_button "Confirm vote" + expect(page).to have_content "Vote introduced!" + expect(Poll::Voter.where(document_number: '12345678Y', poll_id: poll, origin: 'booth', officer_id: officer2).count).to be(1) visit final_officing_polls_path page.should have_content("Polls ready for final recounting") diff --git a/spec/features/polls/polls_spec.rb b/spec/features/polls/polls_spec.rb index e36720038..7bf51473f 100644 --- a/spec/features/polls/polls_spec.rb +++ b/spec/features/polls/polls_spec.rb @@ -367,4 +367,17 @@ feature 'Polls' do end end + + context "Results and stats" do + scenario "See polls statistics", :js do + user = create(:user) + poll = create(:poll, summary: "Summary", description: "Description") + login_as user + visit poll_path(poll) + + click_link "Participation statistics" + + expect(page).to have_content("Total participation") + end + end end diff --git a/spec/features/polls/voter_spec.rb b/spec/features/polls/voter_spec.rb index d5770cd0e..ff9b71755 100644 --- a/spec/features/polls/voter_spec.rb +++ b/spec/features/polls/voter_spec.rb @@ -147,10 +147,36 @@ feature "Voter" do expect(page).to have_link('Yes') expect(page).to have_link('No') end - end end + scenario "Voting in poll and then verifiying account", :js do + user = create(:user) + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Yes') + answer2 = create(:poll_question_answer, question: question, title: 'No') + + login_through_form_as_officer(officer.user) + vote_for_poll_via_booth + + visit root_path + click_link "Sign out" + + login_as user + visit account_path + click_link 'Verify my account' + + verify_residence + confirm_phone(user) + + visit poll_path(poll) + + expect(page).to_not have_link('Yes') + expect(page).to have_content "You have already participated in a physical booth. You can not participate again." + expect(Poll::Voter.count).to eq(1) + end + end end diff --git a/spec/models/debate_spec.rb b/spec/models/debate_spec.rb index 64dbf729f..3e1278bd7 100644 --- a/spec/models/debate_spec.rb +++ b/spec/models/debate_spec.rb @@ -725,10 +725,10 @@ describe Debate do end it "Should return debates ordered by cached_votes_total" do - debate1 = create(:debate, cached_votes_total: 1, tag_list: "Sport" ) - debate2 = create(:debate, cached_votes_total: 5, tag_list: "Sport" ) - debate3 = create(:debate, cached_votes_total: 10, tag_list: "Sport" ) - proposal = create(:proposal, tag_list: "Sport" ) + debate1 = create(:debate, cached_votes_total: 1, tag_list: "Sport") + debate2 = create(:debate, cached_votes_total: 5, tag_list: "Sport") + debate3 = create(:debate, cached_votes_total: 10, tag_list: "Sport") + proposal = create(:proposal, tag_list: "Sport") create(:follow, followable: proposal, user: user) result = Debate.recommendations(user).sort_by_recommendations @@ -741,7 +741,7 @@ describe Debate do it "Should return debates related with user interests" do debate1 = create(:debate, tag_list: "Sport") debate2 = create(:debate, tag_list: "Politics") - proposal1 = create(:proposal, tag_list: "Sport") + proposal1 = create(:proposal, tag_list: "Sport") create(:follow, followable: proposal1, user: user) result = Debate.recommendations(user) @@ -753,7 +753,7 @@ describe Debate do it "Should not return debates when user is the author" do debate1 = create(:debate, author: user, tag_list: "Sport") debate2 = create(:debate, tag_list: "Sport") - proposal = create(:proposal, tag_list: "Sport" ) + proposal = create(:proposal, tag_list: "Sport") create(:follow, followable: proposal, user: user) result = Debate.recommendations(user) diff --git a/spec/models/direct_upload_spec.rb b/spec/models/direct_upload_spec.rb index 5abe06765..8cfebf076 100644 --- a/spec/models/direct_upload_spec.rb +++ b/spec/models/direct_upload_spec.rb @@ -42,7 +42,7 @@ describe DirectUpload do proposal_document_direct_upload.save_attachment - expect(File.exists?(proposal_document_direct_upload.relation.attachment.path)).to eq(true) + expect(File.exist?(proposal_document_direct_upload.relation.attachment.path)).to eq(true) expect(proposal_document_direct_upload.relation.attachment.path).to include('cached_attachments') end @@ -57,7 +57,7 @@ describe DirectUpload do uploaded_path = proposal_document_direct_upload.relation.attachment.path proposal_document_direct_upload.destroy_attachment - expect(File.exists?(uploaded_path)).to eq(false) + expect(File.exist?(uploaded_path)).to eq(false) end end diff --git a/spec/models/map_location_spec.rb b/spec/models/map_location_spec.rb index bd093a71e..62070529e 100644 --- a/spec/models/map_location_spec.rb +++ b/spec/models/map_location_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' describe MapLocation do - let(:map_location) { build(:map_location, :proposal_map_location ) } + let(:map_location) { build(:map_location, :proposal_map_location) } it "should be valid" do expect(map_location).to be_valid diff --git a/spec/models/poll/answer_spec.rb b/spec/models/poll/answer_spec.rb index 8731445cc..33cf833b6 100644 --- a/spec/models/poll/answer_spec.rb +++ b/spec/models/poll/answer_spec.rb @@ -25,9 +25,12 @@ describe Poll::Answer do expect(answer).to_not be_valid end - it "should be valid for answers included in the Poll::Question's list" do - skip "review when removing valid_answers" - question = create(:poll_question, valid_answers: 'One, Two, Three') + it "should be valid for answers included in the Poll::Question's question_answers list" do + question = create(:poll_question) + create(:poll_question_answer, title: 'One', question: question) + create(:poll_question_answer, title: 'Two', question: question) + create(:poll_question_answer, title: 'Three', question: question) + expect(build(:poll_answer, question: question, answer: 'One')).to be_valid expect(build(:poll_answer, question: question, answer: 'Two')).to be_valid expect(build(:poll_answer, question: question, answer: 'Three')).to be_valid @@ -40,7 +43,7 @@ describe Poll::Answer do let(:author) { create(:user, :level_two) } let(:poll) { create(:poll) } - let(:question) { create(:poll_question, poll: poll, valid_answers: "Yes, No") } + let(:question) { create(:poll_question, :with_answers, poll: poll) } it "creates a poll_voter with user and poll data" do answer = create(:poll_answer, question: question, author: author, answer: "Yes") diff --git a/spec/models/poll/partial_result_spec.rb b/spec/models/poll/partial_result_spec.rb index dd6176a06..316b17524 100644 --- a/spec/models/poll/partial_result_spec.rb +++ b/spec/models/poll/partial_result_spec.rb @@ -4,12 +4,16 @@ describe Poll::PartialResult do describe "validations" do it "validates that the answers are included in the Poll::Question's list" do - q = create(:poll_question, valid_answers: 'One, Two, Three') - expect(build(:poll_partial_result, question: q, answer: 'One')).to be_valid - expect(build(:poll_partial_result, question: q, answer: 'Two')).to be_valid - expect(build(:poll_partial_result, question: q, answer: 'Three')).to be_valid + question = create(:poll_question) + create(:poll_question_answer, title: 'One', question: question) + create(:poll_question_answer, title: 'Two', question: question) + create(:poll_question_answer, title: 'Three', question: question) - expect(build(:poll_partial_result, question: q, answer: 'Four')).to_not be_valid + expect(build(:poll_partial_result, question: question, answer: 'One')).to be_valid + expect(build(:poll_partial_result, question: question, answer: 'Two')).to be_valid + expect(build(:poll_partial_result, question: question, answer: 'Three')).to be_valid + + expect(build(:poll_partial_result, question: question, answer: 'Four')).to_not be_valid end end @@ -57,24 +61,24 @@ describe Poll::PartialResult do expect(partial_result.amount_log).to eq("") expect(partial_result.author_id_log).to eq("") - author_A = create(:poll_officer).user - author_B = create(:poll_officer).user - author_C = create(:poll_officer).user + author1 = create(:poll_officer).user + author2 = create(:poll_officer).user + author3 = create(:poll_officer).user partial_result.amount = 33 - partial_result.author_id = author_A.id + partial_result.author_id = author1.id partial_result.save! partial_result.amount = 32 - partial_result.author_id = author_B.id + partial_result.author_id = author2.id partial_result.save! partial_result.amount = 34 - partial_result.author_id = author_C.id + partial_result.author_id = author3.id partial_result.save! expect(partial_result.amount_log).to eq(":33:32") - expect(partial_result.author_id_log).to eq(":#{author_A.id}:#{author_B.id}") + expect(partial_result.author_id_log).to eq(":#{author1.id}:#{author2.id}") end end diff --git a/spec/models/poll/question_spec.rb b/spec/models/poll/question_spec.rb index 60f9d6716..8c8a94d35 100644 --- a/spec/models/poll/question_spec.rb +++ b/spec/models/poll/question_spec.rb @@ -3,13 +3,6 @@ require 'rails_helper' RSpec.describe Poll::Question, type: :model do let(:poll_question) { build(:poll_question) } - describe "#valid_answers" do - it "gets a comma-separated string, but returns an array" do - poll_question.valid_answers = "Yes, No" - expect(poll_question.valid_answers).to eq(["Yes", "No"]) - end - end - describe "#poll_question_id" do it "should be invalid if a poll is not selected" do poll_question.poll_id = nil @@ -27,7 +20,6 @@ RSpec.describe Poll::Question, type: :model do create_list(:geozone, 3) p = create(:proposal) poll_question.copy_attributes_from_proposal(p) - expect(poll_question.valid_answers).to eq(['Yes', 'No']) expect(poll_question.author).to eq(p.author) expect(poll_question.author_visible_name).to eq(p.author.name) expect(poll_question.proposal_id).to eq(p.id) diff --git a/spec/models/poll/stats_spec.rb b/spec/models/poll/stats_spec.rb new file mode 100644 index 000000000..ee431fa97 --- /dev/null +++ b/spec/models/poll/stats_spec.rb @@ -0,0 +1,45 @@ +require 'rails_helper' + +describe Poll::Stats do + + describe "Calculate stats" do + it "Generate the correct stats" do + poll = create(:poll) + booth = create(:poll_booth) + booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + create(:poll_voter, poll: poll, origin: 'web') + 3.times {create(:poll_voter, poll: poll, origin: 'booth')} + create(:poll_voter, poll: poll) + create(:poll_recount, origin: 'booth', white_amount: 1, null_amount: 0, total_amount: 2, booth_assignment_id: booth_assignment.id) + stats = Poll::Stats.new(poll).generate + + expect(stats[:total_participants]).to eq(5) + expect(stats[:total_participants_web]).to eq(2) + expect(stats[:total_participants_booth]).to eq(3) + expect(stats[:total_valid_votes]).to eq(4) + expect(stats[:total_white_votes]).to eq(1) + expect(stats[:total_null_votes]).to eq(0) + + expect(stats[:total_web_valid]).to eq(2) + expect(stats[:total_web_white]).to eq(0) + expect(stats[:total_web_null]).to eq(0) + + expect(stats[:total_booth_valid]).to eq(2) + expect(stats[:total_booth_white]).to eq(1) + expect(stats[:total_booth_null]).to eq(0) + + expect(stats[:total_participants_web_percentage]).to eq(40) + expect(stats[:total_participants_booth_percentage]).to eq(60) + expect(stats[:valid_percentage_web]).to eq(50) + expect(stats[:white_percentage_web]).to eq(0) + expect(stats[:null_percentage_web]).to eq(0) + expect(stats[:valid_percentage_booth]).to eq(50) + expect(stats[:white_percentage_booth]).to eq(100) + expect(stats[:null_percentage_booth]).to eq(0) + expect(stats[:total_valid_percentage]).to eq(80) + expect(stats[:total_white_percentage]).to eq(20) + expect(stats[:total_null_percentage]).to eq(0) + end + end + +end \ No newline at end of file diff --git a/spec/models/proposal_spec.rb b/spec/models/proposal_spec.rb index 588bd4057..29338a62f 100644 --- a/spec/models/proposal_spec.rb +++ b/spec/models/proposal_spec.rb @@ -903,10 +903,10 @@ describe Proposal do end it "Should return proposals ordered by cached_votes_up" do - proposal1 = create(:proposal, cached_votes_up: 1, tag_list: "Sport" ) - proposal2 = create(:proposal, cached_votes_up: 5, tag_list: "Sport" ) - proposal3 = create(:proposal, cached_votes_up: 10, tag_list: "Sport" ) - proposal4 = create(:proposal, tag_list: "Sport" ) + proposal1 = create(:proposal, cached_votes_up: 1, tag_list: "Sport") + proposal2 = create(:proposal, cached_votes_up: 5, tag_list: "Sport") + proposal3 = create(:proposal, cached_votes_up: 10, tag_list: "Sport") + proposal4 = create(:proposal, tag_list: "Sport") create(:follow, followable: proposal4, user: user) result = Proposal.recommendations(user).sort_by_recommendations diff --git a/spec/shared/features/mappable.rb b/spec/shared/features/mappable.rb index ccbcd5625..65ece1f25 100644 --- a/spec/shared/features/mappable.rb +++ b/spec/shared/features/mappable.rb @@ -2,7 +2,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, include ActionView::Helpers - let!(:user) { create(:user, :level_two) } + let!(:user) { create(:user, :level_two) } before do Setting['feature.map'] = true @@ -11,7 +11,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, describe "At #{mappable_new_path}" do let!(:arguments) { {} } - let!(:mappable) { create("#{mappable_factory_name}".to_sym) } + let!(:mappable) { create(mappable_factory_name.to_s.to_sym) } let!(:map_location) { create(:map_location, "#{mappable_factory_name}_map_location".to_sym, "#{mappable_association_name}": mappable) } before { set_arguments(arguments, mappable, mappable_path_arguments) } @@ -77,10 +77,10 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, describe "At #{mappable_edit_path}" do - let!(:mappable) { create("#{mappable_factory_name}".to_sym) } + let!(:mappable) { create(mappable_factory_name.to_s.to_sym) } let!(:map_location) { create(:map_location, "#{mappable_factory_name}_map_location".to_sym, "#{mappable_association_name}": mappable) } - before { skip } unless mappable_edit_path.present? + before { skip } if mappable_edit_path.blank? scenario "Should edit map on #{mappable_factory_name} and contain default values", :js do login_as mappable.author @@ -143,13 +143,13 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, describe "At #{mappable_show_path}" do let!(:arguments) { {} } - let!(:mappable) { create("#{mappable_factory_name}".to_sym) } + let!(:mappable) { create(mappable_factory_name.to_s.to_sym) } let!(:map_location) { create(:map_location, "#{mappable_factory_name}_map_location".to_sym, "#{mappable_association_name}": mappable) } before { set_arguments(arguments, mappable, mappable_path_arguments) } scenario "Should display map on #{mappable_factory_name} show page", :js do - arguments.merge!("id": mappable.id) + arguments[:id] = mappable.id visit send(mappable_show_path, arguments) @@ -157,9 +157,9 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, end scenario "Should not display map on #{mappable_factory_name} show when marker is not defined", :js do - mappable_without_map = create("#{mappable_factory_name}".to_sym) + mappable_without_map = create(mappable_factory_name.to_s.to_sym) set_arguments(arguments, mappable_without_map, mappable_path_arguments) - arguments.merge!("id": mappable_without_map.id) + arguments[:id] = mappable_without_map.id visit send(mappable_show_path, arguments) @@ -168,7 +168,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, scenario "Should not display map on #{mappable_factory_name} show page when feature.map is disable", :js do Setting['feature.map'] = false - arguments.merge!("id": mappable.id) + arguments[:id] = mappable.id visit send(mappable_show_path, arguments) @@ -212,9 +212,7 @@ def submit_budget_investment_form end def set_arguments(arguments, mappable, mappable_path_arguments) - if mappable_path_arguments - mappable_path_arguments.each do |argument_name, path_to_value| + mappable_path_arguments&.each do |argument_name, path_to_value| arguments.merge!("#{argument_name}": mappable.send(path_to_value)) - end end end diff --git a/spec/shared/features/nested_documentable.rb b/spec/shared/features/nested_documentable.rb index 24d6631a8..3661af408 100644 --- a/spec/shared/features/nested_documentable.rb +++ b/spec/shared/features/nested_documentable.rb @@ -199,8 +199,8 @@ shared_examples "nested documentable" do |login_as_name, documentable_factory_na find("#tab-documents-label").click expect(page).to have_content "empty.pdf" - #Review - #Doble check why the file is stored with a name different to empty.pdf + # Review + # Doble check why the file is stored with a name different to empty.pdf expect(page).to have_css("a[href$='.pdf']") end diff --git a/spec/shared/features/nested_imageable.rb b/spec/shared/features/nested_imageable.rb index 1eef9a269..947887afa 100644 --- a/spec/shared/features/nested_imageable.rb +++ b/spec/shared/features/nested_imageable.rb @@ -1,4 +1,4 @@ -shared_examples "nested imageable" do |imageable_factory_name, path, imageable_path_arguments, fill_resource_method_name, submit_button, imageable_success_notice, has_many_images=false| +shared_examples "nested imageable" do |imageable_factory_name, path, imageable_path_arguments, fill_resource_method_name, submit_button, imageable_success_notice, has_many_images = false| include ActionView::Helpers include ImagesHelper include ImageablesHelper @@ -9,15 +9,11 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p let!(:imageable) { create(imageable_factory_name) } before do - if imageable_path_arguments - imageable_path_arguments.each do |argument_name, path_to_value| + imageable_path_arguments&.each do |argument_name, path_to_value| arguments.merge!("#{argument_name}": imageable.send(path_to_value)) - end end - if imageable.respond_to?(:author) - imageable.update(author: user) - end + imageable.update(author: user) if imageable.respond_to?(:author) end describe "at #{path}" do @@ -119,7 +115,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p click_on submit_button if has_many_images - #Pending. Review soon and test + # Pending. Review soon and test else within "#nested-image .image" do expect(page).to have_content("can't be blank", count: 2) @@ -174,7 +170,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p imageable_redirected_to_resource_show_or_navigate_to if has_many_images - #Pending. Review soon and test + # Pending. Review soon and test else expect(page).to have_selector "figure img" expect(page).to have_selector "figure figcaption" @@ -230,7 +226,7 @@ rescue return end -def imageable_attach_new_file(imageable_factory_name, path, success = true) +def imageable_attach_new_file(_imageable_factory_name, path, success = true) click_link "Add image" within "#nested-image" do image = find(".image") diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb index 256b070e4..b87a54d8e 100644 --- a/spec/support/common_actions.rb +++ b/spec/support/common_actions.rb @@ -163,14 +163,15 @@ module CommonActions expect(page).to have_content 'Document verified with Census' end - def confirm_phone + def confirm_phone(user = nil) + user ||= User.last + fill_in 'sms_phone', with: "611111111" click_button 'Send' expect(page).to have_content 'Enter the confirmation code sent to you by text message' - user = User.last.reload - fill_in 'sms_confirmation_code', with: user.sms_confirmation_code + fill_in 'sms_confirmation_code', with: user.reload.sms_confirmation_code click_button 'Send' expect(page).to have_content 'Code correct'