diff --git a/Gemfile.lock b/Gemfile.lock index 446e3a55..9846f7ee 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -345,7 +345,7 @@ GEM rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) sexp_processor (4.16.1) - shoulda-matchers (5.1.0) + shoulda-matchers (5.3.0) activesupport (>= 5.2.0) simplecov (0.21.2) docile (~> 1.1) diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 2879890f..79093667 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -13,20 +13,21 @@ def show end def new - venue = Venue.find_by(id: params[:venue_id]) - @event = Event.new(venue:) + @form = CreateEventForm.new(venue_id: params[:venue_id]) end def edit @event = Event.find(params[:id]) + @form = EditEventForm.from_event(@event) end def create - @event = Event.new(event_params) + @form = CreateEventForm.new(event_params) - if @event.save + if @form.valid? + event = Event.create!(@form.to_h) flash[:notice] = t("flash.success", model: "Event", action: "created") - redirect_to(@event) + redirect_to(event) else render action: "new" end @@ -35,10 +36,11 @@ def create def update @event = Event.find(params[:id]) - audit_comment = EventParamsCommenter.new.comment(@event, event_params) - update_params = event_params.merge!(audit_comment) - - if @event.update(update_params) + @form = EditEventForm.new(event_params) + if @form.valid? + audit_comment = EventParamsCommenter.new.comment(@event, event_params) + update_params = @form.to_h.merge!(audit_comment) + @event.update!(update_params) flash[:notice] = t("flash.success", model: "Event", action: "updated") redirect_to(@event) else @@ -78,8 +80,8 @@ def event_params course_length day frequency - date_array - cancellation_array + dates + cancellations first_date last_date url diff --git a/app/forms/create_event_form.rb b/app/forms/create_event_form.rb new file mode 100644 index 00000000..1ea549c1 --- /dev/null +++ b/app/forms/create_event_form.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +class CreateEventForm + include ActiveModel::Model + include ActiveModel::Attributes + + attribute :title, :string + attribute :url, :string + attribute :venue_id, :integer + attribute :event_type, :string + + attribute :has_social, :boolean + attribute :social_organiser_id, :integer + + attribute :has_class, :boolean + attribute :has_taster, :boolean + attribute :class_style, :string + attribute :course_length, :string + attribute :class_organiser_id, :integer + + attribute :frequency, :integer + attribute :day, :string + attribute :dates, :string + attribute :cancellations, :string + attribute :first_date, :string + attribute :last_date, :string + + def self.model_name + Event.model_name + end + + validates :url, presence: true, uri: true + validates :venue_id, presence: true + validates :event_type, presence: true + validates :frequency, presence: true + validates :course_length, numericality: { only_integer: true, greater_than: 0, allow_blank: true } + + validates_with ValidSocialOrClass + validates_with ValidWeeklyEvent + + def action + "Create" + end + + def weekly? + frequency == 1 + end + + def infrequent? + return false if frequency.nil? + + frequency.zero? || frequency >= 4 + end + + def has_social? # rubocop:disable Naming/PredicateName + !!has_social + end + + def has_class? # rubocop:disable Naming/PredicateName + !!has_class + end + + def to_h + attributes.merge( + "dates" => DatesStringParser.new.parse(dates), + "cancellations" => DatesStringParser.new.parse(cancellations) + ) + end +end diff --git a/app/forms/edit_event_form.rb b/app/forms/edit_event_form.rb new file mode 100644 index 00000000..350972e7 --- /dev/null +++ b/app/forms/edit_event_form.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +class EditEventForm < CreateEventForm + include ActiveModel::Model + include ActiveModel::Attributes + + class << self + def from_event(event) + new( + { + title: event.title, + url: event.url, + venue_id: event.venue_id, + event_type: event.event_type, + + has_social: event.has_social, + social_organiser_id: event.social_organiser_id, + + has_class: event.has_class, + has_taster: event.has_taster, + class_style: event.class_style, + course_length: event.course_length, + class_organiser_id: event.class_organiser_id, + + frequency: event.frequency, + day: event.day, + dates: event.print_dates, + cancellations: event.print_cancellations, + first_date: event.first_date, + last_date: event.last_date + } + ) + end + end + + def action + "Update" + end + + def persisted? + true + end +end diff --git a/app/helpers/listings_helper.rb b/app/helpers/listings_helper.rb index a599c0e9..8f269527 100644 --- a/app/helpers/listings_helper.rb +++ b/app/helpers/listings_helper.rb @@ -122,7 +122,7 @@ def postcode_link(postcode_string, map_url = nil) # Return a span containing a message about cancelled dates: def swingclass_cancelledmsg(swingclass) - return "" if swingclass.cancellation_array(future: true).empty? + return "" if swingclass.future_cancellations.empty? date_printer = DatePrinter.new(separator: ", ", format: :short_date) cancellations = date_printer.print(swingclass.future_cancellations) diff --git a/app/models/event.rb b/app/models/event.rb index 637991a3..5c729f1f 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -144,10 +144,6 @@ def dates=(array_of_new_dates) array_of_new_dates.each { |nd| add_date(nd) } end - def date_array=(date_string) - self.dates = DatesStringParser.new.parse(date_string) - end - def cancellations swing_cancellations.collect(&:date) end @@ -161,24 +157,10 @@ def add_cancellation(new_cancellation) swing_cancellations << SwingDate.find_or_initialize_by(date: new_cancellation) end - def cancellation_array=(date_string) - self.cancellations = DatesStringParser.new.parse(date_string) - end - def future_cancellations filter_future(cancellations) end - # READ METHODS # - - def date_array(future: false) - return_array_of_dates(dates, future:) - end - - def cancellation_array(future: false) - return_array_of_dates(cancellations, future:) - end - private # Given an array of dates, return an appropriately filtered array diff --git a/app/services/event_params_commenter.rb b/app/services/event_params_commenter.rb index 8ee6c0e4..ea4e092a 100644 --- a/app/services/event_params_commenter.rb +++ b/app/services/event_params_commenter.rb @@ -17,19 +17,23 @@ def comment(event, update_params) private def updated_dates_comment(event, update_params) - comment_text("Updated dates", event.print_dates, update_params[:date_array]) + comment_text("Updated dates", event.print_dates, update_params[:dates]) end def updated_cancellations_comment(event, update_params) - comment_text("Updated cancellations", event.print_cancellations, update_params[:cancellation_array]) + comment_text("Updated cancellations", event.print_cancellations, update_params[:cancellations]) end def changed_dates(event, update_params) - (event.print_dates != update_params[:date_array]) + return false if update_params[:dates].nil? + + (event.print_dates != update_params[:dates]) end def changed_cancellations(event, update_params) - (event.print_cancellations != update_params[:cancellation_array]) + return false if update_params[:cancellations].nil? + + (event.print_cancellations != update_params[:cancellations]) end def comment_text(message, old, new) diff --git a/app/validators/valid_weekly_event.rb b/app/validators/valid_weekly_event.rb index 4a803fda..24c1e3dd 100644 --- a/app/validators/valid_weekly_event.rb +++ b/app/validators/valid_weekly_event.rb @@ -15,8 +15,8 @@ def weekly_events_must_have_day(event) end def cannot_be_weekly_and_have_dates(event) - return unless event.weekly? && !event.dates.empty? + return unless event.weekly? && event.dates.present? - event.errors.add(:date_array, "must be empty for weekly events") + event.errors.add(:dates, "must be empty for weekly events") end end diff --git a/app/views/events/_event_listing_table_row.html.erb b/app/views/events/_event_listing_table_row.html.erb index 64cfd368..f2f468ff 100644 --- a/app/views/events/_event_listing_table_row.html.erb +++ b/app/views/events/_event_listing_table_row.html.erb @@ -30,7 +30,7 @@ <%= link_to 'Show', event %> <%= link_to 'Delete', event, data: { confirm: 'Are you sure you want to delete this event?' }, method: :delete %> - <%= link_to 'Archive', archive_event_path(event), :method => :put %> + <%= link_to 'Archive', archive_event_path(event), data: { "turbo-method" => :put } %> <% end %> diff --git a/app/views/events/_form.html.erb b/app/views/events/_form.html.erb index f747b969..b7a77630 100644 --- a/app/views/events/_form.html.erb +++ b/app/views/events/_form.html.erb @@ -1,5 +1,5 @@ -<%= form_with(model: @event, class: "event-form") do |f| %> - <%= render "shared/error_messages", target: @event %> +<%= form_with(model: @form, url: submit_path, class: "event-form") do |f| %> + <%= render "shared/error_messages", target: @form %>
@@ -24,7 +24,7 @@
- <% if @event.persisted? %> + <% if @form.persisted? %> <%= render "events/organiser_link", event: @event %> <% end %> @@ -66,14 +66,14 @@

Class style

- <%= radio_button_tag 'class_style_option', 'lindy', @event.class_style.blank? %> + <%= radio_button_tag 'class_style_option', 'lindy', @form.class_style.blank? %> <%= label_tag :class_style_option_lindy, t('forms.events.default_class_style') %>
- <%= radio_button_tag 'class_style_option', 'other', !@event.class_style.blank?, data: { target: 'class-style-group' }%> + <%= radio_button_tag 'class_style_option', 'other', !@form.class_style.blank?, data: { target: 'class-style-group' }%> <%= label_tag 'class_style_option_other', 'Other (balboa, shag etc)' %>
-
' id="class-style-group"> +
' id="class-style-group"> <%= f.label :class_style, "Dance style:" %> <%= f.text_field :class_style %>
@@ -96,23 +96,23 @@ <%= f.radio_button(:frequency, 0, data: { action: "event-frequency#setInfrequently" }) %> Monthly or occasionally - <% if @event.persisted? && [0, 1].exclude?(@event.frequency) %> -

Legacy frequency: <%= @event.frequency %>

+ <% if @form.persisted? && [0, 1].exclude?(@form.frequency) %> +

Legacy frequency: <%= @form.frequency %>

<% end %>
-
+
<%= f.label :day %> <%= f.select :day, DAYNAMES, include_blank: true %>
-
- <%= f.label :date_array, 'Upcoming dates' %> +
+ <%= f.label :dates, 'Upcoming dates' %>

<%= t('forms.help.dates') %>

- <%= f.text_field :date_array, value: @event.print_dates %> + <%= f.text_field :dates, value: @form.dates %>
- <%= f.label :cancellation_array, 'Cancelled dates' %> + <%= f.label :cancellations, 'Cancelled dates' %>

<%= t('forms.help.dates') %>

- <%= f.text_field :cancellation_array, value: @event.print_cancellations %> + <%= f.text_field :cancellations, value: @form.cancellations %>
<%= f.label :first_date %> @@ -121,17 +121,17 @@ A NEW! label will be shown on the listing for <%= distance_of_time_in_words(Event::CONSIDERED_NEW_FOR) %> after this date.

- <%= f.text_field :first_date, value: @event.first_date.to_s, size: 10, class: "shortfield" %> + <%= f.text_field :first_date, value: @form.first_date.to_s, size: 10, class: "shortfield" %>
<%= f.label :last_date %>

The event will stop being included in the listings after this date

- <%= f.text_field :last_date, value: @event.last_date.to_s, size: 10, class: "shortfield" %> + <%= f.text_field :last_date, value: @form.last_date.to_s, size: 10, class: "shortfield" %>
- <%= f.submit action, class: 'button' %> + <%= f.submit @form.action, class: 'button' %> <%= link_to 'Cancel', cancel_path, class: "button button-secondary" %>
<% end %> diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb index faaf2d69..810a44ca 100644 --- a/app/views/events/edit.html.erb +++ b/app/views/events/edit.html.erb @@ -1,3 +1,3 @@

Editing event

-<%=render partial: "form", locals: { action: "Update", cancel_path: event_path(@event) } %> +<%= render "form", submit_path: event_path(@event), cancel_path: event_path(@event) %> diff --git a/app/views/events/new.html.erb b/app/views/events/new.html.erb index 3466c307..72f97e18 100644 --- a/app/views/events/new.html.erb +++ b/app/views/events/new.html.erb @@ -1,3 +1,3 @@

New event

-<%=render partial: "form", locals: { action: "Create", cancel_path: events_path } %> +<%= render "form", submit_path: events_path, cancel_path: events_path %> diff --git a/spec/controllers/events_controller_spec.rb b/spec/controllers/events_controller_spec.rb index 8c0fc4ac..dff048e0 100644 --- a/spec/controllers/events_controller_spec.rb +++ b/spec/controllers/events_controller_spec.rb @@ -32,26 +32,4 @@ expect(assigns[:warning]).to be_nil end end - - describe "GET new" do - context "when a venue id is provided which matches a venue" do - it "creates an event at that venue" do - venue = create(:venue, id: 23) - get :new, params: { venue_id: 23 } - expect(assigns(:event).venue).to eq venue - end - end - - context "when a venue id is provided which doesn't match a venue" do - [ - 23, - nil - ].each do |vid| - it "creates an event with a null venue" do - get :new, params: { venue_id: vid } - expect(assigns(:event).venue).to be_nil - end - end - end - end end diff --git a/spec/form_spec_helper.rb b/spec/form_spec_helper.rb new file mode 100644 index 00000000..e40c2508 --- /dev/null +++ b/spec/form_spec_helper.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require "spec_helper" +require "active_model" +require "factory_bot" +require "faker" +require "spec/support/forms/shoulda_matchers" + +RSpec.configure do |config| + config.include FactoryBot::Syntax::Methods + config.include Shoulda::Matchers::ActiveModel +end + +FactoryBot.define do + trait :event_form do + title { Faker::Company.social_dance } + has_taster { false } + has_class { false } + has_social { true } + event_type { "school" } + frequency { 0 } + url { Faker::Internet.url } + venue_id { rand(999) } + end + + factory :create_event_form do + event_form + end + + factory :edit_event_form do + event_form + end +end + +# MONKEY PATCH +module Shoulda + module Matchers + module RailsShim + class << self + def serialized_attributes_for(model) + # the real definition depends on ::ActiveRecord::Type::Serialized, which we're not loading in these isolated specs: + # https://github.com/thoughtbot/shoulda-matchers/issues/1553 + attribute_types_for(model) + end + end + end + end +end + +# Add locale to the path for Faker +I18n.load_path << "./config/locales/en.yml" + +def stub_model_name(model_class_name) + model_name = instance_double("ActiveModel::Name", human: model_class_name.downcase, i18n_key: model_class_name.downcase.to_sym) + stub_const(model_class_name, class_double(model_class_name, model_name:)) +end diff --git a/spec/forms/create_event_form_spec.rb b/spec/forms/create_event_form_spec.rb new file mode 100644 index 00000000..c97a12fc --- /dev/null +++ b/spec/forms/create_event_form_spec.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true + +require "form_spec_helper" +require "config/initializers/inflections" # because of URI in URIValidator +require "app/validators/uri_validator" +require "app/validators/valid_social_or_class" +require "app/validators/valid_weekly_event" +require "app/forms/create_event_form" +require "spec/support/shared_examples/events/validates_class_and_social" +require "spec/support/shared_examples/events/validates_weekly" +require "spec/support/shared_examples/events/validates_course_length" +require "spec/support/shared_examples/validates_url" + +RSpec.describe CreateEventForm do + describe "(validations)" do + subject { described_class.new } + + before { stub_model_name("Event") } + + it_behaves_like "validates class and social", :create_event_form + it_behaves_like "validates weekly", :create_event_form + it_behaves_like "validates course length", :create_event_form + it_behaves_like "validates url", :create_event_form + + it { is_expected.to validate_presence_of(:event_type) } + it { is_expected.to validate_presence_of(:frequency) } + it { is_expected.to validate_presence_of(:url) } + it { is_expected.to validate_presence_of(:venue_id) } + end + + describe "#action" do + it "is 'Create'" do + form = described_class.new + + expect(form.action).to eq "Create" + end + end + + describe "#weekly?" do + it "is true if frequency is 1" do + form = described_class.new(frequency: 1) + + expect(form.weekly?).to be true + end + + it "is false if frequency is not 1" do + form = described_class.new(frequency: 0) + + expect(form.weekly?).to be false + end + end + + describe "infrequent?" do + it "is true if frequency is 0" do + form = described_class.new(frequency: 0) + + expect(form.infrequent?).to be true + end + + it "is true if frequency is 4" do + form = described_class.new(frequency: 4) + + expect(form.infrequent?).to be true + end + + it "is true if frequency is more than 4" do + form = described_class.new(frequency: 5) + + expect(form.infrequent?).to be true + end + + it "is false if frequency is 1" do + form = described_class.new(frequency: 1) + + expect(form.infrequent?).to be false + end + end + + # Are these still a thing?? + # it "handles an event with no dates and a weekly event" do + # event = create(:event) + # event.dates = "Weekly" + # end + # + # it "handles an event with no dates and adding unknown dates" do + # event = create(:event) + # event.dates = "Unknown" + # expect(event.swing_dates).to eq([]) + # end + + pending "multiple valid dates, one invalid date on the end" + pending "multiple valid dates, one invalid date in the middle" + pending "blanking out where there are existing dates" + pending "fails to add an invalid date to an event" + + pending "save with an invalid dates array" + + pending "test with multiple dates, different orders, whitespace" + + pending "multiple valid cancellations, one invalid date on the end" + pending "multiple valid cancellations, one invalid date in the middle" + pending "fails to add an invalid date to an event" + + pending "save with an invalid cancellations array" + + pending "test with multiple cancellations, different orders, whitespace" +end diff --git a/spec/forms/edit_event_form_spec.rb b/spec/forms/edit_event_form_spec.rb new file mode 100644 index 00000000..6cb8c4f2 --- /dev/null +++ b/spec/forms/edit_event_form_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require "form_spec_helper" +require "config/initializers/inflections" # because of URI in URIValidator +require "app/validators/uri_validator" +require "app/validators/valid_social_or_class" +require "app/validators/valid_weekly_event" +require "app/forms/create_event_form" +require "app/forms/edit_event_form" +require "spec/support/shared_examples/events/validates_class_and_social" +require "spec/support/shared_examples/events/validates_weekly" +require "spec/support/shared_examples/events/validates_course_length" +require "spec/support/shared_examples/validates_url" + +RSpec.describe EditEventForm do + describe "(validations)" do + subject { described_class.new } + + before { stub_model_name("Event") } + + it_behaves_like "validates class and social", :edit_event_form + it_behaves_like "validates weekly", :edit_event_form + it_behaves_like "validates course length", :edit_event_form + it_behaves_like "validates url", :edit_event_form + + it { is_expected.to validate_presence_of(:event_type) } + it { is_expected.to validate_presence_of(:frequency) } + it { is_expected.to validate_presence_of(:url) } + it { is_expected.to validate_presence_of(:venue_id) } + end + + describe "#action" do + it "is 'Update'" do + form = described_class.new + + expect(form.action).to eq "Update" + end + end + + describe ".persisted?" do + it "is always true" do + expect(described_class.new.persisted?).to be true + end + end +end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 3eab3442..b702b547 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -71,124 +71,72 @@ end # ultimately do away with date_array and test .dates= instead" - describe ".date_array =" do + describe ".dates =" do describe "empty strings" do it "handles an event with with no dates and adding no dates" do event = create(:event) - event.date_array = "" + event.dates = [] expect(event.swing_dates).to eq([]) end - - it "handles an event with with no dates and adding nil dates" do - event = create(:event) - event.date_array = nil - expect(event.swing_dates).to eq([]) - end - - it "handles an event with no dates and adding unknown dates" do - event = create(:event) - event.date_array = "Unknown" - expect(event.swing_dates).to eq([]) - end - - it "handles an event with no dates and a weekly event" do - event = create(:event) - event.date_array = "Weekly" - end end it "successfully adds one valid date to an event" do event = create(:event) - event.date_array = "01/02/2012" + event.dates = ["01/02/2012".to_date] expect(event.dates).to eq([Date.new(2012, 2, 1)]) end it "successfully adds two valid dates to an event with no dates and orders them" do event = create(:event) - event.date_array = "01/02/2012, 30/11/2011" + event.dates = ["01/02/2012", "30/11/2011"].map(&:to_date) expect(event.dates).to eq([Date.new(2011, 11, 30), Date.new(2012, 2, 1)]) end it "blanks out a date array where there existing dates" do # rubocop:disable RSpec/MultipleExpectations - event = create(:event, date_array: "01/02/2012, 30/11/2011") + event = create(:event, dates: ["01/02/2012", "30/11/2011"].map(&:to_date)) expect(event.dates).to eq([Date.new(2011, 11, 30), Date.new(2012, 2, 1)]) - event.date_array = "" + event.dates = [] expect(event.dates).to eq([]) end it "does not create multiple instances of the same date" do event1 = create(:event) - event1.date_array = "05/05/2005" + event1.dates = ["05/05/2005".to_date] event1.save! event2 = create(:event) - event2.date_array = "05/05/2005" + event2.dates = ["05/05/2005".to_date] event2.save! expect(SwingDate.where(date: Date.new(2005, 5, 5)).length).to eq(1) end - - pending "multiple valid dates, one invalid date on the end" - pending "multiple valid dates, one invalid date in the middle" - pending "blanking out where there are existing dates" - pending "fails to add an invalid date to an event" - - pending "save with an invalid dates array" - - pending "test with multiple dates, different orders, whitespace" end - describe ".cancellation_array =" do + describe ".cancellations =" do describe "empty strings" do it "handles an event with with no cancellations and adding no cancellations" do event = described_class.new - event.cancellation_array = "" - expect(event.swing_cancellations).to eq([]) - end - - it "handles an event with with no cancellations and adding nil cancellations" do - event = described_class.new - event.cancellation_array = nil - expect(event.swing_cancellations).to eq([]) - end - - it "handles an event with no cancellations and adding unknown cancellations" do - event = described_class.new - event.cancellation_array = "Unknown" - expect(event.swing_cancellations).to eq([]) - end - - it "handles an event with no cancellations and a weekly event" do - event = described_class.new - event.cancellation_array = "Weekly" + event.cancellations = [] expect(event.swing_cancellations).to eq([]) end end it "successfully adds one valid cancellation to an event with no cancellations" do event = described_class.new - event.cancellation_array = "01/02/2012" + event.cancellations = ["01/02/2012".to_date] expect(event.cancellations).to eq([Date.new(2012, 2, 1)]) end it "successfully adds two valid cancellations to an event with no cancellations and orders them" do event = described_class.new - event.cancellation_array = "01/02/2012, 30/11/2011" + event.cancellations = ["01/02/2012", "30/11/2011"].map(&:to_date) expect(event.cancellations).to eq([Date.new(2012, 2, 1), Date.new(2011, 11, 30)]) end it "blanks out a cancellation array where there existing dates" do # rubocop:disable RSpec/MultipleExpectations - event = create(:event, cancellation_array: "01/02/2012") + event = create(:event, cancellations: ["01/02/2012".to_date]) expect(event.cancellations).to eq([Date.new(2012, 2, 1)]) - event.cancellation_array = "" + event.cancellations = [] expect(event.cancellations).to eq([]) end - - pending "multiple valid cancellations, one invalid date on the end" - pending "multiple valid cancellations, one invalid date in the middle" - pending "fails to add an invalid date to an event" - - pending "save with an invalid cancellations array" - - pending "test with multiple cancellations, different orders, whitespace" end describe "active.classes" do @@ -232,9 +180,9 @@ describe "(validations)" do subject { build(:event) } - it_behaves_like "validates class and social" - it_behaves_like "validates weekly" - it_behaves_like "validates course length" + it_behaves_like "validates class and social", :event + it_behaves_like "validates weekly", :event + it_behaves_like "validates course length", :event it_behaves_like "validates url", :event it "is invalid with no venue" do diff --git a/spec/services/event_params_commenter_spec.rb b/spec/services/event_params_commenter_spec.rb index 7065c75d..50ec3d58 100644 --- a/spec/services/event_params_commenter_spec.rb +++ b/spec/services/event_params_commenter_spec.rb @@ -2,13 +2,14 @@ require "spec_helper" require "app/services/event_params_commenter" +require "active_support/core_ext/string/conversions" RSpec.describe EventParamsCommenter do describe "#comment" do context "when there are changes to the dates" do it "returns an audit comment" do - event = instance_double("Event", print_dates: "12/04/2011", print_cancellations: nil) - update_params = { date_array: "11/04/2011" } + event = instance_double("Event", print_dates: "12/04/2011", print_cancellations: "") + update_params = { dates: "11/04/2011" } comment = described_class.new.comment(event, update_params) expect(comment).to eq(audit_comment: "Updated dates: (old: 12/04/2011) (new: 11/04/2011)") @@ -17,8 +18,8 @@ context "when there are no changes to the dates" do it "returns an empty hash" do - event = instance_double("Event", print_dates: "12/04/2011", print_cancellations: nil) - update_params = { date_array: "12/04/2011" } + event = instance_double("Event", print_dates: "12/04/2011", print_cancellations: "") + update_params = { dates: "12/04/2011" } comment = described_class.new.comment(event, update_params) expect(comment).to eq({}) @@ -27,8 +28,8 @@ context "when there are changes to the cancellations" do it "returns an audit comment" do - event = instance_double("Event", print_dates: nil, print_cancellations: "12/04/2011") - update_params = { cancellation_array: "11/04/2011" } + event = instance_double("Event", print_dates: "", print_cancellations: "12/04/2011") + update_params = { cancellations: "11/04/2011" } comment = described_class.new.comment(event, update_params) expect(comment).to eq(audit_comment: "Updated cancellations: (old: 12/04/2011) (new: 11/04/2011)") @@ -38,7 +39,7 @@ context "when there are changes to both dates and cancellations" do it "returns an audit comment" do event = instance_double("Event", print_dates: "12/04/2011", print_cancellations: "12/04/2011") - update_params = { date_array: "11/04/2011", cancellation_array: "11/04/2011" } + update_params = { dates: "11/04/2011", cancellations: "11/04/2011" } comment = described_class.new.comment(event, update_params) expect(comment).to eq( diff --git a/spec/support/forms/shoulda_matchers b/spec/support/forms/shoulda_matchers new file mode 100644 index 00000000..e92475a5 --- /dev/null +++ b/spec/support/forms/shoulda_matchers @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require "shoulda/matchers" + +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :active_model + end +end diff --git a/spec/support/forms/shoulda_matchers.rb b/spec/support/forms/shoulda_matchers.rb new file mode 100644 index 00000000..e92475a5 --- /dev/null +++ b/spec/support/forms/shoulda_matchers.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require "shoulda/matchers" + +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :active_model + end +end diff --git a/spec/support/shared_examples/events/validates_class_and_social.rb b/spec/support/shared_examples/events/validates_class_and_social.rb index a5f38e81..c1b17360 100644 --- a/spec/support/shared_examples/events/validates_class_and_social.rb +++ b/spec/support/shared_examples/events/validates_class_and_social.rb @@ -1,35 +1,33 @@ -# frozen_string_literal: true - -RSpec.shared_examples "validates class and social" do +RSpec.shared_examples "validates class and social" do |model_name| it "is invalid if it has neither a class nor a social nor a taster" do - expect(build(:event, has_taster: false, has_social: false, has_class: false)).not_to be_valid + expect(build(model_name, has_taster: false, has_social: false, has_class: false)).not_to be_valid end it "is invalid if it has a taster but no class or social" do - expect(build(:event, has_taster: true, has_social: false, has_class: false)).not_to be_valid + expect(build(model_name, has_taster: true, has_social: false, has_class: false)).not_to be_valid end it "is valid if it has a class but no taster or social (and everything else is OK)" do - expect(build(:event, has_taster: false, has_social: false, has_class: true, class_organiser_id: 7)).to be_valid + expect(build(model_name, has_taster: false, has_social: false, has_class: true, class_organiser_id: 7)).to be_valid end it "is valid if it has a social but no taster or class (and everything else is OK)" do - expect(build(:event, has_taster: false, has_social: true, has_class: false)).to be_valid + expect(build(model_name, has_taster: false, has_social: true, has_class: false)).to be_valid end it "is valid if it's a class without a title" do - expect(build(:event, has_taster: false, has_social: false, has_class: true, title: nil, class_organiser_id: 7)).to be_valid + expect(build(model_name, has_taster: false, has_social: false, has_class: true, title: nil, class_organiser_id: 7)).to be_valid end it "is invalid if it's a social without a title" do - event = build(:event, has_taster: false, has_social: true, has_class: false, title: nil) - event.valid? - expect(event.errors.messages).to eq(title: ["must be present for social dances"]) + model = build(model_name, has_taster: false, has_social: true, has_class: false, title: nil) + model.valid? + expect(model.errors.messages).to eq(title: ["must be present for social dances"]) end it "is invalid if it has a class and doesn't have a class organiser" do - event = build(:event, has_taster: false, has_social: false, has_class: true, class_organiser: nil) - event.valid? - expect(event.errors.messages).to eq(class_organiser_id: ["must be present for classes"]) + model = build(model_name, has_taster: false, has_social: false, has_class: true, class_organiser_id: nil) + model.valid? + expect(model.errors.messages).to eq(class_organiser_id: ["must be present for classes"]) end end diff --git a/spec/support/shared_examples/events/validates_course_length.rb b/spec/support/shared_examples/events/validates_course_length.rb index 9e6159bf..ff301c88 100644 --- a/spec/support/shared_examples/events/validates_course_length.rb +++ b/spec/support/shared_examples/events/validates_course_length.rb @@ -1,33 +1,33 @@ # frozen_string_literal: true -RSpec.shared_examples "validates course length" do +RSpec.shared_examples "validates course length" do |model_name| it "is valid if blank" do - event = build(:event, course_length: nil) + model = build(model_name, course_length: nil) - expect(event).to be_valid + expect(model).to be_valid end it "is valid if 1" do - event = build(:event, course_length: nil) + model = build(model_name, course_length: nil) - expect(event).to be_valid + expect(model).to be_valid end it "is invalid if 0" do - event = build(:event, course_length: 0) - event.valid? - expect(event.errors.messages).to eq(course_length: ["must be greater than 0"]) + model = build(model_name, course_length: 0) + model.valid? + expect(model.errors.messages).to eq(course_length: ["must be greater than 0"]) end it "is invalid if negative" do - event = build(:event, course_length: -1) - event.valid? - expect(event.errors.messages).to eq(course_length: ["must be greater than 0"]) + model = build(model_name, course_length: -1) + model.valid? + expect(model.errors.messages).to eq(course_length: ["must be greater than 0"]) end it "is invalid if non-integer" do - event = build(:event, course_length: 2.5) - event.valid? - expect(event.errors.messages).to eq(course_length: ["must be an integer"]) + model = build(model_name, course_length: 2.5) + model.valid? + expect(model.errors.messages).to eq(course_length: ["must be an integer"]) end end diff --git a/spec/support/shared_examples/events/validates_weekly.rb b/spec/support/shared_examples/events/validates_weekly.rb index a5866e5f..af698638 100644 --- a/spec/support/shared_examples/events/validates_weekly.rb +++ b/spec/support/shared_examples/events/validates_weekly.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true -RSpec.shared_examples "validates weekly" do +RSpec.shared_examples "validates weekly" do |model_name| it "is invalid if it's weekly and has no day" do - event = build(:event, frequency: 1, day: nil) - event.valid? - expect(event.errors.messages).to eq(day: ["must be present for weekly events"]) + model = build(model_name, frequency: 1, day: nil) + model.valid? + expect(model.errors.messages).to eq(day: ["must be present for weekly events"]) end it "is valid if it's occasional and has no day" do - expect(build(:event, frequency: 0, day: nil)).to be_valid + expect(build(model_name, frequency: 0, day: nil)).to be_valid end end diff --git a/spec/system/admins_can_archive_events_spec.rb b/spec/system/admins_can_archive_events_spec.rb index 31b6e675..f33632d0 100644 --- a/spec/system/admins_can_archive_events_spec.rb +++ b/spec/system/admins_can_archive_events_spec.rb @@ -21,7 +21,7 @@ it "with an occasional event" do skip_login - create(:event, frequency: 0, date_array: "02/01/2000") + create(:event, frequency: 0, dates: ["02/01/2000".to_date]) visit "/events" diff --git a/spec/system/admins_can_create_events_spec.rb b/spec/system/admins_can_create_events_spec.rb index 12c8705f..293c0658 100644 --- a/spec/system/admins_can_create_events_spec.rb +++ b/spec/system/admins_can_create_events_spec.rb @@ -62,7 +62,7 @@ click_on "Create" expect(page).to have_content("5 errors prevented this record from being saved") - .and have_content("Venue must exist") + .and have_content("Venue can't be blank") .and have_content("Url can't be blank") .and have_content("Event type can't be blank") .and have_content("Frequency can't be blank") @@ -148,7 +148,7 @@ click_on "Create" expect(page).to have_content("5 errors prevented this record from being saved") - .and have_content("Venue must exist") + .and have_content("Venue can't be blank") .and have_content("Url can't be blank") .and have_content("Event type can't be blank") .and have_content("Frequency can't be blank") diff --git a/spec/system/organisers_can_edit_events_spec.rb b/spec/system/organisers_can_edit_events_spec.rb index 510b32e5..f4c52199 100644 --- a/spec/system/organisers_can_edit_events_spec.rb +++ b/spec/system/organisers_can_edit_events_spec.rb @@ -27,6 +27,8 @@ fill_in "Last date", with: "12/01/2013" click_on "Update" + expect(page).to have_content("Event was successfully updated") + aggregate_failures do expect(page).to have_select("Venue", selected: "The 100 Club - central") expect(page).to have_field("Upcoming dates", with: "12/12/2012,12/01/2013") @@ -62,6 +64,8 @@ fill_in "Last date", with: "12/01/2013" click_on "Update" + expect(page).to have_content("Event was successfully updated") + aggregate_failures do expect(page).to have_select("Venue", selected: "The 100 Club - central") expect(page).not_to have_content("Upcoming dates")