pest icon indicating copy to clipboard operation
pest copied to clipboard

[Feature request] Before each after running helper function

Open michaelw85 opened this issue 2 years ago • 0 comments

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.

michaelw85 avatar Dec 13 '23 16:12 michaelw85