[Feature request] Before each after running helper function
Hi,
Context: When defining a helper function in "pest.php" these functions can be chained to a test case:
it('should..', function () {
expect();
})->asAdmin();
In my opinion, this is a very nice readable and reusable syntax to toggle state in your app or prepare mocks with some variation.
I like to keep as much mocking/data prep outside of the test itself and this syntax is also in line with the data (->with()) method.
This is already somewhat usable but in terms of timing, this is executed after the beforeEach where you generally would prepare data.
Request:
So what I'm asking for is a new hook that would be executed after chained helper functions, just before the test runs.
Alternatively, delay the beforeEach hook slightly.
Workaround: I've created a somewhat dirty workaround to be able to get this working in my project.
// Pest.php
// Extend "it" to call global custom beforeEach and callback within suite
function itShould(string $description, ?Closure $closure = null): TestCall
{
$description = sprintf('it should %s', $description);
/** @var TestCall $test */
return test($description, function () use ($closure): void {
// call global before each
$this->jitBeforeEach();
// call beforeEach in test suite
TestCaseContext::$context->call($this);
$closure->call($this, ...func_get_args());
});
}
// Alternative to register a "beforeEach"
function context(Closure $closure): void
{
TestCaseContext::$context = $closure;
}
// TestCase.php
abstract class TestCase extends LyfterTestCase
{
// My global custom beforeEach
protected function jitBeforeEach(): void
{
// contains custom logic for mocking app specific vars
}
}
//TestCaseContext.php
class TestCaseContext
{
// Temporary static to store the closure until the test is run.
public static ?Closure $context = null;
}
// SomethingTest.php
context(function (): void {
// additional before each logic
// this could even potentially receive params for conditional logic
// although this can already be done using the $this scope.
});
itShould('do this', function (): void {
expect(...)->toBeTrue();
})->runAsAdmin();
I hope this illustrates what I'm doing and why. If not please ask for clarification. I'm willing to contribute if this would be accepted as a good addition to Pest.