Vastly improves the logic around bound datasets to make them more user friendly.

This commit is contained in:
Luke Downing
2021-10-19 21:40:40 +01:00
parent de46ee0f64
commit eed3ed5513
4 changed files with 85 additions and 6 deletions

View File

@ -7,8 +7,10 @@ namespace Pest\Concerns;
use Closure;
use Pest\Support\ChainableClosure;
use Pest\Support\ExceptionTrace;
use Pest\Support\Reflection;
use Pest\TestSuite;
use PHPUnit\Framework\ExecutionOrderDependency;
use function sprintf;
use Throwable;
/**
@ -257,7 +259,7 @@ trait Testable
*/
public function toString(): string
{
return \sprintf(
return sprintf(
'%s::%s',
self::$__filename,
$this->__description
@ -283,9 +285,28 @@ trait Testable
*/
private function resolveTestArguments(array $arguments): array
{
return array_map(function ($data) {
return $data instanceof Closure ? $this->__callClosure($data, []) : $data;
}, $arguments);
if (count($arguments) !== 1) {
return $arguments;
}
if (!$arguments[0] instanceof Closure) {
return $arguments;
}
$underlyingTest = Reflection::getFunctionVariable($this->__test, 'factoryTest');
$testParameterTypes = array_values(Reflection::getFunctionArguments($underlyingTest));
if (in_array($testParameterTypes[0], ['Closure', 'callable'])) {
return $arguments;
}
$boundDatasetResult = $this->__callClosure($arguments[0], []);
if (count($testParameterTypes) === 1 || !is_array($boundDatasetResult)) {
return [$boundDatasetResult];
}
return array_values($boundDatasetResult);
}
/**

View File

@ -204,4 +204,12 @@ final class Reflection
return $arguments;
}
/**
* @return mixed
*/
public static function getFunctionVariable(Closure $function, string $key)
{
return (new ReflectionFunction($function))->getStaticVariables()[$key] ?? null;
}
}

View File

@ -96,11 +96,20 @@
✓ more than two datasets with (2) / (4) / (5)
✓ more than two datasets with (2) / (4) / (6)
✓ more than two datasets did the job right
✓ it can resolve a dataset after the test case is available with (Closure Object (...))
✓ it can resolve a dataset after the test case is available with (Closure Object (...)) #1
✓ it can resolve a dataset after the test case is available with (Closure Object (...)) #2
✓ it can resolve a dataset after the test case is available with shared yield sets with (Closure Object (...)) #1
✓ it can resolve a dataset after the test case is available with shared yield sets with (Closure Object (...)) #2
✓ it can resolve a dataset after the test case is available with shared array sets with (Closure Object (...)) #1
✓ it can resolve a dataset after the test case is available with shared array sets with (Closure Object (...)) #2
✓ it resolves a potential bound dataset logically with ('foo', Closure Object (...))
✓ it resolves a potential bound dataset logically even when the closure comes first with (Closure Object (...), 'bar')
✓ it will not resolve a closure if it is type hinted as a closure with (Closure Object (...)) #1
✓ it will not resolve a closure if it is type hinted as a closure with (Closure Object (...)) #2
✓ it will not resolve a closure if it is type hinted as a callable with (Closure Object (...)) #1
✓ it will not resolve a closure if it is type hinted as a callable with (Closure Object (...)) #2
✓ it can correctly resolve a bound dataset that returns an array with (Closure Object (...))
✓ it can correctly resolve a bound dataset that returns an array but wants to be spread with (Closure Object (...))
PASS Tests\Features\Exceptions
✓ it gives access the the underlying expectException
@ -720,5 +729,5 @@
✓ it is a test
✓ it uses correct parent class
Tests: 4 incompleted, 9 skipped, 478 passed
Tests: 4 incompleted, 9 skipped, 487 passed

View File

@ -232,6 +232,7 @@ it('can resolve a dataset after the test case is available', function ($result)
expect($result)->toBe('bar');
})->with([
function () { return $this->foo; },
[function () { return $this->foo; }],
]);
it('can resolve a dataset after the test case is available with shared yield sets', function ($result) {
@ -241,3 +242,43 @@ it('can resolve a dataset after the test case is available with shared yield set
it('can resolve a dataset after the test case is available with shared array sets', function ($result) {
expect($result)->toBeInt()->toBeLessThan(3);
})->with('bound.array');
it('resolves a potential bound dataset logically', function ($foo, $bar) {
expect($foo)->toBe('foo');
expect($bar())->toBe('bar');
})->with([
['foo', function () { return 'bar'; }], // This should be passed as a closure because we've passed multiple arguments
]);
it('resolves a potential bound dataset logically even when the closure comes first', function ($foo, $bar) {
expect($foo())->toBe('foo');
expect($bar)->toBe('bar');
})->with([
[function () { return 'foo'; }, 'bar'], // This should be passed as a closure because we've passed multiple arguments
]);
it('will not resolve a closure if it is type hinted as a closure', function (Closure $data) {
expect($data())->toBeString();
})->with([
function () { return 'foo'; },
function () { return 'bar'; },
]);
it('will not resolve a closure if it is type hinted as a callable', function (callable $data) {
expect($data())->toBeString();
})->with([
function () { return 'foo'; },
function () { return 'bar'; },
]);
it('can correctly resolve a bound dataset that returns an array', function (array $data) {
expect($data)->toBe(['foo', 'bar', 'baz']);
})->with([
function () { return ['foo', 'bar', 'baz']; },
]);
it('can correctly resolve a bound dataset that returns an array but wants to be spread', function (string $foo, string $bar, string $baz) {
expect([$foo, $bar, $baz])->toBe(['foo', 'bar', 'baz']);
})->with([
function () { return ['foo', 'bar', 'baz']; },
]);