Tests for BonusScoreDefinitionController.php

This commit is contained in:
Matt Young 2025-07-09 22:49:09 -05:00
parent beae7cae20
commit aeb2557be3
3 changed files with 300 additions and 13 deletions

View File

@ -27,7 +27,7 @@ class BonusScoreDefinitionController extends Controller
public function store() public function store()
{ {
$validData = request()->validate([ $validData = request()->validate([
'name' => 'required', 'name' => 'required|unique:bonus_score_definitions,name',
'max_score' => 'required|numeric', 'max_score' => 'required|numeric',
'weight' => 'required|numeric', 'weight' => 'required|numeric',
]); ]);
@ -49,6 +49,7 @@ class BonusScoreDefinitionController extends Controller
public function assignAuditions(Request $request) public function assignAuditions(Request $request)
{ {
// TODO: add pivot model to log changes to assignments
$validData = $request->validate([ $validData = $request->validate([
'bonus_score_id' => 'required|exists:bonus_score_definitions,id', 'bonus_score_id' => 'required|exists:bonus_score_definitions,id',
'audition' => 'required|array', 'audition' => 'required|array',
@ -70,12 +71,8 @@ class BonusScoreDefinitionController extends Controller
public function unassignAudition(Audition $audition) public function unassignAudition(Audition $audition)
{ {
if (! $audition->exists()) { // TODO: add pivot model to log changes to assignments
return redirect()->route('admin.bonus-scores.index')->with('error', 'Audition not found');
}
if (! $audition->bonusScore()->count() > 0) {
return redirect()->route('admin.bonus-scores.index')->with('error', 'Audition does not have a bonus score');
}
$audition->bonusScore()->detach(); $audition->bonusScore()->detach();
return redirect()->route('admin.bonus-scores.index')->with('success', 'Audition unassigned from bonus score'); return redirect()->route('admin.bonus-scores.index')->with('success', 'Audition unassigned from bonus score');
@ -83,6 +80,7 @@ class BonusScoreDefinitionController extends Controller
public function judges() public function judges()
{ {
//TODO Need to show if judge is assigned, and show bonus assignments or normal judging page
$bonusScores = BonusScoreDefinition::all(); $bonusScores = BonusScoreDefinition::all();
$users = User::orderBy('last_name')->orderBy('first_name')->get(); $users = User::orderBy('last_name')->orderBy('first_name')->get();
@ -91,9 +89,6 @@ class BonusScoreDefinitionController extends Controller
public function assignJudge(BonusScoreDefinition $bonusScore) public function assignJudge(BonusScoreDefinition $bonusScore)
{ {
if (! $bonusScore->exists()) {
return redirect()->route('admin.bonus-scores.judges')->with('error', 'Bonus Score not found');
}
$validData = request()->validate([ $validData = request()->validate([
'judge' => 'required|exists:users,id', 'judge' => 'required|exists:users,id',
]); ]);
@ -104,9 +99,6 @@ class BonusScoreDefinitionController extends Controller
public function removeJudge(BonusScoreDefinition $bonusScore) public function removeJudge(BonusScoreDefinition $bonusScore)
{ {
if (! $bonusScore->exists()) {
return redirect()->route('admin.bonus-scores.judges')->with('error', 'Bonus Score not found');
}
$validData = request()->validate([ $validData = request()->validate([
'judge' => 'required|exists:users,id', 'judge' => 'required|exists:users,id',
]); ]);

View File

@ -0,0 +1,40 @@
<?php
namespace App\Observers;
use App\Models\BonusScoreDefinition;
class BonusScoreDefinitionObserver
{
public function created(BonusScoreDefinition $bonusScoreDefinition): void
{
$message = 'Added bonus score definition #'.$bonusScoreDefinition->id.': '.$bonusScoreDefinition->name;
$message .= '<br>Max Score: '.$bonusScoreDefinition->max_score;
$message .= '<br>Weight: '.$bonusScoreDefinition->weight;
$affected = ['bonus_score_definitions' => [$bonusScoreDefinition->id]];
auditionLog($message, $affected);
}
public function updated(BonusScoreDefinition $bonusScoreDefinition): void
{
$message = 'Updated bonus score definition #'.$bonusScoreDefinition->id.': '.$bonusScoreDefinition->getOriginal('name');
if ($bonusScoreDefinition->name !== $bonusScoreDefinition->getOriginal('name')) {
$message .= '<br>'.$bonusScoreDefinition->getOriginal('name').' -> '.$bonusScoreDefinition->name;
}
if ($bonusScoreDefinition->max_score !== $bonusScoreDefinition->getOriginal('max_score')) {
$message .= '<br>Max Score: '.$bonusScoreDefinition->getOriginal('max_score').' -> '.$bonusScoreDefinition->max_score;
}
if ($bonusScoreDefinition->weight !== $bonusScoreDefinition->getOriginal('weight')) {
$message .= '<br>Weight: '.$bonusScoreDefinition->getOriginal('weight').' -> '.$bonusScoreDefinition->weight;
}
$affected = ['bonus_score_definitions' => [$bonusScoreDefinition->id]];
auditionLog($message, $affected);
}
public function deleted(BonusScoreDefinition $bonusScoreDefinition): void
{
$message = 'Deleted bonus score definition #'.$bonusScoreDefinition->id.': '.$bonusScoreDefinition->name;
$affected = ['bonus_score_definitions' => [$bonusScoreDefinition->id]];
auditionLog($message, $affected);
}
}

View File

@ -0,0 +1,255 @@
<?php
use App\Models\Audition;
use App\Models\BonusScoreDefinition;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
describe('BonusScoreDefinitionController::index', function () {
it('denies access to a non-admin user', function () {
$this->get(route('admin.bonus-scores.index'))->assertRedirect(route('home'));
actAsNormal();
$this->get(route('admin.bonus-scores.index'))->assertRedirect(route('dashboard'));
actAsTab();
$this->get(route('admin.bonus-scores.index'))->assertRedirect(route('dashboard'));
});
it('show a page to manage bonus score definitions', function () {
actAsAdmin();
$this->get(route('admin.bonus-scores.index'))->assertOk();
});
it('includes all bonus score definitions', function () {
actAsAdmin();
$bonusScores = BonusScoreDefinition::factory()->count(3)->create();
$response = $this->get(route('admin.bonus-scores.index'));
$response->assertOk();
foreach ($bonusScores as $bonusScore) {
$response->assertSee($bonusScore->name);
}
});
it('provides the view with a collection of auditions that have no bonus score assigned', function () {
actAsAdmin();
$bonusScore = BonusScoreDefinition::factory()->create();
$auditionsWithoutBonusScore = \App\Models\Audition::factory()->count(3)->create();
$auditionsWithBonusScore = \App\Models\Audition::factory()->count(3)->create();
foreach ($auditionsWithBonusScore as $audition) {
DB::table('bonus_score_audition_assignment')->insert([
'bonus_score_definition_id' => $bonusScore->id,
'audition_id' => $audition->id,
]);
}
$response = $this->get(route('admin.bonus-scores.index'));
$response->assertOk();
foreach ($auditionsWithBonusScore as $audition) {
expect($response->viewData('unassignedAuditions')->contains('id', $audition->id))->toBeFalse();
}
foreach ($auditionsWithoutBonusScore as $audition) {
expect($response->viewData('unassignedAuditions')->contains('id', $audition->id))->toBeTrue();
}
});
});
describe('BonusScoreDefinitionController::store', function () {
it('denies access to a non-admin user', function () {
$this->post(route('admin.bonus-scores.store'))->assertRedirect(route('home'));
actAsNormal();
$this->post(route('admin.bonus-scores.store'))->assertRedirect(route('dashboard'));
actAsTab();
$this->post(route('admin.bonus-scores.store'))->assertRedirect(route('dashboard'));
});
it('creates a bonus score definition', function () {
actAsAdmin();
$this->post(route('admin.bonus-scores.store'), [
'name' => 'Test Bonus Score',
'max_score' => 100,
'weight' => 1,
])->assertRedirect(route('admin.bonus-scores.index'))->assertSessionHas('success');
$this->assertDatabaseHas('bonus_score_definitions', [
'name' => 'Test Bonus Score',
]);
});
it('will not create a bonus score definition with a duplicate name', function () {
BonusScoreDefinition::create(['name' => 'Test Bonus Score', 'max_score' => 100, 'weight' => 1]);
actAsAdmin();
$response = $this->post(route('admin.bonus-scores.store'), [
'name' => 'Test Bonus Score',
'max_score' => 100,
'weight' => 1,
])->assertSessionHasErrors('name');
expect(BonusScoreDefinition::count())->toBe(1);
});
});
describe('BonusScoreDefinitionController::destroy', function () {
beforeEach(function () {
$this->bonusScore = BonusScoreDefinition::create(['name' => 'Test Bonus Score', 'max_score' => 100,
'weight' => 1,
]);
});
it('can delete a bonus score definition', function () {
actAsAdmin();
$this->delete(route('admin.bonus-scores.destroy',
$this->bonusScore))->assertRedirect(route('admin.bonus-scores.index'))->assertSessionHas('success');
$this->assertDatabaseMissing('bonus_score_definitions', [
'id' => $this->bonusScore->id,
]);
});
it('denies access to a non-admin user', function () {
$this->delete(route('admin.bonus-scores.destroy', $this->bonusScore))->assertRedirect(route('home'));
actAsNormal();
$this->delete(route('admin.bonus-scores.destroy', $this->bonusScore))->assertRedirect(route('dashboard'));
actAsTab();
$this->delete(route('admin.bonus-scores.destroy', $this->bonusScore))->assertRedirect(route('dashboard'));
});
it('will not delete a bonus score definition that has auditions assigned to it', function () {
$audition = Audition::factory()->create();
DB::table('bonus_score_audition_assignment')->insert([
'bonus_score_definition_id' => $this->bonusScore->id,
'audition_id' => $audition->id,
]);
actAsAdmin();
$this->delete(route('admin.bonus-scores.destroy',
$this->bonusScore))->assertRedirect(route('admin.bonus-scores.index'))
->assertSessionHas('error');
$this->assertDatabaseCount('bonus_score_definitions', 1);
});
});
describe('BonusScoreDefinitionController::assignAuditions', function () {
it('can assign a bonus score definition to an audition', function () {
$audition = Audition::factory()->create();
$bonusScoreDefinition = BonusScoreDefinition::factory()->create();
actAsAdmin();
$response = $this->post(route('admin.bonus-scores.addAuditions', $bonusScoreDefinition), [
'audition' => [$audition->id => 1],
'bonus_score_id' => $bonusScoreDefinition->id,
]);
$response->assertRedirect(route('admin.bonus-scores.index'))->assertSessionHas('success');
$this->assertDatabaseHas('bonus_score_audition_assignment', [
'bonus_score_definition_id' => $bonusScoreDefinition->id,
'audition_id' => $audition->id,
]);
});
it('denies access to a non-admin user', function () {
$this->post(route('admin.bonus-scores.addAuditions'))->assertRedirect(route('home'));
actAsNormal();
$this->post(route('admin.bonus-scores.addAuditions'))->assertRedirect(route('dashboard'));
actAsTab();
$this->post(route('admin.bonus-scores.addAuditions'))->assertRedirect(route('dashboard'));
});
it('will note assign a bonus score to the same audition twice', function () {
$bonusScoreDefinition = BonusScoreDefinition::factory()->create();
$audition = Audition::factory()->create();
DB::table('bonus_score_audition_assignment')->insert([
'bonus_score_definition_id' => $bonusScoreDefinition->id,
'audition_id' => $audition->id,
]);
actAsAdmin();
$response = $this->post(route('admin.bonus-scores.addAuditions', $bonusScoreDefinition), [
'audition' => [$audition->id => 1],
'bonus_score_id' => $bonusScoreDefinition->id,
]);
$response->assertRedirect(route('admin.bonus-scores.index'))->assertSessionHas('error',
'Error assigning auditions to bonus score');
$this->assertDatabaseCount('bonus_score_audition_assignment', 1);
});
});
describe('BonusScoreDefinitionController::unassignAudition', function () {
beforeEach(function () {
$this->bonusScoreDefinition = BonusScoreDefinition::factory()->create();
$this->audition = Audition::factory()->create();
DB::table('bonus_score_audition_assignment')->insert([
'bonus_score_definition_id' => $this->bonusScoreDefinition->id,
'audition_id' => $this->audition->id,
]);
});
it('denies access to a non-admin user', function () {
$this->delete(route('admin.bonus-scores.unassignAudition', $this->audition->id))->assertRedirect(route('home'));
actAsNormal();
$this->delete(route('admin.bonus-scores.unassignAudition',
$this->audition->id))->assertRedirect(route('dashboard'));
actAsTab();
$this->delete(route('admin.bonus-scores.unassignAudition',
$this->audition->id))->assertRedirect(route('dashboard'));
});
it('can unassign an audition from a bonus score definition', function () {
actAsAdmin();
$this->delete(route('admin.bonus-scores.unassignAudition',
$this->audition->id))->assertRedirect(route('admin.bonus-scores.index'))->assertSessionHas('success');
$this->assertDatabaseMissing('bonus_score_audition_assignment', [
'bonus_score_definition_id' => $this->bonusScoreDefinition->id,
'audition_id' => $this->audition->id,
]);
});
});
describe('BonusScoreDefinitionController::judges', function () {
it('denies access to a non-admin user', function () {
$this->get(route('admin.bonus-scores.judges'))->assertRedirect(route('home'));
actAsNormal();
$this->get(route('admin.bonus-scores.judges'))->assertRedirect(route('dashboard'));
actAsTab();
$this->get(route('admin.bonus-scores.judges'))->assertRedirect(route('dashboard'));
});
it('shows a page to manage subscore judges', function () {
actAsAdmin();
$this->get(route('admin.bonus-scores.judges'))->assertOk();
});
});
describe('BonusScoreDefinitionController::assignJudge', function () {
it('denies access to a non-admin user', function () {
$bonusScore = BonusScoreDefinition::factory()->create();
$this->post(route('admin.bonus-scores.judges.assign', $bonusScore))->assertRedirect(route('home'));
actAsNormal();
$this->post(route('admin.bonus-scores.judges.assign', $bonusScore))->assertRedirect(route('dashboard'));
actAsTab();
$this->post(route('admin.bonus-scores.judges.assign', $bonusScore))->assertRedirect(route('dashboard'));
});
it('can assign a judge to a bonus score', function () {
$judge = User::factory()->create();
$bonusScore = BonusScoreDefinition::factory()->create();
actAsAdmin();
$response = $this->post(route('admin.bonus-scores.judges.assign', $bonusScore), [
'judge' => $judge->id,
]);
$response->assertRedirect(route('admin.bonus-scores.judges'))->assertSessionHas('success');
$this->assertDatabaseHas('bonus_score_judge_assignment', [
'bonus_score_definition_id' => $bonusScore->id,
'user_id' => $judge->id,
]);
});
});
describe('BonusScoreDefinitionController::removeJudge', function () {
it('denies access to a non-admin user', function () {
$bonusScore = BonusScoreDefinition::factory()->create();
$this->delete(route('admin.bonus-scores.judges.remove', $bonusScore))->assertRedirect(route('home'));
actAsNormal();
$this->delete(route('admin.bonus-scores.judges.remove', $bonusScore))->assertRedirect(route('dashboard'));
actAsTab();
$this->delete(route('admin.bonus-scores.judges.remove', $bonusScore))->assertRedirect(route('dashboard'));
});
it('can remove a judge from a bonus score', function () {
$judge = User::factory()->create();
$bonusScore = BonusScoreDefinition::factory()->create();
DB::table('bonus_score_judge_assignment')->insert([
'bonus_score_definition_id' => $bonusScore->id,
'user_id' => $judge->id,
]);
actAsAdmin();
$response = $this->delete(route('admin.bonus-scores.judges.remove', $bonusScore), [
'judge' => $judge->id,
]);
$response->assertRedirect(route('admin.bonus-scores.judges'))->assertSessionHas('success');
$this->assertDatabaseMissing('bonus_score_judge_assignment', [
'bonus_score_definition_id' => $bonusScore->id,
'user_id' => $judge->id,
]);
});
});