diff --git a/app/controllers/campaign_requests_controller.rb b/app/controllers/campaign_requests_controller.rb index 0cea995bd..30f489fb8 100644 --- a/app/controllers/campaign_requests_controller.rb +++ b/app/controllers/campaign_requests_controller.rb @@ -24,9 +24,15 @@ def campaign_request_params full_responsibility_confirmation accessibility_confirmation cookie_and_privacy_notice_confirmation - start_date - end_date - development_start_date + start_day + start_month + start_year + end_day + end_month + end_year + development_start_day + development_start_month + development_start_year performance_review_contact_email government_theme description diff --git a/app/controllers/content_advice_requests_controller.rb b/app/controllers/content_advice_requests_controller.rb index e9b6e5f4a..009203370 100644 --- a/app/controllers/content_advice_requests_controller.rb +++ b/app/controllers/content_advice_requests_controller.rb @@ -20,7 +20,7 @@ def content_advice_request_params :urls, :contact_number, requester_attributes: %i[email name collaborator_emails], - time_constraint_attributes: %i[needed_by_date time_constraint_reason], + time_constraint_attributes: %i[needed_by_date needed_by_day needed_by_month needed_by_year time_constraint_reason], ).to_h end end diff --git a/app/controllers/content_change_requests_controller.rb b/app/controllers/content_change_requests_controller.rb index 6ac5085a0..26e6eaa2d 100644 --- a/app/controllers/content_change_requests_controller.rb +++ b/app/controllers/content_change_requests_controller.rb @@ -22,7 +22,7 @@ def content_change_request_params :url, :related_urls, requester_attributes: %i[email name collaborator_emails], - time_constraint_attributes: %i[not_before_date needed_by_date time_constraint_reason needed_by_time not_before_time], + time_constraint_attributes: %i[not_before_day not_before_month not_before_year needed_by_date needed_by_day needed_by_month needed_by_year time_constraint_reason needed_by_time not_before_time], ).to_h end end diff --git a/app/controllers/remove_user_requests_controller.rb b/app/controllers/remove_user_requests_controller.rb index 56d498f04..c180a4a73 100644 --- a/app/controllers/remove_user_requests_controller.rb +++ b/app/controllers/remove_user_requests_controller.rb @@ -19,7 +19,7 @@ def remove_user_request_params :user_email, :reason_for_removal, requester_attributes: %i[email name collaborator_emails], - time_constraint_attributes: %i[not_before_date needed_by_date time_constraint_reason], + time_constraint_attributes: %i[needed_by_day needed_by_month needed_by_year time_constraint_reason not_before_day not_before_month not_before_year], ).to_h end end diff --git a/app/helpers/design_system_date_helper.rb b/app/helpers/design_system_date_helper.rb new file mode 100644 index 000000000..e52ba3094 --- /dev/null +++ b/app/helpers/design_system_date_helper.rb @@ -0,0 +1,15 @@ +module DesignSystemDateHelper + def formatted_date(day, month, year) + return "" unless year.present? && month.present? && day.present? + + return errors.add(:base, message: "The provided date is invalid.") unless year.match?(/^\d+$/) + + begin + date = Date.strptime("#{year}-#{month}-#{day}", "%Y-%m-%d") + date.strftime("%d-%m-%Y") + rescue ArgumentError + errors.add :base, message: "The provided date is invalid." + nil + end + end +end diff --git a/app/models/support/gds/campaign.rb b/app/models/support/gds/campaign.rb index 649c8087f..93cfa2c3d 100644 --- a/app/models/support/gds/campaign.rb +++ b/app/models/support/gds/campaign.rb @@ -4,15 +4,22 @@ module Support module GDS class Campaign include ActiveModel::Model + include DesignSystemDateHelper attr_accessor :has_read_guidance_confirmation, :has_read_oasis_guidance_confirmation, :full_responsibility_confirmation, :accessibility_confirmation, :cookie_and_privacy_notice_confirmation, :signed_campaign, - :start_date, - :end_date, - :development_start_date, + :start_day, + :start_month, + :start_year, + :end_day, + :end_month, + :end_year, + :development_start_day, + :development_start_month, + :development_start_year, :performance_review_contact_email, :government_theme, :description, @@ -27,9 +34,15 @@ class Campaign :ga_contact_email validates :signed_campaign, - :start_date, - :end_date, - :development_start_date, + :start_day, + :start_month, + :start_year, + :end_day, + :end_month, + :end_year, + :development_start_day, + :development_start_month, + :development_start_year, :performance_review_contact_email, :government_theme, :description, @@ -50,7 +63,6 @@ class Campaign :accessibility_confirmation, :cookie_and_privacy_notice_confirmation, acceptance: { allow_nil: false, accept: "Yes" } - validates_date :start_date, on_or_after: :today validates_date :end_date, after: :start_date validates_date :development_start_date, on_or_before: :start_date @@ -58,6 +70,18 @@ class Campaign VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :performance_review_contact_email, :ga_contact_email, format: { with: VALID_EMAIL_REGEX } + + def start_date + formatted_date(start_day, start_month, start_year) + end + + def end_date + formatted_date(end_day, end_month, end_year) + end + + def development_start_date + formatted_date(development_start_day, development_start_month, development_start_year) + end end end end diff --git a/app/models/support/requests/time_constraint.rb b/app/models/support/requests/time_constraint.rb index 213b7ca9d..45fde223b 100644 --- a/app/models/support/requests/time_constraint.rb +++ b/app/models/support/requests/time_constraint.rb @@ -4,7 +4,8 @@ module Support module Requests class TimeConstraint include ActiveModel::Model - attr_accessor :not_before_date, :not_before_time, :needed_by_date, :needed_by_time, :time_constraint_reason + include DesignSystemDateHelper + attr_accessor :not_before_day, :not_before_month, :not_before_year, :not_before_time, :needed_by_day, :needed_by_month, :needed_by_year, :needed_by_time, :time_constraint_reason validates_date :needed_by_date, allow_blank: true, on_or_after: :today validates_date :not_before_date, allow_blank: true, on_or_after: :today @@ -24,6 +25,14 @@ class TimeConstraint validates_time :not_before_time, on_or_before: :needed_by_time, unless: proc { |c| [c.needed_by_date, c.needed_by_time, c.not_before_date, c.not_before_time].any?(&:blank?) || c.needed_by_date != c.not_before_date } + + def not_before_date + formatted_date(not_before_day, not_before_month, not_before_year) + end + + def needed_by_date + formatted_date(needed_by_day, needed_by_month, needed_by_year) + end end end end diff --git a/app/views/campaign_requests/_request_details.html.erb b/app/views/campaign_requests/_request_details.html.erb index 6be873901..1fde5eef7 100644 --- a/app/views/campaign_requests/_request_details.html.erb +++ b/app/views/campaign_requests/_request_details.html.erb @@ -78,8 +78,22 @@ Start date of campaign site* <% end %> - - <%= r.text_field :start_date, required: true, aria: { required: true }, placeholder: "dd-mm-yyyy", value: r.object.start_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %> + +
+ + + <%= r.label :start_day, "Day", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :start_day, required: false, value: r.object.start_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "start-day" %> + + + + <%= r.label :start_month, "Month", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :start_month, required: false, value: r.object.start_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "start-month" %> + + + + <%= r.label :start_year, "Year", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :start_year, required: false, value: r.object.start_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "start-year" %>

Once your site is live, you should allow time for testing before driving traffic to it. We advise leaving 1-2 days for no-cost campaigns, and at least a week for paid advertising campaigns. @@ -92,9 +106,24 @@ Proposed end date of campaign site* <% end %> - - <%= r.text_field :end_date, required: true, aria: { required: true }, placeholder: "dd-mm-yyyy", value: r.object.end_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %> + +
+ + + <%= r.label :end_day, "Day", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :end_day, required: false, value: r.object.end_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "end-day" %> + + + + <%= r.label :end_month, "Month", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :end_month, required: false, value: r.object.end_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "end-month" %> + + + <%= r.label :end_year, "Year", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :end_year, required: false, value: r.object.end_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "end-year" %> + +

@@ -103,9 +132,24 @@ Site build to commence on* <% end %> - - <%= r.text_field :development_start_date, required: true, aria: { required: true }, placeholder: "dd-mm-yyyy", value: r.object.development_start_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %> + +
+ + + <%= r.label :development_start_day, "Day", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :development_start_day, required: false, value: r.object.development_start_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "development-start-day" %> + + + <%= r.label :development_start_month, "Month", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :development_start_month, required: false, value: r.object.development_start_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "development-start-month" %> + + + + <%= r.label :development_start_year, "Year", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :development_start_year, required: false, value: r.object.development_start_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "development-start-year" %> + +

We expect the website to go live within 1 month of approval diff --git a/app/views/content_advice_requests/_request_details.html.erb b/app/views/content_advice_requests/_request_details.html.erb index d098ff1e4..3e93575da 100644 --- a/app/views/content_advice_requests/_request_details.html.erb +++ b/app/views/content_advice_requests/_request_details.html.erb @@ -57,11 +57,23 @@

- - <%= r.label :needed_by_date, "Is there a date you need to have a response by?" %> +

+ <%= "Is there a date you need to have a response by?" %> +

+ + + <%= r.label :needed_by_day, "Day", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :needed_by_day, required: false, value: r.object.needed_by_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "needed-by-day" %> - - <%= r.text_field :needed_by_date, placeholder: "dd-mm-yyyy", value: r.object.needed_by_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %> + + + <%= r.label :needed_by_month, "Month", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :needed_by_month, required: false, value: r.object.needed_by_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "needed-by-month" %> + + + + <%= r.label :needed_by_year, "Year", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :needed_by_year, required: false, value: r.object.needed_by_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "needed-by-year" %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 86d4d5980..227ba9efa 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -10,6 +10,7 @@ <%= csrf_meta_tag %> <%= csp_meta_tag %> <%= stylesheet_link_tag "legacy/application", :media => "all" %> + <%= stylesheet_link_tag "application", :media => "all" %> <%= javascript_include_tag "legacy/application" %> <%= javascript_include_tag 'es6-components', type: "module" %> <% end %> diff --git a/app/views/remove_user_requests/_request_details.html.erb b/app/views/remove_user_requests/_request_details.html.erb index 27c29199b..55578afc7 100644 --- a/app/views/remove_user_requests/_request_details.html.erb +++ b/app/views/remove_user_requests/_request_details.html.erb @@ -31,14 +31,44 @@ <%= f.fields_for :time_constraint do |r| %> + +

+ <%= "MUST NOT be removed BEFORE" %> +

+ +
+ For example, 27 3 2007 +
+
- - <%= r.label :not_before_date, "MUST NOT be removed BEFORE" %> - - - <%= r.text_field :not_before_date, required: false, placeholder: "dd-mm-yyyy", value: r.object.not_before_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %> - + +
+ +
+
+ <%= r.label :not_before_day, "Day", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :not_before_day, required: false, value: r.object.not_before_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "not-before-day" %> +
+
+ +
+
+ <%= r.label :not_before_month, "Month", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :not_before_month, required: false, value: r.object.not_before_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "not-before-month" %> +
+
+ +
+
+ <%= r.label :not_before_year, "Year", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :not_before_year, required: false, value: r.object.not_before_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "not-before-year" %> +
+
+ +
+
+ <% end %>
diff --git a/app/views/support/_time_constraint.html.erb b/app/views/support/_time_constraint.html.erb index 9db761f7f..7c5981b55 100644 --- a/app/views/support/_time_constraint.html.erb +++ b/app/views/support/_time_constraint.html.erb @@ -8,9 +8,22 @@ <%= r.label :needed_by_date, "Deadline" %> - - <%= r.text_field :needed_by_date, required: false, placeholder: "dd-mm-yyyy", value: r.object.needed_by_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %> +
+ + + <%= r.label :needed_by_day, "Day", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :needed_by_day, required: false, value: r.object.needed_by_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "needed-by-day" %> + + + + <%= r.label :needed_by_month, "Month", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :needed_by_month, required: false, value: r.object.needed_by_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "needed-by-month" %> + + + <%= r.label :needed_by_year, "Year", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :needed_by_year, required: false, value: r.object.needed_by_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "needed-by-year" %> +
@@ -26,8 +39,21 @@ <%= r.label :not_before_date, "Must not be published before" %> - - <%= r.text_field :not_before_date, required: false, placeholder: "dd-mm-yyyy", value: r.object.not_before_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %> +
+ + + <%= r.label :not_before_day, "Day", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :not_before_day, required: false, value: r.object.not_before_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "not-before-day" %> + + + + <%= r.label :not_before_month, "Month", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :not_before_month, required: false, value: r.object.not_before_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "not-before-month" %> + + + + <%= r.label :not_before_year, "Year", class: "govuk-label govuk-date-input__label" %> + <%= r.text_field :not_before_year, required: false, value: r.object.not_before_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "not-before-year" %>
diff --git a/spec/features/campaign_requests_spec.rb b/spec/features/campaign_requests_spec.rb index 8091e4ebb..1854e46b8 100644 --- a/spec/features/campaign_requests_spec.rb +++ b/spec/features/campaign_requests_spec.rb @@ -92,9 +92,15 @@ accessibility_confirmation: true, cookie_and_privacy_notice_confirmation: true, signed_campaign: "John Smith", - start_date: "01-01-#{next_year}", - end_date: "01-02-#{next_year}", - development_start_date: "31-12-2019", + start_day: "01", + start_month: "01", + start_year: next_year.to_s, + end_day: "01", + end_month: "02", + end_year: next_year.to_s, + development_start_day: "31", + development_start_month: "12", + development_start_year: "2019", performance_review_contact_email: "john.smith@example.com", government_theme: "Example government theme", description: "Pensions", @@ -129,9 +135,15 @@ def user_makes_a_campaign_request(details) check "I/We agree to take responsibility to maintain and up-date the Cookie Notice and Privacy Notice as necessary, with our Data Protection Officer (NB : GDS will add a basic \"boilerplate\", however departments will need to identify if additions are needed)." if details[:cookie_and_privacy_notice_confirmation] fill_in "Name of the Head of Digital Communications who signed off the campaign website application*", with: details[:signed_campaign] - fill_in "Start date of campaign site*", with: details[:start_date] - fill_in "Proposed end date of campaign site*", with: details[:end_date] - fill_in "Site build to commence on", with: details[:development_start_date] + find("#start-day").set(details[:start_day]) + find("#start-month").set(details[:start_month]) + find("#start-year").set(details[:start_year]) + find("#end-day").set(details[:end_day]) + find("#end-month").set(details[:end_month]) + find("#end-year").set(details[:end_year]) + find("#development-start-day").set(details[:development_start_day]) + find("#development-start-month").set(details[:development_start_month]) + find("#development-start-year").set(details[:development_start_year]) fill_in "Contact email/s for website performance review every 6 months*", with: details[:performance_review_contact_email] fill_in "Which of the current Government Communications Plan priority themes does this campaign website support and how?*", with: details[:government_theme] fill_in "Campaign description*", with: details[:description] diff --git a/spec/features/content_advice_requests_spec.rb b/spec/features/content_advice_requests_spec.rb index b97a30176..394ef69eb 100644 --- a/spec/features/content_advice_requests_spec.rb +++ b/spec/features/content_advice_requests_spec.rb @@ -37,7 +37,9 @@ title: "Which format", details: "I need help to choose a format, here's my content...", urls: "https://www.gov.uk/x, https://www.gov.uk/y", - needed_by: "12-01-#{next_year}", + needed_by_day: "12", + needed_by_month: "01", + needed_by_year: next_year.to_s, reason_for_deadline: "Ministerial announcement Z", contact_number: "0121 111111", ) @@ -81,8 +83,9 @@ def user_requests_content_advice(details) fill_in "Title of request", with: details[:title] fill_in "Please explain what you would like help with", with: details[:details] fill_in "Relevant URLs (if applicable)", with: details[:urls] - - fill_in "Is there a date you need to have a response by?", with: details[:needed_by] + find("#needed-by-day").set(details[:needed_by_day]) + find("#needed-by-month").set(details[:needed_by_month]) + find("#needed-by-year").set(details[:needed_by_year]) fill_in "Reason for deadline", with: details[:reason_for_deadline] fill_in "Contact telephone number (in case we need to call you to discuss the content)", with: details[:contact_number] diff --git a/spec/features/content_change_requests_spec.rb b/spec/features/content_change_requests_spec.rb index 784728373..a047c15a8 100644 --- a/spec/features/content_change_requests_spec.rb +++ b/spec/features/content_change_requests_spec.rb @@ -61,9 +61,13 @@ details_of_change: "Out of date XX YY", url: "http://gov.uk/X", related_urls: "http://gov.uk/welsh", - needed_by_date: "31-12-#{next_year}", + needed_by_day: "31", + needed_by_month: "12", + needed_by_year: next_year.to_s, needed_by_time: "13:00", - not_before_date: "01-12-#{next_year}", + not_before_day: "01", + not_before_month: "12", + not_before_year: next_year.to_s, not_before_time: "18:00", reason: "New law", ) diff --git a/spec/features/remove_user_requests_spec.rb b/spec/features/remove_user_requests_spec.rb index f8d435714..d4737a683 100644 --- a/spec/features/remove_user_requests_spec.rb +++ b/spec/features/remove_user_requests_spec.rb @@ -35,7 +35,9 @@ user_name: "Bob", user_email: "bob@someagency.gov.uk", reason_for_removal: "User has left the organisation", - not_before_date: "31-12-#{next_year}", + not_before_day: "31", + not_before_month: "12", + not_before_year: next_year.to_s, ) expect(request).to have_been_made @@ -56,7 +58,9 @@ def user_requests_removal_of_another_user(details) fill_in "Reason for removal", with: details[:reason_for_removal] end - fill_in "MUST NOT be removed BEFORE", with: details[:not_before_date] + find("#not-before-day").set(details[:not_before_day]) + find("#not-before-month").set(details[:not_before_month]) + find("#not-before-year").set(details[:not_before_year]) user_submits_the_request_successfully end diff --git a/spec/helpers/design_system_date_helper_spec.rb b/spec/helpers/design_system_date_helper_spec.rb new file mode 100644 index 000000000..5394c0ec2 --- /dev/null +++ b/spec/helpers/design_system_date_helper_spec.rb @@ -0,0 +1,64 @@ +require "rails_helper" + +describe DesignSystemDateHelper, type: :helper do + include DesignSystemDateHelper + include ActiveModel::Validations + include GdsApi::TestHelpers::SupportApi + + context "Date Helper" do + it "returns formatted date when all input entered are valid" do + day = "28" + month = "09" + year = "1984" + + date_input = formatted_date(day, month, year) + + expect(date_input).to eq("28-09-1984") + end + + it "returns empty string if any values entered are empty strings" do + day = "" + month = "09" + year = "1984" + + date_input = formatted_date(day, month, year) + + expect(date_input).to eq("") + end + end + + context "When Date Helper is receiving invalid date input" do + it "returns 'provided date is invalid' error message when incorrect day is entered" do + allow(self).to receive(:errors).and_return(double("errors", add: true)) + + day = "abc" + month = "09" + year = "1984" + + formatted_date(day, month, year) + expect(errors).to have_received(:add).with(:base, message: "The provided date is invalid.") + end + + it "returns 'provided date is invalid' when incorrect month is entered" do + allow(self).to receive(:errors).and_return(double("errors", add: true)) + + day = "28" + month = "Marchuary" + year = "1984" + + formatted_date(day, month, year) + expect(errors).to have_received(:add).with(:base, message: "The provided date is invalid.") + end + + it "returns 'provided date is invalid' when incorrect year is entered" do + allow(self).to receive(:errors).and_return(double("errors", add: true)) + + day = "28" + month = "09" + year = "foo" + + formatted_date(day, month, year) + expect(errors).to have_received(:add).with(:base, message: "The provided date is invalid.") + end + end +end diff --git a/spec/models/support/gds/campaign_spec.rb b/spec/models/support/gds/campaign_spec.rb index 526eb3e80..8de96e875 100644 --- a/spec/models/support/gds/campaign_spec.rb +++ b/spec/models/support/gds/campaign_spec.rb @@ -7,34 +7,52 @@ def as_str(date) date.strftime("%d-%m-%Y") end - subject do - Campaign.new( + let(:required_attr) do + { signed_campaign: "Test Signer", has_read_guidance_confirmation: "Yes", has_read_oasis_guidance_confirmation: "Yes", full_responsibility_confirmation: "Yes", accessibility_confirmation: "Yes", cookie_and_privacy_notice_confirmation: "Yes", - start_date: as_str(Time.zone.today), - end_date: as_str(Date.tomorrow), - development_start_date: as_str(Time.zone.today), + start_day: Time.zone.today.strftime("%d"), + start_month: Time.zone.today.strftime("%m"), + start_year: Time.zone.today.strftime("%Y"), + end_day: Time.zone.tomorrow.strftime("%d"), + end_month: Time.zone.tomorrow.strftime("%m"), + end_year: Time.zone.tomorrow.strftime("%Y"), + development_start_day: Time.zone.today.strftime("%d"), + development_start_month: Time.zone.today.strftime("%m"), + development_start_year: Time.zone.today.strftime("%Y"), performance_review_contact_email: "test@digital.cabinet-office.gov.uk", government_theme: "Test theme", description: "Test Description", call_to_action: "Test Call to Action", proposed_url: "example.campaign.gov.uk", + site_title: "Some title", + site_tagline: "Some tagline", site_metadescription: "tag1, tag2", cost_of_campaign: 1200, hmg_code: "HMGXX-XXX", strategic_planning_code: "CSBXX-XXX", ga_contact_email: "ga_test@digital.cabinet-office.gov.uk", - ) + } + end + + subject do + Campaign.new(required_attr) end it { should validate_presence_of(:signed_campaign) } - it { should validate_presence_of(:start_date) } - it { should validate_presence_of(:end_date) } - it { should validate_presence_of(:development_start_date) } + it { should validate_presence_of(:start_day) } + it { should validate_presence_of(:start_month) } + it { should validate_presence_of(:start_year) } + it { should validate_presence_of(:end_day) } + it { should validate_presence_of(:end_month) } + it { should validate_presence_of(:end_year) } + it { should validate_presence_of(:development_start_day) } + it { should validate_presence_of(:development_start_month) } + it { should validate_presence_of(:development_start_year) } it { should validate_presence_of(:performance_review_contact_email) } it { should validate_presence_of(:government_theme) } it { should validate_presence_of(:description) } @@ -58,9 +76,32 @@ def as_str(date) it { should allow_value("example.campaign.gov.uk").for(:proposed_url) } it { should_not allow_value("Non Campaign platform").for(:proposed_url) } - it { should_not allow_value("xxx").for(:start_date) } - it { should_not allow_value("xxx").for(:end_date) } - it { should_not allow_value("xxx").for(:development_start_date) } + it "should not allow 'start date' values to be random characters " do + constraint = Campaign.new( + start_day: "xxx", + start_month: "xxx", + start_year: "xxx", + ) + expect(constraint).to_not be_valid + end + + it "should not allow 'end date' values to be random characters " do + constraint = Campaign.new( + end_day: "xxx", + end_month: "xxx", + end_year: "xxx", + ) + expect(constraint).to_not be_valid + end + + it "should not allow 'development start date' values to be random characters " do + constraint = Campaign.new( + development_start_day: "xxx", + development_start_month: "xxx", + development_start_year: "xxx", + ) + expect(constraint).to_not be_valid + end it { should allow_value("test@digital.cabinet-office.gov.uk").for(:performance_review_contact_email) } it { should allow_value("test@test.com").for(:performance_review_contact_email) } @@ -70,16 +111,77 @@ def as_str(date) it { should_not allow_value("test").for(:performance_review_contact_email) } it { should_not allow_value("test@").for(:performance_review_contact_email) } - it { should allow_value(as_str(Date.tomorrow)).for(:start_date) } - it { should allow_value(as_str(Time.zone.today)).for(:start_date) } - it { should_not allow_value(as_str(Time.zone.today - 1)).for(:start_date) } + it "allows the start date to be after today" do + required_attr[:start_day] = Time.zone.tomorrow.strftime("%d") + required_attr[:start_month] = Time.zone.tomorrow.strftime("%m") + required_attr[:start_year] = Time.zone.tomorrow.strftime("%Y") + + required_attr[:end_day] = (Time.zone.tomorrow + 1).strftime("%d") + required_attr[:end_month] = (Time.zone.tomorrow + 1).strftime("%m") + required_attr[:end_year] = (Time.zone.tomorrow + 1).strftime("%Y") + + constraint = Campaign.new(required_attr) + expect(constraint).to be_valid + end + + it "allows the start date to be today" do + constraint = Campaign.new(required_attr) + expect(constraint).to be_valid + end + + it "doesn't allow the start date to in the past" do + required_attr[:start_day] = Time.zone.yesterday.strftime("%d") + required_attr[:start_month] = Time.zone.yesterday.strftime("%m") + required_attr[:start_year] = Time.zone.yesterday.strftime("%Y") + + constraint = Campaign.new(required_attr) + expect(constraint).to_not be_valid + end + + it "allows the end date to be after the start day" do + required_attr[:end_day] = Time.zone.tomorrow.strftime("%d") + required_attr[:end_month] = Time.zone.tomorrow.strftime("%m") + required_attr[:end_year] = Time.zone.tomorrow.strftime("%Y") - it { should allow_value(as_str(Date.tomorrow)).for(:end_date) } - it { should_not(allow_value(as_str(Time.zone.today)).for(:end_date)) } + constraint = Campaign.new(required_attr) + expect(constraint).to be_valid + end + + it "should not allow the end date to be before the start date" do + required_attr[:end_day] = Time.zone.today.strftime("%d") + required_attr[:end_month] = Time.zone.today.strftime("%m") + required_attr[:end_year] = Time.zone.today.strftime("%Y") + + constraint = Campaign.new(required_attr) + expect(constraint).to_not be_valid + end - it { should_not allow_value(as_str(Date.tomorrow)).for(:development_start_date) } - it { should allow_value(as_str(Time.zone.today - 1)).for(:development_start_date) } - it { should allow_value(as_str(Time.zone.today)).for(:development_start_date) } + it "should not allow the development start date to be after start date" do + required_attr[:development_start_day] = Time.zone.tomorrow.strftime("%d") + required_attr[:development_start_month] = Time.zone.tomorrow.strftime("%m") + required_attr[:development_start_year] = Time.zone.tomorrow.strftime("%Y") + + constraint = Campaign.new(required_attr) + expect(constraint).to_not be_valid + end + + it "should allow the development start date to be before the start date" do + required_attr[:development_start_day] = Time.zone.yesterday.strftime("%d") + required_attr[:development_start_month] = Time.zone.yesterday.strftime("%m") + required_attr[:development_start_year] = Time.zone.yesterday.strftime("%Y") + + constraint = Campaign.new(required_attr) + expect(constraint).to be_valid + end + + it "should allow the development start date to be on the start date" do + required_attr[:development_start_day] = Time.zone.today.strftime("%d") + required_attr[:development_start_month] = Time.zone.today.strftime("%m") + required_attr[:development_start_year] = Time.zone.today.strftime("%Y") + + constraint = Campaign.new(required_attr) + expect(constraint).to be_valid + end it { should allow_value("test@digital.cabinet-office.gov.uk").for(:ga_contact_email) } it { should allow_value("test@test.com").for(:ga_contact_email) } diff --git a/spec/models/support/requests/time_constraint_spec.rb b/spec/models/support/requests/time_constraint_spec.rb index 7fb3de8c5..59808798d 100644 --- a/spec/models/support/requests/time_constraint_spec.rb +++ b/spec/models/support/requests/time_constraint_spec.rb @@ -11,26 +11,88 @@ def time_as_str(time) time.strftime("%H:%M") end - it { should_not allow_value("xxx").for(:needed_by_date) } + it "should not allow needed by date values to be random characters " do + constraint = TimeConstraint.new( + needed_by_day: "xxx", + needed_by_month: "xxx", + needed_by_year: "xxx", + ) + expect(constraint).to_not be_valid + end - it { should allow_value(as_str(Date.tomorrow)).for(:needed_by_date) } - it { should allow_value(as_str(Time.zone.today)).for(:needed_by_date) } - it { should_not allow_value(as_str(Date.yesterday)).for(:needed_by_date) } + it "allows the 'needed by' date to be in the future" do + constraint = TimeConstraint.new( + needed_by_day: Time.zone.tomorrow.strftime("%d"), + needed_by_month: Time.zone.tomorrow.strftime("%m"), + needed_by_year: Time.zone.tomorrow.strftime("%Y"), + ) + expect(constraint).to be_valid + end - it { should_not allow_value("xxx").for(:not_before_date) } + it "allows the 'needed by' date to be today" do + constraint = TimeConstraint.new( + needed_by_day: Time.zone.today.strftime("%d"), + needed_by_month: Time.zone.today.strftime("%m"), + needed_by_year: Time.zone.today.strftime("%Y"), + ) + expect(constraint).to be_valid + end - it { should allow_value(as_str(Date.tomorrow)).for(:not_before_date) } - it { should allow_value(as_str(Time.zone.today)).for(:not_before_date) } - it { should_not allow_value(as_str(Date.yesterday)).for(:not_before_date) } + it "should not allow the 'needed by' date to be in the past" do + constraint = TimeConstraint.new( + needed_by_day: Time.zone.yesterday.strftime("%d"), + needed_by_month: Time.zone.yesterday.strftime("%m"), + needed_by_year: Time.zone.yesterday.strftime("%Y"), + ) + expect(constraint).to_not be_valid + end + + it "allows the 'not before' date to be in the future" do + constraint = TimeConstraint.new( + not_before_day: Time.zone.tomorrow.strftime("%d"), + not_before_month: Time.zone.tomorrow.strftime("%m"), + not_before_year: Time.zone.tomorrow.strftime("%Y"), + ) + expect(constraint).to be_valid + end + + it "allows the 'not before' date to be today" do + constraint = TimeConstraint.new( + not_before_day: Time.zone.today.strftime("%d"), + not_before_month: Time.zone.today.strftime("%m"), + not_before_year: Time.zone.today.strftime("%Y"), + ) + expect(constraint).to be_valid + end + + it "doesn't allow the 'not before' date to be in the past" do + constraint = TimeConstraint.new( + not_before_day: Time.zone.yesterday.strftime("%d"), + not_before_month: Time.zone.yesterday.strftime("%m"), + not_before_year: Time.zone.yesterday.strftime("%Y"), + ) + expect(constraint).to_not be_valid + end - it "allows the 'not before' and 'needed by' dates to be blank" do - expect(TimeConstraint.new(not_before_date: "", needed_by_date: "")).to be_valid + it "allows the 'not before' and 'needed by' date fields to be blank" do + expect(TimeConstraint.new( + not_before_day: "", + not_before_month: "", + not_before_year: "", + needed_by_day: "", + needed_by_month: "", + needed_by_year: "", + )).to be_valid end it "doesn't allow the 'not before' date to be set after the 'needed by' date" do constraint = TimeConstraint.new( - not_before_date: as_str(Date.tomorrow + 1.day), - needed_by_date: as_str(Date.tomorrow), + not_before_day: (Time.zone.tomorrow + 1.day).strftime("%d"), + not_before_month: (Time.zone.tomorrow + 1.day).strftime("%m"), + not_before_year: (Time.zone.tomorrow + 1.day).strftime("%Y"), + needed_by_day: Time.zone.tomorrow.strftime("%d"), + needed_by_month: Time.zone.tomorrow.strftime("%m"), + needed_by_year: Time.zone.tomorrow.strftime("%Y"), ) expect(constraint).to_not be_valid expect(constraint).to have_at_least(1).error_on(:not_before_date) @@ -38,8 +100,12 @@ def time_as_str(time) it "doesn't allow the 'not before' time to be set after the 'needed by' time, if the 'not before' date and 'not before' time are the same" do constraint = TimeConstraint.new( - not_before_date: as_str(Date.tomorrow), - needed_by_date: as_str(Date.tomorrow), + not_before_day: Time.zone.tomorrow.strftime("%d"), + not_before_month: Time.zone.tomorrow.strftime("%m"), + not_before_year: Time.zone.tomorrow.strftime("%Y"), + needed_by_day: Time.zone.tomorrow.strftime("%d"), + needed_by_month: Time.zone.tomorrow.strftime("%m"), + needed_by_year: Time.zone.tomorrow.strftime("%Y"), not_before_time: "12:00", needed_by_time: "11:00", ) @@ -49,8 +115,12 @@ def time_as_str(time) it "allows the 'not before' time to be set after the 'needed by' time, if the 'not before' date and 'not before' time are different" do constraint = TimeConstraint.new( - not_before_date: as_str(Date.tomorrow), - needed_by_date: as_str(Date.tomorrow + 1.day), + not_before_day: Time.zone.tomorrow.strftime("%d"), + not_before_month: Time.zone.tomorrow.strftime("%m"), + not_before_year: Time.zone.tomorrow.strftime("%Y"), + needed_by_day: (Time.zone.tomorrow + 1.day).strftime("%d"), + needed_by_month: (Time.zone.tomorrow + 1.day).strftime("%m"), + needed_by_year: (Time.zone.tomorrow + 1.day).strftime("%Y"), not_before_time: "12:00", needed_by_time: "11:00", ) @@ -59,14 +129,18 @@ def time_as_str(time) it "validates that the 'not before' time is after now" do constraint = TimeConstraint.new( - not_before_date: as_str(Time.zone.today), + not_before_day: Time.zone.today.strftime("%d"), + not_before_month: Time.zone.today.strftime("%m"), + not_before_year: Time.zone.today.strftime("%Y"), not_before_time: time_as_str(Time.zone.now - 1.minute), ) expect(constraint).to_not be_valid expect(constraint).to have_at_least(1).error_on(:not_before_time) constraint = TimeConstraint.new( - not_before_date: as_str(Date.tomorrow), + not_before_day: Time.zone.tomorrow.strftime("%d"), + not_before_month: Time.zone.tomorrow.strftime("%m"), + not_before_year: Time.zone.tomorrow.strftime("%Y"), not_before_time: time_as_str(Time.zone.now - 1.minute), ) expect(constraint).to be_valid @@ -74,27 +148,39 @@ def time_as_str(time) it "validates that the 'needed by' time is after now" do constraint = TimeConstraint.new( - needed_by_date: as_str(Time.zone.today), + needed_by_day: Time.zone.today.strftime("%d"), + needed_by_month: Time.zone.today.strftime("%m"), + needed_by_year: Time.zone.today.strftime("%Y"), needed_by_time: time_as_str(Time.zone.now - 1.minute), ) expect(constraint).to_not be_valid expect(constraint).to have_at_least(1).error_on(:needed_by_time) constraint = TimeConstraint.new( - needed_by_date: as_str(Time.zone.tomorrow), + needed_by_day: Time.zone.tomorrow.strftime("%d"), + needed_by_month: Time.zone.tomorrow.strftime("%m"), + needed_by_year: Time.zone.tomorrow.strftime("%Y"), needed_by_time: time_as_str(Time.zone.now - 1.minute), ) expect(constraint).to be_valid end it "allows a blank not_before_date if the needed_by_date is set" do - expect(TimeConstraint.new(needed_by_date: as_str(Date.tomorrow))).to be_valid + expect(TimeConstraint.new( + needed_by_day: Time.zone.tomorrow.strftime("%d"), + needed_by_month: Time.zone.tomorrow.strftime("%m"), + needed_by_year: Time.zone.tomorrow.strftime("%Y"), + )).to be_valid end it "allows launch dates (i.e. not_before_date = needed_by_date)" do constraint = TimeConstraint.new( - not_before_date: as_str(Date.tomorrow), - needed_by_date: as_str(Date.tomorrow), + not_before_day: Time.zone.tomorrow.strftime("%d"), + not_before_month: Time.zone.tomorrow.strftime("%m"), + not_before_year: Time.zone.tomorrow.strftime("%Y"), + needed_by_day: Time.zone.tomorrow.strftime("%d"), + needed_by_month: Time.zone.tomorrow.strftime("%m"), + needed_by_year: Time.zone.tomorrow.strftime("%Y"), ) expect(constraint).to be_valid end @@ -117,8 +203,12 @@ def time_as_str(time) it "returns the correct error message when 'not before' date is after 'needed by' date" do constraint = Support::Requests::TimeConstraint.new( - not_before_date: (Time.zone.today + 2.days).strftime("%d-%m-%Y"), - needed_by_date: (Time.zone.today + 1.day).strftime("%d-%m-%Y"), + not_before_day: (Time.zone.today + 2.days).strftime("%d"), + not_before_month: (Time.zone.today + 2.days).strftime("%m"), + not_before_year: (Time.zone.today + 2.days).strftime("%Y"), + needed_by_day: (Time.zone.today + 1.day).strftime("%d"), + needed_by_month: (Time.zone.today + 1.day).strftime("%m"), + needed_by_year: (Time.zone.today + 1.day).strftime("%Y"), ) constraint.valid? diff --git a/spec/support/app_actions.rb b/spec/support/app_actions.rb index e136a58ba..2832c0f36 100644 --- a/spec/support/app_actions.rb +++ b/spec/support/app_actions.rb @@ -83,9 +83,13 @@ def doctype_summary_results end def user_fills_out_time_constraints(details) - fill_in "Deadline", with: details[:needed_by_date] + find("#needed-by-day").set(details[:needed_by_day]) + find("#needed-by-month").set(details[:needed_by_month]) + find("#needed-by-year").set(details[:needed_by_year]) fill_in "Time this must be published by", with: details[:needed_by_time] - fill_in "Must not be published before", with: details[:not_before_date] + find("#not-before-day").set(details[:not_before_day]) + find("#not-before-month").set(details[:not_before_month]) + find("#not-before-year").set(details[:not_before_year]) fill_in "Time this must not be published before", with: details[:not_before_time] fill_in "Reason for deadline", with: details[:reason] end