Skip to content

Commit

Permalink
Added Functional tests for Symfony & Twig integration
Browse files Browse the repository at this point in the history
  • Loading branch information
yohang committed Jan 13, 2025
1 parent 3238aa5 commit dd07204
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 12 deletions.
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
"symfony/framework-bundle": ">=5.4,<8",
"symfony/event-dispatcher": ">=5.4,<8",
"symfony/stopwatch": ">=5.4,<8",
"symfony/twig-bundle": ">=5.4,<8"
"symfony/twig-bundle": ">=5.4,<8",
"symfony/browser-kit": ">=5.4,<8",
"symfony/css-selector": ">=5.4,<8"
},
"autoload": {
"psr-4": {
Expand Down
32 changes: 21 additions & 11 deletions src/Extension/Twig/FiniteExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,31 @@ class FiniteExtension extends AbstractExtension
{
public function __construct(
private readonly StateMachine $stateMachine,
) {}
)
{
}

public function getFunctions(): array
{
return [
new TwigFunction(
'finite_can',
/** @param class-string|null $stateClass */
fn(object $object, string $transitionName, ?string $stateClass = null) => $this->stateMachine->can($object, $transitionName, $stateClass),
),
new TwigFunction(
'finite_reachable_transitions',
/** @param class-string|null $stateClass */
fn(object $object, ?string $stateClass = null) => $this->stateMachine->getReachablesTransitions($object, $stateClass),
),
new TwigFunction('finite_can', $this->can(...)),
new TwigFunction('finite_reachable_transitions', $this->finiteReachableTransitions(...)),
];
}

/**
* @param class-string|null $stateClass
*/
public function can(object $object, string $transitionName, ?string $stateClass = null): bool
{
return $this->stateMachine->can($object, $transitionName, $stateClass);
}

/**
* @param class-string|null $stateClass
*/
public function finiteReachableTransitions(object $object, ?string $stateClass = null): array
{
return $this->stateMachine->getReachablesTransitions($object, $stateClass);
}
}
31 changes: 31 additions & 0 deletions tests/Extension/Symfony/Fixtures/Controller/FiniteController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);

namespace Finite\Tests\Extension\Symfony\Fixtures\Controller;

use Finite\Tests\Extension\Symfony\Fixtures\Model\Document;
use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;

final class FiniteController
{
public function __construct(
private readonly Environment $twig,
)
{
}

public function __invoke(): Response
{
$document = new Document;

return new Response(
$this->twig->render(
'finite.html.twig',
[
'document' => $document,
]
),
);
}
}
26 changes: 26 additions & 0 deletions tests/Extension/Symfony/Fixtures/app/AppKernel.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
<?php
declare(strict_types=1);

use Finite\Tests\Extension\Symfony\Fixtures\Controller\FiniteController;
use Psr\Log\NullLogger;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

class AppKernel extends Kernel
{
Expand All @@ -22,12 +27,33 @@ public function registerBundles(): iterable
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader): void
{
$c->setParameter('kernel.debug', true);
$c->setParameter('kernel.secret', uniqid());
$c->prependExtensionConfig('framework', ['test' => true, 'profiler' => true]);
$c->prependExtensionConfig('twig', ['paths' => [__DIR__.'/templates']]);

$c->addDefinitions(
[
FiniteController::class => (new Definition(FiniteController::class))
->setAutowired(true)
->addTag('controller.service_arguments'),
'logger' => (new Definition(NullLogger::class))
]
);
}

public function getProjectDir(): string
{
return __DIR__;
}

public function loadRoutes(LoaderInterface $loader): RouteCollection
{
$collection = new RouteCollection;
$collection->add(
'finite',
new Route('/finite', ['_controller' => FiniteController::class]),
);

return $collection;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div class="can">{{ finite_can(document, 'publish') ? 'yes' : 'no' }}</div>
<div class="cannot">{{ finite_can(document, 'clear') ? 'yes' : 'no' }}</div>
<div class="reachables">
{%- for transition in finite_reachable_transitions(document)%}
<span>{{ transition.name }}</span>
{%- endfor -%}
</div>
25 changes: 25 additions & 0 deletions tests/Extension/Symfony/Functional/FiniteTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace Finite\Tests\Extension\Symfony\Functional;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class FiniteTest extends WebTestCase
{
public function test_finite_controller(): void
{
$client = $this->createClient();
$client->request('GET', '/finite');

$this->assertResponseIsSuccessful();
$this->assertSelectorTextContains('.can', 'yes');
$this->assertSelectorTextContains('.cannot', 'no');
$this->assertSelectorTextContains('.reachables', 'publish');
}

protected static function getKernelClass(): string
{
return \AppKernel::class;
}
}

0 comments on commit dd07204

Please sign in to comment.