Skip to content

Commit

Permalink
Add Behat tests to assert the integration with Behat works and to dem…
Browse files Browse the repository at this point in the history
…onstrate how to use the lib
  • Loading branch information
J-Ben87 committed Jun 8, 2023
1 parent 3b14f32 commit bd6c2a3
Show file tree
Hide file tree
Showing 14 changed files with 476 additions and 19 deletions.
5 changes: 5 additions & 0 deletions behat.yaml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
default:
suites:
default:
contexts:
- 'Presta\BehatParser\Tests\Behat\Context\EvaluatorContext'
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
"require-dev": {
"ext-pdo_sqlite": "*",
"behat/behat": "^3.13",
"dama/doctrine-test-bundle": "^7.2",
"doctrine/doctrine-bundle": "^2.9",
"doctrine/orm": "^2.15",
Expand All @@ -42,6 +43,7 @@
"autoload-dev": {
"psr-4": {
"Presta\\BehatParser\\Tests\\Application\\": "tests/Application/src/",
"Presta\\BehatParser\\Tests\\Behat\\": "tests/Behat/",
"Presta\\BehatParser\\Tests\\Extension\\": "tests/Extension/",
"Presta\\BehatParser\\Tests\\Integration\\": "tests/Integration/",
"Presta\\BehatParser\\Tests\\Resources\\": "tests/Resources/",
Expand Down
143 changes: 143 additions & 0 deletions docs/behat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Behat

## Usage

When creating a [Behat step][1], you may get inputs as parameters.

Sometimes you'll need to evaluate these parameters to transform the placeholder(s) they may contain.

You can do that very easily by using the [Evaluator][4] provided by this library.

#### Using the [Friends of Behat's SymfonyExtension][3]

This extension allows you to take advantage of the dependency injection.

You should be able to inject the [Evaluator][4] in your custom [Behat Context][2]'s constructor and invoke it out of the box.

```php
<?php

namespace App\Tests\Behat\Context;

use Behat\Behat\Context\Context;
use Presta\BehatParser\Evaluator;

final class MyContext implements Context
{
public function __construct(private readonly Evaluator $evaluate)
{
}

/**
* @Then I should see :text
*/
public function assertPageTextContains(string $text): void
{
$text = ($this->evaluate)($text);

// ...
}
}
```

The [Evaluator][4]'s configuration can be customized through dependency injection:

```yaml
services:
_instanceof:
Adapter:
tags: ['app.presta_behat_adapter']

App\Adapter\CustomAdapter:
tags: ['app.presta_behat_adapter']

Presta\BehatParser\Evaluator:
arguments:
$adapters: !tagged_iterator 'app.presta_behat_adapter'

Presta\BehatParser\ExpressionLanguage\ExpressionLanguage:
arguments:
$culture: 'fr_FR'

Presta\BehatParser\Foundry\FactoryClassFactory:
arguments:
$namespace: 'Your\Custom\Namespace'
```

#### Using without dependency injection

There is also a way to use the [Evaluator][4] easily without dependency injection.

The class exposes 2 static methods that use a default configuration which can be easily extended.

```php
<?php

namespace App\Tests\Behat\Context;

use Behat\Behat\Context\Context;
use Presta\BehatParser\Evaluator;

final class MyContext implements Context
{
/**
* @Given the database contains a :entity like:
* @Given the database contains an :entity like:
*/
public function assertPageTextContains(string $entity, TableNode $data): void
{
$entity = Evaluator::evaluate($entity);
$data = array_map(
static fn (array $attributes): array => Evaluator::evaluateMany($attributes),
$data->getHash(),
);

// ...
}
}
```

The static methods create an [Evaluator][4] thank's to the [EvaluatorBuilder][5] which allows to customize the configuration.

```php
<?php

namespace App\Tests\Behat\Context;

use Behat\Behat\Context\Context;
use Presta\BehatParser\Evaluator;
use Presta\BehatParser\EvaluatorBuilder;

final class MyContext implements Context
{
/**
* @Then I should see :text
*/
public function assertPageTextContains(string $text): void
{
$builder = new EvaluatorBuilder();

// customize the options

$text = Evaluator::evaluate($text, $builder);

// ...
}
}
```

See the [evaluator builder][8] guide for more details.

---

You may return to the [README][6] or read the [evaluator][7], the [evaluator builder][8] or the [adapters][9] guides.

[1]: https://behat.org/en/latest/user_guide/writing_scenarios.html#steps
[2]: https://behat.org/en/latest/user_guide/context.html
[3]: https://github.com/FriendsOfBehat/SymfonyExtension
[4]: ../src/Evaluator.php
[5]: ../src/EvaluatorBuilder.php
[6]: ../README.md
[7]: ./evaluator.md
[8]: ./evaluator_builder.md
[9]: ./adapters/
5 changes: 3 additions & 2 deletions docs/evaluator.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ $value = $evaluate('any value');

---

You may return to the [README][2] or read the [adapters][3] guides.
You may return to the [README][2] or read the [evaluator builder][3] or the [adapters][4] guides.

[1]: ../src/Evaluator.php
[2]: ../README.md
[3]: ./adapters/
[3]: ./evaluator_builder.md
[4]: ./adapters/
32 changes: 32 additions & 0 deletions docs/evaluator_builder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# EvaluatorBuilder

The [EvaluatorBuilder][1] build an [Evaluator][2] after configuring a few options.

## Usage

```php
$builder = new EvaluatorBuilder();

// allows you to add a custom adapter
$builder->registerAdapter($customAdapter);

// the default is "en_US"
$builder->withCulture('fr_FR');

// the default is "App\\Foundry\\Factory"
$builder->withFactoryNamespace('Your\Custom\Namespace');

// the default is created using InflectorFactory::create()->build()
$builder->withInflector($inflector);

$evaluator = $builder->build();
```

---

You may return to the [README][2] or read the [evaluator][3] or the [adapters][4] guides.

[1]: ../src/Evaluator.php
[2]: ../README.md
[3]: ./evaluator.md
[4]: ./adapters/
10 changes: 6 additions & 4 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ All you need is to instantiate the [Presta\BehatParser\Evaluator][6] with a coll

> Simple as that!
[More details here][10].
[More details here][11].

## How it works?

Expand All @@ -123,7 +123,7 @@ In the end, the value will be returned after having been transformed (or not) by

---

You may return to the [README][9] or read the [evaluator][10] or the [adapters][11] guides.
You may return to the [README][9] or read the [behat][10], the [evaluator][11], the [evaluator builder][12] or the [adapters][13] guides.

[1]: https://behat.org/en/latest/index.html
[2]: https://behat.org/en/latest/quick_start.html#installation
Expand All @@ -134,5 +134,7 @@ You may return to the [README][9] or read the [evaluator][10] or the [adapters][
[7]: ../src/Adapter/AdapterInterface.php
[8]: https://symfony.com/doc/current/components/expression_language.html
[9]: ../README.md
[10]: ./evaluator.md
[11]: ./adapters/
[10]: ./behat.md
[11]: ./evaluator.md
[12]: ./evaluator_builder.md
[13]: ./adapters/
13 changes: 13 additions & 0 deletions features/evaluate.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Feature:
As a test user
I want to evaluate input string
So that I can transform them in more complex objects

Scenario:
Given the local storage contains:
| <datetime_immutable("2023-01-01")> |
| <datetime("today")> |
When I format the datetime entries of the local storage with "d/m/Y"
Then the local storage should contain:
| 01/01/2023 |
| <datetime("today", "d/m/Y")> |
20 changes: 20 additions & 0 deletions src/Evaluator.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,24 @@ public function __invoke(mixed $value): mixed

return $value;
}

public static function evaluate(mixed $value, EvaluatorBuilder $builder = new EvaluatorBuilder()): mixed
{
$evaluate = $builder->build();

return $evaluate($value);
}

/**
* @param list<mixed> $values
*
* @return list<mixed>
*/
public static function evaluateMany(array $values, EvaluatorBuilder $builder = new EvaluatorBuilder()): array
{
return array_map(
static fn (mixed $value): mixed => self::evaluate($value, $builder),
$values,
);
}
}
84 changes: 84 additions & 0 deletions src/EvaluatorBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

declare(strict_types=1);

namespace Presta\BehatParser;

use Doctrine\Inflector\Inflector;
use Doctrine\Inflector\InflectorFactory;
use Presta\BehatParser\Adapter\AdapterInterface;
use Presta\BehatParser\Adapter\ConstantAdapter;
use Presta\BehatParser\Adapter\DateTimeAdapter;
use Presta\BehatParser\Adapter\FactoryAdapter;
use Presta\BehatParser\Adapter\NthAdapter;
use Presta\BehatParser\Adapter\ScalarAdapter;
use Presta\BehatParser\Adapter\UnescapeAdapter;
use Presta\BehatParser\ExpressionLanguage\ExpressionLanguage;
use Presta\BehatParser\Foundry\FactoryClassFactory;

final class EvaluatorBuilder
{
/**
* @var list<AdapterInterface>
*/
private array $adapters = [];

private string $culture = 'en_US';

private string $factoryNamespace = 'App\\Foundry\\Factory';

private Inflector $inflector;

public function __construct()
{
$this->inflector = InflectorFactory::create()->build();
}

public function registerAdapter(AdapterInterface $adapter): self
{
$this->adapters[] = $adapter;

return $this;
}

public function withCulture(string $culture): self
{
$this->culture = $culture;

return $this;
}

public function withFactoryNamespace(string $factoryNamespace): self
{
$this->factoryNamespace = $factoryNamespace;

return $this;
}

public function withInflector(Inflector $inflector): self
{
$this->inflector = $inflector;

return $this;
}

public function build(): Evaluator
{
$expressionLanguage = new ExpressionLanguage(
new FactoryClassFactory($this->factoryNamespace, $this->inflector),
$this->culture,
);

return new Evaluator(
[
new ConstantAdapter($expressionLanguage),
new DateTimeAdapter($expressionLanguage),
new FactoryAdapter($expressionLanguage),
new NthAdapter(),
new ScalarAdapter(),
new UnescapeAdapter(),
...$this->adapters,
],
);
}
}
10 changes: 2 additions & 8 deletions src/Foundry/FactoryClassFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@
namespace Presta\BehatParser\Foundry;

use Doctrine\Inflector\Inflector;
use Doctrine\Inflector\InflectorFactory;
use Zenstruck\Foundry\ModelFactory;

final class FactoryClassFactory
{
private readonly Inflector $inflector;

public function __construct(
private readonly string $namespace = 'App\\Foundry\\Factory\\',
Inflector $inflector = null,
) {
$this->inflector = $inflector ?? InflectorFactory::create()->build();
public function __construct(private readonly string $namespace, private readonly Inflector $inflector)
{
}

public function fromName(string $name): string
Expand Down
Loading

0 comments on commit bd6c2a3

Please sign in to comment.