It seems like the error you're encountering is due to the $belt variable being null when you're trying to access its id property. This can happen if there are no Belt records in the database that meet the condition specified in the where clause.
To resolve this issue, you should ensure that there are Belt records in the database before running the test, and that at least one of them will satisfy the condition min_xp <= $xp. Additionally, you should handle the case where no Belt is found to avoid the null reference error.
Here's how you can modify your CharacterFactory to handle the case where no Belt is found:
public function definition(): array
{
$xp = fake()->numberBetween(0 , 50);
$belt = Belt::where('min_xp', '<=', $xp)->orderBy('min_xp', 'desc')->first();
// Check if a belt was found, if not, you can either create one or handle the error
if (!$belt) {
// Option 1: Create a default belt or throw an exception
// $belt = Belt::factory()->create(['min_xp' => 0]); // Create a default belt
// Option 2: Handle the error, for example by throwing an exception
throw new \Exception('No belt found for the given XP');
}
return [
'user_id' => User::factory(),
'name' => fake()->randomAscii(0, 25),
'xp' => $xp,
'belt_id' => $belt->id, // Now it should not be null
'wins' => fake()->numberBetween(0, 99),
'loses' => fake()->numberBetween(0, 99),
'draws' => fake()->numberBetween(0, 99)
];
}
In your test, you're creating three Belt instances, but you need to make sure that at least one of them will have a min_xp value that is less than or equal to the xp value generated in the CharacterFactory. If the Belt instances you're creating do not cover the range of xp values that CharacterFactory might generate, you'll run into the same issue.
Make sure your Belt factory creates belts with a range of min_xp values that cover the possible xp values generated by the CharacterFactory. If necessary, you can adjust the Belt factory or explicitly create a Belt with a min_xp of 0 to ensure there's always a belt available for any xp value.