diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index cbfb196804..44cbf32882 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,13 +10,13 @@ on: jobs: cs-fix: name: Run code style check - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" strategy: matrix: php: - '8.0' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP Action uses: shivammathur/setup-php@v2 @@ -26,7 +26,7 @@ jobs: extensions: 'pdo_sqlite, gd' tools: cs2pr - - uses: "ramsey/composer-install@v1" + - uses: ramsey/composer-install@v2 with: dependency-versions: "highest" @@ -35,7 +35,7 @@ jobs: tests: name: Tests - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" timeout-minutes: 10 strategy: @@ -47,7 +47,7 @@ jobs: - '8.1' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP Action uses: shivammathur/setup-php@v2 @@ -57,7 +57,7 @@ jobs: extensions: pdo_sqlite, gd tools: cs2pr - - uses: "ramsey/composer-install@v1" + - uses: ramsey/composer-install@v2 with: dependency-versions: "highest" composer-options: "--prefer-dist --no-progress" @@ -66,7 +66,113 @@ jobs: run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - name: Run test suite - run: composer run-script --timeout=600 test + run: composer run-script --timeout=600 test-unit - name: Run PHPStan analysis run: composer run-script phpstan + + integration-tests-postgres: + name: PostgreSQL integration tests + needs: tests + services: + postgres: + image: postgres:10 + ports: + - 5432 + env: + POSTGRES_PASSWORD: postgres + POSTGRES_DB: testdb + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + --tmpfs /var/lib/postgresql/data + runs-on: "ubuntu-22.04" + timeout-minutes: 20 + + strategy: + matrix: + php: + - '7.4' + - '8.0' + - '8.1' + + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP Action + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + extensions: pdo_pgsql, gd + tools: cs2pr + + - uses: ramsey/composer-install@v2 + with: + dependency-versions: "highest" + + - name: Setup problem matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Run integration test suite on Postgres + run: composer run-script --timeout=600 test-integration + env: + SEARCH_ENGINE: legacy + DATABASE_URL: "pgsql://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/testdb?server_version=10" + + integration-tests-mysql: + name: MySQL integration tests + needs: tests + + services: + mysql: + image: ghcr.io/ibexa/core/mysql + ports: + - 3306/tcp + env: + MYSQL_RANDOM_ROOT_PASSWORD: true + MYSQL_USER: mysql + MYSQL_PASSWORD: mysql + MYSQL_DATABASE: testdb + options: >- + --health-cmd="mysqladmin ping" + --health-interval=10s + --health-timeout=5s + --health-retries=5 + --tmpfs=/var/lib/mysql + runs-on: "ubuntu-22.04" + timeout-minutes: 20 + + strategy: + fail-fast: false + matrix: + php: + - '7.4' + - '8.0' + - '8.1' + + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP Action + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + extensions: pdo_mysql, gd + tools: cs2pr + + - uses: ramsey/composer-install@v2 + with: + dependency-versions: "highest" + + - name: Setup problem matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Run integration test suite vs MySQL + run: composer run-script --timeout=600 test-integration + env: + SEARCH_ENGINE: legacy + DATABASE_URL: "mysql://mysql:mysql@127.0.0.1:${{ job.services.mysql.ports[3306] }}/testdb" diff --git a/composer.json b/composer.json index 15b055658b..cf4c95091a 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "psr-4": { "Ibexa\\Tests\\Bundle\\AdminUi\\": "tests/bundle/", "Ibexa\\Tests\\AdminUi\\": "tests/lib/", + "Ibexa\\Tests\\Integration\\AdminUi\\": "tests/integration/", "EzSystems\\EzPlatformAdminUi\\Tests\\": "tests/lib/", "Ibexa\\Platform\\Tests\\Assets\\": "tests/lib/" } @@ -63,6 +64,7 @@ "twig/string-extra": "^3.0" }, "require-dev": { + "dama/doctrine-test-bundle": "^v6.7", "ibexa/ci-scripts": "^0.2@dev", "ibexa/behat": "~4.6.0@dev", "friendsofphp/php-cs-fixer": "^3.0", @@ -71,9 +73,11 @@ "ibexa/doctrine-schema": "~4.6.0@dev", "ibexa/http-cache": "~4.6.0@dev", "ibexa/code-style": "^1.0", + "ibexa/test-core": "^0.1.x-dev", "phpstan/phpstan": "^1.10", "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-symfony": "^1.3" + "phpstan/phpstan-symfony": "^1.3", + "symfony/webpack-encore-bundle": "^1.17.2" }, "config": { "allow-plugins": { @@ -84,7 +88,9 @@ "fix-cs": "php-cs-fixer fix --config=.php-cs-fixer.php -v --show-progress=dots", "check-cs": "@fix-cs --dry-run", "phpstan": "phpstan analyse", - "test": "phpunit -c phpunit.xml" + "test": ["@test-unit", "@test-integration"], + "test-unit": "phpunit -c phpunit.xml", + "test-integration": "phpunit -c phpunit.integration.xml" }, "extra": { "branch-alias": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f2890b572c..e0cc17161c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -3685,16 +3685,6 @@ parameters: count: 1 path: src/lib/Event/Options.php - - - message: "#^Call to method getEntrypointLookup\\(\\) on an unknown class Symfony\\\\WebpackEncoreBundle\\\\Asset\\\\EntrypointLookupCollectionInterface\\.$#" - count: 1 - path: src/lib/EventListener/AdminExceptionListener.php - - - - message: "#^Call to method reset\\(\\) on an unknown class Symfony\\\\WebpackEncoreBundle\\\\Asset\\\\TagRenderer\\.$#" - count: 1 - path: src/lib/EventListener/AdminExceptionListener.php - - message: "#^Cannot call method log\\(\\) on Psr\\\\Log\\\\LoggerInterface\\|null\\.$#" count: 1 @@ -3715,26 +3705,6 @@ parameters: count: 1 path: src/lib/EventListener/AdminExceptionListener.php - - - message: "#^Parameter \\$encoreTagRenderer of method Ibexa\\\\AdminUi\\\\EventListener\\\\AdminExceptionListener\\:\\:__construct\\(\\) has invalid type Symfony\\\\WebpackEncoreBundle\\\\Asset\\\\TagRenderer\\.$#" - count: 2 - path: src/lib/EventListener/AdminExceptionListener.php - - - - message: "#^Parameter \\$entrypointLookupCollection of method Ibexa\\\\AdminUi\\\\EventListener\\\\AdminExceptionListener\\:\\:__construct\\(\\) has invalid type Symfony\\\\WebpackEncoreBundle\\\\Asset\\\\EntrypointLookupCollectionInterface\\.$#" - count: 2 - path: src/lib/EventListener/AdminExceptionListener.php - - - - message: "#^Property Ibexa\\\\AdminUi\\\\EventListener\\\\AdminExceptionListener\\:\\:\\$encoreTagRenderer has unknown class Symfony\\\\WebpackEncoreBundle\\\\Asset\\\\TagRenderer as its type\\.$#" - count: 1 - path: src/lib/EventListener/AdminExceptionListener.php - - - - message: "#^Property Ibexa\\\\AdminUi\\\\EventListener\\\\AdminExceptionListener\\:\\:\\$entrypointLookupCollection has unknown class Symfony\\\\WebpackEncoreBundle\\\\Asset\\\\EntrypointLookupCollectionInterface as its type\\.$#" - count: 1 - path: src/lib/EventListener/AdminExceptionListener.php - - message: "#^Property Ibexa\\\\AdminUi\\\\EventListener\\\\AdminExceptionListener\\:\\:\\$siteAccessGroups type has no value type specified in iterable type array\\.$#" count: 1 diff --git a/phpunit.integration.xml b/phpunit.integration.xml new file mode 100644 index 0000000000..aedc8a766a --- /dev/null +++ b/phpunit.integration.xml @@ -0,0 +1,25 @@ + + + + tests/integration + + + + + + + + + + + diff --git a/src/bundle/Resources/config/services/components.yaml b/src/bundle/Resources/config/services/components.yaml index 890c5dacf4..6de3bd5d79 100644 --- a/src/bundle/Resources/config/services/components.yaml +++ b/src/bundle/Resources/config/services/components.yaml @@ -1,6 +1,6 @@ imports: - - { resource: services/components/content/edit.yaml } - - { resource: services/components/content_type/edit.yaml } + - { resource: components/content/edit.yaml } + - { resource: components/content_type/edit.yaml } services: _defaults: diff --git a/src/bundle/Resources/config/services/events.yaml b/src/bundle/Resources/config/services/events.yaml index ca0d5b7841..28316fa85b 100644 --- a/src/bundle/Resources/config/services/events.yaml +++ b/src/bundle/Resources/config/services/events.yaml @@ -5,7 +5,7 @@ services: public: false Ibexa\AdminUi\EventListener\: - resource: "../../../lib/EventListener/*" + resource: "../../../../lib/EventListener/*" public: true tags: - { name: kernel.event_subscriber } diff --git a/src/bundle/Resources/config/services/form_processors.yaml b/src/bundle/Resources/config/services/form_processors.yaml index 9a46dd2156..5896bfa67a 100644 --- a/src/bundle/Resources/config/services/form_processors.yaml +++ b/src/bundle/Resources/config/services/form_processors.yaml @@ -10,7 +10,7 @@ services: public: false Ibexa\AdminUi\Form\Processor\: - resource: "../../../lib/Form/Processor/*" + resource: "../../../../lib/Form/Processor/*" public: true tags: - { name: kernel.event_subscriber } diff --git a/src/bundle/Resources/config/services/tabs.yaml b/src/bundle/Resources/config/services/tabs.yaml index 88b07c80c8..db108b4ae2 100644 --- a/src/bundle/Resources/config/services/tabs.yaml +++ b/src/bundle/Resources/config/services/tabs.yaml @@ -13,7 +13,7 @@ services: lazy: true Ibexa\AdminUi\Tab\Event\Subscriber\: - resource: "../../../lib/Tab/Event/Subscriber/*" + resource: "../../../../lib/Tab/Event/Subscriber/*" public: true tags: ['kernel.event_subscriber'] diff --git a/src/bundle/Resources/config/services/tabs/content_type.yaml b/src/bundle/Resources/config/services/tabs/content_type.yaml index 89fd2e97ac..62b73eccd2 100644 --- a/src/bundle/Resources/config/services/tabs/content_type.yaml +++ b/src/bundle/Resources/config/services/tabs/content_type.yaml @@ -1,6 +1,6 @@ services: Ibexa\AdminUi\Tab\ContentType\: - resource: "../../../lib/Tab/ContentType/*" + resource: "../../../../../lib/Tab/ContentType/*" parent: Ibexa\Contracts\AdminUi\Tab\AbstractEventDispatchingTab public: true tags: diff --git a/src/bundle/Resources/config/services/tabs/locationview.yaml b/src/bundle/Resources/config/services/tabs/locationview.yaml index 25426556f4..180a5f1707 100644 --- a/src/bundle/Resources/config/services/tabs/locationview.yaml +++ b/src/bundle/Resources/config/services/tabs/locationview.yaml @@ -1,6 +1,6 @@ services: Ibexa\AdminUi\Tab\LocationView\: - resource: "../../../lib/Tab/LocationView/*" + resource: "../../../../../lib/Tab/LocationView/*" parent: Ibexa\Contracts\AdminUi\Tab\AbstractTab public: true tags: diff --git a/src/bundle/Resources/config/services/universal_discovery_widget.yaml b/src/bundle/Resources/config/services/universal_discovery_widget.yaml index 434d9efefc..2242cb7b05 100644 --- a/src/bundle/Resources/config/services/universal_discovery_widget.yaml +++ b/src/bundle/Resources/config/services/universal_discovery_widget.yaml @@ -9,7 +9,7 @@ services: - { name: twig.extension } Ibexa\AdminUi\UniversalDiscovery\Event\Subscriber\: - resource: "../../../lib/UniversalDiscovery/Event/Subscriber/*" + resource: "../../../../lib/UniversalDiscovery/Event/Subscriber/*" public: true tags: ['kernel.event_subscriber'] diff --git a/src/bundle/Resources/config/services/utils.yaml b/src/bundle/Resources/config/services/utils.yaml index 58788c9883..45f619f827 100644 --- a/src/bundle/Resources/config/services/utils.yaml +++ b/src/bundle/Resources/config/services/utils.yaml @@ -5,4 +5,4 @@ services: public: false Ibexa\AdminUi\Util\: - resource: "../../../lib/Util" + resource: "../../../../lib/Util" diff --git a/src/bundle/Resources/config/services/validators.yaml b/src/bundle/Resources/config/services/validators.yaml index e028c7b512..5ffab6fa94 100644 --- a/src/bundle/Resources/config/services/validators.yaml +++ b/src/bundle/Resources/config/services/validators.yaml @@ -5,7 +5,7 @@ services: public: false Ibexa\AdminUi\Validator\Constraints\: - resource: "../../../lib/Validator/Constraints" + resource: "../../../../lib/Validator/Constraints" Ibexa\AdminUi\Validator\Constraints\LocationIsWithinCopySubtreeLimitValidator: arguments: diff --git a/tests/integration/AdminUiIbexaTestKernel.php b/tests/integration/AdminUiIbexaTestKernel.php new file mode 100644 index 0000000000..4ec7741667 --- /dev/null +++ b/tests/integration/AdminUiIbexaTestKernel.php @@ -0,0 +1,109 @@ +load(static function (ContainerBuilder $container): void { + $container->setParameter('locale_fallback', 'en'); + }); + + $loader->load(__DIR__ . '/Resources/ibexa.yaml'); + + $loader->load(static function (ContainerBuilder $container): void { + self::configureIbexaDXPBundles($container); + self::configureThirdPartyBundles($container); + }); + } + + private static function configureIbexaDXPBundles(ContainerBuilder $container): void + { + $container->setParameter('form.type_extension.csrf.enabled', false); + $container->setParameter('ibexa.http_cache.purge_type', 'local'); + $container->setParameter('ibexa.http_cache.translation_aware.enabled', false); + $container->setParameter('locale_fallback', 'en'); + $container->register('fragment.renderer.esi', EsiFragmentRenderer::class); + + /** @var \Ibexa\Bundle\Core\DependencyInjection\IbexaCoreExtension $kernel */ + $kernel = $container->getExtension('ibexa'); + $kernel->addConfigParser( + new IgnoredConfigParser( + [ + 'admin_ui_forms', + 'calendar', + 'content_create_view', + 'content_translate_view', + 'content_edit_view', + 'design', + 'search_view', + 'universal_discovery_widget_module', + ] + ) + ); + } + + protected static function getExposedServicesByClass(): iterable + { + yield from parent::getExposedServicesByClass(); + } + + private static function configureThirdPartyBundles(ContainerBuilder $container): void + { + $container->setParameter('fos_http_cache.tag_handler.strict', false); + $container->setParameter('fos_http_cache.compiler_pass.tag_annotations', false); + + self::addSyntheticService($container, Swift_Mailer::class); + self::addSyntheticService($container, JWTTokenManagerInterface::class); + self::addSyntheticService($container, FactoryInterface::class); + self::addSyntheticService($container, TagRenderer::class, 'webpack_encore.tag_renderer'); + self::addSyntheticService( + $container, + EntrypointLookupCollection::class, + 'webpack_encore.entrypoint_lookup_collection' + ); + } +} diff --git a/tests/integration/DependencyInjection/Configuration/IgnoredConfigParser.php b/tests/integration/DependencyInjection/Configuration/IgnoredConfigParser.php new file mode 100644 index 0000000000..3dcb6fc586 --- /dev/null +++ b/tests/integration/DependencyInjection/Configuration/IgnoredConfigParser.php @@ -0,0 +1,41 @@ + */ + private array $keys; + + /** + * @param array $keys + */ + public function __construct(array $keys) + { + $this->keys = $keys; + } + + public function addSemanticConfig(NodeBuilder $nodeBuilder): void + { + foreach ($this->keys as $key) { + $nodeBuilder->variableNode($key)->defaultNull()->end(); + } + } + + /** + * @param array $scopeSettings + */ + public function mapConfig(array &$scopeSettings, $currentScope, ContextualizerInterface $contextualizer): void + { + } +} diff --git a/tests/integration/Resources/ibexa.yaml b/tests/integration/Resources/ibexa.yaml new file mode 100644 index 0000000000..08f5404385 --- /dev/null +++ b/tests/integration/Resources/ibexa.yaml @@ -0,0 +1,4 @@ +ibexa: + system: + default: + languages: [ eng-GB, ger-DE ] diff --git a/tests/integration/TranslationTest.php b/tests/integration/TranslationTest.php new file mode 100644 index 0000000000..a34f6fc081 --- /dev/null +++ b/tests/integration/TranslationTest.php @@ -0,0 +1,19 @@ +boot(); + +$application = new Application($kernel); +$application->setAutoExit(false); + +if (getenv('DATABASE_URL') !== false && strpos(getenv('DATABASE_URL'), 'sqlite') !== 0) { + $application->run(new ArrayInput([ + 'command' => 'doctrine:database:drop', + '--if-exists' => '1', + '--force' => '1', + ])); +} + +$application->run(new ArrayInput([ + 'command' => 'doctrine:database:create', +])); + +/** @var \Psr\Container\ContainerInterface $testContainer */ +$testContainer = $kernel->getContainer()->get('test.service_container'); + +/** @var \Ibexa\Tests\Core\Repository\LegacySchemaImporter $schemaImporter */ +$schemaImporter = $testContainer->get(LegacySchemaImporter::class); +foreach ($kernel->getSchemaFiles() as $file) { + $schemaImporter->importSchema($file); +} + +/** @var \Ibexa\Contracts\Core\Test\Persistence\Fixture\FixtureImporter $fixtureImporter */ +$fixtureImporter = $testContainer->get(FixtureImporter::class); +foreach ($kernel->getFixtures() as $fixture) { + $fixtureImporter->import($fixture); +} + +$kernel->shutdown();