AdminEntriesEdit Page Test

This commit is contained in:
Matt Young 2024-07-04 11:10:56 -05:00
parent 3fc4d13675
commit 89dd6a9a0e
8 changed files with 132 additions and 25 deletions

View File

@ -11,6 +11,7 @@ use App\Models\Student;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use function auditionSetting;
use function compact; use function compact;
use function to_route; use function to_route;
@ -139,21 +140,23 @@ class EntryController extends Controller
'Entries in auditions with advancement results published cannot be modified'); 'Entries in auditions with advancement results published cannot be modified');
} }
$validData = request()->validate([ $validData = request()->validate([
'student_id' => ['required', 'exists:students,id'],
'audition_id' => ['required', 'exists:auditions,id'], 'audition_id' => ['required', 'exists:auditions,id'],
]); ]);
$validData['for_seating'] = $request->get('for_seating') ? 1 : 0; $validData['for_seating'] = $request->get('for_seating') ? 1 : 0;
$validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0; $validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0;
if (! auditionSetting('advanceTo')) {
$validData['for_seating'] = 1;
}
$entry->update([ $entry->update([
'student_id' => $validData['student_id'],
'audition_id' => $validData['audition_id'], 'audition_id' => $validData['audition_id'],
'for_seating' => $validData['for_seating'], 'for_seating' => $validData['for_seating'],
'for_advancement' => $validData['for_advancement'], '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) public function destroy(Request $request, Entry $entry)

View File

@ -20,7 +20,7 @@ class CheckIfAdmin
return $next($request); 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');
} }
} }

View File

@ -42,7 +42,7 @@ class AuditionFactory extends Factory
return [ return [
'event_id' => $event->id, 'event_id' => $event->id,
#'name' => $this->faker->randomElement($instruments).$this->faker->numberBetween(1, 1000), #'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), 'score_order' => $this->faker->numberBetween(2, 50),
'entry_deadline' => Carbon::tomorrow(), 'entry_deadline' => Carbon::tomorrow(),
'entry_fee' => 1000, 'entry_fee' => 1000,

View File

@ -20,7 +20,7 @@ class SchoolEmailDomainFactory extends Factory
$school = School::factory()->create(); $school = School::factory()->create();
return [ return [
'school_id' => $school->id, 'school_id' => $school->id,
'domain' => $this->faker->domainName, 'domain' => $this->faker->unique()->domainName,
]; ];
} }
} }

View File

@ -11,7 +11,7 @@
</x-slot:right_side> </x-slot:right_side>
</x-card.heading> </x-card.heading>
<x-form.form method="PATCH" action="/admin/entries/{{ $entry->id }}"> <x-form.form id='entryEditForm' method="PATCH" action="/admin/entries/{{ $entry->id }}">
<x-form.body-grid columns="6"> <x-form.body-grid columns="6">
@if(! Seat::where('entry_id', $entry->id)->exists()) @if(! Seat::where('entry_id', $entry->id)->exists())
<x-form.select name="student_id" colspan="4" disabled> <x-form.select name="student_id" colspan="4" disabled>

View File

@ -2,11 +2,19 @@
use App\Models\Audition; use App\Models\Audition;
use App\Models\Entry; use App\Models\Entry;
use App\Models\Room;
use App\Models\ScoringGuide;
use App\Models\SubscoreDefinition;
use App\Models\User;
use App\Settings; use App\Settings;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Artisan;
use Sinnbeck\DomAssertions\Asserts\AssertElement; use Sinnbeck\DomAssertions\Asserts\AssertElement;
use Sinnbeck\DomAssertions\Asserts\AssertForm;
use Sinnbeck\DomAssertions\Asserts\AssertSelect;
use function Pest\Laravel\get; use function Pest\Laravel\get;
use function Pest\Laravel\patch;
uses(RefreshDatabase::class); uses(RefreshDatabase::class);
beforeEach(function () { beforeEach(function () {
@ -47,26 +55,30 @@ it('has a delete link', function () {
get(route('admin.entries.edit', $this->entry)) get(route('admin.entries.edit', $this->entry))
->assertSee('<input type="hidden" name="_method" value="DELETE">', false); ->assertSee('<input type="hidden" name="_method" value="DELETE">', false);
}); });
it('has a dropdown for all auditions', function () { it('has a dropdown for all auditions appropriate to the students grade', function () {
// Arrange // 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(); actAsAdmin();
$response = get(route('admin.entries.edit', $this->entry)); $auditionsArray = [];
foreach ($auditions as $audition) { foreach ($auditions as $audition) {
$response->assertSeeInOrder([ $auditionsArray[] = ['value' => $audition->id, 'text' => $audition->name];
'option', break;
'value=',
$audition->id,
'option',
], false);
$response->assertSeeInOrder([
'option',
'value=',
$this->entry->audition->id,
'selected',
'option',
], false);
} }
$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 () { it('shows checkboxes for entry types only if advancement is enabled', function () {
actAsAdmin(); actAsAdmin();
@ -112,3 +124,95 @@ it('properly checks boxes based on entries settings', function () {
}); });
// Submission tests // 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);
}
});

View File

@ -299,7 +299,7 @@ it('does not allow a non administrator to delete a student', function () {
/** @noinspection PhpUnhandledExceptionInspection */ /** @noinspection PhpUnhandledExceptionInspection */
delete(route('admin.schools.destroy', $condemnedSchool)) delete(route('admin.schools.destroy', $condemnedSchool))
->assertSessionHasNoErrors() ->assertSessionHasNoErrors()
->assertSessionHas('error', 'You do not have admin access.') ->assertSessionHas('error', 'You are not authorized to perform this action')
->assertRedirect(route('dashboard')); ->assertRedirect(route('dashboard'));
expect(School::find($condemnedSchool->id))->toBeInstanceOf(School::class); expect(School::find($condemnedSchool->id))->toBeInstanceOf(School::class);
}); });

View File

@ -220,7 +220,7 @@ it('does not allow a non administrator to delete a student', function () {
/** @noinspection PhpUnhandledExceptionInspection */ /** @noinspection PhpUnhandledExceptionInspection */
delete(route('admin.students.destroy', $condemnedStudent)) delete(route('admin.students.destroy', $condemnedStudent))
->assertSessionHasNoErrors() ->assertSessionHasNoErrors()
->assertSessionHas('error', 'You do not have admin access.') ->assertSessionHas('error', 'You are not authorized to perform this action')
->assertRedirect(route('dashboard')); ->assertRedirect(route('dashboard'));
expect(Student::find($condemnedStudent->id))->toBeInstanceOf(Student::class); expect(Student::find($condemnedStudent->id))->toBeInstanceOf(Student::class);
}); });