setUpHasPlanner(); } 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()); $recurringDates = Schedule::all() ->filter(fn (Schedule $schedule) => $schedule->scheduledUserDishes ->contains(fn ($scheduledUserDish) => $scheduledUserDish->userDish->dish->id === $dishRecurring->id) ) ->map(fn (Schedule $schedule) => $schedule->date) ->sort() ->values(); $this->assertGreaterThan(1, $recurringDates->count(), 'Recurring dish was not scheduled often enough to verify spacing'); $gaps = $recurringDates ->sliding(2) ->map(fn ($pair) => (int) $pair->first()->diffInDays($pair->last())); $this->assertEmpty( $gaps->reject(fn (int $gap) => $gap >= $recurringMinimum)->all(), 'Dates are not spaced properly' ); } }