diff --git a/.gitattributes b/.gitattributes index 1842989ac..830ddef1d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,4 +15,6 @@ /phpstan.neon export-ignore /phpunit-dama-doctrine.xml.dist export-ignore /phpunit.xml.dist export-ignore +/behat.yml.dist export-ignore /tests export-ignore +/features export-ignore diff --git a/.gitignore b/.gitignore index cdc5006a5..af6f45707 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /composer.lock /phpunit.xml /phpunit-dama-doctrine.xml +/behat.yml /vendor/ /bin/tools/*/vendor/ /build/ diff --git a/behat.yml.dist b/behat.yml.dist new file mode 100644 index 000000000..063097bea --- /dev/null +++ b/behat.yml.dist @@ -0,0 +1,14 @@ +default: + extensions: + FriendsOfBehat\SymfonyExtension: + kernel: + class: Zenstruck\Foundry\Tests\Fixtures\Kernel + bootstrap: tests/bootstrap.php + + suites: + default: + paths: [ "%paths.base%/tests/Behat" ] + contexts: + - Zenstruck\Foundry\Tests\Behat\TestContext + - Zenstruck\Foundry\Test\Behat\FactoriesContext + - Zenstruck\Foundry\Test\Behat\ResetDatabaseContext diff --git a/composer.json b/composer.json index e0389b7c0..bb25907bc 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "doctrine/doctrine-migrations-bundle": "^2.2|^3.0", "doctrine/mongodb-odm-bundle": "^3.1|^4.2", "doctrine/orm": "^2.7", + "friends-of-behat/symfony-extension": "^2.4", "matthiasnoback/symfony-dependency-injection-test": "^4.1", "symfony/framework-bundle": "^4.4|^5.0|^6.0", "symfony/maker-bundle": "^1.30", @@ -54,6 +55,9 @@ "App\\Tests\\": "tests/Fixtures/tmp/tests" } }, + "suggest": { + "friends-of-behat/symfony-extension": "To use the Behat contexts" + }, "extra": { "bamarni-bin": { "target-directory": "bin/tools", diff --git a/src/Bundle/DependencyInjection/ZenstruckFoundryExtension.php b/src/Bundle/DependencyInjection/ZenstruckFoundryExtension.php index 69a5be76a..db671607e 100644 --- a/src/Bundle/DependencyInjection/ZenstruckFoundryExtension.php +++ b/src/Bundle/DependencyInjection/ZenstruckFoundryExtension.php @@ -4,15 +4,19 @@ use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle; +use FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle; use Symfony\Bundle\MakerBundle\Maker\AbstractMaker; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension; use Zenstruck\Foundry\Bundle\Command\StubMakeFactory; use Zenstruck\Foundry\Bundle\Command\StubMakeStory; use Zenstruck\Foundry\ModelFactory; use Zenstruck\Foundry\Story; +use Zenstruck\Foundry\Test\Behat\FactoriesContext; +use Zenstruck\Foundry\Test\Behat\ResetDatabaseContext; use Zenstruck\Foundry\Test\ORMDatabaseResetter; /** @@ -49,6 +53,11 @@ protected function loadInternal(array $mergedConfig, ContainerBuilder $container $container->register('.zenstruck_foundry.maker.factory_stub', StubMakeFactory::class)->addTag('console.command'); $container->register('.zenstruck_foundry.maker.story_stub', StubMakeStory::class)->addTag('console.command'); } + + if (self::isBundleLoaded($container, FriendsOfBehatSymfonyExtensionBundle::class)) { + $container->register(FactoriesContext::class)->addArgument(new Reference('service_container'))->setAutoconfigured(true); + $container->register(ResetDatabaseContext::class)->setAutowired(true)->setAutoconfigured(true); + } } private function configureFaker(array $config, ContainerBuilder $container): void diff --git a/src/Test/Behat/FactoriesContext.php b/src/Test/Behat/FactoriesContext.php new file mode 100644 index 000000000..6281b4d23 --- /dev/null +++ b/src/Test/Behat/FactoriesContext.php @@ -0,0 +1,41 @@ + + */ +final class FactoriesContext implements Context +{ + public function __construct(private ContainerInterface $container) + { + } + + /** + * @BeforeScenario + */ + public function setUpFactories(): void + { + TestState::bootFromContainer($this->container); + Factory::configuration()->setManagerRegistry( + new LazyManagerRegistry(function (): ChainManagerRegistry { + return TestState::initializeChainManagerRegistry($this->container); + }) + ); + } + + /** + * @AfterScenario + */ + public function tearDownFactories(): void + { + TestState::shutdownFoundry(); + } +} diff --git a/src/Test/Behat/ResetDatabaseContext.php b/src/Test/Behat/ResetDatabaseContext.php new file mode 100644 index 000000000..262686ad2 --- /dev/null +++ b/src/Test/Behat/ResetDatabaseContext.php @@ -0,0 +1,33 @@ + + */ +final class ResetDatabaseContext implements Context +{ + public function __construct(private KernelInterface $kernel) + { + } + + /** + * @BeforeScenario + */ + public function resetDatabase(): void + { + DatabaseResetter::resetDatabase($this->kernel); + } + + /** + * @AfterScenario + */ + public function resetSchema(): void + { + DatabaseResetter::resetSchema($this->kernel); + } +} diff --git a/tests/Behat/Foundry.feature b/tests/Behat/Foundry.feature new file mode 100644 index 000000000..35fc4b90b --- /dev/null +++ b/tests/Behat/Foundry.feature @@ -0,0 +1,15 @@ +Feature: Behat support for Foundry + + As a developer writing tests with Behat, I want to be able to + use Foundry for creating test data. Foundry needs to be configured, + started and stopped accordingly. The database has to be reset before + scenarios are run. + + Scenario: Creating two categories + When I create 2 categories + Then there should be 2 categories in the database + + Scenario: Adding to the database + Given 1 category has been created + When I create 2 categories + Then there should be 3 categories in the database diff --git a/tests/Behat/TestContext.php b/tests/Behat/TestContext.php new file mode 100644 index 000000000..18d048b6f --- /dev/null +++ b/tests/Behat/TestContext.php @@ -0,0 +1,29 @@ + + */ +final class TestContext implements Context +{ + /** + * @Given /^(?P\d+) (?:category has|categories have) been created$/ + * @When /^I create (?P\d+) categor(?:y|ies)$/ + */ + public function createCategories(int $count): void + { + CategoryFactory::createMany($count); + } + + /** + * @Then /^there should be (?P\d+) categor(?:y|ies) in the database$/ + */ + public function assertCategoryCount(int $count): void + { + CategoryFactory::assert()->count($count); + } +} diff --git a/tests/Fixtures/Kernel.php b/tests/Fixtures/Kernel.php index 723a74dd5..612d98b62 100644 --- a/tests/Fixtures/Kernel.php +++ b/tests/Fixtures/Kernel.php @@ -6,14 +6,18 @@ use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle; use Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle; +use FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\MakerBundle\MakerBundle; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\Kernel as BaseKernel; use Symfony\Component\Routing\RouteCollectionBuilder; +use Zenstruck\Foundry\Test\Behat\FactoriesContext; use Zenstruck\Foundry\Test\ORMDatabaseResetter; +use Zenstruck\Foundry\Tests\Behat\TestContext; use Zenstruck\Foundry\Tests\Fixtures\Factories\AddressFactory; use Zenstruck\Foundry\Tests\Fixtures\Factories\CategoryFactory; use Zenstruck\Foundry\Tests\Fixtures\Factories\CategoryServiceFactory; @@ -79,6 +83,8 @@ public function registerBundles(): iterable if ($this->enableDoctrine && \getenv('USE_ODM')) { yield new DoctrineMongoDBBundle(); } + + yield new FriendsOfBehatSymfonyExtensionBundle(); } public function getCacheDir(): string @@ -98,6 +104,10 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ->setAutowired(true) ; + $c->register(TestContext::class) + ->setAutoconfigured(true) + ->setAutowired(true); + foreach ($this->factoriesRegistered as $factory) { $c->register($factory) ->setAutoconfigured(true)