From d2bb92c65317ae66e66aabf3fbb1268328e24cba Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Tue, 27 May 2025 15:25:18 -0400 Subject: [PATCH 01/11] Add scopes to ContestInstance model for filtering by contest description. Introduced `active_for_contest_description` and `for_contest_description` scopes to enhance query capabilities and improve data retrieval for active contest instances. --- app/models/contest_instance.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/models/contest_instance.rb b/app/models/contest_instance.rb index fca1cfe4..463138bc 100644 --- a/app/models/contest_instance.rb +++ b/app/models/contest_instance.rb @@ -88,6 +88,14 @@ class ContestInstance < ApplicationRecord where.not(id: maxed_out_contest_instance_ids) } + scope :active_for_contest_description, ->(contest_description_id) { + where(active: true, contest_description_id: contest_description_id) + } + + scope :for_contest_description, ->(contest_description_id) { + where(contest_description_id: contest_description_id) + } + def open? active && Time.current.between?(date_open, date_closed) end From 85a0c972bc5449fec95b36ee1c1739b6a44f378c Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Tue, 27 May 2025 15:25:30 -0400 Subject: [PATCH 02/11] Add active and inactive description counts to container and contest instance views. Enhanced user feedback by displaying the number of active and inactive descriptions for containers and contest instances, improving overall data visibility. --- app/views/containers/_container_detail.html.erb | 5 +++++ app/views/contest_instances/index.html.erb | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/app/views/containers/_container_detail.html.erb b/app/views/containers/_container_detail.html.erb index 5698d7c3..32cd81e7 100644 --- a/app/views/containers/_container_detail.html.erb +++ b/app/views/containers/_container_detail.html.erb @@ -74,6 +74,11 @@ +
+ This collection has <%= pluralize(container_contest_descriptions.active.count, "active description") %> + and <%= pluralize(container_contest_descriptions.count - container_contest_descriptions.active.count, "inactive description") %>. +
+
<% if container_contest_descriptions.present? %> <%= render 'contest_descriptions_table', diff --git a/app/views/contest_instances/index.html.erb b/app/views/contest_instances/index.html.erb index ac97b501..b41dd3f5 100644 --- a/app/views/contest_instances/index.html.erb +++ b/app/views/contest_instances/index.html.erb @@ -47,6 +47,10 @@ Show only Active contest instances
+
+ This contest has <%= pluralize(@contest_instances.active_for_contest_description(@contest_description.id).count, "active instance") %> + and <%= pluralize(@contest_instances.for_contest_description(@contest_description.id).count - @contest_instances.active_for_contest_description(@contest_description.id).count, "inactive instance") %>. +
From d218646b1fabebeb707d4b17eedeae4bfdcd223d Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:56:00 -0400 Subject: [PATCH 03/11] Add deactivate route for ContestInstances. Introduced a new PATCH route to allow deactivation of contest instances, enhancing the management capabilities within the judging rounds context. --- config/routes.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/routes.rb b/config/routes.rb index 84f7a14a..e8ba039b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -46,6 +46,7 @@ post 'send_round_results' get :export_entries get :export_round_results + patch :deactivate end resources :judging_rounds do member do From cf896ae9dd258cbeb6b72723c12396c46d0a7410 Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:56:26 -0400 Subject: [PATCH 04/11] Fix missing newline at end of contest description edit view file. Ensured proper formatting for better compatibility and adherence to coding standards. --- app/views/contest_descriptions/edit.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/contest_descriptions/edit.html.erb b/app/views/contest_descriptions/edit.html.erb index 8a29312a..667893df 100644 --- a/app/views/contest_descriptions/edit.html.erb +++ b/app/views/contest_descriptions/edit.html.erb @@ -6,4 +6,4 @@
<%= render 'form' %> -
\ No newline at end of file + From e0fb1e162397de24185a2c1a7f6c8658c51b8079 Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:56:47 -0400 Subject: [PATCH 05/11] Refactor contest description form for improved readability and add inline rendering of active instances. Enhanced the form structure for better code clarity and included a partial to display active instances related to the contest description. --- app/views/contest_descriptions/_form.html.erb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/views/contest_descriptions/_form.html.erb b/app/views/contest_descriptions/_form.html.erb index 57a49f80..a8dacf87 100644 --- a/app/views/contest_descriptions/_form.html.erb +++ b/app/views/contest_descriptions/_form.html.erb @@ -1,5 +1,8 @@
- <%= simple_form_for([@container, @contest_description], html: { id: 'new_contest_description_form' }) do |f| %> + <%= simple_form_for([@container, @contest_description], + html: { + id: 'new_contest_description_form' + }) do |f| %> <%= f.error_notification %> <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> @@ -18,3 +21,5 @@
<% end %> + +<%= render 'contest_descriptions/active_instances_inline', contest_description: @contest_description %> From d3c3d24ca178698bc8739ba78834ac6668b0829e Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:57:03 -0400 Subject: [PATCH 06/11] Add inline rendering for active contest instances in contest descriptions. Introduced a new partial to display active instances with options to deactivate, enhancing user interaction and visibility of contest management. --- .../_active_instances_inline.html.erb | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 app/views/contest_descriptions/_active_instances_inline.html.erb diff --git a/app/views/contest_descriptions/_active_instances_inline.html.erb b/app/views/contest_descriptions/_active_instances_inline.html.erb new file mode 100644 index 00000000..adc682eb --- /dev/null +++ b/app/views/contest_descriptions/_active_instances_inline.html.erb @@ -0,0 +1,27 @@ + + <% active_instances = contest_description.active_contest_instances %> + <% if active_instances.any? %> +
+
Active Contest Instances
+
    + <% active_instances.each do |instance| %> +
  • + + <%= instance.display_name %> + [<%= l(instance.date_open, format: :short) %> - <%= l(instance.date_closed, format: :short) %>] + + <%= button_to 'Deactivate', + deactivate_container_contest_description_contest_instance_path( + contest_description.container, contest_description, instance + ), + method: :patch, + data: { turbo_frame: 'active-instances-list' }, + class: 'btn btn-danger btn-sm' %> +
  • + <% end %> +
+
+ <% else %> +
No active contest instances.
+ <% end %> +
From 919321c810d306beabc55661de62d6d7e61f119a Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:57:17 -0400 Subject: [PATCH 07/11] Add validation to ContestInstance model to prevent activation if associated contest description is inactive. This ensures data integrity and improves error handling during contest management. --- app/models/contest_instance.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/models/contest_instance.rb b/app/models/contest_instance.rb index 463138bc..934af75c 100644 --- a/app/models/contest_instance.rb +++ b/app/models/contest_instance.rb @@ -56,6 +56,7 @@ class ContestInstance < ApplicationRecord validate :must_have_at_least_one_category validate :only_one_active_per_contest_description validate :date_closed_after_date_open + validate :cannot_activate_if_description_inactive # Scopes scope :active_and_open, -> { @@ -179,4 +180,10 @@ def date_closed_after_date_open errors.add(:date_closed, 'must be after date contest opens') end end + + def cannot_activate_if_description_inactive + if active && contest_description && !contest_description.active? + errors.add(:active, 'Cannot activate a contest instance when its contest description is inactive.') + end + end end From c79bec05cc0d4b408b6ac984e323e3c1a43d6c3e Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:57:32 -0400 Subject: [PATCH 08/11] Add validation to ContestDescription model to prevent deactivation if active contest instances exist. This ensures data integrity during contest management and enhances error handling for contest descriptions. --- app/models/contest_description.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/models/contest_description.rb b/app/models/contest_description.rb index 38ea4aa4..ce798e5d 100644 --- a/app/models/contest_description.rb +++ b/app/models/contest_description.rb @@ -29,6 +29,19 @@ class ContestDescription < ApplicationRecord validates :created_by, presence: true validates :name, presence: true, uniqueness: true + validate :cannot_deactivate_with_active_instances scope :active, -> { where(active: true) } + + def active_contest_instances + contest_instances.where(active: true) + end + + private + + def cannot_deactivate_with_active_instances + if will_save_change_to_active? && !active && contest_instances.where(active: true).exists? + errors.add(:active, 'Cannot deactivate contest description while instances are active.') + end + end end From 4fea360a85eea6420565c89e1b59607139135ee0 Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:58:06 -0400 Subject: [PATCH 09/11] Add deactivate action to ContestInstancesController. Implemented functionality to update contest instance status to inactive, with Turbo Stream response for inline rendering of active instances. This enhances contest management capabilities and user interaction. --- app/controllers/contest_instances_controller.rb | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/app/controllers/contest_instances_controller.rb b/app/controllers/contest_instances_controller.rb index 5011e151..19e90fa2 100644 --- a/app/controllers/contest_instances_controller.rb +++ b/app/controllers/contest_instances_controller.rb @@ -1,7 +1,7 @@ class ContestInstancesController < ApplicationController before_action :set_container before_action :set_contest_description - before_action :set_contest_instance, only: %i[show edit update destroy send_round_results] + before_action :set_contest_instance, only: %i[show edit update destroy send_round_results deactivate] before_action :authorize_container_access # GET /contest_instances @@ -213,6 +213,21 @@ def export_round_results end end + def deactivate + @contest_instance.update(active: false) + @contest_description = @contest_instance.contest_description + respond_to do |format| + format.turbo_stream do + render turbo_stream: turbo_stream.replace( + 'active-instances-list', + partial: 'contest_descriptions/active_instances_inline', + locals: { contest_description: @contest_description } + ) + end + format.html { redirect_to container_contest_description_path(@contest_description.container, @contest_description), notice: 'Instance deactivated.' } + end + end + private def authorize_container_access From 30b9dd4ae1842a220bd000702ff1bdc1b2900616 Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:58:19 -0400 Subject: [PATCH 10/11] Implement validation in update action of ContestDescriptionsController to prevent deactivation if active contest instances exist. Added Turbo Stream response for user feedback and inline rendering of the form, enhancing error handling and user experience during contest management. --- .../contest_descriptions_controller.rb | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/app/controllers/contest_descriptions_controller.rb b/app/controllers/contest_descriptions_controller.rb index 4d0dbd2a..52cff0af 100644 --- a/app/controllers/contest_descriptions_controller.rb +++ b/app/controllers/contest_descriptions_controller.rb @@ -26,7 +26,22 @@ def create end def update - handle_save(@contest_description.update(contest_description_params), 'updated') + # Check if trying to deactivate with active instances + if contest_description_params[:active] == "0" && @contest_description.active_contest_instances.any? + flash.now[:alert] = "Cannot deactivate contest description while it has active instances. Please deactivate all instances first." + + respond_to do |format| + format.turbo_stream { + render turbo_stream: [ + turbo_stream.replace('flash', partial: 'shared/flash_messages'), + turbo_stream.replace('contest_description_form', partial: 'contest_descriptions/form', locals: { contest_description: @contest_description }) + ], status: :unprocessable_entity + } + format.html { render :edit, status: :unprocessable_entity } + end + else + handle_save(@contest_description.update(contest_description_params), 'updated') + end end def destroy From 4bf3248c0926bf4ddd86ea52a39b2136abae8b47 Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Wed, 28 May 2025 16:59:21 -0400 Subject: [PATCH 11/11] Update specs to use active contest descriptions across controllers and features. This change ensures that tests reflect the current business logic by only associating active contest descriptions, enhancing the accuracy of test coverage and maintaining data integrity in contest management. --- .../contest_instances_controller_spec.rb | 8 +++---- .../entry_rankings_controller_spec.rb | 2 +- .../judge_dashboard_controller_spec.rb | 2 +- .../judging_assignments_controller_spec.rb | 2 +- .../judging_rounds_controller_spec.rb | 2 +- .../bulk_contest_instance_creation_spec.rb | 16 ++++++------- spec/features/judging_round_selection_spec.rb | 2 +- spec/mailers/results_mailer_spec.rb | 2 +- spec/models/container_spec.rb | 18 +++++++++++---- spec/models/contest_description_spec.rb | 23 +++++++++++++++++++ spec/models/contest_instance_spec.rb | 15 ++++++++++++ spec/policies/contest_instance_policy_spec.rb | 2 +- spec/system/email_preferences_spec.rb | 2 +- spec/system/judge_dashboard_spec.rb | 6 ++--- spec/system/judge_management_spec.rb | 2 +- spec/system/judge_round_visibility_spec.rb | 2 +- spec/system/judging_results_email_spec.rb | 2 +- spec/system/judging_rounds_spec.rb | 2 +- spec/system/profile_access_spec.rb | 2 +- 19 files changed, 80 insertions(+), 32 deletions(-) diff --git a/spec/controllers/contest_instances_controller_spec.rb b/spec/controllers/contest_instances_controller_spec.rb index 677c62fd..e811233d 100644 --- a/spec/controllers/contest_instances_controller_spec.rb +++ b/spec/controllers/contest_instances_controller_spec.rb @@ -7,7 +7,7 @@ let(:department) { create(:department) } let(:user) { create(:user, :axis_mundi) } # Admin user with full privileges let(:container) { create(:container, department: department) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:judging_round) { create(:judging_round, contest_instance: contest_instance, completed: true) } @@ -72,7 +72,7 @@ let(:department) { create(:department) } let(:user) { create(:user, :axis_mundi) } # Admin user with full privileges let(:container) { create(:container, department: department) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } before do @@ -243,7 +243,7 @@ describe 'GET #export_entries' do let(:department) { create(:department) } let(:container) { create(:container, department: department) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } context 'with authorized users' do let(:user) { create(:user, :axis_mundi) } @@ -514,7 +514,7 @@ describe 'GET #export_round_results' do let(:department) { create(:department) } let(:container) { create(:container, department: department) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:judging_round) { create(:judging_round, contest_instance: contest_instance, completed: true) } diff --git a/spec/controllers/entry_rankings_controller_spec.rb b/spec/controllers/entry_rankings_controller_spec.rb index 2b999790..fa9ece59 100644 --- a/spec/controllers/entry_rankings_controller_spec.rb +++ b/spec/controllers/entry_rankings_controller_spec.rb @@ -2,7 +2,7 @@ RSpec.describe EntryRankingsController, type: :controller do let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:judging_round) { create(:judging_round, contest_instance: contest_instance) } let(:entry) { create(:entry, contest_instance: contest_instance) } diff --git a/spec/controllers/judge_dashboard_controller_spec.rb b/spec/controllers/judge_dashboard_controller_spec.rb index 821e7626..5274ee6a 100644 --- a/spec/controllers/judge_dashboard_controller_spec.rb +++ b/spec/controllers/judge_dashboard_controller_spec.rb @@ -2,7 +2,7 @@ RSpec.describe JudgeDashboardController, type: :controller do let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } # Start at a known point in time before(:all) do diff --git a/spec/controllers/judging_assignments_controller_spec.rb b/spec/controllers/judging_assignments_controller_spec.rb index 3ecdebc4..b0b818f6 100644 --- a/spec/controllers/judging_assignments_controller_spec.rb +++ b/spec/controllers/judging_assignments_controller_spec.rb @@ -2,7 +2,7 @@ RSpec.describe JudgingAssignmentsController, type: :controller do let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:admin) { create(:user) } let!(:judge_role) { create(:role, kind: 'Judge') } diff --git a/spec/controllers/judging_rounds_controller_spec.rb b/spec/controllers/judging_rounds_controller_spec.rb index 240bad03..ea25c104 100644 --- a/spec/controllers/judging_rounds_controller_spec.rb +++ b/spec/controllers/judging_rounds_controller_spec.rb @@ -2,7 +2,7 @@ RSpec.describe JudgingRoundsController, type: :controller do let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:judging_round) { create(:judging_round, contest_instance: contest_instance) } let(:admin) { create(:user) } diff --git a/spec/features/bulk_contest_instance_creation_spec.rb b/spec/features/bulk_contest_instance_creation_spec.rb index 95fca3ad..956474c3 100644 --- a/spec/features/bulk_contest_instance_creation_spec.rb +++ b/spec/features/bulk_contest_instance_creation_spec.rb @@ -11,8 +11,8 @@ end it "shows only contest descriptions that have existing instances" do - description1 = create(:contest_description, container: @container) - description2 = create(:contest_description, container: @container) + description1 = create(:contest_description, :active, container: @container) + description2 = create(:contest_description, :active, container: @container) create(:contest_instance, contest_description: description1) create(:contest_instance, contest_description: description2) @@ -22,13 +22,13 @@ expect(page).to have_content(description2.name) # Create a new contest description without instances - new_description = create(:contest_description, container: @container) + new_description = create(:contest_description, :active, container: @container) expect(page).to have_no_content(new_description.name) end it "allows selection of multiple contest descriptions" do - description1 = create(:contest_description, container: @container) - description2 = create(:contest_description, container: @container) + description1 = create(:contest_description, :active, container: @container) + description2 = create(:contest_description, :active, container: @container) create(:contest_instance, contest_description: description1) create(:contest_instance, contest_description: description2) @@ -42,7 +42,7 @@ end it "requires date selection" do - description = create(:contest_description, container: @container) + description = create(:contest_description, :active, container: @container) create(:contest_instance, contest_description: description) visit new_container_bulk_contest_instance_path(@container) @@ -55,7 +55,7 @@ end it "creates new instances based on most recent existing instances" do - description = create(:contest_description, container: @container) + description = create(:contest_description, :active, container: @container) existing_instance = create(:contest_instance, contest_description: description) new_open_date = 1.month.from_now new_close_date = 2.months.from_now @@ -78,7 +78,7 @@ end it "validates date ranges" do - description = create(:contest_description, container: @container) + description = create(:contest_description, :active, container: @container) create(:contest_instance, contest_description: description) visit new_container_bulk_contest_instance_path(@container) diff --git a/spec/features/judging_round_selection_spec.rb b/spec/features/judging_round_selection_spec.rb index ac736a73..85afd56c 100644 --- a/spec/features/judging_round_selection_spec.rb +++ b/spec/features/judging_round_selection_spec.rb @@ -2,7 +2,7 @@ RSpec.describe 'Judging Round Selection', type: :system do let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:judging_round) do create(:judging_round, diff --git a/spec/mailers/results_mailer_spec.rb b/spec/mailers/results_mailer_spec.rb index 505e5b6b..6b02f3b2 100644 --- a/spec/mailers/results_mailer_spec.rb +++ b/spec/mailers/results_mailer_spec.rb @@ -7,7 +7,7 @@ let(:profile) { create(:profile, user: user) } let(:department) { create(:department) } let(:container) { create(:container, name: 'Test Container', department: department, contact_email: 'contact@example.com') } - let(:contest_description) { create(:contest_description, name: 'Test Contest', container: container) } + let(:contest_description) { create(:contest_description, :active, name: 'Test Contest', container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description, date_open: 2.months.ago, date_closed: 1.month.ago) } let(:category) { create(:category, kind: 'Poetry') } let(:entry) { create(:entry, title: 'Test Entry', profile: profile, contest_instance: contest_instance, category: category, pen_name: 'Writer Pen') } diff --git a/spec/models/container_spec.rb b/spec/models/container_spec.rb index e2ab38e9..524dc457 100644 --- a/spec/models/container_spec.rb +++ b/spec/models/container_spec.rb @@ -162,12 +162,22 @@ end it 'excludes entries from inactive contest descriptions' do - inactive_desc = create(:contest_description, container: container, active: false) - inactive_instance = create(:contest_instance, contest_description: inactive_desc, active: true) - create(:entry, profile: create(:profile, campus: campus1), contest_instance: inactive_instance) + # Create an active contest description with an active instance and entry + active_desc = create(:contest_description, container: container, active: true) + active_instance = create(:contest_instance, contest_description: active_desc, active: true) + create(:entry, profile: create(:profile, campus: campus1), contest_instance: active_instance) + # Verify the entry is included initially summary = container.entries_summary - expect(summary.find { |s| s.campus_descr == 'Campus A' }.entry_count).to eq(2) + expect(summary.find { |s| s.campus_descr == 'Campus A' }.entry_count).to eq(3) # 2 from setup + 1 new + + # Deactivate both the instance and description (business rule: must deactivate instance first) + active_instance.update!(active: false) + active_desc.update!(active: false) + + # Now verify that entries from the deactivated contest description are excluded + summary = container.entries_summary + expect(summary.find { |s| s.campus_descr == 'Campus A' }.entry_count).to eq(2) # Back to original 2 end end diff --git a/spec/models/contest_description_spec.rb b/spec/models/contest_description_spec.rb index 3223f01c..f7174550 100644 --- a/spec/models/contest_description_spec.rb +++ b/spec/models/contest_description_spec.rb @@ -64,4 +64,27 @@ end end end + + describe 'deactivation with active instances' do + let(:container) { create(:container) } + let!(:description) { create(:contest_description, container: container, active: true) } + let!(:active_instance) { create(:contest_instance, contest_description: description, active: true) } + let!(:inactive_instance) { create(:contest_instance, contest_description: description, active: false) } + + it 'is not valid to deactivate if any contest_instance is active' do + description.active = false + expect(description).not_to be_valid + expect(description.errors[:active]).to include('Cannot deactivate contest description while instances are active.') + end + + it 'is valid to deactivate if all contest_instances are inactive' do + active_instance.update!(active: false) + description.active = false + expect(description).to be_valid + end + + it 'returns only active contest_instances from #active_contest_instances' do + expect(description.active_contest_instances).to contain_exactly(active_instance) + end + end end diff --git a/spec/models/contest_instance_spec.rb b/spec/models/contest_instance_spec.rb index 90bcc15f..845257ad 100644 --- a/spec/models/contest_instance_spec.rb +++ b/spec/models/contest_instance_spec.rb @@ -252,4 +252,19 @@ end end end + + describe 'activation with inactive contest_description' do + let(:description) { create(:contest_description, active: false) } + let(:instance) { build(:contest_instance, contest_description: description, active: true) } + + it 'is not valid to activate if contest_description is inactive' do + expect(instance).not_to be_valid + expect(instance.errors[:active]).to include('Cannot activate a contest instance when its contest description is inactive.') + end + + it 'is valid to activate if contest_description is active' do + description.update!(active: true) + expect(instance).to be_valid + end + end end diff --git a/spec/policies/contest_instance_policy_spec.rb b/spec/policies/contest_instance_policy_spec.rb index 03a6ef6c..03c384b7 100644 --- a/spec/policies/contest_instance_policy_spec.rb +++ b/spec/policies/contest_instance_policy_spec.rb @@ -4,7 +4,7 @@ subject { described_class.new(user, contest_instance) } let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:container_admin_role) { create(:role, kind: 'Collection Administrator') } let(:axis_mundi_role) { create(:role, kind: 'Axis Mundi') } diff --git a/spec/system/email_preferences_spec.rb b/spec/system/email_preferences_spec.rb index 9621dcca..edf4962a 100644 --- a/spec/system/email_preferences_spec.rb +++ b/spec/system/email_preferences_spec.rb @@ -4,7 +4,7 @@ let(:department) { create(:department, name: 'Test Department') } let(:admin_user) { create(:user, :axis_mundi) } let(:container) { create(:container, name: 'Test Container', department: department, contact_email: 'admin@example.com') } - let(:contest_description) { create(:contest_description, name: 'Test Contest', container: container) } + let(:contest_description) { create(:contest_description, :active, name: 'Test Contest', container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description, date_open: 4.months.ago, date_closed: 3.months.ago) } # Create applicant user and entry diff --git a/spec/system/judge_dashboard_spec.rb b/spec/system/judge_dashboard_spec.rb index b121c3e5..1b45b40d 100644 --- a/spec/system/judge_dashboard_spec.rb +++ b/spec/system/judge_dashboard_spec.rb @@ -14,7 +14,7 @@ def last_entry_title let(:judge) { create(:user, first_name: 'John', last_name: 'Doe', email: 'judge+gmail.com@umich.edu') } let(:judge_role) { create(:role, :judge) } let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container, name: 'Test Contest') } + let(:contest_description) { create(:contest_description, :active, container: container, name: 'Test Contest') } let(:contest_instance) { create(:contest_instance, contest_description: contest_description, date_open: 2.months.ago, @@ -120,7 +120,7 @@ def last_entry_title it 'only shows assigned contests' do # Create another contest that the judge is not assigned to other_container = create(:container) - other_contest_description = create(:contest_description, container: other_container, name: 'Other Contest') + other_contest_description = create(:contest_description, :active, container: other_container, name: 'Other Contest') unassigned_contest = create(:contest_instance, contest_description: other_contest_description, date_open: 2.months.ago, @@ -163,7 +163,7 @@ def last_entry_title context 'when attempting to access unassigned contest data' do let(:unassigned_container) { create(:container) } - let(:unassigned_contest_description) { create(:contest_description, container: unassigned_container, name: 'Unassigned Contest') } + let(:unassigned_contest_description) { create(:contest_description, :active, container: unassigned_container, name: 'Unassigned Contest') } let(:unassigned_contest) { create(:contest_instance, contest_description: unassigned_contest_description, date_open: 2.months.ago, diff --git a/spec/system/judge_management_spec.rb b/spec/system/judge_management_spec.rb index 820d2ea6..c3a3718c 100644 --- a/spec/system/judge_management_spec.rb +++ b/spec/system/judge_management_spec.rb @@ -2,7 +2,7 @@ RSpec.describe 'Judge Management', type: :system do let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:admin_user) { create(:user) } let(:admin_role) { create(:role, kind: 'Collection Administrator') } diff --git a/spec/system/judge_round_visibility_spec.rb b/spec/system/judge_round_visibility_spec.rb index 81dbde3b..f6ff55e9 100644 --- a/spec/system/judge_round_visibility_spec.rb +++ b/spec/system/judge_round_visibility_spec.rb @@ -4,7 +4,7 @@ include ApplicationHelper let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description, date_open: 5.days.ago, diff --git a/spec/system/judging_results_email_spec.rb b/spec/system/judging_results_email_spec.rb index 6ca16d80..2c6f6ef9 100644 --- a/spec/system/judging_results_email_spec.rb +++ b/spec/system/judging_results_email_spec.rb @@ -18,7 +18,7 @@ let(:department) { create(:department, name: 'Test Department') } let(:admin_user) { create(:user, :axis_mundi) } let(:container) { create(:container, name: 'Test Container', department: department, contact_email: 'admin@example.com') } - let(:contest_description) { create(:contest_description, name: 'Test Contest', container: container) } + let(:contest_description) { create(:contest_description, :active, name: 'Test Contest', container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description, date_open: 4.months.ago, date_closed: 3.months.ago) } # Create applicant user and entry diff --git a/spec/system/judging_rounds_spec.rb b/spec/system/judging_rounds_spec.rb index 2a3bd94a..287a1d30 100644 --- a/spec/system/judging_rounds_spec.rb +++ b/spec/system/judging_rounds_spec.rb @@ -5,7 +5,7 @@ let(:admin) { create(:user) } let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description, date_open: 2.days.ago, diff --git a/spec/system/profile_access_spec.rb b/spec/system/profile_access_spec.rb index 142af47a..c273754f 100644 --- a/spec/system/profile_access_spec.rb +++ b/spec/system/profile_access_spec.rb @@ -2,7 +2,7 @@ RSpec.describe 'Profile Access', type: :system do let(:container) { create(:container) } - let(:contest_description) { create(:contest_description, container: container) } + let(:contest_description) { create(:contest_description, :active, container: container) } let(:contest_instance) { create(:contest_instance, contest_description: contest_description) } let(:profile) { create(:profile) } let(:profile_owner) { profile.user }