From 579d5284b612a615eb641b9537d5992d0d93d9d8 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Tue, 18 Jun 2024 16:38:14 +0200 Subject: [PATCH] refs #451. Testing hardwareType --- config/api_platform/HardwareType.yaml | 31 +++++ config/services.yaml | 5 + src/Dto/Input/HardwareInput.php | 8 +- src/Dto/Input/HardwareTypeInput.php | 35 ++++++ src/Dto/Output/HardwareOutput.php | 4 +- src/Dto/Output/HardwareTypeOutput.php | 21 ++++ src/Factory/HardwareTypeFactory.php | 76 ++++++++++++ src/State/Processor/HardwareTypeProcessor.php | 77 ++++++++++++ src/State/Provider/HardwareTypeProvider.php | 78 ++++++++++++ tests/Functional/HardwareTypeTest.php | 117 ++++++++++++++++++ 10 files changed, 446 insertions(+), 6 deletions(-) create mode 100644 config/api_platform/HardwareType.yaml create mode 100644 src/Dto/Input/HardwareTypeInput.php create mode 100644 src/Dto/Output/HardwareTypeOutput.php create mode 100644 src/Factory/HardwareTypeFactory.php create mode 100644 src/State/Processor/HardwareTypeProcessor.php create mode 100644 src/State/Provider/HardwareTypeProvider.php create mode 100644 tests/Functional/HardwareTypeTest.php diff --git a/config/api_platform/HardwareType.yaml b/config/api_platform/HardwareType.yaml new file mode 100644 index 0000000..3223e15 --- /dev/null +++ b/config/api_platform/HardwareType.yaml @@ -0,0 +1,31 @@ +resources: + App\Entity\HardwareType: + processor: App\State\Processor\HardwareTypeProcessor + input: App\Dto\Input\HardwareTypeInput + output: App\Dto\Output\HardwareTypeOutput + normalization_context: + groups: ['default', 'hardware-type:read'] + denormalization_context: + groups: ['hardware-type:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\HardwareTypeProvider + filters: + - 'api_platform.filter.hardware_type.order' + - 'api_platform.filter.hardware_type.search' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\HardwareTypeProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\HardwareTypeProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\HardwareTypeProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + +properties: + App\Entity\HardwareType: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index e842f55..f454029 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -66,6 +66,11 @@ services: $itemProvider: '@api_platform.doctrine.orm.state.item_provider' App\State\Provider\OperativeSystemProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\HardwareTypeProvider: bind: $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' $itemProvider: '@api_platform.doctrine.orm.state.item_provider' \ No newline at end of file diff --git a/src/Dto/Input/HardwareInput.php b/src/Dto/Input/HardwareInput.php index f46117a..0e41d38 100644 --- a/src/Dto/Input/HardwareInput.php +++ b/src/Dto/Input/HardwareInput.php @@ -3,6 +3,7 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; +use App\Dto\Output\HardwareTypeOutput; use App\Entity\Hardware; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -20,8 +21,7 @@ final class HardwareInput #[Groups(['hardware:write'])] #[ApiProperty(description: 'The type of the hardware', example: "Server")] - public ?string $type = null; - + public ?HardwareTypeOutput $type = null; public function __construct(?Hardware $hardware = null) { @@ -31,7 +31,7 @@ final class HardwareInput $this->name = $hardware->getName(); $this->description = $hardware->getDescription(); - $this->type = $hardware->getType(); + $this->type = new HardwareTypeOutput($hardware->getType()); } public function createOrUpdateEntity(?Hardware $hardware = null): Hardware @@ -42,7 +42,7 @@ final class HardwareInput $hardware->setName($this->name); $hardware->setDescription($this->description); - $hardware->setType($this->type); + $hardware->setType($this->type->getEntity()); return $hardware; } diff --git a/src/Dto/Input/HardwareTypeInput.php b/src/Dto/Input/HardwareTypeInput.php new file mode 100644 index 0000000..8279a6f --- /dev/null +++ b/src/Dto/Input/HardwareTypeInput.php @@ -0,0 +1,35 @@ +name = $hardwareType->getName(); + } + + public function createOrUpdateEntity(?HardwareType $hardwareType = null): HardwareType + { + if (!$hardwareType) { + $hardwareType = new HardwareType(); + } + + $hardwareType->setName($this->name); + + return $hardwareType; + } + +} \ No newline at end of file diff --git a/src/Dto/Output/HardwareOutput.php b/src/Dto/Output/HardwareOutput.php index 262cd6d..ae879d1 100644 --- a/src/Dto/Output/HardwareOutput.php +++ b/src/Dto/Output/HardwareOutput.php @@ -16,7 +16,7 @@ final class HardwareOutput extends AbstractOutput public ?string $description = ''; #[Groups(['hardware:read'])] - public ?string $type = ''; + public ?HardwareTypeOutput $type = null; #[Groups(['hardware:read'])] public \DateTime $createAt; @@ -30,7 +30,7 @@ final class HardwareOutput extends AbstractOutput $this->name = $hardware->getName(); $this->description = $hardware->getDescription(); - $this->type = $hardware->getType(); + $this->type = new HardwareTypeOutput($hardware->getType()); $this->createAt = $hardware->getCreatedAt(); $this->createBy = $hardware->getCreatedBy(); } diff --git a/src/Dto/Output/HardwareTypeOutput.php b/src/Dto/Output/HardwareTypeOutput.php new file mode 100644 index 0000000..29516b0 --- /dev/null +++ b/src/Dto/Output/HardwareTypeOutput.php @@ -0,0 +1,21 @@ +name = $hardwareType->getName(); + } +} \ No newline at end of file diff --git a/src/Factory/HardwareTypeFactory.php b/src/Factory/HardwareTypeFactory.php new file mode 100644 index 0000000..b307824 --- /dev/null +++ b/src/Factory/HardwareTypeFactory.php @@ -0,0 +1,76 @@ + + * + * @method HardwareType|Proxy create(array|callable $attributes = []) + * @method static HardwareType|Proxy createOne(array $attributes = []) + * @method static HardwareType|Proxy find(object|array|mixed $criteria) + * @method static HardwareType|Proxy findOrCreate(array $attributes) + * @method static HardwareType|Proxy first(string $sortedField = 'id') + * @method static HardwareType|Proxy last(string $sortedField = 'id') + * @method static HardwareType|Proxy random(array $attributes = []) + * @method static HardwareType|Proxy randomOrCreate(array $attributes = []) + * @method static HardwareTypeRepository|ProxyRepositoryDecorator repository() + * @method static HardwareType[]|Proxy[] all() + * @method static HardwareType[]|Proxy[] createMany(int $number, array|callable $attributes = []) + * @method static HardwareType[]|Proxy[] createSequence(iterable|callable $sequence) + * @method static HardwareType[]|Proxy[] findBy(array $attributes) + * @method static HardwareType[]|Proxy[] randomRange(int $min, int $max, array $attributes = []) + * @method static HardwareType[]|Proxy[] randomSet(int $number, array $attributes = []) + */ +final class HardwareTypeFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + public static function class(): string + { + return HardwareType::class; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'createdAt' => self::faker()->dateTime(), + 'name' => self::faker()->text(255), + 'updatedAt' => self::faker()->dateTime(), + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(HardwareType $hardwareType): void {}) + ; + } + + protected static function getClass(): string + { + return HardwareType::class; + } +} diff --git a/src/State/Processor/HardwareTypeProcessor.php b/src/State/Processor/HardwareTypeProcessor.php new file mode 100644 index 0000000..1da80bb --- /dev/null +++ b/src/State/Processor/HardwareTypeProcessor.php @@ -0,0 +1,77 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): HardwareTypeOutput + { + if (!($data instanceof HardwareTypeInput)) { + throw new \Exception(sprintf('data is not instance of %s', MenuInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->hardwareTypeRepository->findOneByUuid($uriVariables['uuid']); + } + + $hardwareType = $data->createOrUpdateEntity($entity); + $this->validator->validate($hardwareType); + $this->hardwareTypeRepository->save($hardwareType); + + return new HardwareTypeOutput($hardwareType); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->hardwareTypeRepository->findOneByUuid($uriVariables['uuid']); + $this->hardwareTypeRepository->delete($user); + + return null; + } +} diff --git a/src/State/Provider/HardwareTypeProvider.php b/src/State/Provider/HardwareTypeProvider.php new file mode 100644 index 0000000..891097d --- /dev/null +++ b/src/State/Provider/HardwareTypeProvider.php @@ -0,0 +1,78 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new HardwareTypeOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('Operative system not found'); + } + + return new HardwareTypeOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new HardwareTypeInput($item) : null; + } + + return new HardwareTypeInput(); + } +} diff --git a/tests/Functional/HardwareTypeTest.php b/tests/Functional/HardwareTypeTest.php new file mode 100644 index 0000000..21526bc --- /dev/null +++ b/tests/Functional/HardwareTypeTest.php @@ -0,0 +1,117 @@ + self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + HardwareTypeFactory::createMany(10); + + $this->createClientWithCredentials()->request('GET', '/hardware-types'); + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/HardwareType', + '@id' => '/hardware-types', + '@type' => 'hydra:Collection', + 'hydra:totalItems' => 10, + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testCreateHardwareType(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + $this->createClientWithCredentials()->request('POST', '/hardware-types',['json' => [ + 'name' => self::HW_TYPE_CREATE, + ]]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/HardwareTypeOutput', + '@type' => 'HardwareType', + 'name' => self::HW_TYPE_CREATE + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testUpdateHardwareType(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + HardwareTypeFactory::createOne(['name' => self::HW_TYPE_CREATE]); + $iri = $this->findIriBy(HardwareType::class, ['name' => self::HW_TYPE_CREATE]); + + $this->createClientWithCredentials()->request('PUT', $iri, ['json' => [ + 'name' => self::HW_TYPE_UPDATE, + ]]); + + $this->assertResponseIsSuccessful(); + $this->assertJsonContains([ + '@id' => $iri, + 'name' => self::HW_TYPE_UPDATE, + ]); + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + */ + public function testDeleteHardwareType(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + HardwareTypeFactory::createOne(['name' => self::HW_TYPE_DELETE]); + $iri = $this->findIriBy(HardwareType::class, ['name' => self::HW_TYPE_DELETE]); + + $this->createClientWithCredentials()->request('DELETE', $iri); + $this->assertResponseStatusCodeSame(204); + $this->assertNull( + static::getContainer()->get('doctrine')->getRepository(HardwareType::class)->findOneBy(['name' => self::HW_TYPE_DELETE]) + ); + } +} \ No newline at end of file