diff --git a/app/models/invitation_manager.rb b/app/models/invitation_manager.rb index 53838c50d..60cc0c571 100644 --- a/app/models/invitation_manager.rb +++ b/app/models/invitation_manager.rb @@ -62,10 +62,10 @@ def log_event_meeting_invitation_failure(context, member, error) end def chapter_students(chapter) - Member.in_group(chapter.groups.students) + Member.in_group(chapter.groups.students).distinct end def chapter_coaches(chapter) - Member.in_group(chapter.groups.coaches) + Member.in_group(chapter.groups.coaches).distinct end end diff --git a/spec/models/invitation_manager_deduplication_spec.rb b/spec/models/invitation_manager_deduplication_spec.rb new file mode 100644 index 000000000..22438b5b6 --- /dev/null +++ b/spec/models/invitation_manager_deduplication_spec.rb @@ -0,0 +1,69 @@ +require 'rails_helper' + +RSpec.describe InvitationManager do + subject(:manager) { InvitationManager.new } + + let(:chapter) { Fabricate(:chapter) } + let(:member_in_both_groups) { Fabricate(:member, accepted_toc_at: Time.zone.now) } + + describe '#chapter_students' do + context 'when a member has multiple subscriptions to the same group type' do + before do + students_group1 = Fabricate(:group, name: 'Students', chapter: chapter) + students_group2 = Fabricate(:group, name: 'Students', chapter: chapter) + students_group1.members << member_in_both_groups + students_group2.members << member_in_both_groups + end + + it 'returns unique members' do + result = manager.send(:chapter_students, chapter) + + expect(result.count).to eq(1) + expect(result).to contain_exactly(member_in_both_groups) + end + end + end + + describe '#chapter_coaches' do + context 'when a member has multiple subscriptions to the same group type' do + before do + coaches_group1 = Fabricate(:group, name: 'Coaches', chapter: chapter) + coaches_group2 = Fabricate(:group, name: 'Coaches', chapter: chapter) + coaches_group1.members << member_in_both_groups + coaches_group2.members << member_in_both_groups + end + + it 'returns unique members' do + result = manager.send(:chapter_coaches, chapter) + + expect(result.count).to eq(1) + expect(result).to contain_exactly(member_in_both_groups) + end + end + end + + describe 'sending invitations to members in both students and coaches groups' do + let(:workshop) { Fabricate(:workshop, chapter: chapter) } + let(:students_group) { Fabricate(:group, name: 'Students', chapter: chapter) } + let(:coaches_group) { Fabricate(:group, name: 'Coaches', chapter: chapter) } + + before do + students_group.members << member_in_both_groups + coaches_group.members << member_in_both_groups + end + + it 'sends one invitation per role when audience is everyone' do + expect(WorkshopInvitation).to receive(:find_or_create_by) + .with(workshop: workshop, member: member_in_both_groups, role: 'Student') + .and_call_original + .once + + expect(WorkshopInvitation).to receive(:find_or_create_by) + .with(workshop: workshop, member: member_in_both_groups, role: 'Coach') + .and_call_original + .once + + manager.send_workshop_emails(workshop, 'everyone') + end + end +end