From a2e3773783ace86dccd5ef61118c6917d7b36242 Mon Sep 17 00:00:00 2001 From: Morgan Roderick Date: Fri, 9 Oct 2026 08:45:04 +0200 Subject: [PATCH] test: pin cross-role waiting list promotion Promotion on reject filters by the cancelling invitation's role via WaitingList.where_role, so an older entry for the other role must never be promoted when a seat of one role frees up. Nothing pinned that. Pin it on both levels: the model (next_spot returns nothing for a Student seat while only an older Coach entry is waitlisted) and the controller (a Coach waitlist entry's invitation keeps attending nil and the waitlist is unchanged when a Student cancels). --- .../workshop_invitation_controller_spec.rb | 21 +++++++++++++++++++ spec/models/waiting_list_spec.rb | 9 ++++++++ 2 files changed, 30 insertions(+) diff --git a/spec/controllers/workshop_invitation_controller_spec.rb b/spec/controllers/workshop_invitation_controller_spec.rb index 21fbc136d..bc957c6e4 100644 --- a/spec/controllers/workshop_invitation_controller_spec.rb +++ b/spec/controllers/workshop_invitation_controller_spec.rb @@ -170,6 +170,27 @@ expect(waitlisted_invitation.reload.attending).to be true end end + + context 'when a coach is waitlisted and a student seat frees up' do + let(:coach) { Fabricate(:coach) } + let(:coach_invitation) { Fabricate(:coach_workshop_invitation, workshop:, member: coach) } + + before do + invitation.update!(attending: true) + WaitingList.add(coach_invitation, auto_rsvp: true) + end + + it 'does not promote the coach invitation' do + post :reject, params: { id: invitation.token } + + expect(coach_invitation.reload.attending).to be_nil + end + + it 'leaves the waiting list unchanged' do + expect { post :reject, params: { id: invitation.token } } + .not_to change(WaitingList, :count) + end + end end describe 'PATCH #update' do diff --git a/spec/models/waiting_list_spec.rb b/spec/models/waiting_list_spec.rb index df731164b..051c27ddd 100644 --- a/spec/models/waiting_list_spec.rb +++ b/spec/models/waiting_list_spec.rb @@ -24,6 +24,15 @@ expect(described_class.next_spot(workshop, 'Student').invitation).to eq(invitation) end + + it 'ignores an older entry for another role' do + coach_invitation = Fabricate(:coach_workshop_invitation, workshop:, member: Fabricate(:coach)) + described_class.add(coach_invitation) + + expect(described_class.next_spot(workshop, 'Student')).to be_nil + expect(coach_invitation.reload.attending).to be_nil + expect(described_class.by_workshop(workshop).count).to eq(1) + end end end