Create tests for app/Models/Student and Audition

This commit is contained in:
Matt Young 2025-07-03 21:40:43 -05:00
parent bcbbf92457
commit c6b4522f9e
10 changed files with 265 additions and 11 deletions

View File

@ -2,11 +2,14 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
class HistoricalSeat extends Model class HistoricalSeat extends Model
{ {
use hasFactory;
protected $guarded = []; protected $guarded = [];
public function student(): BelongsTo public function student(): BelongsTo

View File

@ -2,11 +2,14 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
class NominationEnsemble extends Model class NominationEnsemble extends Model
{ {
use HasFactory;
protected $guarded = []; protected $guarded = [];
protected function casts(): array protected function casts(): array

View File

@ -13,7 +13,7 @@ class Student extends Model
{ {
use HasFactory; use HasFactory;
public static $shirtSizes = [ public static array $shirtSizes = [
'none' => '---', 'none' => '---',
'YS' => 'Youth Small', 'YS' => 'Youth Small',
'YM' => 'Youth Medium', 'YM' => 'Youth Medium',
@ -68,7 +68,7 @@ class Student extends Model
/** /**
* Returns the directors at this student's school. * Returns the directors at this student's school.
* Alias of users()) * Alias of users()
* ' * '
*/ */
public function directors(): HasManyThrough public function directors(): HasManyThrough
@ -116,8 +116,8 @@ class Student extends Model
return Entry::query() return Entry::query()
->where('student_id', $this->id) ->where('student_id', $this->id)
->whereHas('audition', function ($query) use ($event) { ->whereHas('audition', function ($query) use ($eventId) {
$query->where('event_id', $event); $query->where('event_id', $eventId);
}) })
->with('audition.SeatingLimits') // Eager load the audition relation if needed ->with('audition.SeatingLimits') // Eager load the audition relation if needed
->with('totalScore') ->with('totalScore')

View File

@ -74,4 +74,13 @@ class AuditionFactory extends Factory
fn (array $attributes) => ['for_seating' => 0] fn (array $attributes) => ['for_seating' => 0]
); );
} }
public function forEvent(Event $event): self
{
return $this->state(function (array $attributes) use ($event) {
return [
'event_id' => $event->id,
];
});
}
} }

View File

@ -0,0 +1,43 @@
<?php
namespace Database\Factories;
use App\Models\DoublerRequest;
use App\Models\Event;
use App\Models\Student;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;
class DoublerRequestFactory extends Factory
{
protected $model = DoublerRequest::class;
public function definition(): array
{
return [
'request' => $this->faker->word(),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
'event_id' => Event::factory(),
'student_id' => Student::factory(),
];
}
public function forStudent(Student $student): self
{
return $this->state(function (array $attributes) use ($student) {
return [
'student_id' => $student->id,
];
});
}
public function forEvent(Event $event): self
{
return $this->state(function (array $attributes) use ($event) {
return [
'event_id' => $event->id,
];
});
}
}

View File

@ -18,11 +18,9 @@ class EntryFactory extends Factory
*/ */
public function definition(): array public function definition(): array
{ {
$student = Student::factory()->create();
$audition = Audition::factory()->create();
return [ return [
'student_id' => $student->id, 'student_id' => Student::factory(),
'audition_id' => $audition->id, 'audition_id' => Audition::factory(),
'draw_number' => null, 'draw_number' => null,
'for_seating' => 1, 'for_seating' => 1,
'for_advancement' => 1, 'for_advancement' => 1,
@ -43,4 +41,22 @@ class EntryFactory extends Factory
fn (array $attributes) => ['for_seating' => 0] fn (array $attributes) => ['for_seating' => 0]
); );
} }
public function forStudent(Student $student): self
{
return $this->state(function (array $attributes) use ($student) {
return [
'student_id' => $student->id,
];
});
}
public function forAudition(Audition $audition): self
{
return $this->state(function (array $attributes) use ($audition) {
return [
'audition_id' => $audition->id,
];
});
}
} }

View File

@ -0,0 +1,33 @@
<?php
namespace Database\Factories;
use App\Models\HistoricalSeat;
use App\Models\Student;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;
class HistoricalSeatFactory extends Factory
{
protected $model = HistoricalSeat::class;
public function definition(): array
{
return [
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
'year' => $this->faker->randomNumber(),
'seat_description' => $this->faker->text(),
'student_id' => Student::factory(),
];
}
public function forStudent(Student $student): self
{
return $this->state(function (array $attributes) use ($student) {
return [
'student_id' => $student->id,
];
});
}
}

View File

@ -2,7 +2,9 @@
namespace Database\Factories; namespace Database\Factories;
use App\Models\NominationEnsemble;
use App\Models\NominationEnsembleEntry; use App\Models\NominationEnsembleEntry;
use App\Models\Student;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
@ -13,11 +15,29 @@ class NominationEnsembleEntryFactory extends Factory
public function definition(): array public function definition(): array
{ {
return [ return [
'student_id' => $this->faker->randomNumber(), 'student_id' => Student::factory(),
'nomination_ensemble_id' => $this->faker->randomNumber(), 'nomination_ensemble_id' => NominationEnsemble::factory(),
'data' => $this->faker->words(), 'data' => json_encode([5, 2, 4]),
'created_at' => Carbon::now(), 'created_at' => Carbon::now(),
'updated_at' => Carbon::now(), 'updated_at' => Carbon::now(),
]; ];
} }
public function forEnsemble(NominationEnsemble $ensemble): self
{
return $this->state(function (array $attributes) use ($ensemble) {
return [
'nomination_ensemble_id' => $ensemble->id,
];
});
}
public function forStudent(Student $student): self
{
return $this->state(function (array $attributes) use ($student) {
return [
'student_id' => $student->id,
];
});
}
} }

View File

@ -0,0 +1,25 @@
<?php
namespace Database\Factories;
use App\Models\NominationEnsemble;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;
class NominationEnsembleFactory extends Factory
{
protected $model = NominationEnsemble::class;
public function definition(): array
{
return [
'name' => $this->faker->name(),
'entry_deadline' => Carbon::now(),
'minimum_grade' => 1,
'maximum_grade' => 15,
'data' => json_encode([2, 5, 3]),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
}
}

View File

@ -0,0 +1,102 @@
<?php
use App\Models\Audition;
use App\Models\Doubler;
use App\Models\DoublerRequest;
use App\Models\Entry;
use App\Models\Event;
use App\Models\HistoricalSeat;
use App\Models\NominationEnsembleEntry;
use App\Models\School;
use App\Models\Student;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
beforeEach(function () {
$this->student = Student::factory()->create();
});
it('can return its nominations', function () {
NominationEnsembleEntry::factory()
->forStudent($this->student)->create();
expect($this->student->nominations()->count())->toEqual(1)
->and($this->student->nominations()->first())->toBeInstanceOf(NominationEnsembleEntry::class);
});
it('can return its school', function () {
expect($this->student->school->id)->toEqual(1)
->and($this->student->school)->toBeInstanceOf(School::class);
});
it('can return its historical seats', function () {
HistoricalSeat::factory()
->forStudent($this->student)->create();
expect($this->student->historicalSeats->count())->toEqual(1)
->and($this->student->historicalSeats()->first())->toBeInstanceOf(HistoricalSeat::class);
});
it('can return the students directors using either director or user', function () {
User::factory()->count(2)->create(['school_id' => $this->student->school_id]);
expect($this->student->directors()->count())->toEqual(2)
->and($this->student->directors()->first())->toBeInstanceOf(User::class);
});
it('can return its entries)', function () {
Entry::factory()->count(3)->forStudent($this->student)->create();
expect($this->student->entries()->count())->toEqual(3)
->and($this->student->entries()->first())->toBeInstanceOf(Entry::class);
});
it('can return its full name', function () {
expect($this->student->full_name())->toEqual($this->student->first_name.' '.$this->student->last_name)
->and($this->student->full_name(true))->toEqual($this->student->last_name.', '.$this->student->first_name);
});
it('can return its doubler requests', function () {
DoublerRequest::factory()->forStudent($this->student)->create();
DoublerRequest::factory()->forStudent($this->student)->create();
expect($this->student->doublerRequests()->count())->toEqual(2)
->and($this->student->doublerRequests()->first())->toBeInstanceOf(DoublerRequest::class);
});
it('can return its doublers', function () {
$event = Event::factory()->create();
DB::table('doublers')->insert([
'student_id' => $this->student->id,
'event_id' => $event->id,
'entries' => json_encode([1, 2, 3]),
'accepted_entry' => null,
]);
expect($this->student->doublers()->count())->toEqual(1)
->and($this->student->doublers()->first())->toBeInstanceOf(Doubler::class);
});
it('can check if it is a doubler in a given event', function () {
$event = Event::factory()->create();
expect($this->student->isDoublerInEvent($event))->toBeFalse();
DB::table('doublers')->insert([
'student_id' => $this->student->id,
'event_id' => $event->id,
'entries' => json_encode([1, 2, 3]),
'accepted_entry' => null,
]);
expect($this->student->isDoublerInEvent($event))->toBeTrue();
});
it('can return its entries for a given event', function () {
$event1 = Event::factory()->create();
$event2 = Event::factory()->create();
$audition1 = Audition::factory()->forEvent($event1)->create();
$audition2 = Audition::factory()->forEvent($event2)->create();
$audition3 = Audition::factory()->forEvent($event2)->create();
Entry::factory()->forStudent($this->student)->forAudition($audition1)->create();
Entry::factory()->forStudent($this->student)->forAudition($audition2)->create();
Entry::factory()->forStudent($this->student)->forAudition($audition3)->create();
expect($this->student->entries()->count())->toEqual(3)
->and($this->student->entriesForEvent($event1->id)->count())->toEqual(1)
->and($this->student->entriesForEvent($event1->id)->first())->toBeInstanceOf(Entry::class)
->and($this->student->entriesForEvent($event2)->count())->toEqual(2)
->and($this->student->entriesForEvent($event2)->first())->toBeInstanceOf(Entry::class);
});