diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index d596595cf0..3e7b570f19 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -23292,60 +23292,6 @@ parameters: count: 1 path: tests/integration/Core/Repository/BaseTestCase.php - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertPropertiesCorrect\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertPropertiesCorrectUnsorted\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertPropertiesEqual\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertPropertiesEqual\(\) has parameter \$actualValue with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertPropertiesEqual\(\) has parameter \$expectedValue with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertPropertiesEqual\(\) has parameter \$propertyName with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertPropertiesEqual\(\) has parameter \$sortArray with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertStructPropertiesCorrect\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:assertStructPropertiesCorrect\(\) has parameter \$additionalProperties with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:createFolder\(\) has parameter \$names with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -23388,48 +23334,18 @@ parameters: count: 1 path: tests/integration/Core/Repository/BaseTestCase.php - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:sortItems\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:sortItems\(\) has parameter \$items with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:updateFolder\(\) has parameter \$names with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 path: tests/integration/Core/Repository/BaseTestCase.php - - - message: '#^PHPDoc tag @param references unknown parameter\: \$propertyNames$#' - identifier: parameter.notFound - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - message: '#^PHPDoc tag @var for variable \$searchHandler contains unknown class Ibexa\\Solr\\Handler\.$#' identifier: class.notFound count: 1 path: tests/integration/Core/Repository/BaseTestCase.php - - - message: '#^Parameter \#1 \$string1 of function strcmp expects string, bool\|float\|int\|string given\.$#' - identifier: argument.type - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - - - message: '#^Parameter \#2 \$string2 of function strcmp expects string, bool\|float\|int\|string given\.$#' - identifier: argument.type - count: 1 - path: tests/integration/Core/Repository/BaseTestCase.php - - message: '#^Property Ibexa\\Tests\\Integration\\Core\\Repository\\BaseTestCase\:\:\$repository \(Ibexa\\Contracts\\Core\\Repository\\Repository\) does not accept null\.$#' identifier: assign.propertyType @@ -31663,146 +31579,8 @@ parameters: path: tests/integration/Core/Repository/LanguageServiceMaximumSupportedLanguagesTest.php - - message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\Language'' and Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\Language will always evaluate to true\.$#' - identifier: staticMethod.alreadyNarrowedType - count: 3 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\LanguageCreateStruct'' and Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\LanguageCreateStruct will always evaluate to true\.$#' - identifier: staticMethod.alreadyNarrowedType - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:loadLanguagesReturnsAnEmptyArrayByDefault\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testCreateLanguageInTransactionWithCommit\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testCreateLanguageInTransactionWithRollback\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testCreateLanguageSetsExpectedProperties\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testCreateLanguageSetsIdPropertyOnReturnedLanguage\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testCreateLanguageThrowsInvalidArgumentException\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testDeleteLanguage\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testDeleteLanguageThrowsInvalidArgumentException\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testDisableLanguage\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testEnableLanguage\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testGetDefaultLanguageCode\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testLoadLanguage\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testLoadLanguageById\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testLoadLanguageByIdThrowsNotFoundException\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testLoadLanguageThrowsInvalidArgumentException\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testLoadLanguageThrowsNotFoundException\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testLoadLanguages\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testNewLanguageCreateStruct\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testUpdateLanguageName\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testUpdateLanguageNameInTransactionWithCommit\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testUpdateLanguageNameInTransactionWithRollback\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/integration/Core/Repository/LanguageServiceTest.php - - - - message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\LanguageServiceTest\:\:testUpdateLanguageNameThrowsInvalidArgumentException\(\) has no return type specified\.$#' - identifier: missingType.return + message: '#^Argument of an invalid type Ibexa\\Contracts\\Core\\Repository\\Values\\ValueObject supplied for foreach, only iterables are supported\.$#' + identifier: foreach.nonIterable count: 1 path: tests/integration/Core/Repository/LanguageServiceTest.php diff --git a/phpunit-integration-legacy.xml b/phpunit-integration-legacy.xml index ecc8215071..3e716dd6b2 100644 --- a/phpunit-integration-legacy.xml +++ b/phpunit-integration-legacy.xml @@ -12,7 +12,7 @@ - + diff --git a/src/contracts/Repository/Values/Content/LanguageCreateStruct.php b/src/contracts/Repository/Values/Content/LanguageCreateStruct.php index 84d291aa92..886f3066b7 100644 --- a/src/contracts/Repository/Values/Content/LanguageCreateStruct.php +++ b/src/contracts/Repository/Values/Content/LanguageCreateStruct.php @@ -9,6 +9,7 @@ namespace Ibexa\Contracts\Core\Repository\Values\Content; use Ibexa\Contracts\Core\Repository\Values\ValueObject; +use Symfony\Component\Validator\Constraints as Assert; /** * This class represents a value for creating a language. @@ -18,13 +19,16 @@ class LanguageCreateStruct extends ValueObject /** * The languageCode code. * - * Needs to be a unique. + * Needs to be unique. */ + #[Assert\NotBlank] + #[Assert\Regex('~^[a-zA-Z\_\-]+$~')] public ?string $languageCode = null; /** * Human-readable name of the language. */ + #[Assert\NotBlank] public ?string $name = null; /** diff --git a/src/contracts/Validation/StructValidator.php b/src/contracts/Validation/StructValidator.php index b0073afbf4..85bfe8b4fd 100644 --- a/src/contracts/Validation/StructValidator.php +++ b/src/contracts/Validation/StructValidator.php @@ -10,13 +10,11 @@ use Symfony\Component\Validator\Validator\ValidatorInterface; -final class StructValidator +final readonly class StructValidator { - private ValidatorInterface $validator; - - public function __construct(ValidatorInterface $validator) - { - $this->validator = $validator; + public function __construct( + private ValidatorInterface $validator + ) { } /** diff --git a/src/lib/Repository/LanguageService.php b/src/lib/Repository/LanguageService.php index efaa763a41..07de7c2098 100644 --- a/src/lib/Repository/LanguageService.php +++ b/src/lib/Repository/LanguageService.php @@ -17,6 +17,7 @@ use Ibexa\Contracts\Core\Repository\Repository as RepositoryInterface; use Ibexa\Contracts\Core\Repository\Values\Content\Language; use Ibexa\Contracts\Core\Repository\Values\Content\LanguageCreateStruct; +use Ibexa\Contracts\Core\Validation\StructValidator; use Ibexa\Core\Base\Exceptions\InvalidArgumentException; use Ibexa\Core\Base\Exceptions\InvalidArgumentValue; use Ibexa\Core\Base\Exceptions\UnauthorizedException; @@ -36,9 +37,6 @@ class LanguageService implements LanguageServiceInterface /** @var array */ protected $settings; - /** @var \Ibexa\Contracts\Core\Repository\PermissionResolver */ - private $permissionResolver; - /** * Setups service with reference to repository object that created it & corresponding handler. * @@ -49,12 +47,12 @@ class LanguageService implements LanguageServiceInterface public function __construct( RepositoryInterface $repository, Handler $languageHandler, - PermissionResolver $permissionResolver, - array $settings = [] + private readonly PermissionResolver $permissionResolver, + private readonly StructValidator $validator, + array $settings = [], ) { $this->repository = $repository; $this->languageHandler = $languageHandler; - $this->permissionResolver = $permissionResolver; // Union makes sure default settings are ignored if provided in argument $this->settings = $settings + [ 'languages' => ['eng-GB'], @@ -64,12 +62,9 @@ public function __construct( /** * Creates the a new Language in the content repository. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\LanguageCreateStruct $languageCreateStruct - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Language - * * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException If user does not have access to content translations * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if the languageCode already exists + * @throws \Ibexa\Contracts\Core\Validation\ValidationFailedException */ public function createLanguage(LanguageCreateStruct $languageCreateStruct): Language { @@ -92,10 +87,12 @@ public function createLanguage(LanguageCreateStruct $languageCreateStruct): Lang sprintf('language with the "%s" language code already exists', $languageCreateStruct->languageCode) ); } - } catch (APINotFoundException $e) { + } catch (APINotFoundException) { // Do nothing } + $this->validator->assertValidStruct('$languageCreateStruct', $languageCreateStruct, ['create']); + $createStruct = new CreateStruct( [ 'languageCode' => $languageCreateStruct->languageCode, @@ -104,6 +101,8 @@ public function createLanguage(LanguageCreateStruct $languageCreateStruct): Lang ] ); + $this->validator->assertValidStruct('$languageCreateStruct', $createStruct, ['create']); + $this->repository->beginTransaction(); try { $createdLanguage = $this->languageHandler->create($createStruct); diff --git a/src/lib/Repository/Repository.php b/src/lib/Repository/Repository.php index e5092d9d2d..2087445c13 100644 --- a/src/lib/Repository/Repository.php +++ b/src/lib/Repository/Repository.php @@ -40,6 +40,7 @@ use Ibexa\Contracts\Core\Repository\Validator\ContentValidator; use Ibexa\Contracts\Core\Search\Handler as SearchHandler; use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface; +use Ibexa\Contracts\Core\Validation\StructValidator; use Ibexa\Core\FieldType\FieldTypeRegistry; use Ibexa\Core\Repository\Collector\ContentCollector; use Ibexa\Core\Repository\Helper\RelationProcessor; @@ -399,7 +400,8 @@ public function getContentLanguageService(): LanguageServiceInterface $this, $this->persistenceHandler->contentLanguageHandler(), $this->getPermissionResolver(), - $this->serviceSettings['language'] + new StructValidator($this->validator), + $this->serviceSettings['language'], ); return $this->languageService; diff --git a/tests/integration/Core/CoreSolrTestKernel.php b/tests/integration/Core/CoreSolrTestKernel.php new file mode 100644 index 0000000000..f93402d020 --- /dev/null +++ b/tests/integration/Core/CoreSolrTestKernel.php @@ -0,0 +1,21 @@ +load(__DIR__ . '/Resources/services/services.php'); + } +} diff --git a/tests/integration/Core/CoreTestKernel.php b/tests/integration/Core/CoreTestKernel.php new file mode 100644 index 0000000000..6d4d361827 --- /dev/null +++ b/tests/integration/Core/CoreTestKernel.php @@ -0,0 +1,21 @@ +load(__DIR__ . '/Resources/services/services.php'); + } +} diff --git a/tests/integration/Core/Repository/AssertPropertiesTrait.php b/tests/integration/Core/Repository/AssertPropertiesTrait.php new file mode 100644 index 0000000000..3b534c054b --- /dev/null +++ b/tests/integration/Core/Repository/AssertPropertiesTrait.php @@ -0,0 +1,135 @@ + $propertyValue) { + if ($propertyValue instanceof ValueObject) { + self::assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName); + } elseif (is_array($propertyValue)) { + foreach ($propertyValue as $key => $value) { + if ($value instanceof ValueObject) { + self::assertStructPropertiesCorrect($value, $actualObject->$propertyName[$key]); + } else { + self::assertPropertiesEqual("$propertyName\[$key\]", $value, $actualObject->$propertyName[$key]); + } + } + } else { + self::assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName); + } + } + } + + /** + * Asserts that properties given in $expectedValues are correctly set in + * $actualObject. + * + * If the property type is array, it will be sorted before comparison. + * + * @TODO: introduced because of randomly failing tests, ref: https://issues.ibexa.co/browse/EZP-21734 + * + * @param mixed[] $expectedValues + * @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject + */ + protected function assertPropertiesCorrectUnsorted(array $expectedValues, ValueObject $actualObject): void + { + foreach ($expectedValues as $propertyName => $propertyValue) { + if ($propertyValue instanceof ValueObject) { + self::assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName); + } else { + self::assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName, true); + } + } + } + + /** + * Asserts all properties from $expectedValues are correctly set in + * $actualObject. Additional (virtual) properties can be asserted using + * $additionalProperties. + * + * @param array $additionalProperties + */ + protected static function assertStructPropertiesCorrect( + ValueObject $expectedValues, + ValueObject $actualObject, + array $additionalProperties = [], + ): void { + foreach ($expectedValues as $propertyName => $propertyValue) { + if ($propertyValue instanceof ValueObject) { + self::assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName); + } else { + self::assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName); + } + } + + foreach ($additionalProperties as $propertyName) { + self::assertPropertiesEqual($propertyName, $expectedValues->$propertyName, $actualObject->$propertyName); + } + } + + /** + * @param array $items An array of scalar values + * + * @see \Ibexa\Tests\Integration\Core\Repository\BaseTestCase::assertPropertiesCorrectUnsorted + */ + private static function sortItems(array &$items): void + { + $sorter = static function ($a, $b): int { + if (!is_scalar($a) || !is_scalar($b)) { + self::fail('Wrong usage: method ' . __METHOD__ . ' accepts only an array of scalar values'); + } + + return strcmp((string)$a, (string)$b); + }; + usort($items, $sorter); + } + + private static function assertPropertiesEqual( + string $propertyName, + mixed $expectedValue, + mixed $actualValue, + bool $sortArray = false + ): void { + if ($expectedValue instanceof ArrayObject) { + $expectedValue = $expectedValue->getArrayCopy(); + } elseif ($expectedValue instanceof DateTimeInterface) { + $expectedValue = $expectedValue->format(DateTime::RFC850); + } + if ($actualValue instanceof ArrayObject) { + $actualValue = $actualValue->getArrayCopy(); + } elseif ($actualValue instanceof DateTimeInterface) { + $actualValue = $actualValue->format(DateTime::RFC850); + } + + if ($sortArray && is_array($actualValue) && is_array($expectedValue)) { + self::sortItems($actualValue); + self::sortItems($expectedValue); + } + + self::assertEquals( + $expectedValue, + $actualValue, + sprintf('Object property "%s" incorrect.', $propertyName) + ); + } +} diff --git a/tests/integration/Core/Repository/BaseTestCase.php b/tests/integration/Core/Repository/BaseTestCase.php index 72dd8d9fda..6a96d112d0 100644 --- a/tests/integration/Core/Repository/BaseTestCase.php +++ b/tests/integration/Core/Repository/BaseTestCase.php @@ -7,8 +7,6 @@ namespace Ibexa\Tests\Integration\Core\Repository; -use ArrayObject; -use DateTime; use Doctrine\DBAL\Connection; use ErrorException; use Exception; @@ -25,7 +23,6 @@ use Ibexa\Contracts\Core\Repository\Values\User\User; use Ibexa\Contracts\Core\Repository\Values\User\UserGroup; use Ibexa\Contracts\Core\Repository\Values\User\UserReference; -use Ibexa\Contracts\Core\Repository\Values\ValueObject; use Ibexa\Contracts\Core\Test\Repository\SetupFactory; use Ibexa\Contracts\Core\Test\Repository\SetupFactory\Legacy as LegacySetupFactory; use Ibexa\Tests\Core\Repository\PHPUnitConstraint; @@ -37,6 +34,8 @@ */ abstract class BaseTestCase extends TestCase { + use AssertPropertiesTrait; + /** * Maximum integer number accepted by the different backends. */ @@ -184,120 +183,6 @@ protected function getSetupFactory(): SetupFactory return $this->setupFactory; } - /** - * Asserts that properties given in $expectedValues are correctly set in - * $actualObject. - * - * @param mixed[] $expectedValues - * @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject - */ - protected function assertPropertiesCorrect(array $expectedValues, ValueObject $actualObject) - { - foreach ($expectedValues as $propertyName => $propertyValue) { - if ($propertyValue instanceof ValueObject) { - $this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName); - } elseif (is_array($propertyValue)) { - foreach ($propertyValue as $key => $value) { - if ($value instanceof ValueObject) { - $this->assertStructPropertiesCorrect($value, $actualObject->$propertyName[$key]); - } else { - $this->assertPropertiesEqual("$propertyName\[$key\]", $value, $actualObject->$propertyName[$key]); - } - } - } else { - $this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName); - } - } - } - - /** - * Asserts that properties given in $expectedValues are correctly set in - * $actualObject. - * - * If the property type is array, it will be sorted before comparison. - * - * @TODO: introduced because of randomly failing tests, ref: https://issues.ibexa.co/browse/EZP-21734 - * - * @param mixed[] $expectedValues - * @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject - */ - protected function assertPropertiesCorrectUnsorted(array $expectedValues, ValueObject $actualObject) - { - foreach ($expectedValues as $propertyName => $propertyValue) { - if ($propertyValue instanceof ValueObject) { - $this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName); - } else { - $this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName, true); - } - } - } - - /** - * Asserts all properties from $expectedValues are correctly set in - * $actualObject. Additional (virtual) properties can be asserted using - * $additionalProperties. - * - * @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $expectedValues - * @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject - * @param array $propertyNames - */ - protected function assertStructPropertiesCorrect(ValueObject $expectedValues, ValueObject $actualObject, array $additionalProperties = []) - { - foreach ($expectedValues as $propertyName => $propertyValue) { - if ($propertyValue instanceof ValueObject) { - $this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName); - } else { - $this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName); - } - } - - foreach ($additionalProperties as $propertyName) { - $this->assertPropertiesEqual($propertyName, $expectedValues->$propertyName, $actualObject->$propertyName); - } - } - - /** - * @param array $items An array of scalar values - * - * @see \Ibexa\Tests\Integration\Core\Repository\BaseTestCase::assertPropertiesCorrectUnsorted - */ - private function sortItems(array &$items) - { - $sorter = function ($a, $b): int { - if (!is_scalar($a) || !is_scalar($b)) { - $this->fail('Wrong usage: method ' . __METHOD__ . ' accepts only an array of scalar values'); - } - - return strcmp($a, $b); - }; - usort($items, $sorter); - } - - private function assertPropertiesEqual($propertyName, $expectedValue, $actualValue, $sortArray = false) - { - if ($expectedValue instanceof ArrayObject) { - $expectedValue = $expectedValue->getArrayCopy(); - } elseif ($expectedValue instanceof DateTime) { - $expectedValue = $expectedValue->format(DateTime::RFC850); - } - if ($actualValue instanceof ArrayObject) { - $actualValue = $actualValue->getArrayCopy(); - } elseif ($actualValue instanceof DateTime) { - $actualValue = $actualValue->format(DateTime::RFC850); - } - - if ($sortArray && is_array($actualValue) && is_array($expectedValue)) { - $this->sortItems($actualValue); - $this->sortItems($expectedValue); - } - - self::assertEquals( - $expectedValue, - $actualValue, - sprintf('Object property "%s" incorrect.', $propertyName) - ); - } - /** * Create a user in editor user group. */ diff --git a/tests/integration/Core/Repository/LanguageServiceTest.php b/tests/integration/Core/Repository/LanguageServiceTest.php index 3226bce22e..c93ce9c6b3 100644 --- a/tests/integration/Core/Repository/LanguageServiceTest.php +++ b/tests/integration/Core/Repository/LanguageServiceTest.php @@ -10,8 +10,10 @@ use Exception; use Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException; use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException; +use Ibexa\Contracts\Core\Repository\LanguageService; +use Ibexa\Contracts\Core\Repository\Repository; use Ibexa\Contracts\Core\Repository\Values\Content\Language; -use Ibexa\Contracts\Core\Repository\Values\Content\LanguageCreateStruct; +use Ibexa\Contracts\Core\Test\IbexaKernelTestCase; /** * Test case for operations in the LanguageService using in memory storage. @@ -21,27 +23,35 @@ * @group integration * @group language */ -class LanguageServiceTest extends BaseTestCase +final class LanguageServiceTest extends IbexaKernelTestCase { - /** - * Test for the newLanguageCreateStruct() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::newLanguageCreateStruct - */ - public function testNewLanguageCreateStruct() + use AssertPropertiesTrait; + + private Repository $repository; + + private LanguageService $languageService; + + protected function setUp(): void { - $repository = $this->getRepository(); + self::bootKernel(); - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); + self::loadSchema(); + self::loadFixtures(); - $languageCreate = $languageService->newLanguageCreateStruct(); - /* END: Use Case */ + self::setAdministratorUser(); - self::assertInstanceOf( - LanguageCreateStruct::class, - $languageCreate - ); + $this->repository = self::getServiceByClassName(Repository::class); + $this->languageService = $this->repository->getContentLanguageService(); + } + + private function generateId(string $type, int $rawId): int + { + return self::getServiceByClassName(IdManager::class)->generateId($type, $rawId); + } + + public function testNewLanguageCreateStruct(): void + { + $languageCreate = $this->languageService->newLanguageCreateStruct(); $this->assertPropertiesCorrect( [ @@ -54,61 +64,34 @@ public function testNewLanguageCreateStruct() } /** - * Test for the createLanguage() method. - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Language - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::createLanguage - * * @depends testNewLanguageCreateStruct */ - public function testCreateLanguage() + public function testCreateLanguage(): Language { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - $languageCreate = $languageService->newLanguageCreateStruct(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = true; $languageCreate->name = 'English (New Zealand)'; $languageCreate->languageCode = 'eng-NZ'; - $language = $languageService->createLanguage($languageCreate); - /* END: Use Case */ + $language = $this->languageService->createLanguage($languageCreate); - self::assertInstanceOf( - Language::class, - $language - ); + $this->expectNotToPerformAssertions(); return $language; } /** - * Test for the createLanguage() method. - * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\Language $language - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::createLanguage - * * @depends testCreateLanguage */ - public function testCreateLanguageSetsIdPropertyOnReturnedLanguage($language) + public function testCreateLanguageSetsIdPropertyOnReturnedLanguage(Language $language): void { self::assertNotNull($language->id); } /** - * Test for the createLanguage() method. - * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\Language $language - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::createLanguage - * * @depends testCreateLanguage */ - public function testCreateLanguageSetsExpectedProperties($language) + public function testCreateLanguageSetsExpectedProperties(Language $language): void { self::assertEquals( [ @@ -125,64 +108,67 @@ public function testCreateLanguageSetsExpectedProperties($language) } /** - * Test for the createLanguage() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::createLanguage - * * @depends testCreateLanguage */ - public function testCreateLanguageThrowsInvalidArgumentException() + public function testCreateLanguageThrowsInvalidArgumentException(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Argument \'languageCreateStruct\' is invalid: language with the "nor-NO" language code already exists'); - - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - $languageCreate = $languageService->newLanguageCreateStruct(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = true; $languageCreate->name = 'Norwegian'; $languageCreate->languageCode = 'nor-NO'; - $languageService->createLanguage($languageCreate); + $this->languageService->createLanguage($languageCreate); // This call should fail with an InvalidArgumentException, because // the language code "nor-NO" already exists. - $languageService->createLanguage($languageCreate); - /* END: Use Case */ + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Argument \'languageCreateStruct\' is invalid: language with the "nor-NO" language code already exists'); + $this->languageService->createLanguage($languageCreate); + } + + public function testCreateLanguageWithEmptyLanguageCode(): void + { + $languageCreate = $this->languageService->newLanguageCreateStruct(); + $languageCreate->enabled = true; + $languageCreate->name = 'English'; + $languageCreate->languageCode = ''; + + $this->expectException(InvalidArgumentException::class); + $this->languageService->createLanguage($languageCreate); } /** - * Test for the loadLanguageById() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguageById - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguageListById - * - * @depends testCreateLanguage + * @testWith ["."] + * ["ąę"] + * ["%^"] + * ["eng 123"] */ - public function testLoadLanguageById() + public function testCreateLanguageWithInvalidLanguageCode(string $languageCode): void { - $repository = $this->getRepository(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); + $languageCreate->enabled = true; + $languageCreate->name = 'English'; + $languageCreate->languageCode = $languageCode; - $languageService = $repository->getContentLanguageService(); + $this->expectException(InvalidArgumentException::class); + $this->languageService->createLanguage($languageCreate); + } - $languageCreate = $languageService->newLanguageCreateStruct(); + /** + * @depends testCreateLanguage + */ + public function testLoadLanguageById(): void + { + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = false; $languageCreate->name = 'English'; $languageCreate->languageCode = 'eng-NZ'; - $languageId = $languageService->createLanguage($languageCreate)->id; + $languageId = $this->languageService->createLanguage($languageCreate)->id; - $language = $languageService->loadLanguageById($languageId); + $this->languageService->loadLanguageById($languageId); - self::assertInstanceOf( - Language::class, - $language - ); - - $languages = iterator_to_array($languageService->loadLanguageListById([$languageId])); + $languages = iterator_to_array($this->languageService->loadLanguageListById([$languageId])); self::assertIsIterable($languages); self::assertCount(1, $languages); @@ -190,69 +176,43 @@ public function testLoadLanguageById() } /** - * Test for the loadLanguageById() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguageById - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguageListById - * * @depends testLoadLanguageById */ - public function testLoadLanguageByIdThrowsNotFoundException() + public function testLoadLanguageByIdThrowsNotFoundException(): void { - $repository = $this->getRepository(); - $nonExistentLanguageId = $this->generateId('language', 2342); - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - $languages = $languageService->loadLanguageListById([$nonExistentLanguageId]); + $languages = $this->languageService->loadLanguageListById([$nonExistentLanguageId]); self::assertIsIterable($languages); self::assertCount(0, $languages); $this->expectException(NotFoundException::class); - $languageService->loadLanguageById($nonExistentLanguageId); - /* END: Use Case */ + $this->languageService->loadLanguageById($nonExistentLanguageId); } /** - * Test for the updateLanguageName() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::updateLanguageName - * * @depends testLoadLanguageById */ - public function testUpdateLanguageName() + public function testUpdateLanguageName(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - $languageCreate = $languageService->newLanguageCreateStruct(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = false; $languageCreate->name = 'English'; $languageCreate->languageCode = 'eng-NZ'; - $languageId = $languageService->createLanguage($languageCreate)->id; + $languageId = $this->languageService->createLanguage($languageCreate)->id; - $language = $languageService->loadLanguageById($languageId); + $language = $this->languageService->loadLanguageById($languageId); - $updatedLanguage = $languageService->updateLanguageName( + $this->languageService->updateLanguageName( $language, 'New language name.' ); - /* END: Use Case */ - - // Verify that the service returns an updated language instance. - self::assertInstanceOf( - Language::class, - $updatedLanguage - ); // Verify that the service also persists the changes - $updatedLanguage = $languageService->loadLanguageById($languageId); + $updatedLanguage = $this->languageService->loadLanguageById($languageId); $this->assertPropertiesCorrect( [ 'id' => $language->id, @@ -264,108 +224,68 @@ public function testUpdateLanguageName() ); } - /** - * Test service method for updating language name throwing InvalidArgumentException. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::updateLanguageName - */ - public function testUpdateLanguageNameThrowsInvalidArgumentException() + public function testUpdateLanguageNameThrowsInvalidArgumentException(): void { + $language = $this->languageService->loadLanguage('eng-GB'); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Argument \'newName\' is invalid: \'\' is incorrect value'); - - $repository = $this->getRepository(); - $languageService = $repository->getContentLanguageService(); - - $language = $languageService->loadLanguage('eng-GB'); - $languageService->updateLanguageName($language, ''); + $this->languageService->updateLanguageName($language, ''); } /** - * Test for the enableLanguage() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::enableLanguage - * * @depends testLoadLanguageById */ - public function testEnableLanguage() + public function testEnableLanguage(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - $languageCreate = $languageService->newLanguageCreateStruct(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = false; $languageCreate->name = 'English'; $languageCreate->languageCode = 'eng-NZ'; - $language = $languageService->createLanguage($languageCreate); + $language = $this->languageService->createLanguage($languageCreate); // Now lets enable the newly created language - $languageService->enableLanguage($language); + $this->languageService->enableLanguage($language); - $enabledLanguage = $languageService->loadLanguageById($language->id); - /* END: Use Case */ + $enabledLanguage = $this->languageService->loadLanguageById($language->id); self::assertTrue($enabledLanguage->enabled); } /** - * Test for the disableLanguage() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::disableLanguage - * * @depends testLoadLanguageById */ - public function testDisableLanguage() + public function testDisableLanguage(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - $languageCreate = $languageService->newLanguageCreateStruct(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = true; $languageCreate->name = 'English'; $languageCreate->languageCode = 'eng-NZ'; - $language = $languageService->createLanguage($languageCreate); + $language = $this->languageService->createLanguage($languageCreate); // Now lets disable the newly created language - $languageService->disableLanguage($language); + $this->languageService->disableLanguage($language); - $enabledLanguage = $languageService->loadLanguageById($language->id); - /* END: Use Case */ + $enabledLanguage = $this->languageService->loadLanguageById($language->id); self::assertFalse($enabledLanguage->enabled); } /** - * Test for the loadLanguage() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguage - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguageListByCode - * * @depends testCreateLanguage */ - public function testLoadLanguage() + public function testLoadLanguage(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - $languageCreate = $languageService->newLanguageCreateStruct(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = true; $languageCreate->name = 'English'; $languageCreate->languageCode = 'eng-NZ'; - $languageId = $languageService->createLanguage($languageCreate)->id; + $languageId = $this->languageService->createLanguage($languageCreate)->id; - // Now load the newly created language by it's language code - $language = $languageService->loadLanguage('eng-NZ'); - /* END: Use Case */ + $language = $this->languageService->loadLanguage('eng-NZ'); $this->assertPropertiesCorrect( [ @@ -377,7 +297,7 @@ public function testLoadLanguage() $language ); - $languages = iterator_to_array($languageService->loadLanguageListByCode(['eng-NZ'])); + $languages = iterator_to_array($this->languageService->loadLanguageListByCode(['eng-NZ'])); self::assertIsIterable($languages); self::assertCount(1, $languages); @@ -394,178 +314,120 @@ public function testLoadLanguage() } /** - * Test for the loadLanguage() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguage - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguageListByCode - * * @depends testLoadLanguage */ - public function testLoadLanguageThrowsNotFoundException() + public function testLoadLanguageThrowsNotFoundException(): void { - $repository = $this->getRepository(); - - $languageService = $repository->getContentLanguageService(); - - $languages = $languageService->loadLanguageListByCode(['fre-FR']); + $languages = $this->languageService->loadLanguageListByCode(['fre-FR']); self::assertIsIterable($languages); self::assertCount(0, $languages); $this->expectException(NotFoundException::class); - $languageService->loadLanguage('fre-FR'); + $this->languageService->loadLanguage('fre-FR'); } - /** - * Test service method for loading language throwing InvalidArgumentException. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguage - */ - public function testLoadLanguageThrowsInvalidArgumentException() + public function testLoadLanguageThrowsInvalidArgumentException(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Argument \'languageCode\' is invalid: language code has an invalid value'); - $repository = $this->getRepository(); - - $repository->getContentLanguageService()->loadLanguage(''); + $this->languageService->loadLanguage(''); } /** - * Test for the loadLanguages() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguages - * * @depends testCreateLanguage * @depends testLoadLanguage */ - public function testLoadLanguages() + public function testLoadLanguages(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - // Create some languages - $languageCreateEnglish = $languageService->newLanguageCreateStruct(); + $languageCreateEnglish = $this->languageService->newLanguageCreateStruct(); $languageCreateEnglish->enabled = false; $languageCreateEnglish->name = 'English'; $languageCreateEnglish->languageCode = 'eng-NZ'; - $languageCreateFrench = $languageService->newLanguageCreateStruct(); + $languageCreateFrench = $this->languageService->newLanguageCreateStruct(); $languageCreateFrench->enabled = false; $languageCreateFrench->name = 'French'; $languageCreateFrench->languageCode = 'fre-FR'; - $languageService->createLanguage($languageCreateEnglish); - $languageService->createLanguage($languageCreateFrench); + $this->languageService->createLanguage($languageCreateEnglish); + $this->languageService->createLanguage($languageCreateFrench); - $languages = $languageService->loadLanguages(); + $languages = $this->languageService->loadLanguages(); self::assertIsArray($languages); foreach ($languages as $language) { self::assertInstanceOf(Language::class, $language); - $singleLanguage = $languageService->loadLanguage($language->languageCode); + $singleLanguage = $this->languageService->loadLanguage($language->languageCode); $this->assertStructPropertiesCorrect( $singleLanguage, $language, ['id', 'languageCode', 'name', 'enabled'] ); } - /* END: Use Case */ // eng-US, eng-GB, ger-DE + 2 newly created self::assertCount(5, $languages); } /** - * Test for the loadLanguages() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::loadLanguages - * * @depends testCreateLanguage */ - public function loadLanguagesReturnsAnEmptyArrayByDefault() + public function loadLanguagesReturnsAnEmptyArrayByDefault(): void { - $repository = $this->getRepository(); - - $languageService = $repository->getContentLanguageService(); - - self::assertSame([], $languageService->loadLanguages()); + self::assertSame([], $this->languageService->loadLanguages()); } /** - * Test for the deleteLanguage() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::deleteLanguage - * * @depends testLoadLanguages */ - public function testDeleteLanguage() + public function testDeleteLanguage(): void { - $repository = $this->getRepository(); - $languageService = $repository->getContentLanguageService(); - - $beforeCount = count($languageService->loadLanguages()); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); + $beforeCount = count($this->languageService->loadLanguages()); - $languageCreateEnglish = $languageService->newLanguageCreateStruct(); + $languageCreateEnglish = $this->languageService->newLanguageCreateStruct(); $languageCreateEnglish->enabled = false; $languageCreateEnglish->name = 'English'; $languageCreateEnglish->languageCode = 'eng-NZ'; - $language = $languageService->createLanguage($languageCreateEnglish); + $language = $this->languageService->createLanguage($languageCreateEnglish); // Delete the newly created language - $languageService->deleteLanguage($language); - /* END: Use Case */ + $this->languageService->deleteLanguage($language); // +1 -1 - self::assertEquals($beforeCount, count($languageService->loadLanguages())); + self::assertEquals($beforeCount, count($this->languageService->loadLanguages())); $this->expectException(NotFoundException::class); $this->expectExceptionMessage('Could not find \'Language\' with identifier \'eng-NZ\''); // ensure just created & deleted language doesn't exist - $languageService->loadLanguage($languageCreateEnglish->languageCode); - self::fail('Language is still returned after being deleted'); + $this->languageService->loadLanguage($languageCreateEnglish->languageCode); } /** - * Test for the deleteLanguage() method. - * * NOTE: This test has a dependency against several methods in the content * service, but because there is no topological sort for test dependencies * we cannot declare them here. * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::deleteLanguage - * * @depends testDeleteLanguage */ - public function testDeleteLanguageThrowsInvalidArgumentException() + public function testDeleteLanguageThrowsInvalidArgumentException(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Argument \'language\' is invalid: Cannot delete language: some content still references the language'); - - $repository = $this->getRepository(); - $editorsGroupId = $this->generateId('group', 13); - /* BEGIN: Use Case */ // $editorsGroupId is the ID of the "Editors" user group in an Ibexa // Publish demo installation - $languageService = $repository->getContentLanguageService(); - - $languageCreateEnglish = $languageService->newLanguageCreateStruct(); + $languageCreateEnglish = $this->languageService->newLanguageCreateStruct(); $languageCreateEnglish->enabled = true; $languageCreateEnglish->name = 'English'; $languageCreateEnglish->languageCode = 'eng-NZ'; - $language = $languageService->createLanguage($languageCreateEnglish); + $language = $this->languageService->createLanguage($languageCreateEnglish); - $contentService = $repository->getContentService(); + $contentService = $this->repository->getContentService(); // Get metadata update struct and set new language as main language. $metadataUpdate = $contentService->newContentMetadataUpdateStruct(); @@ -579,188 +441,130 @@ public function testDeleteLanguageThrowsInvalidArgumentException() // This call will fail with an "InvalidArgumentException", because the // new language is used by a content object. - $languageService->deleteLanguage($language); - /* END: Use Case */ + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Argument \'language\' is invalid: Cannot delete language: some content still references the language'); + $this->languageService->deleteLanguage($language); } - /** - * Test for the getDefaultLanguageCode() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::getDefaultLanguageCode - */ - public function testGetDefaultLanguageCode() + public function testGetDefaultLanguageCode(): void { - $repository = $this->getRepository(); - $languageService = $repository->getContentLanguageService(); - - self::assertRegExp( - '(^[a-z]{3}\-[A-Z]{2}$)', - $languageService->getDefaultLanguageCode() + self::assertMatchesRegularExpression( + '(^[a-z]{3}-[A-Z]{2}$)', + $this->languageService->getDefaultLanguageCode() ); } /** - * Test for the createLanguage() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::createLanguage - * * @depends testCreateLanguage */ - public function testCreateLanguageInTransactionWithRollback() + public function testCreateLanguageInTransactionWithRollback(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - // Start a new transaction - $repository->beginTransaction(); + $this->repository->beginTransaction(); try { // Get create struct and set properties - $languageCreate = $languageService->newLanguageCreateStruct(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = true; $languageCreate->name = 'English (New Zealand)'; $languageCreate->languageCode = 'eng-NZ'; // Create new language - $languageService->createLanguage($languageCreate); + $this->languageService->createLanguage($languageCreate); } catch (Exception $e) { // Cleanup hanging transaction on error - $repository->rollback(); + $this->repository->rollback(); throw $e; } // Rollback all changes - $repository->rollback(); + $this->repository->rollback(); try { // This call will fail with a "NotFoundException" - $languageService->loadLanguage('eng-NZ'); + $this->languageService->loadLanguage('eng-NZ'); } catch (NotFoundException $e) { // Expected execution path } - /* END: Use Case */ self::assertTrue(isset($e), 'Can still load language after rollback'); } /** - * Test for the createLanguage() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::createLanguage - * * @depends testCreateLanguage */ - public function testCreateLanguageInTransactionWithCommit() + public function testCreateLanguageInTransactionWithCommit(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - // Start a new transaction - $repository->beginTransaction(); + $this->repository->beginTransaction(); try { - // Get create struct and set properties - $languageCreate = $languageService->newLanguageCreateStruct(); + $languageCreate = $this->languageService->newLanguageCreateStruct(); $languageCreate->enabled = true; $languageCreate->name = 'English (New Zealand)'; $languageCreate->languageCode = 'eng-NZ'; // Create new language - $languageService->createLanguage($languageCreate); + $this->languageService->createLanguage($languageCreate); // Commit all changes - $repository->commit(); + $this->repository->commit(); } catch (Exception $e) { // Cleanup hanging transaction on error - $repository->rollback(); + $this->repository->rollback(); throw $e; } - // Load new language - $language = $languageService->loadLanguage('eng-NZ'); - /* END: Use Case */ + $language = $this->languageService->loadLanguage('eng-NZ'); self::assertEquals('eng-NZ', $language->languageCode); } /** - * Test for the updateLanguageName() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::updateLanguageName - * * @depends testUpdateLanguageName */ - public function testUpdateLanguageNameInTransactionWithRollback() + public function testUpdateLanguageNameInTransactionWithRollback(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - // Start a new transaction - $repository->beginTransaction(); + $this->repository->beginTransaction(); try { - // Load an existing language - $language = $languageService->loadLanguage('eng-US'); + $language = $this->languageService->loadLanguage('eng-US'); - // Update the language name - $languageService->updateLanguageName($language, 'My English'); + $this->languageService->updateLanguageName($language, 'My English'); } catch (Exception $e) { // Cleanup hanging transaction on error - $repository->rollback(); + $this->repository->rollback(); throw $e; } // Rollback all changes - $repository->rollback(); + $this->repository->rollback(); // Load updated version, name will still be "English (American)" - $updatedLanguage = $languageService->loadLanguage('eng-US'); - /* END: Use Case */ + $updatedLanguage = $this->languageService->loadLanguage('eng-US'); self::assertEquals('English (American)', $updatedLanguage->name); } /** - * Test for the updateLanguageName() method. - * - * @covers \Ibexa\Contracts\Core\Repository\LanguageService::updateLanguageName - * * @depends testUpdateLanguageName */ - public function testUpdateLanguageNameInTransactionWithCommit() + public function testUpdateLanguageNameInTransactionWithCommit(): void { - $repository = $this->getRepository(); - - /* BEGIN: Use Case */ - $languageService = $repository->getContentLanguageService(); - - // Start a new transaction - $repository->beginTransaction(); + $this->repository->beginTransaction(); try { - // Load an existing language - $language = $languageService->loadLanguage('eng-US'); + $language = $this->languageService->loadLanguage('eng-US'); - // Update the language name - $languageService->updateLanguageName($language, 'My English'); + $this->languageService->updateLanguageName($language, 'My English'); - // Commit all changes - $repository->commit(); + $this->repository->commit(); } catch (Exception $e) { - // Cleanup hanging transaction on error - $repository->rollback(); + $this->repository->rollback(); throw $e; } // Load updated version, name will be "My English" - $updatedLanguage = $languageService->loadLanguage('eng-US'); - /* END: Use Case */ + $updatedLanguage = $this->languageService->loadLanguage('eng-US'); self::assertEquals('My English', $updatedLanguage->name); } diff --git a/tests/integration/Core/Resources/services/services.php b/tests/integration/Core/Resources/services/services.php new file mode 100644 index 0000000000..dc3888379b --- /dev/null +++ b/tests/integration/Core/Resources/services/services.php @@ -0,0 +1,24 @@ +services(); + $services->defaults() + ->autowire() + ->autoconfigure() + ->private(); + + $services->set('test.' . IdManager::class, Php::class) + ->public() + ; +};