auditionadmin/tests/Feature/app/Actions/Entries/UpdateEntryTest.php

236 lines
11 KiB
PHP

<?php
/** @noinspection PhpUnhandledExceptionInspection */
use App\Actions\Development\FakeScoresForEntry;
use App\Actions\Entries\UpdateEntry;
use App\Exceptions\AuditionAdminException;
use App\Models\Audition;
use App\Models\AuditionFlag;
use App\Models\AuditLogEntry;
use App\Models\Entry;
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->entryScribe = app(UpdateEntry::class);
$this->audition = Audition::factory()->create(
[
'minimum_grade' => 9, 'maximum_grade' => 10,
'name' => 'Flute',
]);
$this->student = Student::factory()->create(['grade' => 9]);
$this->entry = Entry::factory()->create([
'student_id' => $this->student->id,
'audition_id' => $this->audition->id,
]);
});
it('throws an exception when an invalid entry is provided', function () {
($this->entryScribe)(35, []);
})->throws(AuditionAdminException::class, 'Invalid entry provided');
it('throws an exception when a non-existent entry is provided', function () {
$newEntry = Entry::factory()->make();
($this->entryScribe)($newEntry, []);
})->throws(AuditionAdminException::class, 'Invalid entry provided');
it('will not modify an entry in an audition with published seats', function () {
$this->entry->audition->addFlag('seats_published');
$newAudition = Audition::factory()->create(['event_id' => $this->entry->audition->event_id]);
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
})->throws(AuditionAdminException::class,
'Cannot change the audition for an entry where seating for that entry\'s current audition is published');
it('will not modify an entry in an audition with published advancement', function () {
$this->entry->audition->addFlag('advancement_published');
$newAudition = Audition::factory()->create(['event_id' => $this->entry->audition->event_id]);
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
})->throws(AuditionAdminException::class,
'Cannot change the audition for an entry where advancement for that entry\'s current audition is published');
it('will not move an entry to an audition with published seating', function () {
$newAudition = Audition::factory()->create(['event_id' => $this->entry->audition->event_id]);
$newAudition->addFlag('seats_published');
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
})->throws(AuditionAdminException::class, 'Cannot change the entry to an audition with published seating');
it('will not move an entry to an audition with published advancement', function () {
$newAudition = Audition::factory()->create(['event_id' => $this->entry->audition->event_id]);
$newAudition->addFlag('advancement_published');
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
})->throws(AuditionAdminException::class, 'Cannot change the entry to an audition with published advancement');
it('will not move to an audition for which the student is too young', function () {
$newAudition = Audition::factory()->create([
'event_id' => $this->entry->audition->event_id,
'minimum_grade' => 10,
'maximum_grade' => 11,
]);
$this->entry->student->update(['grade' => 9]);
dump('student grade: '.$this->entry->student->grade);
dump('new audition minimum: '.$newAudition->minimum_grade);
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
})->throws(AuditionAdminException::class, 'The student is too young to enter that audition');
it('will not move to an audition for which the student is too old', function () {
$newAudition = Audition::factory()->create([
'event_id' => $this->entry->audition->event_id,
'maximum_grade' => 8,
'minimum_grade' => 7,
]);
$this->entry->student->update(['grade' => 9]);
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
})->throws(AuditionAdminException::class, 'The student is too old to enter that audition');
it('will not change auditions for an entry with scores', function () {
$scoreFaker = app(FakeScoresForEntry::class);
$newAudition = Audition::factory()->create([
'event_id' => $this->entry->audition->event_id,
'minimum_grade' => 9,
'maximum_grade' => 10,
]);
$scoringGuide = ScoringGuide::factory()->create();
$judge1 = User::factory()->create();
$judge2 = User::factory()->create();
$room = Room::factory()->create();
$room->addJudge($judge1);
$room->addJudge($judge2);
$this->entry->audition->update([
'scoring_guide_id' => $scoringGuide->id,
'room_id' => $room->id,
'order_in_room' => 1,
]);
$scoreFaker($this->entry);
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
})->throws(AuditionAdminException::class, 'Cannot change the audition for an entry with scores');
it(('will not change the audition to one in which the student is already entered'), function () {
$newAudition = Audition::factory()->create(['minimum_grade' => 9, 'maximum_grade' => 10]);
Entry::create([
'student_id' => $this->student->id,
'audition_id' => $newAudition->id,
]);
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
})->throws(AuditionAdminException::class, 'That student is already entered in that audition');
it('will not set a draw number if the new audition is not drawn', function () {
$newAudition = Audition::factory()->create(['minimum_grade' => 9, 'maximum_grade' => 10]);
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
$this->entry->refresh();
expect($this->entry->draw_number)->toBeNull();
});
it('will assign the next draw number if the new audition is drawn', function () {
$newAudition = Audition::factory()
->has(Entry::factory()->count(5))
->create(['minimum_grade' => 9, 'maximum_grade' => 10]);
AuditionFlag::create(['audition_id' => $newAudition->id, 'flag_name' => 'drawn']);
$n = 1;
foreach ($newAudition->entries as $entry) {
$entry->update(['draw_number' => $n]);
$n++;
}
($this->entryScribe)($this->entry, ['audition_id' => $newAudition->id]);
expect($this->entry->draw_number)->toBe($n);
});
it('can change and entries audition', function () {
$newAudition = Audition::factory()->create(['minimum_grade' => 9, 'maximum_grade' => 10]);
($this->entryScribe)($this->entry, ['audition' => $newAudition]);
$this->entry->refresh();
$freshEntry = Entry::find($this->entry->id);
expect($freshEntry->audition_id)->toBe($newAudition->id);
});
it('can remove forAdvancement from the entry', function () {
($this->entryScribe)($this->entry, ['for_advancement' => false]);
expect($this->entry->for_advancement)->toBeFalsy();
});
it('can add forAdvancement to the entry', function () {
$this->entry->update(['for_advancement' => false]);
expect($this->entry->for_advancement)->toBeFalsy();
($this->entryScribe)($this->entry, ['for_advancement' => true]);
expect($this->entry->for_advancement)->toBeTruthy();
});
it('cannot remove forAdvancement if advancement is published', function () {
$this->entry->audition->addFlag('advancement_published');
($this->entryScribe)($this->entry, ['for_advancement' => false]);
})->throws(AuditionAdminException::class,
'Cannot remove advancement from an entry in an audition where advancement is published');
it('cannot add forAdvancement if advancement is published', function () {
$this->entry->update(['for_advancement' => false]);
expect($this->entry->for_advancement)->toBeFalsy();
$this->entry->audition->addFlag('advancement_published');
($this->entryScribe)($this->entry, ['for_advancement' => true]);
})->throws(AuditionAdminException::class,
'Cannot add advancement to an entry in an audition where advancement is published');
it('can remove forSeating from the entry', function () {
($this->entryScribe)($this->entry, ['for_seating' => false]);
expect($this->entry->for_seating)->toBeFalsy();
});
it('can add forSeating to the entry', function () {
$this->entry->update(['for_seating' => false]);
expect($this->entry->for_seating)->toBeFalsy();
($this->entryScribe)($this->entry, ['for_seating' => true]);
expect($this->entry->for_seating)->toBeTruthy();
});
it('cannot remove forSeating if seating is published', function () {
$this->entry->audition->addFlag('seats_published');
($this->entryScribe)($this->entry, ['for_seating' => false]);
})->throws(AuditionAdminException::class,
'Cannot remove seating from an entry in an audition where seats are published');
it('cannot add forSeating if seating is published', function () {
$this->entry->update(['for_seating' => false]);
expect($this->entry->for_seating)->toBeFalsy();
$this->entry->audition->addFlag('seats_published');
($this->entryScribe)($this->entry, ['for_seating' => true]);
})->throws(AuditionAdminException::class,
'Cannot add seating to an entry in an audition where seats are published');
it('logs changes', function () {
actAsAdmin();
$originalEntry = Entry::find($this->entry->id);
$newAudition = Audition::factory()->create(['minimum_grade' => 9, 'maximum_grade' => 10, 'name' => 'Alphorn']);
($this->entryScribe)($this->entry, ['audition' => $newAudition]);
$logEntry = AuditLogEntry::latest()->first();
expect($logEntry->affected['auditions'])->toEqual([$originalEntry->audition_id, $newAudition->id])
->and($logEntry->affected['entries'])->toEqual([$this->entry->id])
->and($logEntry->affected['students'])->toEqual([$this->entry->student_id])
->and($logEntry->affected['schools'])->toEqual([$this->entry->student->school_id])
->and($logEntry->message)->toEqual('Changed entry '.$this->entry->id.' from '.$originalEntry->audition->name.' to '.$newAudition->name.'<br>');
});
it('will not change to a non-existent audition', function () {
$newAudition = Audition::factory()->make();
($this->entryScribe)($this->entry, ['audition' => $newAudition]);
})->throws(AuditionAdminException::class, 'Invalid audition provided');
it('wont change if we give it the same audition', function () {
($this->entryScribe)($this->entry, ['audition' => $this->entry->audition]);
expect($this->entry->audition_id)->toBe($this->entry->audition->id);
});
it('wont change seating if we give the same value', function () {
($this->entryScribe)($this->entry, ['for_seating' => 1]);
expect($this->entry->for_seating)->toBe($this->entry->for_seating);
});
it('wont change advancement if we give the same value', function () {
($this->entryScribe)($this->entry, ['for_advancement' => 1]);
expect($this->entry->for_advancement)->toBe($this->entry->for_advancement);
});