diff --git a/api/.php-cs-fixer.dist.php b/api/.php-cs-fixer.dist.php index 1052b203f..aca1fcd12 100644 --- a/api/.php-cs-fixer.dist.php +++ b/api/.php-cs-fixer.dist.php @@ -13,19 +13,20 @@ '@Symfony' => true, '@Symfony:risky' => true, 'declare_strict_types' => true, + 'php_unit_data_provider_name' => false, 'php_unit_data_provider_return_type' => true, 'php_unit_data_provider_static' => true, 'php_unit_dedicate_assert' => true, 'php_unit_dedicate_assert_internal_type' => true, 'php_unit_expectation' => true, 'php_unit_fqcn_annotation' => true, - 'php_unit_internal_class' => true, + 'php_unit_internal_class' => false, 'php_unit_method_casing' => true, 'php_unit_mock_short_will_return' => true, 'php_unit_namespaced' => true, 'php_unit_no_expectation_annotation' => true, 'php_unit_set_up_tear_down_visibility' => true, - 'php_unit_strict' => true, + 'php_unit_strict' => false, 'php_unit_test_annotation' => ['style' => 'annotation'], 'php_unit_test_case_static_method_calls' => false, 'php_unit_test_class_requires_covers' => false, diff --git a/api/config/bootstrap.php b/api/config/bootstrap.php index e41d0e73f..30095b122 100644 --- a/api/config/bootstrap.php +++ b/api/config/bootstrap.php @@ -1,8 +1,10 @@ =1.2) -if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) { +if (is_array($env = @include dirname(__DIR__) . '/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) { (new Dotenv())->usePutenv(false)->populate($env); } else { // load all the .env files - (new Dotenv())->usePutenv(false)->loadEnv(dirname(__DIR__).'/.env'); + (new Dotenv())->usePutenv(false)->loadEnv(dirname(__DIR__) . '/.env'); } $_SERVER += $_ENV; $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; -$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; +$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], \FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; diff --git a/api/config/bundles.php b/api/config/bundles.php index 48b608768..24080a7f5 100644 --- a/api/config/bundles.php +++ b/api/config/bundles.php @@ -1,5 +1,7 @@ ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], diff --git a/api/config/preload.php b/api/config/preload.php index 5ebcdb215..69de61575 100644 --- a/api/config/preload.php +++ b/api/config/preload.php @@ -1,5 +1,7 @@ progressStart($limit); $data = []; while ($offset < $limit) { - /* @see https://openlibrary.org/dev/docs/restful_api */ - $uri = 'https://openlibrary.org/query?type=/type/edition&languages=/languages/eng&subjects=Science%20Fiction&authors=&covers=&title=&description=&publish_date&offset='.$offset; + /** @see https://openlibrary.org/dev/docs/restful_api */ + $uri = 'https://openlibrary.org/query?type=/type/edition&languages=/languages/eng&subjects=Science%20Fiction&authors=&covers=&title=&description=&publish_date&offset=' . $offset; $books = $this->getData($uri); foreach ($books as $book) { $this->logger->info('Importing book.', [ - 'book' => 'https://openlibrary.org'.$book['key'].'.json', + 'book' => 'https://openlibrary.org' . $book['key'] . '.json', ]); $datum = [ - 'book' => 'https://openlibrary.org'.$book['key'].'.json', + 'book' => 'https://openlibrary.org' . $book['key'] . '.json', 'title' => $book['title'], ]; if (isset($book['authors'][0]['key'])) { - $author = $this->getData('https://openlibrary.org'.$book['authors'][0]['key']); + $author = $this->getData('https://openlibrary.org' . $book['authors'][0]['key']); if (isset($author['name'])) { $datum['author'] = $author['name']; } diff --git a/api/src/DataFixtures/Factory/BookFactory.php b/api/src/DataFixtures/Factory/BookFactory.php index 9d795e359..e65dbf055 100644 --- a/api/src/DataFixtures/Factory/BookFactory.php +++ b/api/src/DataFixtures/Factory/BookFactory.php @@ -57,7 +57,7 @@ public function __construct() { parent::__construct(); - $this->data = json_decode(file_get_contents(__DIR__.'/../books.json'), true); + $this->data = json_decode(file_get_contents(__DIR__ . '/../books.json'), true); shuffle($this->data); } @@ -77,36 +77,36 @@ protected function getDefaults(): array protected function initialize(): self { return $this - ->afterInstantiate(function (Book $book): void { - if ($book->book && $book->title && $book->author) { - return; - } + ->afterInstantiate(function (Book $book): void { + if ($book->book && $book->title && $book->author) { + return; + } - if (!$book->book) { - $book->book = 'https://openlibrary.org/books/OL'.self::faker()->unique()->randomNumber(7, true).'M.json'; - $book->title ??= self::faker()->text(); - $book->author ??= self::faker()->name(); + if (!$book->book) { + $book->book = 'https://openlibrary.org/books/OL' . self::faker()->unique()->randomNumber(7, true) . 'M.json'; + $book->title ??= self::faker()->text(); + $book->author ??= self::faker()->name(); - return; - } + return; + } - // An Open Library book URI has been specified: try to find it in the array of books - $data = array_filter($this->data, static function (array $datum) use ($book) { - return $book->book === $datum['book']; - }); - if ($data) { - $datum = current($data); - $book->title ??= $datum['title']; - // A book can have no author - $book->author ??= $datum['author'] ?? self::faker()->name(); + // An Open Library book URI has been specified: try to find it in the array of books + $data = array_filter($this->data, static function (array $datum) use ($book) { + return $book->book === $datum['book']; + }); + if ($data) { + $datum = current($data); + $book->title ??= $datum['title']; + // A book can have no author + $book->author ??= $datum['author'] ?? self::faker()->name(); - return; - } + return; + } - // No Open Library book has been found in the array of books - $book->title ??= self::faker()->text(); - $book->author ??= self::faker()->name(); - }) + // No Open Library book has been found in the array of books + $book->title ??= self::faker()->text(); + $book->author ??= self::faker()->name(); + }) ; } diff --git a/api/src/DataFixtures/Factory/BookmarkFactory.php b/api/src/DataFixtures/Factory/BookmarkFactory.php index ccd3e7b21..efc712a84 100644 --- a/api/src/DataFixtures/Factory/BookmarkFactory.php +++ b/api/src/DataFixtures/Factory/BookmarkFactory.php @@ -63,8 +63,8 @@ public function __construct() protected function getDefaults(): array { return [ - 'user' => lazy(fn () => UserFactory::new()), - 'book' => lazy(fn () => BookFactory::new()), + 'user' => lazy(static fn () => UserFactory::new()), + 'book' => lazy(static fn () => BookFactory::new()), 'bookmarkedAt' => \DateTimeImmutable::createFromMutable(self::faker()->dateTime()), ]; } @@ -74,9 +74,8 @@ protected function getDefaults(): array */ protected function initialize(): self { - return $this - // ->afterInstantiate(function(Bookmark $bookmark): void {}) - ; + return $this; + // ->afterInstantiate(function(Bookmark $bookmark): void {}) } protected static function getClass(): string diff --git a/api/src/DataFixtures/Factory/ReviewFactory.php b/api/src/DataFixtures/Factory/ReviewFactory.php index 0eba44f07..d22a35749 100644 --- a/api/src/DataFixtures/Factory/ReviewFactory.php +++ b/api/src/DataFixtures/Factory/ReviewFactory.php @@ -63,8 +63,8 @@ public function __construct() protected function getDefaults(): array { return [ - 'user' => lazy(fn () => UserFactory::new()), - 'book' => lazy(fn () => BookFactory::new()), + 'user' => lazy(static fn () => UserFactory::new()), + 'book' => lazy(static fn () => BookFactory::new()), 'publishedAt' => \DateTimeImmutable::createFromMutable(self::faker()->dateTime('-1 week')), 'body' => self::faker()->text(), 'rating' => self::faker()->numberBetween(0, 5), @@ -76,9 +76,8 @@ protected function getDefaults(): array */ protected function initialize(): self { - return $this - // ->afterInstantiate(function(Review $review): void {}) - ; + return $this; + // ->afterInstantiate(function(Review $review): void {}) } protected static function getClass(): string diff --git a/api/src/DataFixtures/Factory/UserFactory.php b/api/src/DataFixtures/Factory/UserFactory.php index b0d0836a7..479bdb995 100644 --- a/api/src/DataFixtures/Factory/UserFactory.php +++ b/api/src/DataFixtures/Factory/UserFactory.php @@ -56,9 +56,9 @@ public function __construct() parent::__construct(); } - public static function createOneAdmin(array $attributes = []): User|Proxy + public static function createOneAdmin(array $attributes = []): Proxy|User { - return static::createOne(['roles' => ['ROLE_ADMIN']] + $attributes); + return self::createOne(['roles' => ['ROLE_ADMIN']] + $attributes); } /** @@ -80,9 +80,8 @@ protected function getDefaults(): array */ protected function initialize(): self { - return $this - // ->afterInstantiate(function(User $user): void {}) - ; + return $this; + // ->afterInstantiate(function(User $user): void {}) } protected static function getClass(): string diff --git a/api/src/DataFixtures/Story/DefaultStory.php b/api/src/DataFixtures/Story/DefaultStory.php index 77462435c..1fd38a140 100644 --- a/api/src/DataFixtures/Story/DefaultStory.php +++ b/api/src/DataFixtures/Story/DefaultStory.php @@ -14,9 +14,7 @@ final class DefaultStory extends Story { - public function __construct(private readonly DecoderInterface $decoder) - { - } + public function __construct(private readonly DecoderInterface $decoder) {} public function build(): void { @@ -36,7 +34,7 @@ public function build(): void // Import books $books = []; // store books in array to pick 30 random ones later without the default one - $data = $this->decoder->decode(file_get_contents(__DIR__.'/../books.json'), 'json'); + $data = $this->decoder->decode(file_get_contents(__DIR__ . '/../books.json'), 'json'); foreach ($data as $datum) { $book = BookFactory::createOne($datum + [ 'condition' => BookCondition::cases()[array_rand(BookCondition::cases())], diff --git a/api/src/Doctrine/Orm/Extension/BookmarkQueryCollectionExtension.php b/api/src/Doctrine/Orm/Extension/BookmarkQueryCollectionExtension.php index a333cf4fe..bf7c31a43 100644 --- a/api/src/Doctrine/Orm/Extension/BookmarkQueryCollectionExtension.php +++ b/api/src/Doctrine/Orm/Extension/BookmarkQueryCollectionExtension.php @@ -16,9 +16,7 @@ */ final readonly class BookmarkQueryCollectionExtension implements QueryCollectionExtensionInterface { - public function __construct(private Security $security) - { - } + public function __construct(private Security $security) {} public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { @@ -32,6 +30,7 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator $queryBuilder ->andWhere(sprintf('%s.user = :user', $queryBuilder->getRootAliases()[0])) - ->setParameter('user', $user); + ->setParameter('user', $user) + ; } } diff --git a/api/src/Doctrine/Orm/Filter/NameFilter.php b/api/src/Doctrine/Orm/Filter/NameFilter.php index 65b9cd1eb..21d18220e 100644 --- a/api/src/Doctrine/Orm/Filter/NameFilter.php +++ b/api/src/Doctrine/Orm/Filter/NameFilter.php @@ -45,11 +45,11 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB $alias = $queryBuilder->getRootAliases()[0]; $expressions = []; foreach ($values as $key => $value) { - $parameterName = $queryNameGenerator->generateParameterName("name$key"); - $queryBuilder->setParameter($parameterName, "%$value%"); + $parameterName = $queryNameGenerator->generateParameterName("name{$key}"); + $queryBuilder->setParameter($parameterName, "%{$value}%"); $expressions[] = $queryBuilder->expr()->orX( - $queryBuilder->expr()->like(sprintf('%s.firstName', $alias), ":$parameterName"), - $queryBuilder->expr()->like(sprintf('%s.lastName', $alias), ":$parameterName") + $queryBuilder->expr()->like(sprintf('%s.firstName', $alias), ":{$parameterName}"), + $queryBuilder->expr()->like(sprintf('%s.lastName', $alias), ":{$parameterName}") ); } $queryBuilder->andWhere($queryBuilder->expr()->andX(...$expressions)); diff --git a/api/src/Entity/Book.php b/api/src/Entity/Book.php index 0c8433957..8aa6c1a50 100644 --- a/api/src/Entity/Book.php +++ b/api/src/Entity/Book.php @@ -71,7 +71,7 @@ AbstractNormalizer::GROUPS => ['Book:write'], ], // todo waiting for https://github.com/api-platform/core/pull/5844 -// collectDenormalizationErrors: true, + // collectDenormalizationErrors: true, security: 'is_granted("ROLE_ADMIN")' )] #[ApiResource( @@ -119,7 +119,7 @@ class Book * @see https://schema.org/name */ #[ApiFilter(OrderFilter::class)] - #[ApiFilter(SearchFilter::class, strategy: 'i'.SearchFilterInterface::STRATEGY_PARTIAL)] + #[ApiFilter(SearchFilter::class, strategy: 'i' . SearchFilterInterface::STRATEGY_PARTIAL)] #[ApiProperty( types: ['https://schema.org/name'], example: 'Hyperion' @@ -131,7 +131,7 @@ class Book /** * @see https://schema.org/author */ - #[ApiFilter(SearchFilter::class, strategy: 'i'.SearchFilterInterface::STRATEGY_PARTIAL)] + #[ApiFilter(SearchFilter::class, strategy: 'i' . SearchFilterInterface::STRATEGY_PARTIAL)] #[ApiProperty( types: ['https://schema.org/author'], example: 'Dan Simmons' diff --git a/api/src/Entity/Bookmark.php b/api/src/Entity/Bookmark.php index 7938239b1..84bd32453 100644 --- a/api/src/Entity/Bookmark.php +++ b/api/src/Entity/Bookmark.php @@ -53,7 +53,7 @@ AbstractNormalizer::GROUPS => ['Bookmark:write'], ], // todo waiting for https://github.com/api-platform/core/pull/5844 -// collectDenormalizationErrors: true, + // collectDenormalizationErrors: true, mercure: true, security: 'is_granted("ROLE_USER")' )] diff --git a/api/src/Entity/Review.php b/api/src/Entity/Review.php index 1a71c25a3..469e325a2 100644 --- a/api/src/Entity/Review.php +++ b/api/src/Entity/Review.php @@ -76,7 +76,7 @@ AbstractNormalizer::GROUPS => ['Review:write', 'Review:write:admin'], ], // todo waiting for https://github.com/api-platform/core/pull/5844 -// collectDenormalizationErrors: true, + // collectDenormalizationErrors: true, security: 'is_granted("ROLE_ADMIN")' )] #[ApiResource( @@ -139,7 +139,7 @@ AbstractNormalizer::GROUPS => ['Review:write'], ], // todo waiting for https://github.com/api-platform/core/pull/5844 -// collectDenormalizationErrors: true + // collectDenormalizationErrors: true )] #[ORM\Entity(repositoryClass: ReviewRepository::class)] #[ORM\UniqueConstraint(fields: ['user', 'book'])] diff --git a/api/src/Entity/User.php b/api/src/Entity/User.php index f530f3657..fa6a018d0 100644 --- a/api/src/Entity/User.php +++ b/api/src/Entity/User.php @@ -101,9 +101,7 @@ public function getId(): ?Uuid return $this->id; } - public function eraseCredentials(): void - { - } + public function eraseCredentials(): void {} /** * @return array diff --git a/api/src/Enum/BookCondition.php b/api/src/Enum/BookCondition.php index 06fd7ca94..c27ad3fc8 100644 --- a/api/src/Enum/BookCondition.php +++ b/api/src/Enum/BookCondition.php @@ -17,8 +17,8 @@ shortName: 'BookCondition', types: ['https://schema.org/OfferItemCondition'], operations: [ - new GetCollection(provider: BookCondition::class.'::getCases'), - new Get(provider: BookCondition::class.'::getCase'), + new GetCollection(provider: BookCondition::class . '::getCases'), + new Get(provider: BookCondition::class . '::getCase'), ], )] enum BookCondition: string diff --git a/api/src/Kernel.php b/api/src/Kernel.php index 779cd1f2b..ad0fb4800 100644 --- a/api/src/Kernel.php +++ b/api/src/Kernel.php @@ -1,5 +1,7 @@ createQueryBuilder('r') ->select('AVG(r.rating)') ->where('r.book = :book')->setParameter('book', $book) - ->getQuery()->getSingleScalarResult(); + ->getQuery()->getSingleScalarResult() + ; return $rating ? (int) $rating : null; } diff --git a/api/src/Security/Core/UserProvider.php b/api/src/Security/Core/UserProvider.php index 55b27e36e..99f7e0779 100644 --- a/api/src/Security/Core/UserProvider.php +++ b/api/src/Security/Core/UserProvider.php @@ -17,9 +17,7 @@ */ final readonly class UserProvider implements AttributesBasedUserProviderInterface { - public function __construct(private ManagerRegistry $registry, private UserRepository $repository) - { - } + public function __construct(private ManagerRegistry $registry, private UserRepository $repository) {} public function refreshUser(UserInterface $user): UserInterface { diff --git a/api/src/Serializer/BookNormalizer.php b/api/src/Serializer/BookNormalizer.php index 9fa2745c5..ee7d3c27a 100644 --- a/api/src/Serializer/BookNormalizer.php +++ b/api/src/Serializer/BookNormalizer.php @@ -24,8 +24,7 @@ public function __construct( private RouterInterface $router, #[Autowire(service: ReviewRepository::class)] private ObjectRepository $repository - ) { - } + ) {} /** * @param Book $object @@ -38,9 +37,7 @@ public function normalize(mixed $object, string $format = null, array $context = $object->rating = $this->repository->getAverageRating($object); /** @var array $data */ - $data = $this->normalizer->normalize($object, $format, [self::class => true] + $context); - - return $data; + return $this->normalizer->normalize($object, $format, [self::class => true] + $context); } public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool diff --git a/api/src/Serializer/IriTransformerNormalizer.php b/api/src/Serializer/IriTransformerNormalizer.php index 9db2bc1ab..9cd4c1777 100644 --- a/api/src/Serializer/IriTransformerNormalizer.php +++ b/api/src/Serializer/IriTransformerNormalizer.php @@ -21,8 +21,7 @@ final class IriTransformerNormalizer implements NormalizerInterface, NormalizerA public function __construct( private readonly IriConverterInterface $iriConverter, private readonly OperationMetadataFactoryInterface $operationMetadataFactory - ) { - } + ) {} public function normalize(mixed $object, string $format = null, array $context = []): array { @@ -30,12 +29,12 @@ public function normalize(mixed $object, string $format = null, array $context = $data = $this->normalizer->normalize($object, $format, $context + [self::class => true]); $value = $context[self::CONTEXT_KEY]; - if (!is_array($value)) { + if (!\is_array($value)) { $value = [$value]; } foreach ($value as $property => $uriTemplate) { - if (!isset($data[$property]) || !(is_string($data[$property]) || isset($data[$property]['@id']))) { + if (!isset($data[$property]) || !(\is_string($data[$property]) || isset($data[$property]['@id']))) { continue; } @@ -45,7 +44,7 @@ public function normalize(mixed $object, string $format = null, array $context = $this->operationMetadataFactory->create($uriTemplate) ); - if (is_string($data[$property])) { + if (\is_string($data[$property])) { $data[$property] = $iri; } elseif (isset($data[$property]['@id'])) { $data[$property]['@id'] = $iri; @@ -57,7 +56,7 @@ public function normalize(mixed $object, string $format = null, array $context = public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool { - return is_object($data) + return \is_object($data) && !is_iterable($data) && isset($context[self::CONTEXT_KEY]) && ItemNormalizer::FORMAT === $format diff --git a/api/src/State/Processor/BookPersistProcessor.php b/api/src/State/Processor/BookPersistProcessor.php index dd6729f27..d19d7b0c5 100644 --- a/api/src/State/Processor/BookPersistProcessor.php +++ b/api/src/State/Processor/BookPersistProcessor.php @@ -29,8 +29,7 @@ public function __construct( private ProcessorInterface $mercureProcessor, private HttpClientInterface $client, private DecoderInterface $decoder - ) { - } + ) {} /** * @param Book $data @@ -42,7 +41,7 @@ public function process(mixed $data, Operation $operation, array $uriVariables = $data->author = null; if (isset($book['authors'][0]['key'])) { - $author = $this->getData('https://openlibrary.org'.$book['authors'][0]['key'].'.json'); + $author = $this->getData('https://openlibrary.org' . $book['authors'][0]['key'] . '.json'); if (isset($author['name'])) { $data->author = $author['name']; } diff --git a/api/src/State/Processor/BookRemoveProcessor.php b/api/src/State/Processor/BookRemoveProcessor.php index c345d5d92..3db394b3a 100644 --- a/api/src/State/Processor/BookRemoveProcessor.php +++ b/api/src/State/Processor/BookRemoveProcessor.php @@ -19,7 +19,7 @@ final readonly class BookRemoveProcessor implements ProcessorInterface { /** - * @param RemoveProcessor $removeProcessor + * @param RemoveProcessor $removeProcessor * @param MercureProcessor $mercureProcessor */ public function __construct( @@ -29,8 +29,7 @@ public function __construct( private ProcessorInterface $mercureProcessor, private ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, private IriConverterInterface $iriConverter - ) { - } + ) {} /** * @param Book $data diff --git a/api/src/State/Processor/BookmarkPersistProcessor.php b/api/src/State/Processor/BookmarkPersistProcessor.php index 5588a596b..0889f04c4 100644 --- a/api/src/State/Processor/BookmarkPersistProcessor.php +++ b/api/src/State/Processor/BookmarkPersistProcessor.php @@ -25,8 +25,7 @@ public function __construct( private ProcessorInterface $persistProcessor, private Security $security, private ClockInterface $clock - ) { - } + ) {} /** * @param Bookmark $data diff --git a/api/src/State/Processor/MercureProcessor.php b/api/src/State/Processor/MercureProcessor.php index e157ca3f1..b7e25a6bc 100644 --- a/api/src/State/Processor/MercureProcessor.php +++ b/api/src/State/Processor/MercureProcessor.php @@ -31,8 +31,7 @@ public function __construct( private ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, #[Autowire('%api_platform.formats%')] private array $formats - ) { - } + ) {} /** * @param array{item_uri_template?: string, topics?: array, mercure_data?: string} $context diff --git a/api/src/State/Processor/ReviewPersistProcessor.php b/api/src/State/Processor/ReviewPersistProcessor.php index cb19bad2a..47ad47bf4 100644 --- a/api/src/State/Processor/ReviewPersistProcessor.php +++ b/api/src/State/Processor/ReviewPersistProcessor.php @@ -29,8 +29,7 @@ public function __construct( private ProcessorInterface $mercureProcessor, private Security $security, private ClockInterface $clock - ) { - } + ) {} /** * @param Review $data diff --git a/api/src/State/Processor/ReviewRemoveProcessor.php b/api/src/State/Processor/ReviewRemoveProcessor.php index 955e9347d..39e0cb602 100644 --- a/api/src/State/Processor/ReviewRemoveProcessor.php +++ b/api/src/State/Processor/ReviewRemoveProcessor.php @@ -19,7 +19,7 @@ final readonly class ReviewRemoveProcessor implements ProcessorInterface { /** - * @param RemoveProcessor $removeProcessor + * @param RemoveProcessor $removeProcessor * @param MercureProcessor $mercureProcessor */ public function __construct( @@ -29,8 +29,7 @@ public function __construct( private ProcessorInterface $mercureProcessor, private ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, private IriConverterInterface $iriConverter - ) { - } + ) {} /** * @param Review $data diff --git a/api/src/Validator/UniqueUserBookValidator.php b/api/src/Validator/UniqueUserBookValidator.php index 8429d8b4e..b8616652c 100644 --- a/api/src/Validator/UniqueUserBookValidator.php +++ b/api/src/Validator/UniqueUserBookValidator.php @@ -23,8 +23,7 @@ public function __construct( private readonly Security $security, private readonly ManagerRegistry $registry, private readonly PropertyAccessorInterface $propertyAccessor - ) { - } + ) {} /** * @param Bookmark|Review|null $value diff --git a/api/tests/Api/Admin/BookTest.php b/api/tests/Api/Admin/BookTest.php index c42c02e66..5b443ea0d 100644 --- a/api/tests/Api/Admin/BookTest.php +++ b/api/tests/Api/Admin/BookTest.php @@ -37,8 +37,10 @@ protected function setup(): void /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotGetACollectionOfBooks(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotGetACollectionOfBooks(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $options = []; if ($userFactory) { @@ -62,8 +64,10 @@ public function testAsNonAdminUserICannotGetACollectionOfBooks(int $expectedCode /** * @dataProvider getUrls + * + * @test */ - public function testAsAdminUserICanGetACollectionOfBooks(FactoryCollection $factory, string $url, int $hydraTotalItems, int $itemsPerPage = null): void + public function asAdminUserICanGetACollectionOfBooks(FactoryCollection $factory, string $url, int $hydraTotalItems, int $itemsPerPage = null): void { // Cannot use Factory as data provider because BookFactory has a service dependency $factory->create(); @@ -80,10 +84,10 @@ public function testAsAdminUserICanGetACollectionOfBooks(FactoryCollection $fact 'hydra:totalItems' => $hydraTotalItems, ]); self::assertCount(min($itemsPerPage ?? $hydraTotalItems, 30), $response->toArray()['hydra:member']); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Book/collection.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Book/collection.json')); } - public function getUrls(): iterable + public static function getUrls(): iterable { yield 'all books' => [ BookFactory::new()->many(35), @@ -97,7 +101,7 @@ public function getUrls(): iterable 10, ]; yield 'books filtered by title' => [ - BookFactory::new()->sequence(function () { + BookFactory::new()->sequence(static function () { yield ['title' => 'Hyperion']; foreach (range(1, 10) as $i) { yield []; @@ -107,7 +111,7 @@ public function getUrls(): iterable 1, ]; yield 'books filtered by author' => [ - BookFactory::new()->sequence(function () { + BookFactory::new()->sequence(static function () { yield ['author' => 'Dan Simmons']; foreach (range(1, 10) as $i) { yield []; @@ -117,18 +121,21 @@ public function getUrls(): iterable 1, ]; yield 'books filtered by condition' => [ - BookFactory::new()->sequence(function () { + BookFactory::new()->sequence(static function () { foreach (range(1, 100) as $i) { // 33% of books are damaged yield ['condition' => $i % 3 ? BookCondition::NewCondition : BookCondition::DamagedCondition]; } }), - '/admin/books?condition='.BookCondition::DamagedCondition->value, + '/admin/books?condition=' . BookCondition::DamagedCondition->value, 33, ]; } - public function testAsAdminUserICanGetACollectionOfBooksOrderedByTitle(): void + /** + * @test + */ + public function asAdminUserICanGetACollectionOfBooksOrderedByTitle(): void { BookFactory::createOne(['title' => 'Hyperion']); BookFactory::createOne(['title' => 'The Wandering Earth']); @@ -145,13 +152,15 @@ public function testAsAdminUserICanGetACollectionOfBooksOrderedByTitle(): void self::assertEquals('Ball Lightning', $response->toArray()['hydra:member'][0]['title']); self::assertEquals('Hyperion', $response->toArray()['hydra:member'][1]['title']); self::assertEquals('The Wandering Earth', $response->toArray()['hydra:member'][2]['title']); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Book/collection.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Book/collection.json')); } /** * @dataProvider getAllUsers + * + * @test */ - public function testAsAnyUserICannotGetAnInvalidBook(?UserFactory $userFactory): void + public function asAnyUserICannotGetAnInvalidBook(?UserFactory $userFactory): void { BookFactory::createOne(); @@ -168,7 +177,7 @@ public function testAsAnyUserICannotGetAnInvalidBook(?UserFactory $userFactory): self::assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND); } - public function getAllUsers(): iterable + public static function getAllUsers(): iterable { yield [null]; yield [UserFactory::new()]; @@ -177,8 +186,10 @@ public function getAllUsers(): iterable /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotGetABook(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotGetABook(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $book = BookFactory::createOne(); @@ -190,7 +201,7 @@ public function testAsNonAdminUserICannotGetABook(int $expectedCode, string $hyd $options['auth_bearer'] = $token; } - $this->client->request('GET', '/admin/books/'.$book->getId(), $options); + $this->client->request('GET', '/admin/books/' . $book->getId(), $options); self::assertResponseStatusCodeSame($expectedCode); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -204,8 +215,10 @@ public function testAsNonAdminUserICannotGetABook(int $expectedCode, string $hyd /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsAdminUserICanGetABook(): void + public function asAdminUserICanGetABook(): void { $book = BookFactory::createOne(); @@ -213,24 +226,26 @@ public function testAsAdminUserICanGetABook(): void 'email' => UserFactory::createOneAdmin()->email, ]); - $this->client->request('GET', '/admin/books/'.$book->getId(), ['auth_bearer' => $token]); + $this->client->request('GET', '/admin/books/' . $book->getId(), ['auth_bearer' => $token]); self::assertResponseIsSuccessful(); self::assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); self::assertJsonContains([ - '@id' => '/admin/books/'.$book->getId(), + '@id' => '/admin/books/' . $book->getId(), 'book' => $book->book, 'condition' => $book->condition->value, 'title' => $book->title, 'author' => $book->author, ]); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Book/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Book/item.json')); } /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotCreateABook(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotCreateABook(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $options = []; if ($userFactory) { @@ -263,8 +278,10 @@ public function testAsNonAdminUserICannotCreateABook(int $expectedCode, string $ /** * @dataProvider getInvalidDataOnCreate + * + * @test */ - public function testAsAdminUserICannotCreateABookWithInvalidData(array $data, int $statusCode, array $expected): void + public function asAdminUserICannotCreateABookWithInvalidData(array $data, int $statusCode, array $expected): void { $token = $this->generateToken([ 'email' => UserFactory::createOneAdmin()->email, @@ -308,7 +325,7 @@ public function getInvalidDataOnCreate(): iterable yield from $this->getInvalidData(); } - public function getInvalidData(): iterable + public static function getInvalidData(): iterable { yield 'empty data' => [ [ @@ -317,25 +334,25 @@ public function getInvalidData(): iterable ], Response::HTTP_BAD_REQUEST, // todo waiting for https://github.com/api-platform/core/pull/5844 -// Response::HTTP_UNPROCESSABLE_ENTITY, + // Response::HTTP_UNPROCESSABLE_ENTITY, [ '@type' => 'hydra:Error', 'hydra:title' => 'An error occurred', - 'hydra:description' => 'The data must belong to a backed enumeration of type '.BookCondition::class, + 'hydra:description' => 'The data must belong to a backed enumeration of type ' . BookCondition::class, // todo waiting for https://github.com/api-platform/core/pull/5844[ -// '@type' => 'ConstraintViolationList', -// 'hydra:title' => 'An error occurred', -// 'hydra:description' => 'book: This value should not be blank.\ncondition: This value should be of type '.BookCondition::class.'.', -// 'violations' => [ -// [ -// 'propertyPath' => 'book', -// 'hint' => 'This value should not be blank.', -// ], -// [ -// 'propertyPath' => 'condition', -// 'hint' => 'The data must belong to a backed enumeration of type '.BookCondition::class, -// ], -// ], + // '@type' => 'ConstraintViolationList', + // 'hydra:title' => 'An error occurred', + // 'hydra:description' => 'book: This value should not be blank.\ncondition: This value should be of type '.BookCondition::class.'.', + // 'violations' => [ + // [ + // 'propertyPath' => 'book', + // 'hint' => 'This value should not be blank.', + // ], + // [ + // 'propertyPath' => 'condition', + // 'hint' => 'The data must belong to a backed enumeration of type '.BookCondition::class, + // ], + // ], ], ]; yield 'invalid condition' => [ @@ -345,21 +362,21 @@ public function getInvalidData(): iterable ], Response::HTTP_BAD_REQUEST, // todo waiting for https://github.com/api-platform/core/pull/5844 -// Response::HTTP_UNPROCESSABLE_ENTITY, + // Response::HTTP_UNPROCESSABLE_ENTITY, [ '@type' => 'hydra:Error', 'hydra:title' => 'An error occurred', - 'hydra:description' => 'The data must belong to a backed enumeration of type '.BookCondition::class, + 'hydra:description' => 'The data must belong to a backed enumeration of type ' . BookCondition::class, // todo waiting for https://github.com/api-platform/core/pull/5844 -// '@type' => 'ConstraintViolationList', -// 'hydra:title' => 'An error occurred', -// 'hydra:description' => 'condition: This value should be of type '.BookCondition::class.'.', -// 'violations' => [ -// [ -// 'propertyPath' => 'condition', -// 'hint' => 'The data must belong to a backed enumeration of type '.BookCondition::class, -// ], -// ], + // '@type' => 'ConstraintViolationList', + // 'hydra:title' => 'An error occurred', + // 'hydra:description' => 'condition: This value should be of type '.BookCondition::class.'.', + // 'violations' => [ + // [ + // 'propertyPath' => 'condition', + // 'hint' => 'The data must belong to a backed enumeration of type '.BookCondition::class, + // ], + // ], ], ]; yield 'invalid book' => [ @@ -384,8 +401,10 @@ public function getInvalidData(): iterable /** * @group apiCall * @group mercure + * + * @test */ - public function testAsAdminUserICanCreateABook(): void + public function asAdminUserICanCreateABook(): void { $token = $this->generateToken([ 'email' => UserFactory::createOneAdmin()->email, @@ -411,14 +430,14 @@ public function testAsAdminUserICanCreateABook(): void 'title' => 'Foundation', 'author' => 'Isaac Asimov', ]); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Book/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Book/item.json')); $id = preg_replace('/^.*\/(.+)$/', '$1', $response->toArray()['@id']); /** @var Book $book */ $book = self::getContainer()->get(BookRepository::class)->find($id); self::assertCount(2, self::getMercureMessages()); self::assertEquals( new Update( - topics: ['http://localhost/admin/books/'.$book->getId()], + topics: ['http://localhost/admin/books/' . $book->getId()], data: self::serialize( $book, 'jsonld', @@ -429,7 +448,7 @@ public function testAsAdminUserICanCreateABook(): void ); self::assertEquals( new Update( - topics: ['http://localhost/books/'.$book->getId()], + topics: ['http://localhost/books/' . $book->getId()], data: self::serialize( $book, 'jsonld', @@ -442,8 +461,10 @@ public function testAsAdminUserICanCreateABook(): void /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotUpdateBook(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotUpdateBook(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $book = BookFactory::createOne(); @@ -455,7 +476,7 @@ public function testAsNonAdminUserICannotUpdateBook(int $expectedCode, string $h $options['auth_bearer'] = $token; } - $this->client->request('PUT', '/admin/books/'.$book->getId(), $options + [ + $this->client->request('PUT', '/admin/books/' . $book->getId(), $options + [ 'json' => [ 'book' => 'https://openlibrary.org/books/OL28346544M.json', 'condition' => BookCondition::NewCondition->value, @@ -476,7 +497,10 @@ public function testAsNonAdminUserICannotUpdateBook(int $expectedCode, string $h ]); } - public function testAsAdminUserICannotUpdateAnInvalidBook(): void + /** + * @test + */ + public function asAdminUserICannotUpdateAnInvalidBook(): void { BookFactory::createOne(); @@ -500,8 +524,10 @@ public function testAsAdminUserICannotUpdateAnInvalidBook(): void /** * @dataProvider getInvalidData + * + * @test */ - public function testAsAdminUserICannotUpdateABookWithInvalidData(array $data, int $statusCode, array $expected): void + public function asAdminUserICannotUpdateABookWithInvalidData(array $data, int $statusCode, array $expected): void { $book = BookFactory::createOne(); @@ -509,7 +535,7 @@ public function testAsAdminUserICannotUpdateABookWithInvalidData(array $data, in 'email' => UserFactory::createOneAdmin()->email, ]); - $this->client->request('PUT', '/admin/books/'.$book->getId(), [ + $this->client->request('PUT', '/admin/books/' . $book->getId(), [ 'auth_bearer' => $token, 'json' => $data, 'headers' => [ @@ -527,8 +553,10 @@ public function testAsAdminUserICannotUpdateABookWithInvalidData(array $data, in /** * @group apiCall * @group mercure + * + * @test */ - public function testAsAdminUserICanUpdateABook(): void + public function asAdminUserICanUpdateABook(): void { $book = BookFactory::createOne([ 'book' => 'https://openlibrary.org/books/OL28346544M.json', @@ -539,10 +567,10 @@ public function testAsAdminUserICanUpdateABook(): void 'email' => UserFactory::createOneAdmin()->email, ]); - $this->client->request('PUT', '/admin/books/'.$book->getId(), [ + $this->client->request('PUT', '/admin/books/' . $book->getId(), [ 'auth_bearer' => $token, 'json' => [ - '@id' => '/books/'.$book->getId(), + '@id' => '/books/' . $book->getId(), // Must set all data because of standard PUT 'book' => 'https://openlibrary.org/books/OL28346544M.json', 'condition' => BookCondition::DamagedCondition->value, @@ -561,11 +589,11 @@ public function testAsAdminUserICanUpdateABook(): void 'title' => 'Foundation', 'author' => 'Isaac Asimov', ]); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Book/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Book/item.json')); self::assertCount(2, self::getMercureMessages()); self::assertEquals( new Update( - topics: ['http://localhost/admin/books/'.$book->getId()], + topics: ['http://localhost/admin/books/' . $book->getId()], data: self::serialize( $book->object(), 'jsonld', @@ -576,7 +604,7 @@ public function testAsAdminUserICanUpdateABook(): void ); self::assertEquals( new Update( - topics: ['http://localhost/books/'.$book->getId()], + topics: ['http://localhost/books/' . $book->getId()], data: self::serialize( $book->object(), 'jsonld', @@ -589,8 +617,10 @@ public function testAsAdminUserICanUpdateABook(): void /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotDeleteABook(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotDeleteABook(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $book = BookFactory::createOne(); @@ -602,7 +632,7 @@ public function testAsNonAdminUserICannotDeleteABook(int $expectedCode, string $ $options['auth_bearer'] = $token; } - $this->client->request('DELETE', '/admin/books/'.$book->getId(), $options); + $this->client->request('DELETE', '/admin/books/' . $book->getId(), $options); self::assertResponseStatusCodeSame($expectedCode); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -614,7 +644,10 @@ public function testAsNonAdminUserICannotDeleteABook(int $expectedCode, string $ ]); } - public function testAsAdminUserICannotDeleteAnInvalidBook(): void + /** + * @test + */ + public function asAdminUserICannotDeleteAnInvalidBook(): void { BookFactory::createOne(); @@ -629,8 +662,10 @@ public function testAsAdminUserICannotDeleteAnInvalidBook(): void /** * @group mercure + * + * @test */ - public function testAsAdminUserICanDeleteABook(): void + public function asAdminUserICanDeleteABook(): void { $book = BookFactory::createOne(['title' => 'Hyperion']); self::getMercureHub()->reset(); @@ -640,7 +675,7 @@ public function testAsAdminUserICanDeleteABook(): void 'email' => UserFactory::createOneAdmin()->email, ]); - $response = $this->client->request('DELETE', '/admin/books/'.$id, ['auth_bearer' => $token]); + $response = $this->client->request('DELETE', '/admin/books/' . $id, ['auth_bearer' => $token]); self::assertResponseStatusCodeSame(Response::HTTP_NO_CONTENT); self::assertEmpty($response->getContent()); @@ -649,15 +684,15 @@ public function testAsAdminUserICanDeleteABook(): void // todo how to ensure it's a delete update self::assertEquals( new Update( - topics: ['http://localhost/admin/books/'.$id], - data: json_encode(['@id' => 'http://localhost/admin/books/'.$id]) + topics: ['http://localhost/admin/books/' . $id], + data: json_encode(['@id' => 'http://localhost/admin/books/' . $id]) ), self::getMercureMessage() ); self::assertEquals( new Update( - topics: ['http://localhost/books/'.$id], - data: json_encode(['@id' => 'http://localhost/books/'.$id]) + topics: ['http://localhost/books/' . $id], + data: json_encode(['@id' => 'http://localhost/books/' . $id]) ), self::getMercureMessage(1) ); diff --git a/api/tests/Api/Admin/ReviewTest.php b/api/tests/Api/Admin/ReviewTest.php index 7fa13fa47..93109f8f2 100644 --- a/api/tests/Api/Admin/ReviewTest.php +++ b/api/tests/Api/Admin/ReviewTest.php @@ -38,8 +38,10 @@ protected function setup(): void /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotGetACollectionOfReviews(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotGetACollectionOfReviews(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $options = []; if ($userFactory) { @@ -63,8 +65,10 @@ public function testAsNonAdminUserICannotGetACollectionOfReviews(int $expectedCo /** * @dataProvider getAdminUrls + * + * @test */ - public function testAsAdminUserICanGetACollectionOfReviews(FactoryCollection $factory, string|callable $url, int $hydraTotalItems, int $itemsPerPage = null): void + public function asAdminUserICanGetACollectionOfReviews(FactoryCollection $factory, callable|string $url, int $hydraTotalItems, int $itemsPerPage = null): void { $factory->create(); @@ -72,7 +76,7 @@ public function testAsAdminUserICanGetACollectionOfReviews(FactoryCollection $fa 'email' => UserFactory::createOneAdmin()->email, ]); - if (is_callable($url)) { + if (\is_callable($url)) { $url = $url(); } @@ -84,10 +88,10 @@ public function testAsAdminUserICanGetACollectionOfReviews(FactoryCollection $fa 'hydra:totalItems' => $hydraTotalItems, ]); self::assertCount(min($itemsPerPage ?? $hydraTotalItems, 30), $response->toArray()['hydra:member']); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Review/collection.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Review/collection.json')); } - public function getAdminUrls(): iterable + public static function getAdminUrls(): iterable { yield 'all reviews' => [ ReviewFactory::new()->many(35), @@ -101,7 +105,7 @@ public function getAdminUrls(): iterable 10, ]; yield 'reviews filtered by rating' => [ - ReviewFactory::new()->sequence(function () { + ReviewFactory::new()->sequence(static function () { foreach (range(1, 100) as $i) { // 33% of reviews are rated 5 yield ['rating' => $i % 3 ? 3 : 5]; @@ -111,7 +115,7 @@ public function getAdminUrls(): iterable 33, ]; yield 'reviews filtered by user' => [ - ReviewFactory::new()->sequence(function () { + ReviewFactory::new()->sequence(static function () { $user = UserFactory::createOne(['email' => 'user@example.com']); yield ['user' => $user]; foreach (range(1, 10) as $i) { @@ -122,12 +126,12 @@ static function (): string { /** @var User[] $users */ $users = UserFactory::findBy(['email' => 'user@example.com']); - return '/admin/reviews?user=/admin/users/'.$users[0]->getId(); + return '/admin/reviews?user=/admin/users/' . $users[0]->getId(); }, 1, ]; yield 'reviews filtered by book' => [ - ReviewFactory::new()->sequence(function () { + ReviewFactory::new()->sequence(static function () { yield ['book' => BookFactory::createOne(['title' => 'Hyperion'])]; foreach (range(1, 10) as $i) { yield ['book' => BookFactory::createOne()]; @@ -137,7 +141,7 @@ static function (): string { /** @var Book[] $books */ $books = BookFactory::findBy(['title' => 'Hyperion']); - return '/admin/reviews?book=/books/'.$books[0]->getId(); + return '/admin/reviews?book=/books/' . $books[0]->getId(); }, 1, ]; @@ -145,8 +149,10 @@ static function (): string { /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotGetAReview(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotGetAReview(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $review = ReviewFactory::createOne(); @@ -158,7 +164,7 @@ public function testAsNonAdminUserICannotGetAReview(int $expectedCode, string $h $options['auth_bearer'] = $token; } - $this->client->request('GET', '/admin/reviews/'.$review->getId(), $options); + $this->client->request('GET', '/admin/reviews/' . $review->getId(), $options); self::assertResponseStatusCodeSame($expectedCode); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -170,7 +176,10 @@ public function testAsNonAdminUserICannotGetAReview(int $expectedCode, string $h ]); } - public function testAsAdminUserICannotGetAnInvalidReview(): void + /** + * @test + */ + public function asAdminUserICannotGetAnInvalidReview(): void { $token = $this->generateToken([ 'email' => UserFactory::createOneAdmin()->email, @@ -181,7 +190,10 @@ public function testAsAdminUserICannotGetAnInvalidReview(): void self::assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND); } - public function testAsAdminUserICanGetAReview(): void + /** + * @test + */ + public function asAdminUserICanGetAReview(): void { $review = ReviewFactory::createOne(); @@ -189,17 +201,19 @@ public function testAsAdminUserICanGetAReview(): void 'email' => UserFactory::createOneAdmin()->email, ]); - $this->client->request('GET', '/admin/reviews/'.$review->getId(), ['auth_bearer' => $token]); + $this->client->request('GET', '/admin/reviews/' . $review->getId(), ['auth_bearer' => $token]); self::assertResponseIsSuccessful(); self::assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Review/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Review/item.json')); } /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotUpdateAReview(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotUpdateAReview(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $review = ReviewFactory::createOne(); @@ -211,7 +225,7 @@ public function testAsNonAdminUserICannotUpdateAReview(int $expectedCode, string $options['auth_bearer'] = $token; } - $this->client->request('GET', '/admin/reviews/'.$review->getId(), $options + [ + $this->client->request('GET', '/admin/reviews/' . $review->getId(), $options + [ 'json' => [ 'body' => 'Very good book!', 'rating' => 5, @@ -232,7 +246,10 @@ public function testAsNonAdminUserICannotUpdateAReview(int $expectedCode, string ]); } - public function testAsAdminUserICannotUpdateAnInvalidReview(): void + /** + * @test + */ + public function asAdminUserICannotUpdateAnInvalidReview(): void { $token = $this->generateToken([ 'email' => UserFactory::createOneAdmin()->email, @@ -255,8 +272,10 @@ public function testAsAdminUserICannotUpdateAnInvalidReview(): void /** * @group mercure + * + * @test */ - public function testAsAdminUserICanUpdateAReview(): void + public function asAdminUserICanUpdateAReview(): void { $book = BookFactory::createOne(); $review = ReviewFactory::createOne(['book' => $book]); @@ -266,11 +285,11 @@ public function testAsAdminUserICanUpdateAReview(): void 'email' => $user->email, ]); - $this->client->request('PUT', '/admin/reviews/'.$review->getId(), [ + $this->client->request('PUT', '/admin/reviews/' . $review->getId(), [ 'auth_bearer' => $token, 'json' => [ // Must set all data because of standard PUT - 'book' => '/admin/books/'.$book->getId(), + 'book' => '/admin/books/' . $book->getId(), 'letter' => null, 'body' => 'Very good book!', 'rating' => 5, @@ -289,11 +308,11 @@ public function testAsAdminUserICanUpdateAReview(): void ]); // ensure user hasn't changed self::assertNotEquals($user, $review->object()->user); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Review/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Review/item.json')); self::assertCount(2, self::getMercureMessages()); self::assertEquals( new Update( - topics: ['http://localhost/admin/reviews/'.$review->getId()], + topics: ['http://localhost/admin/reviews/' . $review->getId()], data: self::serialize( $review->object(), 'jsonld', @@ -304,7 +323,7 @@ public function testAsAdminUserICanUpdateAReview(): void ); self::assertEquals( new Update( - topics: ['http://localhost/books/'.$review->book->getId().'/reviews/'.$review->getId()], + topics: ['http://localhost/books/' . $review->book->getId() . '/reviews/' . $review->getId()], data: self::serialize( $review->object(), 'jsonld', @@ -317,8 +336,10 @@ public function testAsAdminUserICanUpdateAReview(): void /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotDeleteAReview(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotDeleteAReview(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $review = ReviewFactory::createOne(); @@ -330,7 +351,7 @@ public function testAsNonAdminUserICannotDeleteAReview(int $expectedCode, string $options['auth_bearer'] = $token; } - $this->client->request('DELETE', '/admin/reviews/'.$review->getId(), $options); + $this->client->request('DELETE', '/admin/reviews/' . $review->getId(), $options); self::assertResponseStatusCodeSame($expectedCode); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -342,7 +363,10 @@ public function testAsNonAdminUserICannotDeleteAReview(int $expectedCode, string ]); } - public function testAsAdminUserICannotDeleteAnInvalidReview(): void + /** + * @test + */ + public function asAdminUserICannotDeleteAnInvalidReview(): void { $token = $this->generateToken([ 'email' => UserFactory::createOneAdmin()->email, @@ -355,8 +379,10 @@ public function testAsAdminUserICannotDeleteAnInvalidReview(): void /** * @group mercure + * + * @test */ - public function testAsAdminUserICanDeleteAReview(): void + public function asAdminUserICanDeleteAReview(): void { $review = ReviewFactory::createOne(['body' => 'Best book ever!']); $id = $review->getId(); @@ -366,7 +392,7 @@ public function testAsAdminUserICanDeleteAReview(): void 'email' => UserFactory::createOneAdmin()->email, ]); - $response = $this->client->request('DELETE', '/admin/reviews/'.$review->getId(), [ + $response = $this->client->request('DELETE', '/admin/reviews/' . $review->getId(), [ 'auth_bearer' => $token, ]); @@ -377,15 +403,15 @@ public function testAsAdminUserICanDeleteAReview(): void // todo how to ensure it's a delete update self::assertEquals( new Update( - topics: ['http://localhost/admin/reviews/'.$id], - data: json_encode(['@id' => 'http://localhost/admin/reviews/'.$id]) + topics: ['http://localhost/admin/reviews/' . $id], + data: json_encode(['@id' => 'http://localhost/admin/reviews/' . $id]) ), self::getMercureMessage() ); self::assertEquals( new Update( - topics: ['http://localhost/books/'.$bookId.'/reviews/'.$id], - data: json_encode(['@id' => 'http://localhost/books/'.$bookId.'/reviews/'.$id]) + topics: ['http://localhost/books/' . $bookId . '/reviews/' . $id], + data: json_encode(['@id' => 'http://localhost/books/' . $bookId . '/reviews/' . $id]) ), self::getMercureMessage(1) ); diff --git a/api/tests/Api/Admin/UserTest.php b/api/tests/Api/Admin/UserTest.php index abfa156ac..43ada6155 100644 --- a/api/tests/Api/Admin/UserTest.php +++ b/api/tests/Api/Admin/UserTest.php @@ -31,8 +31,10 @@ protected function setup(): void /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotGetACollectionOfUsers(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotGetACollectionOfUsers(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $options = []; if ($userFactory) { @@ -56,8 +58,10 @@ public function testAsNonAdminUserICannotGetACollectionOfUsers(int $expectedCode /** * @dataProvider getAdminUrls + * + * @test */ - public function testAsAdminUserICanGetACollectionOfUsers(FactoryCollection $factory, string|callable $url, int $hydraTotalItems, int $itemsPerPage = null): void + public function asAdminUserICanGetACollectionOfUsers(FactoryCollection $factory, callable|string $url, int $hydraTotalItems, int $itemsPerPage = null): void { $factory->create(); @@ -65,7 +69,7 @@ public function testAsAdminUserICanGetACollectionOfUsers(FactoryCollection $fact 'email' => UserFactory::createOneAdmin()->email, ]); - if (is_callable($url)) { + if (\is_callable($url)) { $url = $url(); } @@ -77,10 +81,10 @@ public function testAsAdminUserICanGetACollectionOfUsers(FactoryCollection $fact 'hydra:totalItems' => $hydraTotalItems, ]); self::assertCount(min($itemsPerPage ?? $hydraTotalItems, 30), $response->toArray()['hydra:member']); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/User/collection.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/User/collection.json')); } - public function getAdminUrls(): iterable + public static function getAdminUrls(): iterable { yield 'all users' => [ UserFactory::new()->many(34), @@ -94,7 +98,7 @@ public function getAdminUrls(): iterable 10, ]; yield 'users filtered by name' => [ - UserFactory::new()->sequence(function () { + UserFactory::new()->sequence(static function () { yield ['firstName' => 'John', 'lastName' => 'DOE']; foreach (range(1, 10) as $i) { yield []; @@ -107,8 +111,10 @@ public function getAdminUrls(): iterable /** * @dataProvider getNonAdminUsers + * + * @test */ - public function testAsNonAdminUserICannotGetAUser(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void + public function asNonAdminUserICannotGetAUser(int $expectedCode, string $hydraDescription, ?UserFactory $userFactory): void { $user = UserFactory::createOne(); @@ -120,7 +126,7 @@ public function testAsNonAdminUserICannotGetAUser(int $expectedCode, string $hyd $options['auth_bearer'] = $token; } - $this->client->request('GET', '/admin/users/'.$user->getId(), $options); + $this->client->request('GET', '/admin/users/' . $user->getId(), $options); self::assertResponseStatusCodeSame($expectedCode); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -132,7 +138,10 @@ public function testAsNonAdminUserICannotGetAUser(int $expectedCode, string $hyd ]); } - public function testAsAdminUserICanGetAUser(): void + /** + * @test + */ + public function asAdminUserICanGetAUser(): void { $user = UserFactory::createOne(); @@ -140,18 +149,21 @@ public function testAsAdminUserICanGetAUser(): void 'email' => UserFactory::createOneAdmin()->email, ]); - $this->client->request('GET', '/admin/users/'.$user->getId(), ['auth_bearer' => $token]); + $this->client->request('GET', '/admin/users/' . $user->getId(), ['auth_bearer' => $token]); self::assertResponseIsSuccessful(); self::assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); self::assertJsonContains([ - '@id' => '/admin/users/'.$user->getId(), + '@id' => '/admin/users/' . $user->getId(), ]); // note: email property is never exposed - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/User/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/User/item.json')); } - public function testAsAUserIAmUpdatedOnLogin(): void + /** + * @test + */ + public function asAUserIAmUpdatedOnLogin(): void { $user = UserFactory::createOne([ 'firstName' => 'John', diff --git a/api/tests/Api/BookTest.php b/api/tests/Api/BookTest.php index b56e14778..572b4d49a 100644 --- a/api/tests/Api/BookTest.php +++ b/api/tests/Api/BookTest.php @@ -28,8 +28,10 @@ protected function setup(): void /** * @dataProvider getUrls + * + * @test */ - public function testAsAnonymousICanGetACollectionOfBooks(FactoryCollection $factory, string $url, int $hydraTotalItems): void + public function asAnonymousICanGetACollectionOfBooks(FactoryCollection $factory, string $url, int $hydraTotalItems): void { // Cannot use Factory as data provider because BookFactory has a service dependency $factory->create(); @@ -42,10 +44,10 @@ public function testAsAnonymousICanGetACollectionOfBooks(FactoryCollection $fact 'hydra:totalItems' => $hydraTotalItems, ]); self::assertCount(min($hydraTotalItems, 30), $response->toArray()['hydra:member']); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Book/collection.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Book/collection.json')); } - public function getUrls(): iterable + public static function getUrls(): iterable { yield 'all books' => [ BookFactory::new()->many(35), @@ -53,7 +55,7 @@ public function getUrls(): iterable 35, ]; yield 'books filtered by title' => [ - BookFactory::new()->sequence(function () { + BookFactory::new()->sequence(static function () { yield ['title' => 'Hyperion']; foreach (range(1, 10) as $i) { yield []; @@ -63,7 +65,7 @@ public function getUrls(): iterable 1, ]; yield 'books filtered by author' => [ - BookFactory::new()->sequence(function () { + BookFactory::new()->sequence(static function () { yield ['author' => 'Dan Simmons']; foreach (range(1, 10) as $i) { yield []; @@ -73,18 +75,21 @@ public function getUrls(): iterable 1, ]; yield 'books filtered by condition' => [ - BookFactory::new()->sequence(function () { + BookFactory::new()->sequence(static function () { foreach (range(1, 100) as $i) { // 33% of books are damaged yield ['condition' => $i % 3 ? BookCondition::NewCondition : BookCondition::DamagedCondition]; } }), - '/books?condition='.BookCondition::DamagedCondition->value, + '/books?condition=' . BookCondition::DamagedCondition->value, 33, ]; } - public function testAsAdminUserICanGetACollectionOfBooksOrderedByTitle(): void + /** + * @test + */ + public function asAdminUserICanGetACollectionOfBooksOrderedByTitle(): void { BookFactory::createOne(['title' => 'Hyperion']); BookFactory::createOne(['title' => 'The Wandering Earth']); @@ -97,10 +102,13 @@ public function testAsAdminUserICanGetACollectionOfBooksOrderedByTitle(): void self::assertEquals('Ball Lightning', $response->toArray()['hydra:member'][0]['title']); self::assertEquals('Hyperion', $response->toArray()['hydra:member'][1]['title']); self::assertEquals('The Wandering Earth', $response->toArray()['hydra:member'][2]['title']); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Book/collection.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Book/collection.json')); } - public function testAsAnonymousICannotGetAnInvalidBook(): void + /** + * @test + */ + public function asAnonymousICannotGetAnInvalidBook(): void { BookFactory::createOne(); @@ -109,7 +117,10 @@ public function testAsAnonymousICannotGetAnInvalidBook(): void self::assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND); } - public function testAsAnonymousICanGetABook(): void + /** + * @test + */ + public function asAnonymousICanGetABook(): void { $book = BookFactory::createOne(); ReviewFactory::createOne(['rating' => 1, 'book' => $book]); @@ -118,19 +129,19 @@ public function testAsAnonymousICanGetABook(): void ReviewFactory::createOne(['rating' => 4, 'book' => $book]); ReviewFactory::createOne(['rating' => 5, 'book' => $book]); - $this->client->request('GET', '/books/'.$book->getId()); + $this->client->request('GET', '/books/' . $book->getId()); self::assertResponseIsSuccessful(); self::assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); self::assertJsonContains([ - '@id' => '/books/'.$book->getId(), + '@id' => '/books/' . $book->getId(), 'book' => $book->book, 'condition' => $book->condition->value, 'title' => $book->title, 'author' => $book->author, - 'reviews' => '/books/'.$book->getId().'/reviews', + 'reviews' => '/books/' . $book->getId() . '/reviews', 'rating' => 3, ]); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Book/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Book/item.json')); } } diff --git a/api/tests/Api/BookmarkTest.php b/api/tests/Api/BookmarkTest.php index b28d1cafa..d28ace0c7 100644 --- a/api/tests/Api/BookmarkTest.php +++ b/api/tests/Api/BookmarkTest.php @@ -33,7 +33,10 @@ protected function setup(): void $this->client = self::createClient(); } - public function testAsAnonymousICannotGetACollectionOfBookmarks(): void + /** + * @test + */ + public function asAnonymousICannotGetACollectionOfBookmarks(): void { BookmarkFactory::createMany(10); @@ -51,8 +54,10 @@ public function testAsAnonymousICannotGetACollectionOfBookmarks(): void /** * Filters are disabled on /bookmarks. + * + * @test */ - public function testAsAUserICanGetACollectionOfMyBookmarksWithoutFilters(): void + public function asAUserICanGetACollectionOfMyBookmarksWithoutFilters(): void { BookmarkFactory::createMany(10); $user = UserFactory::createOne(); @@ -70,16 +75,19 @@ public function testAsAUserICanGetACollectionOfMyBookmarksWithoutFilters(): void 'hydra:totalItems' => 35, ]); self::assertCount(30, $response->toArray()['hydra:member']); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Bookmark/collection.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Bookmark/collection.json')); } - public function testAsAnonymousICannotCreateABookmark(): void + /** + * @test + */ + public function asAnonymousICannotCreateABookmark(): void { $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL2055137M.json']); $this->client->request('POST', '/bookmarks', [ 'json' => [ - 'book' => '/books/'.$book->getId(), + 'book' => '/books/' . $book->getId(), ], 'headers' => [ 'Content-Type' => 'application/ld+json', @@ -97,7 +105,10 @@ public function testAsAnonymousICannotCreateABookmark(): void ]); } - public function testAsAUserICannotCreateABookmarkWithInvalidData(): void + /** + * @test + */ + public function asAUserICannotCreateABookmarkWithInvalidData(): void { $token = $this->generateToken([ 'email' => UserFactory::createOne()->email, @@ -107,7 +118,7 @@ public function testAsAUserICannotCreateABookmarkWithInvalidData(): void $this->client->request('POST', '/bookmarks', [ 'json' => [ - 'book' => '/books/'.$uuid, + 'book' => '/books/' . $uuid, ], 'headers' => [ 'Content-Type' => 'application/ld+json', @@ -118,32 +129,34 @@ public function testAsAUserICannotCreateABookmarkWithInvalidData(): void self::assertResponseStatusCodeSame(Response::HTTP_BAD_REQUEST); // todo waiting for https://github.com/api-platform/core/pull/5844 -// self::assertResponseStatusCodeSame(Response::HTTP_UNPROCESSABLE_ENTITY); + // self::assertResponseStatusCodeSame(Response::HTTP_UNPROCESSABLE_ENTITY); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); self::assertResponseHeaderSame('link', '; rel="http://www.w3.org/ns/json-ld#error",; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"'); self::assertJsonContains([ '@type' => 'hydra:Error', 'hydra:title' => 'An error occurred', - 'hydra:description' => 'Item not found for "/books/'.$uuid.'".', + 'hydra:description' => 'Item not found for "/books/' . $uuid . '".', ]); // todo waiting for https://github.com/api-platform/core/pull/5844 -// self::assertJsonContains([ -// '@type' => 'ConstraintViolationList', -// 'hydra:title' => 'An error occurred', -// 'hydra:description' => 'book: This value should be of type '.Book::class.'.', -// 'violations' => [ -// [ -// 'propertyPath' => 'book', -// 'hint' => 'Item not found for "/books/'.$uuid.'".', -// ], -// ], -// ]); + // self::assertJsonContains([ + // '@type' => 'ConstraintViolationList', + // 'hydra:title' => 'An error occurred', + // 'hydra:description' => 'book: This value should be of type '.Book::class.'.', + // 'violations' => [ + // [ + // 'propertyPath' => 'book', + // 'hint' => 'Item not found for "/books/'.$uuid.'".', + // ], + // ], + // ]); } /** * @group mercure + * + * @test */ - public function testAsAUserICanCreateABookmark(): void + public function asAUserICanCreateABookmark(): void { $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL2055137M.json']); $user = UserFactory::createOne(); @@ -155,7 +168,7 @@ public function testAsAUserICanCreateABookmark(): void $response = $this->client->request('POST', '/bookmarks', [ 'json' => [ - 'book' => '/books/'.$book->getId(), + 'book' => '/books/' . $book->getId(), ], 'headers' => [ 'Content-Type' => 'application/ld+json', @@ -168,17 +181,17 @@ public function testAsAUserICanCreateABookmark(): void self::assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); self::assertJsonContains([ 'book' => [ - '@id' => '/books/'.$book->getId(), + '@id' => '/books/' . $book->getId(), ], ]); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Bookmark/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Bookmark/item.json')); $id = preg_replace('/^.*\/(.+)$/', '$1', $response->toArray()['@id']); $object = self::getContainer()->get(BookmarkRepository::class)->find($id); self::assertCount(1, self::getMercureMessages()); self::assertEquals( self::getMercureMessage(), new Update( - topics: ['http://localhost/bookmarks/'.$id], + topics: ['http://localhost/bookmarks/' . $id], data: self::serialize( $object, 'jsonld', @@ -188,7 +201,10 @@ public function testAsAUserICanCreateABookmark(): void ); } - public function testAsAUserICannotCreateADuplicateBookmark(): void + /** + * @test + */ + public function asAUserICannotCreateADuplicateBookmark(): void { $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL2055137M.json']); $user = UserFactory::createOne(); @@ -200,7 +216,7 @@ public function testAsAUserICannotCreateADuplicateBookmark(): void $this->client->request('POST', '/bookmarks', [ 'json' => [ - 'book' => '/books/'.$book->getId(), + 'book' => '/books/' . $book->getId(), ], 'headers' => [ 'Content-Type' => 'application/ld+json', @@ -219,11 +235,14 @@ public function testAsAUserICannotCreateADuplicateBookmark(): void ]); } - public function testAsAnonymousICannotDeleteABookmark(): void + /** + * @test + */ + public function asAnonymousICannotDeleteABookmark(): void { $bookmark = BookmarkFactory::createOne(); - $this->client->request('DELETE', '/bookmarks/'.$bookmark->getId()); + $this->client->request('DELETE', '/bookmarks/' . $bookmark->getId()); self::assertResponseStatusCodeSame(Response::HTTP_UNAUTHORIZED); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -235,7 +254,10 @@ public function testAsAnonymousICannotDeleteABookmark(): void ]); } - public function testAsAUserICannotDeleteABookmarkOfAnotherUser(): void + /** + * @test + */ + public function asAUserICannotDeleteABookmarkOfAnotherUser(): void { $bookmark = BookmarkFactory::createOne(['user' => UserFactory::createOne()]); @@ -243,7 +265,7 @@ public function testAsAUserICannotDeleteABookmarkOfAnotherUser(): void 'email' => UserFactory::createOne()->email, ]); - $this->client->request('DELETE', '/bookmarks/'.$bookmark->getId(), [ + $this->client->request('DELETE', '/bookmarks/' . $bookmark->getId(), [ 'auth_bearer' => $token, ]); @@ -257,7 +279,10 @@ public function testAsAUserICannotDeleteABookmarkOfAnotherUser(): void ]); } - public function testAsAUserICannotDeleteAnInvalidBookmark(): void + /** + * @test + */ + public function asAUserICannotDeleteAnInvalidBookmark(): void { $token = $this->generateToken([ 'email' => UserFactory::createOne()->email, @@ -272,8 +297,10 @@ public function testAsAUserICannotDeleteAnInvalidBookmark(): void /** * @group mercure + * + * @test */ - public function testAsAUserICanDeleteMyBookmark(): void + public function asAUserICanDeleteMyBookmark(): void { $book = BookFactory::createOne(['title' => 'Hyperion']); $bookmark = BookmarkFactory::createOne(['book' => $book]); @@ -285,7 +312,7 @@ public function testAsAUserICanDeleteMyBookmark(): void 'email' => $bookmark->user->email, ]); - $response = $this->client->request('DELETE', '/bookmarks/'.$bookmark->getId(), [ + $response = $this->client->request('DELETE', '/bookmarks/' . $bookmark->getId(), [ 'auth_bearer' => $token, ]); @@ -296,8 +323,8 @@ public function testAsAUserICanDeleteMyBookmark(): void // todo how to ensure it's a delete update self::assertEquals( new Update( - topics: ['http://localhost/bookmarks/'.$id], - data: json_encode(['@id' => '/bookmarks/'.$id, '@type' => 'https://schema.org/BookmarkAction']) + topics: ['http://localhost/bookmarks/' . $id], + data: json_encode(['@id' => '/bookmarks/' . $id, '@type' => 'https://schema.org/BookmarkAction']) ), self::getMercureMessage() ); diff --git a/api/tests/Api/ReviewTest.php b/api/tests/Api/ReviewTest.php index 58ddffa1b..24a9b9c40 100644 --- a/api/tests/Api/ReviewTest.php +++ b/api/tests/Api/ReviewTest.php @@ -39,12 +39,14 @@ protected function setup(): void * Filters are disabled on /books/{bookId}/reviews. * * @dataProvider getUrls + * + * @test */ - public function testAsAnonymousICanGetACollectionOfBookReviewsWithoutFilters(FactoryCollection $factory, string|callable $url, int $hydraTotalItems, int $totalHydraMember = 30): void + public function asAnonymousICanGetACollectionOfBookReviewsWithoutFilters(FactoryCollection $factory, callable|string $url, int $hydraTotalItems, int $totalHydraMember = 30): void { $factory->create(); - if (is_callable($url)) { + if (\is_callable($url)) { $url = $url(); } @@ -56,13 +58,13 @@ public function testAsAnonymousICanGetACollectionOfBookReviewsWithoutFilters(Fac 'hydra:totalItems' => $hydraTotalItems, ]); self::assertCount(min($hydraTotalItems, $totalHydraMember), $response->toArray()['hydra:member']); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Review/collection.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Review/collection.json')); } - public function getUrls(): iterable + public static function getUrls(): iterable { yield 'all book reviews' => [ - ReviewFactory::new()->sequence(function () { + ReviewFactory::new()->sequence(static function () { $book = BookFactory::createOne(['title' => 'Hyperion']); foreach (range(1, 35) as $i) { yield ['book' => $book]; @@ -72,12 +74,12 @@ static function (): string { /** @var Book[] $books */ $books = BookFactory::findBy(['title' => 'Hyperion']); - return '/books/'.$books[0]->getId().'/reviews'; + return '/books/' . $books[0]->getId() . '/reviews'; }, 35, ]; yield 'all book reviews using itemsPerPage' => [ - ReviewFactory::new()->sequence(function () { + ReviewFactory::new()->sequence(static function () { $book = BookFactory::createOne(['title' => 'Hyperion']); foreach (range(1, 20) as $i) { yield ['book' => $book]; @@ -87,13 +89,13 @@ static function (): string { /** @var Book[] $books */ $books = BookFactory::findBy(['title' => 'Hyperion']); - return '/books/'.$books[0]->getId().'/reviews?itemsPerPage=10'; + return '/books/' . $books[0]->getId() . '/reviews?itemsPerPage=10'; }, 20, 10, ]; yield 'book reviews filtered by rating (filter is disabled for non-admin users)' => [ - ReviewFactory::new()->sequence(function () { + ReviewFactory::new()->sequence(static function () { $book = BookFactory::createOne(['title' => 'Hyperion']); foreach (range(1, 100) as $i) { // 33% of reviews are rated 5 @@ -104,12 +106,12 @@ static function (): string { /** @var Book[] $books */ $books = BookFactory::findBy(['title' => 'Hyperion']); - return '/books/'.$books[0]->getId().'/reviews?rating=5'; + return '/books/' . $books[0]->getId() . '/reviews?rating=5'; }, 100, ]; yield 'book reviews filtered by user (filter is disabled for non-admin users)' => [ - ReviewFactory::new()->sequence(function () { + ReviewFactory::new()->sequence(static function () { $book = BookFactory::createOne(['title' => 'Hyperion']); yield ['book' => $book, 'user' => UserFactory::createOne(['email' => 'user@example.com'])]; foreach (range(1, 34) as $i) { @@ -122,17 +124,20 @@ static function (): string { /** @var User[] $users */ $users = UserFactory::findBy(['email' => 'user@example.com']); - return '/books/'.$books[0]->getId().'/reviews?user=/users/'.$users[0]->getId(); + return '/books/' . $books[0]->getId() . '/reviews?user=/users/' . $users[0]->getId(); }, 35, ]; } - public function testAsAnonymousICannotAddAReviewOnABook(): void + /** + * @test + */ + public function asAnonymousICannotAddAReviewOnABook(): void { $book = BookFactory::createOne(); - $this->client->request('POST', '/books/'.$book->getId().'/reviews', [ + $this->client->request('POST', '/books/' . $book->getId() . '/reviews', [ 'json' => [ 'body' => 'Very good book!', 'rating' => 5, @@ -155,8 +160,10 @@ public function testAsAnonymousICannotAddAReviewOnABook(): void /** * @dataProvider getInvalidData + * + * @test */ - public function testAsAUserICannotAddAReviewOnABookWithInvalidData(array $data, int $statusCode, array $expected): void + public function asAUserICannotAddAReviewOnABookWithInvalidData(array $data, int $statusCode, array $expected): void { $book = BookFactory::createOne(); @@ -164,7 +171,7 @@ public function testAsAUserICannotAddAReviewOnABookWithInvalidData(array $data, 'email' => UserFactory::createOne()->email, ]); - $this->client->request('POST', '/books/'.$book->getId().'/reviews', [ + $this->client->request('POST', '/books/' . $book->getId() . '/reviews', [ 'auth_bearer' => $token, 'json' => $data, 'headers' => [ @@ -179,7 +186,7 @@ public function testAsAUserICannotAddAReviewOnABookWithInvalidData(array $data, self::assertJsonContains($expected); } - public function getInvalidData(): iterable + public static function getInvalidData(): iterable { yield 'empty data' => [ [], @@ -201,7 +208,10 @@ public function getInvalidData(): iterable ]; } - public function testAsAUserICannotAddAReviewWithValidDataOnAnInvalidBook(): void + /** + * @test + */ + public function asAUserICannotAddAReviewWithValidDataOnAnInvalidBook(): void { $book = BookFactory::createOne(); ReviewFactory::createMany(5, ['book' => $book]); @@ -235,8 +245,10 @@ public function testAsAUserICannotAddAReviewWithValidDataOnAnInvalidBook(): void /** * @group mercure + * + * @test */ - public function testAsAUserICanAddAReviewOnABook(): void + public function asAUserICanAddAReviewOnABook(): void { $book = BookFactory::createOne(); ReviewFactory::createMany(5, ['book' => $book]); @@ -247,7 +259,7 @@ public function testAsAUserICanAddAReviewOnABook(): void 'email' => $user->email, ]); - $response = $this->client->request('POST', '/books/'.$book->getId().'/reviews', [ + $response = $this->client->request('POST', '/books/' . $book->getId() . '/reviews', [ 'auth_bearer' => $token, 'json' => [ 'body' => 'Very good book!', @@ -262,14 +274,14 @@ public function testAsAUserICanAddAReviewOnABook(): void self::assertResponseStatusCodeSame(Response::HTTP_CREATED); self::assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); self::assertJsonContains([ - 'book' => '/books/'.$book->getId(), + 'book' => '/books/' . $book->getId(), 'user' => [ - '@id' => '/users/'.$user->getId(), + '@id' => '/users/' . $user->getId(), ], 'body' => 'Very good book!', 'rating' => 5, ]); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Review/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Review/item.json')); // if I add a review on a book with reviews, it doesn't erase the existing reviews $reviews = self::getContainer()->get(ReviewRepository::class)->findBy(['book' => $book->object()]); self::assertCount(6, $reviews); @@ -279,17 +291,20 @@ public function testAsAUserICanAddAReviewOnABook(): void self::assertCount(2, self::getMercureMessages()); self::assertMercureUpdateMatchesJsonSchema( update: self::getMercureMessage(), - topics: ['http://localhost/admin/reviews/'.$review->getId()], - jsonSchema: file_get_contents(__DIR__.'/Admin/schemas/Review/item.json') + topics: ['http://localhost/admin/reviews/' . $review->getId()], + jsonSchema: file_get_contents(__DIR__ . '/Admin/schemas/Review/item.json') ); self::assertMercureUpdateMatchesJsonSchema( update: self::getMercureMessage(1), - topics: ['http://localhost/books/'.$book->getId().'/reviews/'.$review->getId()], - jsonSchema: file_get_contents(__DIR__.'/schemas/Review/item.json') + topics: ['http://localhost/books/' . $book->getId() . '/reviews/' . $review->getId()], + jsonSchema: file_get_contents(__DIR__ . '/schemas/Review/item.json') ); } - public function testAsAUserICannotAddADuplicateReviewOnABook(): void + /** + * @test + */ + public function asAUserICannotAddADuplicateReviewOnABook(): void { $book = BookFactory::createOne(); ReviewFactory::createMany(5, ['book' => $book]); @@ -300,7 +315,7 @@ public function testAsAUserICannotAddADuplicateReviewOnABook(): void 'email' => $user->email, ]); - $this->client->request('POST', '/books/'.$book->getId().'/reviews', [ + $this->client->request('POST', '/books/' . $book->getId() . '/reviews', [ 'auth_bearer' => $token, 'json' => [ 'body' => 'Very good book!', @@ -322,11 +337,14 @@ public function testAsAUserICannotAddADuplicateReviewOnABook(): void ]); } - public function testAsAnonymousICannotGetAnInvalidReview(): void + /** + * @test + */ + public function asAnonymousICannotGetAnInvalidReview(): void { $book = BookFactory::createOne(); - $this->client->request('GET', '/books/'.$book->getId().'/reviews/invalid'); + $this->client->request('GET', '/books/' . $book->getId() . '/reviews/invalid'); self::assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -338,11 +356,14 @@ public function testAsAnonymousICannotGetAnInvalidReview(): void ]); } - public function testAsAnonymousICanGetABookReview(): void + /** + * @test + */ + public function asAnonymousICanGetABookReview(): void { $review = ReviewFactory::createOne(); - $this->client->request('GET', '/books/'.$review->book->getId().'/reviews/'.$review->getId()); + $this->client->request('GET', '/books/' . $review->book->getId() . '/reviews/' . $review->getId()); self::assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -354,11 +375,14 @@ public function testAsAnonymousICanGetABookReview(): void ]); } - public function testAsAnonymousICannotUpdateABookReview(): void + /** + * @test + */ + public function asAnonymousICannotUpdateABookReview(): void { $review = ReviewFactory::createOne(); - $this->client->request('PATCH', '/books/'.$review->book->getId().'/reviews/'.$review->getId(), [ + $this->client->request('PATCH', '/books/' . $review->book->getId() . '/reviews/' . $review->getId(), [ 'json' => [ 'body' => 'Very good book!', 'rating' => 5, @@ -378,7 +402,10 @@ public function testAsAnonymousICannotUpdateABookReview(): void ]); } - public function testAsAUserICannotUpdateABookReviewOfAnotherUser(): void + /** + * @test + */ + public function asAUserICannotUpdateABookReviewOfAnotherUser(): void { $review = ReviewFactory::createOne(['user' => UserFactory::createOne()]); @@ -386,7 +413,7 @@ public function testAsAUserICannotUpdateABookReviewOfAnotherUser(): void 'email' => UserFactory::createOne()->email, ]); - $this->client->request('PATCH', '/books/'.$review->book->getId().'/reviews/'.$review->getId(), [ + $this->client->request('PATCH', '/books/' . $review->book->getId() . '/reviews/' . $review->getId(), [ 'auth_bearer' => $token, 'json' => [ 'body' => 'Very good book!', @@ -407,7 +434,10 @@ public function testAsAUserICannotUpdateABookReviewOfAnotherUser(): void ]); } - public function testAsAUserICannotUpdateAnInvalidBookReview(): void + /** + * @test + */ + public function asAUserICannotUpdateAnInvalidBookReview(): void { $book = BookFactory::createOne(); @@ -415,7 +445,7 @@ public function testAsAUserICannotUpdateAnInvalidBookReview(): void 'email' => UserFactory::createOne()->email, ]); - $this->client->request('PATCH', '/books/'.$book->getId().'/reviews/invalid', [ + $this->client->request('PATCH', '/books/' . $book->getId() . '/reviews/invalid', [ 'auth_bearer' => $token, 'json' => [ 'body' => 'Very good book!', @@ -431,8 +461,10 @@ public function testAsAUserICannotUpdateAnInvalidBookReview(): void /** * @group mercure + * + * @test */ - public function testAsAUserICanUpdateMyBookReview(): void + public function asAUserICanUpdateMyBookReview(): void { $review = ReviewFactory::createOne(); self::getMercureHub()->reset(); @@ -441,7 +473,7 @@ public function testAsAUserICanUpdateMyBookReview(): void 'email' => $review->user->email, ]); - $this->client->request('PATCH', '/books/'.$review->book->getId().'/reviews/'.$review->getId(), [ + $this->client->request('PATCH', '/books/' . $review->book->getId() . '/reviews/' . $review->getId(), [ 'auth_bearer' => $token, 'json' => [ 'body' => 'Very good book!', @@ -458,25 +490,28 @@ public function testAsAUserICanUpdateMyBookReview(): void 'body' => 'Very good book!', 'rating' => 5, ]); - self::assertMatchesJsonSchema(file_get_contents(__DIR__.'/schemas/Review/item.json')); + self::assertMatchesJsonSchema(file_get_contents(__DIR__ . '/schemas/Review/item.json')); self::assertCount(2, self::getMercureMessages()); self::assertMercureUpdateMatchesJsonSchema( update: self::getMercureMessage(), - topics: ['http://localhost/admin/reviews/'.$review->getId()], - jsonSchema: file_get_contents(__DIR__.'/Admin/schemas/Review/item.json') + topics: ['http://localhost/admin/reviews/' . $review->getId()], + jsonSchema: file_get_contents(__DIR__ . '/Admin/schemas/Review/item.json') ); self::assertMercureUpdateMatchesJsonSchema( update: self::getMercureMessage(1), - topics: ['http://localhost/books/'.$review->book->getId().'/reviews/'.$review->getId()], - jsonSchema: file_get_contents(__DIR__.'/schemas/Review/item.json') + topics: ['http://localhost/books/' . $review->book->getId() . '/reviews/' . $review->getId()], + jsonSchema: file_get_contents(__DIR__ . '/schemas/Review/item.json') ); } - public function testAsAnonymousICannotDeleteABookReview(): void + /** + * @test + */ + public function asAnonymousICannotDeleteABookReview(): void { $review = ReviewFactory::createOne(); - $this->client->request('DELETE', '/books/'.$review->book->getId().'/reviews/'.$review->getId()); + $this->client->request('DELETE', '/books/' . $review->book->getId() . '/reviews/' . $review->getId()); self::assertResponseStatusCodeSame(Response::HTTP_UNAUTHORIZED); self::assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); @@ -488,7 +523,10 @@ public function testAsAnonymousICannotDeleteABookReview(): void ]); } - public function testAsAUserICannotDeleteABookReviewOfAnotherUser(): void + /** + * @test + */ + public function asAUserICannotDeleteABookReviewOfAnotherUser(): void { $review = ReviewFactory::createOne(['user' => UserFactory::createOne()]); @@ -496,7 +534,7 @@ public function testAsAUserICannotDeleteABookReviewOfAnotherUser(): void 'email' => UserFactory::createOne()->email, ]); - $this->client->request('DELETE', '/books/'.$review->book->getId().'/reviews/'.$review->getId(), [ + $this->client->request('DELETE', '/books/' . $review->book->getId() . '/reviews/' . $review->getId(), [ 'auth_bearer' => $token, ]); @@ -510,7 +548,10 @@ public function testAsAUserICannotDeleteABookReviewOfAnotherUser(): void ]); } - public function testAsAUserICannotDeleteAnInvalidBookReview(): void + /** + * @test + */ + public function asAUserICannotDeleteAnInvalidBookReview(): void { $book = BookFactory::createOne(); @@ -518,7 +559,7 @@ public function testAsAUserICannotDeleteAnInvalidBookReview(): void 'email' => UserFactory::createOne()->email, ]); - $this->client->request('DELETE', '/books/'.$book->getId().'/reviews/invalid', [ + $this->client->request('DELETE', '/books/' . $book->getId() . '/reviews/invalid', [ 'auth_bearer' => $token, ]); @@ -527,8 +568,10 @@ public function testAsAUserICannotDeleteAnInvalidBookReview(): void /** * @group mercure + * + * @test */ - public function testAsAUserICanDeleteMyBookReview(): void + public function asAUserICanDeleteMyBookReview(): void { $review = ReviewFactory::createOne(['body' => 'Best book ever!']); self::getMercureHub()->reset(); @@ -539,7 +582,7 @@ public function testAsAUserICanDeleteMyBookReview(): void 'email' => $review->user->email, ]); - $response = $this->client->request('DELETE', '/books/'.$bookId.'/reviews/'.$id, [ + $response = $this->client->request('DELETE', '/books/' . $bookId . '/reviews/' . $id, [ 'auth_bearer' => $token, ]); @@ -550,15 +593,15 @@ public function testAsAUserICanDeleteMyBookReview(): void // todo how to ensure it's a delete update self::assertEquals( new Update( - topics: ['http://localhost/admin/reviews/'.$id], - data: json_encode(['@id' => 'http://localhost/admin/reviews/'.$id]) + topics: ['http://localhost/admin/reviews/' . $id], + data: json_encode(['@id' => 'http://localhost/admin/reviews/' . $id]) ), self::getMercureMessage() ); self::assertEquals( new Update( - topics: ['http://localhost/books/'.$bookId.'/reviews/'.$id], - data: json_encode(['@id' => 'http://localhost/books/'.$bookId.'/reviews/'.$id]) + topics: ['http://localhost/books/' . $bookId . '/reviews/' . $id], + data: json_encode(['@id' => 'http://localhost/books/' . $bookId . '/reviews/' . $id]) ), self::getMercureMessage(1) ); diff --git a/api/tests/Doctrine/Orm/Extension/BookmarkQueryCollectionExtensionTest.php b/api/tests/Doctrine/Orm/Extension/BookmarkQueryCollectionExtensionTest.php index f71a98bb4..08a929340 100644 --- a/api/tests/Doctrine/Orm/Extension/BookmarkQueryCollectionExtensionTest.php +++ b/api/tests/Doctrine/Orm/Extension/BookmarkQueryCollectionExtensionTest.php @@ -34,30 +34,38 @@ protected function setUp(): void $this->extension = new BookmarkQueryCollectionExtension($this->securityMock); } - public function testItFiltersBookmarksQueryOnCurrentUser(): void + /** + * @test + */ + public function itFiltersBookmarksQueryOnCurrentUser(): void { $this->operationMock ->expects($this->once()) ->method('getName') - ->willReturn('_api_/bookmarks{._format}_get_collection'); + ->willReturn('_api_/bookmarks{._format}_get_collection') + ; $this->securityMock ->expects($this->once()) ->method('getUser') - ->willReturn($this->userMock); + ->willReturn($this->userMock) + ; $this->queryBuilderMock ->expects($this->once()) ->method('getRootAliases') - ->willReturn(['o']); + ->willReturn(['o']) + ; $this->queryBuilderMock ->expects($this->once()) ->method('andWhere') ->with('o.user = :user') - ->willReturn($this->queryBuilderMock); + ->willReturn($this->queryBuilderMock) + ; $this->queryBuilderMock ->expects($this->once()) ->method('setParameter') ->with('user', $this->userMock) - ->willReturn($this->queryBuilderMock); + ->willReturn($this->queryBuilderMock) + ; $this->extension->applyToCollection( $this->queryBuilderMock, @@ -67,7 +75,10 @@ public function testItFiltersBookmarksQueryOnCurrentUser(): void ); } - public function testItIgnoresInvalidResourceClass(): void + /** + * @test + */ + public function itIgnoresInvalidResourceClass(): void { $this->operationMock->expects($this->never())->method('getName'); $this->securityMock->expects($this->never())->method('getUser'); @@ -83,12 +94,16 @@ public function testItIgnoresInvalidResourceClass(): void ); } - public function testItIgnoresInvalidOperation(): void + /** + * @test + */ + public function itIgnoresInvalidOperation(): void { $this->operationMock ->expects($this->once()) ->method('getName') - ->willReturn('_api_/books{._format}_get_collection'); + ->willReturn('_api_/books{._format}_get_collection') + ; $this->securityMock->expects($this->never())->method('getUser'); $this->queryBuilderMock->expects($this->never())->method('getRootAliases'); $this->queryBuilderMock->expects($this->never())->method('andWhere'); @@ -102,16 +117,21 @@ public function testItIgnoresInvalidOperation(): void ); } - public function testItIgnoresInvalidUser(): void + /** + * @test + */ + public function itIgnoresInvalidUser(): void { $this->operationMock ->expects($this->once()) ->method('getName') - ->willReturn('_api_/bookmarks{._format}_get_collection'); + ->willReturn('_api_/bookmarks{._format}_get_collection') + ; $this->securityMock ->expects($this->once()) ->method('getUser') - ->willReturn(null); + ->willReturn(null) + ; $this->queryBuilderMock->expects($this->never())->method('getRootAliases'); $this->queryBuilderMock->expects($this->never())->method('andWhere'); $this->queryBuilderMock->expects($this->never())->method('setParameter'); diff --git a/api/tests/Security/Core/UserProviderTest.php b/api/tests/Security/Core/UserProviderTest.php index 36e738628..f887f7aaf 100644 --- a/api/tests/Security/Core/UserProviderTest.php +++ b/api/tests/Security/Core/UserProviderTest.php @@ -17,7 +17,7 @@ final class UserProviderTest extends TestCase { - private MockObject|ManagerRegistry $registryMock; + private ManagerRegistry|MockObject $registryMock; private MockObject|ObjectManager $managerMock; private MockObject|UserRepository $repositoryMock; private MockObject|User $userMock; @@ -33,17 +33,26 @@ protected function setUp(): void $this->provider = new UserProvider($this->registryMock, $this->repositoryMock); } - public function testItDoesNotSupportAnInvalidClass(): void + /** + * @test + */ + public function itDoesNotSupportAnInvalidClass(): void { $this->assertFalse($this->provider->supportsClass(\stdClass::class)); } - public function testItSupportsAValidClass(): void + /** + * @test + */ + public function itSupportsAValidClass(): void { $this->assertTrue($this->provider->supportsClass(User::class)); } - public function testItCannotRefreshAnInvalidObject(): void + /** + * @test + */ + public function itCannotRefreshAnInvalidObject(): void { $this->expectException(UnsupportedUserException::class); @@ -52,32 +61,40 @@ public function testItCannotRefreshAnInvalidObject(): void ->expects($this->once()) ->method('getManagerForClass') ->with($objectMock::class) - ->willReturn(null); + ->willReturn(null) + ; $this->provider->refreshUser($objectMock); } - public function testItRefreshesAValidObject(): void + /** + * @test + */ + public function itRefreshesAValidObject(): void { $objectMock = $this->createMock(UserInterface::class); $this->registryMock ->expects($this->once()) ->method('getManagerForClass') ->with($objectMock::class) - ->willReturn($this->managerMock); + ->willReturn($this->managerMock) + ; $this->managerMock ->expects($this->once()) ->method('refresh') ->with($objectMock) - ->willReturn($this->managerMock); + ->willReturn($this->managerMock) + ; $this->assertSame($objectMock, $this->provider->refreshUser($objectMock)); } /** * @dataProvider getInvalidAttributes + * + * @test */ - public function testItCannotLoadUserIfAttributeIsMissing(array $attributes): void + public function itCannotLoadUserIfAttributeIsMissing(array $attributes): void { $this->expectException(UnsupportedUserException::class); @@ -85,13 +102,14 @@ public function testItCannotLoadUserIfAttributeIsMissing(array $attributes): voi ->expects($this->once()) ->method('findOneBy') ->with(['email' => 'john.doe@example.com']) - ->willReturn($this->userMock); + ->willReturn($this->userMock) + ; $this->repositoryMock->expects($this->never())->method('save'); $this->provider->loadUserByIdentifier('john.doe@example.com', $attributes); } - public function getInvalidAttributes(): iterable + public static function getInvalidAttributes(): iterable { yield 'missing sub' => [[]]; yield 'missing given_name' => [[ @@ -103,17 +121,22 @@ public function getInvalidAttributes(): iterable ]]; } - public function testItLoadsUserFromAttributes(): void + /** + * @test + */ + public function itLoadsUserFromAttributes(): void { $this->repositoryMock ->expects($this->once()) ->method('findOneBy') ->with(['email' => 'john.doe@example.com']) - ->willReturn($this->userMock); + ->willReturn($this->userMock) + ; $this->repositoryMock ->expects($this->once()) ->method('save') - ->with($this->userMock); + ->with($this->userMock) + ; $this->assertSame($this->userMock, $this->provider->loadUserByIdentifier('john.doe@example.com', [ 'sub' => 'ba86c94b-efeb-4452-a0b4-93ed3c889156', @@ -122,7 +145,10 @@ public function testItLoadsUserFromAttributes(): void ])); } - public function testItCreatesAUserFromAttributes(): void + /** + * @test + */ + public function itCreatesAUserFromAttributes(): void { $expectedUser = new User(); $expectedUser->firstName = 'John'; @@ -134,11 +160,13 @@ public function testItCreatesAUserFromAttributes(): void ->expects($this->once()) ->method('findOneBy') ->with(['email' => 'john.doe@example.com']) - ->willReturn(null); + ->willReturn(null) + ; $this->repositoryMock ->expects($this->once()) ->method('save') - ->with($expectedUser); + ->with($expectedUser) + ; $this->assertEquals($expectedUser, $this->provider->loadUserByIdentifier('john.doe@example.com', [ 'sub' => 'ba86c94b-efeb-4452-a0b4-93ed3c889156', diff --git a/api/tests/Serializer/BookNormalizerTest.php b/api/tests/Serializer/BookNormalizerTest.php index 4192c27fc..3a3a37b08 100644 --- a/api/tests/Serializer/BookNormalizerTest.php +++ b/api/tests/Serializer/BookNormalizerTest.php @@ -19,7 +19,7 @@ final class BookNormalizerTest extends TestCase private MockObject|NormalizerInterface $normalizerMock; private MockObject|RouterInterface $routerMock; private MockObject|ReviewRepository $repositoryMock; - private MockObject|Book $objectMock; + private Book|MockObject $objectMock; private BookNormalizer $normalizer; protected function setUp(): void @@ -33,22 +33,34 @@ protected function setUp(): void $this->normalizer->setNormalizer($this->normalizerMock); } - public function testItDoesNotSupportInvalidObjectClass(): void + /** + * @test + */ + public function itDoesNotSupportInvalidObjectClass(): void { $this->assertFalse($this->normalizer->supportsNormalization(new \stdClass())); } - public function testItDoesNotSupportInvalidContext(): void + /** + * @test + */ + public function itDoesNotSupportInvalidContext(): void { $this->assertFalse($this->normalizer->supportsNormalization($this->objectMock, null, [BookNormalizer::class => true])); } - public function testItSupportsValidObjectClassAndContext(): void + /** + * @test + */ + public function itSupportsValidObjectClassAndContext(): void { $this->assertTrue($this->normalizer->supportsNormalization($this->objectMock)); } - public function testItNormalizesData(): void + /** + * @test + */ + public function itNormalizesData(): void { $expectedObject = $this->objectMock; $expectedObject->reviews = '/books/a528046c-7ba1-4acc-bff2-b5390ab17d41/reviews'; @@ -57,17 +69,20 @@ public function testItNormalizesData(): void $this->objectMock ->expects($this->once()) ->method('getId') - ->willReturn(Uuid::fromString('a528046c-7ba1-4acc-bff2-b5390ab17d41')); + ->willReturn(Uuid::fromString('a528046c-7ba1-4acc-bff2-b5390ab17d41')) + ; $this->routerMock ->expects($this->once()) ->method('generate') ->with('_api_/books/{bookId}/reviews{._format}_get_collection', ['bookId' => 'a528046c-7ba1-4acc-bff2-b5390ab17d41']) - ->willReturn('/books/a528046c-7ba1-4acc-bff2-b5390ab17d41/reviews'); + ->willReturn('/books/a528046c-7ba1-4acc-bff2-b5390ab17d41/reviews') + ; $this->repositoryMock ->expects($this->once()) ->method('getAverageRating') ->with($this->objectMock) - ->willReturn(3); + ->willReturn(3) + ; $this->normalizerMock ->expects($this->once()) ->method('normalize') @@ -79,7 +94,8 @@ public function testItNormalizesData(): void 'condition' => BookCondition::NewCondition->value, 'reviews' => '/books/a528046c-7ba1-4acc-bff2-b5390ab17d41/reviews', 'rating' => 3, - ]); + ]) + ; $this->assertEquals([ 'book' => 'https://openlibrary.org/books/OL2055137M.json', diff --git a/api/tests/Serializer/IriTransformerNormalizerTest.php b/api/tests/Serializer/IriTransformerNormalizerTest.php index 226c8b538..1020c8c59 100644 --- a/api/tests/Serializer/IriTransformerNormalizerTest.php +++ b/api/tests/Serializer/IriTransformerNormalizerTest.php @@ -17,7 +17,7 @@ final class IriTransformerNormalizerTest extends TestCase { private MockObject|NormalizerInterface $normalizerMock; - private MockObject|IriConverterInterface $iriConverterMock; + private IriConverterInterface|MockObject $iriConverterMock; private MockObject|OperationMetadataFactoryInterface $operationMetadataFactoryMock; private MockObject|Operation $operationMock; private MockObject|\stdClass $objectMock; @@ -37,7 +37,10 @@ protected function setUp(): void $this->normalizer->setNormalizer($this->normalizerMock); } - public function testItDoesNotSupportInvalidData(): void + /** + * @test + */ + public function itDoesNotSupportInvalidData(): void { $this->assertFalse($this->normalizer->supportsNormalization(null)); $this->assertFalse($this->normalizer->supportsNormalization([])); @@ -46,13 +49,19 @@ public function testItDoesNotSupportInvalidData(): void $this->assertFalse($this->normalizer->supportsNormalization(new ArrayCollection([$this->objectMock]))); } - public function testItDoesNotSupportInvalidContext(): void + /** + * @test + */ + public function itDoesNotSupportInvalidContext(): void { $this->assertFalse($this->normalizer->supportsNormalization($this->objectMock)); $this->assertFalse($this->normalizer->supportsNormalization($this->objectMock, null, [IriTransformerNormalizer::class => true])); } - public function testItDoesNotSupportInvalidFormat(): void + /** + * @test + */ + public function itDoesNotSupportInvalidFormat(): void { $this->assertFalse($this->normalizer->supportsNormalization($this->objectMock, null, [ IriTransformerNormalizer::CONTEXT_KEY => [ @@ -71,7 +80,10 @@ public function testItDoesNotSupportInvalidFormat(): void ])); } - public function testItSupportsValidObjectClassAndContext(): void + /** + * @test + */ + public function itSupportsValidObjectClassAndContext(): void { $this->assertTrue($this->normalizer->supportsNormalization($this->objectMock, 'jsonld', [ IriTransformerNormalizer::CONTEXT_KEY => [ @@ -80,7 +92,10 @@ public function testItSupportsValidObjectClassAndContext(): void ])); } - public function testItNormalizesData(): void + /** + * @test + */ + public function itNormalizesData(): void { $this->normalizerMock ->expects($this->once()) @@ -98,7 +113,8 @@ public function testItNormalizesData(): void 'user' => [ '@id' => '/admin/users/b960cf9e-8f1a-4690-8923-623c1d049d41', ], - ]); + ]) + ; $this->operationMetadataFactoryMock ->expects($this->exactly(2)) ->method('create') @@ -109,7 +125,8 @@ public function testItNormalizesData(): void ->willReturnOnConsecutiveCalls( $this->operationMock, $this->operationMock, - ); + ) + ; $this->iriConverterMock ->expects($this->exactly(2)) ->method('getIriFromResource') @@ -120,7 +137,8 @@ public function testItNormalizesData(): void ->willReturnOnConsecutiveCalls( '/books/a528046c-7ba1-4acc-bff2-b5390ab17d41', '/users/b960cf9e-8f1a-4690-8923-623c1d049d41', - ); + ) + ; $this->assertEquals([ 'book' => '/books/a528046c-7ba1-4acc-bff2-b5390ab17d41', diff --git a/api/tests/State/Processor/BookPersistProcessorTest.php b/api/tests/State/Processor/BookPersistProcessorTest.php index bdea381bd..a565ab373 100644 --- a/api/tests/State/Processor/BookPersistProcessorTest.php +++ b/api/tests/State/Processor/BookPersistProcessorTest.php @@ -19,10 +19,10 @@ final class BookPersistProcessorTest extends TestCase { private MockObject|ProcessorInterface $persistProcessorMock; private MockObject|ProcessorInterface $mercureProcessorMock; - private MockObject|HttpClientInterface $clientMock; + private HttpClientInterface|MockObject $clientMock; private MockObject|ResponseInterface $responseMock; - private MockObject|DecoderInterface $decoderMock; - private MockObject|Book $objectMock; + private DecoderInterface|MockObject $decoderMock; + private Book|MockObject $objectMock; private MockObject|Operation $operationMock; private BookPersistProcessor $processor; @@ -45,7 +45,10 @@ protected function setUp(): void ); } - public function testItUpdatesBookDataBeforeSaveAndSendMercureUpdates(): void + /** + * @test + */ + public function itUpdatesBookDataBeforeSaveAndSendMercureUpdates(): void { $expectedData = $this->objectMock; $expectedData->title = 'Foundation'; @@ -70,7 +73,8 @@ public function testItUpdatesBookDataBeforeSaveAndSendMercureUpdates(): void ], ], ) - ->willReturnOnConsecutiveCalls($this->responseMock, $this->responseMock); + ->willReturnOnConsecutiveCalls($this->responseMock, $this->responseMock) + ; $this->responseMock ->expects($this->exactly(2)) ->method('getContent') @@ -84,7 +88,8 @@ public function testItUpdatesBookDataBeforeSaveAndSendMercureUpdates(): void json_encode([ 'name' => 'Dan Simmons', ]), - ); + ) + ; $this->decoderMock ->expects($this->exactly(2)) ->method('decode') @@ -115,12 +120,14 @@ public function testItUpdatesBookDataBeforeSaveAndSendMercureUpdates(): void [ 'name' => 'Dan Simmons', ], - ); + ) + ; $this->persistProcessorMock ->expects($this->once()) ->method('process') ->with($expectedData, $this->operationMock, [], []) - ->willReturn($expectedData); + ->willReturn($expectedData) + ; $this->mercureProcessorMock ->expects($this->exactly(2)) ->method('process') @@ -131,7 +138,8 @@ public function testItUpdatesBookDataBeforeSaveAndSendMercureUpdates(): void ->willReturnOnConsecutiveCalls( $expectedData, $expectedData, - ); + ) + ; $this->assertEquals($expectedData, $this->processor->process($this->objectMock, $this->operationMock)); } diff --git a/api/tests/State/Processor/BookRemoveProcessorTest.php b/api/tests/State/Processor/BookRemoveProcessorTest.php index f0217c6e2..376e7eb34 100644 --- a/api/tests/State/Processor/BookRemoveProcessorTest.php +++ b/api/tests/State/Processor/BookRemoveProcessorTest.php @@ -24,8 +24,8 @@ final class BookRemoveProcessorTest extends TestCase private MockObject|ProcessorInterface $mercureProcessorMock; private MockObject|ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactoryMock; private ResourceMetadataCollection $resourceMetadataCollection; - private MockObject|IriConverterInterface $iriConverterMock; - private MockObject|Book $objectMock; + private IriConverterInterface|MockObject $iriConverterMock; + private Book|MockObject $objectMock; private MockObject|Operation $operationMock; private BookRemoveProcessor $processor; @@ -50,12 +50,16 @@ protected function setUp(): void ); } - public function testItRemovesBookAndSendMercureUpdates(): void + /** + * @test + */ + public function itRemovesBookAndSendMercureUpdates(): void { $this->removeProcessorMock ->expects($this->once()) ->method('process') - ->with($this->objectMock, $this->operationMock, [], []); + ->with($this->objectMock, $this->operationMock, [], []) + ; $this->resourceMetadataCollectionFactoryMock ->expects($this->exactly(2)) ->method('create') @@ -66,7 +70,8 @@ public function testItRemovesBookAndSendMercureUpdates(): void ->willReturnOnConsecutiveCalls( $this->resourceMetadataCollection, $this->resourceMetadataCollection, - ); + ) + ; $this->iriConverterMock ->expects($this->exactly(2)) ->method('getIriFromResource') @@ -77,7 +82,8 @@ public function testItRemovesBookAndSendMercureUpdates(): void ->willReturnOnConsecutiveCalls( '/admin/books/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6', '/books/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6', - ); + ) + ; $this->mercureProcessorMock ->expects($this->exactly(2)) ->method('process') @@ -100,7 +106,8 @@ public function testItRemovesBookAndSendMercureUpdates(): void MercureProcessor::DATA => json_encode(['@id' => '/books/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6']), ], ], - ); + ) + ; $this->processor->process($this->objectMock, $this->operationMock); } diff --git a/api/tests/State/Processor/BookmarkPersistProcessorTest.php b/api/tests/State/Processor/BookmarkPersistProcessorTest.php index cbce69546..20ba1f34a 100644 --- a/api/tests/State/Processor/BookmarkPersistProcessorTest.php +++ b/api/tests/State/Processor/BookmarkPersistProcessorTest.php @@ -20,9 +20,9 @@ final class BookmarkPersistProcessorTest extends TestCase private MockObject|ProcessorInterface $persistProcessorMock; private MockObject|Security $securityMock; private MockObject|User $userMock; - private MockObject|Bookmark $objectMock; + private Bookmark|MockObject $objectMock; private MockObject|Operation $operationMock; - private MockObject|ClockInterface $clockMock; + private ClockInterface|MockObject $clockMock; private BookmarkPersistProcessor $processor; protected function setUp(): void @@ -37,7 +37,10 @@ protected function setUp(): void $this->processor = new BookmarkPersistProcessor($this->persistProcessorMock, $this->securityMock, $this->clockMock); } - public function testItUpdatesBookmarkDataBeforeSave(): void + /** + * @test + */ + public function itUpdatesBookmarkDataBeforeSave(): void { $expectedData = $this->objectMock; $expectedData->user = $this->userMock; @@ -46,12 +49,14 @@ public function testItUpdatesBookmarkDataBeforeSave(): void $this->securityMock ->expects($this->once()) ->method('getUser') - ->willReturn($this->userMock); + ->willReturn($this->userMock) + ; $this->persistProcessorMock ->expects($this->once()) ->method('process') ->with($expectedData, $this->operationMock, [], []) - ->willReturn($expectedData); + ->willReturn($expectedData) + ; $this->assertEquals($expectedData, $this->processor->process($this->objectMock, $this->operationMock)); } diff --git a/api/tests/State/Processor/MercureProcessorTest.php b/api/tests/State/Processor/MercureProcessorTest.php index 8b48947ba..24d1fc1cd 100644 --- a/api/tests/State/Processor/MercureProcessorTest.php +++ b/api/tests/State/Processor/MercureProcessorTest.php @@ -24,11 +24,11 @@ final class MercureProcessorTest extends TestCase { private MockObject|SerializerInterface $serializerMock; private HubRegistry $hubRegistry; - private MockObject|HubInterface $hubMock; - private MockObject|IriConverterInterface $iriConverterMock; + private HubInterface|MockObject $hubMock; + private IriConverterInterface|MockObject $iriConverterMock; private MockObject|ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactoryMock; private ResourceMetadataCollection $resourceMetadataCollection; - private MockObject|Book $objectMock; + private Book|MockObject $objectMock; private MockObject|Operation $operationMock; private MercureProcessor $processor; @@ -55,41 +55,52 @@ protected function setUp(): void ); } - public function testItSendsAMercureUpdate(): void + /** + * @test + */ + public function itSendsAMercureUpdate(): void { $this->resourceMetadataCollectionFactoryMock->expects($this->never())->method('create'); $this->iriConverterMock ->expects($this->once()) ->method('getIriFromResource') ->with($this->objectMock, UrlGeneratorInterface::ABS_URL, $this->operationMock) - ->willReturn('/books/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6'); + ->willReturn('/books/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6') + ; $this->operationMock ->expects($this->once()) ->method('getNormalizationContext') - ->willReturn(null); + ->willReturn(null) + ; $this->serializerMock ->expects($this->once()) ->method('serialize') ->with($this->objectMock, 'jsonld', []) - ->willReturn(json_encode(['foo' => 'bar'])); + ->willReturn(json_encode(['foo' => 'bar'])) + ; $this->hubMock ->expects($this->once()) ->method('publish') ->with($this->equalTo(new Update( topics: ['/books/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6'], data: json_encode(['foo' => 'bar']), - ))); + ))) + ; $this->processor->process($this->objectMock, $this->operationMock); } - public function testItSendsAMercureUpdateWithContextOptions(): void + /** + * @test + */ + public function itSendsAMercureUpdateWithContextOptions(): void { $this->resourceMetadataCollectionFactoryMock ->expects($this->once()) ->method('create') ->with($this->objectMock::class) - ->willReturn($this->resourceMetadataCollection); + ->willReturn($this->resourceMetadataCollection) + ; $this->iriConverterMock->expects($this->never())->method('getIriFromResource'); $this->operationMock->expects($this->never())->method('getNormalizationContext'); $this->serializerMock->expects($this->never())->method('serialize'); @@ -99,7 +110,8 @@ public function testItSendsAMercureUpdateWithContextOptions(): void ->with($this->equalTo(new Update( topics: ['/admin/books/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6'], data: json_encode(['bar' => 'baz']), - ))); + ))) + ; $this->processor->process($this->objectMock, $this->operationMock, [], [ 'item_uri_template' => '/admin/books/{id}{._format}', diff --git a/api/tests/State/Processor/ReviewPersistProcessorTest.php b/api/tests/State/Processor/ReviewPersistProcessorTest.php index 41ca5706e..09644c73d 100644 --- a/api/tests/State/Processor/ReviewPersistProcessorTest.php +++ b/api/tests/State/Processor/ReviewPersistProcessorTest.php @@ -23,7 +23,7 @@ final class ReviewPersistProcessorTest extends TestCase private MockObject|Security $securityMock; private MockObject|User $userMock; private MockObject|Review $objectMock; - private MockObject|ClockInterface $clockMock; + private ClockInterface|MockObject $clockMock; private ReviewPersistProcessor $processor; protected function setUp(): void @@ -43,7 +43,10 @@ protected function setUp(): void ); } - public function testItUpdatesReviewDataFromOperationBeforeSaveAndSendMercureUpdates(): void + /** + * @test + */ + public function itUpdatesReviewDataFromOperationBeforeSaveAndSendMercureUpdates(): void { $operation = new Post(); @@ -54,12 +57,14 @@ public function testItUpdatesReviewDataFromOperationBeforeSaveAndSendMercureUpda $this->securityMock ->expects($this->once()) ->method('getUser') - ->willReturn($this->userMock); + ->willReturn($this->userMock) + ; $this->persistProcessorMock ->expects($this->once()) ->method('process') ->with($expectedData, $operation, [], []) - ->willReturn($expectedData); + ->willReturn($expectedData) + ; $this->mercureProcessorMock ->expects($this->exactly(2)) ->method('process') @@ -70,12 +75,16 @@ public function testItUpdatesReviewDataFromOperationBeforeSaveAndSendMercureUpda ->willReturnOnConsecutiveCalls( $expectedData, $expectedData, - ); + ) + ; $this->assertEquals($expectedData, $this->processor->process($this->objectMock, $operation)); } - public function testItUpdatesReviewDataFromContextBeforeSaveAndSendMercureUpdates(): void + /** + * @test + */ + public function itUpdatesReviewDataFromContextBeforeSaveAndSendMercureUpdates(): void { $operation = $this->createMock(Operation::class); @@ -91,12 +100,14 @@ public function testItUpdatesReviewDataFromContextBeforeSaveAndSendMercureUpdate $this->securityMock ->expects($this->never()) - ->method('getUser'); + ->method('getUser') + ; $this->persistProcessorMock ->expects($this->once()) ->method('process') ->with($expectedData, $operation, [], $context) - ->willReturn($expectedData); + ->willReturn($expectedData) + ; $this->mercureProcessorMock ->expects($this->exactly(2)) ->method('process') @@ -107,7 +118,8 @@ public function testItUpdatesReviewDataFromContextBeforeSaveAndSendMercureUpdate ->willReturnOnConsecutiveCalls( $expectedData, $expectedData, - ); + ) + ; $this->assertEquals($expectedData, $this->processor->process($this->objectMock, $operation, [], $context)); } diff --git a/api/tests/State/Processor/ReviewRemoveProcessorTest.php b/api/tests/State/Processor/ReviewRemoveProcessorTest.php index 12dc38928..cb7b43fbb 100644 --- a/api/tests/State/Processor/ReviewRemoveProcessorTest.php +++ b/api/tests/State/Processor/ReviewRemoveProcessorTest.php @@ -24,7 +24,7 @@ final class ReviewRemoveProcessorTest extends TestCase private MockObject|ProcessorInterface $mercureProcessorMock; private MockObject|ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactoryMock; private ResourceMetadataCollection $resourceMetadataCollection; - private MockObject|IriConverterInterface $iriConverterMock; + private IriConverterInterface|MockObject $iriConverterMock; private MockObject|Review $objectMock; private MockObject|Operation $operationMock; private ReviewRemoveProcessor $processor; @@ -50,12 +50,16 @@ protected function setUp(): void ); } - public function testItRemovesBookAndSendMercureUpdates(): void + /** + * @test + */ + public function itRemovesBookAndSendMercureUpdates(): void { $this->removeProcessorMock ->expects($this->once()) ->method('process') - ->with($this->objectMock, $this->operationMock, [], []); + ->with($this->objectMock, $this->operationMock, [], []) + ; $this->resourceMetadataCollectionFactoryMock ->expects($this->exactly(2)) ->method('create') @@ -66,7 +70,8 @@ public function testItRemovesBookAndSendMercureUpdates(): void ->willReturnOnConsecutiveCalls( $this->resourceMetadataCollection, $this->resourceMetadataCollection, - ); + ) + ; $this->iriConverterMock ->expects($this->exactly(2)) ->method('getIriFromResource') @@ -77,7 +82,8 @@ public function testItRemovesBookAndSendMercureUpdates(): void ->willReturnOnConsecutiveCalls( '/admin/reviews/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6', '/books/8ad70d36-abaf-4c9b-aeaa-7ec63e6ca6f3/reviews/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6', - ); + ) + ; $this->mercureProcessorMock ->expects($this->exactly(2)) ->method('process') @@ -100,7 +106,8 @@ public function testItRemovesBookAndSendMercureUpdates(): void MercureProcessor::DATA => json_encode(['@id' => '/books/8ad70d36-abaf-4c9b-aeaa-7ec63e6ca6f3/reviews/9aff4b91-31cf-4e91-94b0-1d52bbe23fe6']), ], ], - ); + ) + ; $this->processor->process($this->objectMock, $this->operationMock); } diff --git a/api/tests/bootstrap.php b/api/tests/bootstrap.php index 3181151d9..56a892dc7 100644 --- a/api/tests/bootstrap.php +++ b/api/tests/bootstrap.php @@ -1,13 +1,15 @@ bootEnv(dirname(__DIR__).'/.env'); + (new Dotenv())->bootEnv(dirname(__DIR__) . '/.env'); } if ($_SERVER['APP_DEBUG']) {