412 lines
20 KiB
PHP
412 lines
20 KiB
PHP
<?php
|
|
|
|
use App\Models\Audition;
|
|
use App\Models\Ensemble;
|
|
use App\Models\Entry;
|
|
use App\Models\Event;
|
|
use App\Models\Student;
|
|
use App\Models\User;
|
|
use App\Settings;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
use function Pest\Laravel\assertDatabaseMissing;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$this->event = Event::factory()->create();
|
|
$this->auditions = Audition::factory()->count(2)->create(['event_id' => $this->event->id]);
|
|
$this->students = Student::factory()->count(2)->create();
|
|
$this->entry1 = Entry::factory()->create([
|
|
'audition_id' => $this->auditions[0]->id, 'student_id' => $this->students[0]->id, 'for_seating' => 1,
|
|
'for_advancement' => 0,
|
|
]);
|
|
$this->entry2 = Entry::factory()->create([
|
|
'audition_id' => $this->auditions[1]->id, 'student_id' => $this->students[1]->id, 'for_seating' => 1,
|
|
'for_advancement' => 1,
|
|
]);
|
|
$this->entry3 = Entry::factory()->create([
|
|
'audition_id' => $this->auditions[0]->id, 'student_id' => $this->students[1]->id, 'for_seating' => 0,
|
|
'for_advancement' => 1,
|
|
]);
|
|
$this->entry4 = Entry::factory()->create([
|
|
'audition_id' => $this->auditions[1]->id, 'student_id' => $this->students[0]->id, 'for_seating' => 1,
|
|
'for_advancement' => 1,
|
|
]);
|
|
$this->entry1->student->update(['grade' => 9]);
|
|
$this->entry2->student->update(['grade' => 10]);
|
|
});
|
|
|
|
describe('EntryController::index', function () {
|
|
it('denies access to non-admins', function () {
|
|
$this->get(route('admin.entries.index'))->assertRedirect(route('home'));
|
|
actAsNormal();
|
|
$this->get(route('admin.entries.index'))->assertRedirect(route('dashboard'));
|
|
actAsTab();
|
|
$this->get(route('admin.entries.index'))->assertRedirect(route('dashboard'));
|
|
});
|
|
it('provides a list of entries', function () {
|
|
actAsAdmin();
|
|
$response = $this->get(route('admin.entries.index'))->assertOk()
|
|
->assertViewIs('admin.entries.index');
|
|
foreach (Entry::all() as $entry) {
|
|
$response->assertSee($entry->student->full_name());
|
|
$response->assertSee($entry->audition->name);
|
|
}
|
|
});
|
|
describe('test filters', function () {
|
|
it('can filter by ID', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'id' => $this->entry4->id,
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$response->assertSee($this->entry4->student->full_name())
|
|
->assertDontSee($this->entry2->student->full_name());
|
|
});
|
|
it('can filter by first_name', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'first_name' => $this->entry4->student->first_name,
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$response->assertSee($this->entry4->student->full_name())
|
|
->assertDontSee($this->entry2->student->full_name());
|
|
});
|
|
it('can filter by last_name', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'last_name' => $this->entry4->student->last_name,
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$response->assertSee($this->entry4->student->full_name())
|
|
->assertDontSee($this->entry2->student->full_name());
|
|
});
|
|
it('can filter by audition', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'audition' => $this->entry1->audition_id,
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$returnedEntries = $response->viewData('entries');
|
|
expect($returnedEntries->contains('id', $this->entry1->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry2->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry3->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry4->id))->toBeFalse();
|
|
});
|
|
it('can filter by school', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'school' => $this->entry1->student->school_id,
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$returnedEntries = $response->viewData('entries');
|
|
expect($returnedEntries->contains('id', $this->entry1->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry2->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry3->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry4->id))->toBeTrue();
|
|
});
|
|
it('can filter by grade', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'grade' => 9,
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$returnedEntries = $response->viewData('entries');
|
|
expect($returnedEntries->contains('id', $this->entry1->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry2->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry3->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry4->id))->toBeTrue();
|
|
});
|
|
it('can show auditions entered in seating', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'entry_type' => 'seats',
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$returnedEntries = $response->viewData('entries');
|
|
expect($returnedEntries->contains('id', $this->entry1->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry2->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry3->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry4->id))->toBeTrue();
|
|
});
|
|
it('can show auditions entered in advancement', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'entry_type' => 'advancement',
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$returnedEntries = $response->viewData('entries');
|
|
expect($returnedEntries->contains('id', $this->entry1->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry2->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry3->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry4->id))->toBeTrue();
|
|
});
|
|
it('can show auditions entered only in seating', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'entry_type' => 'seatsOnly',
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$returnedEntries = $response->viewData('entries');
|
|
expect($returnedEntries->contains('id', $this->entry1->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry2->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry3->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry4->id))->toBeFalse();
|
|
});
|
|
it('can show auditions entered only in advancement', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'entry_type' => 'advancementOnly',
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$returnedEntries = $response->viewData('entries');
|
|
expect($returnedEntries->contains('id', $this->entry1->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry2->id))->toBeFalse()
|
|
->and($returnedEntries->contains('id', $this->entry3->id))->toBeTrue()
|
|
->and($returnedEntries->contains('id', $this->entry4->id))->toBeFalse();
|
|
});
|
|
it('can limit the number of results per page', function () {
|
|
actAsAdmin();
|
|
$response = $this->withSession([
|
|
'adminEntryFilters' => [
|
|
'entries_per_page' => 1,
|
|
],
|
|
])->get(route('admin.entries.index'))->assertOk();
|
|
$returnedEntries = $response->viewData('entries');
|
|
expect($returnedEntries->count())->toEqual(1);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('EntryController::create', function () {
|
|
it('denies access to non-admins', function () {
|
|
$this->get(route('admin.entries.create'))->assertRedirect(route('home'));
|
|
actAsNormal();
|
|
$this->get(route('admin.entries.create'))->assertRedirect(route('dashboard'));
|
|
actAsTab();
|
|
$this->get(route('admin.entries.create'))->assertRedirect(route('dashboard'));
|
|
});
|
|
it('provides a form to make an entry', function () {
|
|
actAsAdmin();
|
|
$response = $this->get(route('admin.entries.create'));
|
|
$response->assertOk();
|
|
});
|
|
it('provides auditions to the form', function () {
|
|
actAsAdmin();
|
|
$response = $this->get(route('admin.entries.create'));
|
|
$response->assertOk();
|
|
$response->assertViewHas('auditions');
|
|
$returnedAuditions = $response->viewData('auditions');
|
|
foreach (Audition::all() as $audition) {
|
|
expect($returnedAuditions->contains('id', $audition->id))->toBeTrue();
|
|
}
|
|
});
|
|
it('does not provide published auditions to the form', function () {
|
|
actAsAdmin();
|
|
$unavailableAudition[0] = Audition::factory()->create();
|
|
$unavailableAudition[0]->addFlag('seats_published');
|
|
$unavailableAudition[1] = Audition::factory()->create();
|
|
$unavailableAudition[1]->addFlag('advancement_published');
|
|
|
|
$response = $this->get(route('admin.entries.create'));
|
|
$response->assertOk();
|
|
$response->assertViewHas('auditions');
|
|
$returnedAuditions = $response->viewData('auditions');
|
|
foreach ($unavailableAudition as $audition) {
|
|
expect($returnedAuditions->contains('id', $audition->id))->toBeFalse();
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('EntryController::store', function () {
|
|
beforeEach(function () {
|
|
$this->testAudition = Audition::factory()->create();
|
|
$this->testStudent = Student::factory()->create();
|
|
$this->testSubmitData = [
|
|
'student_id' => $this->testStudent->id,
|
|
'audition_id' => $this->testAudition->id,
|
|
'for_seating' => 'on',
|
|
'for_advancement' => 'on',
|
|
'late_fee_waived' => 'on',
|
|
];
|
|
});
|
|
it('denies access to non-admins', function () {
|
|
$this->post(route('admin.entries.store'), $this->testSubmitData)->assertRedirect(route('home'));
|
|
actAsNormal();
|
|
$this->post(route('admin.entries.store'), $this->testSubmitData)->assertRedirect(route('dashboard'));
|
|
actAsTab();
|
|
$this->post(route('admin.entries.store'), $this->testSubmitData)->assertRedirect(route('dashboard'));
|
|
});
|
|
it('creates an entry', function () {
|
|
$startingEntryCount = Entry::count();
|
|
actAsAdmin();
|
|
$this->post(route('admin.entries.store'), $this->testSubmitData);
|
|
expect(Entry::count())->toEqual($startingEntryCount + 1);
|
|
});
|
|
});
|
|
|
|
describe('EntryController::edit', function () {
|
|
it('denies access to non-admins', function () {
|
|
$this->get(route('admin.entries.edit', $this->entry1))->assertRedirect(route('home'));
|
|
actAsNormal();
|
|
$this->get(route('admin.entries.edit', $this->entry1))->assertRedirect(route('dashboard'));
|
|
actAsTab();
|
|
$this->get(route('admin.entries.edit', $this->entry1))->assertRedirect(route('dashboard'));
|
|
});
|
|
it('will not edit a published audition', function () {
|
|
actAsAdmin();
|
|
$this->entry1->audition->addFlag('seats_published');
|
|
$this->entry1->refresh();
|
|
$this->get(route('admin.entries.edit', $this->entry1))->assertRedirect(route('admin.entries.index'))
|
|
->assertSessionHas('error', 'Entries in auditions with seats published cannot be modified');
|
|
$this->entry2->audition->addFlag('advancement_published');
|
|
$this->entry2->refresh();
|
|
$this->get(route('admin.entries.edit', $this->entry2))->assertRedirect(route('admin.entries.index'))
|
|
->assertSessionHas('error', 'Entries in auditions with advancement results published cannot be modified');
|
|
});
|
|
it('presents a form to edit an entry', function () {
|
|
actAsAdmin();
|
|
$this->get(route('admin.entries.edit', $this->entry1))->assertOk()
|
|
->assertViewIs('admin.entries.edit');
|
|
});
|
|
});
|
|
|
|
describe('EntryController::update', function () {
|
|
it('denies access to non-admins', function () {
|
|
$this->patch(route('admin.entries.update', $this->entry1))->assertRedirect(route('home'));
|
|
actAsNormal();
|
|
$this->patch(route('admin.entries.update', $this->entry1))->assertRedirect(route('dashboard'));
|
|
actAsTab();
|
|
$this->patch(route('admin.entries.update', $this->entry1))->assertRedirect(route('dashboard'));
|
|
});
|
|
it('will not update an entry whose current audition has published seats', function () {
|
|
actAsAdmin();
|
|
$this->auditions[0]->addFlag('seats_published');
|
|
$response = $this->patch(route('admin.entries.update', $this->entry1), [
|
|
'audition_id' => $this->auditions[1]->id,
|
|
]);
|
|
$response->assertRedirect(route('admin.entries.index'))->assertSessionHas('error',
|
|
'Entries in published auditions cannot be modified');
|
|
});
|
|
it('will not update an entry whose current audition has published advancement', function () {
|
|
actAsAdmin();
|
|
$this->auditions[0]->addFlag('advancement_published');
|
|
$response = $this->patch(route('admin.entries.update', $this->entry1), [
|
|
'audition_id' => $this->auditions[1]->id,
|
|
]);
|
|
$response->assertRedirect(route('admin.entries.index'))->assertSessionHas('error',
|
|
'Entries in published auditions cannot be modified');
|
|
});
|
|
it('will not update an entry whose proposed audition has published seats', function () {
|
|
actAsAdmin();
|
|
$this->auditions[1]->addFlag('seats_published');
|
|
$response = $this->patch(route('admin.entries.update', $this->entry1), [
|
|
'audition_id' => $this->auditions[1]->id,
|
|
]);
|
|
$response->assertRedirect(route('admin.entries.index'))->assertSessionHas('error',
|
|
'Entries cannot be moved to published auditions');
|
|
});
|
|
it('will not update an entry whose proposed audition has published advancement', function () {
|
|
actAsAdmin();
|
|
$this->auditions[1]->addFlag('advancement_published');
|
|
$response = $this->patch(route('admin.entries.update', $this->entry1), [
|
|
'audition_id' => $this->auditions[1]->id,
|
|
]);
|
|
$response->assertRedirect(route('admin.entries.index'))->assertSessionHas('error',
|
|
'Entries cannot be moved to published auditions');
|
|
});
|
|
it('chan change entry type', function () {
|
|
actAsAdmin();
|
|
$response = $this->patch(route('admin.entries.update', $this->entry1), [
|
|
'audition_id' => $this->auditions[0]->id,
|
|
'for_advancement' => 'on',
|
|
]);
|
|
$response->assertRedirect(route('admin.entries.index'));
|
|
$this->entry1->refresh();
|
|
expect($this->entry1->for_seating)->toBeFalsy()
|
|
->and($this->entry1->for_advancement)->toBeTruthy();
|
|
});
|
|
it('can waive late fees', function () {
|
|
actAsAdmin();
|
|
$response = $this->patch(route('admin.entries.update', $this->entry1), [
|
|
'audition_id' => $this->auditions[0]->id,
|
|
'for_advancement' => 'on',
|
|
'late_fee_waived' => 'on',
|
|
]);
|
|
$response->assertRedirect(route('admin.entries.index'));
|
|
$this->entry1->refresh();
|
|
expect($this->entry1->hasFlag('late_fee_waived'))->toBeTruthy();
|
|
});
|
|
it('if we dont have advancement, for_seating must be true', function () {
|
|
actAsAdmin();
|
|
Settings::set('advanceTo', '');
|
|
$response = $this->patch(route('admin.entries.update', $this->entry1), [
|
|
'audition_id' => $this->auditions[0]->id,
|
|
]);
|
|
$response->assertRedirect(route('admin.entries.index'));
|
|
$this->entry1->refresh();
|
|
expect($this->entry1->for_seating)->toBeTruthy()
|
|
->and($this->entry1->for_advancement)->toBeFalsy();
|
|
});
|
|
});
|
|
|
|
describe('EntryController::destroy', function () {
|
|
it('denies access to non-admins', function () {
|
|
$this->delete(route('admin.entries.destroy', $this->entry1))->assertRedirect(route('home'));
|
|
actAsNormal();
|
|
$this->delete(route('admin.entries.destroy', $this->entry1))->assertRedirect(route('dashboard'));
|
|
actAsTab();
|
|
$this->delete(route('admin.entries.destroy', $this->entry1))->assertRedirect(route('dashboard'));
|
|
});
|
|
it('will not delete an entry with a published audition', function () {
|
|
actAsAdmin();
|
|
$this->auditions[0]->addFlag('seats_published');
|
|
$this->auditions[1]->addFlag('advancement_published');
|
|
$this->delete(route('admin.entries.destroy', $this->entry1))->assertRedirect(route('admin.entries.index'))
|
|
->assertSessionHas('error', 'Entries in published auditions cannot be deleted');
|
|
$this->delete(route('admin.entries.destroy', $this->entry2))->assertRedirect(route('admin.entries.index'))
|
|
->assertSessionHas('error', 'Entries in published auditions cannot be deleted');
|
|
});
|
|
it('will not delete an entry that is seated', function () {
|
|
actAsAdmin();
|
|
$ensemble = Ensemble::factory()->create();
|
|
DB::table('seats')->insert([
|
|
'ensemble_id' => $ensemble->id,
|
|
'audition_id' => $this->entry1->audition_id,
|
|
'seat' => 1,
|
|
'entry_id' => $this->entry1->id,
|
|
]);
|
|
$this->delete(route('admin.entries.destroy', $this->entry1))->assertRedirect(route('admin.entries.index'))
|
|
->assertSessionHas('error', 'Cannot delete an entry that is seated');
|
|
});
|
|
it('will not delete an entry that is scored', function () {
|
|
actAsAdmin();
|
|
DB::table('score_sheets')->insert([
|
|
'user_id' => User::factory()->create()->id,
|
|
'entry_id' => $this->entry1->id,
|
|
'subscores' => json_encode([3, 5, 6]),
|
|
'seating_total' => 44,
|
|
'advancement_total' => 55,
|
|
]);
|
|
$this->delete(route('admin.entries.destroy', $this->entry1))->assertRedirect(route('admin.entries.index'))
|
|
->assertSessionHas('error', 'Cannot delete an entry that has been scored');
|
|
});
|
|
it('can delete an entry', function () {
|
|
actAsAdmin();
|
|
$this->delete(route('admin.entries.destroy', $this->entry1))->assertRedirect(route('admin.entries.index'))
|
|
->assertSessionHas('success', 'Entry Deleted');
|
|
assertDatabaseMissing('entries', ['id' => $this->entry1->id]);
|
|
});
|
|
});
|