diff --git a/composer.json b/composer.json index f52af3a..1d55140 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "doctrine/orm": "^3.0", "doctrine/doctrine-bundle": "^2.13 || ^3.0", "symfony/translation": "^6.4 || ^7.0 || ^8.0", - "symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0" + "symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0", + "symfony/yaml": "^6.4 || ^7.0 || ^8.0" }, "require-dev": { "phpunit/phpunit": "^10.5", @@ -23,7 +24,10 @@ "phpstan/extension-installer": "^1.4", "phpstan/phpstan-symfony": "^2.0", "phpstan/phpstan-doctrine": "^2.0", - "friendsofphp/php-cs-fixer": "^3.95" + "friendsofphp/php-cs-fixer": "^3.95", + "symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0", + "symfony/validator": "^6.4 || ^7.0 || ^8.0", + "api-platform/core": "^3.4 || ^4.0" }, "prefer-stable": true, "autoload": { diff --git a/tests/Fixtures/TestKernel.php b/tests/Fixtures/TestKernel.php new file mode 100644 index 0000000..b57bdef --- /dev/null +++ b/tests/Fixtures/TestKernel.php @@ -0,0 +1,76 @@ +environment; + } + + public function getLogDir(): string + { + return sys_get_temp_dir().'/aptb-tests/log'; + } + + protected function build(ContainerBuilder $container): void + { + // Keep the bundle services visible to the test; private unused + // services are otherwise inlined or removed during compilation. + $container->addCompilerPass(new class implements CompilerPassInterface { + public function process(ContainerBuilder $container): void + { + foreach ($container->getDefinitions() as $id => $definition) { + if (str_starts_with($id, 'locastic_api_platform_translation.')) { + $definition->setPublic(true); + } + } + } + }); + } + + protected function configureContainer(ContainerConfigurator $container): void + { + $container->extension('framework', [ + 'secret' => 'test', + 'test' => true, + 'http_method_override' => false, + 'validation' => ['enabled' => true], + ]); + + $container->extension('doctrine', [ + 'dbal' => ['url' => 'sqlite:///:memory:'], + ]); + + $container->extension('api_platform', [ + 'title' => 'Test', + 'mapping' => ['paths' => []], + 'doctrine' => false, + ]); + } +} diff --git a/tests/Functional/BundleInitializationTest.php b/tests/Functional/BundleInitializationTest.php new file mode 100644 index 0000000..2eac886 --- /dev/null +++ b/tests/Functional/BundleInitializationTest.php @@ -0,0 +1,44 @@ +assertInstanceOf( + Translator::class, + $container->get('locastic_api_platform_translation.translation.translator') + ); + $this->assertInstanceOf( + AssignLocaleListener::class, + $container->get('locastic_api_platform_translation.listener.assign_locale') + ); + $this->assertInstanceOf( + GroupFilter::class, + $container->get('locastic_api_platform_translation.filter.translation_groups') + ); + } +} diff --git a/tests/Model/TranslatableTraitTest.php b/tests/Model/TranslatableTraitTest.php index ea22f2b..ee8b13e 100644 --- a/tests/Model/TranslatableTraitTest.php +++ b/tests/Model/TranslatableTraitTest.php @@ -89,6 +89,81 @@ public function testGetTranslationWithoutLocales(): void $dummyTranslatable->getTranslation(); } + /** + * @test getTranslation + */ + public function testGetTranslationCreatesAndAddsMissingTranslation(): void + { + $dummyTranslatable = $this->setTranslatable('es', 'en'); + $this->assertCount(0, $dummyTranslatable->getTranslations()); + + $translation = $dummyTranslatable->getTranslation('fr'); + + $this->assertSame('fr', $translation->getLocale()); + $this->assertSame($dummyTranslatable, $translation->getTranslatable()); + $this->assertCount(1, $dummyTranslatable->getTranslations()); + } + + /** + * @test hasTranslation + */ + public function testHasTranslation(): void + { + $dummyTranslatable = $this->setTranslatable('es', 'en'); + $english = $this->setTranslation('en', 'english', $dummyTranslatable); + + $notAdded = new DummyTranslation(); + $notAdded->setLocale('fr'); + + $this->assertTrue($dummyTranslatable->hasTranslation($english)); + $this->assertFalse($dummyTranslatable->hasTranslation($notAdded)); + } + + /** + * @test addTranslation + */ + public function testAddTranslationIgnoresTranslationWithoutLocale(): void + { + $dummyTranslatable = $this->setTranslatable('es', 'en'); + + $translation = new DummyTranslation(); + $dummyTranslatable->addTranslation($translation); + + $this->assertCount(0, $dummyTranslatable->getTranslations()); + $this->assertNull($translation->getTranslatable()); + } + + /** + * @test addTranslation + */ + public function testAddTranslationIgnoresDuplicateLocale(): void + { + $dummyTranslatable = $this->setTranslatable('es', 'en'); + $this->setTranslation('en', 'english', $dummyTranslatable); + + $duplicate = new DummyTranslation(); + $duplicate->setLocale('en'); + $duplicate->setTranslation('english again'); + $dummyTranslatable->addTranslation($duplicate); + + $this->assertCount(1, $dummyTranslatable->getTranslations()); + $this->assertSame('english', $dummyTranslatable->getTranslation('en')->getTranslation()); + } + + /** + * @test removeTranslationWithLocale + */ + public function testRemoveTranslationWithLocale(): void + { + $dummyTranslatable = $this->setTranslatable('es', 'en'); + $this->setTranslation('en', 'english', $dummyTranslatable); + $this->setTranslation('es', 'espanol', $dummyTranslatable); + + $dummyTranslatable->removeTranslationWithLocale('en'); + + $this->assertSame(['es'], array_values($dummyTranslatable->getTranslationLocales())); + } + /** * @param TranslatableInterface $translatable */ diff --git a/tests/Translation/TranslatorTest.php b/tests/Translation/TranslatorTest.php index dfbc732..7bbd897 100644 --- a/tests/Translation/TranslatorTest.php +++ b/tests/Translation/TranslatorTest.php @@ -220,5 +220,7 @@ public function provideLocalesWithAcceptLanguage(): \Generator yield [null, null, 'en']; yield [null, 'fr_FR', 'fr']; yield [null, 'es', 'en']; // Accept-Language locale not enabled + yield [null, 'it;q=0.4, fr;q=0.9', 'fr']; // Quality values respected + yield [null, 'fr;q=0.3, it;q=0.9', 'it']; } }