From 67d13d289930a3372a6d5cc7aab8c35685060b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Tue, 6 Sep 2022 01:50:00 +0200 Subject: [PATCH 1/9] Show the time when a poll starts and ends This is consistent with the way we show the duration of a budget and its phases. Since budgets are the section with the most recent changes in the admin area, we're using it as a reference. Note that, unlike budgets (which are shown to finish at the beginning of their ending day), a poll has always been considered to finish at the end of their ending day, so we're showing it this way. We're also solving a minor usability issue. While it's pretty intuitive that a poll starting on a certain date will start at the beginning of the day, a poll ending on a certain date isn't clear about when it finishes exactly: is it at the beginning of the day, or at the end of the day? So now we're making this point clear. --- app/views/admin/poll/polls/_poll.html.erb | 4 ++-- app/views/admin/poll/polls/_poll_header.html.erb | 2 +- spec/system/admin/poll/polls_spec.rb | 6 +++--- spec/system/budget_polls/budgets_spec.rb | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/views/admin/poll/polls/_poll.html.erb b/app/views/admin/poll/polls/_poll.html.erb index a578bfe60..8f477c586 100644 --- a/app/views/admin/poll/polls/_poll.html.erb +++ b/app/views/admin/poll/polls/_poll.html.erb @@ -1,7 +1,7 @@ <%= poll.name %> - <%= l poll.starts_at.to_date %> - <%= l poll.ends_at.to_date %> + <%= l poll.starts_at.beginning_of_day, format: :short_datetime %> + <%= l poll.ends_at.end_of_day, format: :short_datetime %> <% if feature?(:sdg) %> <%= poll.sdg_goal_list %> <%= poll.sdg_target_list %> diff --git a/app/views/admin/poll/polls/_poll_header.html.erb b/app/views/admin/poll/polls/_poll_header.html.erb index 2b1ade5fb..ef24e0e0c 100644 --- a/app/views/admin/poll/polls/_poll_header.html.erb +++ b/app/views/admin/poll/polls/_poll_header.html.erb @@ -12,7 +12,7 @@
<%= t("admin.polls.index.dates") %>
- <%= l @poll.starts_at.to_date %> - <%= l @poll.ends_at.to_date %> + <%= render Admin::DateRangeComponent.new(@poll.starts_at.beginning_of_day, @poll.ends_at.end_of_day) %>
<% if @poll.geozone_restricted %> diff --git a/spec/system/admin/poll/polls_spec.rb b/spec/system/admin/poll/polls_spec.rb index ede4bd5f3..7bd857ecc 100644 --- a/spec/system/admin/poll/polls_spec.rb +++ b/spec/system/admin/poll/polls_spec.rb @@ -67,8 +67,8 @@ describe "Admin polls", :admin do expect(page).to have_content "Poll created successfully" expect(page).to have_content "Upcoming poll" - expect(page).to have_content I18n.l(start_date) - expect(page).to have_content I18n.l(end_date) + expect(page).to have_content "#{I18n.l(start_date)} 00:00" + expect(page).to have_content "#{I18n.l(end_date)} 23:59" visit poll_path(id: "upcoming-poll") @@ -93,7 +93,7 @@ describe "Admin polls", :admin do expect(page).to have_content "Poll updated successfully" expect(page).to have_content "Next Poll" - expect(page).to have_content I18n.l(end_date.to_date) + expect(page).to have_content "#{I18n.l(end_date)} 23:59" end scenario "Edit from index" do diff --git a/spec/system/budget_polls/budgets_spec.rb b/spec/system/budget_polls/budgets_spec.rb index bb5152f76..6a4f1c56b 100644 --- a/spec/system/budget_polls/budgets_spec.rb +++ b/spec/system/budget_polls/budgets_spec.rb @@ -12,8 +12,8 @@ describe "Admin Budgets", :admin do expect(page).to have_current_path(/admin\/polls\/\d+/) expect(page).to have_content(budget.name) - expect(page).to have_content(balloting_phase.starts_at.to_date) - expect(page).to have_content(balloting_phase.ends_at.to_date) + expect(page).to have_content("#{balloting_phase.starts_at.to_date} 00:00") + expect(page).to have_content("#{balloting_phase.ends_at.to_date} 23:59") end scenario "Create poll in current locale if the budget does not have a poll associated" do From 7227815a16dd829735ed5ee28eeed74d364682d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Tue, 6 Sep 2022 10:02:14 +0200 Subject: [PATCH 2/9] Split duration component in two We were displaying dates in two different formats in the same component, leading to strange hacks like manually calling the `call` method or not being able to use `render_inline` in the tests. Since we're going to reuse one of these formats outside the budgets section, we're splitting the component. We're also removing the mentioned hacks. --- .../admin/budget_phases/phases_component.rb | 2 +- .../admin/budgets/duration_component.rb | 25 ------- .../duration_in_words_component.html.erb | 1 + .../budgets/duration_in_words_component.rb | 17 +++++ .../admin/budgets/index_component.rb | 4 +- .../admin/duration_component.html.erb | 1 + app/components/admin/duration_component.rb | 21 ++++++ .../admin/budgets/duration_component_spec.rb | 73 ------------------- .../duration_in_words_component_spec.rb | 30 ++++++++ .../admin/duration_component_spec.rb | 32 ++++++++ 10 files changed, 105 insertions(+), 101 deletions(-) delete mode 100644 app/components/admin/budgets/duration_component.rb create mode 100644 app/components/admin/budgets/duration_in_words_component.html.erb create mode 100644 app/components/admin/budgets/duration_in_words_component.rb create mode 100644 app/components/admin/duration_component.html.erb create mode 100644 app/components/admin/duration_component.rb delete mode 100644 spec/components/admin/budgets/duration_component_spec.rb create mode 100644 spec/components/admin/budgets/duration_in_words_component_spec.rb create mode 100644 spec/components/admin/duration_component_spec.rb diff --git a/app/components/admin/budget_phases/phases_component.rb b/app/components/admin/budget_phases/phases_component.rb index 5dfd9c6f5..7de363c86 100644 --- a/app/components/admin/budget_phases/phases_component.rb +++ b/app/components/admin/budget_phases/phases_component.rb @@ -12,7 +12,7 @@ class Admin::BudgetPhases::PhasesComponent < ApplicationComponent end def dates(phase) - Admin::Budgets::DurationComponent.new(phase).dates + render Admin::DurationComponent.new(phase) end def enabled_cell(phase) diff --git a/app/components/admin/budgets/duration_component.rb b/app/components/admin/budgets/duration_component.rb deleted file mode 100644 index 368ed92d8..000000000 --- a/app/components/admin/budgets/duration_component.rb +++ /dev/null @@ -1,25 +0,0 @@ -class Admin::Budgets::DurationComponent < ApplicationComponent - attr_reader :durable - - def initialize(durable) - @durable = durable - end - - def dates - Admin::DateRangeComponent.new(start_time, end_time).call - end - - def duration - distance_of_time_in_words(durable.starts_at, durable.ends_at) if durable.starts_at && durable.ends_at - end - - private - - def start_time - durable.starts_at - end - - def end_time - durable.ends_at - 1.second if durable.ends_at.present? - end -end diff --git a/app/components/admin/budgets/duration_in_words_component.html.erb b/app/components/admin/budgets/duration_in_words_component.html.erb new file mode 100644 index 000000000..a0323de85 --- /dev/null +++ b/app/components/admin/budgets/duration_in_words_component.html.erb @@ -0,0 +1 @@ +<%= duration -%> diff --git a/app/components/admin/budgets/duration_in_words_component.rb b/app/components/admin/budgets/duration_in_words_component.rb new file mode 100644 index 000000000..455ec54d2 --- /dev/null +++ b/app/components/admin/budgets/duration_in_words_component.rb @@ -0,0 +1,17 @@ +class Admin::Budgets::DurationInWordsComponent < ApplicationComponent + attr_reader :durable + + def initialize(durable) + @durable = durable + end + + def render? + durable.starts_at && durable.ends_at + end + + private + + def duration + distance_of_time_in_words(durable.starts_at, durable.ends_at) + end +end diff --git a/app/components/admin/budgets/index_component.rb b/app/components/admin/budgets/index_component.rb index 53f1d5d6f..72b3c4615 100644 --- a/app/components/admin/budgets/index_component.rb +++ b/app/components/admin/budgets/index_component.rb @@ -37,11 +37,11 @@ class Admin::Budgets::IndexComponent < ApplicationComponent end def dates(budget) - Admin::Budgets::DurationComponent.new(budget).dates + render Admin::DurationComponent.new(budget) end def duration(budget) - Admin::Budgets::DurationComponent.new(budget).duration + render Admin::Budgets::DurationInWordsComponent.new(budget) end def status_html_class(budget) diff --git a/app/components/admin/duration_component.html.erb b/app/components/admin/duration_component.html.erb new file mode 100644 index 000000000..f6920c3b7 --- /dev/null +++ b/app/components/admin/duration_component.html.erb @@ -0,0 +1 @@ +<%= dates -%> diff --git a/app/components/admin/duration_component.rb b/app/components/admin/duration_component.rb new file mode 100644 index 000000000..417e8edd3 --- /dev/null +++ b/app/components/admin/duration_component.rb @@ -0,0 +1,21 @@ +class Admin::DurationComponent < ApplicationComponent + attr_reader :durable + + def initialize(durable) + @durable = durable + end + + private + + def dates + render Admin::DateRangeComponent.new(start_time, end_time) + end + + def start_time + durable.starts_at + end + + def end_time + durable.ends_at - 1.second if durable.ends_at.present? + end +end diff --git a/spec/components/admin/budgets/duration_component_spec.rb b/spec/components/admin/budgets/duration_component_spec.rb deleted file mode 100644 index d84d13c7b..000000000 --- a/spec/components/admin/budgets/duration_component_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require "rails_helper" - -describe Admin::Budgets::DurationComponent do - describe "#dates" do - it "shows both dates when both are defined" do - durable = double( - starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), - ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00) - ) - - dates = Admin::Budgets::DurationComponent.new(durable).dates - - render dates - - expect(page.text).to eq "2015-08-01 12:00 - 2016-09-30 16:29" - expect(dates).to be_html_safe - end - - it "shows the start date when no end date is defined" do - durable = double(starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), ends_at: nil) - render Admin::Budgets::DurationComponent.new(durable).dates - - expect(page.text).to eq "2015-08-01 12:00 - " - end - - it "shows the end date when no start date is defined" do - durable = double(starts_at: nil, ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00)) - - render Admin::Budgets::DurationComponent.new(durable).dates - - expect(page.text).to eq "- 2016-09-30 16:29" - end - end - - describe "#duration" do - it "describes the total duration in human language" do - durable = double( - starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), - ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00) - ) - - render Admin::Budgets::DurationComponent.new(durable).duration - - expect(page.text).to eq "about 1 year" - end - - it "is not defined when no end date is defined" do - durable = double(starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), ends_at: nil) - - render Admin::Budgets::DurationComponent.new(durable).duration - - expect(page).not_to be_rendered - end - - it "is not defined when no start date is defined" do - durable = double(starts_at: nil, ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00)) - - render Admin::Budgets::DurationComponent.new(durable).duration - - expect(page).not_to be_rendered - end - end - - attr_reader :content - - def render(content) - @content = content - end - - def page - Capybara::Node::Simple.new(content.to_s) - end -end diff --git a/spec/components/admin/budgets/duration_in_words_component_spec.rb b/spec/components/admin/budgets/duration_in_words_component_spec.rb new file mode 100644 index 000000000..8cb72431b --- /dev/null +++ b/spec/components/admin/budgets/duration_in_words_component_spec.rb @@ -0,0 +1,30 @@ +require "rails_helper" + +describe Admin::Budgets::DurationInWordsComponent do + it "describes the total duration in human language" do + durable = double( + starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), + ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00) + ) + + render_inline Admin::Budgets::DurationInWordsComponent.new(durable) + + expect(page.text).to eq "about 1 year" + end + + it "is not defined when no end date is defined" do + durable = double(starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), ends_at: nil) + + render_inline Admin::Budgets::DurationInWordsComponent.new(durable) + + expect(page).not_to be_rendered + end + + it "is not defined when no start date is defined" do + durable = double(starts_at: nil, ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00)) + + render_inline Admin::Budgets::DurationInWordsComponent.new(durable) + + expect(page).not_to be_rendered + end +end diff --git a/spec/components/admin/duration_component_spec.rb b/spec/components/admin/duration_component_spec.rb new file mode 100644 index 000000000..9780df837 --- /dev/null +++ b/spec/components/admin/duration_component_spec.rb @@ -0,0 +1,32 @@ +require "rails_helper" + +describe Admin::DurationComponent do + it "shows both dates when both are defined" do + durable = double( + starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), + ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00) + ) + + render_inline Admin::DurationComponent.new(durable) + + expect(page.text).to eq "2015-08-01 12:00 - 2016-09-30 16:29" + expect(page).to have_css "time", exact_text: "2015-08-01 12:00" + expect(page).to have_css "time", exact_text: "2016-09-30 16:29" + end + + it "shows the start date when no end date is defined" do + durable = double(starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), ends_at: nil) + + render_inline Admin::DurationComponent.new(durable) + + expect(page.text).to eq "2015-08-01 12:00 - " + end + + it "shows the end date when no start date is defined" do + durable = double(starts_at: nil, ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00)) + + render_inline Admin::DurationComponent.new(durable) + + expect(page.text).to eq "- 2016-09-30 16:29" + end +end From 90d5759c23f6b6c2043756b5fa1e6bc8d4d2f134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Tue, 6 Sep 2022 18:20:12 +0200 Subject: [PATCH 3/9] Show the precise ending time unless it's midnight The reason why we were displaying the ending date as "one second before the actual ending" was that, when seeing that a phase ends at a date like "2000-12-31 00:00", we might end up thinking that the phase will finished at the midnight between December 31st and January the 1st, while it actually ends at the midnight between December the 30th and December the 31st. This is particularly important because we use a date field to select the date of a phase and if select December the 31st, it will be stored in the database as "2000-12-31 00:00". So, instead, in this case we display "2000-12-30 23:59", which is less confusing. But now we're going to add support for setting a time on polls, which means a certain poll might end at 15:30. In this case, displaying that it ends at 15:29 doesn't make much sense. --- app/components/admin/duration_component.rb | 6 +++++- .../components/admin/duration_component_spec.rb | 17 ++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/app/components/admin/duration_component.rb b/app/components/admin/duration_component.rb index 417e8edd3..5a8f49cd6 100644 --- a/app/components/admin/duration_component.rb +++ b/app/components/admin/duration_component.rb @@ -16,6 +16,10 @@ class Admin::DurationComponent < ApplicationComponent end def end_time - durable.ends_at - 1.second if durable.ends_at.present? + if durable.ends_at.present? && durable.ends_at == durable.ends_at.beginning_of_day + durable.ends_at - 1.second + else + durable.ends_at + end end end diff --git a/spec/components/admin/duration_component_spec.rb b/spec/components/admin/duration_component_spec.rb index 9780df837..6271a3d31 100644 --- a/spec/components/admin/duration_component_spec.rb +++ b/spec/components/admin/duration_component_spec.rb @@ -9,9 +9,20 @@ describe Admin::DurationComponent do render_inline Admin::DurationComponent.new(durable) - expect(page.text).to eq "2015-08-01 12:00 - 2016-09-30 16:29" + expect(page.text).to eq "2015-08-01 12:00 - 2016-09-30 16:30" expect(page).to have_css "time", exact_text: "2015-08-01 12:00" - expect(page).to have_css "time", exact_text: "2016-09-30 16:29" + expect(page).to have_css "time", exact_text: "2016-09-30 16:30" + end + + it "shows the moment before the end date when it ends at midnight" do + durable = double( + starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), + ends_at: Time.zone.local(2016, 9, 30, 00, 00, 00) + ) + + render_inline Admin::DurationComponent.new(durable) + + expect(page.text).to eq "2015-08-01 12:00 - 2016-09-29 23:59" end it "shows the start date when no end date is defined" do @@ -27,6 +38,6 @@ describe Admin::DurationComponent do render_inline Admin::DurationComponent.new(durable) - expect(page.text).to eq "- 2016-09-30 16:29" + expect(page.text).to eq "- 2016-09-30 16:30" end end From bd85a09d326d3845358230bc9498d1357b2d73f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Wed, 7 Sep 2022 18:47:17 +0200 Subject: [PATCH 4/9] Group poll scopes tests together We're also using the convention of using a `.` to describe class methods. --- spec/models/poll/poll_spec.rb | 62 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb index 172d2b81d..10f4b03ce 100644 --- a/spec/models/poll/poll_spec.rb +++ b/spec/models/poll/poll_spec.rb @@ -107,33 +107,6 @@ describe Poll do end end - describe "#recounting" do - it "returns polls in recount & scrutiny phase" do - current = create(:poll, :current) - expired = create(:poll, :expired) - recounting = create(:poll, :recounting) - - recounting_polls = Poll.recounting - - expect(recounting_polls).to eq [recounting] - expect(recounting_polls).not_to include(current) - expect(recounting_polls).not_to include(expired) - end - end - - describe "#current_or_recounting" do - it "returns current or recounting polls" do - current = create(:poll, :current) - expired = create(:poll, :expired) - recounting = create(:poll, :recounting) - - current_or_recounting = Poll.current_or_recounting - - expect(current_or_recounting).to match_array [current, recounting] - expect(current_or_recounting).not_to include(expired) - end - end - describe "answerable_by" do let(:geozone) { create(:geozone) } @@ -198,7 +171,7 @@ describe Poll do end end - describe "votable_by" do + describe ".votable_by" do it "returns polls that have not been voted by a user" do user = create(:user, :level_two) @@ -337,8 +310,35 @@ describe Poll do end end - context "scopes" do - describe "#not_budget" do + describe "scopes" do + describe ".recounting" do + it "returns polls in recount & scrutiny phase" do + current = create(:poll, :current) + expired = create(:poll, :expired) + recounting = create(:poll, :recounting) + + recounting_polls = Poll.recounting + + expect(recounting_polls).to eq [recounting] + expect(recounting_polls).not_to include(current) + expect(recounting_polls).not_to include(expired) + end + end + + describe ".current_or_recounting" do + it "returns current or recounting polls" do + current = create(:poll, :current) + expired = create(:poll, :expired) + recounting = create(:poll, :recounting) + + current_or_recounting = Poll.current_or_recounting + + expect(current_or_recounting).to match_array [current, recounting] + expect(current_or_recounting).not_to include(expired) + end + end + + describe ".not_budget" do it "returns polls not associated to a budget" do poll1 = create(:poll) poll2 = create(:poll) @@ -350,7 +350,7 @@ describe Poll do end end - describe "#sort_for_list" do + describe ".sort_for_list" do it "returns polls sorted by name ASC" do starts_at = 1.day.from_now poll1 = create(:poll, geozone_restricted: true, starts_at: starts_at, name: "Zzz...") From 2153bd9e98f5bd974bad10995f1003e4294d64f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Wed, 7 Sep 2022 18:57:41 +0200 Subject: [PATCH 5/9] Add tests for current/expired/recounting polls We didn't have model tests for some of these scopes, and neither scope tests nor instance method tests covered edge cases like the current date. --- spec/factories/polls.rb | 5 --- spec/models/poll/poll_spec.rb | 83 ++++++++++++++++++++++++++++------- 2 files changed, 66 insertions(+), 22 deletions(-) diff --git a/spec/factories/polls.rb b/spec/factories/polls.rb index fe98957cc..c55101c31 100644 --- a/spec/factories/polls.rb +++ b/spec/factories/polls.rb @@ -22,11 +22,6 @@ FactoryBot.define do ends_at { 2.months.ago } end - trait :recounting do - starts_at { 1.month.ago } - ends_at { Date.current } - end - trait :published do published { true } end diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb index 10f4b03ce..c7b4656cf 100644 --- a/spec/models/poll/poll_spec.rb +++ b/spec/models/poll/poll_spec.rb @@ -86,17 +86,31 @@ describe Poll do end end - describe "#opened?" do + describe "#current?" do it "returns true only when it isn't too late" do - expect(create(:poll, :expired)).not_to be_current - expect(create(:poll)).to be_current + about_to_start = create(:poll, starts_at: Date.tomorrow) + just_started = create(:poll, starts_at: Date.current) + about_to_end = create(:poll, ends_at: Date.current) + just_ended = create(:poll, ends_at: Date.yesterday) + + expect(just_started).to be_current + expect(about_to_end).to be_current + expect(about_to_start).not_to be_current + expect(just_ended).not_to be_current end end describe "#expired?" do it "returns true only when it is too late" do - expect(create(:poll, :expired)).to be_expired - expect(create(:poll)).not_to be_expired + about_to_start = create(:poll, starts_at: Date.tomorrow) + about_to_end = create(:poll, ends_at: Date.current) + just_ended = create(:poll, ends_at: Date.yesterday) + recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) + + expect(just_ended).to be_expired + expect(recounting_ended).to be_expired + expect(about_to_start).not_to be_expired + expect(about_to_end).not_to be_expired end end @@ -311,30 +325,65 @@ describe Poll do end describe "scopes" do + describe ".current" do + it "returns polls which have started but not ended" do + about_to_start = create(:poll, starts_at: Date.tomorrow) + just_started = create(:poll, starts_at: Date.current) + about_to_end = create(:poll, ends_at: Date.current) + just_ended = create(:poll, ends_at: Date.yesterday) + + current_polls = Poll.current + + expect(current_polls).to match_array [just_started, about_to_end] + expect(current_polls).not_to include(about_to_start) + expect(current_polls).not_to include(just_ended) + end + end + + describe ".expired" do + it "returns polls which have already ended" do + about_to_start = create(:poll, starts_at: Date.tomorrow) + about_to_end = create(:poll, ends_at: Date.current) + just_ended = create(:poll, ends_at: Date.yesterday) + recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) + + expired_polls = Poll.expired + + expect(expired_polls).to match_array [just_ended, recounting_ended] + expect(expired_polls).not_to include(about_to_start) + expect(expired_polls).not_to include(about_to_end) + end + end + describe ".recounting" do it "returns polls in recount & scrutiny phase" do - current = create(:poll, :current) - expired = create(:poll, :expired) - recounting = create(:poll, :recounting) + about_to_start = create(:poll, starts_at: Date.tomorrow) + about_to_end = create(:poll, ends_at: Date.tomorrow) + just_ended = create(:poll, ends_at: Date.yesterday) + recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) recounting_polls = Poll.recounting - expect(recounting_polls).to eq [recounting] - expect(recounting_polls).not_to include(current) - expect(recounting_polls).not_to include(expired) + expect(recounting_polls).to eq [just_ended] + expect(recounting_polls).not_to include(about_to_start) + expect(recounting_polls).not_to include(about_to_end) + expect(recounting_polls).not_to include(recounting_ended) end end describe ".current_or_recounting" do it "returns current or recounting polls" do - current = create(:poll, :current) - expired = create(:poll, :expired) - recounting = create(:poll, :recounting) + about_to_start = create(:poll, starts_at: Date.tomorrow) + just_started = create(:poll, starts_at: Date.current) + about_to_end = create(:poll, ends_at: Date.current) + just_ended = create(:poll, ends_at: Date.yesterday) + recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) current_or_recounting = Poll.current_or_recounting - expect(current_or_recounting).to match_array [current, recounting] - expect(current_or_recounting).not_to include(expired) + expect(current_or_recounting).to match_array [just_started, about_to_end, just_ended] + expect(current_or_recounting).not_to include(about_to_start) + expect(current_or_recounting).not_to include(recounting_ended) end end @@ -425,7 +474,7 @@ describe Poll do end it "is false for recounting polls" do - poll = create(:poll, :recounting) + poll = create(:poll, ends_at: Date.yesterday) expect(poll.recounts_confirmed?).to be false end From 354376795148d0b12a9b8e2e017526c9b730cfa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Wed, 7 Sep 2022 19:44:23 +0200 Subject: [PATCH 6/9] Don't include current polls in recounting polls On the day when a poll ends, it was considered both current and recounting. --- app/models/poll.rb | 2 +- spec/models/poll/poll_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/poll.rb b/app/models/poll.rb index 48cffaace..7b127c64d 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -44,7 +44,7 @@ class Poll < ApplicationRecord scope :for, ->(element) { where(related: element) } scope :current, -> { where("starts_at <= ? and ? <= ends_at", Date.current.beginning_of_day, Date.current.beginning_of_day) } scope :expired, -> { where("ends_at < ?", Date.current.beginning_of_day) } - scope :recounting, -> { where(ends_at: (Date.current.beginning_of_day - RECOUNT_DURATION)..Date.current.beginning_of_day) } + scope :recounting, -> { where(ends_at: (Date.current.beginning_of_day - RECOUNT_DURATION)...Date.current.beginning_of_day) } scope :published, -> { where(published: true) } scope :by_geozone_id, ->(geozone_id) { where(geozones: { id: geozone_id }.joins(:geozones)) } scope :public_for_api, -> { all } diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb index c7b4656cf..a2b94d729 100644 --- a/spec/models/poll/poll_spec.rb +++ b/spec/models/poll/poll_spec.rb @@ -358,7 +358,7 @@ describe Poll do describe ".recounting" do it "returns polls in recount & scrutiny phase" do about_to_start = create(:poll, starts_at: Date.tomorrow) - about_to_end = create(:poll, ends_at: Date.tomorrow) + about_to_end = create(:poll, ends_at: Date.current) just_ended = create(:poll, ends_at: Date.yesterday) recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) From f5a524d503605c0d0b79b63266c90372f91532f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Wed, 7 Sep 2022 20:06:05 +0200 Subject: [PATCH 7/9] Make poll scope more readable This was the only place where we used the `? <= field` format; we use the `field >= ?` format everywhere else. We're also adding a variable to make it easier to understand that the value is the same in both cases and to make the line shorter ;). --- app/models/poll.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/poll.rb b/app/models/poll.rb index 7b127c64d..dcc081168 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -42,7 +42,7 @@ class Poll < ApplicationRecord accepts_nested_attributes_for :questions, reject_if: :all_blank, allow_destroy: true scope :for, ->(element) { where(related: element) } - scope :current, -> { where("starts_at <= ? and ? <= ends_at", Date.current.beginning_of_day, Date.current.beginning_of_day) } + scope :current, -> { where("starts_at <= :time and ends_at >= :time", time: Date.current.beginning_of_day) } scope :expired, -> { where("ends_at < ?", Date.current.beginning_of_day) } scope :recounting, -> { where(ends_at: (Date.current.beginning_of_day - RECOUNT_DURATION)...Date.current.beginning_of_day) } scope :published, -> { where(published: true) } From 5a0fde40480fa59ad611d448c317d4aff3185159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Wed, 7 Sep 2022 20:10:23 +0200 Subject: [PATCH 8/9] Allow selecting the time when a poll starts/ends We were already saving it as a time, but we didn't offer an interface to select the time due to lack of decent browser support for this field back when this feature was added. However, nowadays all major browsers support this field type and, at the time of writing, at least 86.5% of the browsers support it [1]. This percentage could be much higher, since support in 11.25% of the browsers is unknown. Note we still need to support the case where this field isn't supported, and so we offer a fallback and on the server side we don't assume we're always getting a time. We're doing a strange hack so we set the field type to text before changing its value; otherwise old Firefox browsers crashed. Also note that, until now, we were storing end dates in the database as a date with 00:00 as its time, but we were considering the poll to be open until 23:59 that day. So, in order to keep backwards compatibility, we're adding a task to update the dates of existing polls so we get the same behavior we had until now. This also means budget polls are now created so they end at the beginning of the day when the balloting phase ends. This is consistent with the dates we display in the budget phases table. Finally, there's one test where we're using `beginning_of_minute` when creating a poll. That's because Chrome provides an interface to enter a time in a `%H:%M` format when the "seconds" value of the provided time is zero. However, when the "seconds" value isn't zero, Chrome provides an interface to enter a time in a `%H:%M:%S` format. Since Capybara doesn't enter the seconds when using `fill_in` with a time, the test failed when Capybara tried to enter a time in the `%H:%M` format when Chrome expected a time in the `%H:%M:%S` format. To solve this last point, an alternative would be to manually provide the format when using `fill_in` so it includes the seconds. [1] https://caniuse.com/mdn-html_elements_input_type_datetime-local --- app/assets/javascripts/datepicker.js | 27 +++++++-- app/models/poll.rb | 10 ++-- app/views/admin/poll/polls/_form.html.erb | 4 +- app/views/admin/poll/polls/_poll.html.erb | 4 +- .../admin/poll/polls/_poll_header.html.erb | 2 +- lib/tasks/consul.rake | 3 +- lib/tasks/polls.rake | 10 ++++ spec/lib/tasks/polls_spec.rb | 23 ++++++++ spec/models/poll/poll_spec.rb | 56 +++++++++---------- spec/system/admin/poll/polls_spec.rb | 22 ++++---- spec/system/budget_polls/budgets_spec.rb | 2 +- 11 files changed, 107 insertions(+), 56 deletions(-) create mode 100644 lib/tasks/polls.rake create mode 100644 spec/lib/tasks/polls_spec.rb diff --git a/app/assets/javascripts/datepicker.js b/app/assets/javascripts/datepicker.js index 1e483ea6a..eab188097 100644 --- a/app/assets/javascripts/datepicker.js +++ b/app/assets/javascripts/datepicker.js @@ -23,6 +23,16 @@ }); $(".js-calendar-full").datepicker(); + if (!App.Datepicker.browser_supports_datetime_local_field()) { + if (App.Datepicker.browser_supports_date_field()) { + $("input[type='datetime-local']").prop("type", "text") + .val(App.Datepicker.datetime_to_date) + .prop("type", "date"); + } else { + $("input[type='datetime-local']").val(App.Datepicker.datetime_to_date).datepicker(); + } + } + if (!App.Datepicker.browser_supports_date_field()) { $("input[type='date']").datepicker(); } @@ -39,11 +49,20 @@ }); }, browser_supports_date_field: function() { - var datefield; + return App.Datepicker.browser_supports_field_with_type("date"); + }, + browser_supports_datetime_local_field: function() { + return App.Datepicker.browser_supports_field_with_type("datetime-local"); + }, + browser_supports_field_with_type: function(field_type) { + var field; - datefield = document.createElement("input"); - datefield.setAttribute("type", "date"); - return datefield.type === "date"; + field = document.createElement("input"); + field.setAttribute("type", field_type); + return field.type === field_type; + }, + datetime_to_date: function(index, value) { + return value.split("T")[0]; } }; diff --git a/app/models/poll.rb b/app/models/poll.rb index dcc081168..2acd9cfb0 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -42,9 +42,9 @@ class Poll < ApplicationRecord accepts_nested_attributes_for :questions, reject_if: :all_blank, allow_destroy: true scope :for, ->(element) { where(related: element) } - scope :current, -> { where("starts_at <= :time and ends_at >= :time", time: Date.current.beginning_of_day) } - scope :expired, -> { where("ends_at < ?", Date.current.beginning_of_day) } - scope :recounting, -> { where(ends_at: (Date.current.beginning_of_day - RECOUNT_DURATION)...Date.current.beginning_of_day) } + scope :current, -> { where("starts_at <= :time and ends_at >= :time", time: Time.current) } + scope :expired, -> { where("ends_at < ?", Time.current) } + scope :recounting, -> { where(ends_at: (RECOUNT_DURATION.ago)...Time.current) } scope :published, -> { where(published: true) } scope :by_geozone_id, ->(geozone_id) { where(geozones: { id: geozone_id }.joins(:geozones)) } scope :public_for_api, -> { all } @@ -67,11 +67,11 @@ class Poll < ApplicationRecord name end - def current?(timestamp = Date.current.beginning_of_day) + def current?(timestamp = Time.current) starts_at <= timestamp && timestamp <= ends_at end - def expired?(timestamp = Date.current.beginning_of_day) + def expired?(timestamp = Time.current) ends_at < timestamp end diff --git a/app/views/admin/poll/polls/_form.html.erb b/app/views/admin/poll/polls/_form.html.erb index 926a98ce4..dd0b59292 100644 --- a/app/views/admin/poll/polls/_form.html.erb +++ b/app/views/admin/poll/polls/_form.html.erb @@ -6,11 +6,11 @@
- <%= f.date_field :starts_at %> + <%= f.datetime_field :starts_at %>
- <%= f.date_field :ends_at %> + <%= f.datetime_field :ends_at %>
diff --git a/app/views/admin/poll/polls/_poll.html.erb b/app/views/admin/poll/polls/_poll.html.erb index 8f477c586..80b64d43c 100644 --- a/app/views/admin/poll/polls/_poll.html.erb +++ b/app/views/admin/poll/polls/_poll.html.erb @@ -1,7 +1,7 @@ <%= poll.name %> - <%= l poll.starts_at.beginning_of_day, format: :short_datetime %> - <%= l poll.ends_at.end_of_day, format: :short_datetime %> + <%= l poll.starts_at, format: :short_datetime %> + <%= l poll.ends_at, format: :short_datetime %> <% if feature?(:sdg) %> <%= poll.sdg_goal_list %> <%= poll.sdg_target_list %> diff --git a/app/views/admin/poll/polls/_poll_header.html.erb b/app/views/admin/poll/polls/_poll_header.html.erb index ef24e0e0c..c6dcd0e7c 100644 --- a/app/views/admin/poll/polls/_poll_header.html.erb +++ b/app/views/admin/poll/polls/_poll_header.html.erb @@ -12,7 +12,7 @@
<%= t("admin.polls.index.dates") %>
- <%= render Admin::DateRangeComponent.new(@poll.starts_at.beginning_of_day, @poll.ends_at.end_of_day) %> + <%= render Admin::DurationComponent.new(@poll) %>
<% if @poll.geozone_restricted %> diff --git a/lib/tasks/consul.rake b/lib/tasks/consul.rake index f1074d23e..97bfb0365 100644 --- a/lib/tasks/consul.rake +++ b/lib/tasks/consul.rake @@ -11,6 +11,7 @@ namespace :consul do desc "Runs tasks needed to upgrade from 1.5.0 to 1.6.0" task "execute_release_1.6.0_tasks": [ - "db:calculate_tsv" + "db:calculate_tsv", + "polls:set_ends_at_to_end_of_day" ] end diff --git a/lib/tasks/polls.rake b/lib/tasks/polls.rake new file mode 100644 index 000000000..d909650f1 --- /dev/null +++ b/lib/tasks/polls.rake @@ -0,0 +1,10 @@ +namespace :polls do + desc "Changes the polls ending date to the end of the day" + task set_ends_at_to_end_of_day: :environment do + ApplicationLogger.new.info "Adding time to the date where a poll ends" + + Poll.find_each do |poll| + poll.update_column :ends_at, poll.ends_at.end_of_day.beginning_of_minute + end + end +end diff --git a/spec/lib/tasks/polls_spec.rb b/spec/lib/tasks/polls_spec.rb new file mode 100644 index 000000000..e30e91a71 --- /dev/null +++ b/spec/lib/tasks/polls_spec.rb @@ -0,0 +1,23 @@ +require "rails_helper" + +describe "rake polls:set_ends_at_to_end_of_day" do + before { Rake::Task["polls:set_ends_at_to_end_of_day"].reenable } + + let :run_rake_task do + Rake.application.invoke_task("polls:set_ends_at_to_end_of_day") + end + + it "updates existing polls" do + travel_to(Time.zone.local(2015, 7, 15, 13, 32, 13)) + poll = create(:poll, ends_at: 2.years.from_now) + date_poll = create(:poll, ends_at: 3.years.from_now.to_date) + + expect(I18n.l(poll.reload.ends_at, format: :datetime)).to eq "2017-07-15 13:32:13" + expect(I18n.l(date_poll.reload.ends_at, format: :datetime)).to eq "2018-07-15 00:00:00" + + run_rake_task + + expect(I18n.l(poll.reload.ends_at, format: :datetime)).to eq "2017-07-15 23:59:00" + expect(I18n.l(date_poll.reload.ends_at, format: :datetime)).to eq "2018-07-15 23:59:00" + end +end diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb index a2b94d729..751f4a85a 100644 --- a/spec/models/poll/poll_spec.rb +++ b/spec/models/poll/poll_spec.rb @@ -86,12 +86,12 @@ describe Poll do end end - describe "#current?" do + describe "#current?", :with_frozen_time do it "returns true only when it isn't too late" do - about_to_start = create(:poll, starts_at: Date.tomorrow) - just_started = create(:poll, starts_at: Date.current) - about_to_end = create(:poll, ends_at: Date.current) - just_ended = create(:poll, ends_at: Date.yesterday) + about_to_start = create(:poll, starts_at: 1.second.from_now) + just_started = create(:poll, starts_at: Time.current) + about_to_end = create(:poll, ends_at: Time.current) + just_ended = create(:poll, ends_at: 1.second.ago) expect(just_started).to be_current expect(about_to_end).to be_current @@ -100,11 +100,11 @@ describe Poll do end end - describe "#expired?" do + describe "#expired?", :with_frozen_time do it "returns true only when it is too late" do - about_to_start = create(:poll, starts_at: Date.tomorrow) - about_to_end = create(:poll, ends_at: Date.current) - just_ended = create(:poll, ends_at: Date.yesterday) + about_to_start = create(:poll, starts_at: 1.second.from_now) + about_to_end = create(:poll, ends_at: Time.current) + just_ended = create(:poll, ends_at: 1.second.ago) recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) expect(just_ended).to be_expired @@ -325,12 +325,12 @@ describe Poll do end describe "scopes" do - describe ".current" do + describe ".current", :with_frozen_time do it "returns polls which have started but not ended" do - about_to_start = create(:poll, starts_at: Date.tomorrow) - just_started = create(:poll, starts_at: Date.current) - about_to_end = create(:poll, ends_at: Date.current) - just_ended = create(:poll, ends_at: Date.yesterday) + about_to_start = create(:poll, starts_at: 1.second.from_now) + just_started = create(:poll, starts_at: Time.current) + about_to_end = create(:poll, ends_at: Time.current) + just_ended = create(:poll, ends_at: 1.second.ago) current_polls = Poll.current @@ -340,11 +340,11 @@ describe Poll do end end - describe ".expired" do + describe ".expired", :with_frozen_time do it "returns polls which have already ended" do - about_to_start = create(:poll, starts_at: Date.tomorrow) - about_to_end = create(:poll, ends_at: Date.current) - just_ended = create(:poll, ends_at: Date.yesterday) + about_to_start = create(:poll, starts_at: 1.second.from_now) + about_to_end = create(:poll, ends_at: Time.current) + just_ended = create(:poll, ends_at: 1.second.ago) recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) expired_polls = Poll.expired @@ -355,11 +355,11 @@ describe Poll do end end - describe ".recounting" do + describe ".recounting", :with_frozen_time do it "returns polls in recount & scrutiny phase" do - about_to_start = create(:poll, starts_at: Date.tomorrow) - about_to_end = create(:poll, ends_at: Date.current) - just_ended = create(:poll, ends_at: Date.yesterday) + about_to_start = create(:poll, starts_at: 1.second.from_now) + about_to_end = create(:poll, ends_at: Time.current) + just_ended = create(:poll, ends_at: 1.second.ago) recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) recounting_polls = Poll.recounting @@ -371,12 +371,12 @@ describe Poll do end end - describe ".current_or_recounting" do + describe ".current_or_recounting", :with_frozen_time do it "returns current or recounting polls" do - about_to_start = create(:poll, starts_at: Date.tomorrow) - just_started = create(:poll, starts_at: Date.current) - about_to_end = create(:poll, ends_at: Date.current) - just_ended = create(:poll, ends_at: Date.yesterday) + about_to_start = create(:poll, starts_at: 1.second.from_now) + just_started = create(:poll, starts_at: Time.current) + about_to_end = create(:poll, ends_at: Time.current) + just_ended = create(:poll, ends_at: 1.second.ago) recounting_ended = create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) current_or_recounting = Poll.current_or_recounting @@ -474,7 +474,7 @@ describe Poll do end it "is false for recounting polls" do - poll = create(:poll, ends_at: Date.yesterday) + poll = create(:poll, ends_at: 1.second.ago) expect(poll.recounts_confirmed?).to be false end diff --git a/spec/system/admin/poll/polls_spec.rb b/spec/system/admin/poll/polls_spec.rb index 7bd857ecc..23f023e1f 100644 --- a/spec/system/admin/poll/polls_spec.rb +++ b/spec/system/admin/poll/polls_spec.rb @@ -47,15 +47,14 @@ describe "Admin polls", :admin do end scenario "Create" do + travel_to(Time.zone.local(2015, 7, 15, 13, 32, 13)) + visit admin_polls_path click_link "Create poll" - start_date = 1.week.from_now.to_date - end_date = 2.weeks.from_now.to_date - fill_in "Name", with: "Upcoming poll" - fill_in "poll_starts_at", with: start_date - fill_in "poll_ends_at", with: end_date + fill_in "Start Date", with: 1.week.from_now + fill_in "Closing Date", with: 2.weeks.from_now fill_in "Summary", with: "Upcoming poll's summary. This poll..." fill_in "Description", with: "Upcomming poll's description. This poll..." @@ -67,8 +66,8 @@ describe "Admin polls", :admin do expect(page).to have_content "Poll created successfully" expect(page).to have_content "Upcoming poll" - expect(page).to have_content "#{I18n.l(start_date)} 00:00" - expect(page).to have_content "#{I18n.l(end_date)} 23:59" + expect(page).to have_content "2015-07-22 13:32" + expect(page).to have_content "2015-07-29 13:32" visit poll_path(id: "upcoming-poll") @@ -76,24 +75,23 @@ describe "Admin polls", :admin do end scenario "Edit" do - poll = create(:poll, :with_image) + travel_to(Time.zone.local(2015, 7, 15, 13, 32, 13)) + poll = create(:poll, :with_image, ends_at: 1.month.from_now.beginning_of_minute) visit admin_poll_path(poll) click_link "Edit poll" - end_date = 1.year.from_now.to_date - expect(page).to have_css("img[alt='#{poll.image.title}']") expect(page).to have_link "Go back", href: admin_polls_path fill_in "Name", with: "Next Poll" - fill_in "poll_ends_at", with: end_date + fill_in "Closing Date", with: 1.year.from_now click_button "Update poll" expect(page).to have_content "Poll updated successfully" expect(page).to have_content "Next Poll" - expect(page).to have_content "#{I18n.l(end_date)} 23:59" + expect(page).to have_content "2016-07-15 13:32" end scenario "Edit from index" do diff --git a/spec/system/budget_polls/budgets_spec.rb b/spec/system/budget_polls/budgets_spec.rb index 6a4f1c56b..bbd8ea26a 100644 --- a/spec/system/budget_polls/budgets_spec.rb +++ b/spec/system/budget_polls/budgets_spec.rb @@ -13,7 +13,7 @@ describe "Admin Budgets", :admin do expect(page).to have_current_path(/admin\/polls\/\d+/) expect(page).to have_content(budget.name) expect(page).to have_content("#{balloting_phase.starts_at.to_date} 00:00") - expect(page).to have_content("#{balloting_phase.ends_at.to_date} 23:59") + expect(page).to have_content("#{balloting_phase.ends_at.to_date - 1.day} 23:59") end scenario "Create poll in current locale if the budget does not have a poll associated" do From d0359d584e9fc7244d8c1da672d7259053f05d37 Mon Sep 17 00:00:00 2001 From: taitus Date: Tue, 30 Aug 2022 13:23:48 +0200 Subject: [PATCH 9/9] Remove trait :current for poll on factories When we create a poll with "create(:poll)" it is already a current poll. --- spec/factories/polls.rb | 5 ----- spec/models/abilities/everyone_spec.rb | 4 ++-- spec/models/poll/booth_spec.rb | 4 ++-- spec/models/poll/poll_spec.rb | 2 +- spec/system/admin/poll/booths_spec.rb | 6 +++--- spec/system/admin/poll/shifts_spec.rb | 8 ++++---- spec/system/budget_polls/voter_spec.rb | 2 +- spec/system/dashboard/polls_spec.rb | 4 ++-- spec/system/officing/voters_spec.rb | 16 ++++++++-------- spec/system/polls/polls_spec.rb | 2 +- spec/system/polls/voter_spec.rb | 2 +- 11 files changed, 25 insertions(+), 30 deletions(-) diff --git a/spec/factories/polls.rb b/spec/factories/polls.rb index c55101c31..7820532f7 100644 --- a/spec/factories/polls.rb +++ b/spec/factories/polls.rb @@ -7,11 +7,6 @@ FactoryBot.define do starts_at { 1.month.ago } ends_at { 1.month.from_now } - trait :current do - starts_at { 2.days.ago } - ends_at { 2.days.from_now } - end - trait :expired do starts_at { 1.month.ago } ends_at { 15.days.ago } diff --git a/spec/models/abilities/everyone_spec.rb b/spec/models/abilities/everyone_spec.rb index 7aaa1e1c5..903317158 100644 --- a/spec/models/abilities/everyone_spec.rb +++ b/spec/models/abilities/everyone_spec.rb @@ -33,12 +33,12 @@ describe Abilities::Everyone do it { should be_able_to(:results, create(:poll, :expired, results_enabled: true)) } it { should_not be_able_to(:results, create(:poll, :expired, results_enabled: false)) } - it { should_not be_able_to(:results, create(:poll, :current, results_enabled: true)) } + it { should_not be_able_to(:results, create(:poll, results_enabled: true)) } it { should_not be_able_to(:results, create(:poll, :for_budget, :expired, results_enabled: true)) } it { should be_able_to(:stats, create(:poll, :expired, stats_enabled: true)) } it { should_not be_able_to(:stats, create(:poll, :expired, stats_enabled: false)) } - it { should_not be_able_to(:stats, create(:poll, :current, stats_enabled: true)) } + it { should_not be_able_to(:stats, create(:poll, stats_enabled: true)) } it { should_not be_able_to(:stats, create(:poll, :for_budget, :expired, stats_enabled: true)) } it { should be_able_to(:read_results, create(:budget, :finished, results_enabled: true)) } diff --git a/spec/models/poll/booth_spec.rb b/spec/models/poll/booth_spec.rb index 765e3b719..67dd08706 100644 --- a/spec/models/poll/booth_spec.rb +++ b/spec/models/poll/booth_spec.rb @@ -45,7 +45,7 @@ describe Poll::Booth do describe ".available" do it "returns booths associated to current polls" do - booth_for_current_poll = create(:poll_booth, polls: [create(:poll, :current)]) + booth_for_current_poll = create(:poll_booth, polls: [create(:poll)]) booth_for_expired_poll = create(:poll_booth, polls: [create(:poll, :expired)]) expect(Poll::Booth.available).to eq [booth_for_current_poll] @@ -53,7 +53,7 @@ describe Poll::Booth do end it "returns polls with multiple translations only once" do - create(:poll_booth, polls: [create(:poll, :current, name: "English", name_es: "Spanish")]) + create(:poll_booth, polls: [create(:poll, name: "English", name_es: "Spanish")]) expect(Poll::Booth.available.count).to eq 1 end diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb index 751f4a85a..7d48c502f 100644 --- a/spec/models/poll/poll_spec.rb +++ b/spec/models/poll/poll_spec.rb @@ -468,7 +468,7 @@ describe Poll do describe "#recounts_confirmed" do it "is false for current polls" do - poll = create(:poll, :current) + poll = create(:poll) expect(poll.recounts_confirmed?).to be false end diff --git a/spec/system/admin/poll/booths_spec.rb b/spec/system/admin/poll/booths_spec.rb index a930bf9f6..61b440bc0 100644 --- a/spec/system/admin/poll/booths_spec.rb +++ b/spec/system/admin/poll/booths_spec.rb @@ -32,7 +32,7 @@ describe "Admin booths", :admin do end scenario "Available" do - booth_for_current_poll = create(:poll_booth, polls: [create(:poll, :current)]) + booth_for_current_poll = create(:poll_booth, polls: [create(:poll)]) booth_for_expired_poll = create(:poll_booth, polls: [create(:poll, :expired)]) visit admin_root_path @@ -74,7 +74,7 @@ describe "Admin booths", :admin do end scenario "Edit" do - poll = create(:poll, :current) + poll = create(:poll) booth = create(:poll_booth, polls: [poll]) visit admin_booths_path @@ -99,7 +99,7 @@ describe "Admin booths", :admin do end scenario "Back link go back to available list when manage shifts" do - poll = create(:poll, :current) + poll = create(:poll) booth = create(:poll_booth, polls: [poll]) visit available_admin_booths_path diff --git a/spec/system/admin/poll/shifts_spec.rb b/spec/system/admin/poll/shifts_spec.rb index a5a475092..1b92aa606 100644 --- a/spec/system/admin/poll/shifts_spec.rb +++ b/spec/system/admin/poll/shifts_spec.rb @@ -27,7 +27,7 @@ describe "Admin shifts", :admin do scenario "Create Vote Collection Shift and Recount & Scrutiny Shift on same date" do create(:poll) - poll = create(:poll, :current) + poll = create(:poll) booth = create(:poll_booth, polls: [poll, create(:poll, :expired)]) officer = create(:poll_officer) vote_collection_dates = (Date.current..poll.ends_at.to_date).to_a.map { |date| I18n.l(date, format: :long) } @@ -89,7 +89,7 @@ describe "Admin shifts", :admin do end scenario "Vote Collection Shift and Recount & Scrutiny Shift don't include already assigned dates to officer" do - poll = create(:poll, :current) + poll = create(:poll) booth = create(:poll_booth, polls: [poll]) officer = create(:poll_officer) @@ -137,7 +137,7 @@ describe "Admin shifts", :admin do end scenario "Error on create" do - poll = create(:poll, :current) + poll = create(:poll) booth = create(:poll_booth, polls: [poll]) officer = create(:poll_officer) @@ -158,7 +158,7 @@ describe "Admin shifts", :admin do end scenario "Destroy" do - poll = create(:poll, :current) + poll = create(:poll) booth = create(:poll_booth, polls: [poll]) officer = create(:poll_officer) diff --git a/spec/system/budget_polls/voter_spec.rb b/spec/system/budget_polls/voter_spec.rb index 1662d9dbf..45377cdd3 100644 --- a/spec/system/budget_polls/voter_spec.rb +++ b/spec/system/budget_polls/voter_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" describe "BudgetPolls", :with_frozen_time do let(:budget) { create(:budget, :balloting) } let(:investment) { create(:budget_investment, :selected, budget: budget) } - let(:poll) { create(:poll, :current, budget: budget) } + let(:poll) { create(:poll, budget: budget) } let(:booth) { create(:poll_booth) } let(:officer) { create(:poll_officer) } let(:admin) { create(:administrator) } diff --git a/spec/system/dashboard/polls_spec.rb b/spec/system/dashboard/polls_spec.rb index 33647a008..c8f477cd5 100644 --- a/spec/system/dashboard/polls_spec.rb +++ b/spec/system/dashboard/polls_spec.rb @@ -124,7 +124,7 @@ describe "Polls" do end scenario "Edit poll is not allowed for current polls" do - poll = create(:poll, :current, related: proposal) + poll = create(:poll, related: proposal) visit proposal_dashboard_polls_path(proposal) @@ -232,7 +232,7 @@ describe "Polls" do end scenario "View results available for current polls" do - poll = create(:poll, :current, related: proposal) + poll = create(:poll, related: proposal) visit proposal_dashboard_polls_path(proposal) diff --git a/spec/system/officing/voters_spec.rb b/spec/system/officing/voters_spec.rb index 9ab626784..62216860c 100644 --- a/spec/system/officing/voters_spec.rb +++ b/spec/system/officing/voters_spec.rb @@ -1,7 +1,7 @@ require "rails_helper" describe "Voters" do - let(:poll) { create(:poll, :current) } + let(:poll) { create(:poll) } let(:booth) { create(:poll_booth) } let(:officer) { create(:poll_officer) } @@ -35,7 +35,7 @@ describe "Voters" do end scenario "Cannot vote" do - unvotable_poll = create(:poll, :current, geozone_restricted: true, geozones: [create(:geozone, census_code: "02")]) + unvotable_poll = create(:poll, geozone_restricted: true, geozones: [create(:geozone, census_code: "02")]) create(:poll_officer_assignment, officer: officer, poll: unvotable_poll, booth: booth) set_officing_booth(booth) @@ -49,7 +49,7 @@ describe "Voters" do end scenario "Already voted" do - poll2 = create(:poll, :current) + poll2 = create(:poll) create(:poll_officer_assignment, officer: officer, poll: poll2, booth: booth) user = create(:user, :level_two) @@ -84,7 +84,7 @@ describe "Voters" do context "Polls displayed to officers" do scenario "Display current polls assigned to a booth" do - poll = create(:poll, :current) + poll = create(:poll) create(:poll_officer_assignment, officer: officer, poll: poll, booth: booth) set_officing_booth(booth) @@ -96,7 +96,7 @@ describe "Voters" do end scenario "Display polls that the user can vote" do - votable_poll = create(:poll, :current, geozone_restricted: true, geozones: [Geozone.first]) + votable_poll = create(:poll, geozone_restricted: true, geozones: [Geozone.first]) create(:poll_officer_assignment, officer: officer, poll: votable_poll, booth: booth) set_officing_booth(booth) @@ -108,7 +108,7 @@ describe "Voters" do end scenario "Display polls that the user cannot vote" do - unvotable_poll = create(:poll, :current, geozone_restricted: true, geozones: [create(:geozone, census_code: "02")]) + unvotable_poll = create(:poll, geozone_restricted: true, geozones: [create(:geozone, census_code: "02")]) create(:poll_officer_assignment, officer: officer, poll: unvotable_poll, booth: booth) set_officing_booth(booth) @@ -132,8 +132,8 @@ describe "Voters" do end scenario "Do not display polls from other booths" do - poll1 = create(:poll, :current) - poll2 = create(:poll, :current) + poll1 = create(:poll) + poll2 = create(:poll) booth1 = create(:poll_booth) booth2 = create(:poll_booth) diff --git a/spec/system/polls/polls_spec.rb b/spec/system/polls/polls_spec.rb index b0eb0ccaa..d2631c873 100644 --- a/spec/system/polls/polls_spec.rb +++ b/spec/system/polls/polls_spec.rb @@ -543,7 +543,7 @@ describe "Polls" do end scenario "Don't show poll results and stats if is not expired" do - poll = create(:poll, :current, results_enabled: true, stats_enabled: true) + poll = create(:poll, results_enabled: true, stats_enabled: true) user = create(:user) login_as user diff --git a/spec/system/polls/voter_spec.rb b/spec/system/polls/voter_spec.rb index 3b9c6bc1d..46305ce4a 100644 --- a/spec/system/polls/voter_spec.rb +++ b/spec/system/polls/voter_spec.rb @@ -2,7 +2,7 @@ require "rails_helper" describe "Voter" do context "Origin", :with_frozen_time do - let(:poll) { create(:poll, :current) } + let(:poll) { create(:poll) } let(:question) { create(:poll_question, poll: poll) } let(:booth) { create(:poll_booth) } let(:officer) { create(:poll_officer) }