From 27fa79a8267916a57215456ce04647df4549c35a Mon Sep 17 00:00:00 2001 From: AEtherC0r3 Date: Thu, 17 Aug 2017 13:36:46 +0300 Subject: [PATCH] Track related refactoring Add roles as nested routes to track (for the track organizer role) Allow transition from to_accept to to_reject and backwards Split Track#valid_dates validation to many independent ones Show all the confirmed tracks in the conference's splashpage Add comment in admin/Tracks#toggle_cfp_inclusion Rewrite admin/TracksController#accept spec Add feature spec for track requests Change 'In' to 'Room' in Tracks#index Rewrite Track#overlapping Refactor code in ProposalsController Fix typos --- app/controllers/admin/programs_controller.rb | 2 +- app/controllers/admin/roles_controller.rb | 10 +- app/controllers/admin/schedules_controller.rb | 3 +- app/controllers/admin/tracks_controller.rb | 2 +- app/controllers/proposals_controller.rb | 6 +- app/helpers/events_helper.rb | 4 +- app/models/track.rb | 60 ++++----- app/views/admin/roles/index.html.haml | 8 +- app/views/admin/roles/show.html.haml | 3 +- app/views/admin/tracks/index.html.haml | 4 +- .../admin/tracks/toggle_cfp_inclusion.js.erb | 5 + .../conferences/_conference_details.html.haml | 6 +- .../_schedule_splashpage.html.haml | 2 +- app/views/conferences/show.html.haml | 8 +- app/views/tracks/_form.html.haml | 2 +- app/views/tracks/index.html.haml | 21 +-- config/routes.rb | 13 +- .../admin/tracks_controller_spec.rb | 87 ++++++++---- spec/features/tracks_spec.rb | 126 +++++++++++++++--- spec/models/cfp_spec.rb | 4 +- spec/models/track_spec.rb | 47 ++++--- 21 files changed, 279 insertions(+), 144 deletions(-) diff --git a/app/controllers/admin/programs_controller.rb b/app/controllers/admin/programs_controller.rb index fe401078..3d9f66d8 100644 --- a/app/controllers/admin/programs_controller.rb +++ b/app/controllers/admin/programs_controller.rb @@ -30,7 +30,7 @@ module Admin flash.now[:error] = "Updating program failed. #{@program.errors.to_a.join('. ')}." render :new end - format.js { render json: { errors: "The selected schedule couldn't been updated #{@program.errors.to_a.join('. ')}" }, status: 422 } + format.js { render json: { errors: "The selected schedule couldn't be updated #{@program.errors.to_a.join('. ')}" }, status: 422 } end end end diff --git a/app/controllers/admin/roles_controller.rb b/app/controllers/admin/roles_controller.rb index e4b83241..7ddb7953 100644 --- a/app/controllers/admin/roles_controller.rb +++ b/app/controllers/admin/roles_controller.rb @@ -15,7 +15,7 @@ module Admin def show @url = if @track - toggle_user_track_admin_conference_role_path(@conference.short_title, @role.name, @track) + toggle_user_admin_conference_program_track_role_path(@conference.short_title, @track, @role.name) else toggle_user_admin_conference_role_path(@conference.short_title, @role.name) end @@ -24,7 +24,7 @@ module Admin def edit @url = if @track - track_admin_conference_role_path(@conference.short_title, @role.name, @track) + admin_conference_program_track_role_path(@conference.short_title, @track, @role.name) else admin_conference_role_path(@conference.short_title, @role.name) end @@ -36,7 +36,7 @@ module Admin if @role.update_attributes(role_params) url = if @track - track_admin_conference_role_path(@conference.short_title, @role.name, @track) + admin_conference_program_track_role_path(@conference.short_title, @track, @role.name) else admin_conference_role_path(@conference.short_title, @role.name) end @@ -55,7 +55,7 @@ module Admin state = user_params[:state] url = if @track - track_admin_conference_role_path(@conference.short_title, @role.name, @track) + admin_conference_program_track_role_path(@conference.short_title, @track, @role.name) else admin_conference_role_path(@conference.short_title, @role.name) end @@ -108,7 +108,7 @@ module Admin @selection = params[:id] ? params[:id].parameterize.underscore : 'organizer' if @selection == 'track_organizer' - @track = @conference.program.tracks.find_by(short_name: params[:track_name]) + @track = @conference.program.tracks.find_by(short_name: params[:track_id]) @role = Role.find_by(name: @selection, resource: @track) else @role = Role.find_by(name: @selection, resource: @conference) diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index 00ef9a1d..9f6c222b 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -43,7 +43,8 @@ module Admin self_organized_tracks_events = @program.tracks.self_organized.confirmed.map do |t| t.events.confirmed end - @unscheduled_events = @program.events.confirmed - @schedule.events - self_organized_tracks_events.flatten.compact + self_organized_tracks_events.flatten.compact! + @unscheduled_events = @program.events.confirmed - @schedule.events - self_organized_tracks_events @dates = @conference.start_date..@conference.end_date @rooms = @conference.venue.rooms if @conference.venue end diff --git a/app/controllers/admin/tracks_controller.rb b/app/controllers/admin/tracks_controller.rb index 03f26448..7352ee35 100644 --- a/app/controllers/admin/tracks_controller.rb +++ b/app/controllers/admin/tracks_controller.rb @@ -108,7 +108,7 @@ module Admin end else respond_to do |format| - format.js { render json: { errors: "The selected schedule couldn't been updated #{@track.errors.to_a.join('. ')}" }, status: 422 } + format.js { render json: { errors: "The selected schedule couldn't be updated #{@track.errors.to_a.join('. ')}" }, status: 422 } end end end diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index b75f648e..66052310 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -50,7 +50,8 @@ class ProposalsController < ApplicationController @event.speakers = [current_user] @event.submitter = current_user - if Track.find_by(id: params[:event][:track_id]).try(:cfp_active) == false + track = Track.find_by(id: params[:event][:track_id]) + if track && !track.cfp_active flash.now[:error] = 'You have selected a track that doesn\'t accept proposals' render action: 'new' return @@ -68,7 +69,8 @@ class ProposalsController < ApplicationController def update @url = conference_program_proposal_path(@conference.short_title, params[:id]) - if Track.find_by(id: params[:event][:track_id]).try(:cfp_active) == false + track = Track.find_by(id: params[:event][:track_id]) + if track && !track.cfp_active flash.now[:error] = 'You have selected a track that doesn\'t accept proposals' render action: 'edit' return diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index dbc609ac..e8f295d5 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -41,9 +41,9 @@ module EventsHelper end def track_selector_input(form) - if @program.tracks.any? + if @program.tracks.confirmed.cfp_active.any? form.input :track_id, as: :select, - collection: @program.tracks.where(state: 'confirmed', cfp_active: true).pluck(:name, :id), + collection: @program.tracks.confirmed.cfp_active.pluck(:name, :id), include_blank: true end end diff --git a/app/models/track.rb b/app/models/track.rb index c3d02950..02d49f8c 100644 --- a/app/models/track.rb +++ b/app/models/track.rb @@ -31,8 +31,9 @@ class Track < ActiveRecord::Base validates :room, presence: true, if: :self_organized_and_accepted_or_confirmed? validates :relevance, presence: true, if: :self_organized? validates :description, presence: true, if: :self_organized? - validate :valid_dates - validate :valid_room, if: :self_organized_and_accepted_or_confirmed? + validate :dates_within_conference_dates + validate :start_date_before_end_date + validate :valid_room validate :overlapping before_validation :capitalize_color @@ -56,7 +57,7 @@ class Track < ActiveRecord::Base transitions to: :new, from: [:rejected, :withdrawn, :canceled] end event :to_accept do - transitions to: :to_accept, from: [:new] + transitions to: :to_accept, from: [:new, :to_reject] end event :accept do transitions to: :accepted, from: [:new, :to_accept], on_transition: :create_organizer_role @@ -65,7 +66,7 @@ class Track < ActiveRecord::Base transitions to: :confirmed, from: [:accepted], on_transition: :assign_role_to_submitter end event :to_reject do - transitions to: :to_reject, from: [:new] + transitions to: :to_reject, from: [:new, :to_accept] end event :reject do transitions to: :rejected, from: [:new, :to_reject] @@ -194,46 +195,41 @@ class Track < ActiveRecord::Base Role.where(name: 'track_organizer', resource: self).first_or_create(description: 'For the organizers of the Track') end - def valid_dates - if start_date && program && program.conference && program.conference.start_date && (start_date < program.conference.start_date) - errors.add(:start_date, "can't be before the conference start date (#{program.conference.start_date})") - end + ## + # Verify that the track's dates are between the conference's dates + # + def dates_within_conference_dates + return unless start_date && end_date && program.try(:conference).try(:start_date) && program.try(:conference).try(:end_date) + errors.add(:start_date, "can't be outside of the conference's dates (#{program.conference.start_date}-#{program.conference.end_date})") unless (program.conference.start_date..program.conference.end_date).cover?(start_date) + errors.add(:end_date, "can't be outside of the conference's dates (#{program.conference.start_date}-#{program.conference.end_date})") unless (program.conference.start_date..program.conference.end_date).cover?(end_date) + end - if end_date && program && program.conference && program.conference.start_date && (end_date < program.conference.start_date) - errors.add(:end_date, "can't be before the conference start date (#{program.conference.start_date})") - end - - if start_date && program && program.conference && program.conference.end_date && (start_date > program.conference.end_date) - errors.add(:start_date, "can't be after the conference end date (#{program.conference.end_date})") - end - - if end_date && program && program.conference && program.conference.end_date && (end_date > program.conference.end_date) - errors.add(:end_date, "can't be after the conference end date (#{program.conference.end_date})") - end - - if start_date && end_date && (start_date > end_date) - errors.add(:start_date, 'can\'t be after the end date') - end + ## + # Verify that the start date isn't after the end date + # + def start_date_before_end_date + return unless start_date && end_date + errors.add(:start_date, 'can\'t be after the end date') if start_date > end_date end ## # Verify that the room is a room of the conference + # def valid_room - if room && room.venue && room.venue.conference && program && program.conference && (program.conference != room.venue.conference) - errors.add(:room, "must be a room of #{program.conference.venue.name}") - end + return unless room.try(:venue).try(:conference) && program.try(:conference) + errors.add(:room, "must be a room of #{program.conference.venue.name}") unless room.venue.conference == program.conference end ## # Check that there is no other track in the same room with overlapping dates + # def overlapping return unless start_date && end_date && room && program.try(:tracks) - (program.tracks.accepted + program.tracks.confirmed - [self]).each do |other_track| - if other_track.room == room && - other_track.start_date && other_track.end_date && - (other_track.start_date <= start_date && other_track.end_date >= start_date || - other_track.start_date <= end_date && other_track.end_date >= end_date || - start_date <= other_track.start_date && other_track.end_date <= end_date) + (program.tracks.accepted + program.tracks.confirmed - [self]).each do |existing_track| + next unless existing_track.room == room && existing_track.start_date && existing_track.end_date + if start_date >= existing_track.start_date && start_date <= existing_track.end_date || + end_date >= existing_track.start_date && end_date <= existing_track.end_date || + start_date <= existing_track.start_date && end_date >= existing_track.end_date errors.add(:track, 'has overlapping dates with a confirmed or accepted track in the same room') break end diff --git a/app/views/admin/roles/index.html.haml b/app/views/admin/roles/index.html.haml index 4a100025..4990673e 100644 --- a/app/views/admin/roles/index.html.haml +++ b/app/views/admin/roles/index.html.haml @@ -27,15 +27,17 @@ = role.users.pluck(:name).first(5).join ', ' - if role.users.count > 5 - if role.resource_type == 'Track' - = link_to '...', track_admin_conference_role_path(@conference.short_title, role.name, role.resource) + = link_to '...', admin_conference_program_track_role_path(@conference.short_title, role.resource, role.name) - else = link_to '...', admin_conference_role_path(@conference.short_title, role.name) %td .btn-group - if role.resource_type == 'Track' - = link_to 'Users', track_admin_conference_role_path(@conference.short_title, role.name, role.resource), class: 'btn btn-success' + = link_to 'Users', admin_conference_program_track_role_path(@conference.short_title, role.resource, role.name), + class: 'btn btn-success' - if can? :edit, role - = link_to 'Edit', track_edit_admin_conference_role_path(@conference.short_title, role.name, role.resource), class: 'btn btn-primary' + = link_to 'Edit', edit_admin_conference_program_track_role_path(@conference.short_title, role.resource, role.name), + class: 'btn btn-primary' - else = link_to 'Users', admin_conference_role_path(@conference.short_title, role.name), class: 'btn btn-success' - if can? :edit, role diff --git a/app/views/admin/roles/show.html.haml b/app/views/admin/roles/show.html.haml index ee249975..b264bc5f 100644 --- a/app/views/admin/roles/show.html.haml +++ b/app/views/admin/roles/show.html.haml @@ -7,7 +7,8 @@ = @role.name.titleize - if can? :edit, @role - if @track - = link_to 'Edit', track_edit_admin_conference_role_path(@conference.short_title, @role.name, @track), class: 'btn btn-primary pull-right' + = link_to 'Edit', edit_admin_conference_program_track_role_path(@conference.short_title, @track, @role.name), + class: 'btn btn-primary pull-right' - else = link_to 'Edit', edit_admin_conference_role_path(@conference.short_title, @role.name), class: 'btn btn-primary pull-right' .text-muted diff --git a/app/views/admin/tracks/index.html.haml b/app/views/admin/tracks/index.html.haml index 48c0d1b3..6ac42003 100644 --- a/app/views/admin/tracks/index.html.haml +++ b/app/views/admin/tracks/index.html.haml @@ -24,7 +24,7 @@ %tr %td = track.id - %td{style: "padding: 15px 0px 0px 10px;"} + %td{ style: 'padding: 15px 0px 0px 10px;' } = link_to admin_conference_program_track_path(@conference.short_title, track), class: 'btn' do %span.label{style: "background-color: #{track.color}; color: #{ contrast_color(track.color) }"} = track.name @@ -60,7 +60,7 @@ - else = track.state.humanize %td - .btn-group{role: "group"} + .btn-group{ role: 'group' } - if can? :edit, track = link_to 'Edit', edit_admin_conference_program_track_path(@conference.short_title, track), class: 'btn btn-primary' - special_style = true diff --git a/app/views/admin/tracks/toggle_cfp_inclusion.js.erb b/app/views/admin/tracks/toggle_cfp_inclusion.js.erb index 6ee83003..84ddd69a 100644 --- a/app/views/admin/tracks/toggle_cfp_inclusion.js.erb +++ b/app/views/admin/tracks/toggle_cfp_inclusion.js.erb @@ -5,4 +5,9 @@ track_cfp_td = $('#cfp_switch_' + track_id); track_cfp_value = <%= @track.cfp_active %>; track_cfp_td.attr('data-order', track_cfp_value); + +/* +* The updated data-order attribute isn't taken into account +* until we invalidate the cell +*/ $('#tracks').DataTable().cell(track_cfp_td).invalidate(); diff --git a/app/views/conferences/_conference_details.html.haml b/app/views/conferences/_conference_details.html.haml index f4ec7101..ebf80ef6 100644 --- a/app/views/conferences/_conference_details.html.haml +++ b/app/views/conferences/_conference_details.html.haml @@ -30,10 +30,10 @@ = link_to "Register", new_conference_conference_registration_path(conference.short_title), class: "btn btn-default", disabled: cannot?(:new, Registration.new(conference_id: conference.id)) - if cannot?(:new, Registration.new(conference_id: conference.id)) && conference.registration_limit_exceeded? Sorry, no places left - - if !current_user.nil? && current_user.tracks.where(program: conference.program).length > 0 - = link_to "My Track Requests", conference_program_tracks_path(conference.short_title), class: 'btn btn-default' + - if current_user && current_user.tracks.where(program: conference.program).length > 0 + = link_to 'My Track Requests', conference_program_tracks_path(conference.short_title), class: 'btn btn-default' - elsif can? :new, conference.program.tracks.new - = link_to "Submit Track Request", new_conference_program_track_path(conference.short_title), class: 'btn btn-default' + = link_to 'Submit Track Request', new_conference_program_track_path(conference.short_title), class: 'btn btn-default' - if !current_user.nil? && current_user.proposal_count(conference) > 0 = link_to "My Proposals", conference_program_proposals_path(conference.short_title), class: 'btn btn-default' - elsif can? :new, conference.program.events.new diff --git a/app/views/conferences/_schedule_splashpage.html.haml b/app/views/conferences/_schedule_splashpage.html.haml index defd3e4d..790582cb 100644 --- a/app/views/conferences/_schedule_splashpage.html.haml +++ b/app/views/conferences/_schedule_splashpage.html.haml @@ -10,7 +10,7 @@ - if @conference.splashpage and @conference.program.tracks.any? and @conference.splashpage.include_tracks See rock-star speakers cover the topics of - if @conference.splashpage and @conference.splashpage.include_tracks - - @conference.program.tracks.confirmed.cfp_active.each_slice(3) do |slice| + - @conference.program.tracks.confirmed.each_slice(3) do |slice| .row.row-centered - slice.each do |track| .col-md-4.col-sm-4.col-centered.col-top.track diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml index afda1516..f94b8ee4 100644 --- a/app/views/conferences/show.html.haml +++ b/app/views/conferences/show.html.haml @@ -45,14 +45,14 @@ %section#program = render 'schedule_splashpage' - - if @conference.program.cfps.for_tracks.try(:open?) && @conference.splashpage.include_cfp - %section#callfortracks - = render 'call_for_tracks' - - if @conference.program.cfp_open? and @conference.splashpage.include_cfp %section#callforpapers = render 'call_for_paper' + - if @conference.program.cfps.for_tracks.try(:open?) && @conference.splashpage.include_cfp + %section#callfortracks + = render 'call_for_tracks' + - if @conference.venue and @conference.splashpage.include_venue %section#venue = render 'venue' diff --git a/app/views/tracks/_form.html.haml b/app/views/tracks/_form.html.haml index ab693dc5..42832e80 100644 --- a/app/views/tracks/_form.html.haml +++ b/app/views/tracks/_form.html.haml @@ -16,5 +16,5 @@ = f.input :start_date, as: :string, input_html: { id: 'registration-period-start-datepicker', start_date: @conference.start_date, end_date: @conference.end_date, readonly: 'readonly' } = f.input :end_date, as: :string, input_html: { id: 'registration-period-end-datepicker', readonly: 'readonly' } = f.input :description, input_html: {rows: 2, data: { provide: 'markdown-editable' } }, required: true, hint: "This will be public #{markdown_hint}".html_safe - = f.input :relevance, input_html: {rows: 5, data: { provide: 'markdown-editable' } }, required: true, hint: "Please explain here how this track relates to the conference, how you are related to it's content and why we should accept it. #{markdown_hint}".html_safe + = f.input :relevance, input_html: {rows: 5, data: { provide: 'markdown-editable' } }, required: true, hint: "Please explain here how this track relates to the conference, how you are related to its content and why we should accept it. #{markdown_hint}".html_safe = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/tracks/index.html.haml b/app/views/tracks/index.html.haml index d17ee766..b20a3ca9 100644 --- a/app/views/tracks/index.html.haml +++ b/app/views/tracks/index.html.haml @@ -19,7 +19,7 @@ If you submit a track request, the conference organizers will review it and either accept or reject it. %br If your track request is accepted, the conference organizers expect you to confirm that you will be able to hold it. - Then you will gain the Track organizer role. + Then you will be assigned the Track organizer role. %br If your track request is rejected, you can either live with that or adapt it and resubmit it for review again. %br @@ -29,6 +29,13 @@ .row .col-md-12 %table.table.table-striped#tracks + %th + %th + %th + %th From + %th To + %th Room + %th - @tracks.each do |track| %tr %td{style: "padding:15px 0px 0px 8px;"} @@ -47,17 +54,11 @@ %td = markdown(truncate(track.description)) %td - - if track.start_date - From: - = track.start_date.strftime('%A, %B %-d. %Y') + = track.start_date.strftime('%A, %B %-d. %Y') if track.start_date %td - - if track.end_date - To: - = track.end_date.strftime('%A, %B %-d. %Y') + = track.end_date.strftime('%A, %B %-d. %Y') if track.end_date %td - - if track.room - In: - = track.room.name + = track.try(:room).try(:name) %td .pull-right - if track.transition_possible? :confirm diff --git a/config/routes.rb b/config/routes.rb index 0e1cad2e..0d7e7aec 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -90,6 +90,11 @@ Osem::Application.routes.draw do patch :cancel patch :update_selected_schedule end + resources :roles, only: [:show, :edit, :update] do + member do + post :toggle_user + end + end end resources :event_types resources :difficulty_levels @@ -118,15 +123,9 @@ Osem::Application.routes.draw do resources :campaigns, except: [:show] resources :emails, only: [:show, :update, :index] resources :physical_ticket, only: [:index] - resources :roles, only: [:edit] - resources :roles, except: [ :new, :create, :edit ] do + resources :roles, except: [:new, :create] do member do post :toggle_user - get ':track_name' => 'roles#show', as: 'track' - get ':track_name/edit' => 'roles#edit', as: 'track_edit' - patch ':track_name' => 'roles#update' - put ':track_name' => 'roles#update' - post ':track_name/toggle_user' => 'roles#toggle_user', as: 'toggle_user_track' end end diff --git a/spec/controllers/admin/tracks_controller_spec.rb b/spec/controllers/admin/tracks_controller_spec.rb index 795906aa..03511ce1 100644 --- a/spec/controllers/admin/tracks_controller_spec.rb +++ b/spec/controllers/admin/tracks_controller_spec.rb @@ -3,9 +3,11 @@ require 'spec_helper' describe Admin::TracksController do let(:admin) { create(:admin) } - let(:conference) { create(:conference) } + let(:conference) { create(:conference, start_date: Date.current - 1.day) } + let(:venue) { create(:venue, conference: conference) } + let(:room) { create(:room, venue: venue) } let!(:track) { create(:track, program: conference.program, color: '#800080') } - let!(:self_organized_track) { create(:track, :self_organized, program: conference.program, name: 'My awesome track') } + let!(:self_organized_track) { create(:track, :self_organized, program: conference.program, name: 'My awesome track', start_date: Date.current, end_date: Date.current, room: room) } before :each do sign_in(admin) @@ -81,7 +83,7 @@ describe Admin::TracksController do expect(Track.find(assigns(:track).id)).to be_a Track end - it 'the new tracks has the correct attributes' do + it 'the new track has the correct attributes' do expect(assigns(:track).state).to eq 'confirmed' expect(assigns(:track).cfp_active).to eq true end @@ -358,20 +360,13 @@ describe Admin::TracksController do end describe 'PATCH #accept' do - shared_examples 'fails to accept' do |start_date, end_date, room| + shared_examples 'fails to accept' do before :each do - self_organized_track.start_date = start_date ? Date.today : nil - self_organized_track.end_date = end_date ? Date.today : nil - if room - conference.venue = create(:venue) - self_organized_track.room = create(:room, venue: conference.venue) - else - self_organized_track.room = nil - end - self_organized_track.save! - patch :accept, conference_id: conference.short_title, id: self_organized_track.short_name - self_organized_track.reload + end + + it 'assigns the correct track' do + expect(assigns(:track)).to eq self_organized_track end it 'redirects to Tracks#edit' do @@ -385,12 +380,6 @@ describe Admin::TracksController do context 'has start_date, end_date and room' do before :each do - self_organized_track.start_date = Date.today - self_organized_track.end_date = Date.today - conference.venue = create(:venue) - self_organized_track.room = create(:room, venue: conference.venue) - self_organized_track.save! - patch :accept, conference_id: conference.short_title, id: self_organized_track.short_name self_organized_track.reload end @@ -409,31 +398,71 @@ describe Admin::TracksController do end context 'has start_date and end_date' do - it_behaves_like 'fails to accept', true, true, false + before :each do + self_organized_track.room = nil + self_organized_track.save! + end + + it_behaves_like 'fails to accept' end context 'has start_date and room' do - it_behaves_like 'fails to accept', true, false, true + before :each do + self_organized_track.end_date = nil + self_organized_track.save! + end + + it_behaves_like 'fails to accept' end context 'has start_date' do - it_behaves_like 'fails to accept', true, false, false + before :each do + self_organized_track.end_date = nil + self_organized_track.room = nil + self_organized_track.save! + end + + it_behaves_like 'fails to accept' end context 'has end_date and room' do - it_behaves_like 'fails to accept', false, true, true + before :each do + self_organized_track.start_date = nil + self_organized_track.save! + end + + it_behaves_like 'fails to accept' end context 'has end_date' do - it_behaves_like 'fails to accept', false, true, false + before :each do + self_organized_track.start_date = nil + self_organized_track.room = nil + self_organized_track.save! + end + + it_behaves_like 'fails to accept' end context 'has room' do - it_behaves_like 'fails to accept', false, false, true + before :each do + self_organized_track.start_date = nil + self_organized_track.end_date = nil + self_organized_track.save! + end + + it_behaves_like 'fails to accept' end - context 'has non of start_date, end_date, room' do - it_behaves_like 'fails to accept', false, false, false + context 'has none of start_date, end_date, room' do + before :each do + self_organized_track.start_date = nil + self_organized_track.end_date = nil + self_organized_track.room = nil + self_organized_track.save! + end + + it_behaves_like 'fails to accept' end end diff --git a/spec/features/tracks_spec.rb b/spec/features/tracks_spec.rb index 91e90ee9..0819c650 100644 --- a/spec/features/tracks_spec.rb +++ b/spec/features/tracks_spec.rb @@ -4,26 +4,29 @@ feature Track do let!(:conference) { create(:conference) } let!(:organizer_role) { Role.find_by(name: 'organizer', resource: conference) } let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } + let(:user) { create(:user) } - shared_examples 'tracks' do + shared_examples 'admin tracks' do scenario 'adds a track', feature: true, js: true do sign_in organizer - visit admin_conference_program_tracks_path(conference_id: conference.short_title) - click_link 'New Track' + expected = expect do + visit admin_conference_program_tracks_path(conference_id: conference.short_title) + click_link 'New Track' - fill_in 'track_name', with: 'Distribution' - fill_in 'track_short_name', with: 'Distribution' - page.find('#track_color').set('#B94D4D') - fill_in 'track_description', with: 'Events about our Linux distribution' - click_button 'Create Track' + fill_in 'track_name', with: 'Distribution' + fill_in 'track_short_name', with: 'Distribution' + page.find('#track_color').set('#B94D4D') + fill_in 'track_description', with: 'Events about our Linux distribution' + click_button 'Create Track' + end + expected.to change { Track.count }.by 1 expect(flash).to eq('Track successfully created.') within('table#tracks') do expect(page.has_content?('Distribution')).to be true expect(page.has_content?('Events about our Linux')).to be true - expect(page.assert_selector('tr', count: 2)).to be true end end @@ -31,15 +34,17 @@ feature Track do track = create(:track, program_id: conference.program.id) sign_in organizer - visit admin_conference_program_tracks_path(conference_id: conference.short_title) + expected = expect do + visit admin_conference_program_tracks_path(conference_id: conference.short_title) - click_link 'Delete' + click_link 'Delete' + end + expected.to change { Track.count }.by(-1) expect(flash).to eq('Track successfully deleted.') within('table#tracks') do expect(page.has_content?(track.name)).to be false expect(page.has_content?(track.description)).to be false - expect(page.has_content?('No data available in table')).to eq true end end @@ -47,25 +52,104 @@ feature Track do create(:track, program_id: conference.program.id) sign_in organizer - visit admin_conference_program_tracks_path(conference_id: conference.short_title) - click_link 'Edit' + expected = expect do + visit admin_conference_program_tracks_path(conference_id: conference.short_title) + click_link 'Edit' - fill_in 'track_name', with: 'Distribution' - fill_in 'track_short_name', with: 'Distribution' - page.find('#track_color').set('#B94D4D') - fill_in 'track_description', with: 'Events about our Linux distribution' - click_button 'Update Track' + fill_in 'track_name', with: 'Distribution' + fill_in 'track_short_name', with: 'Distribution' + page.find('#track_color').set('#B94D4D') + fill_in 'track_description', with: 'Events about our Linux distribution' + click_button 'Update Track' + end + expected.to_not(change { Track.count }) expect(flash).to eq('Track successfully updated.') within('table#tracks') do expect(page.has_content?('Distribution')).to be true expect(page.has_content?('Events about our Linux')).to be true - expect(page.assert_selector('tr', count: 2)).to be true + end + end + end + + shared_examples 'non admin tracks' do + scenario 'adds a track', feature: true, js: true do + + sign_in user + + expected = expect do + visit conference_program_tracks_path(conference_id: conference.short_title) + click_link 'New Track request' + + fill_in 'track_name', with: 'Distribution' + fill_in 'track_short_name', with: 'Distribution' + page.find('#track_color').set('#B94D4D') + fill_in 'track_description', with: 'Events about our Linux distribution' + fill_in 'track_relevance', with: 'Maintainer of super awesome distribution' + click_button 'Create Track' + end + + expected.to change { Track.count }.by 1 + expect(flash).to eq('Track request successfully created.') + within('table#tracks') do + expect(page.has_content?('Distribution')).to eq true + expect(page.has_content?('Events about our Linux dist...')).to eq true + end + end + + scenario 'withdraws a track', feature: true, js: true do + track = create(:track, :self_organized, program_id: conference.program.id, submitter: user) + sign_in user + + expected = expect do + visit conference_program_tracks_path(conference_id: conference.short_title) + + accept_confirm do + click_link 'Withdraw' + end + end + + expected.to_not(change { Track.count }) + expect(flash).to eq("Track #{track.name} withdrawn.") + within('table#tracks') do + expect(page.has_content?(track.name)).to eq true + expect(page.has_link?('Re-Submit')).to eq true + end + end + + scenario 'updates a track', feature: true, js: true do + create(:track, :self_organized, program_id: conference.program.id, submitter: user) + sign_in user + + expected = expect do + visit conference_program_tracks_path(conference_id: conference.short_title) + click_link 'Edit' + + fill_in 'track_name', with: 'Distribution' + fill_in 'track_short_name', with: 'Distribution' + page.find('#track_color').set('#B94D4D') + fill_in 'track_description', with: 'Events about our Linux distribution' + click_button 'Update Track' + end + + expected.to_not(change { Track.count }) + expect(flash).to eq('Track request successfully updated.') + within('table#tracks') do + expect(page.has_content?('Distribution')).to eq true + expect(page.has_content?('Events about our Linux dist...')).to eq true end end end describe 'organizer' do - it_behaves_like 'tracks' + it_behaves_like 'admin tracks' + end + + describe 'signed in user' do + before :each do + create(:cfp, cfp_type: 'tracks', program: conference.program) + end + + it_behaves_like 'non admin tracks' end end diff --git a/spec/models/cfp_spec.rb b/spec/models/cfp_spec.rb index 95607491..6c437d35 100644 --- a/spec/models/cfp_spec.rb +++ b/spec/models/cfp_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Cfp do subject { create(:cfp) } let!(:conference) { create(:conference, end_date: Date.today) } - let!(:cfp) { create(:cfp, start_date: Date.today - 2, end_date: Date.today - 1, program_id: conference.program.id) } + let!(:cfp) { create(:cfp, cfp_type: 'events', start_date: Date.today - 2, end_date: Date.today - 1, program_id: conference.program.id) } describe 'validations' do it { is_expected.to validate_presence_of(:cfp_type) } @@ -18,7 +18,7 @@ describe Cfp do end it 'returns nil when the cfp for events doesn\'t exist' do - conference.program.cfp.destroy + cfp.destroy! expect(conference.program.cfps.for_events).to eq nil end end diff --git a/spec/models/track_spec.rb b/spec/models/track_spec.rb index d356a2c7..8f53c732 100644 --- a/spec/models/track_spec.rb +++ b/spec/models/track_spec.rb @@ -68,14 +68,14 @@ describe Track do it { is_expected.to_not validate_presence_of(:description) } end - describe '#valid_dates' do + describe '#dates_within_conference_dates' do before :each do @conference = create(:conference, start_date: 1.day.ago, end_date: 2.days.from_now) end context 'is valid' do - it 'when the track\'s start date is before it\'s end date and between the conference start/end dates' do - track = build(:track, start_date: Date.today, end_date: Date.tomorrow, program: @conference.program) + it 'when the track\'s dates are between the conference\'s dates' do + track = build(:track, start_date: @conference.start_date, end_date: @conference.end_date, program: @conference.program) expect(track.valid?).to eq true end end @@ -84,27 +84,42 @@ describe Track do it 'when the track\'s start date is before the conference\'s start date' do track = build(:track, start_date: 2.days.ago, end_date: Date.tomorrow, program: @conference.program) expect(track.valid?).to eq false - expect(track.errors[:start_date]).to eq ["can't be before the conference start date (#{1.day.ago.to_date})"] - end - - it 'when the track\'s end date is before the conference\'s start date' do - track = build(:track, start_date: 3.days.ago, end_date: 2.days.ago, program: @conference.program) - expect(track.valid?).to eq false - expect(track.errors[:end_date]).to eq ["can't be before the conference start date (#{1.day.ago.to_date})"] + expect(track.errors[:start_date]).to eq ["can't be outside of the conference's dates (#{1.day.ago.to_date}-#{2.days.from_now.to_date})"] end it 'when the track\'s start date is after the conference\'s end date' do track = build(:track, start_date: 3.days.from_now, end_date: 4.days.from_now, program: @conference.program) expect(track.valid?).to eq false - expect(track.errors[:start_date]).to eq ["can't be after the conference end date (#{2.days.from_now.to_date})"] + expect(track.errors[:start_date]).to eq ["can't be outside of the conference's dates (#{1.day.ago.to_date}-#{2.days.from_now.to_date})"] + end + + it 'when the track\'s end date is before the conference\'s start date' do + track = build(:track, start_date: 3.days.ago, end_date: 2.days.ago, program: @conference.program) + expect(track.valid?).to eq false + expect(track.errors[:end_date]).to eq ["can't be outside of the conference's dates (#{1.day.ago.to_date}-#{2.days.from_now.to_date})"] end it 'when the track\'s end date is after the conference\'s end date' do track = build(:track, start_date: Date.today, end_date: 3.days.from_now, program: @conference.program) expect(track.valid?).to eq false - expect(track.errors[:end_date]).to eq ["can't be after the conference end date (#{2.days.from_now.to_date})"] + expect(track.errors[:end_date]).to eq ["can't be outside of the conference's dates (#{1.day.ago.to_date}-#{2.days.from_now.to_date})"] end + end + end + describe '#start_date_before_end_date' do + before :each do + @conference = create(:conference, start_date: 1.day.ago, end_date: 2.days.from_now) + end + + context 'is valid' do + it 'when the track\'s start date is before its end date' do + track = build(:track, start_date: Date.today, end_date: Date.tomorrow, program: @conference.program) + expect(track.valid?).to eq true + end + end + + context 'is invalid' do it 'when the track\'s start date is after it\'s end date' do track = build(:track, start_date: 1.day.from_now, end_date: 1.day.ago) expect(track.valid?).to eq false @@ -235,7 +250,7 @@ describe Track do end context 'includes' do - it 'when track is confirmed' do + it 'tracks with state \'confirmed\'' do confirmed_track = create(:track, state: 'confirmed', program: @program) expect(@program.tracks.confirmed.include?(confirmed_track)).to eq true end @@ -243,7 +258,7 @@ describe Track do context 'excludes' do %w[new to_accept accepted to_reject rejected canceled withdrawn].each do |state| - it "when track is #{state.humanize}" do + it "tracks with state '#{state}'" do unconfirmed_track = create(:track, state: state, program: @program) expect(@program.tracks.confirmed.include?(unconfirmed_track)).to eq false end @@ -310,10 +325,10 @@ describe Track do transitions = [:restart, :to_accept, :accept, :confirm, :to_reject, :reject, :cancel, :withdraw] states_transitions = { new: { restart: false, to_accept: true, accept: true, confirm: false, to_reject: true, reject: true, cancel: false, withdraw: true }, - to_accept: { restart: false, to_accept: false, accept: true, confirm: false, to_reject: false, reject: false, cancel: true, withdraw: true }, + to_accept: { restart: false, to_accept: false, accept: true, confirm: false, to_reject: true, reject: false, cancel: true, withdraw: true }, accepted: { restart: false, to_accept: false, accept: false, confirm: true, to_reject: false, reject: false, cancel: true, withdraw: true }, confirmed: { restart: false, to_accept: false, accept: false, confirm: false, to_reject: false, reject: false, cancel: true, withdraw: true }, - to_reject: { restart: false, to_accept: false, accept: false, confirm: false, to_reject: false, reject: true, cancel: true, withdraw: true }, + to_reject: { restart: false, to_accept: true, accept: false, confirm: false, to_reject: false, reject: true, cancel: true, withdraw: true }, rejected: { restart: true, to_accept: false, accept: false, confirm: false, to_reject: false, reject: false, cancel: false, withdraw: false }, canceled: { restart: true, to_accept: false, accept: false, confirm: false, to_reject: false, reject: false, cancel: false, withdraw: false }, withdrawn: { restart: true, to_accept: false, accept: false, confirm: false, to_reject: false, reject: false, cancel: false, withdraw: false } }