auditionadmin/tests/Feature/app/Models/EntryTest.php

250 lines
8.7 KiB
PHP

<?php
use App\Actions\Tabulation\RankAuditionEntries;
use App\Models\Audition;
use App\Models\Ensemble;
use App\Models\Entry;
use App\Models\EntryTotalScore;
use App\Models\ScoreSheet;
use App\Models\Student;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
beforeEach(function () {
$this->entry = Entry::factory()->create();
});
it('can return its total score', function () {
DB::table('entry_total_scores')->insert([
'entry_id' => $this->entry->id,
'seating_total' => 10,
'advancement_total' => 10,
'seating_subscore_totals' => json_encode([5, 5]),
'advancement_subscore_totals' => json_encode([5, 5]),
'bonus_total' => null,
]);
expect($this->entry->totalScore)->toBeInstanceOf(EntryTotalScore::class);
});
it('returns false if we try to get a rank when the audition is unscored', function () {
expect($this->entry->rank('seating'))->toBeFalse()
->and($this->entry->rank('advancement'))->toBeFalse();
});
it('should return the rank in its audition for seating', function () {
// We need the entry to be scored
DB::table('entry_total_scores')->insert([
'entry_id' => $this->entry->id,
'seating_total' => 10,
'advancement_total' => 10,
'seating_subscore_totals' => json_encode([5, 5]),
'advancement_subscore_totals' => json_encode([5, 5]),
'bonus_total' => null,
]);
// Prepare a collection of mocked entries
$mockedRankedEntries = collect([
(object) ['id' => 101, 'seatingRank' => 1],
(object) ['id' => 102, 'seatingRank' => 2],
(object) ['id' => 103, 'seatingRank' => 'declined'],
(object) ['id' => $this->entry->id, 'seatingRank' => 3],
(object) ['id' => 104, 'seatingRank' => 4],
]);
// Mock RankAuditionEntries to return the mocked collection
$mockRanker = Mockery::mock(RankAuditionEntries::class);
$mockRanker->shouldReceive('__invoke')
->once()
->andReturn($mockedRankedEntries);
// Bind the mock to the container
$this->app->instance(RankAuditionEntries::class, $mockRanker);
// Test the function
expect($this->entry->rank('seating'))->toEqual(3);
});
it('should return the rank in its audition for advancement', function () {
// We need the entry to be scored
DB::table('entry_total_scores')->insert([
'entry_id' => $this->entry->id,
'seating_total' => 10,
'advancement_total' => 10,
'seating_subscore_totals' => json_encode([5, 5]),
'advancement_subscore_totals' => json_encode([5, 5]),
'bonus_total' => null,
]);
// Prepare a collection of mocked entries
$mockedRankedEntries = collect([
(object) ['id' => 101, 'advancementRank' => 1],
(object) ['id' => 102, 'advancementRank' => 2],
(object) ['id' => 103, 'advancementRank' => 3],
(object) ['id' => $this->entry->id, 'advancementRank' => 4],
(object) ['id' => 104, 'advancementRank' => 5],
]);
// Mock RankAuditionEntries to return the mocked collection
$mockRanker = Mockery::mock(RankAuditionEntries::class);
$mockRanker->shouldReceive('__invoke')
->once()
->andReturn($mockedRankedEntries);
// Bind the mock to the container
$this->app->instance(RankAuditionEntries::class, $mockRanker);
// Test the function
expect($this->entry->rank('advancement'))->toEqual(4);
});
it('can return its student', function () {
expect($this->entry->student->id)->toEqual($this->entry->student_id)
->and(Entry::first()->student)->toBeInstanceOf(Student::class);
});
it('can return its audition', function () {
expect($this->entry->audition->id)->toEqual($this->entry->audition_id)
->and(Entry::first()->audition)->toBeInstanceOf(Audition::class);
});
it('can return its school', function () {
expect($this->entry->school)->toBeInstanceOf(App\Models\School::class)
->and($this->entry->school->id)->toEqual($this->entry->student->school->id);
});
it('can return its scoreSheets', function () {
$judge = User::factory()->create();
$judge2 = User::factory()->create();
DB::table('score_sheets')->insert([
[
'user_id' => $judge->id,
'entry_id' => $this->entry->id,
'subscores' => json_encode([5, 5, 5, 5, 5]),
'seating_total' => 5,
'advancement_total' => 5,
],
[
'user_id' => $judge2->id,
'entry_id' => $this->entry->id,
'subscores' => json_encode([5, 5, 5, 5, 5]),
'seating_total' => 5,
'advancement_total' => 5,
],
]);
expect($this->entry->scoreSheets()->count())->toBe(2)
->and($this->entry->scoreSheets()->first())->toBeInstanceOf(ScoreSheet::class);
});
it('can return bonus scores', function () {
$judge = User::factory()->create();
DB::table('bonus_scores')->insert([
'entry_id' => $this->entry->id,
'user_id' => $judge->id,
'originally_scored_entry' => $this->entry->id,
'score' => 28,
]);
expect($this->entry->bonusScores()->count())->toBe(1)
->and($this->entry->bonusScores()->first())->toBeInstanceOf(App\Models\BonusScore::class);
});
it('can return its advancement votes', function () {
$judge = User::factory()->create();
DB::table('judge_advancement_votes')->insert([
'user_id' => $judge->id,
'entry_id' => $this->entry->id,
'vote' => 'yes',
]);
expect($this->entry->advancementVotes()->count())->toBe(1)
->and($this->entry->advancementVotes()->first())->toBeInstanceOf(App\Models\JudgeAdvancementVote::class);
});
it('can return all of its flags set', function () {
$this->entry->addFlag('no_show');
$this->entry->addFlag('failed_prelim');
expect($this->entry->flags()->count())->toEqual(2)
->and($this->entry->flags()->first())->toBeInstanceOf(App\Models\EntryFlag::class);
});
it('can add a flag', function () {
expect($this->entry->flags()->count())->toEqual(0);
$this->entry->addFlag('no_show');
expect($this->entry->flags()->count())->toEqual(1);
});
it('can check for the presence of a given flag', function () {
expect($this->entry->hasFlag('no_show'))->toBeFalse();
$this->entry->addFlag('no_show');
expect($this->entry->hasFlag('no_show'))->toBeTrue();
});
it('can remove a flag', function () {
$this->entry->addFlag('no_show');
expect($this->entry->hasFlag('no_show'))->toBeTrue();
$this->entry->removeFlag('no_show');
expect($this->entry->hasFlag('no_show'))->toBeFalse();
});
it('will not duplicate a flag', function () {
$this->entry->addFlag('no_show');
$this->entry->addFlag('no_show');
expect($this->entry->flags()->count())->toEqual(1);
});
it('can always return a score sheet count', function () {
$judge = User::factory()->create();
$judge2 = User::factory()->create();
DB::table('score_sheets')->insert([
[
'user_id' => $judge->id,
'entry_id' => $this->entry->id,
'subscores' => json_encode([5, 5, 5, 5, 5]),
'seating_total' => 5,
'advancement_total' => 5,
],
[
'user_id' => $judge2->id,
'entry_id' => $this->entry->id,
'subscores' => json_encode([5, 5, 5, 5, 5]),
'seating_total' => 5,
'advancement_total' => 5,
],
]);
expect($this->entry->score_sheets_count)->toEqual(2);
});
it('returns its seat if it has one', function () {
expect($this->entry->seat)->toBeNull();
$ensemble = Ensemble::factory()->create();
DB::table('seats')->insert([
'ensemble_id' => $ensemble->id,
'audition_id' => $this->entry->audition_id,
'seat' => 5,
'entry_id' => $this->entry->id,
]);
$this->entry->refresh();
expect($this->entry->seat)->toBeInstanceOf(App\Models\Seat::class);
});
it('has a scope for only entries entered for seating', function () {
$newEntry = Entry::factory()->create(['for_seating' => false]);
expect(Entry::count())->toEqual(2)
->and(Entry::forSeating()->count())->toEqual(1);
});
it('has a scope for only entries entered for advancement', function () {
$newEntry = Entry::factory()->create(['for_advancement' => false]);
expect(Entry::count())->toEqual(2)
->and(Entry::forAdvancement()->count())->toEqual(1);
});
it('has a scope for only available entries', function () {
$declinedEntry = Entry::factory()->create();
$noShowEntry = Entry::factory()->create();
$failedEntry = Entry::factory()->create();
$declinedEntry->addFlag('declined');
$noShowEntry->addFlag('no_show');
$failedEntry->addFlag('failed_prelim');
expect(Entry::count())->toEqual(4)
->and(Entry::available()->count())->toEqual(1);
});