From 1fbed57e2b2a78d9030c771914c269f2bf7e91d5 Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Sun, 26 Jul 2020 12:20:33 +0200 Subject: [PATCH 1/6] feat(test): add behat tests This commit adds the first functional tests. --- .github/workflows/ci.yml | 31 ++++----- .gitignore | 1 + .php_cs.dist | 2 +- Makefile | 3 + behat.yaml | 11 ++++ composer.json | 11 +++- features/crud.feature | 61 ++++++++++++++++++ tests/Behat/Context/AbstractContext.php | 26 ++++++++ tests/Behat/Context/BasicsContext.php | 69 +++++++++++++++++++++ tests/Behat/Context/TodoContext.php | 29 +++++++++ tests/TestApplication/.env | 2 + tests/TestApplication/bin/console | 43 +++++++++++++ tests/TestApplication/config/bootstrap.php | 7 +++ tests/TestApplication/config/bundles.php | 21 +++++++ tests/TestApplication/config/config.yaml | 34 ++++++++++ tests/TestApplication/config/melodiia.yaml | 3 + tests/TestApplication/config/routing.yaml | 21 +++++++ tests/TestApplication/public/index.php | 27 ++++++++ tests/TestApplication/src/Entity/Todo.php | 39 ++++++++++++ tests/TestApplication/src/Form/TodoType.php | 23 +++++++ tests/TestApplication/src/Kernel.php | 29 +++++++++ tests/TestApplication/var/.gitkeep | 0 22 files changed, 475 insertions(+), 18 deletions(-) create mode 100644 behat.yaml create mode 100644 features/crud.feature create mode 100644 tests/Behat/Context/AbstractContext.php create mode 100644 tests/Behat/Context/BasicsContext.php create mode 100644 tests/Behat/Context/TodoContext.php create mode 100644 tests/TestApplication/.env create mode 100755 tests/TestApplication/bin/console create mode 100644 tests/TestApplication/config/bootstrap.php create mode 100644 tests/TestApplication/config/bundles.php create mode 100644 tests/TestApplication/config/config.yaml create mode 100644 tests/TestApplication/config/melodiia.yaml create mode 100644 tests/TestApplication/config/routing.yaml create mode 100644 tests/TestApplication/public/index.php create mode 100644 tests/TestApplication/src/Entity/Todo.php create mode 100644 tests/TestApplication/src/Form/TodoType.php create mode 100644 tests/TestApplication/src/Kernel.php create mode 100644 tests/TestApplication/var/.gitkeep diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f4665c..5c4ee71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: - cron: '0 0 * * *' jobs: - tests: + unit-test: runs-on: ubuntu-latest strategy: @@ -17,24 +17,14 @@ jobs: php: [7.4] steps: - - name: Setup PHP - run: | - sudo update-alternatives --set php /usr/bin/php${{ matrix.php }} - echo "date.timezone=UTC" >> /tmp/timezone.ini - sudo mv /tmp/timezone.ini /etc/php/${{ matrix.php }}/cli/conf.d/timezone.ini - echo ${{ matrix.php }} > .php-version - - uses: actions/checkout@v2 - - uses: actions/cache@v1 + - uses: actions/cache@v2 id: cache-composer with: - path: /home/runner/.composer/cache - key: composer-php:${{ matrix.php }}-${{ github.sha }} - restore-keys: composer-php:${{ matrix.php }}- - - - run: mkdir -p /home/runner/.composer/cache - if: steps.cache-composer.outputs.cache-hit != 'true' + path: ~/.composer/cache + key: composer-php-${{ matrix.php }}-${{ github.sha }} + restore-keys: composer-php-${{ matrix.php }}- - name: Valid composer.json run: make test.composer @@ -47,3 +37,14 @@ jobs: - name: Run PHPUnit tests run: make test.phpunit + + functional-test: + runs-on: ubuntu-latest + + strategy: + matrix: + php: [7.4] + + steps: + - name: Run Behat tests + run: make test.behat diff --git a/.gitignore b/.gitignore index f0c5241..035a7a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ composer.lock vendor .php_cs.cache +tests/TestApplication/var \ No newline at end of file diff --git a/.php_cs.dist b/.php_cs.dist index 18581e7..0d7b522 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -2,7 +2,7 @@ $finder = PhpCsFixer\Finder::create() ->in(__DIR__) - ->exclude(['Tests', 'vendor']) + ->exclude(['tests/TestApplication/var', 'vendor']) ; return PhpCsFixer\Config::create() diff --git a/Makefile b/Makefile index 72459eb..d5c8f98 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,9 @@ test.phpcs.fix: ## Run PHP CS Fixer and fix issues if possible test.phpunit: ## Run PHPUnit tests php vendor/bin/phpunit +test.behat: ## Run Behat tests + php vendor/bin/behat + hooks.install: ## Install git hooks @cp -vp resources/git/pre-commit.sh .git/hooks/pre-commit diff --git a/behat.yaml b/behat.yaml new file mode 100644 index 0000000..a15f6d5 --- /dev/null +++ b/behat.yaml @@ -0,0 +1,11 @@ +default: + suites: + default: + contexts: + - SwagIndustries\Melodiia\Tests\Behat\Context\BasicsContext + - SwagIndustries\Melodiia\Tests\Behat\Context\TodoContext + extensions: + FriendsOfBehat\SymfonyExtension: + bootstrap: tests/TestApplication/config/bootstrap.php + kernel: + class: TestApplication\Kernel diff --git a/composer.json b/composer.json index da6731a..17d82a7 100644 --- a/composer.json +++ b/composer.json @@ -4,6 +4,7 @@ "type": "symfony-bundle", "scripts": { "phpcs": "php-cs-fixer fix --using-cache=false", + "test-app": "@php -S localhost:8000 -t tests/TestApplication/public", "post-install-cmd": "make hooks.install" }, "require": { @@ -22,7 +23,11 @@ "symfony/symfony": "^4.3 || ^5.0", "doctrine/orm": "^2.6", "justinrainbow/json-schema": "^5.2", - "doctrine/annotations": "^1.8" + "doctrine/annotations": "^1.8", + "doctrine/doctrine-bundle": "^2.1", + "behat/behat": "^3.7", + "friends-of-behat/symfony-extension": "^2.1", + "fzaninotto/faker": "^1.9" }, "autoload": { "psr-4": { @@ -31,7 +36,9 @@ }, "autoload-dev": { "psr-4": { - "SwagIndustries\\Melodiia\\Test\\": "tests/Melodiia/" + "SwagIndustries\\Melodiia\\Test\\": "tests/Melodiia/", + "TestApplication\\": "tests/TestApplication/src/", + "SwagIndustries\\Melodiia\\Tests\\Behat\\": "tests/Behat/" } }, "license": "MIT", diff --git a/features/crud.feature b/features/crud.feature new file mode 100644 index 0000000..6eaa8e4 --- /dev/null +++ b/features/crud.feature @@ -0,0 +1,61 @@ +Feature: + In order to create, read, update and delete data using the API + As a client software + I should be able use standard REST CRUD actions with todos + + Scenario: list some todo + Given there are some todos + When I make a GET request on "/todos" + Then I should retrieve: + """ + { + "meta": { + "totalPages": 1, + "totalResults": 3, + "currentPage": 1, + "maxPerPage": 30 + }, + "links": { + "prev": null, + "next": null, + "last": "http://localhost/todos", + "first": "http://localhost/todos" + }, + "data": [ + { + "id": 1, + "content": "foo" + }, + { + "id": 2, + "content": "bar" + }, + { + "id": 3, + "content": "baz" + } + ] + } + """ + + Scenario: create a todo and get it + Given I make a "POST" request on "/todos" with the content: + """ + { + "content": "hello" + } + """ + And the last response contains: + """ + { + "id": "1" + } + """ + When I make a GET request on "/todos/1" + Then I should retrieve: + """ + { + "id": 1, + "content": "hello" + } + """ diff --git a/tests/Behat/Context/AbstractContext.php b/tests/Behat/Context/AbstractContext.php new file mode 100644 index 0000000..f88b039 --- /dev/null +++ b/tests/Behat/Context/AbstractContext.php @@ -0,0 +1,26 @@ +kernel = $kernel; + $this->faker = Factory::create(); + } + + protected function getContainer(): ContainerInterface + { + return $this->kernel->getContainer(); + } +} diff --git a/tests/Behat/Context/BasicsContext.php b/tests/Behat/Context/BasicsContext.php new file mode 100644 index 0000000..41ba297 --- /dev/null +++ b/tests/Behat/Context/BasicsContext.php @@ -0,0 +1,69 @@ +getContainer()->get('test.client'); + + if ('GET' === $verb) { + $client->request($verb, $uri); + $this->response = $client->getResponse(); + + return; + } + + if (empty($content)) { + throw new \Exception(sprintf('Cannot process request "%s" with no content.', $verb)); + } + + // Just validate json + json_decode($content->getRaw(), true, 512, JSON_THROW_ON_ERROR); + + $client->request($verb, $uri, [], [], [], $content); + $this->response = $client->getResponse(); + } + + /** + * @Then I should retrieve: + * @Given the last response contains: + */ + public function iShouldRetrieve(PyStringNode $string) + { + $json = $this->response->getContent(); + $expected = \json_encode(\json_decode($string->getRaw(), true, 512, JSON_THROW_ON_ERROR)); + + if ($json !== $expected) { + if (json_decode($json)) { + echo "Expected: $expected\n"; + echo "Actual: $json\n"; + } + + throw new \Exception('Expected request result does not match actual result.'); + } + } + + /** + * @BeforeScenario + */ + public function resetDb() + { + @unlink(dirname(__DIR__) . '/../TestApplication/var/data.db'); + + $entityManager = $this->getContainer()->get('doctrine')->getManager(); + $metadatas = $entityManager->getMetadataFactory()->getAllMetadata(); + $schemaTool = new SchemaTool($entityManager); + $schemaTool->createSchema($metadatas); + } +} diff --git a/tests/Behat/Context/TodoContext.php b/tests/Behat/Context/TodoContext.php new file mode 100644 index 0000000..a66fce9 --- /dev/null +++ b/tests/Behat/Context/TodoContext.php @@ -0,0 +1,29 @@ +getContainer()->get('doctrine')->getManager(); + + $todo1 = new Todo(); + $todo1->setContent('foo'); + $todo2 = new Todo(); + $todo2->setContent('bar'); + $todo3 = new Todo(); + $todo3->setContent('baz'); + + $entityManager->persist($todo1); + $entityManager->persist($todo2); + $entityManager->persist($todo3); + + $entityManager->flush(); + } +} diff --git a/tests/TestApplication/.env b/tests/TestApplication/.env new file mode 100644 index 0000000..d10d56a --- /dev/null +++ b/tests/TestApplication/.env @@ -0,0 +1,2 @@ +APP_ENV=test +DATABASE_URL=sqlite:///%kernel.project_dir%/var/data.db diff --git a/tests/TestApplication/bin/console b/tests/TestApplication/bin/console new file mode 100755 index 0000000..b4995e2 --- /dev/null +++ b/tests/TestApplication/bin/console @@ -0,0 +1,43 @@ +#!/usr/bin/env php +getParameterOption(['--env', '-e'], null, true)) { + putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env); +} + +if ($input->hasParameterOption('--no-debug', true)) { + putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0'); +} + +(new Dotenv())->bootEnv(dirname(__DIR__).'/.env'); + +if ($_SERVER['APP_DEBUG']) { + umask(0000); + + if (class_exists(Debug::class)) { + Debug::enable(); + } +} + +$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); +$application = new Application($kernel); +$application->run($input); diff --git a/tests/TestApplication/config/bootstrap.php b/tests/TestApplication/config/bootstrap.php new file mode 100644 index 0000000..d198651 --- /dev/null +++ b/tests/TestApplication/config/bootstrap.php @@ -0,0 +1,7 @@ +bootEnv(dirname(__DIR__) . '/.env'); diff --git a/tests/TestApplication/config/bundles.php b/tests/TestApplication/config/bundles.php new file mode 100644 index 0000000..cdb8dc1 --- /dev/null +++ b/tests/TestApplication/config/bundles.php @@ -0,0 +1,21 @@ + ['all' => true], + Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], +// Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], +// Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], +// Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], + FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle::class => ['test' => true], + \SwagIndustries\Melodiia\Bridge\Symfony\MelodiiaBundle::class => ['all' => true], +// DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true], +// Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], +// Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], +// Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], +// Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], +// Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], +// HtmlSanitizer\Bundle\HtmlSanitizerBundle::class => ['all' => true], +]; diff --git a/tests/TestApplication/config/config.yaml b/tests/TestApplication/config/config.yaml new file mode 100644 index 0000000..e29d9d7 --- /dev/null +++ b/tests/TestApplication/config/config.yaml @@ -0,0 +1,34 @@ +parameters: + router.request_context.host: 'localhost' + +framework: + serializer: ~ + form: ~ + test: ~ + +doctrine: + dbal: + url: '%env(resolve:DATABASE_URL)%' + + # IMPORTANT: You MUST configure your server version, + # either here or in the DATABASE_URL env var (see .env file) + #server_version: '5.7' + orm: + auto_generate_proxy_classes: true + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware + auto_mapping: true + mappings: + TestApplication: + is_bundle: false + type: annotation + dir: '%kernel.project_dir%/src/Entity' + prefix: 'TestApplication\Entity' + alias: App + +services: + _defaults: + autowire: true + autoconfigure: true + + SwagIndustries\Melodiia\Tests\Behat\: + resource: '../../Behat/*' diff --git a/tests/TestApplication/config/melodiia.yaml b/tests/TestApplication/config/melodiia.yaml new file mode 100644 index 0000000..6d20b87 --- /dev/null +++ b/tests/TestApplication/config/melodiia.yaml @@ -0,0 +1,3 @@ +melodiia: + apis: + main: ~ diff --git a/tests/TestApplication/config/routing.yaml b/tests/TestApplication/config/routing.yaml new file mode 100644 index 0000000..8ef5fa6 --- /dev/null +++ b/tests/TestApplication/config/routing.yaml @@ -0,0 +1,21 @@ +get_todos: + path: /todos + controller: 'melodiia.crud.controller.get_all' + methods: GET + defaults: + melodiia_model: TestApplication\Entity\Todo + +get_todo: + path: /todos/{id} + controller: 'melodiia.crud.controller.get' + methods: GET + defaults: + melodiia_model: TestApplication\Entity\Todo + +post_todos: + path: /todos + controller: 'melodiia.crud.controller.create' + methods: POST + defaults: + melodiia_model: TestApplication\Entity\Todo + melodiia_form: TestApplication\Form\TodoType diff --git a/tests/TestApplication/public/index.php b/tests/TestApplication/public/index.php new file mode 100644 index 0000000..610a8e8 --- /dev/null +++ b/tests/TestApplication/public/index.php @@ -0,0 +1,27 @@ +handle($request); +$response->send(); +$kernel->terminate($request, $response); diff --git a/tests/TestApplication/src/Entity/Todo.php b/tests/TestApplication/src/Entity/Todo.php new file mode 100644 index 0000000..61e7e47 --- /dev/null +++ b/tests/TestApplication/src/Entity/Todo.php @@ -0,0 +1,39 @@ +id; + } + + public function getContent(): ?string + { + return $this->content; + } + + public function setContent($content): void + { + $this->content = $content; + } +} diff --git a/tests/TestApplication/src/Form/TodoType.php b/tests/TestApplication/src/Form/TodoType.php new file mode 100644 index 0000000..09df7c7 --- /dev/null +++ b/tests/TestApplication/src/Form/TodoType.php @@ -0,0 +1,23 @@ +add('content', TextType::class, ['constraints' => new NotBlank()]); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefault('data_class', Todo::class); + } +} diff --git a/tests/TestApplication/src/Kernel.php b/tests/TestApplication/src/Kernel.php new file mode 100644 index 0000000..88b956c --- /dev/null +++ b/tests/TestApplication/src/Kernel.php @@ -0,0 +1,29 @@ +import('../config/config.yaml'); + $container->import('../config/melodiia.yaml'); + } + + protected function configureRoutes(RoutingConfigurator $routes): void + { + $routes->import('../config/routing.yaml'); + } + + public function getProjectDir() + { + return dirname(__DIR__); + } +} diff --git a/tests/TestApplication/var/.gitkeep b/tests/TestApplication/var/.gitkeep new file mode 100644 index 0000000..e69de29 From 7ee70eb35557693cdb6aeb1a182acf31b99cf534 Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Tue, 18 Aug 2020 18:00:11 +0200 Subject: [PATCH 2/6] feat(config): adds editorconfig See https://editorconfig.org/ for details. --- .editorconfig | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c18da54 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,29 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true + +# Matches multiple files with brace expansion notation +# Set default charset +[*.{js,ts}] +indent_size = 2 + +# Tab indentation (no size specified) +[Makefile] +indent_style = tab + +[*.md] +max_line_length = off +trim_trailing_whitespace = false + +[*.{yaml,yml}] +indent_size = 2 From 13b795a891357beea7b22ffc179f274d4f8a9380 Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Tue, 18 Aug 2020 18:00:55 +0200 Subject: [PATCH 3/6] fix(form): entity without constructor is now supported Problem: after building the functional test suite I figure out that there was an error if the entity have no constructor. Which must obviously be supported. Solution: modify the domain object data mapper that was an issue for it. --- src/Bridge/Symfony/Form/DomainObjectsDataMapper.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Bridge/Symfony/Form/DomainObjectsDataMapper.php b/src/Bridge/Symfony/Form/DomainObjectsDataMapper.php index 81b149a..5aff930 100644 --- a/src/Bridge/Symfony/Form/DomainObjectsDataMapper.php +++ b/src/Bridge/Symfony/Form/DomainObjectsDataMapper.php @@ -32,6 +32,12 @@ public function createObject(iterable $form, string $dataClass = null) } $ref = new \ReflectionClass($dataClass); + + $constructor = $ref->getConstructor(); + if (null === $constructor) { + return new $dataClass(); + } + $constructorParameters = $ref->getConstructor()->getParameters(); // Case of anemic object, we have nothing to do here. From c1774d8daa17a96944f420904ea2e380962f0a8a Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Tue, 18 Aug 2020 18:13:26 +0200 Subject: [PATCH 4/6] fix(ci): reindent & fix ci config --- .github/workflows/ci.yml | 83 +++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c4ee71..0132ce4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,50 +1,63 @@ name: Test suite on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - schedule: - - cron: '0 0 * * *' + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: '0 0 * * *' jobs: - unit-test: - runs-on: ubuntu-latest + unit-test: + runs-on: ubuntu-latest - strategy: - matrix: - php: [7.4] + strategy: + matrix: + php: [7.4] - steps: - - uses: actions/checkout@v2 + steps: + - uses: actions/checkout@v2 - - uses: actions/cache@v2 - id: cache-composer - with: - path: ~/.composer/cache - key: composer-php-${{ matrix.php }}-${{ github.sha }} - restore-keys: composer-php-${{ matrix.php }}- + - uses: actions/cache@v2 + id: cache-composer + with: + path: ~/.composer/cache + key: composer-php-${{ matrix.php }}-${{ github.sha }} + restore-keys: composer-php-${{ matrix.php }}- - - name: Valid composer.json - run: make test.composer + - name: Valid composer.json + run: make test.composer - - name: Install dependencies - run: composer install --prefer-dist --no-progress --no-suggest + - name: Install dependencies + run: composer install --prefer-dist --no-progress --no-suggest - - name: Run PHP CS Fixer - run: make test.phpcs + - name: Run PHP CS Fixer + run: make test.phpcs - - name: Run PHPUnit tests - run: make test.phpunit + - name: Run PHPUnit tests + run: make test.phpunit - functional-test: - runs-on: ubuntu-latest + functional-test: + runs-on: ubuntu-latest - strategy: - matrix: - php: [7.4] + strategy: + matrix: + php: [7.4] - steps: - - name: Run Behat tests - run: make test.behat + steps: + - uses: actions/checkout@v2 + + - uses: actions/cache@v2 + id: cache-composer + with: + path: ~/.composer/cache + key: composer-php-${{ matrix.php }}-${{ github.sha }} + restore-keys: composer-php-${{ matrix.php }}- + + + - name: Install dependencies + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Run Behat tests + run: make test.behat From 9e0ed4dd7d4c3ceb63476d4399a5e7089a8dfef6 Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Tue, 18 Aug 2020 18:19:34 +0200 Subject: [PATCH 5/6] feat(config): .feature files are indent 2 spaces --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index c18da54..a4f1633 100644 --- a/.editorconfig +++ b/.editorconfig @@ -25,5 +25,5 @@ indent_style = tab max_line_length = off trim_trailing_whitespace = false -[*.{yaml,yml}] +[*.{yaml,yml,feature}] indent_size = 2 From fe39347cf3836d0f35a383d0cfa032e8e6e5f9fe Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Tue, 18 Aug 2020 18:20:41 +0200 Subject: [PATCH 6/6] update(changelog): add behat to changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d374be..be4e51d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Support of more kind of FormError -- Removed requirement to have CSRF protection enabled #25 +- Removed the requirement to have CSRF protection enabled #25 +- Behat test suite. Melodiia is officially battle tested! ### Changed - Huge BC Break on namespaces. You need to rename all classes used to SwagIndustries instead of Biig