From 89dd6a9a0ec3245e408aa88ddd67a059d66c48cd Mon Sep 17 00:00:00 2001 From: Matt Young Date: Thu, 4 Jul 2024 11:10:56 -0500 Subject: [PATCH] AdminEntriesEdit Page Test --- .../Controllers/Admin/EntryController.php | 9 +- app/Http/Middleware/CheckIfAdmin.php | 2 +- database/factories/AuditionFactory.php | 2 +- .../factories/SchoolEmailDomainFactory.php | 2 +- resources/views/admin/entries/edit.blade.php | 2 +- tests/Feature/Pages/Admin/EntriesEditTest.php | 136 +++++++++++++++--- tests/Feature/Pages/Admin/SchoolsShowTest.php | 2 +- tests/Feature/Pages/Admin/StudentEditTest.php | 2 +- 8 files changed, 132 insertions(+), 25 deletions(-) diff --git a/app/Http/Controllers/Admin/EntryController.php b/app/Http/Controllers/Admin/EntryController.php index d88d49d..e135475 100644 --- a/app/Http/Controllers/Admin/EntryController.php +++ b/app/Http/Controllers/Admin/EntryController.php @@ -11,6 +11,7 @@ use App\Models\Student; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use function auditionSetting; use function compact; use function to_route; @@ -139,21 +140,23 @@ class EntryController extends Controller 'Entries in auditions with advancement results published cannot be modified'); } $validData = request()->validate([ - 'student_id' => ['required', 'exists:students,id'], 'audition_id' => ['required', 'exists:auditions,id'], ]); $validData['for_seating'] = $request->get('for_seating') ? 1 : 0; $validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0; + if (! auditionSetting('advanceTo')) { + $validData['for_seating'] = 1; + } + $entry->update([ - 'student_id' => $validData['student_id'], 'audition_id' => $validData['audition_id'], 'for_seating' => $validData['for_seating'], 'for_advancement' => $validData['for_advancement'], ]); - return redirect('/admin/entries'); + return to_route('admin.entries.index')->with('success', 'Entry updated successfully'); } public function destroy(Request $request, Entry $entry) diff --git a/app/Http/Middleware/CheckIfAdmin.php b/app/Http/Middleware/CheckIfAdmin.php index 50d63ab..71c0ceb 100644 --- a/app/Http/Middleware/CheckIfAdmin.php +++ b/app/Http/Middleware/CheckIfAdmin.php @@ -20,7 +20,7 @@ class CheckIfAdmin return $next($request); } - return redirect(route('dashboard'))->with('error', 'You do not have admin access.'); + return redirect(route('dashboard'))->with('error', 'You are not authorized to perform this action'); } } diff --git a/database/factories/AuditionFactory.php b/database/factories/AuditionFactory.php index 484728f..124fd37 100644 --- a/database/factories/AuditionFactory.php +++ b/database/factories/AuditionFactory.php @@ -42,7 +42,7 @@ class AuditionFactory extends Factory return [ 'event_id' => $event->id, #'name' => $this->faker->randomElement($instruments).$this->faker->numberBetween(1, 1000), - 'name' => 'New Instrument ' . $this->faker->unique()->sentence(5), + 'name' => 'New Instrument ' . $this->faker->unique()->words(4,true), 'score_order' => $this->faker->numberBetween(2, 50), 'entry_deadline' => Carbon::tomorrow(), 'entry_fee' => 1000, diff --git a/database/factories/SchoolEmailDomainFactory.php b/database/factories/SchoolEmailDomainFactory.php index e6f4646..5773348 100644 --- a/database/factories/SchoolEmailDomainFactory.php +++ b/database/factories/SchoolEmailDomainFactory.php @@ -20,7 +20,7 @@ class SchoolEmailDomainFactory extends Factory $school = School::factory()->create(); return [ 'school_id' => $school->id, - 'domain' => $this->faker->domainName, + 'domain' => $this->faker->unique()->domainName, ]; } } diff --git a/resources/views/admin/entries/edit.blade.php b/resources/views/admin/entries/edit.blade.php index 9e66245..9f37e22 100644 --- a/resources/views/admin/entries/edit.blade.php +++ b/resources/views/admin/entries/edit.blade.php @@ -11,7 +11,7 @@ - + @if(! Seat::where('entry_id', $entry->id)->exists()) diff --git a/tests/Feature/Pages/Admin/EntriesEditTest.php b/tests/Feature/Pages/Admin/EntriesEditTest.php index 83b4f9a..5214742 100644 --- a/tests/Feature/Pages/Admin/EntriesEditTest.php +++ b/tests/Feature/Pages/Admin/EntriesEditTest.php @@ -2,11 +2,19 @@ use App\Models\Audition; use App\Models\Entry; +use App\Models\Room; +use App\Models\ScoringGuide; +use App\Models\SubscoreDefinition; +use App\Models\User; use App\Settings; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\Artisan; use Sinnbeck\DomAssertions\Asserts\AssertElement; +use Sinnbeck\DomAssertions\Asserts\AssertForm; +use Sinnbeck\DomAssertions\Asserts\AssertSelect; use function Pest\Laravel\get; +use function Pest\Laravel\patch; uses(RefreshDatabase::class); beforeEach(function () { @@ -47,26 +55,30 @@ it('has a delete link', function () { get(route('admin.entries.edit', $this->entry)) ->assertSee('', false); }); -it('has a dropdown for all auditions', function () { +it('has a dropdown for all auditions appropriate to the students grade', function () { // Arrange - $auditions = Audition::factory()->count(5)->create(); + $auditions = Audition::factory()->count(5)->create(['minimum_grade' => 1, 'maximum_grade' => 20]); + $oldAudition = Audition::factory()->create(['minimum_grade' => $this->entry->grade + 1]); + $youngAudition = Audition::factory()->create(['maximum_grade' => $this->entry->grade - 1]); actAsAdmin(); - $response = get(route('admin.entries.edit', $this->entry)); + $auditionsArray = []; foreach ($auditions as $audition) { - $response->assertSeeInOrder([ - 'option', - 'value=', - $audition->id, - 'option', - ], false); - $response->assertSeeInOrder([ - 'option', - 'value=', - $this->entry->audition->id, - 'selected', - 'option', - ], false); + $auditionsArray[] = ['value' => $audition->id, 'text' => $audition->name]; + break; } + $response = get(route('admin.entries.edit', $this->entry)); + $response->assertOk(); + // Act & Assert + foreach ($auditions as $audition) { + $response->assertOk() + ->assertFormExists('#entryEditForm', function (AssertForm $form) use ($audition) { + $form->findSelect('', function (AssertSelect $select) use ($audition) { + $select->containsOption(['value' => $audition->id, 'text' => $audition->name]); + }); + }); + } + $response->assertDontSee('value='.$oldAudition->id) + ->assertDontSee('value='.$youngAudition->id); }); it('shows checkboxes for entry types only if advancement is enabled', function () { actAsAdmin(); @@ -112,3 +124,95 @@ it('properly checks boxes based on entries settings', function () { }); // Submission tests +it('does not let a normal user update an entry', function () { + // Arrange + $newAudition = Audition::factory()->create(); + actAsNormal(); + // Act & Assert + patch(route('admin.entries.update', $this->entry), ['audition_id' => $newAudition->id]) + ->assertSessionHasNoErrors() + ->assertSessionHas('error', 'You are not authorized to perform this action') + ->assertRedirect(route('dashboard')); +}); +it('allows an admin to update an entry', function () { + // Arrange + $newAudition = Audition::factory()->create(); + actAsAdmin(); + // Act & Assert + patch(route('admin.entries.update', $this->entry), ['audition_id' => $newAudition->id]) + ->assertSessionHasNoErrors() + ->assertSessionHas('success', 'Entry updated successfully') + ->assertRedirect(route('admin.entries.index')); + $this->entry->refresh(); + expect($this->entry->audition_id)->toBe($newAudition->id) + ->and($this->entry->for_seating)->toBe(0) + ->and($this->entry->for_advancement)->toBe(0); +}); +it('does not allow an administrator to update an entry in a published audition', function () { + // Arrange + $newAudition = Audition::factory()->create(); + actAsAdmin(); + $this->entry->audition->addFlag('seats_published'); + // Act & Assert + patch(route('admin.entries.update', $this->entry), ['audition_id' => $newAudition->id]) + ->assertSessionHasNoErrors() + ->assertSessionHas('error', 'Entries in auditions with seats published cannot be modified') + ->assertRedirect(route('admin.entries.index')); + $checkEntry = $this->entry->fresh(); + expect($checkEntry->id === $this->entry->id)->toBeTrue() + ->and($checkEntry->audition_id === $this->entry->audition_id)->toBeTrue() + ->and($checkEntry->student_id === $this->entry->student_id)->toBeTrue() + ->and($checkEntry->for_seating === $this->entry->for_seating)->toBeTrue() + ->and($checkEntry->for_advancement === $this->entry->for_advancement)->toBeTrue(); +}); +it('does not allow an administrator to update an entry in an audition with published advancement results', function () { + // Arrange + $newAudition = Audition::factory()->create(); + actAsAdmin(); + $this->entry->audition->addFlag('advancement_published'); + // Act & Assert + patch(route('admin.entries.update', $this->entry), ['audition_id' => $newAudition->id]) + ->assertSessionHasNoErrors() + ->assertSessionHas('error', 'Entries in auditions with advancement results published cannot be modified') + ->assertRedirect(route('admin.entries.index')); + $checkEntry = $this->entry->fresh(); + expect($checkEntry->id === $this->entry->id)->toBeTrue() + ->and($checkEntry->audition_id === $this->entry->audition_id)->toBeTrue() + ->and($checkEntry->student_id === $this->entry->student_id)->toBeTrue() + ->and($checkEntry->for_seating === $this->entry->for_seating)->toBeTrue() + ->and($checkEntry->for_advancement === $this->entry->for_advancement)->toBeTrue(); +}); +it('always sets for_seating to true if advancement is not enabled', function () { + //arrange + Settings::set('advanceTo', ''); + $newAudition = Audition::factory()->create(); + actAsAdmin(); + // Act & Assert + patch(route('admin.entries.update', $this->entry), ['audition_id' => $newAudition->id]) + ->assertSessionHasNoErrors() + ->assertSessionHas('success', 'Entry updated successfully') + ->assertRedirect(route('admin.entries.index')); + $this->entry->refresh(); + expect($this->entry->audition_id)->toBe($newAudition->id) + ->and($this->entry->for_seating)->toBe(1); + +}); +it('displays scores', function () { + // Arrange + $sg = ScoringGuide::factory()->create(); + SubscoreDefinition::factory()->count(5)->create(['scoring_guide_id' => $sg->id]); + $room = Room::factory()->create(); + $judge = User::factory()->create(); + $room->addJudge($judge); + $audition = Audition::factory()->create(['room_id' => $room->id, 'scoring_guide_id' => $sg->id]); + $entry = Entry::factory()->create(['audition_id' => $audition->id]); + // Run the ScoreAllAuditions seeder + Artisan::call('db:seed', ['--class' => 'ScoreAllAuditions']); + // Act & Assert + actAsAdmin(); + $response = get(route('admin.entries.edit', $entry)) + ->assertSee($judge->full_name()); + foreach ($sg->subscores as $subscore) { + $response->assertSee($subscore->name); + } +}); diff --git a/tests/Feature/Pages/Admin/SchoolsShowTest.php b/tests/Feature/Pages/Admin/SchoolsShowTest.php index 0c01581..126b563 100644 --- a/tests/Feature/Pages/Admin/SchoolsShowTest.php +++ b/tests/Feature/Pages/Admin/SchoolsShowTest.php @@ -299,7 +299,7 @@ it('does not allow a non administrator to delete a student', function () { /** @noinspection PhpUnhandledExceptionInspection */ delete(route('admin.schools.destroy', $condemnedSchool)) ->assertSessionHasNoErrors() - ->assertSessionHas('error', 'You do not have admin access.') + ->assertSessionHas('error', 'You are not authorized to perform this action') ->assertRedirect(route('dashboard')); expect(School::find($condemnedSchool->id))->toBeInstanceOf(School::class); }); diff --git a/tests/Feature/Pages/Admin/StudentEditTest.php b/tests/Feature/Pages/Admin/StudentEditTest.php index e024ba5..4b9c5e1 100644 --- a/tests/Feature/Pages/Admin/StudentEditTest.php +++ b/tests/Feature/Pages/Admin/StudentEditTest.php @@ -220,7 +220,7 @@ it('does not allow a non administrator to delete a student', function () { /** @noinspection PhpUnhandledExceptionInspection */ delete(route('admin.students.destroy', $condemnedStudent)) ->assertSessionHasNoErrors() - ->assertSessionHas('error', 'You do not have admin access.') + ->assertSessionHas('error', 'You are not authorized to perform this action') ->assertRedirect(route('dashboard')); expect(Student::find($condemnedStudent->id))->toBeInstanceOf(Student::class); });