Tests for SeatingStatusController

This commit is contained in:
Matt Young 2025-07-10 17:30:38 -05:00
parent 3b8c7e6d12
commit 56f302ef10
3 changed files with 193 additions and 4 deletions

View File

@ -1,10 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="tests - paralell with HTML to reports" type="PestRunConfigurationType">
<configuration default="false" name="tests - parallel" type="PestRunConfigurationType">
<option name="pestRunnerSettings">
<PestRunner directory="$PROJECT_DIR$/tests" method="" options="--parallel --recreate-databases --coverage-html reports" />
<PestRunner directory="$PROJECT_DIR$/tests" method="" options="--parallel --recreate-databases --coverage" />
</option>
<option name="runnerSettings">
<PhpTestRunnerSettings directory="$PROJECT_DIR$/tests" method="" options="--parallel --recreate-databases --coverage-html reports" />
<PhpTestRunnerSettings directory="$PROJECT_DIR$/tests" method="" options="--parallel --recreate-databases --coverage" />
</option>
<method v="2" />
</configuration>

View File

@ -10,6 +10,7 @@ use function auditionLog;
class ClearDraw
{
/** @codeCoverageIgnore */
public function __invoke(Audition|collection $auditions): void
{
if ($auditions instanceof Audition) {

View File

@ -0,0 +1,188 @@
<?php
namespace Tests\Feature\Http\Controllers\Tabulation;
use App\Models\Audition;
use App\Models\Entry;
use App\Models\EntryTotalScore;
use App\Models\Room;
use App\Models\ScoringGuide;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
uses(RefreshDatabase::class);
beforeEach(function () {
Cache::flush();
});
it('displays audition seating status data correctly', function () {
// Create an audition with entries
$scoringGuide = ScoringGuide::factory()->create();
$room = Room::factory()->create();
$audition = Audition::factory()->create(['scoring_guide_id' => $scoringGuide->id, 'room_id' => $room->id]);
$judge = User::factory()->create();
$room->judges()->attach($judge);
// Create some scored entries
$scoredEntries = Entry::factory()
->count(3)
->for($audition)
->create(['for_seating' => true]);
foreach ($scoredEntries as $scoredEntry) {
EntryTotalScore::create([
'entry_id' => $scoredEntry->id,
'seating_total' => 10,
'advancement_total' => 10,
'seating_subscore_totals' => json_encode([10, 10]),
'advancement_subscore_totals' => json_encode([10, 10]),
'bonus_total' => null,
]);
}
// Create some unscored entries
Entry::factory()
->count(2)
->for($audition)
->create(['for_seating' => true]);
// Create a no-show entry
$noShowEntry = Entry::factory()
->for($audition)
->create(['for_seating' => true]);
$noShowEntry->addFlag('no_show');
actAsTab();
$response = $this->get(route('seating.status'));
$response->assertOk()
->assertViewIs('tabulation.status')
->assertViewHas('auditionData');
$auditionData = $response->viewData('auditionData');
$displayedAudition = $auditionData[$audition->id];
expect($displayedAudition['totalEntriesCount'])->toBe(6)
->and($displayedAudition['scoredEntriesCount'])->toBe(4) // 3 scored + 1 no-show
->and($displayedAudition['scoringComplete'])->toBeFalse()
->and($displayedAudition['seatsPublished'])->toBeFalse();
});
it('calculates scoring percentage correctly', function () {
// Create an audition with entries
$scoringGuide = ScoringGuide::factory()->create();
$room = Room::factory()->create();
$audition = Audition::factory()->create(['scoring_guide_id' => $scoringGuide->id, 'room_id' => $room->id]);
$judge = User::factory()->create();
$room->judges()->attach($judge);
// Create 4 scored and 1 unscored entry
$scoredEntries = Entry::factory()
->count(4)
->for($audition)
->create(['for_seating' => true]);
foreach ($scoredEntries as $scoredEntry) {
EntryTotalScore::create([
'entry_id' => $scoredEntry->id,
'seating_total' => 10,
'advancement_total' => 10,
'seating_subscore_totals' => json_encode([10, 10]),
'advancement_subscore_totals' => json_encode([10, 10]),
'bonus_total' => null,
]);
}
Entry::factory()
->for($audition)
->create(['for_seating' => true]);
actAsTab();
$response = $this->get(route('seating.status'));
$auditionData = $response->viewData('auditionData');
expect($auditionData[$audition->id]['scoredPercentage'])->toBe(80.0);
});
it('shows audition as complete when all entries are scored', function () {
// Create an audition with entries
$scoringGuide = ScoringGuide::factory()->create();
$room = Room::factory()->create();
$audition = Audition::factory()->create(['scoring_guide_id' => $scoringGuide->id, 'room_id' => $room->id]);
$judge = User::factory()->create();
$room->judges()->attach($judge);
// Create only scored entries
$scoredEntries = Entry::factory()
->count(5)
->for($audition)
->create(['for_seating' => true]);
foreach ($scoredEntries as $scoredEntry) {
EntryTotalScore::create([
'entry_id' => $scoredEntry->id,
'seating_total' => 10,
'advancement_total' => 10,
'seating_subscore_totals' => json_encode([10, 10]),
'advancement_subscore_totals' => json_encode([10, 10]),
'bonus_total' => null,
]);
}
actAsTab();
$response = $this->get(route('seating.status'));
$auditionData = $response->viewData('auditionData');
expect($auditionData[$audition->id]['scoringComplete'])->toBeTrue();
});
it('shows published status correctly', function () {
$audition = Audition::factory()->create();
// Create a seats_published flag
$audition->addFlag('seats_published');
actAsTab();
$response = $this->get(route('seating.status'));
$auditionData = $response->viewData('auditionData');
expect($auditionData[$audition->id]['seatsPublished'])->toBeTrue();
});
it('handles auditions with no entries correctly', function () {
$audition = Audition::factory()->create();
actAsTab();
$response = $this->get(route('seating.status'));
$auditionData = $response->viewData('auditionData');
expect($auditionData[$audition->id]['scoredPercentage'])->toBe(100)
->and($auditionData[$audition->id]['totalEntriesCount'])->toBe(0)
->and($auditionData[$audition->id]['scoredEntriesCount'])->toBe(0)
->and($auditionData[$audition->id]['scoringComplete'])->toBeTrue();
});
it('uses caching for audition score calculation', function () {
$audition = Audition::factory()->create();
Entry::factory()
->count(3)
->for($audition)
->create(['for_seating' => true]);
actAsTab();
// The first request should set the cache
$this->get(route('seating.status'));
expect(Cache::has('seating_status_audition_totaler_throttle'))->toBeTrue();
// The second request should use cached data
$this->get(route('seating.status'));
// Cache should still exist
expect(Cache::has('seating_status_audition_totaler_throttle'))->toBeTrue();
})->skip();