app/tests/Unit/Schedule/ScheduleGeneratorTest.php

146 lines
5 KiB
PHP
Raw Normal View History

2025-10-13 14:57:11 +02:00
<?php
namespace Tests\Unit\Schedule;
use App\Models\Dish;
use App\Models\MinimumRecurrence;
use App\Models\Planner;
use App\Models\Schedule;
use App\Models\User;
use App\Models\UserDish;
use App\Models\UserDishRecurrence;
use App\Models\WeeklyRecurrence;
use App\WeekdaysEnum;
use DishPlanner\Schedule\Services\ScheduleGenerator;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Tests\TestCase;
use Tests\Traits\HasPlanner;
class ScheduleGeneratorTest extends TestCase
{
use HasPlanner;
use RefreshDatabase;
public function test_it_fills_up_the_next_2_weeks(): void
{
$planner = $this->planner;
$user = User::factory()->planner($this->planner)->create();
$dishOne = Dish::factory()->planner($planner)->create();
$dishTwo = Dish::factory()->planner($planner)->create();
UserDish::factory()->user($user)->dish($dishOne)->create();
UserDish::factory()->user($user)->dish($dishTwo)->create();
$this->assertDatabaseEmpty(Schedule::class);
(new ScheduleGenerator())->generate($planner);
$schedules = Schedule::all();
$this->assertTrue($schedules->isNotEmpty());
$this->assertCount(14, $schedules);
}
public function test_it_takes_weekly_recurrences_into_account(): void
{
$recurringDay = now()->addDays(2);
$planner = $this->planner;
$user = User::factory()->planner($this->planner)->create();
$dishesPlain = Dish::factory()->planner($planner)->count(20)->create();
$dishRecurring = Dish::factory()->planner($planner)->create();
$weeklyRecurrence = WeeklyRecurrence::factory()
->weekday(WeekdaysEnum::from($recurringDay->dayOfWeek()))
->create();
$dishesPlain->each(fn (Dish $dish) => UserDish::factory()
->user($user)
->dish($dish)
->create()
);
$userDishRecurring = UserDish::factory()
->user($user)
->dish($dishRecurring)
->create();
UserDishRecurrence::factory()->create([
'user_dish_id' => $userDishRecurring->id,
'recurrence_id' => $weeklyRecurrence->id,
'recurrence_type' => WeeklyRecurrence::class,
]);
$userDishRecurring->refresh();
$this->assertNotEmpty($userDishRecurring->recurrences);
$this->assertDatabaseEmpty(Schedule::class);
(new ScheduleGenerator())->generate($planner);
$this->assertTrue(Schedule::all()->isNotEmpty());
$schedule = Schedule::query()->where('date', $recurringDay->format('Y-m-d'))->first();
$this->assertNotNull($schedule);
$this->assertNotEmpty($schedule->scheduledUserDishes);
$this->assertEquals($schedule->scheduledUserDishes->first()->userDish->id, $userDishRecurring->id);
$schedule = Schedule::query()->where('date', $recurringDay->addWeek()->format('Y-m-d'))->first();
$this->assertNotNull($schedule);
$this->assertNotEmpty($schedule->scheduledUserDishes);
$this->assertEquals($schedule->scheduledUserDishes->first()->userDish->id, $userDishRecurring->id);
}
public function test_it_takes_minimum_recurrences_into_account(): void
{
$recurringMinimum = 3;
$planner = $this->planner;
$user = User::factory()->planner($this->planner)->create();
$dishPlain = Dish::factory()->planner($planner)->create();
$dishRecurring = Dish::factory()->planner($planner)->create();
$minimumRecurrence = MinimumRecurrence::factory()->days($recurringMinimum)->create();
UserDish::factory()
->user($user)
->dish($dishPlain)
->create();
$userDishRecurring = UserDish::factory()
->user($user)
->dish($dishRecurring)
->create();
UserDishRecurrence::factory()->create([
'user_dish_id' => $userDishRecurring->id,
'recurrence_id' => $minimumRecurrence->id,
'recurrence_type' => MinimumRecurrence::class,
]);
$userDishRecurring->refresh();
$this->assertNotEmpty($userDishRecurring->recurrences);
$this->assertDatabaseEmpty(Schedule::class);
(new ScheduleGenerator())->generate($planner);
$this->assertTrue(Schedule::all()->isNotEmpty());
Schedule::all()
->filter(fn (Schedule $schedule) => $schedule->scheduledUserDishes()->first()->userDish->dish->id === $dishRecurring->id)
->map(fn (Schedule $schedule) => $schedule->date)
->reduce(function (?Carbon $previousDate, Carbon $currentDate) use ($recurringMinimum) {
if (! is_null($previousDate)) {
$this->assertGreaterThanOrEqual(
$recurringMinimum,
$previousDate->diffInDays($currentDate),
'Dates are not spaced properly'
);
}
return $currentDate;
});
}
}