Add Scoring Guide controller test

This commit is contained in:
Matt Young 2025-07-07 21:52:10 -05:00
parent 36da3b0e78
commit 2e8d625ab0
6 changed files with 488 additions and 79 deletions

View File

@ -3,14 +3,12 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\SubscoreDefinitionRequest;
use App\Models\ScoringGuide;
use App\Models\SubscoreDefinition;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use function abort;
use function auditionSetting;
use function request;
use function response;
@ -28,26 +26,19 @@ class ScoringGuideController extends Controller
public function store()
{
if (! Auth::user()->is_admin) {
abort(403);
}
request()->validate([
'name' => ['required', 'unique:scoring_guides'],
]);
$guide = ScoringGuide::create([
ScoringGuide::create([
'name' => request('name'),
]);
return redirect(route('admin.scoring.index'))->with('success', 'Scoring guide created');
}
public function edit(Request $request, ScoringGuide $guide, string $tab = 'detail')
public function edit(ScoringGuide $guide, string $tab = 'detail')
{
if (! Auth::user()->is_admin) {
abort(403);
}
if ($tab == 'tiebreakOrder') {
$subscores = SubscoreDefinition::where('scoring_guide_id', $guide->id)->orderBy('tiebreak_order')->get();
} else {
@ -59,9 +50,6 @@ class ScoringGuideController extends Controller
public function update(ScoringGuide $guide)
{
if (! Auth::user()->is_admin) {
abort(403);
}
request()->validate([
'name' => ['required', 'unique:scoring_guides'],
]);
@ -75,12 +63,9 @@ class ScoringGuideController extends Controller
public function destroy(ScoringGuide $guide)
{
if (! Auth::user()->is_admin) {
abort(403);
}
if ($guide->auditions()->count() > 0) {
return redirect('/admin/scoring')->with('error', 'Cannot delete scoring guide with auditions');
return redirect('/admin/scoring')->with('error',
'Cannot delete scoring guide being used by one or more auditions');
}
$guide->delete();
@ -88,89 +73,57 @@ class ScoringGuideController extends Controller
return redirect('/admin/scoring')->with('success', 'Scoring guide deleted');
}
public function subscore_store(Request $request, ScoringGuide $guide)
public function subscore_store(SubscoreDefinitionRequest $request, ScoringGuide $guide)
{
if (! $guide->exists()) {
abort(409);
}
$validateData = request()->validate([
'name' => ['required'],
'max_score' => ['required', 'integer'],
'weight' => ['required', 'integer'],
'for_seating' => ['nullable', 'boolean'],
'for_advance' => ['nullable', 'boolean'],
]);
$for_seating = $request->has('for_seating') ? (bool) $request->input('for_seating') : false;
$for_advance = $request->has('for_advance') ? (bool) $request->input('for_advance') : false;
if (! auditionSetting('advanceTo')) {
$for_seating = true;
}
$validateData = $request->validated();
// Put the new subscore at the end of the list for both display and tiebreak order
$display_order = SubscoreDefinition::where('scoring_guide_id', '=', $guide->id)->max('display_order') + 1;
$tiebreak_order = SubscoreDefinition::where('scoring_guide_id', '=', $guide->id)->max('tiebreak_order') + 1;
$subscore = SubscoreDefinition::create([
SubscoreDefinition::create([
'scoring_guide_id' => $guide->id,
'name' => $validateData['name'],
'max_score' => $validateData['max_score'],
'weight' => $validateData['weight'],
'display_order' => $display_order,
'tiebreak_order' => $tiebreak_order,
'for_seating' => $for_seating,
'for_advance' => $for_advance,
'for_seating' => $validateData['for_seating'],
'for_advance' => $validateData['for_advance'],
]);
return redirect(route('admin.scoring.edit', $guide))->with('success', 'Subscore added');
}
public function subscore_update(ScoringGuide $guide, SubscoreDefinition $subscore)
{
if (! Auth::user()->is_admin) {
abort(403);
}
if (! $guide->exists() || ! $subscore->exists()) {
abort(409);
}
public function subscore_update(
SubscoreDefinitionRequest $request,
ScoringGuide $guide,
SubscoreDefinition $subscore
) {
if ($subscore->scoring_guide_id !== $guide->id) { // Make sure the subscore were updating belongs to the guide
abort(409);
}
$validateData = request()->validate([
'name' => ['required'],
'max_score' => ['required', 'integer'],
'weight' => ['required', 'integer'],
'for_seating' => ['nullable', 'boolean'],
'for_advance' => ['nullable', 'boolean'],
]);
$for_seating = request()->has('for_seating') ? (bool) request()->input('for_seating') : false;
$for_advance = request()->has('for_advance') ? (bool) request()->input('for_advance') : false;
if (! auditionSetting('advanceTo')) {
$for_seating = true;
return redirect('/admin/scoring/guides/'.$subscore->scoring_guide_id.'/edit')->with('error',
'Cannot update a subscore for a different scoring guide');
}
$validateData = $validateData = $request->validated();
$subscore->update([
'name' => $validateData['name'],
'max_score' => $validateData['max_score'],
'weight' => $validateData['weight'],
'for_seating' => $for_seating,
'for_advance' => $for_advance,
'for_seating' => $validateData['for_seating'],
'for_advance' => $validateData['for_advance'],
]);
return redirect('/admin/scoring/guides/'.$guide->id.'/edit')->with('success', 'Subscore updated');
return redirect(route('admin.scoring.edit', $guide))->with('success', 'Subscore updated');
}
public function subscore_destroy(ScoringGuide $guide, SubscoreDefinition $subscore)
{
if (! Auth::user()->is_admin) {
abort(403);
}
if (! $guide->exists() || ! $subscore->exists()) {
abort(409);
}
if ($subscore->scoring_guide_id !== $guide->id) { // Make sure the subscore were updating belongs to the guide
abort(409);
return redirect(route('admin.scoring.edit', $subscore->scoring_guide_id))->with('error',
'Cannot delete a subscore for a different scoring guide');
}
$subscore->delete();
@ -181,9 +134,6 @@ class ScoringGuideController extends Controller
public function reorder_display(Request $request)
{
if (! Auth::user()->is_admin) {
abort(403);
}
$order = $request->order;
foreach ($order as $index => $id) {
$subscore = SubscoreDefinition::find($id);
@ -196,9 +146,6 @@ class ScoringGuideController extends Controller
public function reorder_tiebreak(Request $request)
{
if (! Auth::user()->is_admin) {
abort(403);
}
$order = $request->order;
foreach ($order as $index => $id) {
$subscore = SubscoreDefinition::find($id);

View File

@ -0,0 +1,57 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class SubscoreDefinitionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return auth()->user()->is_admin; // Only allow admins to create/update subscores
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
$guideId = $this->route('guide')->id; // get the guide ID from route model binding
$definition = $this->route('subscore')->id ?? null; // get the guide ID from route model binding
return [
'name' => [
'required',
'string',
Rule::unique('subscore_definitions') // name must be unique on a guide, allow for the current name
->where(fn ($query) => $query->where('scoring_guide_id', $guideId))
->ignore($definition),
],
'max_score' => ['required', 'integer'],
'weight' => ['required', 'integer'],
'for_seating' => ['sometimes', 'nullable'],
'for_advance' => ['sometimes', 'nullable'],
];
}
protected function passedValidation()
{
// Normalize the boolean inputs
$this->merge([
'for_seating' => $this->has('for_seating') ? (bool) $this->input('for_seating') : false,
'for_advance' => $this->has('for_advance') ? (bool) $this->input('for_advance') : false,
]);
// Apply your custom logic
if (! auditionSetting('advanceTo')) {
$this->merge(['for_seating' => true]);
}
}
}

View File

@ -3,6 +3,7 @@
namespace App\Observers;
use App\Models\ScoringGuide;
use Illuminate\Support\Facades\Schema;
use function auditionLog;
@ -10,7 +11,10 @@ class ScoringGuideObserver
{
public function created(ScoringGuide $scoringGuide): void
{
$message = 'Added scoring guide '.$scoringGuide->name.$scoringGuide->name.'(ID #'.$scoringGuide->id.')';
if (! Schema::hasTable('audit_log_entries')) {
return;
}
$message = 'Added scoring guide '.$scoringGuide->name.'(ID #'.$scoringGuide->id.')';
$affected = ['scoring_guides' => [$scoringGuide->id]];
auditionLog($message, $affected);
}

View File

@ -14,6 +14,7 @@
aria-describedby="comments-description"
name="{{ $name }}"
type="checkbox"
value="1"
@if($checked) checked @endif
{{ $attributes->merge(['class' => "h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600"]) }}>
</div>

View File

@ -33,6 +33,7 @@ it('assigns a user to a school', function () {
});
it('logs the assignment of the user to the school', function () {
$this->user->save();
($this->assigner)($this->user, $this->school);
$logEntry = AuditLogEntry::orderBy('id', 'desc')->first();
expect($logEntry->message)->toEqual('Added '.$this->user->full_name().' to '.$this->school->name);

View File

@ -0,0 +1,399 @@
<?php
use App\Models\Audition;
use App\Models\ScoringGuide;
use App\Models\SubscoreDefinition;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
describe('ScoringGuideController::index', function () {
it('denies access to a non-admin user', function () {
$this->get(route('admin.scoring.index'))->assertRedirect(route('home'));
actAsNormal();
$this->get(route('admin.scoring.index'))->assertRedirect(route('dashboard'));
actAsTab();
$this->get(route('admin.scoring.index'))->assertRedirect(route('dashboard'));
});
it('ensures that auditions with null for scoring_guide_id are set to zero', function () {
$audition = Audition::factory()->create();
actAsAdmin();
$this->get(route('admin.scoring.index'));
$audition->refresh();
expect($audition->scoring_guide_id)->toEqual(0);
});
it('shows the scoring guide index page', function () {
actAsAdmin();
$this->get(route('admin.scoring.index'))
->assertOk()
->assertViewHas('guides')
->assertViewIs('admin.scoring.index');
});
});
describe('ScoringGuideController::store', function () {
it('denies access to a non-admin user', function () {
$this->post(route('admin.scoring.store'))->assertRedirect(route('home'));
actAsNormal();
$this->post(route('admin.scoring.store'))->assertRedirect(route('dashboard'));
actAsTab();
$this->post(route('admin.scoring.store'))->assertRedirect(route('dashboard'));
});
it('stores a scoring guide', function () {
actAsAdmin();
$response = $this->post(route('admin.scoring.store'), [
'name' => 'Test Guide',
]);
$response->assertRedirect(route('admin.scoring.index'));
expect(ScoringGuide::count())->toEqual(2)
->and(ScoringGuide::orderBy('id', 'desc')->first())->toBeInstanceOf(ScoringGuide::class)
->and(ScoringGuide::orderBy('id', 'desc')->first()->name)->toEqual('Test Guide');
});
it('will not store a scoring guide with a blank name', function () {
actAsAdmin();
$response = $this->post(route('admin.scoring.store'), [
'name' => '',
]);
$response->assertSessionHasErrors('name');
expect(ScoringGuide::count())->toEqual(1);
});
it('will not store a scoring guide with a duplicate name', function () {
actAsAdmin();
$response = $this->post(route('admin.scoring.store'), [
'name' => 'Test Guide',
]);
$response = $this->post(route('admin.scoring.store'), [
'name' => 'Test Guide',
]);
$response->assertSessionHasErrors('name');
expect(ScoringGuide::count())->toEqual(2);
});
});
describe('ScoringGuideController::edit', function () {
beforeEach(function () {
$this->guide = ScoringGuide::factory()->create();
});
it('denies access to a non-admin user', function () {
$this->get(route('admin.scoring.edit', $this->guide))->assertRedirect(route('home'));
actAsNormal();
$this->get(route('admin.scoring.edit', $this->guide))->assertRedirect(route('dashboard'));
actAsTab();
$this->get(route('admin.scoring.edit', $this->guide))->assertRedirect(route('dashboard'));
});
it('shows the scoring guide edit page', function () {
actAsAdmin();
$this->get(route('admin.scoring.edit', $this->guide))
->assertOk()
->assertViewIs('admin.scoring.edit')
->assertViewHas('guide')
->assertViewHas('subscores')
->assertViewHas('tab');
});
it('includes links to other tabs for managing subscore order', function () {
actAsAdmin();
$this->get(route('admin.scoring.edit', $this->guide))
->assertSeeInOrder(['href', route('admin.scoring.edit', $this->guide, ['tab' => 'detail'])])
->assertSeeInOrder(['href', route('admin.scoring.edit', $this->guide, ['tab' => 'displayOrder'])])
->assertSeeInOrder(['href', route('admin.scoring.edit', $this->guide, ['tab' => 'tiebreakOrder'])]);
});
it('includes forms to edit each subscore', function () {
actAsAdmin();
$response = $this->get(route('admin.scoring.edit', $this->guide));
foreach (SubscoreDefinition::all() as $subscore) {
$response->assertSeeInOrder([
'POST', 'action', route('admin.scoring.subscore_update', [$this->guide, 'subscore' => $subscore->id]),
]);
}
});
it('gets subscores in the correct order fo the specified tab', function () {
$tbOrderOn = 1;
$displayOrderOn = 10;
SubscoreDefinition::truncate();
$id = $this->guide->id;
$ss1 = SubscoreDefinition::create([
'display_order' => 2,
'tiebreak_order' => 2,
'name' => 'ss1',
'scoring_guide_id' => $id,
'max_score' => 100,
'weight' => 1,
'for_advance' => 1,
'for_seating' => 1,
]);
$ss2 = SubscoreDefinition::create([
'display_order' => 1,
'tiebreak_order' => 3,
'name' => 'ss1',
'scoring_guide_id' => $id,
'max_score' => 100,
'weight' => 1,
'for_advance' => 1,
'for_seating' => 1,
]);
$ss3 = SubscoreDefinition::create([
'display_order' => 3,
'tiebreak_order' => 1,
'name' => 'ss1',
'scoring_guide_id' => $id,
'max_score' => 100,
'weight' => 1,
'for_advance' => 1,
'for_seating' => 1,
]);
actAsAdmin();
$response = $this->get(route('admin.scoring.edit', [$this->guide, 'tab' => 'displayOrder']));
expect($response->viewData('subscores')[0]->id)->toEqual($ss2->id);
$response = $this->get(route('admin.scoring.edit', [$this->guide, 'tab' => 'detail']));
expect($response->viewData('subscores')[0]->id)->toEqual($ss2->id);
$response = $this->get(route('admin.scoring.edit', [$this->guide, 'tab' => 'tiebreakOrder']));
expect($response->viewData('subscores')[0]->id)->toEqual($ss3->id);
});
});
describe('ScoringGuideController::update', function () {
beforeEach(function () {
$this->guide = ScoringGuide::factory()->create();
});
it('denies access to a non-admin user', function () {
$this->patch(route('admin.scoring.update', $this->guide))->assertRedirect(route('home'));
actAsNormal();
$this->patch(route('admin.scoring.update', $this->guide))->assertRedirect(route('dashboard'));
actAsTab();
$this->patch(route('admin.scoring.update', $this->guide))->assertRedirect(route('dashboard'));
});
it('updates a scoring guide', function () {
actAsAdmin();
$response = $this->patch(route('admin.scoring.update', $this->guide), [
'name' => 'Test Guide',
]);
$response->assertRedirect(route('admin.scoring.edit', $this->guide));
expect(ScoringGuide::count())->toEqual(2) // Accounts for guide 0 - no guide assigned
->and(ScoringGuide::orderBy('id', 'desc')->first())->toBeInstanceOf(ScoringGuide::class)
->and(ScoringGuide::orderBy('id', 'desc')->first()->name)->toEqual('Test Guide');
});
it('will not duplicate a scoring guide name', function () {
actAsAdmin();
ScoringGuide::create(['name' => 'Dont Copy Me Bro']);
$response = $this->patch(route('admin.scoring.update', $this->guide), [
'name' => 'Dont Copy Me Bro',
]);
$response->assertSessionHasErrors('name');
expect($this->guide->fresh()->name)->not()->toEqual('Dont Copy Me Bro');
});
});
describe('ScoringGuideController::destroy', function () {
beforeEach(function () {
$this->guide = ScoringGuide::factory()->create();
});
it('denies access to a non-admin user', function () {
$this->delete(route('admin.scoring.destroy', $this->guide))->assertRedirect(route('home'));
actAsNormal();
$this->delete(route('admin.scoring.destroy', $this->guide))->assertRedirect(route('dashboard'));
actAsTab();
$this->delete(route('admin.scoring.destroy', $this->guide))->assertRedirect(route('dashboard'));
});
it('deletes a scoring guide', function () {
actAsAdmin();
$this->delete(route('admin.scoring.destroy', $this->guide))
->assertRedirect(route('admin.scoring.index'));
expect(ScoringGuide::count())->toEqual(1);
expect(ScoringGuide::find($this->guide->id))->toBeNull();
});
it('will not delete a scoring guide that is assigned to an audition', function () {
$audition = Audition::factory()->create(['scoring_guide_id' => $this->guide->id]);
actAsAdmin();
$this->delete(route('admin.scoring.destroy', $this->guide))
->assertRedirect(route('admin.scoring.index'))
->assertSessionHas('error', 'Cannot delete scoring guide being used by one or more auditions');
expect(ScoringGuide::count())->toEqual(2);
});
});
describe('ScoringGuideController::subscore_store', function () {
beforeEach(function () {
$this->guide = ScoringGuide::factory()->create();
});
it('denies access to a non-admin user', function () {
$this->post(route('admin.scoring.subscore_store',
[$this->guide, 'subscore' => $this->guide->id]))->assertRedirect(route('home'));
actAsNormal();
$this->post(route('admin.scoring.subscore_store',
[$this->guide, 'subscore' => $this->guide->id]))->assertRedirect(route('dashboard'));
actAsTab();
$this->post(route('admin.scoring.subscore_store',
[$this->guide, 'subscore' => $this->guide->id]))->assertRedirect(route('dashboard'));
});
it('creates a subscore', function () {
actAsAdmin();
$response = $this->post(route('admin.scoring.subscore_store', [$this->guide, 'subscore' => $this->guide->id]), [
'name' => 'Test Subscore',
'max_score' => 150,
'weight' => 3,
'for_advance' => 'on',
'for_seating' => 'on',
]);
$response->assertRedirect(route('admin.scoring.edit', [$this->guide]));
expect(SubscoreDefinition::orderBy('id', 'desc')->first()->name)->toEqual('Test Subscore');
});
});
describe('ScoringGuideController::subscore_update', function () {
beforeEach(function () {
$this->guide = ScoringGuide::factory()->create();
$this->testSubscore = SubscoreDefinition::first();
$this->testSubscore->name = 'Test Subscore';
$this->testSubscore->save();
});
it('denies access to a non-admin user', function () {
$this->patch(route('admin.scoring.subscore_update',
[$this->guide, 'subscore' => $this->testSubscore->id]))->assertRedirect(route('home'));
actAsNormal();
$this->patch(route('admin.scoring.subscore_update',
[$this->guide, 'subscore' => $this->testSubscore->id]))->assertRedirect(route('dashboard'));
actAsTab();
$this->patch(route('admin.scoring.subscore_update',
[$this->guide, 'subscore' => $this->testSubscore->id]))->assertRedirect(route('dashboard'));
});
it('can update a subscore', function () {
actAsAdmin();
$response = $this->patch(route('admin.scoring.subscore_update',
['subscore' => $this->testSubscore->id, $this->guide]), [
'name' => 'New Name',
'max_score' => 150,
'weight' => 3,
'for_advance' => 'on',
'for_seating' => 'on',
]);
$response->assertRedirect(route('admin.scoring.edit', [$this->guide]));
expect(SubscoreDefinition::find($this->testSubscore->id)->name)->toEqual('New Name');
});
it('can update a subscore without changing name', function () {
actAsAdmin();
$response = $this->patch(route('admin.scoring.subscore_update',
['subscore' => $this->testSubscore->id, $this->guide]), [
'name' => 'Test Subscore',
'max_score' => 90,
'weight' => 3,
'for_advance' => 'on',
'for_seating' => 'on',
]);
$response->assertRedirect(route('admin.scoring.edit', [$this->guide]));
expect(SubscoreDefinition::find($this->testSubscore->id)->name)->toEqual('Test Subscore')
->and(SubscoreDefinition::find($this->testSubscore->id)->max_score)->toEqual(90);
});
it('will not update a subscore for a different guide', function () {
$guide2 = ScoringGuide::factory()->create();
actAsAdmin();
$response = $this->patch(route('admin.scoring.subscore_update',
['subscore' => $this->testSubscore->id, $guide2]), [
'name' => 'Test Subscore',
'max_score' => 90,
'weight' => 3,
'for_advance' => 'on',
'for_seating' => 'on',
]
);
$response->assertSessionHas('error', 'Cannot update a subscore for a different scoring guide')
->assertRedirect(route('admin.scoring.edit', [$this->guide]));
});
});
describe('ScoringGuideController::subscore_destroy', function () {
beforeEach(function () {
$this->guide = ScoringGuide::factory()->create();
$this->testSubscore = SubscoreDefinition::first();
$this->testSubscore->name = 'Test Subscore';
$this->testSubscore->save();
});
it('denies access to a non-admin user', function () {
$this->delete(route('admin.scoring.subscore_destroy',
['subscore' => $this->guide, $this->testSubscore->id]))->assertRedirect(route('home'));
actAsNormal();
$this->delete(route('admin.scoring.subscore_destroy',
['subscore' => $this->guide, $this->testSubscore->id]))->assertRedirect(route('dashboard'));
actAsTab();
$this->delete(route('admin.scoring.subscore_destroy',
['subscore' => $this->guide, $this->testSubscore->id]))->assertRedirect(route('dashboard'));
});
it('can delete a subscore', function () {
actAsAdmin();
$response = $this->delete(route('admin.scoring.subscore_destroy',
['subscore' => $this->guide, $this->testSubscore->id]));
$response->assertRedirect(route('admin.scoring.edit', [$this->guide]));
expect(SubscoreDefinition::find($this->testSubscore->id))->toBeNull();
});
it('will not delete a subscore for a different guide', function () {
$guide2 = ScoringGuide::factory()->create();
actAsAdmin();
$response = $this->delete(route('admin.scoring.subscore_destroy',
[$guide2, $this->testSubscore->id]));
expect(SubscoreDefinition::find($this->testSubscore->id))->not()->toBeNull();
$response->assertSessionHas('error', 'Cannot delete a subscore for a different scoring guide')
->assertRedirect(route('admin.scoring.edit', $this->guide));
});
});
describe('ScoringGuideController::reorder_display', function () {
it('denies access to a non-admin user', function () {
$this->post(route('admin.scoring.reorder_display'))->assertRedirect(route('home'));
actAsNormal();
$this->post(route('admin.scoring.reorder_display'))->assertRedirect(route('dashboard'));
actAsTab();
$this->post(route('admin.scoring.reorder_display'))->assertRedirect(route('dashboard'));
});
it('can reorder display order', function () {
$sg = ScoringGuide::factory()->create();
SubscoreDefinition::truncate();
$ss1 = SubscoreDefinition::factory()->create(['scoring_guide_id' => $sg->id, 'display_order' => 1]);
$ss2 = SubscoreDefinition::factory()->create(['scoring_guide_id' => $sg->id, 'display_order' => 2]);
$ss3 = SubscoreDefinition::factory()->create(['scoring_guide_id' => $sg->id, 'display_order' => 3]);
actAsAdmin();
$response = $this->post(route('admin.scoring.reorder_display'), [
'order' => [$ss2->id, $ss1->id, $ss3->id],
]);
$response->assertJson(['status' => 'success']);
$ss1->refresh();
$ss2->refresh();
$ss3->refresh();
expect($ss1->display_order)->toEqual(2);
expect($ss2->display_order)->toEqual(1);
expect($ss3->display_order)->toEqual(3);
});
});
describe('ScoringGuideController::reorder_tiebreak', function () {
it('denies access to a non-admin user', function () {
$this->post(route('admin.scoring.reorder_tiebreak'))->assertRedirect(route('home'));
actAsNormal();
$this->post(route('admin.scoring.reorder_tiebreak'))->assertRedirect(route('dashboard'));
actAsTab();
$this->post(route('admin.scoring.reorder_tiebreak'))->assertRedirect(route('dashboard'));
});
it('can reorder display order', function () {
$sg = ScoringGuide::factory()->create();
SubscoreDefinition::truncate();
$ss1 = SubscoreDefinition::factory()->create(['scoring_guide_id' => $sg->id, 'tiebreak_order' => 1]);
$ss2 = SubscoreDefinition::factory()->create(['scoring_guide_id' => $sg->id, 'tiebreak_order' => 2]);
$ss3 = SubscoreDefinition::factory()->create(['scoring_guide_id' => $sg->id, 'tiebreak_order' => 3]);
actAsAdmin();
$response = $this->post(route('admin.scoring.reorder_tiebreak'), [
'order' => [$ss3->id, $ss2->id, $ss1->id],
]);
$response->assertJson(['status' => 'success']);
$ss1->refresh();
$ss2->refresh();
$ss3->refresh();
expect($ss1->tiebreak_order)->toEqual(3);
expect($ss2->tiebreak_order)->toEqual(2);
expect($ss3->tiebreak_order)->toEqual(1);
});
});