AdminEnsembles page tests
This commit is contained in:
parent
916baa2c93
commit
3a93aa0ea2
|
|
@ -8,7 +8,7 @@ use App\Models\Event;
|
||||||
use App\Models\SeatingLimit;
|
use App\Models\SeatingLimit;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use function redirect;
|
use function redirect;
|
||||||
|
|
||||||
class EnsembleController extends Controller
|
class EnsembleController extends Controller
|
||||||
|
|
@ -16,16 +16,19 @@ class EnsembleController extends Controller
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$events = Event::with('ensembles')->get();
|
$events = Event::with('ensembles')->get();
|
||||||
return view('admin.ensembles.index',compact('events'));
|
|
||||||
|
return view('admin.ensembles.index', compact('events'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
if(! Auth::user()->is_admin) abort(403);
|
if (! Auth::user()->is_admin) {
|
||||||
|
abort(403);
|
||||||
|
}
|
||||||
request()->validate([
|
request()->validate([
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
'code' => ['required','max:6'],
|
'code' => ['required', 'max:6'],
|
||||||
'event_id' => ['required','exists:events,id']
|
'event_id' => ['required', 'exists:events,id'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Ensemble::create([
|
Ensemble::create([
|
||||||
|
|
@ -34,29 +37,32 @@ class EnsembleController extends Controller
|
||||||
'event_id' => request('event_id'),
|
'event_id' => request('event_id'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return redirect()->route('admin.ensembles.index')->with('success','Ensemble created successfully');
|
return redirect()->route('admin.ensembles.index')->with('success', 'Ensemble created successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Request $request, Ensemble $ensemble)
|
public function destroy(Request $request, Ensemble $ensemble)
|
||||||
{
|
{
|
||||||
if(! Auth::user()->is_admin) abort(403);
|
if ($ensemble->seats->count() > 0) {
|
||||||
|
return redirect()->route('admin.ensembles.index')->with('error', 'Ensemble has students seated and cannot be deleted');
|
||||||
|
}
|
||||||
$ensemble->delete();
|
$ensemble->delete();
|
||||||
|
|
||||||
return redirect()->route('admin.ensembles.index')->with('success', 'Ensemble deleted successfully');
|
return redirect()->route('admin.ensembles.index')->with('success', 'Ensemble deleted successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateEnsemble(Request $request, Ensemble $ensemble)
|
public function updateEnsemble(Request $request, Ensemble $ensemble)
|
||||||
{
|
{
|
||||||
if(! Auth::user()->is_admin) abort(403);
|
|
||||||
request()->validate([
|
request()->validate([
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
'code' => 'required|max:6'
|
'code' => 'required|max:6',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$ensemble->update([
|
$ensemble->update([
|
||||||
'name' => request('name'),
|
'name' => request('name'),
|
||||||
'code' => request('code')
|
'code' => request('code'),
|
||||||
]);
|
]);
|
||||||
return redirect()->route('admin.ensembles.index')->with('success','Ensemble updated successfully');
|
|
||||||
|
return redirect()->route('admin.ensembles.index')->with('success', 'Ensemble updated successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function seatingLimits(Ensemble $ensemble)
|
public function seatingLimits(Ensemble $ensemble)
|
||||||
|
|
@ -65,33 +71,40 @@ class EnsembleController extends Controller
|
||||||
if ($ensemble->exists()) {
|
if ($ensemble->exists()) {
|
||||||
$ensemble->load('seatingLimits');
|
$ensemble->load('seatingLimits');
|
||||||
}
|
}
|
||||||
return view('admin.ensembles.seatingLimits',compact('ensemble','ensembles'));
|
|
||||||
|
return view('admin.ensembles.seatingLimits', compact('ensemble', 'ensembles'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function seatingLimitsSet(Request $request, Ensemble $ensemble)
|
public function seatingLimitsSet(Request $request, Ensemble $ensemble)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'audition' => 'required',
|
'audition' => 'required',
|
||||||
'audition.*' => ['integer','min:0']
|
'audition.*' => ['integer', 'min:0'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach($ensemble->auditions as $audition) {
|
foreach ($ensemble->auditions as $audition) {
|
||||||
SeatingLimit::upsert(
|
SeatingLimit::upsert(
|
||||||
[[
|
[
|
||||||
'ensemble_id' => $ensemble->id,
|
[
|
||||||
'audition_id' => $audition->id,
|
'ensemble_id' => $ensemble->id,
|
||||||
'maximum_accepted' => $request->audition[$audition->id]
|
'audition_id' => $audition->id,
|
||||||
]],
|
'maximum_accepted' => $request->audition[$audition->id],
|
||||||
uniqueBy: ['ensemble_id','audition_id'],
|
],
|
||||||
|
],
|
||||||
|
uniqueBy: ['ensemble_id', 'audition_id'],
|
||||||
update: ['maximum_accepted']
|
update: ['maximum_accepted']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return redirect()->route('admin.ensembles.seatingLimits')->with('success', 'Seating limits set for ' . $ensemble->name);
|
|
||||||
|
return redirect()->route('admin.ensembles.seatingLimits')->with('success',
|
||||||
|
'Seating limits set for '.$ensemble->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateEnsembleRank(Request $request)
|
public function updateEnsembleRank(Request $request)
|
||||||
{
|
{
|
||||||
if(! Auth::user()->is_admin) abort(403);
|
if (! Auth::user()->is_admin) {
|
||||||
|
abort(403);
|
||||||
|
}
|
||||||
|
|
||||||
$order = $request->input('order');
|
$order = $request->input('order');
|
||||||
$eventId = $request->input('event_id');
|
$eventId = $request->input('event_id');
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
</thead>
|
</thead>
|
||||||
<x-table.body>
|
<x-table.body>
|
||||||
@foreach($event->ensembles as $ensemble)
|
@foreach($event->ensembles as $ensemble)
|
||||||
<tr data-id="{{ $ensemble->id }}">
|
<tr data-id="{{ $ensemble->id }}" id="ensembleRow-{{$ensemble->id}}">
|
||||||
<x-table.td class="handle">
|
<x-table.td class="handle">
|
||||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M5 7h14M5 12h14M5 17h14"/>
|
<path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M5 7h14M5 12h14M5 17h14"/>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<x-modal>
|
<x-modal>
|
||||||
<x-slot:button_text>{{ $ensemble->name }}</x-slot:button_text>
|
<x-slot:button_text>{{ $ensemble->name }}</x-slot:button_text>
|
||||||
<x-slot:title class="font-semibold">Rename Ensemble {{ $ensemble->name }}</x-slot:title>
|
<x-slot:title class="font-semibold">Rename Ensemble {{ $ensemble->name }}</x-slot:title>
|
||||||
<x-form.form method="PATCH" action="{{ route('admin.ensembles.updateEnsemble', ['ensemble' => $ensemble->rank]) }}">
|
<x-form.form method="PATCH" action="{{ route('admin.ensembles.update', ['ensemble' => $ensemble->rank]) }}">
|
||||||
<x-form.body-grid columns="4">
|
<x-form.body-grid columns="4">
|
||||||
<x-form.field colspan="2" label_text="New Name" value="{{ $ensemble->name }}" name="name" />
|
<x-form.field colspan="2" label_text="New Name" value="{{ $ensemble->name }}" name="name" />
|
||||||
<x-form.field colspan="1" label_text="New Code" value="{{ $ensemble->code }}" name="code" />
|
<x-form.field colspan="1" label_text="New Code" value="{{ $ensemble->code }}" name="code" />
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Route::middleware(['auth', 'verified', CheckIfAdmin::class])->prefix('admin/')->
|
||||||
Route::post('/', 'store')->name('admin.ensembles.store');
|
Route::post('/', 'store')->name('admin.ensembles.store');
|
||||||
Route::delete('/{ensemble}', 'destroy')->name('admin.ensembles.destroy');
|
Route::delete('/{ensemble}', 'destroy')->name('admin.ensembles.destroy');
|
||||||
Route::post('/updateEnsembleRank', 'updateEnsembleRank')->name('admin.ensembles.updateEnsembleRank');
|
Route::post('/updateEnsembleRank', 'updateEnsembleRank')->name('admin.ensembles.updateEnsembleRank');
|
||||||
Route::patch('/{ensemble}', 'updateEnsemble')->name('admin.ensembles.updateEnsemble');
|
Route::patch('/{ensemble}', 'updateEnsemble')->name('admin.ensembles.update');
|
||||||
Route::get('/seating-limits', 'seatingLimits')->name('admin.ensembles.seatingLimits');
|
Route::get('/seating-limits', 'seatingLimits')->name('admin.ensembles.seatingLimits');
|
||||||
Route::get('/seating-limits/{ensemble}', 'seatingLimits')->name('admin.ensembles.seatingLimits.ensemble');
|
Route::get('/seating-limits/{ensemble}', 'seatingLimits')->name('admin.ensembles.seatingLimits.ensemble');
|
||||||
Route::post('/seating-limits/{ensemble}', 'seatingLimitsSet')->name('admin.ensembles.seatingLimits.ensemble.set');
|
Route::post('/seating-limits/{ensemble}', 'seatingLimitsSet')->name('admin.ensembles.seatingLimits.ensemble.set');
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Audition;
|
||||||
|
use App\Models\Ensemble;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\Event;
|
||||||
|
use App\Models\Seat;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
use function Pest\Laravel\delete;
|
||||||
|
use function Pest\Laravel\get;
|
||||||
|
use function Pest\Laravel\patch;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
it('allows only an admin to manage ensembles', function () {
|
||||||
|
get((route('admin.ensembles.index')))
|
||||||
|
->assertRedirect(route('home'));
|
||||||
|
actAsNormal();
|
||||||
|
get((route('admin.ensembles.index')))
|
||||||
|
->assertRedirect('/dashboard')
|
||||||
|
->assertSessionHas('error', 'You are not authorized to perform this action');
|
||||||
|
actasAdmin();
|
||||||
|
get((route('admin.ensembles.index')))
|
||||||
|
->assertOk();
|
||||||
|
});
|
||||||
|
it('has a form to create an ensemble', function () {
|
||||||
|
// Arrange
|
||||||
|
actAsAdmin();
|
||||||
|
// Act & Assert
|
||||||
|
get((route('admin.ensembles.index')))
|
||||||
|
->assertOk()
|
||||||
|
->assertSee('action="'.route('admin.ensembles.store').'"', false)
|
||||||
|
->assertSee('name="name"', false)
|
||||||
|
->assertSee('name="code"', false)
|
||||||
|
->assertSee('name="event_id"', false)
|
||||||
|
->assertSeeInOrder(['<button', 'type="submit"', '</button>'], false);
|
||||||
|
});
|
||||||
|
it('shows ensemble data', function () {
|
||||||
|
// Arrange
|
||||||
|
Ensemble::factory()->count(10)->create();
|
||||||
|
actAsAdmin();
|
||||||
|
// Act & Assert
|
||||||
|
$response = get((route('admin.ensembles.index')));
|
||||||
|
$response->assertOk();
|
||||||
|
$events = Event::all();
|
||||||
|
foreach ($events as $event) {
|
||||||
|
foreach ($event->ensembles as $ensemble) {
|
||||||
|
$response->assertSeeInOrder([
|
||||||
|
$event->name, '<td', $ensemble->id, '</td>', '<td', e($ensemble->name), '</td>',
|
||||||
|
], false);
|
||||||
|
}
|
||||||
|
$response->assertSee($event->name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it('shows a delete option for ensembles with no students seated', function () {
|
||||||
|
// Arrange
|
||||||
|
$event = Event::factory()->create();
|
||||||
|
$noSeatsEnsemble = Ensemble::factory()->create(['event_id' => $event->id]);
|
||||||
|
$seatsEnsemble = Ensemble::factory()->create(['event_id' => $event->id]);
|
||||||
|
$audition = Audition::factory()->create(['event_id' => $event->id]);
|
||||||
|
$entry = Entry::factory()->create(['audition_id' => $audition->id]);
|
||||||
|
Seat::create([
|
||||||
|
'ensemble_id' => $seatsEnsemble->id,
|
||||||
|
'audition_id' => $audition->id,
|
||||||
|
'seat' => 1,
|
||||||
|
'entry_id' => $entry->id,
|
||||||
|
]);
|
||||||
|
// Act & Assert
|
||||||
|
actAsAdmin();
|
||||||
|
$response = get((route('admin.ensembles.index')));
|
||||||
|
$response->assertOk();
|
||||||
|
$response->assertSee(route('admin.ensembles.destroy', $noSeatsEnsemble), false);
|
||||||
|
#$response->assertDontSee(route('admin.ensembles.destroy', $seatsEnsemble), false); // TODO figure out how to test for a delete form that does not also see an edit form
|
||||||
|
});
|
||||||
|
it('allows an administrator to delete an ensemble while no entries are seated', function () {
|
||||||
|
// Arrange
|
||||||
|
$event = Event::factory()->create();
|
||||||
|
$noSeatsEnsemble = Ensemble::factory()->create(['event_id' => $event->id]);
|
||||||
|
$seatsEnsemble = Ensemble::factory()->create(['event_id' => $event->id]);
|
||||||
|
$audition = Audition::factory()->create(['event_id' => $event->id]);
|
||||||
|
$entry = Entry::factory()->create(['audition_id' => $audition->id]);
|
||||||
|
Seat::create([
|
||||||
|
'ensemble_id' => $seatsEnsemble->id,
|
||||||
|
'audition_id' => $audition->id,
|
||||||
|
'seat' => 1,
|
||||||
|
'entry_id' => $entry->id,
|
||||||
|
]);
|
||||||
|
// Act & Assert
|
||||||
|
actAsAdmin();
|
||||||
|
delete((route('admin.ensembles.destroy', $noSeatsEnsemble)))
|
||||||
|
->assertRedirect(route('admin.ensembles.index'))
|
||||||
|
->assertSessionHas('success', 'Ensemble deleted successfully');
|
||||||
|
expect(Ensemble::find($noSeatsEnsemble->id))->toBeNull();
|
||||||
|
delete((route('admin.ensembles.destroy', $seatsEnsemble)))
|
||||||
|
->assertRedirect(route('admin.ensembles.index'))
|
||||||
|
->assertSessionHas('error', 'Ensemble has students seated and cannot be deleted');
|
||||||
|
});
|
||||||
|
it('does not allow a guest or normal user to delete an ensemble', function () {
|
||||||
|
$ensemble = Ensemble::factory()->create();
|
||||||
|
delete((route('admin.ensembles.destroy', $ensemble)))
|
||||||
|
->assertRedirect(route('home'));
|
||||||
|
actAsNormal();
|
||||||
|
delete((route('admin.ensembles.destroy', $ensemble)))
|
||||||
|
->assertRedirect('/dashboard')
|
||||||
|
->assertSessionHas('error', 'You are not authorized to perform this action');
|
||||||
|
});
|
||||||
|
it('includes a form to edit an ensemble', function () {
|
||||||
|
// Arrange
|
||||||
|
$ensemble = Ensemble::factory()->create();
|
||||||
|
actAsAdmin();
|
||||||
|
// Act & Assert
|
||||||
|
get((route('admin.ensembles.index')))
|
||||||
|
->assertOk()
|
||||||
|
->assertSee('action="'.route('admin.ensembles.update', $ensemble).'"', false);
|
||||||
|
});
|
||||||
|
it('allows an administrator to update an ensemble', function () {
|
||||||
|
// Arrange
|
||||||
|
$ensemble = Ensemble::factory()->create();
|
||||||
|
$newData = [
|
||||||
|
'name' => 'New Ensemble Name',
|
||||||
|
'code' => 'NEWC',
|
||||||
|
];
|
||||||
|
// Act & Assert
|
||||||
|
actAsAdmin();
|
||||||
|
$response = patch(route('admin.ensembles.update', $ensemble), $newData);
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
$response->assertRedirect(route('admin.ensembles.index'))
|
||||||
|
->assertSessionHas('success', 'Ensemble updated successfully')
|
||||||
|
->assertSessionHasNoErrors();
|
||||||
|
$postCheck = Ensemble::find($ensemble->id);
|
||||||
|
expect($postCheck->name)->toBe($newData['name'])
|
||||||
|
->and($postCheck->code)->toBe($newData['code']);
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue