Add tests for admin/SchoolController
This commit is contained in:
parent
2e8d625ab0
commit
e4a646a4ce
|
|
@ -5,14 +5,12 @@ namespace App\Http\Controllers\Admin;
|
|||
use App\Actions\Schools\CreateSchool;
|
||||
use App\Actions\Schools\SetHeadDirector;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AuditLogEntry;
|
||||
use App\Http\Requests\SchoolStoreRequest;
|
||||
use App\Models\School;
|
||||
use App\Models\SchoolEmailDomain;
|
||||
use App\Models\User;
|
||||
use App\Services\Invoice\InvoiceDataService;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use function abort;
|
||||
use function redirect;
|
||||
use function request;
|
||||
|
||||
|
|
@ -39,46 +37,25 @@ class SchoolController extends Controller
|
|||
|
||||
public function show(School $school)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
return view('admin.schools.show', ['school' => $school]);
|
||||
}
|
||||
|
||||
public function edit(School $school)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
$school->loadCount('students');
|
||||
|
||||
return view('admin.schools.edit', ['school' => $school]);
|
||||
}
|
||||
|
||||
public function update(School $school)
|
||||
public function update(SchoolStoreRequest $request, School $school)
|
||||
{
|
||||
request()->validate([
|
||||
'name' => ['required'],
|
||||
'address' => ['required'],
|
||||
'city' => ['required'],
|
||||
'state' => ['required'],
|
||||
'zip' => ['required'],
|
||||
]);
|
||||
|
||||
$school->update([
|
||||
'name' => request('name'),
|
||||
'address' => request('address'),
|
||||
'city' => request('city'),
|
||||
'state' => request('state'),
|
||||
'zip' => request('zip'),
|
||||
]);
|
||||
$message = 'Modified school #'.$school->id.' - '.$school->name.' with address <br>'.$school->address.'<br>'.$school->city.', '.$school->state.' '.$school->zip;
|
||||
AuditLogEntry::create([
|
||||
'user' => auth()->user()->email,
|
||||
'ip_address' => request()->ip(),
|
||||
'message' => $message,
|
||||
'affected' => ['schools' => [$school->id]],
|
||||
'name' => $request['name'],
|
||||
'address' => $request['address'],
|
||||
'city' => $request['city'],
|
||||
'state' => $request['state'],
|
||||
'zip' => $request['zip'],
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.schools.show', ['school' => $school->id])->with('success',
|
||||
|
|
@ -87,48 +64,30 @@ class SchoolController extends Controller
|
|||
|
||||
public function create()
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
return view('admin.schools.create');
|
||||
}
|
||||
|
||||
public function store()
|
||||
public function store(SchoolStoreRequest $request)
|
||||
{
|
||||
$creator = app(CreateSchool::class);
|
||||
$validData = request()->validate([
|
||||
'name' => ['required', 'unique:schools,name'],
|
||||
'address' => ['required'],
|
||||
'city' => ['required'],
|
||||
'state' => ['required'],
|
||||
'zip' => ['required'],
|
||||
]);
|
||||
|
||||
$school = $creator(
|
||||
$validData['name'],
|
||||
$validData['address'],
|
||||
$validData['city'],
|
||||
$validData['state'],
|
||||
$validData['zip'],
|
||||
$request['name'],
|
||||
$request['address'],
|
||||
$request['city'],
|
||||
$request['state'],
|
||||
$request['zip'],
|
||||
);
|
||||
|
||||
return redirect('/admin/schools')->with('success', 'School '.$school->name.' created');
|
||||
return redirect(route('admin.schools.index'))->with('success', 'School '.$school->name.' created');
|
||||
}
|
||||
|
||||
public function destroy(School $school)
|
||||
{
|
||||
if ($school->students()->count() > 0) {
|
||||
return to_route('admin.schools.index')->with('error', 'You cannot delete a school with students.');
|
||||
return to_route('admin.schools.index')->with('error', 'You cannot delete a school that has students.');
|
||||
}
|
||||
$name = $school->name;
|
||||
$message = 'Delete school #'.$school->id.' - '.$school->name;
|
||||
AuditLogEntry::create([
|
||||
'user' => auth()->user()->email,
|
||||
'ip_address' => request()->ip(),
|
||||
'message' => $message,
|
||||
'affected' => ['schools' => [$school->id]],
|
||||
]);
|
||||
|
||||
$school->delete();
|
||||
|
||||
return to_route('admin.schools.index')->with('success', 'School '.$school->name.' deleted');
|
||||
|
|
@ -136,9 +95,6 @@ class SchoolController extends Controller
|
|||
|
||||
public function add_domain(School $school)
|
||||
{
|
||||
if (! Auth::user()->is_admin) {
|
||||
abort(403);
|
||||
}
|
||||
request()->validate([
|
||||
// validate that the combination of school and domain is unique on the school_email_domains table
|
||||
'domain' => ['required'],
|
||||
|
|
@ -147,12 +103,6 @@ class SchoolController extends Controller
|
|||
'school_id' => $school->id,
|
||||
'domain' => request('domain'),
|
||||
]);
|
||||
AuditLogEntry::create([
|
||||
'user' => auth()->user()->email,
|
||||
'ip_address' => request()->ip(),
|
||||
'message' => 'Added '.request('domain').' as an email domain for school #'.$school->id.' - '.$school->name,
|
||||
'affected' => ['schools' => [$school->id]],
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.schools.show', $school)->with('success', 'Domain Added');
|
||||
|
||||
|
|
@ -164,9 +114,11 @@ class SchoolController extends Controller
|
|||
$domain->delete();
|
||||
|
||||
// return a redirect to the previous URL
|
||||
return redirect()->back();
|
||||
return redirect()->back()->with('success', 'Domain removed successfully.');
|
||||
}
|
||||
|
||||
// TODO: Add testing for invoicing
|
||||
/** @codeCoverageIgnore */
|
||||
public function viewInvoice(School $school)
|
||||
{
|
||||
$invoiceData = $this->invoiceService->allData($school->id);
|
||||
|
|
@ -179,8 +131,9 @@ class SchoolController extends Controller
|
|||
if ($user->school_id !== $school->id) {
|
||||
return redirect()->back()->with('error', 'That user is not at that school');
|
||||
}
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$headSetter->setHeadDirector($user);
|
||||
|
||||
return redirect()->back()->with('success', 'Head director set');
|
||||
return redirect()->back()->with('success', 'Head director set successfully.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,21 @@ namespace App\Http\Requests;
|
|||
|
||||
use App\Models\School;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class SchoolStoreRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
$schoolId = $this->route('school');
|
||||
|
||||
return [
|
||||
'name' => ['required', 'min:3', 'max:30', 'unique:schools,name'],
|
||||
'name' => [
|
||||
'required',
|
||||
'min:3',
|
||||
'max:30',
|
||||
Rule::unique('schools', 'name')->ignore($schoolId),
|
||||
],
|
||||
'address' => ['required'],
|
||||
'city' => ['required'],
|
||||
'state' => ['required', 'min:2', 'max:2'],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,328 @@
|
|||
<?php
|
||||
|
||||
use App\Models\School;
|
||||
use App\Models\SchoolEmailDomain;
|
||||
use App\Models\Student;
|
||||
use App\Models\User;
|
||||
use App\Services\Invoice\InvoiceDataService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$mockInvoice = $this->createMock(InvoiceDataService::class);
|
||||
$mockInvoice->method('getGrandTotal')->willReturn(40.00);
|
||||
$this->app->instance(InvoiceDataService::class, $mockInvoice);
|
||||
});
|
||||
|
||||
describe('SchoolController::index', function () {
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->get(route('admin.schools.index'))
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->get(route('admin.schools.index'))
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->get(route('admin.schools.index'))
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('shows all schools', function () {
|
||||
School::factory()->count(3)->create();
|
||||
actAsAdmin();
|
||||
$response = $this->get(route('admin.schools.index'));
|
||||
$response->assertOk();
|
||||
foreach (School::all() as $school) {
|
||||
$response->assertSee($school->name);
|
||||
}
|
||||
$response->assertSee('$40.00');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::show', function () {
|
||||
beforeEach(function () {
|
||||
$this->school = School::factory()->create();
|
||||
});
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->get(route('admin.schools.show', $this->school))
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->get(route('admin.schools.show', $this->school))
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->get(route('admin.schools.show', $this->school))
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('shows the school details', function () {
|
||||
actAsAdmin();
|
||||
$response = $this->get(route('admin.schools.show', $this->school));
|
||||
$response->assertOk();
|
||||
$response->assertSee($this->school->name);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::edit', function () {
|
||||
beforeEach(function () {
|
||||
$this->school = School::factory()->create();
|
||||
});
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->get(route('admin.schools.edit', $this->school))
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->get(route('admin.schools.edit', $this->school))
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->get(route('admin.schools.edit', $this->school))
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('shows the school details', function () {
|
||||
actAsAdmin();
|
||||
$response = $this->get(route('admin.schools.edit', $this->school));
|
||||
$response->assertOk();
|
||||
$response->assertSee($this->school->name);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::update', function () {
|
||||
beforeEach(function () {
|
||||
$this->school = School::create([
|
||||
'name' => 'Test School',
|
||||
'address' => '123 4th street',
|
||||
'city' => 'New York',
|
||||
'state' => 'NY',
|
||||
'zip' => '10001',
|
||||
]);
|
||||
$this->newData = [
|
||||
'name' => 'New Name',
|
||||
'address' => '567 8th street',
|
||||
'city' => 'New Orleans',
|
||||
'state' => 'LA',
|
||||
'zip' => '70110',
|
||||
];
|
||||
});
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->patch(route('admin.schools.update', $this->school), $this->newData)
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->patch(route('admin.schools.update', $this->school), $this->newData)
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->patch(route('admin.schools.update', $this->school), $this->newData)
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('updates the school', function () {
|
||||
actAsAdmin();
|
||||
$this->patch(route('admin.schools.update', $this->school), $this->newData);
|
||||
$this->school->refresh();
|
||||
$this->assertEquals($this->newData['name'], $this->newData['name']);
|
||||
$this->assertEquals($this->newData['address'], $this->newData['address']);
|
||||
$this->assertEquals($this->newData['city'], $this->newData['city']);
|
||||
$this->assertEquals($this->newData['state'], $this->newData['state']);
|
||||
$this->assertEquals($this->newData['zip'], $this->newData['zip']);
|
||||
});
|
||||
it('will not let us duplicate a name', function () {
|
||||
$otherSchool = School::factory()->create();
|
||||
$this->newData['name'] = $otherSchool->name;
|
||||
actAsAdmin();
|
||||
$response = $this->patch(route('admin.schools.update', $this->school), $this->newData);
|
||||
$response->assertSessionHasErrors('name');
|
||||
$this->school->refresh();
|
||||
$this->assertNotEquals($this->school->name, $otherSchool->name);
|
||||
});
|
||||
it('will let us update other data and retain the name', function () {
|
||||
$this->newData['name'] = 'Test School';
|
||||
actAsAdmin();
|
||||
$response = $this->patch(route('admin.schools.update', $this->school), $this->newData);
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$response->assertSessionHasNoErrors();
|
||||
$this->school->refresh();
|
||||
$this->assertEquals($this->newData['address'], $this->newData['address']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::create', function () {
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->get(route('admin.schools.create'))
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->get(route('admin.schools.create'))
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->get(route('admin.schools.create'))
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('shows the school creation form', function () {
|
||||
actAsAdmin();
|
||||
$response = $this->get(route('admin.schools.create'));
|
||||
$response->assertOk();
|
||||
$response->assertSee('Create School');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::store', function () {
|
||||
beforeEach(function () {
|
||||
$this->newData = [
|
||||
'name' => 'Test School',
|
||||
'address' => '123 4th street',
|
||||
'city' => 'New York',
|
||||
'state' => 'NY',
|
||||
'zip' => '10001',
|
||||
];
|
||||
});
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->post(route('admin.schools.store'), $this->newData)
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->post(route('admin.schools.store'), $this->newData)
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->post(route('admin.schools.store'), $this->newData)
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('creates a new school', function () {
|
||||
actAsAdmin();
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$this->post(route('admin.schools.store'),
|
||||
$this->newData)->assertRedirect(route('admin.schools.index'))->assertSessionHasNoErrors();
|
||||
$newSchool = School::first();
|
||||
expect($newSchool)->toBeInstanceOf(School::class)
|
||||
->and($newSchool->name)->toEqual($this->newData['name'])
|
||||
->and($newSchool->address)->toEqual($this->newData['address'])
|
||||
->and($newSchool->city)->toEqual($this->newData['city'])
|
||||
->and($newSchool->state)->toEqual($this->newData['state'])
|
||||
->and($newSchool->zip)->toEqual($this->newData['zip']);
|
||||
});
|
||||
|
||||
it('will not let us duplicate a name', function () {
|
||||
$otherSchool = School::factory()->create();
|
||||
$this->newData['name'] = $otherSchool->name;
|
||||
actAsAdmin();
|
||||
$this->post(route('admin.schools.store'), $this->newData)->assertSessionHasErrors('name');
|
||||
$this->assertEquals(School::count(), 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::destroy', function () {
|
||||
beforeEach(function () {
|
||||
$this->school = School::factory()->create();
|
||||
});
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->delete(route('admin.schools.destroy', $this->school))
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->delete(route('admin.schools.destroy', $this->school))
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->delete(route('admin.schools.destroy', $this->school))
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
|
||||
it('deletes a school', function () {
|
||||
actAsAdmin();
|
||||
$this->delete(route('admin.schools.destroy', $this->school))->assertRedirect(route('admin.schools.index'));
|
||||
expect(School::count())->toEqual(0);
|
||||
});
|
||||
|
||||
it('will not delete a school with students', function () {
|
||||
Student::factory()->forSchool($this->school)->create();
|
||||
actAsAdmin();
|
||||
$response = $this->delete(route('admin.schools.destroy', $this->school));
|
||||
$response->assertRedirect(route('admin.schools.index'))
|
||||
->assertSessionHas('error', 'You cannot delete a school that has students.');
|
||||
|
||||
expect(School::count())->toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::add_domain', function () {
|
||||
beforeEach(function () {
|
||||
$this->school = School::factory()->create();
|
||||
});
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->post(route('admin.schools.add_domain', $this->school))
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->post(route('admin.schools.add_domain', $this->school))
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->post(route('admin.schools.add_domain', $this->school))
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
|
||||
it('can add a domain to a school', function () {
|
||||
actAsAdmin();
|
||||
$this->post(route('admin.schools.add_domain', $this->school),
|
||||
['domain' => 'test.com'])->assertRedirect(route('admin.schools.show', $this->school));
|
||||
$this->school->refresh();
|
||||
expect($this->school->emailDomains)->toHaveCount(1)
|
||||
->and($this->school->emailDomains->first()->domain)->toEqual('test.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::remove_domain', function () {
|
||||
beforeEach(function () {
|
||||
$this->school = School::factory()->create();
|
||||
$this->domain = SchoolEmailDomain::create([
|
||||
'school_id' => $this->school->id,
|
||||
'domain' => 'test.com',
|
||||
]);
|
||||
});
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->delete(route('admin.schools.destroy_domain', $this->domain))
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->delete(route('admin.schools.destroy_domain', $this->domain))
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->delete(route('admin.schools.destroy_domain', $this->domain))
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('can remove a domain from a school', function () {
|
||||
actAsAdmin();
|
||||
$this->delete(route('admin.schools.destroy_domain', $this->domain))->assertSessionHas('success',
|
||||
'Domain removed successfully.');
|
||||
$this->school->refresh();
|
||||
expect($this->school->emailDomains)->toHaveCount(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SchoolController::setHeadDirector', function () {
|
||||
beforeEach(function () {
|
||||
$this->school = School::factory()->create();
|
||||
$this->oldHeadDirector = User::factory()->forSchool($this->school)->create();
|
||||
$this->oldHeadDirector->addFlag('head_director');
|
||||
$this->newHeadDirector = User::factory()->forSchool($this->school)->create();
|
||||
$this->uneployedDirector = User::factory()->create();
|
||||
});
|
||||
it('denies access to a non-admin user', function () {
|
||||
$this->get(route('admin.schools.set_head_director', [$this->school, $this->newHeadDirector]))
|
||||
->assertRedirect(route('home'));
|
||||
actAsNormal();
|
||||
$this->get(route('admin.schools.set_head_director', [$this->school, $this->newHeadDirector]))
|
||||
->assertRedirect(route('dashboard'));
|
||||
actAsTab();
|
||||
$this->get(route('admin.schools.set_head_director', [$this->school, $this->newHeadDirector]))
|
||||
->assertRedirect(route('dashboard'));
|
||||
});
|
||||
it('can set a new head director', function () {
|
||||
actAsAdmin();
|
||||
$this->get(route('admin.schools.set_head_director', [$this->school, $this->newHeadDirector]))
|
||||
->assertSessionHas('success', 'Head director set successfully.');
|
||||
$this->school->refresh();
|
||||
$this->oldHeadDirector->refresh();
|
||||
$this->newHeadDirector->refresh();
|
||||
expect($this->oldHeadDirector->hasFlag('head_director'))->toBeFalse()
|
||||
->and($this->newHeadDirector->hasFlag('head_director'))->toBeTrue();
|
||||
});
|
||||
it('will not promote a user a the wrong school', function () {
|
||||
actAsAdmin();
|
||||
$this->get(route('admin.schools.set_head_director', [$this->school, $this->uneployedDirector]))
|
||||
->assertSessionHas('error', 'That user is not at that school');
|
||||
$this->school->refresh();
|
||||
$this->oldHeadDirector->refresh();
|
||||
$this->newHeadDirector->refresh();
|
||||
expect($this->oldHeadDirector->hasFlag('head_director'))->toBeTrue()
|
||||
->and($this->newHeadDirector->hasFlag('head_director'))->toBeFalse()
|
||||
->and($this->uneployedDirector->hasFlag('head_director'))->toBeFalse();
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue