diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8378612..6c9a4c8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,14 +19,19 @@ jobs: - name: Cache Composer packages id: composer-cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: vendor key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-php- + restore-keys: ${{ runner.os }}-php- + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + - name: Install dependencies run: composer install --prefer-dist --no-progress - name: Run test suite - run: composer run-script test + run: composer run-script tests diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index ec7792f..ae7bd6a 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -5,31 +5,31 @@ return (new PhpCsFixer\Config()) ->setRules([ - '@PSR2' => true, - 'array_syntax' => ['syntax' => 'short'], - 'concat_space' => ['spacing' => 'one'], - 'new_with_braces' => true, - 'no_blank_lines_after_phpdoc' => true, - 'no_empty_phpdoc' => true, - 'no_empty_comment' => true, - 'no_leading_import_slash' => true, - 'no_trailing_comma_in_singleline_array' => true, - 'no_unused_imports' => true, - 'ordered_imports' => ['imports_order' => null, 'sort_algorithm' => 'alpha'], - 'phpdoc_add_missing_param_annotation' => ['only_untyped' => true], - 'phpdoc_align' => true, - 'phpdoc_no_empty_return' => true, - 'phpdoc_order' => true, - 'phpdoc_scalar' => true, - 'phpdoc_to_comment' => true, - 'psr_autoloading' => true, - 'return_type_declaration' => ['space_before' => 'none'], - 'single_blank_line_before_namespace' => true, - 'single_quote' => true, - 'space_after_semicolon' => true, - 'ternary_operator_spaces' => true, - 'trailing_comma_in_multiline' => true, - 'trim_array_spaces' => true, - 'whitespace_after_comma_in_array' => true, + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'concat_space' => ['spacing' => 'one'], + 'new_with_parentheses' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_empty_phpdoc' => true, + 'no_empty_comment' => true, + 'no_leading_import_slash' => true, + 'no_trailing_comma_in_singleline' => true, + 'no_unused_imports' => true, + 'ordered_imports' => ['imports_order' => null, 'sort_algorithm' => 'alpha'], + 'phpdoc_add_missing_param_annotation' => ['only_untyped' => true], + 'phpdoc_align' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_order' => true, + 'phpdoc_scalar' => true, + 'phpdoc_to_comment' => true, + 'psr_autoloading' => true, + 'return_type_declaration' => ['space_before' => 'none'], + 'blank_lines_before_namespace' => true, + 'single_quote' => true, + 'space_after_semicolon' => true, + 'ternary_operator_spaces' => true, + 'trailing_comma_in_multiline' => true, + 'trim_array_spaces' => true, + 'whitespace_after_comma_in_array' => true, ]) ->setFinder($finder); diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..15d00e6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1 @@ +FROM composer:2.2 \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 119f260..0000000 --- a/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -.PHONY: tests -tests: - docker-compose run composer run test - -.PHONY: debug -debug: - docker-compose run --entrypoint=bash composer - -.PHONY: update-dependencies -update-dependencies: - docker-compose run composer update - -.PHONY: checkstyle -checkstyle: - docker-compose run composer run checkstyle - -.PHONY: fix-checkstyle -fix-checkstyle: - docker-compose run composer run fix-checkstyle diff --git a/composer.json b/composer.json index c4c424c..8dab5f2 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,8 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.9", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.8", + "phpunit/phpunit": "^11.0", + "rector/rector": "^2.0", "squizlabs/php_codesniffer": "^3.7", "mockery/mockery": "^1.5" }, @@ -34,27 +34,27 @@ }, "autoload-dev": { "psr-4": { - "Softonic\\GraphQL\\Test\\": "tests/" + "Softonic\\GraphQL\\": "tests/" } }, "bin": [ "bin/graphql-client" ], "scripts": { - "test": [ + "tests": [ "@checkstyle", "@phpunit" ], - "phpunit": "phpunit --coverage-text", + "phpunit": "phpunit", "checkstyle": [ - "php-cs-fixer fix -v --diff --dry-run --allow-risky=yes", - "rector --dry-run" + "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run --allow-risky=yes", + "rector process" ], - "fix-checkstyle": [ + "fix-cs": [ "@php-cs-fixer", "@rector" ], - "php-cs-fixer": "php-cs-fixer fix -v --diff --allow-risky=yes", - "rector": "rector" + "php-cs-fixer": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --allow-risky=yes", + "rector": "rector process" } } diff --git a/docker-compose.yml b/docker-compose.yml index 2f0b2bb..f621e10 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,49 @@ version: '3.8' services: - composer: + php: + build: + context: . + dockerfile: Dockerfile volumes: - - ./:/app - image: softonic/composer-rector:latest + - ./:/app + + install: + build: + context: . + dockerfile: Dockerfile + volumes: + - ./:/app + command: composer install + + update: + build: + context: . + dockerfile: Dockerfile + volumes: + - ./:/app + command: composer update + + phpunit: + build: + context: . + dockerfile: Dockerfile + volumes: + - ./:/app + command: composer phpunit + + tests: + build: + context: . + dockerfile: Dockerfile + volumes: + - ./:/app + command: composer run tests + + fix-cs: + build: + context: . + dockerfile: Dockerfile + volumes: + - ./:/app + command: composer run fix-cs diff --git a/phpunit.xml b/phpunit.xml index 5e6c2bc..8512c56 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,15 +1,14 @@ - + @@ -17,17 +16,6 @@ - - - src - - - - - - - - diff --git a/rector.php b/rector.php index ab89018..f9c4e07 100644 --- a/rector.php +++ b/rector.php @@ -2,24 +2,49 @@ declare(strict_types=1); -use Rector\Set\ValueObject\SetList; +use Rector\CodeQuality\Rector\Class_\CompleteDynamicPropertiesRector; +use Rector\CodingStyle\Rector\Catch_\CatchExceptionNameMatchingTypeRector; +use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector; use Rector\Config\RectorConfig; +use Rector\EarlyReturn\Rector\Return_\ReturnBinaryOrToEarlyReturnRector; +use Rector\PHPUnit\Set\PHPUnitSetList; +use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector; +use Rector\TypeDeclaration\Rector\ArrowFunction\AddArrowFunctionReturnTypeRector; +use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictTypedCallRector; -return static function (RectorConfig $containerConfigurator): void { - // get parameters - $parameters = $containerConfigurator->parameters(); - - // Define what rule sets will be applied - $containerConfigurator->import(SetList::DEAD_CODE); - $containerConfigurator->import(SetList::PHP_80); - $containerConfigurator->import(SetList::TYPE_DECLARATION_STRICT); - $containerConfigurator->import(SetList::TYPE_DECLARATION); - $containerConfigurator->import(SetList::EARLY_RETURN); - $containerConfigurator->import(SetList::PRIVATIZATION); - - // get services (needed for register a single rule) - // $services = $containerConfigurator->services(); - - // register a single rule - // $services->set(TypedPropertyRector::class); -}; +return RectorConfig::configure() + ->withSkip( + [ + // CodeQuality + CompleteDynamicPropertiesRector::class, + DisallowedEmptyRuleFixerRector::class, + // CodingStyle + CatchExceptionNameMatchingTypeRector::class, + EncapsedStringsToSprintfRector::class, + // EarlyReturn + ReturnBinaryOrToEarlyReturnRector::class, + // TypeDeclaration + AddArrowFunctionReturnTypeRector::class, + ReturnTypeFromStrictTypedCallRector::class, + ] + ) + ->withAutoloadPaths([__DIR__ . '/vendor/autoload.php']) + ->withPaths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + ->withImportNames() + ->withPhpSets(php83: true) + ->withSets( + [ + PHPUnitSetList::PHPUNIT_100, + PHPUnitSetList::PHPUNIT_110, + ] + ) + ->withPreparedSets( + deadCode: true, + codeQuality: true, + codingStyle: true, + typeDeclarations: true, + earlyReturn: true + ); diff --git a/src/Client.php b/src/Client.php index 89a28af..a09b258 100644 --- a/src/Client.php +++ b/src/Client.php @@ -4,29 +4,19 @@ use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\TransferException; +use RuntimeException; use Softonic\GraphQL\DataObjects\Mutation\MutationObject; +use UnexpectedValueException; class Client { - /** - * @var ClientInterface - */ - private $httpClient; - - /** - * @var ResponseBuilder - */ - private $responseBuilder; - - public function __construct(ClientInterface $httpClient, ResponseBuilder $responseBuilder) + public function __construct(private ClientInterface $httpClient, private ResponseBuilder $responseBuilder) { - $this->httpClient = $httpClient; - $this->responseBuilder = $responseBuilder; } /** - * @throws \UnexpectedValueException When response body is not a valid json - * @throws \RuntimeException When there are transfer errors + * @throws UnexpectedValueException When response body is not a valid json + * @throws RuntimeException When there are transfer errors */ public function query(string $query, ?array $variables = null): Response { @@ -34,15 +24,15 @@ public function query(string $query, ?array $variables = null): Response } /** - * @throws \UnexpectedValueException When response body is not a valid json - * @throws \RuntimeException When there are transfer errors + * @throws UnexpectedValueException When response body is not a valid json + * @throws RuntimeException When there are transfer errors */ public function mutate(string $query, MutationObject $mutation): Response { return $this->executeQuery($query, $mutation); } - private function executeQuery(string $query, $variables): Response + private function executeQuery(string $query, array|null|MutationObject $variables): Response { $body = ['query' => $query]; if (!is_null($variables)) { @@ -59,7 +49,7 @@ private function executeQuery(string $query, $variables): Response try { $response = $this->httpClient->request('POST', '', $options); } catch (TransferException $e) { - throw new \RuntimeException('Network Error.' . $e->getMessage(), 0, $e); + throw new RuntimeException('Network Error.' . $e->getMessage(), 0, $e); } return $this->responseBuilder->build($response); diff --git a/src/ClientBuilder.php b/src/ClientBuilder.php index fc166e2..e4b8c3e 100644 --- a/src/ClientBuilder.php +++ b/src/ClientBuilder.php @@ -11,9 +11,9 @@ public static function build(string $endpoint, array $guzzleOptions = []): Clien { $guzzleOptions = array_merge(['base_uri' => $endpoint], $guzzleOptions); - return new \Softonic\GraphQL\Client( + return new Client( new \GuzzleHttp\Client($guzzleOptions), - new \Softonic\GraphQL\ResponseBuilder(new \Softonic\GraphQL\DataObjectBuilder()) + new ResponseBuilder(new DataObjectBuilder()) ); } @@ -27,14 +27,14 @@ public static function buildWithOAuth2Provider( $guzzleOptions = array_merge(['base_uri' => $endpoint], $guzzleOptions); - return new \Softonic\GraphQL\Client( + return new Client( \Softonic\OAuth2\Guzzle\Middleware\ClientBuilder::build( $oauthProvider, $tokenOptions, $cache, $guzzleOptions ), - new \Softonic\GraphQL\ResponseBuilder(new \Softonic\GraphQL\DataObjectBuilder()) + new ResponseBuilder(new DataObjectBuilder()) ); } } diff --git a/src/Config/MutationsConfig.php b/src/Config/MutationsConfig.php index 16522f8..d33d662 100644 --- a/src/Config/MutationsConfig.php +++ b/src/Config/MutationsConfig.php @@ -4,10 +4,7 @@ class MutationsConfig { - /** - * @var array - */ - private $mutationsConfig = []; + private array $mutationsConfig = []; public function __construct(array $config) { diff --git a/src/Console/Mutation/GenerateConfig.php b/src/Console/Mutation/GenerateConfig.php index 330d14c..69f36ed 100644 --- a/src/Console/Mutation/GenerateConfig.php +++ b/src/Console/Mutation/GenerateConfig.php @@ -71,7 +71,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } - private function checkArguments(InputInterface $input, OutputInterface $output) + private function checkArguments(InputInterface $input, OutputInterface $output): bool { $jsonPath = $input->getArgument('instrospection-result'); @@ -84,7 +84,7 @@ private function checkArguments(InputInterface $input, OutputInterface $output) return true; } - private function generateConfig(StdClass $jsonSchema, string $mutation) + private function generateConfig(StdClass $jsonSchema, string $mutation): array { foreach ($jsonSchema->data->__schema->types as $type) { if ($type->name === 'Mutation' && $type->fields[0]->name === $mutation) { @@ -105,7 +105,7 @@ private function generateConfig(StdClass $jsonSchema, string $mutation) ]; } - private function getTypeFromField($field) + private function getTypeFromField($field): array { $isCollection = false; $type = $field->type; @@ -114,6 +114,7 @@ private function getTypeFromField($field) if ($type->kind === self::LIST) { $isCollection = true; } + $type = $type->ofType; } @@ -130,7 +131,7 @@ private function getTypeFromField($field) ]; } - private function getMutationConfig(array $graphqlTypes, $inputType, $parentLinksTo = ''): array + private function getMutationConfig(array $graphqlTypes, $inputType, string $parentLinksTo = ''): array { $children = []; foreach ($graphqlTypes as $graphqlType) { @@ -147,7 +148,7 @@ private function getMutationConfig(array $graphqlTypes, $inputType, $parentLinks } // Avoid cyclic relations to define infinite configs. - if ($this->isFieldPreviouslyAdded($inputFieldType, $inputField, $parentLinksTo)) { + if ($this->isFieldPreviouslyAdded($inputFieldType, $parentLinksTo)) { continue; } @@ -159,6 +160,7 @@ private function getMutationConfig(array $graphqlTypes, $inputType, $parentLinks $isCollection ); } + break; } } @@ -166,7 +168,7 @@ private function getMutationConfig(array $graphqlTypes, $inputType, $parentLinks return $children; } - private function isFieldPreviouslyAdded($inputType, $inputField, string $linksTo): bool + private function isFieldPreviouslyAdded($inputType, string $linksTo): bool { $linksParts = explode('.', $linksTo); for ($i=1, $iMax = count($linksParts); $i<= $iMax; $i++) { @@ -187,8 +189,8 @@ private function getFieldInfo( array $graphqlTypes, $graphqlType, $inputFieldName, - $parentLinksTo, - $isCollection + string $parentLinksTo, + bool $isCollection ): array { if ($this->fromSameMutation) { return $this->defineConfigLinkedInputType( @@ -224,7 +226,7 @@ private function getQueryTypeFromInputType($inputType): string return preg_replace('/Input$/', '', $inputType); } - private function queryTypeExists(string $queryType, $types): bool + private function queryTypeExists(string $queryType, array $types): bool { foreach ($types as $type) { if ($type->name === $queryType) { diff --git a/src/Console/Mutation/GetIntrospection.php b/src/Console/Mutation/GetIntrospection.php index 62eaadc..a4dd1d6 100644 --- a/src/Console/Mutation/GetIntrospection.php +++ b/src/Console/Mutation/GetIntrospection.php @@ -17,7 +17,7 @@ protected function configure() 'to generate the needed file to generate the config.'); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln( <<<'GQL' diff --git a/src/DataObjectBuilder.php b/src/DataObjectBuilder.php index f3a7c54..8bdda1d 100644 --- a/src/DataObjectBuilder.php +++ b/src/DataObjectBuilder.php @@ -39,7 +39,7 @@ private function build(array $data, array $objects): array foreach ($data as $key => $value) { if (is_array($value)) { if ($this->isAList($value)) { - if (empty($value) || is_array($value[0])) { + if ($value === [] || is_array($value[0])) { $items = []; foreach ($value as $objectData) { $itemData = $this->build($objectData, $objects); diff --git a/src/DataObjects/AbstractCollection.php b/src/DataObjects/AbstractCollection.php index 982fbdc..f81eb3e 100644 --- a/src/DataObjects/AbstractCollection.php +++ b/src/DataObjects/AbstractCollection.php @@ -2,6 +2,7 @@ namespace Softonic\GraphQL\DataObjects; +use ArrayAccess; use IteratorAggregate; use RecursiveIteratorIterator; use Softonic\GraphQL\DataObjects\Mutation\MutationObject; @@ -9,7 +10,7 @@ use Softonic\GraphQL\Exceptions\InaccessibleArgumentException; use Softonic\GraphQL\Traits\CollectionArrayAccess; -abstract class AbstractCollection extends AbstractObject implements IteratorAggregate, \ArrayAccess +abstract class AbstractCollection extends AbstractObject implements IteratorAggregate, ArrayAccess { use CollectionArrayAccess; @@ -50,7 +51,7 @@ public function isEmpty(): bool public function __get(string $key): AbstractCollection { - if (empty($this->arguments)) { + if ($this->arguments === []) { throw InaccessibleArgumentException::fromEmptyArguments($key); } @@ -119,9 +120,9 @@ private function filterItems(array $arguments, array $filters): array { $filteredItems = array_filter( $arguments, - function ($item) use ($filters) { + function ($item) use ($filters): bool { foreach ($filters as $filterKey => $filterValue) { - if (!($item->{$filterKey} == $filterValue)) { + if ($item->{$filterKey} != $filterValue) { return false; } } diff --git a/src/DataObjects/AbstractItem.php b/src/DataObjects/AbstractItem.php index 775b74c..7242a4e 100644 --- a/src/DataObjects/AbstractItem.php +++ b/src/DataObjects/AbstractItem.php @@ -2,12 +2,13 @@ namespace Softonic\GraphQL\DataObjects; +use Iterator; use JsonSerializable; use Softonic\GraphQL\DataObjects\Interfaces\DataObject; use Softonic\GraphQL\DataObjects\Mutation\FilteredCollection; use Softonic\GraphQL\Traits\ItemIterator; -abstract class AbstractItem extends AbstractObject implements \Iterator +abstract class AbstractItem extends AbstractObject implements Iterator { use ItemIterator; @@ -20,7 +21,7 @@ public function has(string $key): bool return false; } - if (empty($keyPath)) { + if ($keyPath === []) { return true; } @@ -35,7 +36,7 @@ public function has(string $key): bool public function __get(string $key) { - return array_key_exists($key, $this->arguments) ? $this->arguments[$key] : null; + return $this->arguments[$key] ?? null; } public function __set(string $key, $value): void @@ -50,7 +51,7 @@ public function equals(array $data): bool public function isEmpty(): bool { - return empty($this->arguments); + return $this->arguments === []; } public function jsonSerialize(): array diff --git a/src/DataObjects/AbstractObject.php b/src/DataObjects/AbstractObject.php index a8f6543..e0453c2 100644 --- a/src/DataObjects/AbstractObject.php +++ b/src/DataObjects/AbstractObject.php @@ -7,14 +7,8 @@ abstract class AbstractObject implements JsonSerializable, DataObject { - /** - * @var array - */ - protected $arguments; - - public function __construct(array $arguments = []) + public function __construct(protected array $arguments = []) { - $this->arguments = $arguments; } public function toArray(): array diff --git a/src/DataObjects/CollectionIterator.php b/src/DataObjects/CollectionIterator.php index 1944749..ca8b3a6 100644 --- a/src/DataObjects/CollectionIterator.php +++ b/src/DataObjects/CollectionIterator.php @@ -2,6 +2,7 @@ namespace Softonic\GraphQL\DataObjects; +use InvalidArgumentException; use RecursiveArrayIterator; class CollectionIterator extends RecursiveArrayIterator @@ -39,7 +40,7 @@ public function hasChildren(): bool return $current->hasChildren(); } - throw new \InvalidArgumentException("Collections only can contain Items or other Collection, instead '$current' value found"); + throw new InvalidArgumentException("Collections only can contain Items or other Collection, instead '{$current}' value found"); } public function getChildren(): ?RecursiveArrayIterator diff --git a/src/DataObjects/Mutation/FilteredCollection.php b/src/DataObjects/Mutation/FilteredCollection.php index 910ca49..0703620 100644 --- a/src/DataObjects/Mutation/FilteredCollection.php +++ b/src/DataObjects/Mutation/FilteredCollection.php @@ -9,21 +9,14 @@ class FilteredCollection extends AbstractCollection implements MutationObject { use MutationObjectHandler; - /** - * @var array - */ - protected $config; - /** * @var bool */ protected $hasChanged = false; - public function __construct(array $arguments = [], array $config = [], bool $hasChanged = false) + public function __construct(array $arguments = [], protected array $config = [], bool $hasChanged = false) { parent::__construct($arguments); - - $this->config = $config; $this->hasChanged = $hasChanged; } @@ -67,12 +60,12 @@ public function remove(Item $item): bool return false; } - protected function buildFilteredCollection($items) + protected function buildFilteredCollection($items): FilteredCollection { return new FilteredCollection($items, $this->config); } - protected function buildSubCollection(array $items, string $key) + protected function buildSubCollection(array $items, string $key): Collection { return new Collection($items, $this->config[$key]->children); } diff --git a/src/DataObjects/Mutation/Item.php b/src/DataObjects/Mutation/Item.php index 9f8a406..a01c94a 100644 --- a/src/DataObjects/Mutation/Item.php +++ b/src/DataObjects/Mutation/Item.php @@ -9,21 +9,14 @@ class Item extends AbstractItem implements MutationObject { use MutationObjectHandler; - /** - * @var array - */ - protected $config; - /** * @var bool */ private $hasChanged = false; - public function __construct(array $arguments = [], array $config = [], bool $hasChanged = false) + public function __construct(array $arguments = [], protected array $config = [], bool $hasChanged = false) { parent::__construct($arguments); - - $this->config = $config; $this->hasChanged = $hasChanged; } diff --git a/src/DataObjects/Query/Collection.php b/src/DataObjects/Query/Collection.php index ed75ae0..70343b1 100644 --- a/src/DataObjects/Query/Collection.php +++ b/src/DataObjects/Query/Collection.php @@ -20,12 +20,12 @@ public function jsonSerialize(): array return $items; } - protected function buildFilteredCollection($items) + protected function buildFilteredCollection($items): Collection { return new Collection($items); } - protected function buildSubCollection(array $items, string $key) + protected function buildSubCollection(array $items, string $key): Collection { return new Collection($items); } diff --git a/src/Exceptions/InaccessibleArgumentException.php b/src/Exceptions/InaccessibleArgumentException.php index 09a8446..29c282e 100644 --- a/src/Exceptions/InaccessibleArgumentException.php +++ b/src/Exceptions/InaccessibleArgumentException.php @@ -2,10 +2,12 @@ namespace Softonic\GraphQL\Exceptions; -class InaccessibleArgumentException extends \RuntimeException +use RuntimeException; + +class InaccessibleArgumentException extends RuntimeException { public static function fromEmptyArguments(string $key): InaccessibleArgumentException { - return new self("You cannot access a non existing collection '$key'"); + return new self("You cannot access a non existing collection '{$key}'"); } } diff --git a/src/Mutation.php b/src/Mutation.php index 4ff86d8..90a2bca 100644 --- a/src/Mutation.php +++ b/src/Mutation.php @@ -13,15 +13,9 @@ class Mutation { const SOURCE_ROOT_PATH = '.'; - /** - * @var array - */ - private static $config; + private static ?array $config = null; - /** - * @var bool - */ - private static $hasChanged; + private static ?bool $hasChanged = null; /** * @var MutationTypeConfig @@ -79,7 +73,11 @@ private static function generateMutationArguments(QueryItem $source, string $pat continue; } - if (self::hasChildrenToMutate($childConfig, $sourceValue)) { + if (self::hasChildrenToMutate($childConfig)) { + if (is_null($sourceValue)) { + continue; + } + $mutatedChild = self::mutateChild($childConfig, $sourceValue, $childPath); if (!is_null($mutatedChild)) { $arguments[$sourceKey] = $mutatedChild; @@ -88,6 +86,7 @@ private static function generateMutationArguments(QueryItem $source, string $pat if ($sourceValue instanceof QueryObject) { $sourceValue = $sourceValue->toArray(); } + $arguments[$sourceKey] = $sourceValue; } } @@ -100,9 +99,9 @@ private static function createPathFromParent(string $parent, string $child): str return ('.' === $parent) ? ".{$child}" : "{$parent}.{$child}"; } - private static function hasChildrenToMutate(MutationTypeConfig $childConfig, $sourceValue): bool + private static function hasChildrenToMutate(MutationTypeConfig $childConfig): bool { - return !is_null($childConfig->type) && !is_null($sourceValue); + return !is_null($childConfig->type); } private static function mutateChild( @@ -122,7 +121,7 @@ private static function mutateChild( } } - if (empty($arguments)) { + if ($arguments === []) { return null; } diff --git a/src/Response.php b/src/Response.php index 33c33b4..c4b1b7c 100644 --- a/src/Response.php +++ b/src/Response.php @@ -4,26 +4,8 @@ class Response { - /** - * @var array - */ - private $data; - - /** - * @var array - */ - private $errors; - - /** - * @var array - */ - private $dataObject; - - public function __construct(array $data, array $errors = [], array $dataObject = []) + public function __construct(private array $data, private array $errors = [], private array $dataObject = []) { - $this->data = $data; - $this->errors = $errors; - $this->dataObject = $dataObject; } public function getData(): array @@ -38,7 +20,7 @@ public function getErrors(): array public function hasErrors(): bool { - return !empty($this->errors); + return $this->errors !== []; } public function getDataObject(): array diff --git a/src/ResponseBuilder.php b/src/ResponseBuilder.php index cf385e4..2e498ac 100644 --- a/src/ResponseBuilder.php +++ b/src/ResponseBuilder.php @@ -3,17 +3,15 @@ namespace Softonic\GraphQL; use Psr\Http\Message\ResponseInterface; +use UnexpectedValueException; class ResponseBuilder { - private $dataObjectBuilder; - - public function __construct(?DataObjectBuilder $dataObjectBuilder = null) + public function __construct(private ?DataObjectBuilder $dataObjectBuilder = null) { - $this->dataObjectBuilder = $dataObjectBuilder; } - public function build(ResponseInterface $httpResponse) + public function build(ResponseInterface $httpResponse): Response { $body = $httpResponse->getBody(); @@ -30,12 +28,12 @@ public function build(ResponseInterface $httpResponse) ); } - private function getNormalizedResponse(string $body) + private function getNormalizedResponse(string $body): array { $decodedResponse = $this->getJsonDecodedResponse($body); if (false === array_key_exists('data', $decodedResponse) && empty($decodedResponse['errors'])) { - throw new \UnexpectedValueException( + throw new UnexpectedValueException( 'Invalid GraphQL JSON response. Response body: ' . json_encode($decodedResponse) ); } @@ -58,7 +56,7 @@ private function getJsonDecodedResponse(string $body) $error = json_last_error(); if (JSON_ERROR_NONE !== $error) { - throw new \UnexpectedValueException( + throw new UnexpectedValueException( 'Invalid JSON response. Response body: ' . $body ); } diff --git a/src/Traits/CollectionArrayAccess.php b/src/Traits/CollectionArrayAccess.php index 413a115..8adb0db 100644 --- a/src/Traits/CollectionArrayAccess.php +++ b/src/Traits/CollectionArrayAccess.php @@ -2,11 +2,13 @@ namespace Softonic\GraphQL\Traits; +use BadMethodCallException; + trait CollectionArrayAccess { public function offsetSet($offset, $value): void { - throw new \BadMethodCallException('Try using add() instead'); + throw new BadMethodCallException('Try using add() instead'); } public function offsetExists($offset): bool @@ -16,7 +18,7 @@ public function offsetExists($offset): bool public function offsetUnset($offset): void { - throw new \BadMethodCallException('Try using remove() instead'); + throw new BadMethodCallException('Try using remove() instead'); } public function offsetGet($offset): mixed diff --git a/src/Traits/JsonPathAccessor.php b/src/Traits/JsonPathAccessor.php index 475958c..f25709c 100644 --- a/src/Traits/JsonPathAccessor.php +++ b/src/Traits/JsonPathAccessor.php @@ -6,7 +6,7 @@ trait JsonPathAccessor { public function get(string $path) { - if ($path == '.') { + if ($path === '.') { return $this; } @@ -21,8 +21,8 @@ public function get(string $path) */ $value = $this->hasChild($attribute) ? $this->children[$attribute] : $this->{$attribute}; - if (!empty($attributes)) { - $value = $value->get('.' . implode('.', $attributes)); + if ($attributes !== []) { + return $value->get('.' . implode('.', $attributes)); } return $value; diff --git a/tests/ClientBuilderTest.php b/tests/ClientBuilderTest.php index 06f808b..420d7ee 100644 --- a/tests/ClientBuilderTest.php +++ b/tests/ClientBuilderTest.php @@ -9,13 +9,13 @@ class ClientBuilderTest extends TestCase { - public function testBuild() + public function testBuild(): void { $client = ClientBuilder::build('http://foo.bar/qux'); $this->assertInstanceOf(Client::class, $client); } - public function testBuildWithGuzzleOptions() + public function testBuildWithGuzzleOptions(): void { $guzzleOptions = [ 'cookies' => new CookieJar(), @@ -25,7 +25,7 @@ public function testBuildWithGuzzleOptions() $this->assertInstanceOf(Client::class, $client); } - public function testBuildWithOAuth2Provider() + public function testBuildWithOAuth2Provider(): void { $mockCache = $this->createMock(CacheItemPoolInterface::class); $mockProvider = $this->createMock(AbstractProvider::class); @@ -43,7 +43,7 @@ public function testBuildWithOAuth2Provider() $this->assertInstanceOf(Client::class, $client); } - public function testBuildWithOAuth2ProviderAndGuzzleOptions() + public function testBuildWithOAuth2ProviderAndGuzzleOptions(): void { $mockCache = $this->createMock(CacheItemPoolInterface::class); $mockProvider = $this->createMock(AbstractProvider::class); diff --git a/tests/ClientTest.php b/tests/ClientTest.php index a81ee8d..14b8634 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -6,6 +6,7 @@ use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\ServerException; use GuzzleHttp\Exception\TransferException; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -15,11 +16,11 @@ class ClientTest extends TestCase { - private $httpClient; + private MockObject $httpClient; - private $mockGraphqlResponseBuilder; + private MockObject $mockGraphqlResponseBuilder; - private $client; + private Client $client; protected function setUp(): void { @@ -28,7 +29,7 @@ protected function setUp(): void $this->client = new Client($this->httpClient, $this->mockGraphqlResponseBuilder); } - public function testSimpleQueryWhenHasNetworkErrors() + public function testSimpleQueryWhenHasNetworkErrors(): void { $this->httpClient->expects($this->once()) ->method('request') @@ -41,7 +42,7 @@ public function testSimpleQueryWhenHasNetworkErrors() $this->client->query($query); } - private function getSimpleQuery() + private function getSimpleQuery(): string { return <<<'QUERY' { @@ -52,7 +53,7 @@ private function getSimpleQuery() QUERY; } - public function testCanRetrievePreviousExceptionWhenSimpleQueryHasErrors() + public function testCanRetrievePreviousExceptionWhenSimpleQueryHasErrors(): void { $previousException = null; try { @@ -75,7 +76,7 @@ public function testCanRetrievePreviousExceptionWhenSimpleQueryHasErrors() } } - public function testSimpleQueryWhenInvalidJsonIsReceived() + public function testSimpleQueryWhenInvalidJsonIsReceived(): void { $query = $this->getSimpleQuery(); @@ -106,7 +107,7 @@ public function testSimpleQueryWhenInvalidJsonIsReceived() $this->client->query($query); } - public function testSimpleQuery() + public function testSimpleQuery(): void { $mockResponse = $this->createMock(Response::class); $mockHttpResponse = $this->createMock(ResponseInterface::class); @@ -137,7 +138,7 @@ public function testSimpleQuery() $this->assertInstanceOf(Response::class, $response); } - public function testQueryWithVariables() + public function testQueryWithVariables(): void { $mockResponse = $this->createMock(Response::class); $mockHttpResponse = $this->createMock(ResponseInterface::class); @@ -173,7 +174,7 @@ public function testQueryWithVariables() $this->assertInstanceOf(Response::class, $response); } - private function getQueryWithVariables() + private function getQueryWithVariables(): string { return <<<'QUERY' query GetFooBar($idFoo: String, $idBar: String) { @@ -187,7 +188,7 @@ private function getQueryWithVariables() QUERY; } - public function testMutate() + public function testMutate(): void { $mockResponse = $this->createMock(Response::class); $mockHttpResponse = $this->createMock(ResponseInterface::class); @@ -220,7 +221,7 @@ public function testMutate() $this->assertInstanceOf(Response::class, $response); } - private function getMutationQuery() + private function getMutationQuery(): string { return <<<'QUERY' mutation replaceFoo($foo: FooInput!) { diff --git a/tests/Config/MutationsConfigTest.php b/tests/Config/MutationsConfigTest.php index dcd1113..de3a4ca 100644 --- a/tests/Config/MutationsConfigTest.php +++ b/tests/Config/MutationsConfigTest.php @@ -8,7 +8,7 @@ class MutationsConfigTest extends TestCase { - public function testWhenThereIsOneMutationWithOneVariable() + public function testWhenThereIsOneMutationWithOneVariable(): void { $mutationsConfig = new MutationsConfig( [ @@ -54,7 +54,7 @@ public function testWhenThereIsOneMutationWithOneVariable() $this->assertEquals(['book' => $bookConfig], $mutationsConfig->get('ReplaceBook')); } - public function testWhenThereIsOneMutationsWithTwoVariables() + public function testWhenThereIsOneMutationsWithTwoVariables(): void { $mutationsConfig = new MutationsConfig( [ @@ -106,7 +106,7 @@ public function testWhenThereIsOneMutationsWithTwoVariables() $this->assertEquals($expectedMutationConfig, $mutationsConfig->get('ReplaceBook')); } - public function testWhenThereAreTwoMutations() + public function testWhenThereAreTwoMutations(): void { $mutationsConfig = new MutationsConfig( [ diff --git a/tests/ConfigGeneratorTest.php b/tests/ConfigGeneratorTest.php index 4741503..defe1f0 100644 --- a/tests/ConfigGeneratorTest.php +++ b/tests/ConfigGeneratorTest.php @@ -8,7 +8,7 @@ class ConfigGeneratorTest extends TestCase { - public function testGenerateFromQuery() + public function testGenerateFromQuery(): void { $commandTester = new CommandTester(new GenerateConfig()); $commandTester->execute( @@ -23,7 +23,7 @@ public function testGenerateFromQuery() $this->assertSame($expectedOutput, $output); } - public function testGenerateFromMutation() + public function testGenerateFromMutation(): void { $commandTester = new CommandTester(new GenerateConfig()); $commandTester->execute( diff --git a/tests/DataObjectBuilderTest.php b/tests/DataObjectBuilderTest.php index cc3e59c..52cef8d 100644 --- a/tests/DataObjectBuilderTest.php +++ b/tests/DataObjectBuilderTest.php @@ -10,14 +10,14 @@ class DataObjectBuilderTest extends TestCase { - private $builder; + private DataObjectBuilder $builder; protected function setUp(): void { $this->builder = new DataObjectBuilder(); } - public function testWhenDataIsNull() + public function testWhenDataIsNull(): void { $data = [ 'book' => null, @@ -31,7 +31,7 @@ public function testWhenDataIsNull() $this->assertEquals($expectedDataObject, $dataObject); } - public function testWhenDataIsAnEmptyArray() + public function testWhenDataIsAnEmptyArray(): void { $data = [ 'search' => [], @@ -45,7 +45,7 @@ public function testWhenDataIsAnEmptyArray() $this->assertEquals($expectedDataObject, $dataObject); } - public function testWhenDataHasAQueryItem() + public function testWhenDataHasAQueryItem(): void { $data = [ 'book' => [ @@ -69,7 +69,7 @@ public function testWhenDataHasAQueryItem() $this->assertEquals($expectedDataObject, $dataObject); } - public function testWhenDataHasAQueryItemWithAnArrayOfStringsArgument() + public function testWhenDataHasAQueryItemWithAnArrayOfStringsArgument(): void { $data = [ 'book' => [ @@ -95,7 +95,7 @@ public function testWhenDataHasAQueryItemWithAnArrayOfStringsArgument() $this->assertEquals($expectedDataObject, $dataObject); } - public function testWhenDataHasAnArrayOfQueryItems() + public function testWhenDataHasAnArrayOfQueryItems(): void { $data = [ 'search' => [ @@ -137,7 +137,7 @@ public function testWhenDataHasAnArrayOfQueryItems() $this->assertEquals($expectedDataObject, $dataObject); } - public function testWhenDataHasAQueryItemWithEmptySecondLevel() + public function testWhenDataHasAQueryItemWithEmptySecondLevel(): void { $data = [ 'book' => [ @@ -163,7 +163,7 @@ public function testWhenDataHasAQueryItemWithEmptySecondLevel() $this->assertEquals($expectedDataObject, $dataObject); } - public function testWhenDataHasAQueryItemWithSecondLevel() + public function testWhenDataHasAQueryItemWithSecondLevel(): void { $data = [ 'book' => [ @@ -217,7 +217,7 @@ public function testWhenDataHasAQueryItemWithSecondLevel() $this->assertEquals($expectedDataObject, $dataObject); } - public function testWhenDataHasAQueryItemWithThirdLevel() + public function testWhenDataHasAQueryItemWithThirdLevel(): void { $data = [ 'book' => [ @@ -307,7 +307,7 @@ public function testWhenDataHasAQueryItemWithThirdLevel() $this->assertEquals($expectedDataObject, $dataObject); } - public function testWhenDataHasAQueryItemInsideAnotherQueryItem() + public function testWhenDataHasAQueryItemInsideAnotherQueryItem(): void { $data = [ 'book' => [ diff --git a/tests/MutationBuilderTest.php b/tests/MutationBuilderTest.php index 0e23e8b..5e974b8 100644 --- a/tests/MutationBuilderTest.php +++ b/tests/MutationBuilderTest.php @@ -11,25 +11,13 @@ class MutationBuilderTest extends TestCase { - /** - * @var array - */ - private $simpleConfigMock; - - /** - * @var array - */ - private $complexConfigMock; - - /** - * @var array - */ - private $sameQueryStructureConfigMock; - - /** - * @var array - */ - private $collectionConfigMock; + private array $simpleConfigMock; + + private array $complexConfigMock; + + private array $sameQueryStructureConfigMock; + + private array $collectionConfigMock; protected function setUp(): void { @@ -43,7 +31,7 @@ protected function setUp(): void ->get('ReplaceBooks'); } - private function getConfigMock() + private function getConfigMock(): MutationsConfig { return new MutationsConfig( [ @@ -232,7 +220,7 @@ private function getConfigMock() ); } - public function testWhenThereAreOnlyArguments() + public function testWhenThereAreOnlyArguments(): void { $queryItem = new QueryItem( [ @@ -255,7 +243,7 @@ public function testWhenThereAreOnlyArguments() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenThereIsAnEmptyChild() + public function testWhenThereIsAnEmptyChild(): void { $queryItem = new QueryItem( [ @@ -278,7 +266,7 @@ public function testWhenThereIsAnEmptyChild() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenThereAreChildrenWithSimpleConfig() + public function testWhenThereAreChildrenWithSimpleConfig(): void { $queryItem = new QueryItem( [ @@ -336,7 +324,7 @@ public function testWhenThereAreChildrenWithSimpleConfig() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenThereAreChildrenWithComplexConfig() + public function testWhenThereAreChildrenWithComplexConfig(): void { $queryItem = new QueryItem( [ @@ -390,7 +378,7 @@ public function testWhenThereAreChildrenWithComplexConfig() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenThereAreTwoChildren() + public function testWhenThereAreTwoChildren(): void { $queryItem = new QueryItem( [ @@ -472,7 +460,7 @@ public function testWhenThereAreTwoChildren() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenThereIsAThirdLevel() + public function testWhenThereIsAThirdLevel(): void { $queryItem = new QueryItem( [ @@ -611,7 +599,7 @@ public function testWhenThereIsAThirdLevel() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenThereIsAFourthLevel() + public function testWhenThereIsAFourthLevel(): void { $queryItem = new QueryItem( [ @@ -803,7 +791,7 @@ public function testWhenThereIsAFourthLevel() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenTheSourceHasItemsWithItemArguments() + public function testWhenTheSourceHasItemsWithItemArguments(): void { $queryItem = new QueryItem( [ @@ -839,7 +827,7 @@ public function testWhenTheSourceHasItemsWithItemArguments() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenTheSourceHasTheSameStructureThanTheConfig() + public function testWhenTheSourceHasTheSameStructureThanTheConfig(): void { $queryItem = new QueryItem( [ @@ -897,7 +885,7 @@ public function testWhenTheSourceHasTheSameStructureThanTheConfig() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenRootIsACollectionWithoutChildren() + public function testWhenRootIsACollectionWithoutChildren(): void { $queryCollection = new QueryCollection( [ @@ -937,7 +925,7 @@ public function testWhenRootIsACollectionWithoutChildren() $this->assertEquals($expectedMutationArguments, $mutation->jsonSerialize()); } - public function testWhenRootIsACollectionWithChildren() + public function testWhenRootIsACollectionWithChildren(): void { $queryCollection = new QueryCollection( [ diff --git a/tests/MutationTest.php b/tests/MutationTest.php index 92630f2..667f2c1 100644 --- a/tests/MutationTest.php +++ b/tests/MutationTest.php @@ -3,6 +3,7 @@ namespace Softonic\GraphQL; use Error; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; use Softonic\GraphQL\Config\MutationsConfig; use Softonic\GraphQL\DataObjects\Mutation\Collection as MutationCollection; @@ -13,20 +14,11 @@ class MutationTest extends TestCase { - /** - * @var array - */ - private $itemConfigMock; + private array $itemConfigMock; - /** - * @var array - */ - private $sameQueryStructureConfigMock; + private array $sameQueryStructureConfigMock; - /** - * @var array - */ - private $collectionConfigMock; + private array $collectionConfigMock; protected function setUp(): void { @@ -38,7 +30,7 @@ protected function setUp(): void ->get('ReplaceBooks'); } - private function getConfigMock() + private function getConfigMock(): MutationsConfig { return new MutationsConfig([ 'ReplaceBook' => [ @@ -198,7 +190,7 @@ private function getConfigMock() ]); } - public function testIfAnItemHasAnArgument() + public function testIfAnItemHasAnArgument(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -213,7 +205,7 @@ public function testIfAnItemHasAnArgument() $this->assertFalse($mutation->book->has('invalid')); } - public function testWhenThereAreNoChanges() + public function testWhenThereAreNoChanges(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -227,7 +219,7 @@ public function testWhenThereAreNoChanges() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenThereAreChangesInRootLevel() + public function testWhenThereAreChangesInRootLevel(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -249,7 +241,7 @@ public function testWhenThereAreChangesInRootLevel() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenTryingToUpdateAnItemWithTheSameValueItAlreadyHas() + public function testWhenTryingToUpdateAnItemWithTheSameValueItAlreadyHas(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -266,7 +258,7 @@ public function testWhenTryingToUpdateAnItemWithTheSameValueItAlreadyHas() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenThereAreVariousChangesInRootLevelSettingPropertiesNotInRead() + public function testWhenThereAreVariousChangesInRootLevelSettingPropertiesNotInRead(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -290,7 +282,7 @@ public function testWhenThereAreVariousChangesInRootLevelSettingPropertiesNotInR $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenAnArgumentIsUnset() + public function testWhenAnArgumentIsUnset(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -312,7 +304,7 @@ public function testWhenAnArgumentIsUnset() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenThereAreMalformedCollectionsItShouldThrowAnError() + public function testWhenThereAreMalformedCollectionsItShouldThrowAnError(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -325,12 +317,12 @@ public function testWhenThereAreMalformedCollectionsItShouldThrowAnError() ]), ]); - $this->expectException(\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); Mutation::build($this->itemConfigMock, $book); } - public function testWhenThereAreChangesInRootLevelWithSecondLevelInput() + public function testWhenThereAreChangesInRootLevelWithSecondLevelInput(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -364,7 +356,7 @@ public function testWhenThereAreChangesInRootLevelWithSecondLevelInput() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenANewItemIsAddedToACollection() + public function testWhenANewItemIsAddedToACollection(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -412,7 +404,7 @@ public function testWhenANewItemIsAddedToACollection() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenANewItemIsAddedToACollectionNotPresentInTheQuery() + public function testWhenANewItemIsAddedToACollectionNotPresentInTheQuery(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -459,7 +451,7 @@ public function testWhenANewItemIsAddedToACollectionNotPresentInTheQuery() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenChangesAreDoneToAllTheItemsFromACollection() + public function testWhenChangesAreDoneToAllTheItemsFromACollection(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -511,7 +503,7 @@ public function testWhenChangesAreDoneToAllTheItemsFromACollection() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenChangesAreDoneToAllTheItemsFromACollectionWithIncompleteParentDataConfiguration() + public function testWhenChangesAreDoneToAllTheItemsFromACollectionWithIncompleteParentDataConfiguration(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -560,7 +552,7 @@ public function testWhenChangesAreDoneToAllTheItemsFromACollectionWithIncomplete $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenFilteredItemsFromACollectionAreUpdated() + public function testWhenFilteredItemsFromACollectionAreUpdated(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -622,7 +614,7 @@ public function testWhenFilteredItemsFromACollectionAreUpdated() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenAnItemIsAddedAndAFilterIsAppliedToUpdateTheFilteredItemsAndFinallyAnotherItemIsAdded() + public function testWhenAnItemIsAddedAndAFilterIsAppliedToUpdateTheFilteredItemsAndFinallyAnotherItemIsAdded(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -689,7 +681,7 @@ public function testWhenAnItemIsAddedAndAFilterIsAppliedToUpdateTheFilteredItems $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenFilterToUpdateAndAddAnotherItemAndAFilterToUpdate() + public function testWhenFilterToUpdateAndAddAnotherItemAndAFilterToUpdate(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -762,7 +754,7 @@ public function testWhenFilterToUpdateAndAddAnotherItemAndAFilterToUpdate() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenAFilterIsAppliedToUpdateAndAnotherFilteredIsAppliedToUpdateToTheFirstFilteredItems() + public function testWhenAFilterIsAppliedToUpdateAndAnotherFilteredIsAppliedToUpdateToTheFirstFilteredItems(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -828,7 +820,7 @@ public function testWhenAFilterIsAppliedToUpdateAndAnotherFilteredIsAppliedToUpd $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenTwoFiltersAreAppliedToUpdateInSeparateActions() + public function testWhenTwoFiltersAreAppliedToUpdateInSeparateActions(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -901,7 +893,28 @@ public function testWhenTwoFiltersAreAppliedToUpdateInSeparateActions() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testHasMethodForThirdLevelItems() + public function testWhenItemIsNullMutationShouldRemoveTheKey(): void + { + $book = new QueryItem([ + 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', + 'id_author' => 1234, + 'chapters' => null, + ]); + + $mutation = Mutation::build($this->itemConfigMock, $book, true); + + $expectedMutationData = [ + 'book' => [ + 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', + 'id_author' => 1234, + ], + ]; + + $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); + + } + + public function testHasMethodForThirdLevelItems(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -945,7 +958,7 @@ public function testHasMethodForThirdLevelItems() $this->assertFalse($mutation->book->has('chapters.upsert.pages.upsert.has_illustrations.invalid')); } - public function testWhenThirdLevelItemsAreUpdated() + public function testWhenThirdLevelItemsAreUpdated(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1015,7 +1028,7 @@ public function testWhenThirdLevelItemsAreUpdated() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenThirdLevelItemsAreUpdatedForTwoSecondLevelItems() + public function testWhenThirdLevelItemsAreUpdatedForTwoSecondLevelItems(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1127,7 +1140,7 @@ public function testWhenThirdLevelItemsAreUpdatedForTwoSecondLevelItems() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenThirdLevelItemsFilteredAreUpdated() + public function testWhenThirdLevelItemsFilteredAreUpdated(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1253,7 +1266,7 @@ public function testWhenThirdLevelItemsFilteredAreUpdated() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenANewItemIsTriedToBeAddedToAThirdLevelCollectionWhichParentIsNotPresentInTheQuery() + public function testWhenANewItemIsTriedToBeAddedToAThirdLevelCollectionWhichParentIsNotPresentInTheQuery(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1275,7 +1288,7 @@ public function testWhenANewItemIsTriedToBeAddedToAThirdLevelCollectionWhichPare ]); } - public function testWhenANewItemIsTriedToBeAddedToAThirdLevelCollectionWhichParentIsPresentInTheQueryButKeyIsNot() + public function testWhenANewItemIsTriedToBeAddedToAThirdLevelCollectionWhichParentIsPresentInTheQueryButKeyIsNot(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1372,7 +1385,7 @@ public function testWhenANewItemIsTriedToBeAddedToAThirdLevelCollectionWhichPare $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenThirdLevelItemsHaveDifferentUpdates() + public function testWhenThirdLevelItemsHaveDifferentUpdates(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1500,7 +1513,7 @@ public function testWhenThirdLevelItemsHaveDifferentUpdates() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenAnItemIsTriedToBeAddedToAFilteredCollection() + public function testWhenAnItemIsTriedToBeAddedToAFilteredCollection(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1563,7 +1576,7 @@ public function testWhenAnItemIsTriedToBeAddedToAFilteredCollection() ]); } - public function testWhenThirdLevelItemsAreAdded() + public function testWhenThirdLevelItemsAreAdded(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1667,7 +1680,7 @@ public function testWhenThirdLevelItemsAreAdded() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenThirdLevelItemsAreAddedAndThereWereNoneBeforeInTheCollection() + public function testWhenThirdLevelItemsAreAddedAndThereWereNoneBeforeInTheCollection(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1723,7 +1736,7 @@ public function testWhenThirdLevelItemsAreAddedAndThereWereNoneBeforeInTheCollec $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenFourthLevelItemsAreAdded() + public function testWhenFourthLevelItemsAreAdded(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1853,7 +1866,7 @@ public function testWhenFourthLevelItemsAreAdded() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenFourthLevelItemsAreUpdated() + public function testWhenFourthLevelItemsAreUpdated(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -1931,7 +1944,7 @@ public function testWhenFourthLevelItemsAreUpdated() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenFourthLevelItemsAreIterated() + public function testWhenFourthLevelItemsAreIterated(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2051,7 +2064,7 @@ public function testWhenFourthLevelItemsAreIterated() } } - public function testWhenIteratingACollectionAndOneItemIsEmpty() + public function testWhenIteratingACollectionAndOneItemIsEmpty(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2095,7 +2108,7 @@ public function testWhenIteratingACollectionAndOneItemIsEmpty() } } - public function testWhenFourthLevelItemsAreCounted() + public function testWhenFourthLevelItemsAreCounted(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2193,11 +2206,12 @@ public function testWhenFourthLevelItemsAreCounted() foreach ($mutation->book->chapters->upsert->pages->upsert->lines->upsert as $line) { $i++; } + $this->assertEquals(4, $i); $this->assertEquals(4, $mutation->book->chapters->upsert->pages->upsert->lines->upsert->count()); } - public function testWhenCheckIsNotEmpty() + public function testWhenCheckIsNotEmpty(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2280,7 +2294,7 @@ public function testWhenCheckIsNotEmpty() $this->assertFalse($mutation->book->chapters->upsert->pages->upsert->lines->upsert->isEmpty()); } - public function testWhenCheckIsEmpty() + public function testWhenCheckIsEmpty(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2332,7 +2346,7 @@ public function testWhenCheckIsEmpty() $this->assertTrue($mutation->book->chapters->upsert->pages->upsert->lines->upsert->isEmpty()); } - public function testWhenThereAreChangesInARootLevelCollectionForOneItem() + public function testWhenThereAreChangesInARootLevelCollectionForOneItem(): void { $books = new QueryCollection([ new QueryItem([ @@ -2364,7 +2378,7 @@ public function testWhenThereAreChangesInARootLevelCollectionForOneItem() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenSourceContainsMutationData() + public function testWhenSourceContainsMutationData(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2482,7 +2496,7 @@ public function testWhenSourceContainsMutationData() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenFourthLevelItemsPropertyIsUnset() + public function testWhenFourthLevelItemsPropertyIsUnset(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2650,7 +2664,7 @@ public function testWhenFourthLevelItemsPropertyIsUnset() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenFourthLevelItemsExistenceIsChecked() + public function testWhenFourthLevelItemsExistenceIsChecked(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2750,7 +2764,7 @@ public function testWhenFourthLevelItemsExistenceIsChecked() $this->assertFalse($lines->hasItem($itemDataThatDoesNotExist)); } - public function testWhenFourthLevelItemsAreUnset() + public function testWhenFourthLevelItemsAreUnset(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2884,7 +2898,7 @@ public function testWhenFourthLevelItemsAreUnset() $this->assertEquals($expectedMutationData, $mutation->jsonSerialize()); } - public function testWhenFourthLevelItemsAreRemoved() + public function testWhenFourthLevelItemsAreRemoved(): void { $book = new QueryItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', @@ -2964,7 +2978,7 @@ public function testWhenFourthLevelItemsAreRemoved() $mutation = Mutation::build($this->itemConfigMock, $book, true); - foreach ($mutation->book->chapters->upsert->pages->upsert->lines->upsert as $key => $line) { + foreach ($mutation->book->chapters->upsert->pages->upsert->lines->upsert as $line) { if (35 === $line->words_count) { $mutation->book->chapters->upsert->pages->upsert->lines->upsert->remove($line); break; diff --git a/tests/Query/CollectionTest.php b/tests/Query/CollectionTest.php index ccadb31..3f53ad7 100644 --- a/tests/Query/CollectionTest.php +++ b/tests/Query/CollectionTest.php @@ -1,13 +1,17 @@ [ @@ -21,17 +25,14 @@ public function emptyCollectionProvider() ]; } - /** - * @test - * - * @dataProvider emptyCollectionProvider - */ - public function checkEmptyCollection(Collection $collection, bool $isEmpty) + #[DataProvider('emptyCollectionProvider')] + #[Test] + public function checkEmptyCollection(Collection $collection, bool $isEmpty): void { $this->assertSame($isEmpty, $collection->isEmpty()); } - public function filterProvider() + public static function filterProvider(): array { return [ 'Filter matches no item' => [ @@ -117,11 +118,8 @@ public function filterProvider() /** * @dataProvider filterProvider - * - * @param array $filters - * @param Collection $expectedResult */ - public function testFilter(array $filters, Collection $expectedResult) + public function testFilter(array $filters, Collection $expectedResult): void { $books = new Collection( [ @@ -154,7 +152,7 @@ public function testFilter(array $filters, Collection $expectedResult) $this->assertEquals($expectedResult, $filteredBooks); } - public function testFilterWhenRootIsAnItemAndTheFilterIsInSecondLevel() + public function testFilterWhenRootIsAnItemAndTheFilterIsInSecondLevel(): void { $book = new Item( [ @@ -205,7 +203,7 @@ public function testFilterWhenRootIsAnItemAndTheFilterIsInSecondLevel() $this->assertEquals($expectedResult, $book); } - public function testUniqueLevelToArray() + public function testUniqueLevelToArray(): void { $book = new Item( [ @@ -250,7 +248,7 @@ public function testUniqueLevelToArray() $this->assertEquals($expectedResult, $chapters); } - public function testSiblingsToArray() + public function testSiblingsToArray(): void { $book = new Collection( [ @@ -318,7 +316,7 @@ public function testSiblingsToArray() ); } - public function testItemHas() + public function testItemHas(): void { $book = new Item( [ @@ -333,7 +331,7 @@ public function testItemHas() $this->assertFalse($book->has('invalid')); } - public function testHasMethodForThirdLevelItems() + public function testHasMethodForThirdLevelItems(): void { $book = new Item( [ @@ -386,7 +384,7 @@ public function testHasMethodForThirdLevelItems() $this->assertFalse($book->has('not_existing.invalid')); } - public function testWhenFourthLevelItemsExistenceIsChecked() + public function testWhenFourthLevelItemsExistenceIsChecked(): void { $book = new Item( [ @@ -516,7 +514,7 @@ public function testWhenFourthLevelItemsExistenceIsChecked() $this->assertFalse($lines->hasItem($itemDataThatDoesNotExist)); } - public function testArrayAccessOffsetSetShouldThrowABadMethodCallException() + public function testArrayAccessOffsetSetShouldThrowABadMethodCallException(): void { $book = new Item( [ @@ -546,13 +544,13 @@ public function testArrayAccessOffsetSetShouldThrowABadMethodCallException() ] ); - $this->expectException(\BadMethodCallException::class); + $this->expectException(BadMethodCallException::class); $this->expectExceptionMessage('Try using add() instead'); $book->chapters->name[0] = 'Chapter three'; } - public function testArrayAccessOffsetExists() + public function testArrayAccessOffsetExists(): void { $book = new Item( [ @@ -588,7 +586,7 @@ public function testArrayAccessOffsetExists() $this->assertTrue(empty($book->chapters->name[2])); } - public function testArrayAccessOffsetUnsetShouldThrowABadMethodCallException() + public function testArrayAccessOffsetUnsetShouldThrowABadMethodCallException(): void { $book = new Item( [ @@ -618,13 +616,13 @@ public function testArrayAccessOffsetUnsetShouldThrowABadMethodCallException() ] ); - $this->expectException(\BadMethodCallException::class); + $this->expectException(BadMethodCallException::class); $this->expectExceptionMessage('Try using remove() instead'); unset($book->chapters->name[0]); } - public function testArrayAccessOffsetGet() + public function testArrayAccessOffsetGet(): void { $book = new Item( [ diff --git a/tests/ResponseBuilderTest.php b/tests/ResponseBuilderTest.php index d7e3c8a..b983f6c 100644 --- a/tests/ResponseBuilderTest.php +++ b/tests/ResponseBuilderTest.php @@ -3,6 +3,8 @@ namespace Softonic\GraphQL; use GuzzleHttp\Psr7\BufferStream; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; @@ -10,9 +12,9 @@ class ResponseBuilderTest extends TestCase { - private $dataObjectBuilder; + private MockObject $dataObjectBuilder; - private $responseBuilder; + private ResponseBuilder $responseBuilder; protected function setUp(): void { @@ -21,7 +23,7 @@ protected function setUp(): void $this->responseBuilder = new ResponseBuilder($this->dataObjectBuilder); } - public function testBuildMalformedResponse() + public function testBuildMalformedResponse(): void { $mockHttpResponse = $this->createMock(ResponseInterface::class); $mockHttpResponse->expects($this->once()) @@ -34,7 +36,7 @@ public function testBuildMalformedResponse() $this->responseBuilder->build($mockHttpResponse); } - public function buildInvalidGraphqlJsonResponseProvider() + public static function buildInvalidGraphqlJsonResponseProvider(): array { return [ 'Invalid structure' => [ @@ -46,10 +48,8 @@ public function buildInvalidGraphqlJsonResponseProvider() ]; } - /** - * @dataProvider buildInvalidGraphqlJsonResponseProvider - */ - public function testBuildInvalidGraphqlJsonResponse(string $body) + #[DataProvider('buildInvalidGraphqlJsonResponseProvider')] + public function testBuildInvalidGraphqlJsonResponse(string $body): void { $mockHttpResponse = $this->createMock(ResponseInterface::class); @@ -63,7 +63,7 @@ public function testBuildInvalidGraphqlJsonResponse(string $body) $this->responseBuilder->build($mockHttpResponse); } - public function testBuildValidGraphqlJsonWithoutErrors() + public function testBuildValidGraphqlJsonWithoutErrors(): void { $mockHttpResponse = $this->createMock(ResponseInterface::class); @@ -88,7 +88,7 @@ public function testBuildValidGraphqlJsonWithoutErrors() $this->assertEquals($dataObjectMock, $response->getDataObject()); } - public function buildValidGraphqlJsonWithErrorsProvider() + public static function buildValidGraphqlJsonWithErrorsProvider(): array { return [ 'Response with null data' => [ @@ -100,10 +100,8 @@ public function buildValidGraphqlJsonWithErrorsProvider() ]; } - /** - * @dataProvider buildValidGraphqlJsonWithErrorsProvider - */ - public function testBuildValidGraphqlJsonWithErrors(string $body) + #[DataProvider('buildValidGraphqlJsonWithErrorsProvider')] + public function testBuildValidGraphqlJsonWithErrors(string $body): void { $mockHttpResponse = $this->createMock(ResponseInterface::class); diff --git a/tests/Traits/JsonPathAccessorTest.php b/tests/Traits/JsonPathAccessorTest.php index 158accb..59e48dc 100644 --- a/tests/Traits/JsonPathAccessorTest.php +++ b/tests/Traits/JsonPathAccessorTest.php @@ -9,14 +9,14 @@ class JsonPathAccessorTest extends TestCase { - public function testWhenRootIsRetrieved() + public function testWhenRootIsRetrieved(): void { $obj = new MutationTypeConfig(); $this->assertSame($obj, $obj->get('.')); } - public function testWhenChildrenAreRetrieved() + public function testWhenChildrenAreRetrieved(): void { $upsertConfig = new MutationTypeConfig(); $upsertConfig->type = Collection::class; @@ -40,7 +40,7 @@ public function testWhenChildrenAreRetrieved() $this->assertEquals($upsertConfig, $bookConfig->get('.chapters.upsert')); } - public function testWhenObjectAttributesAreRetrieved() + public function testWhenObjectAttributesAreRetrieved(): void { $bookConfig = new MutationTypeConfig(); $bookConfig->type = Item::class;