Tets for BonusScoreController

This commit is contained in:
Matt Young 2025-07-14 23:36:41 -05:00
parent 5e9c7a5084
commit 27e68ab233
4 changed files with 213 additions and 3 deletions

View File

@ -4,7 +4,7 @@ namespace App\Http\Controllers\Tabulation;
use App\Actions\Tabulation\EnterBonusScore; use App\Actions\Tabulation\EnterBonusScore;
use App\Actions\Tabulation\GetBonusScoreRelatedEntries; use App\Actions\Tabulation\GetBonusScoreRelatedEntries;
use App\Exceptions\ScoreEntryException; use App\Exceptions\AuditionAdminException;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\BonusScore; use App\Models\BonusScore;
use App\Models\Entry; use App\Models\Entry;
@ -73,7 +73,7 @@ class BonusScoreController extends Controller
// Set the new score // Set the new score
try { try {
$saveBonusScore($judge, $entry, $validData['score']); $saveBonusScore($judge, $entry, $validData['score']);
} catch (ScoreEntryException $ex) { } catch (AuditionAdminException $ex) {
DB::rollBack(); DB::rollBack();
return redirect()->route('bonus-scores.entryBonusScoreSheet', return redirect()->route('bonus-scores.entryBonusScoreSheet',

View File

@ -14,6 +14,12 @@ class BonusScoreObserver
{ {
$calculator = app(TotalEntryScores::class); $calculator = app(TotalEntryScores::class);
$calculator($bonusScore->entry, true); $calculator($bonusScore->entry, true);
$message = 'Bonus Score Entered.';
$message .= '<br>Judge: '.$bonusScore->judge->full_name().' <'.$bonusScore->judge->email.'>';
$message .= '<br>Score: '.$bonusScore->score;
$message .= '<br>Scored Audition: '.$bonusScore->originallyScoredEntry->audition->name;
$affected = ['auditions' => [$bonusScore->entry->audition_id]];
auditionLog($message, $affected);
} }
/** /**

View File

@ -190,7 +190,7 @@ test('it correctly brings in bonus scores', function () {
} }
$bonusScore = BonusScore::create([ $bonusScore = BonusScore::create([
'entry_id' => $this->entry->id, 'entry_id' => $this->entry->id,
'user_id' => $this->judge1, 'user_id' => $this->judge1->id,
'originally_scored_entry' => $this->entry->id, 'originally_scored_entry' => $this->entry->id,
'score' => 6, 'score' => 6,
]); ]);

View File

@ -0,0 +1,204 @@
<?php
use App\Models\Audition;
use App\Models\BonusScore;
use App\Models\BonusScoreDefinition;
use App\Models\Entry;
use App\Models\Event;
use App\Models\ScoringGuide;
use App\Models\Student;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
describe('BonusScoreController::chooseEntry', function () {
it('does not allow access to guests or normal users', function () {
$this->get(route('bonus-scores.chooseEntry'))->assertRedirect(route('home'));
actAsNormal();
$this->get(route('bonus-scores.chooseEntry'))->assertRedirect(route('dashboard'));
});
it('provides a form to enter an entry id to select an entry to score', function () {
actAsTab();
$this->get(route('bonus-scores.chooseEntry'))->assertOk();
actAsAdmin();
$this->get(route('bonus-scores.chooseEntry'))->assertOk()->assertViewIs('tabulation.choose_entry');
});
});
describe('BonusScoreController::entryBonusScoreSheet', function () {
beforeEach(function () {
$this->event = Event::factory()->create();
$this->ASaudition = Audition::factory()->create([
'event_id' => $this->event->id, 'name' => 'Alto Sax',
]);
$this->TSaudition = Audition::factory()->create([
'event_id' => $this->event->id, 'name' => 'Tenor Sax',
]);
$this->BSaudition = Audition::factory()->create([
'event_id' => $this->event->id, 'name' => 'Bari Sax',
]);
$this->student = Student::factory()->create();
$this->ASentry = Entry::create([
'audition_id' => $this->ASaudition->id, 'student_id' => $this->student->id,
]);
$this->TSentry = Entry::create([
'audition_id' => $this->TSaudition->id, 'student_id' => $this->student->id,
]);
$this->BSentry = Entry::create([
'audition_id' => $this->BSaudition->id, 'student_id' => $this->student->id,
]);
$this->bonusScoreDefinition = BonusScoreDefinition::create([
'name' => 'Sax Improv',
'max_score' => 10,
'weight' => 1,
'for_seating' => 1,
'for_attendance' => 0,
]);
$this->bonusScoreDefinition->auditions()->attach($this->ASaudition);
$this->bonusScoreDefinition->auditions()->attach($this->TSaudition);
$this->bonusScoreDefinition->auditions()->attach($this->BSaudition);
$this->judge1 = User::factory()->create();
$this->judge2 = User::factory()->create();
$this->bonusScoreDefinition->judges()->attach($this->judge1);
$this->bonusScoreDefinition->judges()->attach($this->judge2);
});
it('does not allow access to guests or normal users', function () {
$this->get(route('bonus-scores.entryBonusScoreSheet'))->assertRedirect(route('home'));
actAsNormal();
$this->get(route('bonus-scores.entryBonusScoreSheet'))->assertRedirect(route('dashboard'));
});
it('shows a form to enter bonus scores for a judge by an administrator', function () {
actAsAdmin();
$response = $this->get(route('bonus-scores.entryBonusScoreSheet', ['entry_id' => $this->TSentry->id]));
$response->assertOk()->assertViewIs('tabulation.bonus-score-sheet');
});
it('identifies the student', function () {
actAsAdmin();
$response = $this->get(route('bonus-scores.entryBonusScoreSheet', ['entry_id' => $this->TSentry->id]));
$response->assertSee($this->student->full_name())
->assertSee($this->student->school->name);
});
it('makes judges available', function () {
actAsAdmin();
$response = $this->get(route('bonus-scores.entryBonusScoreSheet', ['entry_id' => $this->TSentry->id]));
$response->assertSee($this->judge1->full_name())
->assertSee($this->judge2->full_name());
});
});
describe('BonusScoreController::saveEntryBonusScoreSheet', function () {
beforeEach(function () {
$this->event = Event::factory()->create();
$sg = ScoringGuide::factory()->create();
$this->ASaudition = Audition::factory()->create([
'event_id' => $this->event->id, 'name' => 'Alto Sax', 'scoring_guide_id' => $sg->id,
]);
$this->TSaudition = Audition::factory()->create([
'event_id' => $this->event->id, 'name' => 'Tenor Sax', 'scoring_guide_id' => $sg->id,
]);
$this->BSaudition = Audition::factory()->create([
'event_id' => $this->event->id, 'name' => 'Bari Sax', 'scoring_guide_id' => $sg->id,
]);
$this->student = Student::factory()->create();
$this->ASentry = Entry::create([
'audition_id' => $this->ASaudition->id, 'student_id' => $this->student->id,
]);
$this->TSentry = Entry::create([
'audition_id' => $this->TSaudition->id, 'student_id' => $this->student->id,
]);
$this->BSentry = Entry::create([
'audition_id' => $this->BSaudition->id, 'student_id' => $this->student->id,
]);
$this->bonusScoreDefinition = BonusScoreDefinition::create([
'name' => 'Sax Improv',
'max_score' => 10,
'weight' => 1,
'for_seating' => 1,
'for_attendance' => 0,
]);
$this->bonusScoreDefinition->auditions()->attach($this->ASaudition);
$this->bonusScoreDefinition->auditions()->attach($this->TSaudition);
$this->bonusScoreDefinition->auditions()->attach($this->BSaudition);
$this->judge1 = User::factory()->create();
$this->judge2 = User::factory()->create();
$this->bonusScoreDefinition->judges()->attach($this->judge1);
$this->bonusScoreDefinition->judges()->attach($this->judge2);
});
it('does not allow access to guests or normal users', function () {
$this->post(route('bonus-scores.saveEntryBonusScoreSheet', $this->TSentry))->assertRedirect(route('home'));
actAsNormal();
$this->post(route('bonus-scores.saveEntryBonusScoreSheet', $this->TSentry))->assertRedirect(route('dashboard'));
});
it('will not post a bonus score to a published audition', function () {
actAsAdmin();
$this->TSaudition->addFlag('seats_published');
$response = $this->post(route('bonus-scores.saveEntryBonusScoreSheet', $this->TSentry));
$response->assertRedirect(route('bonus-scores.entryBonusScoreSheet', ['entry_id' => $this->TSentry->id]))
->assertSessionHas('error');
});
it('applies the bonus score to all related entries, even if a bonus score exists', function () {
$ASbonusScoreRecorded = BonusScore::create([
'entry_id' => $this->ASentry->id,
'user_id' => $this->judge1->id,
'originally_scored_entry' => $this->ASentry->id,
'score' => 2,
]);
$TSbonusScoreRecorded = BonusScore::create([
'entry_id' => $this->TSentry->id,
'user_id' => $this->judge1->id,
'originally_scored_entry' => $this->ASentry->id,
'score' => 2,
]);
$BSbonusScoreRecorded = BonusScore::create([
'entry_id' => $this->BSentry->id,
'user_id' => $this->judge1->id,
'originally_scored_entry' => $this->ASentry->id,
'score' => 2,
]);
actAsAdmin();
$response = $this->post(route('bonus-scores.saveEntryBonusScoreSheet', $this->TSentry), [
'judge_id' => $this->judge1->id,
'entry_id' => $this->TSentry->id,
'score' => 3,
]);
foreach (Entry::all() as $entry) {
$bs = $entry->bonusScores()->first();
expect($bs->score)->toEqual(3);
expect($bs->originallyScoredEntry->id)->toEqual($this->TSentry->id);
}
});
it('deletes all related entries when a null score is submitted', function () {
$ASbonusScoreRecorded = BonusScore::create([
'entry_id' => $this->ASentry->id,
'user_id' => $this->judge1->id,
'originally_scored_entry' => $this->ASentry->id,
'score' => 2,
]);
$TSbonusScoreRecorded = BonusScore::create([
'entry_id' => $this->TSentry->id,
'user_id' => $this->judge1->id,
'originally_scored_entry' => $this->ASentry->id,
'score' => 2,
]);
$BSbonusScoreRecorded = BonusScore::create([
'entry_id' => $this->BSentry->id,
'user_id' => $this->judge1->id,
'originally_scored_entry' => $this->ASentry->id,
'score' => 2,
]);
$adminUser = User::factory()->admin()->create();
$this->actingAs($adminUser);
$response = $this->post(route('bonus-scores.saveEntryBonusScoreSheet', $this->TSentry), [
'judge_id' => $this->judge1->id,
'entry_id' => $this->TSentry->id,
'score' => null,
]);
expect(BonusScore::all())->toHaveCount(0);
});
});