Cleanup and add test for seating status screen
This commit is contained in:
parent
4ff5e1dbcb
commit
d45ebf4eec
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Tabulation;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class SeatAuditionController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle the incoming request.
|
||||||
|
*/
|
||||||
|
public function __invoke(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ class SeatingStatusController extends Controller
|
||||||
$auditions = Audition::forSeating()->withCount(['entries', 'unscoredEntries'])->with('flags')->get();
|
$auditions = Audition::forSeating()->withCount(['entries', 'unscoredEntries'])->with('flags')->get();
|
||||||
$auditionData = [];
|
$auditionData = [];
|
||||||
foreach ($auditions as $audition) {
|
foreach ($auditions as $audition) {
|
||||||
$auditionData[] = [
|
$auditionData[$audition->id] = [
|
||||||
'id' => $audition->id,
|
'id' => $audition->id,
|
||||||
'name' => $audition->name,
|
'name' => $audition->name,
|
||||||
'scoredEntriesCount' => $audition->entries_count - $audition->unscored_entries_count,
|
'scoredEntriesCount' => $audition->entries_count - $audition->unscored_entries_count,
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class Audition extends Model
|
||||||
return $this->hasMany(Entry::class);
|
return $this->hasMany(Entry::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unscoredEntries()
|
public function unscoredEntries(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Entry::class)
|
return $this->hasMany(Entry::class)
|
||||||
->whereDoesntHave('scoreSheets');
|
->whereDoesntHave('scoreSheets');
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,30 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Tabulation Routes
|
// Tabulation Routes
|
||||||
|
use App\Http\Controllers\Tabulation\AdvancementController;
|
||||||
use App\Http\Controllers\Tabulation\DoublerDecisionController;
|
use App\Http\Controllers\Tabulation\DoublerDecisionController;
|
||||||
|
use App\Http\Controllers\Tabulation\EntryFlagController;
|
||||||
|
use App\Http\Controllers\Tabulation\ScoreController;
|
||||||
|
use App\Http\Controllers\Tabulation\SeatAuditionController;
|
||||||
|
use App\Http\Controllers\Tabulation\SeatingStatusController;
|
||||||
|
use App\Http\Controllers\Tabulation\TabulationController;
|
||||||
use App\Http\Middleware\CheckIfCanTab;
|
use App\Http\Middleware\CheckIfCanTab;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::middleware(['auth', 'verified', CheckIfCanTab::class])->group(function () {
|
Route::middleware(['auth', 'verified', CheckIfCanTab::class])->group(function () {
|
||||||
|
|
||||||
// Score Management
|
// Score Management
|
||||||
Route::prefix('scores/')->controller(\App\Http\Controllers\Tabulation\ScoreController::class)->group(function () {
|
Route::prefix('scores/')->controller(ScoreController::class)->group(function () {
|
||||||
Route::get('/choose_entry', 'chooseEntry')->name('scores.chooseEntry');
|
Route::get('/choose_entry', 'chooseEntry')->name('scores.chooseEntry');
|
||||||
Route::get('/entry', 'entryScoreSheet')->name('scores.entryScoreSheet');
|
Route::get('/entry', 'entryScoreSheet')->name('scores.entryScoreSheet');
|
||||||
Route::post('/entry/{entry}', 'saveEntryScoreSheet')->name('scores.saveEntryScoreSheet');
|
Route::post('/entry/{entry}', 'saveEntryScoreSheet')->name('scores.saveEntryScoreSheet');
|
||||||
Route::delete('/{score}',
|
Route::delete('/{score}',
|
||||||
[\App\Http\Controllers\Tabulation\ScoreController::class, 'destroyScore'])->name('scores.destroy');
|
[ScoreController::class, 'destroyScore'])->name('scores.destroy');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Entry Flagging
|
// Entry Flagging
|
||||||
Route::prefix('entry-flags/')->controller(\App\Http\Controllers\Tabulation\EntryFlagController::class)->group(function (
|
Route::prefix('entry-flags/')->controller(EntryFlagController::class)->group(function (
|
||||||
) {
|
) {
|
||||||
Route::get('/choose_no_show', 'noShowSelect')->name('entry-flags.noShowSelect');
|
Route::get('/choose_no_show', 'noShowSelect')->name('entry-flags.noShowSelect');
|
||||||
Route::get('/propose-no-show', 'noShowConfirm')->name('entry-flags.confirmNoShow');
|
Route::get('/propose-no-show', 'noShowConfirm')->name('entry-flags.confirmNoShow');
|
||||||
|
|
@ -27,11 +34,12 @@ Route::middleware(['auth', 'verified', CheckIfCanTab::class])->group(function ()
|
||||||
|
|
||||||
// Seating Routes
|
// Seating Routes
|
||||||
Route::prefix('seating/')->group(function () {
|
Route::prefix('seating/')->group(function () {
|
||||||
Route::get('/', App\Http\Controllers\Tabulation\SeatingStatusController::class)->name('seating.status');
|
Route::get('/', SeatingStatusController::class)->name('seating.status');
|
||||||
|
Route::get('/{audition}', SeatAuditionController::class)->name('seating.audition');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Generic Tabulation Routes (TO BE REPLACED)
|
// Generic Tabulation Routes (TO BE REPLACED)
|
||||||
Route::prefix('tabulation/')->controller(\App\Http\Controllers\Tabulation\TabulationController::class)->group(function (
|
Route::prefix('tabulation/')->controller(TabulationController::class)->group(function (
|
||||||
) {
|
) {
|
||||||
Route::get('/status', 'status')->name('tabulation.status');
|
Route::get('/status', 'status')->name('tabulation.status');
|
||||||
Route::match(['get', 'post'], '/auditions/{audition}', 'auditionSeating')->name('tabulation.audition.seat');
|
Route::match(['get', 'post'], '/auditions/{audition}', 'auditionSeating')->name('tabulation.audition.seat');
|
||||||
|
|
@ -40,7 +48,7 @@ Route::middleware(['auth', 'verified', CheckIfCanTab::class])->group(function ()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Advancement Routes
|
// Advancement Routes
|
||||||
Route::prefix('advancement/')->controller(\App\Http\Controllers\Tabulation\AdvancementController::class)->group(function (
|
Route::prefix('advancement/')->controller(AdvancementController::class)->group(function (
|
||||||
) {
|
) {
|
||||||
Route::get('/status', 'status')->name('advancement.status');
|
Route::get('/status', 'status')->name('advancement.status');
|
||||||
Route::get('/{audition}', 'ranking')->name('advancement.ranking');
|
Route::get('/{audition}', 'ranking')->name('advancement.ranking');
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Audition;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\ScoreSheet;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
use function Pest\Laravel\get;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
it('will not answer to guest or normal user', function () {
|
||||||
|
get(route('seating.status'))
|
||||||
|
->assertRedirect(route('home'));
|
||||||
|
actAsNormal();
|
||||||
|
get(route('seating.status'))
|
||||||
|
->assertRedirect(route('dashboard'))
|
||||||
|
->assertSessionHas('error', 'You are not authorized to perform this action');
|
||||||
|
});
|
||||||
|
it('responds to an admin', function () {
|
||||||
|
// Arrange
|
||||||
|
actAsAdmin();
|
||||||
|
// Act & Assert
|
||||||
|
get(route('seating.status'))
|
||||||
|
->assertOk();
|
||||||
|
});
|
||||||
|
it('responds to a tabulator', function () {
|
||||||
|
// Arrange
|
||||||
|
actAsTab();
|
||||||
|
// Act & Assert
|
||||||
|
get(route('seating.status'))
|
||||||
|
->assertOk();
|
||||||
|
});
|
||||||
|
it('sends the view a collection of audition data that includes data needed by the view', function () {
|
||||||
|
// Arrange
|
||||||
|
$auditions = Audition::factory()->count(5)->create();
|
||||||
|
actAsAdmin();
|
||||||
|
// Act
|
||||||
|
$response = get(route('seating.status'));
|
||||||
|
// Assert
|
||||||
|
foreach ($auditions as $audition) {
|
||||||
|
$response->assertOk()
|
||||||
|
->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['id'] === $audition->id;
|
||||||
|
});
|
||||||
|
$response->assertOk()
|
||||||
|
->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['name'] === $audition->name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it('has correct count info for an audition with 5 entries none scored', function () {
|
||||||
|
$audition = Audition::factory()->create();
|
||||||
|
Entry::factory()->count(5)->create(['audition_id' => $audition->id]);
|
||||||
|
|
||||||
|
actAsAdmin();
|
||||||
|
$response = get(route('seating.status'));
|
||||||
|
$response->assertOk();
|
||||||
|
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoredEntriesCount'] === 0;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['totalEntriesCount'] === 5;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoredPercentage'] === 0;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoringComplete'] === false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('has correct count info for an audition with 8 entries 2 scored', function () {
|
||||||
|
$judge = User::factory()->create();
|
||||||
|
|
||||||
|
$audition = Audition::factory()->create();
|
||||||
|
$entries = Entry::factory()->count(2)->create(['audition_id' => $audition->id]);
|
||||||
|
$entries->each(fn ($entry) => ScoreSheet::create([
|
||||||
|
'user_id' => $judge->id,
|
||||||
|
'entry_id' => $entry->id,
|
||||||
|
'subscores' => 7,
|
||||||
|
]));
|
||||||
|
Entry::factory()->count(6)->create(['audition_id' => $audition->id]);
|
||||||
|
|
||||||
|
actAsAdmin();
|
||||||
|
$response = get(route('seating.status'));
|
||||||
|
$response->assertOk();
|
||||||
|
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoredEntriesCount'] === 2;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['totalEntriesCount'] === 8;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoredPercentage'] == 25;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoringComplete'] === false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct count info for an audition with 1 entries 1 scored', function () {
|
||||||
|
$judge = User::factory()->create();
|
||||||
|
|
||||||
|
$audition = Audition::factory()->create();
|
||||||
|
$entry = Entry::factory()->create(['audition_id' => $audition->id]);
|
||||||
|
ScoreSheet::create([
|
||||||
|
'user_id' => $judge->id,
|
||||||
|
'entry_id' => $entry->id,
|
||||||
|
'subscores' => 3,
|
||||||
|
]);
|
||||||
|
|
||||||
|
actAsAdmin();
|
||||||
|
$response = get(route('seating.status'));
|
||||||
|
$response->assertOk();
|
||||||
|
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoredEntriesCount'] === 1;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['totalEntriesCount'] === 1;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoredPercentage'] == 100;
|
||||||
|
});
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['scoringComplete'] === true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('correctly shows a flag when the audition is flagged as seated', function () {
|
||||||
|
$audition = Audition::factory()->create();
|
||||||
|
|
||||||
|
actAsAdmin();
|
||||||
|
$response = get(route('seating.status'));
|
||||||
|
$response->assertOk();
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['seatsPublished'] === false;
|
||||||
|
});
|
||||||
|
$audition->addFlag('seats_published');
|
||||||
|
$response = get(route('seating.status'));
|
||||||
|
$response->assertOk();
|
||||||
|
$response->assertViewHas('auditionData', function ($viewAuditionData) use ($audition) {
|
||||||
|
return $viewAuditionData[$audition->id]['seatsPublished'] === true;
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue