Skip to content

Conversation

@louisbels
Copy link

What:

  • Bug Fix
  • New Feature

Description

Datasets are not applied when using method chaining patterns with hooks and describe blocks:

describe('with on hook', function () {
    beforeEach()->with([2]);  // ❌ Dataset not applied

    test('value', function ($foo) {
        expect($foo)->toBe(2);  // Error: no dataset provided
    });
});

Error:

Pest\Exceptions\DatasetMissing
A test has [1] argument(s) and no dataset(s) provided

Root Cause

Multiple Pest functions were using Backtrace::file() to determine the current test file. This method returns the immediate caller's filename, which breaks with method chaining:

User writes: beforeEach()->with([2]) in MyTest.php
↓
beforeEach() called
↓
->with() executes through internal Pest code
↓
Backtrace::file() returns "Backtrace.php" (wrong file!)

The callback was stored with the wrong filename key, so tests couldn't find their datasets.

Solution

Use Backtrace::testFile() instead, which walks the entire backtrace to find the actual test file being executed. This matches the pattern already used by Pest's test() and describe() functions.

Changes

src/Functions.php - 8 functions updated:

  • beforeEach() - fixes beforeEach()->with() pattern
  • afterEach() - consistency with beforeEach
  • beforeAll() - better error messages
  • afterAll() - better error messages
  • pest() - fixes pest()->beforeEach() pattern
  • uses() - consistency with pest()
  • covers() - correct test file context
  • mutates() - correct test file context

src/PendingCalls/DescribeCall.php - 3 fixes:

  1. Force BeforeEachCall destructor to run before test creation (timing fix)
  2. Use $this->filename instead of backtrace (optimization)
  3. Properly merge describing context for nested describe blocks

Fixed Patterns

  • beforeEach()->with([...])
  • describe()->with([...])
  • pest()->beforeEach()->with([...])
  • Nested describe blocks with datasets
  • Global hooks from Pest.php config files

Testing

# All dataset tests now pass
docker compose run --rm php bin/pest tests/Features/Describe.php
# ✓ with on hook → value with (2)
# ✓ with on describe → value with (3)

# Global hooks work correctly
docker compose run --rm php bin/pest tests/Hooks/BeforeEachTest.php
# ✓ global beforeEach execution order

# Snapshot tests with datasets
docker compose run --rm php bin/pest tests/Features/Expect/toMatchSnapshot.php
# ✓ 28 tests passed

Consistency with Pest Design

This change extends an existing pattern in Pest's codebase:

// Already using testFile() in original code:
function test()     { $filename = Backtrace::testFile(); } ✓
function describe() { $filename = Backtrace::testFile(); } ✓

// We extended the same pattern:
function beforeEach() { $filename = Backtrace::testFile(); } ✓
function afterEach()  { $filename = Backtrace::testFile(); } ✓
// etc.

Related

PR (Dockerfile): https://github.com/louisbels/pest/pull/new/fix-dockerfile-php83-build

…describe()->with())

Fixes issue where datasets were not applied when using method chaining patterns
like beforeEach()->with([...]) or describe()->with([...]) inside nested describe blocks.

Root cause: Multiple functions were using Backtrace::file() which returns the
immediate caller's filename. This breaks when called through method chaining
because the backtrace returns internal Pest files instead of the test file.

Solution: Use Backtrace::testFile() which walks the entire backtrace to find
the actual test file being executed. This matches the pattern already used by
test() and describe() functions.

Changes in src/Functions.php:
- beforeEach(): Use testFile() to fix beforeEach()->with() pattern
- afterEach(): Use testFile() for consistency with beforeEach()
- beforeAll(): Use testFile() for better error messages
- afterAll(): Use testFile() for better error messages
- pest(): Use testFile() to fix pest()->beforeEach() pattern
- uses(): Use testFile() for consistency with pest()
- covers(): Use testFile() for correct test file context
- mutates(): Use testFile() for correct test file context

Changes in src/PendingCalls/DescribeCall.php:
- __destruct(): Force BeforeEachCall destructor before test creation
- __call(): Use $this->filename instead of Backtrace, more efficient
- __call(): Properly merge describing context for nested describe blocks

Fixes patterns:
- beforeEach()->with([...])
- describe()->with([...])
- pest()->beforeEach()->with([...]

Tests passing:
- tests/Features/Describe.php (all dataset tests)
- tests/Hooks/BeforeEachTest.php (global hook execution)
- tests/Features/Expect/toMatchSnapshot.php (28 tests)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant