Skip to content

Commit

Permalink
Injected current in scope (#619)
Browse files Browse the repository at this point in the history
Injected current in scope to make it accessible in the identity function.
  • Loading branch information
theofidry authored Nov 12, 2016
1 parent 6e4ee16 commit cfa21ed
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 7 deletions.
21 changes: 21 additions & 0 deletions src/Generator/Resolver/Value/Chainable/EvaluatedValueResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Nelmio\Alice\Definition\Value\EvaluatedValue;
use Nelmio\Alice\Definition\ValueInterface;
use Nelmio\Alice\Exception\Generator\Resolver\UnresolvableValueException;
use Nelmio\Alice\Exception\NoValueForCurrentException;
use Nelmio\Alice\FixtureInterface;
use Nelmio\Alice\Generator\GenerationContext;
use Nelmio\Alice\Generator\ResolvedFixtureSet;
Expand Down Expand Up @@ -50,8 +51,20 @@ public function resolve(
GenerationContext $context
): ResolvedValueWithFixtureSet
{
// Scope exclusive to the evaluated expression
// We make use of the underscore prefix (`_`) here to limit the possible conflicts with the variables injected
// in the scope.
$_scope = $scope;
try {
$_scope['current'] = $fixture->getValueForCurrent();
} catch (NoValueForCurrentException $exception) {
// Continue
}

$expression = $this->replacePlaceholders($value->getValue());
// Closure in which the expression is evaluated; This is done in a closure to avoid the expression to have
// access to this method variables (which should remain unknown) and we injected only the variables of the
// closure.
$evaluateExpression = function ($_expression) use ($_scope) {
foreach ($_scope as $_scopeVariableName => $_scopeVariableValue) {
$$_scopeVariableName = $_scopeVariableValue;
Expand All @@ -69,6 +82,14 @@ public function resolve(
return new ResolvedValueWithFixtureSet($evaluatedExpression, $fixtureSet);
}

/**
* Replaces references to another fixtures, e.g. "@another_dummy" by the variable of the scope
* "$_instances['another_dummy']".
*
* @param string $expression
*
* @return string
*/
private function replacePlaceholders(string $expression): string
{
return preg_replace('/(@(?<id>[^\ @\-]+))/', '\$_instances[\'$2\']', $expression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

namespace Nelmio\Alice\Generator\Resolver\Value\Chainable;

use Nelmio\Alice\Definition\Fixture\FakeFixture;
use Nelmio\Alice\Definition\Fixture\SimpleFixture;
use Nelmio\Alice\Definition\SpecificationBagFactory;
use Nelmio\Alice\Definition\Value\EvaluatedValue;
use Nelmio\Alice\Definition\Value\FakeValue;
use Nelmio\Alice\Exception\Generator\Resolver\UnresolvableValueException;
Expand Down Expand Up @@ -51,7 +52,7 @@ public function testCanResolveFixtureReferenceValues()
public function testEvaluateTheGivenExpression()
{
$value = new EvaluatedValue('"Hello"." "."world!"');
$fixture = new FakeFixture();
$fixture = new SimpleFixture('dummy', 'Dummy', SpecificationBagFactory::create());
$set = ResolvedFixtureSetFactory::create();

$expected = new ResolvedValueWithFixtureSet(
Expand All @@ -69,7 +70,7 @@ public function testThrowsAnExceptionIfInvalidExpression()
{
try {
$value = new EvaluatedValue('"unclosed string');
$fixture = new FakeFixture();
$fixture = new SimpleFixture('dummy', 'Dummy', SpecificationBagFactory::create());
$set = ResolvedFixtureSetFactory::create();

$resolver = new EvaluatedValueResolver();
Expand All @@ -93,7 +94,7 @@ public function testThrowsAnExceptionIfInvalidExpression()
public function testThrowsAnExceptionIfAnErrorOccurredDuringEvaluation()
{
$value = new EvaluatedValue('(function () { throw new \\Exception(""); })()');
$fixture = new FakeFixture();
$fixture = new SimpleFixture('dummy', 'Dummy', SpecificationBagFactory::create());
$set = ResolvedFixtureSetFactory::create();

$resolver = new EvaluatedValueResolver();
Expand All @@ -103,7 +104,7 @@ public function testThrowsAnExceptionIfAnErrorOccurredDuringEvaluation()
public function testTheEvaluatedExpressionCanContainScopeFunctions()
{
$value = new EvaluatedValue('$foo');
$fixture = new FakeFixture();
$fixture = new SimpleFixture('dummy', 'Dummy', SpecificationBagFactory::create());
$set = ResolvedFixtureSetFactory::create();
$scope = [
'foo' => 'bar',
Expand All @@ -126,7 +127,7 @@ public function testTheEvaluatedExpressionCanContainScopeFunctions()
public function testVariablesInference()
{
$value = new EvaluatedValue('["foo" => $foo, "expression" => $_expression, "scope" => $_scope]');
$fixture = new FakeFixture();
$fixture = new SimpleFixture('dummy', 'Dummy', SpecificationBagFactory::create());
$set = ResolvedFixtureSetFactory::create();
$scope = [
'foo' => 'bar',
Expand All @@ -144,6 +145,45 @@ public function testVariablesInference()
$resolver = new EvaluatedValueResolver();
$actual = $resolver->resolve($value, $fixture, $set, $scope, new GenerationContext());

$this->assertEquals($expected, $actual);
$this->assertSame(['foo' => 'bar'], $scope);

$value = new EvaluatedValue('$scope');
try {
$resolver->resolve($value, $fixture, $set, $scope, new GenerationContext());
$this->fail('Expected an exception to be thrown.');
} catch (UnresolvableValueException $exception) {
$this->assertEquals(
'Could not evaluate the expression "$scope".',
$exception->getMessage()
);
}
}

public function testVariablesInferenceWithCurrent()
{
$value = new EvaluatedValue('["foo" => $foo, "expression" => $_expression, "scope" => $_scope]');
$fixture = new SimpleFixture('dummy_1', 'Dummy', SpecificationBagFactory::create(), '1');
$set = ResolvedFixtureSetFactory::create();
$scope = [
'foo' => 'bar',
];

$expected = new ResolvedValueWithFixtureSet(
[
'foo' => 'bar',
'expression' => '["foo" => $foo, "expression" => $_expression, "scope" => $_scope]',
'scope' => [
'foo' => 'bar',
'current' => '1',
],
],
$set
);

$resolver = new EvaluatedValueResolver();
$actual = $resolver->resolve($value, $fixture, $set, $scope, new GenerationContext());

$this->assertEquals($expected, $actual);

$value = new EvaluatedValue('$scope');
Expand Down
23 changes: 22 additions & 1 deletion tests/Loader/LoaderIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2038,7 +2038,7 @@ public function provideFixturesToGenerate()
],
];

yield '[identity] has access to variables' => [
yield '[identity] has access to fixtures' => [
[
\stdClass::class => [
'dummy' => [
Expand All @@ -2062,6 +2062,27 @@ public function provideFixturesToGenerate()
],
];

yield '[identity] has access to current' => [
[
\stdClass::class => [
'dummy_{1..2}' => [
'foo' => '<($current)>'
],
],
],
[
'parameters' => [],
'objects' => [
'dummy_1' => StdClassFactory::create([
'foo' => '1',
]),
'dummy_2' => StdClassFactory::create([
'foo' => '2',
]),
],
],
];

yield '[templating] templates are not returned' => [
[
\stdClass::class => [
Expand Down

0 comments on commit cfa21ed

Please sign in to comment.