decider = app(DoublerDecision::class); $this->entryScribe = app(CreateEntry::class); $this->scoreFaker = app(FakeScoresForEntry::class); // Setup doubler $this->scoringGuide = ScoringGuide::factory()->create(); $this->judge1 = User::factory()->create(); $this->judge2 = User::factory()->create(); $this->room = Room::factory()->create(); $this->room->addJudge($this->judge1); $this->room->addJudge($this->judge2); $this->audition1 = Audition::factory()->create( [ 'minimum_grade' => 9, 'maximum_grade' => 12, 'scoring_guide_id' => $this->scoringGuide->id, 'room_id' => $this->room->id, 'order_in_room' => 1, 'name' => 'Flute', ]); $this->audition2 = Audition::factory()->create( [ 'minimum_grade' => 9, 'maximum_grade' => 12, 'scoring_guide_id' => $this->scoringGuide->id, 'room_id' => $this->room->id, 'order_in_room' => 2, 'event_id' => $this->audition1->event_id, 'name' => 'Trumpet', ]); $this->audition3 = Audition::factory()->create( [ 'minimum_grade' => 9, 'maximum_grade' => 12, 'scoring_guide_id' => $this->scoringGuide->id, 'room_id' => $this->room->id, 'order_in_room' => 3, 'event_id' => $this->audition1->event_id, 'name' => 'Trombone', ]); $this->otherEventAudition = Audition::factory()->create([ 'minimum_grade' => 9, 'maximum_grade' => 12, 'scoring_guide_id' => $this->scoringGuide->id, 'room_id' => $this->room->id, 'order_in_room' => 4, 'name' => 'Jazz Trumpet', ]); $this->student = Student::factory()->create([ 'grade' => 9, 'first_name' => 'Percy', 'last_name' => 'Grainger', ]); $this->entry1 = $this->entryScribe->createEntry($this->student, $this->audition1); $this->entry2 = $this->entryScribe->createEntry($this->student, $this->audition2); $this->entry3 = $this->entryScribe->createEntry($this->student, $this->audition3); $this->otherEventEntry = $this->entryScribe->createEntry($this->student, $this->otherEventAudition); }); it('is invokable', function () { ($this->scoreFaker)($this->entry1); ($this->scoreFaker)($this->entry2); ($this->scoreFaker)($this->entry3); ($this->decider)($this->entry2, 'decline'); expect($this->entry2->hasFlag('declined'))->toBeTruthy(); }); it('cannot be called with an invalid decision', function () { ($this->scoreFaker)($this->entry1); ($this->scoreFaker)($this->entry2); ($this->scoreFaker)($this->entry3); ($this->decider)($this->entry2, 'idunno'); })->throws(AuditionAdminException::class, 'Invalid decision specified'); it('can decline an entry', function () { ($this->scoreFaker)($this->entry1); ($this->scoreFaker)($this->entry2); ($this->scoreFaker)($this->entry3); $this->decider->decline($this->entry2); expect($this->entry2->hasFlag('declined'))->toBeTruthy(); }); it('will not decline an entry with no scores', function () { $this->decider->decline($this->entry2); })->throws(AuditionAdminException::class, 'Cannot decline an unscored entry'); it('will not decline an entry that is already declined', function () { ($this->scoreFaker)($this->entry2); $this->entry2->addFlag('declined'); $this->decider->decline($this->entry2); })->throws(AuditionAdminException::class, 'Entry 2 is already declined'); it('will not decline an entry in a published event', function () { ($this->scoreFaker)($this->entry2); $this->audition2->addFlag('seats_published'); $this->entry2->refresh(); $this->decider->decline($this->entry2); })->throws(AuditionAdminException::class, 'Cannot decline an entry in an audition where seats are published'); it('accepts an entry and declines others in the same event', function () { ($this->scoreFaker)($this->entry1); ($this->scoreFaker)($this->entry2); ($this->scoreFaker)($this->entry3); $this->decider->accept($this->entry2); $this->entry1->refresh(); $this->entry2->refresh(); $this->entry3->refresh(); expect($this->entry1->hasFlag('declined'))->toBeTruthy() ->and($this->entry3->hasFlag('declined'))->toBeTruthy(); $doubler = Doubler::findDoubler($this->entry2->student_id, $this->audition2->event_id); expect($doubler->accepted_entry)->toBe($this->entry2->id); }); it('will not accept an entry into an event with seats published', function () { ($this->scoreFaker)($this->entry1); ($this->scoreFaker)($this->entry2); ($this->scoreFaker)($this->entry3); $this->audition2->addFlag('seats_published'); $this->audition2->refresh(); $this->entry2->refresh(); $this->decider->accept($this->entry2); $this->entry1->refresh(); $this->entry2->refresh(); $this->entry3->refresh(); expect($this->entry1->hasFlag('declined'))->toBeTruthy() ->and($this->entry3->hasFlag('declined'))->toBeTruthy(); $doubler = Doubler::findDoubler($this->entry2->student_id, $this->audition2->event_id); expect($doubler->accepted_entry)->toBe($this->entry2->id); })->throws(AuditionAdminException::class, 'Cannot accept an entry in an audition where seats are published'); it('will not accept an entry that has already been declined', function () { ($this->scoreFaker)($this->entry1); ($this->scoreFaker)($this->entry2); ($this->scoreFaker)($this->entry3); $this->entry2->addFlag('declined'); $this->decider->accept($this->entry2); $this->entry1->refresh(); $this->entry2->refresh(); $this->entry3->refresh(); expect($this->entry1->hasFlag('declined'))->toBeTruthy() ->and($this->entry3->hasFlag('declined'))->toBeTruthy(); $doubler = Doubler::findDoubler($this->entry2->student_id, $this->audition2->event_id); expect($doubler->accepted_entry)->toBe($this->entry2->id); })->throws(AuditionAdminException::class, 'Entry 2 is already declined'); it('when accepting a seat, does not decline no_show or failed_prelim entries', function () { ($this->scoreFaker)($this->entry2); $this->entry1->addFlag('no_show'); $this->entry3->addFlag('failed_prelim'); $this->decider->accept($this->entry2); $this->entry1->refresh(); $this->entry2->refresh(); $this->entry3->refresh(); expect($this->entry1->hasFlag('declined'))->toBeFalsy() ->and($this->entry3->hasFlag('declined'))->toBeFalsy(); $doubler = Doubler::findDoubler($this->entry2->student_id, $this->audition2->event_id); expect($doubler->accepted_entry)->toBe($this->entry2->id); }); it('when accepting an entry, does not decline seats in other events', function () { ($this->scoreFaker)($this->entry1); ($this->scoreFaker)($this->entry2); ($this->scoreFaker)($this->entry3); $this->decider->accept($this->entry2); $this->entry1->refresh(); $this->entry2->refresh(); $this->entry3->refresh(); expect($this->otherEventEntry->hasFlag('declined'))->toBeFalsy(); }); it('will not accept an entry if the student has unscored entries', function () { $this->decider->accept($this->entry2); })->throws(AuditionAdminException::class, 'Cannot accept seating for Percy Grainger because student has unscored entries');