Work on refactoring student controller and test
This commit is contained in:
parent
c22f3ddadf
commit
9717ae852e
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StudentStoreRequest;
|
||||
use App\Models\Audition;
|
||||
use App\Models\AuditLogEntry;
|
||||
use App\Models\Student;
|
||||
use App\Rules\UniqueFullNameAtSchool;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
|
|
@ -31,58 +31,24 @@ class StudentController extends Controller
|
|||
['students' => $students, 'auditions' => $auditions, 'shirtSizes' => $shirtSizes]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(StudentStoreRequest $request)
|
||||
{
|
||||
if ($request->user()->cannot('create', Student::class)) {
|
||||
abort(403);
|
||||
}
|
||||
$request->validate([
|
||||
'first_name' => ['required'],
|
||||
'last_name' => [
|
||||
'required',
|
||||
new UniqueFullNameAtSchool(request('first_name'), request('last_name'), Auth::user()->school_id),
|
||||
],
|
||||
'grade' => ['required', 'integer'],
|
||||
'shirt_size' => [
|
||||
'nullable',
|
||||
function ($attribute, $value, $fail) {
|
||||
if (! array_key_exists($value, Student::$shirtSizes)) {
|
||||
$fail("The selected $attribute is invalid.");
|
||||
}
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
$student = Student::create([
|
||||
'first_name' => request('first_name'),
|
||||
'last_name' => request('last_name'),
|
||||
'grade' => request('grade'),
|
||||
'first_name' => $request['first_name'],
|
||||
'last_name' => $request['last_name'],
|
||||
'grade' => $request['grade'],
|
||||
'school_id' => Auth::user()->school_id,
|
||||
]);
|
||||
if (request('shirt_size') !== 'none') {
|
||||
if ($request['shirt_size'] !== 'none') {
|
||||
$student->update(['optional_data->shirt_size' => $request['shirt_size']]);
|
||||
}
|
||||
$message = 'Created student #'.$student->id.' - '.$student->full_name().'<br>Grade: '.$student->grade.'<br>School: '.$student->school->name;
|
||||
AuditLogEntry::create([
|
||||
'user' => auth()->user()->email,
|
||||
'ip_address' => request()->ip(),
|
||||
'message' => $message,
|
||||
'affected' => [
|
||||
'students' => [$student->id],
|
||||
'schools' => [$student->school_id],
|
||||
],
|
||||
]);
|
||||
|
||||
return redirect('/students')->with('success', 'Student Created');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Student;
|
||||
use App\Rules\UniqueFullNameAtSchool;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use function array_key_exists;
|
||||
use function request;
|
||||
|
||||
class StudentStoreRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'first_name' => ['required'],
|
||||
'last_name' => [
|
||||
'required',
|
||||
new UniqueFullNameAtSchool(request('first_name'), request('last_name'), Auth::user()->school_id),
|
||||
],
|
||||
'grade' => ['required', 'integer'],
|
||||
'shirt_size' => [
|
||||
'nullable',
|
||||
function ($attribute, $value, $fail) {
|
||||
if (! array_key_exists($value, Student::$shirtSizes)) {
|
||||
$fail("The selected $attribute is invalid.");
|
||||
}
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\AuditLogEntry;
|
||||
use App\Models\Student;
|
||||
|
||||
class StudentObserver
|
||||
{
|
||||
/**
|
||||
* Handle the Student "created" event.
|
||||
*/
|
||||
public function created(Student $student): void
|
||||
{
|
||||
$message = 'Created student #'.$student->id.' - '.$student->full_name().'<br>Grade: '.$student->grade.'<br>School: '.$student->school->name;
|
||||
AuditLogEntry::create([
|
||||
'user' => auth()->user()->email ?? 'none',
|
||||
'ip_address' => request()->ip(),
|
||||
'message' => $message,
|
||||
'affected' => [
|
||||
'students' => [$student->id],
|
||||
'schools' => [$student->school_id],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Student "updated" event.
|
||||
*/
|
||||
public function updated(Student $student): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Student "deleted" event.
|
||||
*/
|
||||
public function deleted(Student $student): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Student "restored" event.
|
||||
*/
|
||||
public function restored(Student $student): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Student "force deleted" event.
|
||||
*/
|
||||
public function forceDeleted(Student $student): void
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -12,11 +12,13 @@ use App\Models\Entry;
|
|||
use App\Models\EntryFlag;
|
||||
use App\Models\SchoolEmailDomain;
|
||||
use App\Models\ScoreSheet;
|
||||
use App\Models\Student;
|
||||
use App\Observers\BonusScoreObserver;
|
||||
use App\Observers\EntryFlagObserver;
|
||||
use App\Observers\EntryObserver;
|
||||
use App\Observers\SchoolEmailDomainObserver;
|
||||
use App\Observers\ScoreSheetObserver;
|
||||
use App\Observers\StudentObserver;
|
||||
use App\Services\AuditionService;
|
||||
use App\Services\DoublerService;
|
||||
use App\Services\DrawService;
|
||||
|
|
@ -55,6 +57,7 @@ class AppServiceProvider extends ServiceProvider
|
|||
Entry::observe(EntryObserver::class);
|
||||
SchoolEmailDomain::observe(SchoolEmailDomainObserver::class);
|
||||
ScoreSheet::observe(ScoreSheetObserver::class);
|
||||
Student::observe(StudentObserver::class);
|
||||
EntryFlag::observe(EntryFlagObserver::class);
|
||||
|
||||
// Model::preventLazyLoading(! app()->isProduction());
|
||||
|
|
|
|||
|
|
@ -26,4 +26,13 @@ class StudentFactory extends Factory
|
|||
'grade' => rand(7, 12),
|
||||
];
|
||||
}
|
||||
|
||||
public function forSchool(School $school)
|
||||
{
|
||||
return $this->state(function (array $attributes) use ($school) {
|
||||
return [
|
||||
'school_id' => $school->id,
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
|||
|
||||
// Entry Related Routes
|
||||
Route::middleware([
|
||||
'auth', 'verified', 'can:create,App\Models\Entry',
|
||||
'auth', 'verified',
|
||||
])->controller(EntryController::class)->group(function () {
|
||||
Route::get('/entries', 'index')->name('entries.index');
|
||||
Route::get('/entries/create', 'create')->name('entries.create');
|
||||
|
|
@ -37,7 +37,7 @@ Route::middleware([
|
|||
|
||||
// Student Related Routes
|
||||
Route::middleware([
|
||||
'auth', 'verified', 'can:create,App\Models\Student',
|
||||
'auth', 'verified',
|
||||
])->controller(StudentController::class)->group(function () {
|
||||
Route::get('/students', 'index')->name('students.index');
|
||||
Route::post('students', 'store')->name('students.store');
|
||||
|
|
@ -61,7 +61,7 @@ Route::middleware(['auth', 'verified'])->controller(SchoolController::class)->gr
|
|||
|
||||
// Doubler Related Routes
|
||||
Route::middleware([
|
||||
'auth', 'verified', 'can:viewAny,App\Models\DoublerRequest',
|
||||
'auth', 'verified',
|
||||
])->controller(DoublerRequestController::class)->prefix('doubler_request')->group(function () {
|
||||
Route::get('/', 'index')->name('doubler_request.index');
|
||||
Route::post('/', 'makeRequest')->name('doubler_request.make_request');
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ it('shows students index only for a user with a school', function () {
|
|||
$user = User::factory()->create();
|
||||
$this->actingAs($user);
|
||||
get(route('students.index'))
|
||||
->assertStatus(403);
|
||||
->assertRedirect(route('dashboard'));
|
||||
|
||||
$school = School::factory()->create();
|
||||
$user->school_id = $school->id;
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ it('logs the entry creation', function () {
|
|||
$audition = Audition::factory()->create(['minimum_grade' => 9, 'maximum_grade' => 12]);
|
||||
$this->scribe->createEntry($student, $audition);
|
||||
$thisEntry = Entry::where('student_id', $student->id)->first();
|
||||
$logEntry = AuditLogEntry::first();
|
||||
$logEntry = AuditLogEntry::orderBy('id', 'desc')->first();
|
||||
expect($logEntry->message)->toEqual('Entered '.$thisEntry->student->full_name().' from '.$thisEntry->student->school->name.' in '.$audition->name.'.')
|
||||
->and($logEntry->affected['entries'])->toEqual([$thisEntry->id])
|
||||
->and($logEntry->affected['students'])->toEqual([$thisEntry->student_id])
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ it('logs changes', function () {
|
|||
$originalEntry = Entry::find($this->entry->id);
|
||||
$newAudition = Audition::factory()->create(['minimum_grade' => 9, 'maximum_grade' => 10, 'name' => 'Alphorn']);
|
||||
($this->entryScribe)($this->entry, ['audition' => $newAudition]);
|
||||
$logEntry = AuditLogEntry::latest()->first();
|
||||
$logEntry = AuditLogEntry::orderBy('id', 'desc')->first();
|
||||
expect($logEntry->affected['auditions'])->toEqual([$originalEntry->audition_id, $newAudition->id])
|
||||
->and($logEntry->affected['entries'])->toEqual([$this->entry->id])
|
||||
->and($logEntry->affected['students'])->toEqual([$this->entry->student_id])
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use App\Actions\Tabulation\EnterNoShow;
|
|||
use App\Actions\Tabulation\EnterScore;
|
||||
use App\Exceptions\AuditionAdminException;
|
||||
use App\Models\Audition;
|
||||
use App\Models\AuditLogEntry;
|
||||
use App\Models\Entry;
|
||||
use App\Models\SubscoreDefinition;
|
||||
use App\Models\User;
|
||||
|
|
@ -29,7 +30,7 @@ it('can enter a no-show', function () {
|
|||
|
||||
it('creates a log entry when entering a no-show', function () {
|
||||
($this->rollTaker)($this->entry);
|
||||
$logEntry = \App\Models\AuditLogEntry::latest()->first();
|
||||
$logEntry = AuditLogEntry::orderBy('id', 'desc')->first();
|
||||
expect($logEntry->message)->toStartWith('No Show has been entered for');
|
||||
});
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ it('can enter a failed prelim', function () {
|
|||
|
||||
it('creates a log entry when entering a failed prelim', function () {
|
||||
($this->rollTaker)($this->entry, 'failprelim');
|
||||
$logEntry = \App\Models\AuditLogEntry::latest()->first();
|
||||
$logEntry = AuditLogEntry::orderBy('id', 'desc')->first();
|
||||
expect($logEntry->message)->toStartWith('Failed prelim has been entered for');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
use App\Actions\Tabulation\EnterScore;
|
||||
use App\Exceptions\AuditionAdminException;
|
||||
use App\Models\Audition;
|
||||
use App\Models\AuditLogEntry;
|
||||
use App\Models\Entry;
|
||||
use App\Models\ScoreSheet;
|
||||
use App\Models\SubscoreDefinition;
|
||||
|
|
@ -122,6 +123,6 @@ it('removes a no-show flag from an entry', function () {
|
|||
|
||||
it('logs score entry', function () {
|
||||
($this->scribe)($this->judge1, $this->entry1, $this->possibleScoreArray);
|
||||
$logEntry = \App\Models\AuditLogEntry::latest()->first();
|
||||
$logEntry = AuditLogEntry::orderBy('id', 'desc')->first();
|
||||
expect($logEntry->message)->toStartWith('Entered Score for entry id ');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Audition;
|
||||
use App\Models\School;
|
||||
use App\Models\Student;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
describe('Test the index method of the student controller', function () {
|
||||
it('redirects to the dashboard if the user does not have a school', function () {
|
||||
$user = User::factory()->create();
|
||||
$this->actingAs($user);
|
||||
$response = $this->get(route('students.index'));
|
||||
$response->assertRedirect(route('dashboard'));
|
||||
actAsAdmin();
|
||||
$response = $this->get(route('students.index'));
|
||||
$response->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('redirects to the students index if the user has a school', function () {
|
||||
$user = User::factory()->create();
|
||||
$school = School::factory()->create();
|
||||
$user->school_id = $school->id;
|
||||
$user->save();
|
||||
$this->actingAs($user);
|
||||
$response = $this->get(route('students.index'));
|
||||
$response->assertOk();
|
||||
});
|
||||
it('returns the view students.index', function () {
|
||||
$user = User::factory()->create();
|
||||
$school = School::factory()->create();
|
||||
$audition = Audition::factory()->create();
|
||||
$student = Student::factory()->forSchool($school)->create();
|
||||
$user->school_id = $school->id;
|
||||
$user->save();
|
||||
$this->actingAs($user);
|
||||
$response = $this->get(route('students.index'));
|
||||
$response->assertViewIs('students.index')
|
||||
->assertViewHas('students', function ($students) use ($student) {
|
||||
return $students->contains($student);
|
||||
})
|
||||
->assertViewHas('auditions', function ($auditions) use ($audition) {
|
||||
return $auditions->contains($audition);
|
||||
})
|
||||
->assertSee(route('students.store'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test the store method of the student controller', function () {
|
||||
|
||||
});
|
||||
Loading…
Reference in New Issue