192 lines
7.7 KiB
PHP
192 lines
7.7 KiB
PHP
<?php
|
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */
|
|
|
|
use App\Actions\Development\FakeScoresForEntry;
|
|
use App\Actions\Entries\CreateEntry;
|
|
use App\Actions\Entries\DoublerDecision;
|
|
use App\Exceptions\AuditionAdminException;
|
|
use App\Models\Audition;
|
|
use App\Models\Doubler;
|
|
use App\Models\Room;
|
|
use App\Models\ScoringGuide;
|
|
use App\Models\Student;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$this->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');
|