diff --git a/app/decorators/proposal_decorator.rb b/app/decorators/proposal_decorator.rb index ade0fa31e..76e792cd0 100644 --- a/app/decorators/proposal_decorator.rb +++ b/app/decorators/proposal_decorator.rb @@ -1,5 +1,4 @@ class ProposalDecorator < Draper::Decorator - include Proposal::State decorates :proposal delegate_all decorates_association :speakers @@ -8,7 +7,7 @@ def speaker_state(small: false) speaker_state = if object.awaiting_confirmation? 'Waiting for speaker confirmation' elsif state.include?('soft') - SUBMITTED + Proposal.states[:submitted] else state end @@ -18,7 +17,7 @@ def speaker_state(small: false) def reviewer_state(small: false) reviewer_state = if state.include?('soft') - SUBMITTED + Proposal.states[:submitted] else state end @@ -27,11 +26,10 @@ def reviewer_state(small: false) end def state - current_state = object.state - if current_state == REJECTED - NOT_ACCEPTED + if object.rejected? + Proposal.states[:not_accepted] else - current_state + Proposal.states[object.state.to_sym] end end @@ -125,21 +123,13 @@ def speaker def state_class(state) case state - when NOT_ACCEPTED - if h.current_user.reviewer_for_event?(object.event) - 'label-danger' - else - 'label-info' - end - when SOFT_REJECTED + when Proposal.states[:not_accepted] + h.current_user.reviewer_for_event?(object.event) ? 'label-danger' : 'label-info' + when Proposal.states[:soft_rejected] 'label-danger' - when SOFT_WAITLISTED + when Proposal.states[:soft_waitlisted], Proposal.states[:withdrawn] 'label-warning' - when WITHDRAWN - 'label-warning' - when ACCEPTED - 'label-success' - when SOFT_ACCEPTED + when Proposal.states[:accepted], Proposal.states[:soft_accepted] 'label-success' else 'label-default' diff --git a/app/decorators/staff/proposal_decorator.rb b/app/decorators/staff/proposal_decorator.rb index afc7969b3..ac7c5694b 100644 --- a/app/decorators/staff/proposal_decorator.rb +++ b/app/decorators/staff/proposal_decorator.rb @@ -28,7 +28,7 @@ def state_buttons(states: nil, show_finalize: true, show_hard_reset: false, smal def small_state_buttons state_buttons( - states: [ SOFT_ACCEPTED, SOFT_WAITLISTED, SOFT_REJECTED, SUBMITTED ], + states: [:soft_accepted, :soft_waitlisted, :soft_rejected, :submitted], show_finalize: false, small: true ) @@ -103,13 +103,13 @@ def finalize_state_button end def reset_state_button - state_button('Reset Status', update_state_path(SUBMITTED), + state_button('Reset Status', update_state_path(:submitted), type: 'btn-default', hidden: reset_button_hidden?) end def hard_reset_button - state_button('Hard Reset', update_state_path(SUBMITTED), + state_button('Hard Reset', update_state_path(:submitted), data: { turbo_confirm: "This proposal's status has been finalized. Proceed with status reset?" @@ -125,9 +125,9 @@ def update_state_path(state) def buttons [ - [ 'Accept', SOFT_ACCEPTED, 'btn-success', !object.draft? ], - [ 'Waitlist', SOFT_WAITLISTED, 'btn-warning', !object.draft? ], - [ 'Reject', SOFT_REJECTED, 'btn-danger', !object.draft? ] + ['Accept', :soft_accepted, 'btn-success', !object.draft?], + ['Waitlist', :soft_waitlisted, 'btn-warning', !object.draft?], + ['Reject', :soft_rejected, 'btn-danger', !object.draft?] ] end diff --git a/app/mailers/staff/proposal_mailer.rb b/app/mailers/staff/proposal_mailer.rb index 8c6f02b00..9530772a5 100644 --- a/app/mailers/staff/proposal_mailer.rb +++ b/app/mailers/staff/proposal_mailer.rb @@ -4,13 +4,12 @@ class Staff::ProposalMailer < ApplicationMailer attr_accessor :test_mode def send_email(proposal) - case proposal.state - when Proposal::State::ACCEPTED - accept_email(proposal.event, proposal) - when Proposal::State::REJECTED - reject_email(proposal.event, proposal) - when Proposal::State::WAITLISTED - waitlist_email(proposal.event, proposal) + if proposal.accepted? + accept_email(proposal.event, proposal) + elsif proposal.rejected? + reject_email(proposal.event, proposal) + elsif proposal.waitlisted? + waitlist_email(proposal.event, proposal) end end @@ -29,7 +28,7 @@ def accept_email(event, proposal) @proposal = proposal.decorate @event = event @template_name = 'accept_email' - subject = subject_for(proposal: @proposal, type: Proposal::State::ACCEPTED) + subject = subject_for(proposal: @proposal, type: :accepted) mail_to_speakers(event, proposal, subject) end @@ -37,7 +36,7 @@ def reject_email(event, proposal) @proposal = proposal @event = event @template_name = 'reject_email' - subject = subject_for(proposal: @proposal, type: Proposal::State::REJECTED) + subject = subject_for(proposal: @proposal, type: :rejected) mail_to_speakers(event, proposal, subject) end @@ -45,7 +44,7 @@ def waitlist_email(event, proposal) @proposal = proposal.decorate @event = event @template_name = 'waitlist_email' - subject = subject_for(proposal: proposal, type: Proposal::State::WAITLISTED) + subject = subject_for(proposal: proposal, type: :waitlisted) mail_to_speakers(event, proposal, subject) end diff --git a/app/models/concerns/finalization_messages.rb b/app/models/concerns/finalization_messages.rb index 558d40a96..c68136d6c 100644 --- a/app/models/concerns/finalization_messages.rb +++ b/app/models/concerns/finalization_messages.rb @@ -2,10 +2,10 @@ module FinalizationMessages MESSAGES = { - Proposal::State::ACCEPTED => ->(event_name) { "Your proposal for #{event_name} has been accepted" }, - Proposal::State::REJECTED => ->(event_name) { "Your proposal for #{event_name} has not been accepted" }, - Proposal::State::WAITLISTED => ->(event_name) { "Your proposal for #{event_name} has been added to the waitlist" } - }.freeze + accepted: ->(event_name) { "Your proposal for #{event_name} has been accepted" }, + rejected: ->(event_name) { "Your proposal for #{event_name} has not been accepted" }, + waitlisted: ->(event_name) { "Your proposal for #{event_name} has been added to the waitlist" } + }.with_indifferent_access.freeze def subject_for(proposal:, type: proposal.state) default_builder = ->(_) { 'Invalid final proposal type' } diff --git a/app/models/event_stats.rb b/app/models/event_stats.rb index 2cea45f47..b3fce7018 100644 --- a/app/models/event_stats.rb +++ b/app/models/event_stats.rb @@ -31,13 +31,13 @@ def user_ratable_proposals(user, include_withdrawn=false) end def all_accepted_proposals(track_id='all') - q = event.proposals.where(state: [Proposal::ACCEPTED, Proposal::SOFT_ACCEPTED]) + q = event.proposals.where(state: [:accepted, :soft_accepted]) q = filter_by_track(q, track_id) q.size + active_custom_sessions(track_id) end def all_waitlisted_proposals(track_id='all') - q = event.proposals.where(state: [Proposal::WAITLISTED, Proposal::SOFT_WAITLISTED]) + q = event.proposals.where(state: [:waitlisted, :soft_waitlisted]) q = filter_by_track(q, track_id) q.size end @@ -78,18 +78,18 @@ def program proposals_per_track_and_state = event.proposals.left_joins(:track).group('tracks.name', :state).count stats = {'Total' => { - accepted: proposals_per_track_and_state.select {|k, _v| k[1] == Proposal::State::ACCEPTED }.sum(&:second) || 0, - soft_accepted: proposals_per_track_and_state.select {|k, _v| k[1] == Proposal::State::SOFT_ACCEPTED }.sum(&:second) || 0, - waitlisted: proposals_per_track_and_state.select {|k, _v| k[1] == Proposal::State::WAITLISTED }.sum(&:second) || 0, - soft_waitlisted: proposals_per_track_and_state.select {|k, _v| k[1] == Proposal::State::SOFT_WAITLISTED }.sum(&:second) || 0 + accepted: proposals_per_track_and_state.select {|k, _v| k[1] == 'accepted' }.sum(&:second) || 0, + soft_accepted: proposals_per_track_and_state.select {|k, _v| k[1] == 'soft_accepted' }.sum(&:second) || 0, + waitlisted: proposals_per_track_and_state.select {|k, _v| k[1] == 'waitlisted' }.sum(&:second) || 0, + soft_waitlisted: proposals_per_track_and_state.select {|k, _v| k[1] == 'soft_waitlisted' }.sum(&:second) || 0 }} # Prepending `nil` for "General" track event.tracks.pluck(:name).prepend(nil).each do |track_name| stats[track_name || Track::NO_TRACK] = { - accepted: proposals_per_track_and_state[[track_name, Proposal::State::ACCEPTED]] || 0, - soft_accepted: proposals_per_track_and_state[[track_name, Proposal::State::SOFT_ACCEPTED]] || 0, - waitlisted: proposals_per_track_and_state[[track_name, Proposal::State::WAITLISTED]] || 0, - soft_waitlisted: proposals_per_track_and_state[[track_name, Proposal::State::SOFT_WAITLISTED]] || 0 + accepted: proposals_per_track_and_state[[track_name, 'accepted']] || 0, + soft_accepted: proposals_per_track_and_state[[track_name, 'soft_accepted']] || 0, + waitlisted: proposals_per_track_and_state[[track_name, 'waitlisted']] || 0, + soft_waitlisted: proposals_per_track_and_state[[track_name, 'soft_waitlisted']] || 0 } end stats diff --git a/app/models/proposal.rb b/app/models/proposal.rb index 7d019b900..9e5af7e72 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -20,9 +20,7 @@ class Proposal < ApplicationRecord validates :title, :abstract, :session_format, presence: true validate :abstract_length validates :title, length: { maximum: 60 } - validates_inclusion_of :state, in: valid_states, allow_nil: true, message: "'%{value}' not a valid state." - validates_inclusion_of :state, in: FINAL_STATES, allow_nil: false, message: "'%{value}' not a confirmable state.", - if: :confirmed_at_changed? + validate :state_must_be_final_for_confirmation, if: :confirmed_at_changed? serialize :last_change, coder: YAML serialize :proposal_data, type: Hash, coder: YAML @@ -39,20 +37,12 @@ class Proposal < ApplicationRecord before_update :save_attr_history after_save :save_tags, :save_review_tags - scope :accepted, -> { where(state: ACCEPTED) } - scope :waitlisted, -> { where(state: WAITLISTED) } - scope :submitted, -> { where(state: SUBMITTED) } scope :confirmed, -> { where.not(confirmed_at: nil) } - - scope :soft_accepted, -> { where(state: SOFT_ACCEPTED) } - scope :soft_waitlisted, -> { where(state: SOFT_WAITLISTED) } - scope :soft_rejected, -> { where(state: SOFT_REJECTED) } scope :soft_states, -> { where(state: SOFT_STATES) } - scope :working_program, -> { where(state: [SOFT_ACCEPTED, SOFT_WAITLISTED, ACCEPTED, WAITLISTED]) } + scope :working_program, -> { where(state: [:soft_accepted, :soft_waitlisted, :accepted, :waitlisted]) } scope :unrated, -> { where.not(id: Rating.select(:proposal_id)) } scope :rated, -> { where(id: Rating.select(:proposal_id)) } - scope :not_withdrawn, -> { where.not(state: WITHDRAWN) } scope :not_owned_by, ->(user) { where.not(id: user.proposals) } scope :for_state, lambda { |state| where(state: state).order(:title).includes(:event, { speakers: :user }, :review_taggings) @@ -131,7 +121,7 @@ def finalize end def withdraw - update(state: WITHDRAWN) + withdrawn! reviewers.each do |reviewer| Notification.create_for(reviewer, proposal: self, message: "Proposal, #{title}, withdrawn") @@ -144,24 +134,20 @@ def confirm end def promote - update(state: ACCEPTED) if state == WAITLISTED + accepted! if waitlisted? end def decline - update(state: WITHDRAWN, confirmed_at: Time.current) + update(state: :withdrawn, confirmed_at: Time.current) program_session.update(state: :declined) end - def draft? - state == SUBMITTED - end - def finalized? - FINAL_STATES.include?(state) + FINAL_STATES.include?(state.to_sym) end def becomes_program_session? - BECOMES_PROGRAM_SESSION.include?(state) + BECOMES_PROGRAM_SESSION.include?(state.to_sym) end def confirmed? @@ -258,6 +244,10 @@ def changeset_fields private + def state_must_be_final_for_confirmation + errors.add(:state, "'#{state}' not a confirmable state.") unless FINAL_STATES.include?(state.to_sym) + end + def abstract_length return unless abstract_changed? && abstract.gsub(/\r/, '').gsub(/\n/, '').length > 600 diff --git a/app/models/proposal/state.rb b/app/models/proposal/state.rb index 9806edc3f..b67aa0f12 100644 --- a/app/models/proposal/state.rb +++ b/app/models/proposal/state.rb @@ -1,49 +1,34 @@ module Proposal::State extend ActiveSupport::Concern - # TODO: Currently a defect exists in the rake db:migrate task that is - # causing our files to be loaded more than once. Because our files are being - # loaded more than once, we are receiving errors stating that these - # constants have already been defined. Therefore, until this defect is - # fixed, we need to check to ensure that the constants are not already - # defined prior to defining them. - unless const_defined?(:ACCEPTED) - SOFT_ACCEPTED = 'soft accepted' - SOFT_WAITLISTED = 'soft waitlisted' - SOFT_REJECTED = 'soft rejected' + SOFT_STATES = [:soft_accepted, :soft_waitlisted, :soft_rejected, :submitted].freeze + FINAL_STATES = [:accepted, :waitlisted, :rejected, :withdrawn, :not_accepted].freeze - ACCEPTED = 'accepted' - WAITLISTED = 'waitlisted' - REJECTED = 'rejected' - WITHDRAWN = 'withdrawn' - NOT_ACCEPTED = 'not accepted' - SUBMITTED = 'submitted' + SOFT_TO_FINAL = { + soft_accepted: :accepted, + soft_rejected: :rejected, + soft_waitlisted: :waitlisted, + submitted: :rejected + }.with_indifferent_access.freeze - SOFT_STATES = [ SOFT_ACCEPTED, SOFT_WAITLISTED, SOFT_REJECTED, SUBMITTED ] - FINAL_STATES = [ ACCEPTED, WAITLISTED, REJECTED, WITHDRAWN, NOT_ACCEPTED ] - - SOFT_TO_FINAL = { - SOFT_ACCEPTED => ACCEPTED, - SOFT_REJECTED => REJECTED, - SOFT_WAITLISTED => WAITLISTED, - SUBMITTED => REJECTED - } - - BECOMES_PROGRAM_SESSION = [ ACCEPTED, WAITLISTED ] - end + BECOMES_PROGRAM_SESSION = [:accepted, :waitlisted].freeze included do - def self.valid_states - @valid_states ||= Proposal::State.constants.map{|c| const_get(c) if const_get(c).is_a?(String)}.compact! - end + enum :state, { + submitted: 'submitted', + soft_accepted: 'soft accepted', + soft_waitlisted: 'soft waitlisted', + soft_rejected: 'soft rejected', + accepted: 'accepted', + waitlisted: 'waitlisted', + rejected: 'rejected', + withdrawn: 'withdrawn', + not_accepted: 'not accepted' + }, default: :submitted - # Create all state accessor methods like (accepted?, waitlisted?, etc...) - Proposal::State.constants.each do |constant| - next unless const_get(constant).is_a?(String) - method_name = constant.to_s.downcase + '?' - define_method(method_name) do - Proposal::State.const_get(constant) == self.state - end + # draft? is an alias for submitted? + def draft? + submitted? end end end diff --git a/app/models/rating.rb b/app/models/rating.rb index b6da53da4..798505489 100644 --- a/app/models/rating.rb +++ b/app/models/rating.rb @@ -3,7 +3,7 @@ class Rating < ApplicationRecord belongs_to :user scope :for_event, -> (event) { joins(:proposal).where("proposals.event_id = ?", event.id) } - scope :not_withdrawn, -> { joins(:proposal).where("proposals.state != ?", Proposal::State::WITHDRAWN) } + scope :not_withdrawn, -> { joins(:proposal).where.not(proposals: {state: :withdrawn}) } def teammate user.teammates.where(event: proposal.event).first diff --git a/app/models/speaker_email_template.rb b/app/models/speaker_email_template.rb index 22622eda0..3fd307045 100644 --- a/app/models/speaker_email_template.rb +++ b/app/models/speaker_email_template.rb @@ -8,9 +8,9 @@ class SpeakerEmailTemplate }.with_indifferent_access TYPES_TO_STATES = { - accept: Proposal::ACCEPTED, - waitlist: Proposal::WAITLISTED, - reject: Proposal::REJECTED + accept: :accepted, + waitlist: :waitlisted, + reject: :rejected }.with_indifferent_access attr_accessor :email, :type_key diff --git a/app/views/staff/proposals/bulk_finalize.html.haml b/app/views/staff/proposals/bulk_finalize.html.haml index 48f4311b2..426112d46 100644 --- a/app/views/staff/proposals/bulk_finalize.html.haml +++ b/app/views/staff/proposals/bulk_finalize.html.haml @@ -24,7 +24,7 @@ %tbody - @remaining_by_state.each do |proposals| %tr{data: {state: proposals.first.gsub(/\s+/, "-")}} - %td.col-sm-9= "#{proposals.last.count} #{proposals.first} proposal".pluralize(proposals.last.count) + %td.col-sm-9= "#{proposals.last.count} #{proposals.first.humanize.downcase} proposal".pluralize(proposals.last.count) %td.col-sm-3.text-center = link_to "Finalize", finalize_by_state_event_staff_program_proposals_path(event, proposals_state: proposals.first), data: {turbo: true, turbo_method: :post, turbo_confirm: "This will finalize #{proposals.last.count} proposal".pluralize(proposals.last.count) + " in the #{proposals.first} state. Proceed?"}, diff --git a/spec/controllers/proposals_controller_spec.rb b/spec/controllers/proposals_controller_spec.rb index 49800f1ee..a439af755 100644 --- a/spec/controllers/proposals_controller_spec.rb +++ b/spec/controllers/proposals_controller_spec.rb @@ -68,7 +68,7 @@ describe "POST #confirm" do it "confirms a proposal" do - proposal = create(:proposal_with_track, state: Proposal::ACCEPTED, confirmed_at: nil) + proposal = create(:proposal_with_track, state: :accepted, confirmed_at: nil) ProgramSession.create_from_proposal(proposal) allow_any_instance_of(ProposalsController).to receive(:current_user) { create(:speaker) } allow(controller).to receive(:require_speaker).and_return(nil) @@ -115,7 +115,7 @@ end describe 'POST #decline' do - let!(:proposal) { create(:proposal_with_track, state: Proposal::ACCEPTED, confirmed_at: nil) } + let!(:proposal) { create(:proposal_with_track, state: :accepted, confirmed_at: nil) } before { ProgramSession.create_from_proposal(proposal) } before { allow_any_instance_of(ProposalsController).to receive(:current_user) { create(:speaker) } } before { allow(controller).to receive(:require_speaker).and_return(nil) } diff --git a/spec/controllers/staff/proposals_controller_spec.rb b/spec/controllers/staff/proposals_controller_spec.rb index c6994d33d..24d18aad8 100644 --- a/spec/controllers/staff/proposals_controller_spec.rb +++ b/spec/controllers/staff/proposals_controller_spec.rb @@ -65,26 +65,26 @@ end it "finalizes the state" do - proposal = create(:proposal_with_track, event: event, state: Proposal::State::SOFT_ACCEPTED) + proposal = create(:proposal_with_track, event: event, state: :soft_accepted) post :finalize, params: {event_slug: event, proposal_uuid: proposal.uuid} - expect(proposal.reload.state).to eq(Proposal::State::ACCEPTED) + expect(proposal.reload).to be_accepted end it "creates a draft program session" do - proposal = create(:proposal_with_track, event: event, state: Proposal::State::SOFT_ACCEPTED) + proposal = create(:proposal_with_track, event: event, state: :soft_accepted) post :finalize, params: {event_slug: event, proposal_uuid: proposal.uuid} expect(proposal.program_session).to be_unconfirmed_accepted end it "sends appropriate emails" do - proposal = create(:proposal_with_track, event: event, state: Proposal::State::SOFT_ACCEPTED) + proposal = create(:proposal_with_track, event: event, state: :soft_accepted) mail = double(:mail, deliver_now: nil) expect(Staff::ProposalMailer).to receive('send_email').and_return(mail) post :finalize, params: {event_slug: event, proposal_uuid: proposal.uuid} end it "creates a notification" do - proposal = create(:proposal_with_track, :with_two_speakers, event: event, state: Proposal::State::SOFT_ACCEPTED) + proposal = create(:proposal_with_track, :with_two_speakers, event: event, state: :soft_accepted) expect { post :finalize, params: {event_slug: event, proposal_uuid: proposal.uuid} }.to change { diff --git a/spec/decorators/proposal_decorator_spec.rb b/spec/decorators/proposal_decorator_spec.rb index d2872ac72..d9cbcefb3 100644 --- a/spec/decorators/proposal_decorator_spec.rb +++ b/spec/decorators/proposal_decorator_spec.rb @@ -25,24 +25,16 @@ describe "#state" do it "returns 'not accepted' for a rejected state" do - proposal = create(:proposal_with_track, state: ProposalDecorator::REJECTED) - expect(proposal.decorate.state).to eq(ProposalDecorator::NOT_ACCEPTED) + proposal = create(:proposal_with_track, state: :rejected) + expect(proposal.decorate.state).to eq(Proposal.states[:not_accepted]) end it "returns the current state for non-rejected states" do - states = [ - ProposalDecorator::ACCEPTED, - ProposalDecorator::WAITLISTED, - ProposalDecorator::WITHDRAWN, - ProposalDecorator::SUBMITTED, - ProposalDecorator::SOFT_ACCEPTED, - ProposalDecorator::SOFT_WAITLISTED, - ProposalDecorator::SOFT_REJECTED - ] + states = [:accepted, :waitlisted, :withdrawn, :submitted, :soft_accepted, :soft_waitlisted, :soft_rejected] states.each do |state| proposal = create(:proposal_with_track, state: state) - expect(proposal.decorate.state).to eq(state) + expect(proposal.decorate.state).to eq(Proposal.states[state]) end end end diff --git a/spec/factories/program_sessions.rb b/spec/factories/program_sessions.rb index cf806928c..24326c2d3 100644 --- a/spec/factories/program_sessions.rb +++ b/spec/factories/program_sessions.rb @@ -7,7 +7,7 @@ event factory :program_session_with_proposal do - proposal { create(:proposal_with_track, state: Proposal::ACCEPTED, event: event) } + proposal { create(:proposal_with_track, state: :accepted, event: event) } track { proposal.track } trait :with_speaker do diff --git a/spec/mailers/staff/proposal_mailer_spec.rb b/spec/mailers/staff/proposal_mailer_spec.rb index 894bb9230..db1d271cd 100644 --- a/spec/mailers/staff/proposal_mailer_spec.rb +++ b/spec/mailers/staff/proposal_mailer_spec.rb @@ -88,15 +88,15 @@ describe "send_email" do it "selects the appropriate template to use based on proposal state" do - proposal.state = Proposal::ACCEPTED + proposal.state = :accepted Staff::ProposalMailer.send_email(proposal).deliver_now expect(ActionMailer::Base.deliveries.last.subject).to eq("Your proposal for #{event} has been accepted") - proposal.state = Proposal::REJECTED + proposal.state = :rejected Staff::ProposalMailer.send_email(proposal).deliver_now expect(ActionMailer::Base.deliveries.last.subject).to eq("Your proposal for #{event} has not been accepted") - proposal.state = Proposal::WAITLISTED + proposal.state = :waitlisted Staff::ProposalMailer.send_email(proposal).deliver_now expect(ActionMailer::Base.deliveries.last.subject).to eq("Your proposal for #{event} has been added to the waitlist") end diff --git a/spec/models/finalization_notifier_spec.rb b/spec/models/finalization_notifier_spec.rb index 40d3a658a..eceb20c04 100644 --- a/spec/models/finalization_notifier_spec.rb +++ b/spec/models/finalization_notifier_spec.rb @@ -8,7 +8,7 @@ describe '.notify' do let(:user) { create(:user) } let(:event) { create(:event) } - let(:proposal) { create(:proposal_with_track, :with_two_speakers, event: event, state: Proposal::State::ACCEPTED) } + let(:proposal) { create(:proposal_with_track, :with_two_speakers, event: event, state: :accepted) } it 'calls Staff::ProposalMailer.send_email' do allow(Staff::ProposalMailer).to receive_message_chain('send_email.delivier_now') diff --git a/spec/models/proposal_spec.rb b/spec/models/proposal_spec.rb index 49344008d..55b410689 100644 --- a/spec/models/proposal_spec.rb +++ b/spec/models/proposal_spec.rb @@ -46,10 +46,10 @@ describe "state methods" do let(:state_method_map) do { - Proposal::SUBMITTED => :draft?, - Proposal::WITHDRAWN => :withdrawn?, - Proposal::ACCEPTED => :accepted?, - Proposal::WAITLISTED => :waitlisted? + submitted: :draft?, + withdrawn: :withdrawn?, + accepted: :accepted?, + waitlisted: :waitlisted? } end @@ -64,8 +64,7 @@ state_method_map.each do |state, method| diff_state = state while diff_state == state - # Get a random state - diff_state = Proposal::State.const_get(Proposal::State.constants.sample) + diff_state = Proposal.states.keys.sample.to_sym end proposal = create(:proposal_with_track, state: state) @@ -76,7 +75,7 @@ describe "#confirmed?" do it "returns true if proposal has been confirmed" do - proposal = create(:proposal_with_track, state: Proposal::ACCEPTED, confirmed_at: Time.current) + proposal = create(:proposal_with_track, state: :accepted, confirmed_at: Time.current) expect(proposal).to be_confirmed end @@ -88,7 +87,7 @@ describe "#confirm" do it "confirms the proposal" do - proposal = create(:proposal_with_track, state: Proposal::ACCEPTED) + proposal = create(:proposal_with_track, state: :accepted) proposal.confirm @@ -96,10 +95,10 @@ end it "updates the state of it's program session" do - create(:proposal_with_track, state: Proposal::WAITLISTED, confirmed_at: Time.current) - create(:proposal_with_track, state: Proposal::WAITLISTED) - create(:proposal_with_track, state: Proposal::ACCEPTED) - create(:proposal_with_track, state: Proposal::ACCEPTED, confirmed_at: Time.current) + create(:proposal_with_track, state: :waitlisted, confirmed_at: Time.current) + create(:proposal_with_track, state: :waitlisted) + create(:proposal_with_track, state: :accepted) + create(:proposal_with_track, state: :accepted, confirmed_at: Time.current) Proposal.all.each do |prop| create(:program_session, proposal: prop, track: prop.track) @@ -111,23 +110,23 @@ describe "#promote" do it "promotes from waitlisted to accepted" do - waitlisted = create(:proposal_with_track, state: Proposal::WAITLISTED) + waitlisted = create(:proposal_with_track, state: :waitlisted) waitlisted.promote - expect(waitlisted.reload.state).to eq("accepted") + expect(waitlisted.reload).to be_accepted end it "doesn't promote from other states" do event, track = create(:event), create(:track) - create(:proposal_with_track, state: Proposal::ACCEPTED, event: event, track: track) - create(:proposal_with_track, state: Proposal::REJECTED, event: event, track: track) - create(:proposal_with_track, state: Proposal::WITHDRAWN, event: event, track: track) - create(:proposal_with_track, state: Proposal::NOT_ACCEPTED, event: event, track: track) - create(:proposal_with_track, state: Proposal::SUBMITTED, event: event, track: track) - create(:proposal_with_track, state: Proposal::SOFT_ACCEPTED, event: event, track: track) - create(:proposal_with_track, state: Proposal::SOFT_WAITLISTED, event: event, track: track) - create(:proposal_with_track, state: Proposal::SOFT_REJECTED, event: event, track: track) + create(:proposal_with_track, state: :accepted, event: event, track: track) + create(:proposal_with_track, state: :rejected, event: event, track: track) + create(:proposal_with_track, state: :withdrawn, event: event, track: track) + create(:proposal_with_track, state: :not_accepted, event: event, track: track) + create(:proposal_with_track, state: :submitted, event: event, track: track) + create(:proposal_with_track, state: :soft_accepted, event: event, track: track) + create(:proposal_with_track, state: :soft_waitlisted, event: event, track: track) + create(:proposal_with_track, state: :soft_rejected, event: event, track: track) Proposal.all.each do |prop| expect{ prop.promote }.not_to change(prop, :state) @@ -138,18 +137,14 @@ describe "state changing" do describe "#finalized?" do it "returns false for all soft states" do - soft_states = [ Proposal::SOFT_ACCEPTED, Proposal::SOFT_WAITLISTED, Proposal::SOFT_REJECTED, Proposal::SUBMITTED ] - - soft_states.each do |state| + Proposal::SOFT_STATES.each do |state| proposal = create(:proposal_with_track, state: state) expect(proposal).to_not be_finalized end end it "returns true for all finalized states" do - finalized_states = Proposal::FINAL_STATES - - finalized_states.each do |state| + Proposal::FINAL_STATES.each do |state| proposal = create(:proposal_with_track, state: state) expect(proposal).to be_finalized end @@ -157,19 +152,15 @@ end describe "#becomes_program_session?" do - it "returns true for WAITLISTED and ACCEPTED" do - states = [ Proposal::ACCEPTED, Proposal::WAITLISTED ] - - states.each do |state| + it "returns true for waitlisted and accepted" do + [:accepted, :waitlisted].each do |state| proposal = create(:proposal_with_track, state: state) expect(proposal).to be_becomes_program_session end end - it "returns false for SUBMITTED and REJECTED" do - states = [ Proposal::SUBMITTED, Proposal::REJECTED ] - - states.each do |state| + it "returns false for submitted and rejected" do + [:submitted, :rejected].each do |state| proposal = create(:proposal_with_track, state: state) expect(proposal).to_not be_becomes_program_session end @@ -181,21 +172,21 @@ Proposal::SOFT_TO_FINAL.each do |key, val| proposal = create(:proposal_with_track, state: key) proposal.finalize - expect(proposal.state).to eq(val) + expect(proposal.state.to_sym).to eq(val) end end - it "changes a SUBMITTED proposal to REJECTED" do - proposal = create(:proposal_with_track, state: Proposal::SUBMITTED) + it "changes a submitted proposal to rejected" do + proposal = create(:proposal_with_track, state: :submitted) expect(proposal.finalize).to be_truthy - expect(proposal.reload.state).to eq(Proposal::REJECTED) + expect(proposal.reload).to be_rejected end - it "creates a draft program session for WAITLISTED and ACCEPTED proposals, but not for REJECTED or SUBMITTED" do - waitlisted_proposal = create(:proposal_with_track, state: Proposal::SOFT_WAITLISTED) - accepted_proposal = create(:proposal_with_track, state: Proposal::SOFT_ACCEPTED) - rejected_proposal = create(:proposal_with_track, state: Proposal::SOFT_REJECTED) - submitted_proposal = create(:proposal_with_track, state: Proposal::SUBMITTED) + it "creates a draft program session for waitlisted and accepted proposals, but not for rejected or submitted" do + waitlisted_proposal = create(:proposal_with_track, state: :soft_waitlisted) + accepted_proposal = create(:proposal_with_track, state: :soft_accepted) + rejected_proposal = create(:proposal_with_track, state: :soft_rejected) + submitted_proposal = create(:proposal_with_track, state: :submitted) Proposal.all.each do |prop| prop.finalize @@ -210,15 +201,14 @@ describe "#update_state" do it "updates the state" do - proposal = create(:proposal_with_track, state: Proposal::ACCEPTED) - proposal.update_state(Proposal::WAITLISTED) - expect(proposal.state).to eq(Proposal::WAITLISTED) + proposal = create(:proposal_with_track, state: :accepted) + proposal.update_state(:waitlisted) + expect(proposal).to be_waitlisted end it "rejects invalid states" do - proposal = create(:proposal_with_track, state: Proposal::ACCEPTED) - proposal.update_state('almonds!') - expect(proposal.errors.messages[:state][0]).to eq("'almonds!' not a valid state.") + proposal = create(:proposal_with_track, state: :accepted) + expect { proposal.update_state('almonds!') }.to raise_error(ArgumentError) end end end @@ -500,14 +490,14 @@ describe "#withdraw" do it "sets proposal's state to withdrawn" do - proposal = create(:proposal_with_track, state: Proposal::SUBMITTED) + proposal = create(:proposal_with_track, state: :submitted) proposal.withdraw - expect(proposal.state).to eq(Proposal::WITHDRAWN) + expect(proposal).to be_withdrawn end it "sends a notification to reviewers" do - proposal = create(:proposal_with_track, :with_reviewer_public_comment, state: Proposal::SUBMITTED) + proposal = create(:proposal_with_track, :with_reviewer_public_comment, state: :submitted) expect { proposal.withdraw }.to change { Notification.count }.by(1) diff --git a/spec/support/shared_examples/an_open_event.rb b/spec/support/shared_examples/an_open_event.rb index d9277bc98..009025347 100644 --- a/spec/support/shared_examples/an_open_event.rb +++ b/spec/support/shared_examples/an_open_event.rb @@ -1,11 +1,11 @@ RSpec.shared_examples_for 'an open event' do let(:event) { create :event, name: 'Best Event', state: :open } - let(:withdrawn) { Proposal::State::WITHDRAWN } - let(:accepted) { Proposal::State::ACCEPTED } - let(:soft_accepted) { Proposal::State::SOFT_ACCEPTED } - let(:waitlisted) { Proposal::State::WAITLISTED } - let(:soft_waitlisted) { Proposal::State::SOFT_WAITLISTED } + let(:withdrawn) { :withdrawn } + let(:accepted) { :accepted } + let(:soft_accepted) { :soft_accepted } + let(:waitlisted) { :waitlisted } + let(:soft_waitlisted) { :soft_waitlisted } let(:user1) { create :user, :program_team } let(:user2) { create :user, :reviewer } diff --git a/spec/system/proposal_spec.rb b/spec/system/proposal_spec.rb index b4075a3c7..5fd2376e7 100644 --- a/spec/system/proposal_spec.rb +++ b/spec/system/proposal_spec.rb @@ -179,7 +179,7 @@ let(:proposal) { create(:proposal_with_track) } before do - proposal.update(state: Proposal::State::ACCEPTED) + proposal.update(state: :accepted) ProgramSession.create_from_proposal(proposal) end @@ -218,7 +218,7 @@ end context "when deleted" do - let(:proposal) { create(:proposal_with_track, event: event, state: Proposal::State::SUBMITTED) } + let(:proposal) { create(:proposal_with_track, event: event, state: :submitted) } let!(:speaker) { create(:speaker, proposal: proposal, user: user) } before do @@ -232,7 +232,7 @@ end context "when withdrawn" do - let(:proposal) { create(:proposal_with_track, :with_reviewer_public_comment, event: event, state: Proposal::State::SUBMITTED) } + let(:proposal) { create(:proposal_with_track, :with_reviewer_public_comment, event: event, state: :submitted) } let!(:speaker) { create(:speaker, proposal: proposal, user: user) } before do @@ -253,7 +253,7 @@ context "when declined" do before do - @proposal = create(:proposal_with_track, state: Proposal::State::ACCEPTED) + @proposal = create(:proposal_with_track, state: :accepted) speaker = create(:speaker, proposal: @proposal, user: user) @proposal.speakers << speaker ProgramSession.create_from_proposal(@proposal) diff --git a/spec/system/staff/organizer_finalizes_proposals_spec.rb b/spec/system/staff/organizer_finalizes_proposals_spec.rb index 6ee28db56..93787328f 100644 --- a/spec/system/staff/organizer_finalizes_proposals_spec.rb +++ b/spec/system/staff/organizer_finalizes_proposals_spec.rb @@ -27,7 +27,7 @@ scenario "organizer can view soft state proposals by state" do proposal_two = create(:proposal_with_track, event: event) - proposal_two.update(state: Proposal::State::SOFT_ACCEPTED) + proposal_two.update(state: :soft_accepted) visit bulk_finalize_event_staff_program_proposals_path(event) expect(page).to have_content("1 submitted proposal") diff --git a/spec/system/staff/proposals_spec.rb b/spec/system/staff/proposals_spec.rb index c5a5487c9..e9c453533 100644 --- a/spec/system/staff/proposals_spec.rb +++ b/spec/system/staff/proposals_spec.rb @@ -28,7 +28,7 @@ updated_by_speaker_at = proposal.updated_by_speaker_at click_link 'Accept' - expect(proposal.reload.state).to eql(Proposal::State::SOFT_ACCEPTED) + expect(proposal.reload).to be_soft_accepted expect(ActionMailer::Base.deliveries).to be_empty expect(proposal.reload.updated_by_speaker_at).to be_within(1.second).of(updated_by_speaker_at) end @@ -39,7 +39,7 @@ updated_by_speaker_at = proposal.updated_by_speaker_at click_link 'Reject' - expect(proposal.reload.state).to eql(Proposal::State::SOFT_REJECTED) + expect(proposal.reload).to be_soft_rejected expect(ActionMailer::Base.deliveries).to be_empty expect(proposal.reload.updated_by_speaker_at).to be_within(1.second).of(updated_by_speaker_at) end @@ -50,7 +50,7 @@ updated_by_speaker_at = proposal.updated_by_speaker_at click_link 'Waitlist' - expect(proposal.reload.state).to eql(Proposal::State::SOFT_WAITLISTED) + expect(proposal.reload).to be_soft_waitlisted expect(ActionMailer::Base.deliveries).to be_empty expect(proposal.reload.updated_by_speaker_at).to be_within(1.second).of(updated_by_speaker_at) end @@ -77,7 +77,7 @@ end it "sets proposal state to accepted" do - expect(proposal.reload.state).to eql(Proposal::State::ACCEPTED) + expect(proposal.reload).to be_accepted end it "sends an email notification to the speaker" do @@ -93,7 +93,7 @@ end it "sets proposal state to rejected" do - expect(proposal.reload.state).to eql(Proposal::State::REJECTED) + expect(proposal.reload).to be_rejected end it "sends an email notification to the speaker" do @@ -109,7 +109,7 @@ end it "sets proposal state to waitlisted" do - expect(proposal.reload.state).to eql(Proposal::State::WAITLISTED) + expect(proposal.reload).to be_waitlisted end it "sends an email notification to the speaker" do