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]); }); });