In Laravel 7 we pretty routinely use the pattern:
public function provideCanDoThing(): array
{
return [
"Root can do thing" => [['root'], true],
"Normal user cannot do thing" => [[], false],
"Root cannot do thing while suspended" => [['root', 'suspended'], false],
];
}
/**
* @dataProvider provideCanDoThing
*/
public function testCanDoThing(array $userStates, bool $expectedCanDo): void
{
$user = factory(User::class)->states($userStates)->create();
self::expectSame($expectedCanDo, $user->canDoThing());
}
The state "root" can be pretty complicated, with a combo of attributes and afterCreating logic.
In new Laravel 8 factories, the state method no longer runs the collected changes in a named state, instead it... works just like passing attributes to make or create?
I can see how I could rewrite the test more like
$userFactory = User::factory();
foreach($userStates as $userState){
$userFactory = $userFactory->{$userState}();
}
$user = $userFactory->create();
But that seems much less expressive. I guess I'm surprised I can't find a method on Factory that does that for me.