diff --git a/.gitattributes b/.gitattributes index 27d7dee..7d503af 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,5 @@ /.gitattributes export-ignore /.gitignore export-ignore -/.scrutinizer.yml export-ignore -/.travis.yml export-ignore /phpunit.xml.dist export-ignore /fixtures export-ignore /tests export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8be1427 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: CI + +on: [push] + +jobs: + phpunit: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macOS-latest] + php-version: ['7.4'] + name: 'PHPUnit - PHP/${{ matrix.php-version }} - OS/${{ matrix.os }}' + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Setup PHP + uses: shivammathur/setup-php@v1 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, intl + coverage: xdebug + ini-values: xdebug.max_nesting_level=2048 + - name: Get Composer Cache Directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Cache dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + - name: Install Dependencies + run: composer install --no-progress + - name: PHPUnit + run: vendor/bin/phpunit --coverage-clover=coverage.clover + - uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + psalm: + runs-on: ubuntu-latest + strategy: + matrix: + php-version: ['7.4'] + name: 'Psalm - PHP/${{ matrix.php-version }}' + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Setup PHP + uses: shivammathur/setup-php@v1 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, intl + - name: Get Composer Cache Directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Cache dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + - name: Install Dependencies + run: composer install --no-progress + - name: Psalm + run: vendor/bin/psalm --shepherd diff --git a/.gitignore b/.gitignore index 987e2a2..e96516b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ composer.lock vendor +.phpunit.result.cache diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index 202086f..0000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,7 +0,0 @@ -tools: - external_code_coverage: - runs: 2 -filter: - excluded_paths: - - tests/* - - graph.php diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0e4763d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: php -php: - - 7.2 - - 7.3 - - nightly -matrix: - allow_failures: - - php: nightly -before_script: composer install -script: vendor/bin/phpunit --coverage-clover=coverage.clover -after_script: - - if [ "$TRAVIS_PHP_VERSION" != "nightly" ]; then wget https://scrutinizer-ci.com/ocular.phar; fi - - if [ "$TRAVIS_PHP_VERSION" != "nightly" ]; then php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi diff --git a/README.md b/README.md index b045e2c..751c9f2 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,8 @@ # RestClient -| `master` | `develop` | -|----------|-----------| -| [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Innmind/rest-client/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/Innmind/rest-client/?branch=master) | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Innmind/rest-client/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/Innmind/rest-client/?branch=develop) | -| [![Code Coverage](https://scrutinizer-ci.com/g/Innmind/rest-client/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/Innmind/rest-client/?branch=master) | [![Code Coverage](https://scrutinizer-ci.com/g/Innmind/rest-client/badges/coverage.png?b=develop)](https://scrutinizer-ci.com/g/Innmind/rest-client/?branch=develop) | -| [![Build Status](https://scrutinizer-ci.com/g/Innmind/rest-client/badges/build.png?b=master)](https://scrutinizer-ci.com/g/Innmind/rest-client/build-status/master) | [![Build Status](https://scrutinizer-ci.com/g/Innmind/rest-client/badges/build.png?b=develop)](https://scrutinizer-ci.com/g/Innmind/rest-client/build-status/develop) | +[![Build Status](https://github.com/Innmind/rest-client/workflows/CI/badge.svg)](https://github.com/Innmind/rest-client/actions?query=workflow%3ACI) +[![codecov](https://codecov.io/gh/Innmind/rest-client/branch/develop/graph/badge.svg)](https://codecov.io/gh/Innmind/rest-client) +[![Type Coverage](https://shepherd.dev/github/Innmind/rest-client/coverage.svg)](https://shepherd.dev/github/Innmind/rest-client) This library is intended to consume APIs built with the [`RestServer`](https://github.com/Innmind/rest-server). @@ -18,12 +16,16 @@ composer require innmind/rest-client ## Usage ```php +use Innmind\OperatingSystem\Factory; +use Innmind\Url\Path; +use Innmind\UrlResolver\UrlResolver; use function Innmind\Rest\Client\bootstrap; +$os = Factory::build(); $client = bootstrap( - /* instance of Innmind\HttpTransport\Transport */, - /* instance of Innmind\UrlResolver\ResolverInterface */, - /* instance of Innmind\Filesystem\Adapter */ + $os->remote()->http(), + new UrlResolver, + $os->filesystem()->mount(Path::of('/somewhere/to/cache/data')), ); $client diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..b61d75b --- /dev/null +++ b/codecov.yml @@ -0,0 +1,2 @@ +ignore: + - graph.php diff --git a/composer.json b/composer.json index 45e0ecb..48ddc2c 100644 --- a/composer.json +++ b/composer.json @@ -15,13 +15,12 @@ "issues": "http://github.com/Innmind/rest-client/issues" }, "require": { - "php": "~7.2", - "innmind/immutable": "~2.12", + "php": "~7.4", + "innmind/immutable": "~3.5", "innmind/specification": "~2.0", - "innmind/http": "~3.8", - "innmind/filesystem": "~3.0", - "innmind/url-resolver": "~3.0", - "innmind/http-transport": "~4.0", + "innmind/http": "~4.2", + "innmind/operating-system": "~2.0", + "innmind/url-resolver": "~4.0", "willdurand/negotiation": "^2.2", "innmind/json": "^1.1" }, @@ -40,10 +39,9 @@ "test": "vendor/bin/phpunit --colors=always" }, "require-dev": { - "phpunit/phpunit": "~7.0", - "innmind/cli": "^1.5", - "innmind/server-control": "^2.7", - "innmind/server-status": "^1.3", - "innmind/object-graph": "^1.2" + "phpunit/phpunit": "~8.0", + "innmind/cli": "~2.0", + "innmind/object-graph": "~2.0", + "vimeo/psalm": "^3.10" } } diff --git a/graph.php b/graph.php index d90ddc7..1a5c5d9 100644 --- a/graph.php +++ b/graph.php @@ -19,8 +19,7 @@ Visitor\RemoveDependenciesSubGraph, }; use Innmind\Url\{ - UrlInterface, - PathInterface, + Url, Path, }; @@ -39,15 +38,15 @@ protected function main(Environment $env, OperatingSystem $os): void $visualize = new Visualize(new class($env->workingDirectory()) implements LocationRewriter { private $workingDirectory; - public function __construct(PathInterface $workingDirectory) + public function __construct(Path $workingDirectory) { $this->workingDirectory = $workingDirectory; } - public function __invoke(UrlInterface $location): UrlInterface + public function __invoke(Url $location): Url { - return $location->withPath(new Path( - \str_replace((string) $this->workingDirectory, '', (string) $location->path()) + return $location->withPath(Path::of( + \str_replace($this->workingDirectory->toString(), '', $location->path()->toString()) )); } }); diff --git a/graph.svg b/graph.svg index bfbdf24..5ddd4bb 100644 --- a/graph.svg +++ b/graph.svg @@ -1,572 +1,604 @@ - - + G - - + + -object_000000000f18e45f00000000384629db - - -Innmind\Rest\Client\Client\Client +object_0000000047d2d35e000000005b2771cf + + +Innmind\Rest\Client\Client\Client - + -object_000000000f18e44400000000384629db - - -Innmind\Rest\Client\Server\RetryServerFactory +object_0000000047d2d354000000005b2771cf + + +Innmind\Rest\Client\Server\RetryServerFactory - + -object_000000000f18e45f00000000384629db->object_000000000f18e44400000000384629db - - -make +object_0000000047d2d35e000000005b2771cf->object_0000000047d2d354000000005b2771cf + + +make - + -object_000000000f18e44100000000384629db - - -Innmind\Rest\Client\Server\ServerFactory +object_0000000047d2d301000000005b2771cf + + +Innmind\Immutable\Map - + -object_000000000f18e44400000000384629db->object_000000000f18e44100000000384629db - - -make +object_0000000047d2d35e000000005b2771cf->object_0000000047d2d301000000005b2771cf + + +servers - + -object_000000000f18e4e700000000384629db - - -Innmind\HttpTransport\DefaultTransport +object_0000000047d2d355000000005b2771cf + + +Innmind\Rest\Client\Server\ServerFactory - + -object_000000000f18e44100000000384629db->object_000000000f18e4e700000000384629db - - -transport +object_0000000047d2d354000000005b2771cf->object_0000000047d2d355000000005b2771cf + + +make - + -object_000000000f18e4e100000000384629db - - -Innmind\UrlResolver\UrlResolver +object_0000000047d2d3f4000000005b2771cf + + +Innmind\HttpTransport\DefaultTransport - + -object_000000000f18e44100000000384629db->object_000000000f18e4e100000000384629db - - -resolver +object_0000000047d2d355000000005b2771cf->object_0000000047d2d3f4000000005b2771cf + + +transport - + -object_000000000f18e4bc00000000384629db - - -Innmind\Rest\Client\Response\ExtractIdentity +object_0000000047d2d3f0000000005b2771cf + + +Innmind\UrlResolver\UrlResolver - + -object_000000000f18e44100000000384629db->object_000000000f18e4bc00000000384629db - - -extractIdentity +object_0000000047d2d355000000005b2771cf->object_0000000047d2d3f0000000005b2771cf + + +resolver - + -object_000000000f18e4bf00000000384629db - - -Innmind\Rest\Client\Response\ExtractIdentities +object_0000000047d2d34f000000005b2771cf + + +Innmind\Rest\Client\Response\ExtractIdentity - + -object_000000000f18e44100000000384629db->object_000000000f18e4bf00000000384629db - - -extractIdentities +object_0000000047d2d355000000005b2771cf->object_0000000047d2d34f000000005b2771cf + + +extractIdentity - + -object_000000000f18e4b800000000384629db - - -Innmind\Rest\Client\Serializer\Denormalizer\DenormalizeResource +object_0000000047d2d351000000005b2771cf + + +Innmind\Rest\Client\Response\ExtractIdentities - + -object_000000000f18e44100000000384629db->object_000000000f18e4b800000000384629db - - -denormalizeResource +object_0000000047d2d355000000005b2771cf->object_0000000047d2d351000000005b2771cf + + +extractIdentities - + -object_000000000f18e4bb00000000384629db - - -Innmind\Rest\Client\Serializer\Normalizer\NormalizeResource +object_0000000047d2d357000000005b2771cf + + +Innmind\Rest\Client\Serializer\Denormalizer\DenormalizeResource - + -object_000000000f18e44100000000384629db->object_000000000f18e4bb00000000384629db - - -normalizeResource +object_0000000047d2d355000000005b2771cf->object_0000000047d2d357000000005b2771cf + + +denormalizeResource - + -object_000000000f18e45400000000384629db - - -Innmind\Rest\Client\Serializer\Encode\Json +object_0000000047d2d345000000005b2771cf + + +Innmind\Rest\Client\Serializer\Normalizer\NormalizeResource - + -object_000000000f18e44100000000384629db->object_000000000f18e45400000000384629db - - -encode +object_0000000047d2d355000000005b2771cf->object_0000000047d2d345000000005b2771cf + + +normalizeResource - + -object_000000000f18e49a00000000384629db - - -Innmind\Rest\Client\Serializer\Decode\Json +object_0000000047d2d367000000005b2771cf + + +Innmind\Rest\Client\Serializer\Encode\Json - + -object_000000000f18e44100000000384629db->object_000000000f18e49a00000000384629db - - -decode +object_0000000047d2d355000000005b2771cf->object_0000000047d2d367000000005b2771cf + + +encode - + -object_000000000f18e4b200000000384629db - - -Innmind\Rest\Client\Translator\Specification\SpecificationTranslator +object_0000000047d2d3b9000000005b2771cf + + +Innmind\Rest\Client\Serializer\Decode\Json - + -object_000000000f18e44100000000384629db->object_000000000f18e4b200000000384629db - - -translator +object_0000000047d2d355000000005b2771cf->object_0000000047d2d3b9000000005b2771cf + + +decode - + -object_000000000f18e45700000000384629db - - -Innmind\Rest\Client\Formats +object_0000000047d2d370000000005b2771cf + + +Innmind\Rest\Client\Translator\Specification\SpecificationTranslator - + -object_000000000f18e44100000000384629db->object_000000000f18e45700000000384629db - - -formats +object_0000000047d2d355000000005b2771cf->object_0000000047d2d370000000005b2771cf + + +translator - + -object_000000000f18e45900000000384629db - - -Innmind\Rest\Client\Server\Capabilities\RefreshLimitedFactory +object_0000000047d2d371000000005b2771cf + + +Innmind\Rest\Client\Formats - + -object_000000000f18e44100000000384629db->object_000000000f18e45900000000384629db - - -capabilities +object_0000000047d2d355000000005b2771cf->object_0000000047d2d371000000005b2771cf + + +formats - + -object_000000000f18e44800000000384629db - - -Innmind\Rest\Client\Visitor\ResolveIdentity +object_0000000047d2d378000000005b2771cf + + +Innmind\Rest\Client\Server\Capabilities\RefreshLimitedFactory - + -object_000000000f18e4bc00000000384629db->object_000000000f18e44800000000384629db - - -resolveIdentity +object_0000000047d2d355000000005b2771cf->object_0000000047d2d378000000005b2771cf + + +capabilities - - -object_000000000f18e4bf00000000384629db->object_000000000f18e44800000000384629db - - -resolveIdentity - - + -object_000000000f18ee6d00000000384629db - - -ArrayObject +object_0000000047d2d369000000005b2771cf + + +Innmind\Rest\Client\Visitor\ResolveIdentity - + + +object_0000000047d2d34f000000005b2771cf->object_0000000047d2d369000000005b2771cf + + +resolveIdentity + + -object_000000000f18e45700000000384629db->object_000000000f18ee6d00000000384629db - - -formats +object_0000000047d2d351000000005b2771cf->object_0000000047d2d369000000005b2771cf + + +resolveIdentity - + -object_000000000f18e45e00000000384629db - - -Negotiation\Negotiator +object_0000000047d2d36d000000005b2771cf + + +Innmind\Immutable\Map - + -object_000000000f18e45700000000384629db->object_000000000f18e45e00000000384629db - - -negotiator +object_0000000047d2d371000000005b2771cf->object_0000000047d2d36d000000005b2771cf + + +formats - - -object_000000000f18e44e00000000384629db - - -Innmind\Rest\Client\Server\Capabilities\CacheFactory + + +object_0000000047d2d373000000005b2771cf + + +Negotiation\Negotiator - - -object_000000000f18e45900000000384629db->object_000000000f18e44e00000000384629db - - -make - - - -object_000000000f18e44800000000384629db->object_000000000f18e4e100000000384629db - - -resolver + + +object_0000000047d2d371000000005b2771cf->object_0000000047d2d373000000005b2771cf + + +negotiator - - -object_000000000f18ee6a00000000384629db - - -Innmind\Immutable\Pair + + +object_0000000047d2d379000000005b2771cf + + +Innmind\Rest\Client\Server\Capabilities\CacheFactory - - -object_000000000f18ee6d00000000384629db->object_000000000f18ee6a00000000384629db - - -0 + + +object_0000000047d2d378000000005b2771cf->object_0000000047d2d379000000005b2771cf + + +make + + + +object_0000000047d2d369000000005b2771cf->object_0000000047d2d3f0000000005b2771cf + + +resolve - + -object_000000000f18e4ac00000000384629db - - -Innmind\Rest\Client\Format\Format +object_0000000047d2d341000000005b2771cf + + +Innmind\Rest\Client\Format\Format - + -object_000000000f18ee6a00000000384629db->object_000000000f18e4ac00000000384629db - - -value +object_0000000047d2d36d000000005b2771cf->object_0000000047d2d341000000005b2771cf + + +value[0] - + -object_000000000f18efc900000000384629db - - -ArrayObject +object_0000000047d2d358000000005b2771cf + + +Innmind\Immutable\Set - + -object_000000000f18e4ac00000000384629db->object_000000000f18efc900000000384629db - - -types +object_0000000047d2d341000000005b2771cf->object_0000000047d2d358000000005b2771cf + + +types - + -object_000000000f18e4ad00000000384629db - - -Innmind\Rest\Client\Format\MediaType +object_0000000047d2d344000000005b2771cf + + +Innmind\Rest\Client\Format\MediaType - + -object_000000000f18e4ac00000000384629db->object_000000000f18e4ad00000000384629db - - -preferredType +object_0000000047d2d341000000005b2771cf->object_0000000047d2d344000000005b2771cf + + +preferredType + + + +object_0000000047d2d358000000005b2771cf->object_0000000047d2d344000000005b2771cf + + +0 - + -object_000000000f18efc600000000384629db - - -Innmind\Immutable\Pair +object_0000000047d2d363000000005b2771cf + + +Innmind\MediaType\MediaType - - -object_000000000f18efc900000000384629db->object_000000000f18efc600000000384629db - - -0 + + +object_0000000047d2d344000000005b2771cf->object_0000000047d2d363000000005b2771cf + + +mime - + -object_000000000f18e44f00000000384629db - - -Innmind\Filesystem\MediaType\MediaType +object_0000000047d2d34a000000005b2771cf + + +Innmind\Immutable\Set - + -object_000000000f18e4ad00000000384629db->object_000000000f18e44f00000000384629db - - -mime - - - -object_000000000f18efc600000000384629db->object_000000000f18e4ad00000000384629db - - -value +object_0000000047d2d363000000005b2771cf->object_0000000047d2d34a000000005b2771cf + + +topLevels - - -object_000000000f18e44e00000000384629db->object_000000000f18e45400000000384629db - - -encode + + +object_0000000047d2d36c000000005b2771cf + + +Innmind\Immutable\Sequence + - - -object_000000000f18e44e00000000384629db->object_000000000f18e49a00000000384629db - - -decode - - -object_000000000f18e49d00000000384629db - - -Innmind\Filesystem\Adapter\FilesystemAdapter - + + +object_0000000047d2d363000000005b2771cf->object_0000000047d2d36c000000005b2771cf + + +parameters + + +object_0000000047d2d379000000005b2771cf->object_0000000047d2d367000000005b2771cf + + +encode - - -object_000000000f18e44e00000000384629db->object_000000000f18e49d00000000384629db - - -filesystem + + +object_0000000047d2d379000000005b2771cf->object_0000000047d2d3b9000000005b2771cf + + +decode - + -object_000000000f18e46000000000384629db - - -Innmind\Rest\Client\Serializer\Denormalizer\DenormalizeCapabilitiesNames +object_0000000047d2d3b3000000005b2771cf + + +Innmind\Filesystem\Adapter\Filesystem - - -object_000000000f18e44e00000000384629db->object_000000000f18e46000000000384629db - - -denormalizeNames + + +object_0000000047d2d379000000005b2771cf->object_0000000047d2d3b3000000005b2771cf + + +filesystem - + -object_000000000f18e44500000000384629db - - -Innmind\Rest\Client\Serializer\Denormalizer\DenormalizeDefinition +object_0000000047d2d37e000000005b2771cf + + +Innmind\Rest\Client\Serializer\Denormalizer\DenormalizeCapabilitiesNames - + -object_000000000f18e44e00000000384629db->object_000000000f18e44500000000384629db - - -denormalizeDefinition +object_0000000047d2d379000000005b2771cf->object_0000000047d2d37e000000005b2771cf + + +denormalizeNames - + -object_000000000f18e46100000000384629db - - -Innmind\Rest\Client\Serializer\Normalizer\NormalizeDefinition +object_0000000047d2d35d000000005b2771cf + + +Innmind\Rest\Client\Serializer\Denormalizer\DenormalizeDefinition - + -object_000000000f18e44e00000000384629db->object_000000000f18e46100000000384629db - - -normalizeDefinition +object_0000000047d2d379000000005b2771cf->object_0000000047d2d35d000000005b2771cf + + +denormalizeDefinition - + -object_000000000f18e46600000000384629db - - -Innmind\Rest\Client\Server\Capabilities\Factory\Factory +object_0000000047d2d37f000000005b2771cf + + +Innmind\Rest\Client\Serializer\Normalizer\NormalizeDefinition - + -object_000000000f18e44e00000000384629db->object_000000000f18e46600000000384629db - - -make +object_0000000047d2d379000000005b2771cf->object_0000000047d2d37f000000005b2771cf + + +normalizeDefinition - + -object_000000000f18e44c00000000384629db - - -Innmind\Rest\Client\Definition\Types +object_0000000047d2d37c000000005b2771cf + + +Innmind\Rest\Client\Server\Capabilities\Factory\Factory - + -object_000000000f18e44500000000384629db->object_000000000f18e44c00000000384629db - - -build +object_0000000047d2d379000000005b2771cf->object_0000000047d2d37c000000005b2771cf + + +make + + + +object_0000000047d2d372000000005b2771cf + + +Innmind\Rest\Client\Definition\Types + + - + -object_000000000f18e46600000000384629db->object_000000000f18e4e700000000384629db - - -transport +object_0000000047d2d35d000000005b2771cf->object_0000000047d2d372000000005b2771cf + + +build - - -object_000000000f18e46600000000384629db->object_000000000f18e4e100000000384629db - - -resolver + + +object_0000000047d2d37c000000005b2771cf->object_0000000047d2d3f4000000005b2771cf + + +transport - + -object_000000000f18e46600000000384629db->object_000000000f18e45700000000384629db - - -formats +object_0000000047d2d37c000000005b2771cf->object_0000000047d2d3f0000000005b2771cf + + +resolver - - -object_000000000f18e46700000000384629db - - -Innmind\Rest\Client\Server\DefinitionFactory + + +object_0000000047d2d37c000000005b2771cf->object_0000000047d2d371000000005b2771cf + + +formats + + + +object_0000000047d2d37d000000005b2771cf + + +Innmind\Rest\Client\Server\DefinitionFactory - - -object_000000000f18e46600000000384629db->object_000000000f18e46700000000384629db - - -definitionFactory + + +object_0000000047d2d37c000000005b2771cf->object_0000000047d2d37d000000005b2771cf + + +definitionFactory + + + +object_0000000047d2d36a000000005b2771cf + + +Innmind\Immutable\Set + - - -object_000000000f18e46700000000384629db->object_000000000f18e49a00000000384629db - - -decode - - -object_000000000f18e46700000000384629db->object_000000000f18e44500000000384629db - - -denormalize + + +object_0000000047d2d372000000005b2771cf->object_0000000047d2d36a000000005b2771cf + + +defaults + + + +object_0000000047d2d37d000000005b2771cf->object_0000000047d2d3b9000000005b2771cf + + +decode + + + +object_0000000047d2d37d000000005b2771cf->object_0000000047d2d35d000000005b2771cf + + +denormalize diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..617f63d --- /dev/null +++ b/psalm.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/src/Client/Client.php b/src/Client/Client.php index 1ac47ee..6806312 100644 --- a/src/Client/Client.php +++ b/src/Client/Client.php @@ -13,26 +13,28 @@ final class Client implements ClientInterface { - private $make; - private $servers; + private Factory $make; + /** @var Map */ + private Map $servers; public function __construct(Factory $make) { $this->make = $make; - $this->servers = new Map('string', Server::class); + /** @var Map */ + $this->servers = Map::of('string', Server::class); } public function server(string $url): Server { - $url = Url::fromString($url); - $hash = \md5((string) $url); + $url = Url::of($url); + $hash = \md5($url->toString()); if ($this->servers->contains($hash)) { return $this->servers->get($hash); } $server = ($this->make)($url); - $this->servers = $this->servers->put($hash, $server); + $this->servers = ($this->servers)($hash, $server); return $server; } diff --git a/src/Definition/Access.php b/src/Definition/Access.php index 20a19ff..90e52a7 100644 --- a/src/Definition/Access.php +++ b/src/Definition/Access.php @@ -3,22 +3,21 @@ namespace Innmind\Rest\Client\Definition; -use Innmind\Immutable\{ - SetInterface, - Set, -}; +use Innmind\Immutable\Set; +use function Innmind\Immutable\unwrap; final class Access { - const READ = 'READ'; - const CREATE = 'CREATE'; - const UPDATE = 'UPDATE'; + public const READ = 'READ'; + public const CREATE = 'CREATE'; + public const UPDATE = 'UPDATE'; - private $mask; + /** @var Set */ + private Set $mask; public function __construct(string ...$mask) { - $this->mask = Set::of('string', ...$mask); + $this->mask = Set::strings(...$mask); } public function isReadable(): bool @@ -37,16 +36,16 @@ public function isUpdatable(): bool } /** - * @return SetInterface + * @return Set */ - public function mask(): SetInterface + public function mask(): Set { return $this->mask; } public function matches(self $mask): bool { - foreach ($mask->mask() as $access) { + foreach (unwrap($mask->mask()) as $access) { if (!$this->mask->contains($access)) { return false; } diff --git a/src/Definition/AllowedLink.php b/src/Definition/AllowedLink.php index eed6641..26e17c7 100644 --- a/src/Definition/AllowedLink.php +++ b/src/Definition/AllowedLink.php @@ -4,22 +4,25 @@ namespace Innmind\Rest\Client\Definition; use Innmind\Rest\Client\Link; -use Innmind\Immutable\SetInterface; +use Innmind\Immutable\Set; +use function Innmind\Immutable\assertSet; final class AllowedLink { - private $resourcePath; - private $relationship; - private $parameters; + private string $resourcePath; + private string $relationship; + /** @var Set */ + private Set $parameters; + /** + * @param Set $parameters + */ public function __construct( string $resourcePath, string $relationship, - SetInterface $parameters + Set $parameters ) { - if ((string) $parameters->type() !== 'string') { - throw new \TypeError('Argument 3 must be of type SetInterface'); - } + assertSet('string', $parameters, 3); $this->resourcePath = $resourcePath; $this->relationship = $relationship; @@ -37,9 +40,9 @@ public function relationship(): string } /** - * @return SetInterface + * @return Set */ - public function parameters(): SetInterface + public function parameters(): Set { return $this->parameters; } @@ -58,7 +61,7 @@ public function allows(Link $link): bool true, static function(bool $accept, string $parameter) use ($link): bool { return $accept && $link->parameters()->contains($parameter); - } + }, ); } } diff --git a/src/Definition/HttpResource.php b/src/Definition/HttpResource.php index b0319bd..48c9d65 100644 --- a/src/Definition/HttpResource.php +++ b/src/Definition/HttpResource.php @@ -7,59 +7,51 @@ Link, Exception\DomainException, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\Immutable\{ - MapInterface, - SetInterface, + Map, + Set, Str, }; +use function Innmind\Immutable\{ + assertMap, + assertSet, +}; final class HttpResource { - private $name; - private $url; - private $identity; - private $properties; - private $metas; - private $links; - private $rangeable; + private string $name; + private Url $url; + private Identity $identity; + /** @var Map */ + private Map $properties; + /** @var Map */ + private Map $metas; + /** @var Set */ + private Set $links; + private bool $rangeable; + /** + * @param Map $properties + * @param Map $metas + * @param Set $links + */ public function __construct( string $name, - UrlInterface $url, + Url $url, Identity $identity, - MapInterface $properties, - MapInterface $metas, - SetInterface $links, + Map $properties, + Map $metas, + Set $links, bool $rangeable ) { if (Str::of($name)->empty()) { throw new DomainException; } - if ( - (string) $properties->keyType() !== 'string' || - (string) $properties->valueType() !== Property::class - ) { - throw new \TypeError(sprintf( - 'Argument 4 must be of type MapInterface', - Property::class - )); - } - - if ( - (string) $metas->keyType() !== 'scalar' || - (string) $metas->valueType() !== 'variable' - ) { - throw new \TypeError('Argument 5 must be of type MapInterface'); - } - - if ((string) $links->type() !== AllowedLink::class) { - throw new \TypeError(\sprintf( - 'Argument 6 must be of type SetInterface<%s>', - AllowedLink::class - )); - } + assertMap('string', Property::class, $properties, 4); + assertMap('scalar', 'scalar|array', $metas, 5); + assertSet(AllowedLink::class, $links, 6); $this->name = $name; $this->url = $url; @@ -75,7 +67,7 @@ public function name(): string return $this->name; } - public function url(): UrlInterface + public function url(): Url { return $this->url; } @@ -86,25 +78,25 @@ public function identity(): Identity } /** - * @return MapInterface + * @return Map */ - public function properties(): MapInterface + public function properties(): Map { return $this->properties; } /** - * @return MapInterface + * @return Map */ - public function metas(): MapInterface + public function metas(): Map { return $this->metas; } /** - * @return SetInterface + * @return Set */ - public function links(): SetInterface + public function links(): Set { return $this->links; } @@ -115,7 +107,7 @@ public function allowsLink(Link $link): bool false, static function(bool $allows, AllowedLink $allowed) use ($link): bool { return $allows || $allowed->allows($link); - } + }, ); } @@ -124,7 +116,7 @@ public function isRangeable(): bool return $this->rangeable; } - public function __toString(): string + public function toString(): string { return $this->name; } diff --git a/src/Definition/Identity.php b/src/Definition/Identity.php index f76c015..87fc18a 100644 --- a/src/Definition/Identity.php +++ b/src/Definition/Identity.php @@ -8,7 +8,7 @@ final class Identity { - private $name; + private string $name; public function __construct(string $name) { @@ -19,7 +19,7 @@ public function __construct(string $name) $this->name = $name; } - public function __toString(): string + public function toString(): string { return $this->name; } diff --git a/src/Definition/Property.php b/src/Definition/Property.php index 556dac9..a6300c6 100644 --- a/src/Definition/Property.php +++ b/src/Definition/Property.php @@ -5,32 +5,31 @@ use Innmind\Rest\Client\Exception\DomainException; use Innmind\Immutable\{ - SetInterface, + Set, Str, }; +use function Innmind\Immutable\assertSet; final class Property { - private $name; - private $type; - private $access; - private $variants; - private $optional; + private string $name; + private Type $type; + private Access $access; + private Set $variants; + private bool $optional; public function __construct( string $name, Type $type, Access $access, - SetInterface $variants, + Set $variants, bool $optional ) { if (Str::of($name)->empty()) { throw new DomainException; } - if ((string) $variants->type() !== 'string') { - throw new \TypeError(sprintf('Argument 4 must be of type SetInterface')); - } + assertSet('string', $variants, 4); $this->name = $name; $this->type = $type; @@ -54,7 +53,7 @@ public function access(): Access return $this->access; } - public function variants(): SetInterface + public function variants(): Set { return $this->variants; } diff --git a/src/Definition/Type.php b/src/Definition/Type.php index 35285ca..9d21f06 100644 --- a/src/Definition/Type.php +++ b/src/Definition/Type.php @@ -3,9 +3,14 @@ namespace Innmind\Rest\Client\Definition; +use Innmind\Rest\Client\Exception\{ + DenormalizationException, + NormalizationException, +}; + interface Type { - public static function fromString(string $type, Types $build): self; + public static function of(string $type, Types $build): self; /** * Transform the data received via http to a data understandable for php @@ -29,5 +34,5 @@ public function denormalize($data); */ public function normalize($data); - public function __toString(): string; + public function toString(): string; } diff --git a/src/Definition/Type/BoolType.php b/src/Definition/Type/BoolType.php index d7dd424..63b0a11 100644 --- a/src/Definition/Type/BoolType.php +++ b/src/Definition/Type/BoolType.php @@ -11,32 +11,26 @@ final class BoolType implements Type { - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { if ($type !== 'bool') { - throw new DomainException; + throw new DomainException($type); } return new self; } - /** - * {@inheritdoc} - */ public function normalize($data) { return (bool) $data; } - /** - * {@inheritdoc} - */ public function denormalize($data) { return (bool) $data; } - public function __toString(): string + public function toString(): string { return 'bool'; } diff --git a/src/Definition/Type/DateType.php b/src/Definition/Type/DateType.php index 91fa52b..9840dca 100644 --- a/src/Definition/Type/DateType.php +++ b/src/Definition/Type/DateType.php @@ -14,9 +14,9 @@ final class DateType implements Type { - const PATTERN = '~date<(?.+)>~'; + private const PATTERN = '~date<(?.+)>~'; - private $format; + private string $format; public function __construct(string $format) { @@ -27,24 +27,22 @@ public function __construct(string $format) $this->format = $format; } - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { - $type = new Str($type); + $type = Str::of($type); if (!$type->matches(self::PATTERN)) { - throw new DomainException; + throw new DomainException($type->toString()); } return new self( - (string) $type + $type ->capture(self::PATTERN) ->get('format') + ->toString(), ); } - /** - * {@inheritdoc} - */ public function normalize($data) { if (\is_string($data)) { @@ -57,16 +55,13 @@ public function normalize($data) if (!$data instanceof \DateTimeInterface) { throw new NormalizationException( - 'The value must be an instance of \DateTimeInterface' + 'The value must be an instance of \DateTimeInterface', ); } return $data->format($this->format); } - /** - * {@inheritdoc} - */ public function denormalize($data) { if (!\is_string($data)) { @@ -76,7 +71,7 @@ public function denormalize($data) try { $date = \DateTimeImmutable::createFromFormat( $this->format, - $data + $data, ); if (!$date instanceof \DateTimeImmutable) { @@ -89,7 +84,7 @@ public function denormalize($data) } } - public function __toString(): string + public function toString(): string { return 'date<'.$this->format.'>'; } diff --git a/src/Definition/Type/FloatType.php b/src/Definition/Type/FloatType.php index e58fa80..dae0f26 100644 --- a/src/Definition/Type/FloatType.php +++ b/src/Definition/Type/FloatType.php @@ -13,18 +13,15 @@ final class FloatType implements Type { - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { if ($type !== 'float') { - throw new DomainException; + throw new DomainException($type); } return new self; } - /** - * {@inheritdoc} - */ public function normalize($data) { try { @@ -34,9 +31,6 @@ public function normalize($data) } } - /** - * {@inheritdoc} - */ public function denormalize($data) { try { @@ -46,7 +40,7 @@ public function denormalize($data) } } - public function __toString(): string + public function toString(): string { return 'float'; } diff --git a/src/Definition/Type/IntType.php b/src/Definition/Type/IntType.php index a2b5826..b18dbef 100644 --- a/src/Definition/Type/IntType.php +++ b/src/Definition/Type/IntType.php @@ -13,18 +13,15 @@ final class IntType implements Type { - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { if ($type !== 'int') { - throw new DomainException; + throw new DomainException($type); } return new self; } - /** - * {@inheritdoc} - */ public function normalize($data) { try { @@ -34,9 +31,6 @@ public function normalize($data) } } - /** - * {@inheritdoc} - */ public function denormalize($data) { try { @@ -46,7 +40,7 @@ public function denormalize($data) } } - public function __toString(): string + public function toString(): string { return 'int'; } diff --git a/src/Definition/Type/MapType.php b/src/Definition/Type/MapType.php index 6449724..6a548ba 100644 --- a/src/Definition/Type/MapType.php +++ b/src/Definition/Type/MapType.php @@ -12,61 +12,62 @@ }; use Innmind\Immutable\{ Str, - MapInterface, Map, }; final class MapType implements Type { - const PATTERN = '~map<(?.+), ?(?.+)>~'; + private const PATTERN = '~map<(?.+), ?(?.+)>~'; - private $key; - private $value; - private $denormalized; + private Type $key; + private Type $value; + private Map $denormalized; public function __construct(Type $key, Type $value) { $this->key = $key; $this->value = $value; - $this->denormalized = new Map( + $this->denormalized = Map::of( $key instanceof DateType ? - \DateTimeImmutable::class : (string) $key, + \DateTimeImmutable::class : $key->toString(), $value instanceof DateType ? - \DateTimeImmutable::class : (string) $value + \DateTimeImmutable::class : $value->toString(), ); } - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { - $type = new Str($type); + $type = Str::of($type); if (!$type->matches(self::PATTERN)) { - throw new DomainException; + throw new DomainException($type->toString()); } $matches = $type->capture(self::PATTERN); return new self( - $build((string) $matches->get('key')), - $build((string) $matches->get('value')) + $build($matches->get('key')->toString()), + $build($matches->get('value')->toString()), ); } - /** - * {@inheritdoc} - */ public function normalize($data) { - if (!$data instanceof MapInterface) { + if (!$data instanceof Map) { throw new NormalizationException( - 'The value must be an instance of Innmind\Immutable\MapInterface' + 'The value must be an instance of Innmind\Immutable\Map', ); } return $data->reduce( [], function(array $values, $key, $value): array { + /** @psalm-suppress MixedAssignment */ $key = $this->key->normalize($key); + /** + * @psalm-suppress MixedAssignment + * @psalm-suppress MixedArrayOffset + */ $values[$key] = $this->value->normalize($value); return $values; @@ -74,9 +75,6 @@ function(array $values, $key, $value): array { ); } - /** - * {@inheritdoc} - */ public function denormalize($data) { if (!\is_array($data) && !$data instanceof \Traversable) { @@ -86,10 +84,11 @@ public function denormalize($data) $map = $this->denormalized; try { + /** @psalm-suppress MixedAssignment */ foreach ($data as $key => $value) { - $map = $map->put( + $map = ($map)( $this->key->denormalize($key), - $this->value->denormalize($value) + $this->value->denormalize($value), ); } @@ -99,8 +98,8 @@ public function denormalize($data) } } - public function __toString(): string + public function toString(): string { - return 'map<'.$this->key.', '.$this->value.'>'; + return 'map<'.$this->key->toString().', '.$this->value->toString().'>'; } } diff --git a/src/Definition/Type/SetType.php b/src/Definition/Type/SetType.php index 2260189..3a2ca3d 100644 --- a/src/Definition/Type/SetType.php +++ b/src/Definition/Type/SetType.php @@ -12,57 +12,55 @@ }; use Innmind\Immutable\{ Str, - SetInterface, Set, }; final class SetType implements Type { - const PATTERN = '~set<(?.+)>~'; + private const PATTERN = '~set<(?.+)>~'; - private $inner; - private $denormalized; + private Type $inner; + private Set $denormalized; public function __construct(Type $inner) { $this->inner = $inner; - $this->denormalized = new Set( + $this->denormalized = Set::of( $inner instanceof DateType ? - \DateTimeImmutable::class : (string) $inner + \DateTimeImmutable::class : $inner->toString(), ); } - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { - $type = new Str($type); + $type = Str::of($type); if (!$type->matches(self::PATTERN)) { - throw new DomainException; + throw new DomainException($type->toString()); } return new self( $build( - (string) $type + $type ->capture(self::PATTERN) ->get('inner') - ) + ->toString(), + ), ); } - /** - * {@inheritdoc} - */ public function normalize($data) { - if (!$data instanceof SetInterface) { + if (!$data instanceof Set) { throw new NormalizationException( - 'The value must be an instance of Innmind\Immutable\SetInterface' + 'The value must be an instance of Innmind\Immutable\Set', ); } return $data->reduce( [], function(array $values, $value): array { + /** @psalm-suppress MixedAssignment */ $values[] = $this->inner->normalize($value); return $values; @@ -70,9 +68,6 @@ function(array $values, $value): array { ); } - /** - * {@inheritdoc} - */ public function denormalize($data) { if (!\is_array($data)) { @@ -82,10 +77,9 @@ public function denormalize($data) $set = $this->denormalized; try { + /** @psalm-suppress MixedAssignment */ foreach ($data as $value) { - $set = $set->add( - $this->inner->denormalize($value) - ); + $set = ($set)($this->inner->denormalize($value)); } return $set; @@ -94,8 +88,8 @@ public function denormalize($data) } } - public function __toString(): string + public function toString(): string { - return 'set<'.$this->inner.'>'; + return 'set<'.$this->inner->toString().'>'; } } diff --git a/src/Definition/Type/StringType.php b/src/Definition/Type/StringType.php index 6ba2e31..b284594 100644 --- a/src/Definition/Type/StringType.php +++ b/src/Definition/Type/StringType.php @@ -13,18 +13,15 @@ final class StringType implements Type { - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { if ($type !== 'string') { - throw new DomainException; + throw new DomainException($type); } return new self; } - /** - * {@inheritdoc} - */ public function normalize($data) { try { @@ -34,9 +31,6 @@ public function normalize($data) } } - /** - * {@inheritdoc} - */ public function denormalize($data) { try { @@ -46,7 +40,7 @@ public function denormalize($data) } } - public function __toString(): string + public function toString(): string { return 'string'; } diff --git a/src/Definition/Types.php b/src/Definition/Types.php index 9f8c279..5e2b497 100644 --- a/src/Definition/Types.php +++ b/src/Definition/Types.php @@ -14,30 +14,31 @@ Exception\DomainException, Exception\UnknownType, }; -use Innmind\Immutable\{ - SetInterface, - Set, -}; +use Innmind\Immutable\Set; +use function Innmind\Immutable\unwrap; final class Types { - private static $defaults; - private $types = []; + /** @var list> */ + private array $types = []; + /** + * @param list> $types + */ public function __construct(string ...$types) { if (\count($types) === 0) { - $types = self::defaults()->toPrimitive(); + $types = unwrap(self::defaults()); } + /** @var class-string $type */ foreach ($types as $type) { - $refl = new \ReflectionClass($type); - - if (!$refl->implementsInterface(Type::class)) { - throw new DomainException; + if (!\is_a($type, Type::class, true)) { + throw new DomainException($type); } } + /** @var list> */ $this->types = $types; } @@ -45,33 +46,29 @@ public function __invoke(string $type): Type { foreach ($this->types as $builder) { try { - return call_user_func( - [$builder, 'fromString'], - $type, - $this - ); + /** @var Type */ + return [$builder, 'of']($type, $this); } catch (DomainException $e) { //pass } } - throw new UnknownType; + throw new UnknownType($type); } /** - * @return SetInterface + * @return Set */ - public static function defaults(): SetInterface + public static function defaults(): Set { - return self::$defaults ?? self::$defaults = Set::of( - 'string', + return Set::strings( BoolType::class, DateType::class, FloatType::class, IntType::class, MapType::class, SetType::class, - StringType::class + StringType::class, ); } } diff --git a/src/Exception/MissingProperty.php b/src/Exception/MissingProperty.php index d6a29d1..055670e 100644 --- a/src/Exception/MissingProperty.php +++ b/src/Exception/MissingProperty.php @@ -7,11 +7,9 @@ final class MissingProperty extends RuntimeException { public function __construct(string $property) { - parent::__construct( - sprintf( - 'Missing property "%s"', - $property - ) - ); + parent::__construct(\sprintf( + 'Missing property "%s"', + $property, + )); } } diff --git a/src/Format/Format.php b/src/Format/Format.php index ff3b9a5..33d4cde 100644 --- a/src/Format/Format.php +++ b/src/Format/Format.php @@ -4,25 +4,25 @@ namespace Innmind\Rest\Client\Format; use Innmind\Rest\Client\Exception\DomainException; -use Innmind\Immutable\SetInterface; +use Innmind\Immutable\Set; +use function Innmind\Immutable\assertSet; final class Format { - private $name; - private $types; - private $priority; - private $preferredType; + private string $name; + /** @var Set */ + private Set $types; + private int $priority; + private MediaType $preferredType; - public function __construct(string $name, SetInterface $types, int $priority) + /** + * @param Set $types + */ + public function __construct(string $name, Set $types, int $priority) { - if ((string) $types->type() !== MediaType::class) { - throw new \TypeError(sprintf( - 'Argument 2 must be of type SetInterface<%s>', - MediaType::class - )); - } + assertSet(MediaType::class, $types, 2); - if ($types->size() === 0) { + if ($types->empty()) { throw new DomainException; } @@ -30,8 +30,8 @@ public function __construct(string $name, SetInterface $types, int $priority) $this->types = $types; $this->priority = $priority; $this->preferredType = $types - ->sort(function(MediaType $a, MediaType $b): bool { - return $a->priority() < $b->priority(); + ->sort(function(MediaType $a, MediaType $b): int { + return (int) ($a->priority() < $b->priority()); }) ->first(); } @@ -42,9 +42,9 @@ public function name(): string } /** - * @return SetInterface + * @return Set */ - public function mediaTypes(): SetInterface + public function mediaTypes(): Set { return $this->types; } @@ -59,7 +59,7 @@ public function priority(): int return $this->priority; } - public function __toString(): string + public function toString(): string { return $this->name; } diff --git a/src/Format/MediaType.php b/src/Format/MediaType.php index 370f910..de6f839 100644 --- a/src/Format/MediaType.php +++ b/src/Format/MediaType.php @@ -3,16 +3,16 @@ namespace Innmind\Rest\Client\Format; -use Innmind\Filesystem\MediaType\MediaType as FilesystemMediaType; +use Innmind\MediaType\MediaType as FilesystemMediaType; final class MediaType { - private $mime; - private $priority; + private FilesystemMediaType $mime; + private int $priority; public function __construct(string $mime, int $priority) { - $this->mime = FilesystemMediaType::fromString($mime); + $this->mime = FilesystemMediaType::of($mime); $this->priority = $priority; } @@ -36,8 +36,8 @@ public function priority(): int return $this->priority; } - public function __toString(): string + public function toString(): string { - return (string) $this->mime; + return $this->mime->toString(); } } diff --git a/src/Formats.php b/src/Formats.php index e428dde..a3ef52c 100644 --- a/src/Formats.php +++ b/src/Formats.php @@ -10,32 +10,26 @@ Exception\DomainException, }; use Innmind\Immutable\{ - MapInterface, Map, - SetInterface, Set, }; +use function Innmind\Immutable\assertMap; use Negotiation\Negotiator; final class Formats { - private $formats; - private $negotiator; - private $types; + /** @var Map */ + private Map $formats; + private Negotiator $negotiator; - public function __construct(MapInterface $formats) + /** + * @param Map $formats + */ + public function __construct(Map $formats) { - if ( - (string) $formats->keyType() !== 'string' || - (string) $formats->valueType() !== Format::class - ) { - throw new \TypeError(sprintf( - 'Argument 1 must be of type MapInterface', - Format::class - )); - } + assertMap('string', Format::class, $formats, 1); - if ($formats->size() === 0) { + if ($formats->empty()) { throw new DomainException; } @@ -45,11 +39,12 @@ public function __construct(MapInterface $formats) public static function of(Format $first, Format ...$formats): self { - $map = Map::of('string', Format::class) - ($first->name(), $first); + /** @var Map */ + $map = Map::of('string', Format::class); + \array_unshift($formats, $first); foreach ($formats as $format) { - $map = $map->put($format->name(), $format); + $map = ($map)($format->name(), $format); } return new self($map); @@ -61,35 +56,32 @@ public function get(string $name): Format } /** - * @return MapInterface + * @return Map */ - public function all(): MapInterface + public function all(): Map { return $this->formats; } /** - * @return SetInterface + * @return Set */ - public function mediaTypes(): SetInterface + public function mediaTypes(): Set { - if ($this->types === null) { - $this->types = $this - ->formats - ->reduce( - new Set(MediaType::class), - function(Set $types, string $name, Format $format): Set { - return $types->merge($format->mediaTypes()); - } - ); - } - - return $this->types; + /** @var Set */ + return $this + ->formats + ->reduce( + Set::of(MediaType::class), + function(Set $types, string $name, Format $format): Set { + return $types->merge($format->mediaTypes()); + } + ); } public function fromMediaType(string $wished): Format { - $format = $this + $formats = $this ->formats ->values() ->filter(function(Format $format) use ($wished) { @@ -102,17 +94,16 @@ function(bool $carry, MediaType $mediaType) use ($wished): bool { return true; } - return (string) $mediaType === $wished; - } + return $mediaType->toString() === $wished; + }, ); - }) - ->current(); + }); - if (!$format instanceof Format) { + if ($formats->empty()) { throw new InvalidArgumentException; } - return $format; + return $formats->first(); } public function matching(string $wished): Format @@ -124,17 +115,18 @@ public function matching(string $wished): Format ->reduce( [], function(array $carry, MediaType $type): array { - $carry[] = (string) $type; + $carry[] = $type->toString(); return $carry; - } - ) + }, + ), ); if ($best === null) { throw new InvalidArgumentException; } + /** @psalm-suppress UndefinedInterfaceMethod */ return $this->best($best->getBasePart().'/'.$best->getSubPart()); } @@ -144,8 +136,8 @@ private function best(string $mediaType): Format return $this ->formats ->values() - ->sort(function(Format $a, Format $b): bool { - return $a->priority() > $b->priority(); + ->sort(function(Format $a, Format $b): int { + return (int) ($a->priority() > $b->priority()); }) ->first(); } diff --git a/src/HttpResource.php b/src/HttpResource.php index 5f87eb2..afbfbec 100644 --- a/src/HttpResource.php +++ b/src/HttpResource.php @@ -8,42 +8,39 @@ Exception\DomainException, }; use Innmind\Immutable\{ - MapInterface, Map, Str, }; +use function Innmind\Immutable\assertMap; final class HttpResource { - private $name; - private $properties; + private string $name; + /** @var Map */ + private Map $properties; - public function __construct(string $name, MapInterface $properties) + /** + * @param Map $properties + */ + public function __construct(string $name, Map $properties) { if (Str::of($name)->empty()) { throw new DomainException; } - if ( - (string) $properties->keyType() !== 'string' || - (string) $properties->valueType() !== Property::class - ) { - throw new \TypeError(sprintf( - 'Argument 2 must be of type MapInterface', - Property::class - )); - } + assertMap('string', Property::class, $properties, 2); $this->name = $name; $this->properties = $properties; } - public static function of(string $name, Property ...$properties) + public static function of(string $name, Property ...$properties): self { + /** @var Map */ $map = Map::of('string', Property::class); foreach ($properties as $property) { - $map = $map->put($property->name(), $property); + $map = ($map)($property->name(), $property); } return new self($name, $map); @@ -55,9 +52,9 @@ public function name(): string } /** - * @return MapInterface + * @return Map */ - public function properties(): MapInterface + public function properties(): Map { return $this->properties; } diff --git a/src/HttpResource/Property.php b/src/HttpResource/Property.php index 778b9ed..16d8a51 100644 --- a/src/HttpResource/Property.php +++ b/src/HttpResource/Property.php @@ -8,9 +8,13 @@ final class Property { - private $name; + private string $name; + /** @var mixed */ private $value; + /** + * @param mixed $value + */ public function __construct(string $name, $value) { if (Str::of($name)->empty()) { @@ -26,6 +30,9 @@ public function name(): string return $this->name; } + /** + * @return mixed + */ public function value() { return $this->value; diff --git a/src/Identity.php b/src/Identity.php index 2681e08..5265a9c 100644 --- a/src/Identity.php +++ b/src/Identity.php @@ -5,5 +5,5 @@ interface Identity { - public function __toString(): string; + public function toString(): string; } diff --git a/src/Identity/Identity.php b/src/Identity/Identity.php index 954554b..f66b08e 100644 --- a/src/Identity/Identity.php +++ b/src/Identity/Identity.php @@ -11,7 +11,7 @@ class Identity implements IdentityInterface { - private $value; + private string $value; public function __construct(string $value) { @@ -22,7 +22,7 @@ public function __construct(string $value) $this->value = $value; } - public function __toString(): string + public function toString(): string { return $this->value; } diff --git a/src/Link.php b/src/Link.php index f68e5ab..943586e 100644 --- a/src/Link.php +++ b/src/Link.php @@ -8,25 +8,29 @@ Exception\DomainException, }; use Innmind\Immutable\{ - MapInterface, Map, Str, }; +use function Innmind\Immutable\assertMap; final class Link { - private $definition; - private $identity; - private $relationship; - private $parameters; + private string $definition; + private Identity $identity; + private string $relationship; + /** @var Map */ + private Map $parameters; + /** + * @param Map|null $parameters + */ public function __construct( string $definition, Identity $identity, string $relationship, - MapInterface $parameters = null + Map $parameters = null ) { - $parameters = $parameters ?? new Map('string', Parameter::class); + $parameters ??= Map::of('string', Parameter::class); if ( Str::of($definition)->empty() || @@ -35,15 +39,7 @@ public function __construct( throw new DomainException; } - if ( - (string) $parameters->keyType() !== 'string' || - (string) $parameters->valueType() !== Parameter::class - ) { - throw new \TypeError(sprintf( - 'Argument 4 must be of type MapInterface', - Parameter::class - )); - } + assertMap('string', Parameter::class, $parameters, 4); $this->definition = $definition; $this->identity = $identity; @@ -57,10 +53,11 @@ public static function of( string $relationship, Parameter ...$parameters ): self { + /** @var Map */ $map = Map::of('string', Parameter::class); foreach ($parameters as $parameter) { - $map = $map->put($parameter->key(), $parameter); + $map = ($map)($parameter->key(), $parameter); } return new self($definition, $identity, $relationship, $map); @@ -82,9 +79,9 @@ public function relationship(): string } /** - * @return MapInterface + * @return Map */ - public function parameters(): MapInterface + public function parameters(): Map { return $this->parameters; } diff --git a/src/Link/Parameter/Parameter.php b/src/Link/Parameter/Parameter.php index 8c2f88b..dfe7f77 100644 --- a/src/Link/Parameter/Parameter.php +++ b/src/Link/Parameter/Parameter.php @@ -11,8 +11,8 @@ final class Parameter implements ParameterInterface { - private $key; - private $value; + private string $key; + private string $value; public function __construct(string $key, string $value) { diff --git a/src/Request/Range.php b/src/Request/Range.php index 6e6916b..44d51a6 100644 --- a/src/Request/Range.php +++ b/src/Request/Range.php @@ -7,8 +7,8 @@ final class Range { - private $firstPosition; - private $lastPosition; + private int $firstPosition; + private int $lastPosition; public function __construct(int $firstPosition, int $lastPosition) { @@ -16,7 +16,7 @@ public function __construct(int $firstPosition, int $lastPosition) $firstPosition < 0 || $lastPosition < $firstPosition ) { - throw new DomainException; + throw new DomainException("$firstPosition-$lastPosition"); } $this->firstPosition = $firstPosition; diff --git a/src/Response/ExtractIdentities.php b/src/Response/ExtractIdentities.php index d403768..1ccada4 100644 --- a/src/Response/ExtractIdentities.php +++ b/src/Response/ExtractIdentities.php @@ -14,49 +14,49 @@ Header\Value, Header\LinkValue, }; -use Innmind\Immutable\{ - SetInterface, - Set, -}; +use Innmind\Immutable\Set; final class ExtractIdentities { - private $resolveIdentity; + private ResolveIdentity $resolveIdentity; public function __construct(ResolveIdentity $resolveIdentity) { $this->resolveIdentity = $resolveIdentity; } - public function __invoke(Response $response, HttpResource $definition): SetInterface + /** + * @return Set + */ + public function __invoke(Response $response, HttpResource $definition): Set { $headers = $response->headers(); - if (!$headers->has('Link')) { - return new Set(Identity::class); + if (!$headers->contains('Link')) { + return Set::of(Identity::class); } - return $headers + /** @var Set */ + $links = $headers ->get('Link') ->values() ->filter(function(Value $link): bool { return $link instanceof LinkValue; - }) + }); + + /** @var Set */ + return $links ->filter(function(LinkValue $link): bool { return $link->relationship() === 'resource'; }) - ->reduce( - new Set(Identity::class), - function(Set $identities, LinkValue $link) use ($definition): Set { - return $identities->add( - new Identity\Identity( - ($this->resolveIdentity)( - $definition->url(), - $link->url() - ) - ) - ); - } + ->mapTo( + Identity::class, + fn(LinkValue $link): Identity => new Identity\Identity( + ($this->resolveIdentity)( + $definition->url(), + $link->url(), + ), + ), ); } } diff --git a/src/Response/ExtractIdentity.php b/src/Response/ExtractIdentity.php index 1f348c5..3d2b101 100644 --- a/src/Response/ExtractIdentity.php +++ b/src/Response/ExtractIdentity.php @@ -14,10 +14,11 @@ Header\Location, }; use Innmind\Url\Url; +use function Innmind\Immutable\first; final class ExtractIdentity { - private $resolveIdentity; + private ResolveIdentity $resolveIdentity; public function __construct(ResolveIdentity $resolveIdentity) { @@ -28,24 +29,24 @@ public function __invoke(Response $response, HttpResource $definition): Identity { $headers = $response->headers(); - if ( - !$headers->has('Location') || - !$headers->get('Location') instanceof Location - ) { + if (!$headers->contains('Location')) { throw new IdentityNotFound; } - $header = $headers - ->get('Location') - ->values() - ->current(); - $header = Url::fromString((string) $header); + $header = $headers->get('Location'); + + if (!$headers->get('Location') instanceof Location) { + throw new IdentityNotFound; + } + + $header = first($header->values()); + $header = Url::of($header->toString()); return new Identity\Identity( ($this->resolveIdentity)( $definition->url(), - $header - ) + $header, + ), ); } } diff --git a/src/Serializer/Decode/Json.php b/src/Serializer/Decode/Json.php index c603344..4a74fc5 100644 --- a/src/Serializer/Decode/Json.php +++ b/src/Serializer/Decode/Json.php @@ -15,9 +15,10 @@ final class Json implements Decode public function __invoke(string $format, Readable $content): array { if ($format !== 'json') { - throw new LogicException; + throw new LogicException($format); } - return JsonLib::decode((string) $content); + /** @var array */ + return JsonLib::decode($content->toString()); } } diff --git a/src/Serializer/Denormalizer/DenormalizeCapabilitiesNames.php b/src/Serializer/Denormalizer/DenormalizeCapabilitiesNames.php index 043ec9f..ae68503 100644 --- a/src/Serializer/Denormalizer/DenormalizeCapabilitiesNames.php +++ b/src/Serializer/Denormalizer/DenormalizeCapabilitiesNames.php @@ -3,15 +3,17 @@ namespace Innmind\Rest\Client\Serializer\Denormalizer; -use Innmind\Immutable\{ - SetInterface, - Set, -}; +use Innmind\Immutable\Set; final class DenormalizeCapabilitiesNames { - public function __invoke(array $data): SetInterface + /** + * @param list $data + * + * @return Set + */ + public function __invoke(array $data): Set { - return Set::of('string', ...\array_values($data)); + return Set::strings(...\array_values($data)); } } diff --git a/src/Serializer/Denormalizer/DenormalizeDefinition.php b/src/Serializer/Denormalizer/DenormalizeDefinition.php index 52880f2..9a87e6d 100644 --- a/src/Serializer/Denormalizer/DenormalizeDefinition.php +++ b/src/Serializer/Denormalizer/DenormalizeDefinition.php @@ -19,65 +19,77 @@ final class DenormalizeDefinition { - private $build; + private Types $build; public function __construct(Types $build) { $this->build = $build; } + /** + * @param array{metas: array, properties: array, type: string, access: list, optional: bool}>, linkable_to: list}>, url: string, identity: string, rangeable: bool} $definition + */ public function __invoke(array $definition, string $name): HttpResource { - $properties = new Map('string', Property::class); - $metas = Map::of( - 'scalar', - 'variable', - \array_keys($definition['metas']), - \array_values($definition['metas']) - ); + /** @var Map */ + $properties = Map::of('string', Property::class); + /** @var Map */ + $metas = Map::of('scalar', 'scalar|array'); + /** @var Set */ $links = Set::of(AllowedLink::class); + foreach ($definition['metas'] as $key => $value) { + $metas = ($metas)($key, $value); + } + + foreach ($definition['properties'] as $property => $value) { - $properties = $properties->put( + $properties = ($properties)( $property, - $this->buildProperty($property, $value) + $this->buildProperty($property, $value), ); } foreach ($definition['linkable_to'] as $value) { - $links = $links->add($this->buildLink($value)); + $links = ($links)($this->buildLink($value)); } return new HttpResource( $name, - Url::fromString($definition['url']), + Url::of($definition['url']), new Identity($definition['identity']), $properties, $metas, $links, - $definition['rangeable'] + $definition['rangeable'], ); } + /** + * @param array{variants: list, type: string, access: list, optional: bool} $definition + */ private function buildProperty(string $name, array $definition): Property { - $variants = Set::of('string', ...\array_values($definition['variants'])); + $variants = Set::strings(...\array_values($definition['variants'])); return new Property( $name, ($this->build)($definition['type']), new Access(...$definition['access']), $variants, - $definition['optional'] + $definition['optional'], ); } + /** + * @param array{resource_path: string, relationship: string, parameters: list} $link + */ private function buildLink(array $link): AllowedLink { return new AllowedLink( $link['resource_path'], $link['relationship'], - Set::of('string', ...$link['parameters']) + Set::strings(...$link['parameters']), ); } } diff --git a/src/Serializer/Denormalizer/DenormalizeResource.php b/src/Serializer/Denormalizer/DenormalizeResource.php index e97036e..30991ec 100644 --- a/src/Serializer/Denormalizer/DenormalizeResource.php +++ b/src/Serializer/Denormalizer/DenormalizeResource.php @@ -20,6 +20,7 @@ public function __invoke( ResourceDefinition $definition, Access $access ): HttpResource { + /** @var array */ $data = $data['resource']; $properties = $definition @@ -33,30 +34,32 @@ public function __invoke( } return isset($data[$name]); - }) - ->foreach(function(string $name) use ($data) { - if (!isset($data[$name])) { - throw new MissingProperty($name); - } - }) - ->reduce( - new Map('string', Property::class), - function(Map $properties, string $name, PropertyDefinition $property) use ($data): Map { - return $properties->put( - $name, - new Property( - $name, - $property - ->type() - ->denormalize($data[$name]) - ) - ); - } - ); + }); + + $properties->foreach(function(string $name) use ($data) { + if (!isset($data[$name])) { + throw new MissingProperty($name); + } + }); + + /** @var Map */ + $properties = $properties->toMapOf( + 'string', + Property::class, + static function(string $name, PropertyDefinition $property) use ($data): \Generator { + /** @psalm-suppress MixedArrayAccess */ + yield $name => new Property( + $name, + $property + ->type() + ->denormalize($data[$name]), + ); + }, + ); return new HttpResource( $definition->name(), - $properties + $properties, ); } } diff --git a/src/Serializer/Encode/Json.php b/src/Serializer/Encode/Json.php index 05dc089..4cce2d6 100644 --- a/src/Serializer/Encode/Json.php +++ b/src/Serializer/Encode/Json.php @@ -6,14 +6,14 @@ use Innmind\Rest\Client\Serializer\Encode; use Innmind\Stream\Readable; use Innmind\Json\Json as JsonLib; -use Innmind\Filesystem\Stream\StringStream; +use Innmind\Stream\Readable\Stream; final class Json implements Encode { public function __invoke(array $content): Readable { - return new StringStream( - JsonLib::encode($content) + return Stream::ofContent( + JsonLib::encode($content), ); } } diff --git a/src/Serializer/Normalizer/NormalizeDefinition.php b/src/Serializer/Normalizer/NormalizeDefinition.php index daadc4c..b505f0a 100644 --- a/src/Serializer/Normalizer/NormalizeDefinition.php +++ b/src/Serializer/Normalizer/NormalizeDefinition.php @@ -6,42 +6,39 @@ use Innmind\Rest\Client\{ Definition\HttpResource, Definition\Property, - Definition\Identity, - Definition\Access, Definition\AllowedLink, }; -use Innmind\Url\Url; -use Innmind\Immutable\{ - Map, - Set, -}; +use function Innmind\Immutable\unwrap; final class NormalizeDefinition { public function __invoke(HttpResource $definition): array { + /** @psalm-suppress InvalidScalarArgument */ + $metas = \array_combine( + unwrap($definition->metas()->keys()), + unwrap($definition->metas()->values()), + ); + return [ - 'url' => (string) $definition->url(), - 'identity' => (string) $definition->identity(), + 'url' => $definition->url()->toString(), + 'identity' => $definition->identity()->toString(), 'properties' => $definition ->properties() ->reduce( [], function(array $properties, string $name, Property $property): array { $properties[$name] = [ - 'type' => (string) $property->type(), - 'access' => $property->access()->mask()->toPrimitive(), - 'variants' => $property->variants()->toPrimitive(), + 'type' => $property->type()->toString(), + 'access' => unwrap($property->access()->mask()), + 'variants' => unwrap($property->variants()), 'optional' => $property->isOptional(), ]; return $properties; } ), - 'metas' => array_combine( - $definition->metas()->keys()->toPrimitive(), - $definition->metas()->values()->toPrimitive() - ), + 'metas' => $metas, 'linkable_to' => $definition ->links() ->reduce( @@ -50,7 +47,7 @@ static function(array $links, AllowedLink $link): array { $links[] = [ 'relationship' => $link->relationship(), 'resource_path' => $link->resourcePath(), - 'parameters' => $link->parameters()->toPrimitive(), + 'parameters' => unwrap($link->parameters()), ]; return $links; diff --git a/src/Serializer/Normalizer/NormalizeResource.php b/src/Serializer/Normalizer/NormalizeResource.php index edfe4d4..edc8fdd 100644 --- a/src/Serializer/Normalizer/NormalizeResource.php +++ b/src/Serializer/Normalizer/NormalizeResource.php @@ -10,7 +10,6 @@ HttpResource, Exception\MissingProperty, }; -use Innmind\Immutable\Map; final class NormalizeResource { @@ -32,31 +31,34 @@ public function __invoke( $name = $this->resolveName($property, $resource); return $resource->properties()->contains($name); - }) - ->foreach(function(string $name, Property $property) use ($resource) { - $name = $this->resolveName($property, $resource); + }); - if (!$resource->properties()->contains($name)) { - throw new MissingProperty($name); - } - }) - ->reduce( - [], - function(array $properties, string $name, Property $property) use ($resource): array { - $usedName = $this->resolveName($property, $resource); + $properties->foreach(function(string $name, Property $property) use ($resource) { + $name = $this->resolveName($property, $resource); - $properties[$name] = $property - ->type() - ->normalize( - $resource - ->properties() - ->get($usedName) - ->value() - ); + if (!$resource->properties()->contains($name)) { + throw new MissingProperty($name); + } + }); - return $properties; - } - ); + $properties = $properties->reduce( + [], + function(array $properties, string $name, Property $property) use ($resource): array { + $usedName = $this->resolveName($property, $resource); + + /** @psalm-suppress MixedAssignment */ + $properties[$name] = $property + ->type() + ->normalize( + $resource + ->properties() + ->get($usedName) + ->value(), + ); + + return $properties; + } + ); return ['resource' => $properties]; } @@ -75,7 +77,7 @@ function(string $usedName, string $variant) use ($resource): string { } return $usedName; - } + }, ); } } diff --git a/src/Server.php b/src/Server.php index 4cf3610..7d0b893 100644 --- a/src/Server.php +++ b/src/Server.php @@ -7,45 +7,34 @@ Server\Capabilities, Request\Range, }; -use Innmind\Url\UrlInterface; -use Innmind\Immutable\SetInterface; +use Innmind\Url\Url; +use Innmind\Immutable\Set; use Innmind\Specification\Specification; interface Server { /** - * @return SetInterface + * @return Set */ public function all( string $name, Specification $specification = null, Range $range = null - ): SetInterface; + ): Set; public function read(string $name, Identity $identity): HttpResource; public function create(HttpResource $resource): Identity; - public function update( - Identity $identity, - HttpResource $resource - ): self; - public function remove(string $name, Identity $identity): self; + public function update(Identity $identity, HttpResource $resource): void; + public function remove(string $name, Identity $identity): void; /** - * @param SetInterface $links + * @param Set $links */ - public function link( - string $name, - Identity $identity, - SetInterface $links - ): self; + public function link(string $name, Identity $identity, Set $links): void; /** - * @param SetInterface $links + * @param Set $links */ - public function unlink( - string $name, - Identity $identity, - SetInterface $links - ): self; + public function unlink(string $name, Identity $identity, Set $links): void; public function capabilities(): Capabilities; - public function url(): UrlInterface; + public function url(): Url; } diff --git a/src/Server/Capabilities.php b/src/Server/Capabilities.php index d8c65e8..65d0b4d 100644 --- a/src/Server/Capabilities.php +++ b/src/Server/Capabilities.php @@ -5,26 +5,26 @@ use Innmind\Rest\Client\Definition\HttpResource; use Innmind\Immutable\{ - MapInterface, - SetInterface, + Map, + Set, }; interface Capabilities { /** - * @return SetInterface + * @return Set */ - public function names(): SetInterface; + public function names(): Set; public function get(string $name): HttpResource; /** - * @return MapInterface + * @return Map */ - public function definitions(): MapInterface; + public function definitions(): Map; /** * Clear all definition references it holds, in order to be sure next time * we access one it is a fresh definition */ - public function refresh(): self; + public function refresh(): void; } diff --git a/src/Server/Capabilities/CacheCapabilities.php b/src/Server/Capabilities/CacheCapabilities.php index b679b15..57fc076 100644 --- a/src/Server/Capabilities/CacheCapabilities.php +++ b/src/Server/Capabilities/CacheCapabilities.php @@ -16,28 +16,30 @@ Adapter, File, Directory, + Name, Exception\FileNotFound, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\Immutable\{ - SetInterface, Set, - MapInterface, Map, }; +use function Innmind\Immutable\unwrap; final class CacheCapabilities implements CapabilitiesInterface { - private $capabilities; - private $filesystem; - private $decode; - private $encode; - private $denormalizeNames; - private $denormalizeDefinition; - private $normalizeDefinition; - private $directory; - private $names; - private $definitions; + private CapabilitiesInterface $capabilities; + private Adapter $filesystem; + private Decode $decode; + private Encode $encode; + private DenormalizeCapabilitiesNames $denormalizeNames; + private DenormalizeDefinition $denormalizeDefinition; + private NormalizeDefinition $normalizeDefinition; + private Name $directory; + /** @var Set|null */ + private ?Set $names = null; + /** @var Map */ + private Map $definitions; public function __construct( CapabilitiesInterface $capabilities, @@ -47,7 +49,7 @@ public function __construct( DenormalizeCapabilitiesNames $denormalizeNames, DenormalizeDefinition $denormalizeDefinition, NormalizeDefinition $normalizeDefinition, - UrlInterface $host + Url $host ) { $this->capabilities = $capabilities; $this->filesystem = $filesystem; @@ -56,27 +58,26 @@ public function __construct( $this->denormalizeNames = $denormalizeNames; $this->denormalizeDefinition = $denormalizeDefinition; $this->normalizeDefinition = $normalizeDefinition; - $this->directory = \md5((string) $host); - $this->definitions = new Map('string', HttpResource::class); + $this->directory = new Name(\md5($host->toString())); + /** @var Map */ + $this->definitions = Map::of('string', HttpResource::class); } - /** - * {@inheritdoc} - */ - public function names(): SetInterface + public function names(): Set { - if ($this->names instanceof SetInterface) { + if ($this->names instanceof Set) { return $this->names; } try { $file = $this->load('.names'); - return $this->names = ($this->denormalizeNames)( - ($this->decode)('json', $file->content()) - ); + /** @var list */ + $names = ($this->decode)('json', $file->content()); + + return $this->names = ($this->denormalizeNames)($names); } catch (FileNotFound $e) { $this->names = $this->capabilities->names(); - $this->persist('.names', $this->names->toPrimitive()); + $this->persist('.names', unwrap($this->names)); return $this->names; } @@ -90,30 +91,29 @@ public function get(string $name): HttpResource try { $file = $this->load($name); + /** @var array{metas: array, properties: array, type: string, access: list, optional: bool}>, linkable_to: list}>, url: string, identity: string, rangeable: bool} */ + $definition = ($this->decode)('json', $file->content()); $definition = ($this->denormalizeDefinition)( - ($this->decode)('json', $file->content()), - $name + $definition, + $name, ); } catch (FileNotFound $e) { $definition = $this->capabilities->get($name); $this->persist( $name, - ($this->normalizeDefinition)($definition) + ($this->normalizeDefinition)($definition), ); } - $this->definitions = $this->definitions->put( + $this->definitions = ($this->definitions)( $name, - $definition + $definition, ); return $definition; } - /** - * {@inheritdoc} - */ - public function definitions(): MapInterface + public function definitions(): Map { $this->names()->foreach(function(string $name) { $this->get($name); @@ -122,24 +122,19 @@ public function definitions(): MapInterface return $this->definitions; } - /** - * {@inheritdoc} - */ - public function refresh(): CapabilitiesInterface + public function refresh(): void { $this->names = null; $this->definitions = $this->definitions->clear(); $this->filesystem->remove($this->directory); $this->capabilities->refresh(); - - return $this; } private function load(string $file): File { - $file .= '.json'; + $file = new Name($file.'.json'); - if (!$this->filesystem->has($this->directory)) { + if (!$this->filesystem->contains($this->directory)) { throw new FileNotFound; } @@ -149,29 +144,28 @@ private function load(string $file): File throw new FileNotFound; } - if (!$directory->has($file)) { + if (!$directory->contains($file)) { throw new FileNotFound; } return $directory->get($file); } - private function persist(string $name, array $data): self + private function persist(string $name, array $data): void { - if ($this->filesystem->has($this->directory)) { + if ($this->filesystem->contains($this->directory)) { + /** @var Directory */ $directory = $this->filesystem->get($this->directory); } else { $directory = new Directory\Directory($this->directory); } $directory = $directory->add( - new File\File( + File\File::named( $name.'.json', - ($this->encode)($data) - ) + ($this->encode)($data), + ), ); $this->filesystem->add($directory); - - return $this; } } diff --git a/src/Server/Capabilities/CacheFactory.php b/src/Server/Capabilities/CacheFactory.php index b3bdb38..077a085 100644 --- a/src/Server/Capabilities/CacheFactory.php +++ b/src/Server/Capabilities/CacheFactory.php @@ -11,18 +11,18 @@ Serializer\Denormalizer\DenormalizeDefinition, Serializer\Normalizer\NormalizeDefinition, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\Filesystem\Adapter; final class CacheFactory implements Factory { - private $filesystem; - private $decode; - private $encode; - private $denormalizeNames; - private $denormalizeDefinition; - private $normalizeDefinition; - private $make; + private Adapter $filesystem; + private Decode $decode; + private Encode $encode; + private DenormalizeCapabilitiesNames $denormalizeNames; + private DenormalizeDefinition $denormalizeDefinition; + private NormalizeDefinition $normalizeDefinition; + private Factory $make; public function __construct( Adapter $filesystem, @@ -42,7 +42,7 @@ public function __construct( $this->make = $make; } - public function __invoke(UrlInterface $url): CapabilitiesInterface + public function __invoke(Url $url): CapabilitiesInterface { return new CacheCapabilities( ($this->make)($url), @@ -52,7 +52,7 @@ public function __invoke(UrlInterface $url): CapabilitiesInterface $this->denormalizeNames, $this->denormalizeDefinition, $this->normalizeDefinition, - $url + $url, ); } } diff --git a/src/Server/Capabilities/Capabilities.php b/src/Server/Capabilities/Capabilities.php index 4ccdf52..f254b6d 100644 --- a/src/Server/Capabilities/Capabilities.php +++ b/src/Server/Capabilities/Capabilities.php @@ -12,64 +12,61 @@ Formats, }; use Innmind\HttpTransport\Transport; -use Innmind\Url\{ - UrlInterface, - Url, -}; -use Innmind\UrlResolver\ResolverInterface; +use Innmind\Url\Url; +use Innmind\UrlResolver\Resolver; use Innmind\Http\{ Message\Request\Request, - Message\Method\Method, - Headers\Headers, - ProtocolVersion\ProtocolVersion, + Message\Method, + Headers, + ProtocolVersion, Header\Value, Header\LinkValue, Header\Accept, Header\AcceptValue, }; use Innmind\Immutable\{ - MapInterface, - SetInterface, Map, Set, }; +use function Innmind\Immutable\unwrap; final class Capabilities implements CapabilitiesInterface { - private $fulfill; - private $host; - private $resolver; - private $make; - private $formats; - private $optionsUrl; - private $names; - private $paths; - private $definitions; + private Transport $fulfill; + private Url $host; + private Resolver $resolve; + private DefinitionFactory $make; + private Formats $formats; + private Url $optionsUrl; + /** @var Set|null */ + private ?Set $names = null; + /** @var Map */ + private Map $paths; + /** @var Map */ + private Map $definitions; public function __construct( Transport $fulfill, - UrlInterface $host, - ResolverInterface $resolver, + Url $host, + Resolver $resolve, DefinitionFactory $make, Formats $formats ) { $this->fulfill = $fulfill; $this->host = $host; - $this->resolver = $resolver; + $this->resolve = $resolve; $this->make = $make; $this->formats = $formats; - $optionsUrl = $resolver->resolve((string) $host, '/*'); - $this->optionsUrl = Url::fromString($optionsUrl); - $this->paths = new Map('string', UrlInterface::class); - $this->definitions = new Map('string', HttpResource::class); + $this->optionsUrl = $resolve($host, Url::of('/*')); + /** @var Map */ + $this->paths = Map::of('string', Url::class); + /** @var Map */ + $this->definitions = Map::of('string', HttpResource::class); } - /** - * {@inheritdoc} - */ - public function names(): SetInterface + public function names(): Set { - if ($this->names instanceof SetInterface) { + if ($this->names instanceof Set) { return $this->names; } @@ -78,32 +75,34 @@ public function names(): SetInterface new Request( $this->optionsUrl, Method::options(), - new ProtocolVersion(1, 1) - ) + new ProtocolVersion(1, 1), + ), ) ->headers(); - if (!$headers->has('Link')) { - return $this->names = new Set('string'); + if (!$headers->contains('Link')) { + return $this->names = Set::strings(); } - return $this->names = $headers + /** @var Set */ + $links = $headers ->get('Link') ->values() ->filter(function(Value $value): bool { return $value instanceof LinkValue; - }) - ->reduce( - new Set('string'), - function(Set $names, LinkValue $link): Set { - $this->paths = $this->paths->put( - $link->relationship(), - $link->url() - ); - - return $names->add($link->relationship()); - } - ); + }); + + return $this->names = $links->mapTo( + 'string', + function(LinkValue $link): string { + $this->paths = ($this->paths)( + $link->relationship(), + $link->url(), + ); + + return $link->relationship(); + }, + ); } public function get(string $name): HttpResource @@ -116,11 +115,10 @@ public function get(string $name): HttpResource return $this->definitions->get($name); } - $url = $this->resolver->resolve( - (string) $this->host, - (string) $this->paths->get($name) + $url = ($this->resolve)( + $this->host, + $this->paths->get($name), ); - $url = Url::fromString($url); $response = ($this->fulfill)( new Request( $url, @@ -128,43 +126,38 @@ public function get(string $name): HttpResource new ProtocolVersion(1, 1), Headers::of( new Accept( - ...$this + ...unwrap($this ->formats ->all() ->values() - ->sort(function(Format $a, Format $b): bool { - return $a->priority() < $b->priority(); + ->sort(static function(Format $a, Format $b): int { + return (int) ($a->priority() < $b->priority()); }) - ->reduce( - new Set(Value::class), - function(Set $values, Format $format): Set { - return $values->add(new AcceptValue( - $format->preferredMediaType()->topLevel(), - $format->preferredMediaType()->subType() - )); - } - ) - ) - ) - ) + ->mapTo( + Value::class, + static fn(Format $format): AcceptValue => new AcceptValue( + $format->preferredMediaType()->topLevel(), + $format->preferredMediaType()->subType(), + ), + )), + ), + ), + ), ); $definition = ($this->make)( $name, $url, - $response + $response, ); - $this->definitions = $this->definitions->put( + $this->definitions = ($this->definitions)( $name, - $definition + $definition, ); return $definition; } - /** - * {@inheritdoc} - */ - public function definitions(): MapInterface + public function definitions(): Map { $this->names()->foreach(function(string $name) { $this->get($name); @@ -173,15 +166,10 @@ public function definitions(): MapInterface return $this->definitions; } - /** - * {@inheritdoc} - */ - public function refresh(): CapabilitiesInterface + public function refresh(): void { $this->names = null; $this->paths = $this->paths->clear(); $this->definitions = $this->definitions->clear(); - - return $this; } } diff --git a/src/Server/Capabilities/Factory.php b/src/Server/Capabilities/Factory.php index 8b12098..75fe196 100644 --- a/src/Server/Capabilities/Factory.php +++ b/src/Server/Capabilities/Factory.php @@ -4,9 +4,9 @@ namespace Innmind\Rest\Client\Server\Capabilities; use Innmind\Rest\Client\Server\Capabilities as CapabilitiesInterface; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; interface Factory { - public function __invoke(UrlInterface $url): CapabilitiesInterface; + public function __invoke(Url $url): CapabilitiesInterface; } diff --git a/src/Server/Capabilities/Factory/Factory.php b/src/Server/Capabilities/Factory/Factory.php index e29c230..86b489f 100644 --- a/src/Server/Capabilities/Factory/Factory.php +++ b/src/Server/Capabilities/Factory/Factory.php @@ -10,20 +10,20 @@ Server\DefinitionFactory, Formats, }; -use Innmind\Url\UrlInterface; -use Innmind\UrlResolver\ResolverInterface; +use Innmind\Url\Url; +use Innmind\UrlResolver\Resolver; use Innmind\HttpTransport\Transport; final class Factory implements FactoryInterface { - private $transport; - private $resolver; - private $definitionFactory; - private $formats; + private Transport $transport; + private Resolver $resolver; + private DefinitionFactory $definitionFactory; + private Formats $formats; public function __construct( Transport $transport, - ResolverInterface $resolver, + Resolver $resolver, DefinitionFactory $definitionFactory, Formats $formats ) { @@ -33,14 +33,14 @@ public function __construct( $this->formats = $formats; } - public function __invoke(UrlInterface $url): CapabilitiesInterface + public function __invoke(Url $url): CapabilitiesInterface { return new Capabilities( $this->transport, $url, $this->resolver, $this->definitionFactory, - $this->formats + $this->formats, ); } } diff --git a/src/Server/Capabilities/RefreshLimitedCapabilities.php b/src/Server/Capabilities/RefreshLimitedCapabilities.php index 70ba4f8..2104a8a 100644 --- a/src/Server/Capabilities/RefreshLimitedCapabilities.php +++ b/src/Server/Capabilities/RefreshLimitedCapabilities.php @@ -8,24 +8,21 @@ Definition\HttpResource, }; use Innmind\Immutable\{ - SetInterface, - MapInterface, + Set, + Map, }; final class RefreshLimitedCapabilities implements CapabilitiesInterface { - private $capabilities; - private $isFresh = false; + private CapabilitiesInterface $capabilities; + private bool $isFresh = false; public function __construct(CapabilitiesInterface $capabilities) { $this->capabilities = $capabilities; } - /** - * {@inheritdoc} - */ - public function names(): SetInterface + public function names(): Set { return $this->capabilities->names(); } @@ -35,26 +32,18 @@ public function get(string $name): HttpResource return $this->capabilities->get($name); } - /** - * {@inheritdoc} - */ - public function definitions(): MapInterface + public function definitions(): Map { return $this->capabilities->definitions(); } - /** - * {@inheritdoc} - */ - public function refresh(): CapabilitiesInterface + public function refresh(): void { if ($this->isFresh) { - return $this; + return; } $this->capabilities->refresh(); $this->isFresh = true; - - return $this; } } diff --git a/src/Server/Capabilities/RefreshLimitedFactory.php b/src/Server/Capabilities/RefreshLimitedFactory.php index d209deb..7ef79d8 100644 --- a/src/Server/Capabilities/RefreshLimitedFactory.php +++ b/src/Server/Capabilities/RefreshLimitedFactory.php @@ -4,21 +4,21 @@ namespace Innmind\Rest\Client\Server\Capabilities; use Innmind\Rest\Client\Server\Capabilities as CapabilitiesInterface; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; final class RefreshLimitedFactory implements Factory { - private $make; + private Factory $make; public function __construct(Factory $make) { $this->make = $make; } - public function __invoke(UrlInterface $url): CapabilitiesInterface + public function __invoke(Url $url): CapabilitiesInterface { return new RefreshLimitedCapabilities( - ($this->make)($url) + ($this->make)($url), ); } } diff --git a/src/Server/DefinitionFactory.php b/src/Server/DefinitionFactory.php index 31a5e3f..436dc12 100644 --- a/src/Server/DefinitionFactory.php +++ b/src/Server/DefinitionFactory.php @@ -11,14 +11,15 @@ }; use Innmind\Http\Message\{ Response, - StatusCode\StatusCode, + StatusCode, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; +use function Innmind\Immutable\first; final class DefinitionFactory { - private $denormalize; - private $decode; + private DenormalizeDefinition $denormalize; + private Decode $decode; public function __construct( DenormalizeDefinition $denormalize, @@ -30,21 +31,22 @@ public function __construct( public function __invoke( string $name, - UrlInterface $url, + Url $url, Response $response ): HttpResource { $headers = $response->headers(); if ( $response->statusCode()->value() !== StatusCode::codes()->get('OK') || - !$headers->has('Content-Type') || - (string) $headers->get('Content-Type')->values()->current() !== 'application/json' + !$headers->contains('Content-Type') || + first($headers->get('Content-Type')->values())->toString() !== 'application/json' ) { throw new DomainException; } + /** @var array{metas: array, properties: array, type: string, access: list, optional: bool}>, linkable_to: list}>, identity: string, rangeable: bool} */ $data = ($this->decode)('json', $response->body()); - $data['url'] = (string) $url; + $data['url'] = $url->toString(); return ($this->denormalize)($data, $name); } diff --git a/src/Server/Factory.php b/src/Server/Factory.php index ebead92..1c61c9b 100644 --- a/src/Server/Factory.php +++ b/src/Server/Factory.php @@ -4,9 +4,9 @@ namespace Innmind\Rest\Client\Server; use Innmind\Rest\Client\Server as ServerInterface; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; interface Factory { - public function __invoke(UrlInterface $url): ServerInterface; + public function __invoke(Url $url): ServerInterface; } diff --git a/src/Server/RetryServer.php b/src/Server/RetryServer.php index f7c5555..17e6924 100644 --- a/src/Server/RetryServer.php +++ b/src/Server/RetryServer.php @@ -12,9 +12,9 @@ Exception\DenormalizationException, }; use Innmind\HttpTransport\Exception\ClientError; -use Innmind\Http\Message\StatusCode\StatusCode; -use Innmind\Url\UrlInterface; -use Innmind\Immutable\SetInterface; +use Innmind\Http\Message\StatusCode; +use Innmind\Url\Url; +use Innmind\Immutable\Set; use Innmind\Specification\Specification; /** @@ -24,7 +24,7 @@ */ final class RetryServer implements ServerInterface { - private $server; + private ServerInterface $server; public function __construct(ServerInterface $server) { @@ -38,7 +38,7 @@ public function all( string $name, Specification $specification = null, Range $range = null - ): SetInterface { + ): Set { try { return $this->server->all($name, $specification, $range); } catch (\Throwable $e) { @@ -82,10 +82,8 @@ public function create(HttpResource $resource): Identity } } - public function update( - Identity $identity, - HttpResource $resource - ): ServerInterface { + public function update(Identity $identity, HttpResource $resource): void + { try { $this->server->update($identity, $resource); } catch (\Throwable $e) { @@ -96,11 +94,9 @@ public function update( $this->server->capabilities()->refresh(); $this->server->update($identity, $resource); } - - return $this; } - public function remove(string $name, Identity $identity): ServerInterface + public function remove(string $name, Identity $identity): void { try { $this->server->remove($name, $identity); @@ -112,18 +108,10 @@ public function remove(string $name, Identity $identity): ServerInterface $this->server->capabilities()->refresh(); $this->server->remove($name, $identity); } - - return $this; } - /** - * {@inheritdoc} - */ - public function link( - string $name, - Identity $identity, - SetInterface $links - ): ServerInterface { + public function link(string $name, Identity $identity, Set $links): void + { try { $this->server->link($name, $identity, $links); } catch (\Throwable $e) { @@ -134,18 +122,10 @@ public function link( $this->server->capabilities()->refresh(); $this->server->link($name, $identity, $links); } - - return $this; } - /** - * {@inheritdoc} - */ - public function unlink( - string $name, - Identity $identity, - SetInterface $links - ): ServerInterface { + public function unlink(string $name, Identity $identity, Set $links): void + { try { $this->server->unlink($name, $identity, $links); } catch (\Throwable $e) { @@ -156,8 +136,6 @@ public function unlink( $this->server->capabilities()->refresh(); $this->server->unlink($name, $identity, $links); } - - return $this; } public function capabilities(): Capabilities @@ -165,7 +143,7 @@ public function capabilities(): Capabilities return $this->server->capabilities(); } - public function url(): UrlInterface + public function url(): Url { return $this->server->url(); } diff --git a/src/Server/RetryServerFactory.php b/src/Server/RetryServerFactory.php index c5370aa..7ea4f2e 100644 --- a/src/Server/RetryServerFactory.php +++ b/src/Server/RetryServerFactory.php @@ -4,21 +4,21 @@ namespace Innmind\Rest\Client\Server; use Innmind\Rest\Client\Server as ServerInterface; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; final class RetryServerFactory implements Factory { - private $make; + private Factory $make; public function __construct(Factory $make) { $this->make = $make; } - public function __invoke(UrlInterface $url): ServerInterface + public function __invoke(Url $url): ServerInterface { return new RetryServer( - ($this->make)($url) + ($this->make)($url), ); } } diff --git a/src/Server/Server.php b/src/Server/Server.php index a48adbf..9c7583e 100644 --- a/src/Server/Server.php +++ b/src/Server/Server.php @@ -27,16 +27,13 @@ Serializer\Decode, }; use Innmind\HttpTransport\Transport; -use Innmind\Url\{ - UrlInterface, - Url, -}; -use Innmind\UrlResolver\ResolverInterface; +use Innmind\Url\Url; +use Innmind\UrlResolver\Resolver; use Innmind\Http\{ Message\Request\Request, - Message\Method\Method, - ProtocolVersion\ProtocolVersion, - Headers\Headers, + Message\Method, + ProtocolVersion, + Headers, Header, Header\Value, Header\Range as RangeHeader, @@ -50,32 +47,36 @@ Header\LinkValue, }; use Innmind\Immutable\{ - SetInterface, Map, Set, }; +use function Innmind\Immutable\{ + unwrap, + join, + assertSet, +}; use Innmind\Specification\Specification; final class Server implements ServerInterface { - private $url; - private $fulfill; - private $capabilities; - private $resolver; - private $extractIdentity; - private $extractIdentities; - private $denormalizeResource; - private $normalizeResource; - private $encode; - private $decode; - private $translate; - private $formats; + private Url $url; + private Transport $fulfill; + private Capabilities $capabilities; + private Resolver $resolve; + private ExtractIdentity $extractIdentity; + private ExtractIdentities $extractIdentities; + private DenormalizeResource $denormalizeResource; + private NormalizeResource $normalizeResource; + private Encode $encode; + private Decode $decode; + private SpecificationTranslator $translate; + private Formats $formats; public function __construct( - UrlInterface $url, + Url $url, Transport $fulfill, Capabilities $capabilities, - ResolverInterface $resolver, + Resolver $resolver, ExtractIdentity $extractIdentity, ExtractIdentities $extractIdentities, DenormalizeResource $denormalizeResource, @@ -88,7 +89,7 @@ public function __construct( $this->url = $url; $this->fulfill = $fulfill; $this->capabilities = $capabilities; - $this->resolver = $resolver; + $this->resolve = $resolver; $this->extractIdentity = $extractIdentity; $this->extractIdentities = $extractIdentities; $this->denormalizeResource = $denormalizeResource; @@ -99,29 +100,27 @@ public function __construct( $this->formats = $formats; } - /** - * {@inheritdoc} - */ public function all( string $name, Specification $specification = null, Range $range = null - ): SetInterface { + ): Set { $definition = $this->capabilities->get($name); if ($range !== null && !$definition->isRangeable()) { throw new ResourceNotRangeable; } + $url = $definition->url(); + if ($specification !== null) { - $query = '?'.($this->translate)($specification); + $query = Url::of('?'.($this->translate)($specification)); + $url = ($this->resolve)( + $definition->url(), + $query, + ); } - $url = $this->resolver->resolve( - (string) $definition->url(), - $query ?? (string) $definition->url() - ); - $url = Url::fromString($url); $headers = Headers::of(); if ($range !== null) { @@ -130,9 +129,9 @@ public function all( new RangeValue( 'resource', $range->firstPosition(), - $range->lastPosition() - ) - ) + $range->lastPosition(), + ), + ), ); } @@ -141,8 +140,8 @@ public function all( $url, Method::get(), new ProtocolVersion(1, 1), - $headers - ) + $headers, + ), ); return ($this->extractIdentities)($response, $definition); @@ -155,23 +154,29 @@ public function read(string $name, Identity $identity): HttpResource new Request( $this->resolveUrl( $definition->url(), - $identity + $identity, ), Method::get(), new ProtocolVersion(1, 1), Headers::of( - $this->generateAcceptHeader() - ) - ) + $this->generateAcceptHeader(), + ), + ), ); try { $format = $this->formats->matching( - (string) $response - ->headers() - ->get('Content-Type') - ->values() - ->join(', ') + join( + ', ', + $response + ->headers() + ->get('Content-Type') + ->values() + ->mapTo( + 'string', + static fn(Value $value): string => $value->toString(), + ), + )->toString(), ); } catch (\Exception $e) { throw new UnsupportedResponse('', 0, $e); @@ -179,13 +184,13 @@ public function read(string $name, Identity $identity): HttpResource $data = ($this->decode)( $format->name(), - $response->body() + $response->body(), ); return ($this->denormalizeResource)( $data, $definition, - new Access(Access::READ) + new Access(Access::READ), ); } @@ -198,95 +203,68 @@ public function create(HttpResource $resource): Identity Method::post(), new ProtocolVersion(1, 1), Headers::of( - new ContentType( - new ContentTypeValue( - 'application', - 'json' - ) - ), - $this->generateAcceptHeader() + ContentType::of('application', 'json'), + $this->generateAcceptHeader(), ), ($this->encode)( ($this->normalizeResource)( $resource, $definition, - new Access(Access::CREATE) - ) - ) - ) + new Access(Access::CREATE), + ), + ), + ), ); return ($this->extractIdentity)($response, $definition); } - public function update( - Identity $identity, - HttpResource $resource - ): ServerInterface { + public function update(Identity $identity, HttpResource $resource): void + { $definition = $this->capabilities->get($resource->name()); ($this->fulfill)( new Request( $this->resolveUrl( $definition->url(), - $identity + $identity, ), Method::put(), new ProtocolVersion(1, 1), Headers::of( - new ContentType( - new ContentTypeValue( - 'application', - 'json' - ) - ), - $this->generateAcceptHeader() + ContentType::of('application', 'json'), + $this->generateAcceptHeader(), ), ($this->encode)( ($this->normalizeResource)( $resource, $definition, - new Access(Access::UPDATE) - ) - ) - ) + new Access(Access::UPDATE), + ), + ), + ), ); - - return $this; } - public function remove(string $name, Identity $identity): ServerInterface + public function remove(string $name, Identity $identity): void { $definition = $this->capabilities->get($name); ($this->fulfill)( new Request( $this->resolveUrl( $definition->url(), - $identity + $identity, ), Method::delete(), - new ProtocolVersion(1, 1) - ) + new ProtocolVersion(1, 1), + ), ); - - return $this; } - /** - * {@inheritdoc} - */ - public function link( - string $name, - Identity $identity, - SetInterface $links - ): ServerInterface { - if ((string) $links->type() !== Link::class) { - throw new \TypeError(sprintf( - 'Argument 3 must be of type SetInterface<%s>', - Link::class - )); - } + public function link(string $name, Identity $identity, Set $links): void + { + assertSet(Link::class, $links, 3); - if ($links->size() === 0) { + if ($links->empty()) { throw new DomainException; } @@ -296,36 +274,23 @@ public function link( new Request( $this->resolveUrl( $definition->url(), - $identity + $identity, ), Method::link(), new ProtocolVersion(1, 1), Headers::of( $this->generateAcceptHeader(), - $this->generateLinkHeader($links) - ) - ) + $this->generateLinkHeader($links), + ), + ), ); - - return $this; } - /** - * {@inheritdoc} - */ - public function unlink( - string $name, - Identity $identity, - SetInterface $links - ): ServerInterface { - if ((string) $links->type() !== Link::class) { - throw new \TypeError(sprintf( - 'Argument 3 must be of type SetInterface<%s>', - Link::class - )); - } + public function unlink(string $name, Identity $identity, Set $links): void + { + assertSet(Link::class, $links, 3); - if ($links->size() === 0) { + if ($links->empty()) { throw new DomainException; } @@ -335,18 +300,16 @@ public function unlink( new Request( $this->resolveUrl( $definition->url(), - $identity + $identity, ), Method::unlink(), new ProtocolVersion(1, 1), Headers::of( $this->generateAcceptHeader(), - $this->generateLinkHeader($links) - ) - ) + $this->generateLinkHeader($links), + ), + ), ); - - return $this; } public function capabilities(): Capabilities @@ -354,49 +317,44 @@ public function capabilities(): Capabilities return $this->capabilities; } - public function url(): UrlInterface + public function url(): Url { return $this->url; } - private function resolveUrl( - UrlInterface $url, - Identity $identity - ): UrlInterface { - $url = (string) $url; - $url = \rtrim($url, '/').'/'.$identity; + private function resolveUrl(Url $url, Identity $identity): Url + { + $url = \rtrim($url->toString(), '/').'/'.$identity->toString(); - return Url::fromString($url); + return Url::of($url); } private function generateAcceptHeader(): Accept { return new Accept( - ...$this + ...unwrap($this ->formats ->all() ->values() - ->sort(function(Format $a, Format $b): bool { - return $a->priority() < $b->priority(); + ->sort(function(Format $a, Format $b): int { + return (int) ($a->priority() < $b->priority()); }) - ->reduce( - new Set(Value::class), - function(Set $values, Format $format): Set { - return $values->add(new AcceptValue( - $format->preferredMediaType()->topLevel(), - $format->preferredMediaType()->subType() - )); - } - ) + ->mapTo( + Value::class, + static fn(Format $format): AcceptValue => new AcceptValue( + $format->preferredMediaType()->topLevel(), + $format->preferredMediaType()->subType() + ), + )), ); } - private function generateLinkHeader(SetInterface $links): LinkHeader + private function generateLinkHeader(Set $links): LinkHeader { return new LinkHeader( - ...$links->reduce( - new Set(Value::class), - function(Set $carry, Link $link): Set { + ...unwrap($links->mapTo( + Value::class, + function(Link $link): LinkValue { $url = $this->resolveUrl( $this ->capabilities @@ -404,38 +362,33 @@ function(Set $carry, Link $link): Set { ->url(), $link->identity() ); - - return $carry->add( - new LinkValue( - Url::fromString((string) $url->path()), - $link->relationship(), - $link - ->parameters() - ->reduce( - new Map('string', HeaderParameter::class), - function(Map $carry, string $name, Parameter $parameter): Map { - return $carry->put( - $name, - new HeaderParameter\Parameter( - $parameter->key(), - $parameter->value() - ) - ); - } - ) - ) + /** @var Set */ + $parameters = $link + ->parameters() + ->toSetOf( + HeaderParameter::class, + static fn(string $name, Parameter $parameter): \Generator => yield new HeaderParameter\Parameter( + $parameter->key(), + $parameter->value(), + ), + ); + + return new LinkValue( + Url::of($url->path()->toString()), + $link->relationship(), + ...unwrap($parameters) ); - } - ) + }, + )), ); } /** - * @param SetInterface $links + * @param Set $links * * @throws NormalizationException */ - private function validateLinks(Definition $definition, SetInterface $links): void + private function validateLinks(Definition $definition, Set $links): void { $links->foreach(function(Link $link) use ($definition): void { if (!$definition->allowsLink($link)) { diff --git a/src/Server/ServerFactory.php b/src/Server/ServerFactory.php index 1a8338b..cb6a417 100644 --- a/src/Server/ServerFactory.php +++ b/src/Server/ServerFactory.php @@ -14,27 +14,27 @@ Serializer\Encode, Serializer\Decode, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\HttpTransport\Transport; -use Innmind\UrlResolver\ResolverInterface; +use Innmind\UrlResolver\Resolver; final class ServerFactory implements Factory { - private $transport; - private $resolver; - private $extractIdentity; - private $extractIdentities; - private $denormalizeResource; - private $normalizeResource; - private $encode; - private $decode; - private $translator; - private $formats; - private $capabilities; + private Transport $transport; + private Resolver $resolver; + private ExtractIdentity $extractIdentity; + private ExtractIdentities $extractIdentities; + private DenormalizeResource $denormalizeResource; + private NormalizeResource $normalizeResource; + private Encode $encode; + private Decode $decode; + private SpecificationTranslator $translator; + private Formats $formats; + private Capabilities\Factory $capabilities; public function __construct( Transport $transport, - ResolverInterface $resolver, + Resolver $resolver, ExtractIdentity $extractIdentity, ExtractIdentities $extractIdentities, DenormalizeResource $denormalizeResource, @@ -58,7 +58,7 @@ public function __construct( $this->capabilities = $capabilities; } - public function __invoke(UrlInterface $url): ServerInterface + public function __invoke(Url $url): ServerInterface { return new Server( $url, @@ -72,7 +72,7 @@ public function __invoke(UrlInterface $url): ServerInterface $this->encode, $this->decode, $this->translator, - $this->formats + $this->formats, ); } } diff --git a/src/Translator/Specification/SpecificationTranslator.php b/src/Translator/Specification/SpecificationTranslator.php index 662d0aa..88f9038 100644 --- a/src/Translator/Specification/SpecificationTranslator.php +++ b/src/Translator/Specification/SpecificationTranslator.php @@ -17,9 +17,6 @@ Sign, }; -/** - * {@inheritdoc} - */ final class SpecificationTranslator implements SpecificationTranslatorInterface { public function __invoke(Specification $specification): string @@ -30,10 +27,11 @@ public function __invoke(Specification $specification): string throw new OnlyEqualityCanBeTranslated; } + /** @psalm-suppress MixedArgument */ return \sprintf( '%s=%s', $specification->property(), - $specification->value() + $specification->value(), ); case $specification instanceof Composite: @@ -44,7 +42,7 @@ public function __invoke(Specification $specification): string return \sprintf( '%s&%s', $this($specification->left()), - $this($specification->right()) + $this($specification->right()), ); default: diff --git a/src/Visitor/ResolveIdentity.php b/src/Visitor/ResolveIdentity.php index 0f2ef97..78eb697 100644 --- a/src/Visitor/ResolveIdentity.php +++ b/src/Visitor/ResolveIdentity.php @@ -3,30 +3,29 @@ namespace Innmind\Rest\Client\Visitor; -use Innmind\UrlResolver\ResolverInterface; -use Innmind\Url\UrlInterface; +use Innmind\UrlResolver\Resolver; +use Innmind\Url\Url; final class ResolveIdentity { - private $resolver; + private Resolver $resolve; - public function __construct(ResolverInterface $resolver) + public function __construct(Resolver $resolver) { - $this->resolver = $resolver; + $this->resolve = $resolver; } public function __invoke( - UrlInterface $source, - UrlInterface $destination + Url $source, + Url $destination ): string { - $source = (string) $source; - $source = \rtrim($source, '/').'/'; + $source = Url::of(\rtrim($source->toString(), '/').'/'); - $trueDestination = $this->resolver->resolve( + $trueDestination = ($this->resolve)( $source, - (string) $destination + $destination, ); - return \str_replace($source, '', $trueDestination); + return \str_replace($source->toString(), '', $trueDestination->toString()); } } diff --git a/src/bootstrap.php b/src/bootstrap.php index aa66b42..17e91eb 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -26,19 +26,18 @@ Response\ExtractIdentities, }; use Innmind\HttpTransport\Transport; -use Innmind\UrlResolver\ResolverInterface; +use Innmind\UrlResolver\Resolver; use Innmind\Filesystem\Adapter; use Innmind\Immutable\{ - SetInterface, Set, Map, }; function bootstrap( Transport $transport, - ResolverInterface $urlResolver, + Resolver $urlResolver, Adapter $cache, - SetInterface $types = null, + Set $types = null, Formats $contentTypes = null, Decode $decode = null ): Client { @@ -47,8 +46,8 @@ function bootstrap( new Format( 'json', Set::of(MediaType::class, new MediaType('application/json', 0)), - 0 - ) + 0, + ), ); $types = new Types(...($types ?? [])); $resolveIdentity = new ResolveIdentity($urlResolver); @@ -82,11 +81,11 @@ function bootstrap( $transport, $urlResolver, new DefinitionFactory($denormalizeDefinition, $decode), - $contentTypes - ) - ) - ) - ) - ) + $contentTypes, + ), + ), + ), + ), + ), ); } diff --git a/tests/BootstrapTest.php b/tests/BootstrapTest.php index 80543d1..3e9aedd 100644 --- a/tests/BootstrapTest.php +++ b/tests/BootstrapTest.php @@ -6,7 +6,7 @@ use function Innmind\Rest\Client\bootstrap; use Innmind\Rest\Client\Client; use Innmind\HttpTransport\Transport; -use Innmind\UrlResolver\ResolverInterface; +use Innmind\UrlResolver\Resolver; use Innmind\Filesystem\Adapter; use PHPUnit\Framework\TestCase; @@ -16,7 +16,7 @@ public function testBootstrap() { $client = bootstrap( $this->createMock(Transport::class), - $this->createMock(ResolverInterface::class), + $this->createMock(Resolver::class), $this->createMock(Adapter::class) ); diff --git a/tests/Client/ClientTest.php b/tests/Client/ClientTest.php index 6a2ba12..9671109 100644 --- a/tests/Client/ClientTest.php +++ b/tests/Client/ClientTest.php @@ -16,7 +16,7 @@ class ClientTest extends TestCase private $client; private $factory; - public function setUp() + public function setUp(): void { $this->client = new Client( $this->factory = $this->createMock(Factory::class) @@ -38,14 +38,14 @@ public function testServer() ->expects($this->at(0)) ->method('__invoke') ->with($this->callback(function($url): bool { - return (string) $url === 'http://example.com/'; + return $url->toString() === 'http://example.com/'; })); $this ->factory ->expects($this->at(1)) ->method('__invoke') ->with($this->callback(function($url): bool { - return (string) $url === 'http://example.com/api/'; + return $url->toString() === 'http://example.com/api/'; })); $server = $this->client->server('http://example.com/'); diff --git a/tests/Definition/AccessTest.php b/tests/Definition/AccessTest.php index e2cdde5..50266dd 100644 --- a/tests/Definition/AccessTest.php +++ b/tests/Definition/AccessTest.php @@ -4,7 +4,8 @@ namespace Tests\Innmind\Rest\Client\Definition; use Innmind\Rest\Client\Definition\Access; -use Innmind\Immutable\SetInterface; +use Innmind\Immutable\Set; +use function Innmind\Immutable\unwrap; use PHPUnit\Framework\TestCase; class AccessTest extends TestCase @@ -62,11 +63,11 @@ public function testMask() Access::UPDATE ); - $this->assertInstanceOf(SetInterface::class, $access->mask()); + $this->assertInstanceOf(Set::class, $access->mask()); $this->assertSame('string', (string) $access->mask()->type()); $this->assertSame( [Access::READ, Access::CREATE, Access::UPDATE], - $access->mask()->toPrimitive() + unwrap($access->mask()) ); } diff --git a/tests/Definition/AllowedLinkTest.php b/tests/Definition/AllowedLinkTest.php index 4d52ede..7b0275e 100644 --- a/tests/Definition/AllowedLinkTest.php +++ b/tests/Definition/AllowedLinkTest.php @@ -26,7 +26,7 @@ public function testInterface() public function testThrowWhenInvalidParameterSet() { $this->expectException(\TypeError::class); - $this->expectExceptionMessage('Argument 3 must be of type SetInterface'); + $this->expectExceptionMessage('Argument 3 must be of type Set'); new AllowedLink('path', 'rel', Set::of('object')); } diff --git a/tests/Definition/HttpResourceTest.php b/tests/Definition/HttpResourceTest.php index 91e5029..3457da6 100644 --- a/tests/Definition/HttpResourceTest.php +++ b/tests/Definition/HttpResourceTest.php @@ -11,8 +11,9 @@ Link, Link\Parameter, Identity as IdentityInterface, + Exception\DomainException, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\Immutable\{ Map, Set, @@ -25,16 +26,16 @@ public function testInterface() { $resource = new HttpResource( 'foo', - $url = $this->createMock(UrlInterface::class), + $url = Url::of('http://example.com/'), $identity = new Identity('uuid'), - $properties = new Map('string', Property::class), - $metas = new Map('scalar', 'variable'), - $links = new Set(AllowedLink::class), + $properties = Map::of('string', Property::class), + $metas = Map::of('scalar', 'scalar|array'), + $links = Set::of(AllowedLink::class), true ); $this->assertSame('foo', $resource->name()); - $this->assertSame('foo', (string) $resource); + $this->assertSame('foo', $resource->toString()); $this->assertSame($url, $resource->url()); $this->assertSame($identity, $resource->identity()); $this->assertSame($properties, $resource->properties()); @@ -43,69 +44,65 @@ public function testInterface() $this->assertTrue($resource->isRangeable()); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyName() { + $this->expectException(DomainException::class); + new HttpResource( '', - $this->createMock(UrlInterface::class), + Url::of('http://example.com/'), new Identity('uuid'), - new Map('string', Property::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', Property::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), true ); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 4 must be of type MapInterface - */ public function testThrowWhenInvalidPropertyMap() { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 4 must be of type Map'); + new HttpResource( 'foo', - $this->createMock(UrlInterface::class), + Url::of('http://example.com/'), new Identity('uuid'), - new Map('int', Property::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('int', Property::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), true ); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 5 must be of type MapInterface - */ public function testThrowWhenInvalidMetaMap() { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 5 must be of type Map'); + new HttpResource( 'foo', - $this->createMock(UrlInterface::class), + Url::of('http://example.com/'), new Identity('uuid'), - new Map('string', Property::class), - new Map('string', 'scalar'), - new Set(AllowedLink::class), + Map::of('string', Property::class), + Map::of('string', 'scalar'), + Set::of(AllowedLink::class), true ); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 6 must be of type SetInterface - */ public function testThrowWhenInvalidLinkMap() { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 6 must be of type Set'); + new HttpResource( 'foo', - $this->createMock(UrlInterface::class), + Url::of('http://example.com/'), new Identity('uuid'), - new Map('string', Property::class), - new Map('scalar', 'variable'), - new Set('string'), + Map::of('string', Property::class), + Map::of('scalar', 'scalar|array'), + Set::of('string'), true ); } @@ -114,10 +111,10 @@ public function testAllowsLink() { $resource = new HttpResource( 'foo', - $this->createMock(UrlInterface::class), + Url::of('http://example.com/'), new Identity('uuid'), - new Map('string', Property::class), - new Map('scalar', 'variable'), + Map::of('string', Property::class), + Map::of('scalar', 'scalar|array'), Set::of( AllowedLink::class, new AllowedLink( diff --git a/tests/Definition/IdentityTest.php b/tests/Definition/IdentityTest.php index e088c69..65474f3 100644 --- a/tests/Definition/IdentityTest.php +++ b/tests/Definition/IdentityTest.php @@ -3,16 +3,18 @@ namespace Tests\Innmind\Rest\Client\Definition; -use Innmind\Rest\Client\Definition\Identity; +use Innmind\Rest\Client\{ + Definition\Identity, + Exception\DomainException, +}; use PHPUnit\Framework\TestCase; class IdentityTest extends TestCase { - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyIdentity() { + $this->expectException(DomainException::class); + new Identity(''); } @@ -20,7 +22,7 @@ public function testInterface() { $this->assertSame( 'foo', - (string) new Identity('foo') + (new Identity('foo'))->toString() ); } } diff --git a/tests/Definition/PropertyTest.php b/tests/Definition/PropertyTest.php index b99bbee..3a073d3 100644 --- a/tests/Definition/PropertyTest.php +++ b/tests/Definition/PropertyTest.php @@ -3,41 +3,40 @@ namespace Tests\Innmind\Rest\Client\Definition; -use Innmind\Rest\Client\Definition\{ - Property, - Type, - Access, +use Innmind\Rest\Client\{ + Definition\Property, + Definition\Type, + Definition\Access, + Exception\DomainException, }; use Innmind\Immutable\Set; use PHPUnit\Framework\TestCase; class PropertyTest extends TestCase { - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyName() { + $this->expectException(DomainException::class); + new Property( '', $this->createMock(Type::class), new Access, - new Set('string'), + Set::of('string'), true ); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 4 must be of type SetInterface - */ public function testThrowWhenInvalidVariants() { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 4 must be of type Set'); + new Property( 'foo', $this->createMock(Type::class), new Access, - new Set('int'), + Set::of('int'), true ); } @@ -48,7 +47,7 @@ public function testInterface() 'foo', $type = $this->createMock(Type::class), $access = new Access, - $variants = new Set('string'), + $variants = Set::of('string'), true ); @@ -65,7 +64,7 @@ public function assertNotOptional() 'foo', $this->createMock(Type::class), new Access, - new Set('string'), + Set::of('string'), false ); diff --git a/tests/Definition/Type/BoolTypeTest.php b/tests/Definition/Type/BoolTypeTest.php index c61c46d..ba76b29 100644 --- a/tests/Definition/Type/BoolTypeTest.php +++ b/tests/Definition/Type/BoolTypeTest.php @@ -3,10 +3,11 @@ namespace Tests\Innmind\Rest\Client\Definition\Type; -use Innmind\Rest\Client\Definition\{ - Type\BoolType, - Types, - Type, +use Innmind\Rest\Client\{ + Definition\Type\BoolType, + Definition\Types, + Definition\Type, + Exception\DomainException, }; use PHPUnit\Framework\TestCase; @@ -19,7 +20,7 @@ public function testInterface() public function testFromString() { - $type = BoolType::fromString( + $type = BoolType::of( 'bool', new Types ); @@ -27,12 +28,11 @@ public function testFromString() $this->assertInstanceOf(BoolType::class, $type); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenBuildInvalidType() { - BoolType::fromString('int', new Types); + $this->expectException(DomainException::class); + + BoolType::of('int', new Types); } public function testNormalize() @@ -67,6 +67,6 @@ public function testDenormalize() public function testCast() { - $this->assertSame('bool', (string) new BoolType); + $this->assertSame('bool', (new BoolType)->toString()); } } diff --git a/tests/Definition/Type/DateTypeTest.php b/tests/Definition/Type/DateTypeTest.php index 44d0282..162176a 100644 --- a/tests/Definition/Type/DateTypeTest.php +++ b/tests/Definition/Type/DateTypeTest.php @@ -3,10 +3,13 @@ namespace Tests\Innmind\Rest\Client\Definition\Type; -use Innmind\Rest\Client\Definition\{ - Type\DateType, - Types, - Type, +use Innmind\Rest\Client\{ + Definition\Type\DateType, + Definition\Types, + Definition\Type, + Exception\DomainException, + Exception\NormalizationException, + Exception\DenormalizationException, }; use PHPUnit\Framework\TestCase; @@ -19,7 +22,7 @@ public function testInterface() public function testFromString() { - $type = DateType::fromString( + $type = DateType::of( 'date', new Types ); @@ -27,12 +30,11 @@ public function testFromString() $this->assertInstanceOf(DateType::class, $type); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenBuildInvalidType() { - DateType::fromString('date<>', new Types); + $this->expectException(DomainException::class); + + DateType::of('date<>', new Types); } public function testNormalize() @@ -50,21 +52,19 @@ public function testNormalize() ); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - * @expectedExceptionMessage The value must be an instance of \DateTimeInterface - */ public function testThrowWhenNormalizingInvalidData() { + $this->expectException(NormalizationException::class); + $this->expectExceptionMessage('The value must be an instance of \DateTimeInterface'); + (new DateType('c'))->normalize(new \stdClass); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - * @expectedExceptionMessage The value must be a date - */ public function testThrowWhenNormalizingInvalidDateString() { + $this->expectException(NormalizationException::class); + $this->expectExceptionMessage('The value must be a date'); + (new DateType('c'))->normalize('foo'); } @@ -77,26 +77,24 @@ public function testDenormalize() $this->assertSame('2016-01-30', $value->format('Y-m-d')); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be a string - */ public function testThrowWhenDenormalizingInvalidData() { + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be a string'); + (new DateType('c'))->denormalize(new \stdClass); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be a valid date - */ public function testThrowWhenDenormalizingInvalidDateString() { + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be a valid date'); + (new DateType('c'))->denormalize('foo'); } public function testCast() { - $this->assertSame('date', (string) new DateType('c')); + $this->assertSame('date', (new DateType('c'))->toString()); } } diff --git a/tests/Definition/Type/FloatTypeTest.php b/tests/Definition/Type/FloatTypeTest.php index ec2386f..befaa49 100644 --- a/tests/Definition/Type/FloatTypeTest.php +++ b/tests/Definition/Type/FloatTypeTest.php @@ -3,10 +3,13 @@ namespace Tests\Innmind\Rest\Client\Definition\Type; -use Innmind\Rest\Client\Definition\{ - Type\FloatType, - Types, - Type, +use Innmind\Rest\Client\{ + Definition\Type\FloatType, + Definition\Types, + Definition\Type, + Exception\DomainException, + Exception\NormalizationException, + Exception\DenormalizationException, }; use PHPUnit\Framework\TestCase; @@ -19,7 +22,7 @@ public function testInterface() public function testFromString() { - $type = FloatType::fromString( + $type = FloatType::of( 'float', new Types ); @@ -27,12 +30,11 @@ public function testFromString() $this->assertInstanceOf(FloatType::class, $type); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenBuildInvalidType() { - FloatType::fromString('int', new Types); + $this->expectException(DomainException::class); + + FloatType::of('int', new Types); } public function testNormalize() @@ -44,12 +46,11 @@ public function testNormalize() $this->assertSame(1.2, (new FloatType)->normalize('1.2')); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - * @expectedExceptionMessage The value must be a float - */ public function testThrowWhenNormalizingInvalidData() { + $this->expectException(NormalizationException::class); + $this->expectExceptionMessage('The value must be a float'); + (new FloatType)->normalize(new \stdClass); } @@ -62,17 +63,16 @@ public function testDenormalize() $this->assertSame(1.2, (new FloatType)->denormalize('1.2')); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be a float - */ public function testThrowWhenDenormalizingInvalidData() { + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be a float'); + (new FloatType)->denormalize(new \stdClass); } public function testCast() { - $this->assertSame('float', (string) new FloatType); + $this->assertSame('float', (new FloatType)->toString()); } } diff --git a/tests/Definition/Type/IntTypeTest.php b/tests/Definition/Type/IntTypeTest.php index e38e761..0011797 100644 --- a/tests/Definition/Type/IntTypeTest.php +++ b/tests/Definition/Type/IntTypeTest.php @@ -3,10 +3,13 @@ namespace Tests\Innmind\Rest\Client\Definition\Type; -use Innmind\Rest\Client\Definition\{ - Type\IntType, - Types, - Type, +use Innmind\Rest\Client\{ + Definition\Type\IntType, + Definition\Types, + Definition\Type, + Exception\DomainException, + Exception\NormalizationException, + Exception\DenormalizationException, }; use PHPUnit\Framework\TestCase; @@ -19,7 +22,7 @@ public function testInterface() public function testFromString() { - $type = IntType::fromString( + $type = IntType::of( 'int', new Types ); @@ -27,12 +30,11 @@ public function testFromString() $this->assertInstanceOf(IntType::class, $type); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenBuildInvalidType() { - IntType::fromString('float', new Types); + $this->expectException(DomainException::class); + + IntType::of('float', new Types); } public function testNormalize() @@ -44,12 +46,11 @@ public function testNormalize() $this->assertSame(1, (new IntType)->normalize('1.2')); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - * @expectedExceptionMessage The value must be an integer - */ public function testThrowWhenNormalizingInvalidData() { + $this->expectException(NormalizationException::class); + $this->expectExceptionMessage('The value must be an integer'); + (new IntType)->normalize(new \stdClass); } @@ -62,17 +63,16 @@ public function testDenormalize() $this->assertSame(1, (new IntType)->denormalize('1.2')); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be an integer - */ public function testThrowWhenDenormalizingInvalidData() { + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be an integer'); + (new IntType)->denormalize(new \stdClass); } public function testCast() { - $this->assertSame('int', (string) new IntType); + $this->assertSame('int', (new IntType)->toString()); } } diff --git a/tests/Definition/Type/MapTypeTest.php b/tests/Definition/Type/MapTypeTest.php index 5d57486..8cc77fe 100644 --- a/tests/Definition/Type/MapTypeTest.php +++ b/tests/Definition/Type/MapTypeTest.php @@ -3,17 +3,17 @@ namespace Tests\Innmind\Rest\Client\Definition\Type; -use Innmind\Rest\Client\Definition\{ - Type\MapType, - Type\DateType, - Type\IntType, - Types, - Type, -}; -use Innmind\Immutable\{ - MapInterface, - Map, +use Innmind\Rest\Client\{ + Definition\Type\MapType, + Definition\Type\DateType, + Definition\Type\IntType, + Definition\Types, + Definition\Type, + Exception\DomainException, + Exception\NormalizationException, + Exception\DenormalizationException, }; +use Innmind\Immutable\Map; use PHPUnit\Framework\TestCase; class MapTypeTest extends TestCase @@ -32,14 +32,14 @@ public function testInterface() public function testFromString() { $types = new Types(DateType::class, IntType::class); - $type = MapType::fromString( + $type = MapType::of( 'map>', $types ); $this->assertInstanceOf(MapType::class, $type); - $type = MapType::fromString( + $type = MapType::of( 'map>', $types ); @@ -47,12 +47,11 @@ public function testFromString() $this->assertInstanceOf(MapType::class, $type); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenBuildInvalidType() { - MapType::fromString('map<,>', new Types); + $this->expectException(DomainException::class); + + MapType::of('map<,>', new Types); } public function testNormalize() @@ -85,12 +84,11 @@ public function testNormalize() ); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - * @expectedExceptionMessage The value must be an instance of Innmind\Immutable\MapInterface - */ public function testThrowWhenNormalizingInvalidData() { + $this->expectException(NormalizationException::class); + $this->expectExceptionMessage('The value must be an instance of Innmind\Immutable\Map'); + (new MapType(new IntType, new DateType('c')))->normalize(new \stdClass); } @@ -99,31 +97,29 @@ public function testDenormalize() $date = new MapType(new IntType, new DateType('d/m/Y')); $value = $date->denormalize(['2' => '30/01/2016']); - $this->assertInstanceOf(MapInterface::class, $value); + $this->assertInstanceOf(Map::class, $value); $this->assertSame('int', (string) $value->keyType()); $this->assertSame(\DateTimeImmutable::class, (string) $value->valueType()); $this->assertCount(1, $value); $this->assertSame('2016-01-30', $value->get(2)->format('Y-m-d')); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be an array - */ public function testThrowWhenDenormalizingInvalidData() { + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be an array'); + (new MapType(new IntType, new DateType('c')))->denormalize(new \stdClass); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be a valid map - */ public function testThrowWhenDenormalizingInvalidDateString() { $values = new \SplObjectStorage; $values->attach(new \stdClass, 'foo'); + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be a valid map'); + (new MapType(new IntType, new DateType('c')))->denormalize($values); } @@ -131,7 +127,7 @@ public function testCast() { $this->assertSame( 'map>', - (string) new MapType(new IntType, new DateType('c')) + (new MapType(new IntType, new DateType('c')))->toString() ); } } diff --git a/tests/Definition/Type/SetTypeTest.php b/tests/Definition/Type/SetTypeTest.php index f23c4ad..4123ba4 100644 --- a/tests/Definition/Type/SetTypeTest.php +++ b/tests/Definition/Type/SetTypeTest.php @@ -3,16 +3,17 @@ namespace Tests\Innmind\Rest\Client\Definition\Type; -use Innmind\Rest\Client\Definition\{ - Type\SetType, - Type\DateType, - Types, - Type, -}; -use Innmind\Immutable\{ - SetInterface, - Set, +use Innmind\Rest\Client\{ + Definition\Type\SetType, + Definition\Type\DateType, + Definition\Types, + Definition\Type, + Exception\DomainException, + Exception\NormalizationException, + Exception\DenormalizationException, }; +use Innmind\Immutable\Set; +use function Innmind\Immutable\first; use PHPUnit\Framework\TestCase; class SetTypeTest extends TestCase @@ -27,7 +28,7 @@ public function testInterface() public function testFromString() { - $type = SetType::fromString( + $type = SetType::of( 'set>', new Types(DateType::class) ); @@ -35,12 +36,11 @@ public function testFromString() $this->assertInstanceOf(SetType::class, $type); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenBuildInvalidType() { - SetType::fromString('set<>', new Types); + $this->expectException(DomainException::class); + + SetType::of('set<>', new Types); } public function testNormalize() @@ -67,12 +67,11 @@ public function testNormalize() ); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - * @expectedExceptionMessage The value must be an instance of Innmind\Immutable\SetInterface - */ public function testThrowWhenNormalizingInvalidData() { + $this->expectException(NormalizationException::class); + $this->expectExceptionMessage('The value must be an instance of Innmind\Immutable\Set'); + (new SetType(new DateType('c')))->normalize(new \stdClass); } @@ -81,26 +80,24 @@ public function testDenormalize() $date = new SetType(new DateType('d/m/Y')); $value = $date->denormalize(['30/01/2016']); - $this->assertInstanceOf(SetInterface::class, $value); + $this->assertInstanceOf(Set::class, $value); $this->assertSame(\DateTimeImmutable::class, (string) $value->type()); - $this->assertSame('2016-01-30', $value->current()->format('Y-m-d')); + $this->assertSame('2016-01-30', first($value)->format('Y-m-d')); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be an array - */ public function testThrowWhenDenormalizingInvalidData() { + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be an array'); + (new SetType(new DateType('c')))->denormalize(new \stdClass); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be a valid set - */ public function testThrowWhenDenormalizingInvalidDateString() { + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be a valid set'); + (new SetType(new DateType('c')))->denormalize(['foo']); } @@ -108,7 +105,7 @@ public function testCast() { $this->assertSame( 'set>', - (string) new SetType(new DateType('c')) + (new SetType(new DateType('c')))->toString() ); } } diff --git a/tests/Definition/Type/StringTypeTest.php b/tests/Definition/Type/StringTypeTest.php index 4f993ad..5e38408 100644 --- a/tests/Definition/Type/StringTypeTest.php +++ b/tests/Definition/Type/StringTypeTest.php @@ -3,10 +3,13 @@ namespace Tests\Innmind\Rest\Client\Definition\Type; -use Innmind\Rest\Client\Definition\{ - Type\StringType, - Types, - Type, +use Innmind\Rest\Client\{ + Definition\Type\StringType, + Definition\Types, + Definition\Type, + Exception\DomainException, + Exception\NormalizationException, + Exception\DenormalizationException, }; use PHPUnit\Framework\TestCase; @@ -19,7 +22,7 @@ public function testInterface() public function testFromString() { - $type = StringType::fromString( + $type = StringType::of( 'string', new Types ); @@ -27,12 +30,11 @@ public function testFromString() $this->assertInstanceOf(StringType::class, $type); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenBuildInvalidType() { - StringType::fromString('int', new Types); + $this->expectException(DomainException::class); + + StringType::of('int', new Types); } public function testNormalize() @@ -44,12 +46,11 @@ public function testNormalize() $this->assertSame('1.2', (new StringType)->normalize('1.2')); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - * @expectedExceptionMessage The value must be a string - */ public function testThrowWhenNormalizingInvalidData() { + $this->expectException(NormalizationException::class); + $this->expectExceptionMessage('The value must be a string'); + (new StringType)->normalize(new \stdClass); } @@ -62,17 +63,16 @@ public function testDenormalize() $this->assertSame('1.2', (new StringType)->denormalize('1.2')); } - /** - * @expectedException Innmind\Rest\Client\Exception\DenormalizationException - * @expectedExceptionMessage The value must be a string - */ public function testThrowWhenDenormalizingInvalidData() { + $this->expectException(DenormalizationException::class); + $this->expectExceptionMessage('The value must be a string'); + (new StringType)->denormalize(new \stdClass); } public function testCast() { - $this->assertSame('string', (string) new StringType); + $this->assertSame('string', (new StringType)->toString()); } } diff --git a/tests/Definition/TypesTest.php b/tests/Definition/TypesTest.php index a156222..1cb8834 100644 --- a/tests/Definition/TypesTest.php +++ b/tests/Definition/TypesTest.php @@ -14,24 +14,25 @@ Definition\Type\SetType, Definition\Type\StringType, Exception\DomainException, + Exception\UnknownType, }; -use Innmind\Immutable\SetInterface; +use Innmind\Immutable\Set; +use function Innmind\Immutable\unwrap; use PHPUnit\Framework\TestCase; class TypesTest extends TestCase { - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenRegisteringInvalidType() { + $this->expectException(DomainException::class); + new Types('stdClass'); } public function testBuild() { $type1 = new class implements Type { - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { if ($type !== 'type1') { throw new DomainException; @@ -48,13 +49,13 @@ public function denormalize($data) { } - public function __toString(): string + public function toString(): string { return 'type1'; } }; $type2 = new class implements Type { - public static function fromString(string $type, Types $build): Type + public static function of(string $type, Types $build): Type { if ($type !== 'type2') { throw new DomainException; @@ -71,7 +72,7 @@ public function denormalize($data) { } - public function __toString(): string + public function toString(): string { return 'type2'; } @@ -84,11 +85,10 @@ public function __toString(): string $this->assertInstanceOf($class2, $build('type2')); } - /** - * @expectedException Innmind\Rest\Client\Exception\UnknownType - */ public function testThrowWhenBuildingUnknownType() { + $this->expectException(UnknownType::class); + (new Types)('type1'); } @@ -96,7 +96,7 @@ public function testDefaults() { $defaults = Types::defaults(); - $this->assertInstanceOf(SetInterface::class, $defaults); + $this->assertInstanceOf(Set::class, $defaults); $this->assertSame('string', (string) $defaults->type()); $this->assertCount(7, $defaults); $this->assertSame( @@ -109,7 +109,7 @@ public function testDefaults() SetType::class, StringType::class, ], - $defaults->toPrimitive() + unwrap($defaults) ); $this->assertInstanceOf(BoolType::class, (new Types)('bool')); diff --git a/tests/Format/FormatTest.php b/tests/Format/FormatTest.php index dd2c022..9481e09 100644 --- a/tests/Format/FormatTest.php +++ b/tests/Format/FormatTest.php @@ -3,9 +3,10 @@ namespace Tests\Innmind\Rest\Client\Format; -use Innmind\Rest\Client\Format\{ - Format, - MediaType, +use Innmind\Rest\Client\{ + Format\Format, + Format\MediaType, + Exception\DomainException, }; use Innmind\Immutable\Set; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ public function testInterface() ); $this->assertSame('json', $format->name()); - $this->assertSame('json', (string) $format); + $this->assertSame('json', $format->toString()); $this->assertSame($types, $format->mediaTypes()); $this->assertSame(24, $format->priority()); } @@ -43,23 +44,21 @@ public function testPreferredMediaType() $mime = $format->preferredMediaType(); $this->assertInstanceOf(MediaType::class, $mime); - $this->assertSame('application/json', (string) $mime); + $this->assertSame('application/json', $mime->toString()); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 2 must be of type SetInterface - */ public function testThrowWhenInvalidMediaType() { - new Format('foo', new Set('string'), 42); + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 2 must be of type Set'); + + new Format('foo', Set::of('string'), 42); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenNoMediaType() { - new Format('foo', new Set(MediaType::class), 42); + $this->expectException(DomainException::class); + + new Format('foo', Set::of(MediaType::class), 42); } } diff --git a/tests/Format/MediaTypeTest.php b/tests/Format/MediaTypeTest.php index 52fc13c..28c9651 100644 --- a/tests/Format/MediaTypeTest.php +++ b/tests/Format/MediaTypeTest.php @@ -4,6 +4,7 @@ namespace Tests\Innmind\Rest\Client\Format; use Innmind\Rest\Client\Format\MediaType; +use Innmind\MediaType\Exception\InvalidMediaTypeString; use PHPUnit\Framework\TestCase; class MediaTypeTest extends TestCase @@ -12,18 +13,17 @@ public function testInterface() { $mime = new MediaType($string = 'application/vnd.media-type+suffix', 42); - $this->assertSame($string, (string) $mime); + $this->assertSame($string, $mime->toString()); $this->assertSame('application', $mime->topLevel()); $this->assertSame('vnd.media-type', $mime->subType()); $this->assertSame('suffix', $mime->suffix()); $this->assertSame(42, $mime->priority()); } - /** - * @expectedException Innmind\Filesystem\Exception\InvalidMediaTypeString - */ public function testThrowWhenInvalidMediaTypeGiven() { + $this->expectException(InvalidMediaTypeString::class); + new MediaType('foo', 42); } } diff --git a/tests/FormatsTest.php b/tests/FormatsTest.php index 525a734..c174a13 100644 --- a/tests/FormatsTest.php +++ b/tests/FormatsTest.php @@ -7,10 +7,11 @@ Formats, Format\Format, Format\MediaType, + Exception\InvalidArgumentException, + Exception\DomainException, }; use Innmind\Immutable\{ Map, - SetInterface, Set, }; use PHPUnit\Framework\TestCase; @@ -55,30 +56,27 @@ public function testOf() $this->assertSame($format, $formats->get('json')); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 1 must be of type MapInterface - */ public function testThrowWhenInvalidMapKey() { - new Formats(new Map('int', Format::class)); + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 1 must be of type Map'); + + new Formats(Map::of('int', Format::class)); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 1 must be of type MapInterface - */ public function testThrowWhenInvalidMapValue() { - new Formats(new Map('string', 'string')); + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 1 must be of type Map'); + + new Formats(Map::of('string', 'string')); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyMap() { - new Formats(new Map('string', Format::class)); + $this->expectException(DomainException::class); + + new Formats(Map::of('string', Format::class)); } public function testMediaTypes() @@ -111,7 +109,7 @@ public function testMediaTypes() ); $types = $formats->mediaTypes(); - $this->assertInstanceOf(SetInterface::class, $types); + $this->assertInstanceOf(Set::class, $types); $this->assertSame(MediaType::class, (string) $types->type()); $this->assertSame(3, $types->size()); $this->assertTrue($types->contains($json)); @@ -153,9 +151,6 @@ public function testFromMediaType() $this->assertSame($html, $formats->fromMediaType('text/xhtml')); } - /** - * @expectedException Innmind\Rest\Client\Exception\InvalidArgumentException - */ public function testThrowWhenNoFormatForWishedMediaType() { $formats = new Formats( @@ -174,6 +169,8 @@ public function testThrowWhenNoFormatForWishedMediaType() ) ); + $this->expectException(InvalidArgumentException::class); + $formats->fromMediaType('application/json'); } @@ -245,9 +242,6 @@ public function testMatchingWhenAcceptingEverything() $this->assertSame($json, $format); } - /** - * @expectedException Innmind\Rest\Client\Exception\InvalidArgumentException - */ public function testThrowWhenCantMatch() { $formats = new Formats( @@ -277,6 +271,8 @@ public function testThrowWhenCantMatch() ) ); + $this->expectException(InvalidArgumentException::class); + $formats->matching('text/plain'); } } diff --git a/tests/HttpResource/PropertyTest.php b/tests/HttpResource/PropertyTest.php index b51dc9b..3aa97da 100644 --- a/tests/HttpResource/PropertyTest.php +++ b/tests/HttpResource/PropertyTest.php @@ -3,7 +3,10 @@ namespace Tests\Innmind\Rest\Client\HttpResource; -use Innmind\Rest\Client\HttpResource\Property; +use Innmind\Rest\Client\{ + HttpResource\Property, + Exception\DomainException, +}; use PHPUnit\Framework\TestCase; class PropertyTest extends TestCase @@ -16,11 +19,10 @@ public function testInterface() $this->assertSame(['bar'], $property->value()); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyName() { + $this->expectException(DomainException::class); + new Property('', ['bar']); } } diff --git a/tests/HttpResourceTest.php b/tests/HttpResourceTest.php index 8541df2..8af2a03 100644 --- a/tests/HttpResourceTest.php +++ b/tests/HttpResourceTest.php @@ -6,6 +6,7 @@ use Innmind\Rest\Client\{ HttpResource, HttpResource\Property, + Exception\DomainException, }; use Innmind\Immutable\Map; use PHPUnit\Framework\TestCase; @@ -16,7 +17,7 @@ public function testInterface() { $resource = new HttpResource( 'foo', - $properties = new Map('string', Property::class) + $properties = Map::of('string', Property::class) ); $this->assertSame('foo', $resource->name()); @@ -33,26 +34,24 @@ public function testOf() $this->assertSame(42, $resource->properties()->get('bar')->value()); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyName() { + $this->expectException(DomainException::class); + new HttpResource( '', - new Map('string', Property::class) + Map::of('string', Property::class) ); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 2 must be of type MapInterface - */ public function testThrowWhenInvalidProperties() { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 2 must be of type Map'); + new HttpResource( 'foo', - new Map('string', 'variable') + Map::of('string', 'scalar|array') ); } } diff --git a/tests/Identity/IdentityTest.php b/tests/Identity/IdentityTest.php index a7f2822..310d97c 100644 --- a/tests/Identity/IdentityTest.php +++ b/tests/Identity/IdentityTest.php @@ -6,6 +6,7 @@ use Innmind\Rest\Client\{ Identity\Identity, Identity as IdentityInterface, + Exception\DomainException, }; use PHPUnit\Framework\TestCase; @@ -16,14 +17,13 @@ public function testInterface() $identity = new Identity('foo'); $this->assertInstanceOf(IdentityInterface::class, $identity); - $this->assertSame('foo', (string) $identity); + $this->assertSame('foo', $identity->toString()); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyValue() { + $this->expectException(DomainException::class); + new Identity(''); } } diff --git a/tests/Link/Parameter/ParameterTest.php b/tests/Link/Parameter/ParameterTest.php index 8dc364d..62bc1ca 100644 --- a/tests/Link/Parameter/ParameterTest.php +++ b/tests/Link/Parameter/ParameterTest.php @@ -3,9 +3,10 @@ namespace Tests\Innmind\Rest\Client\Link\Parameter; -use Innmind\Rest\Client\Link\{ - Parameter\Parameter, - Parameter as ParameterInterface, +use Innmind\Rest\Client\{ + Link\Parameter\Parameter, + Link\Parameter as ParameterInterface, + Exception\DomainException, }; use PHPUnit\Framework\TestCase; @@ -20,11 +21,10 @@ public function testInterface() $this->assertSame('bar', $parameter->value()); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyKey() { + $this->expectException(DomainException::class); + new Parameter('', 'bar'); } } diff --git a/tests/LinkTest.php b/tests/LinkTest.php index b1b4cb3..ab31b73 100644 --- a/tests/LinkTest.php +++ b/tests/LinkTest.php @@ -7,11 +7,9 @@ Link, Link\Parameter, Identity, + Exception\DomainException, }; -use Innmind\Immutable\{ - MapInterface, - Map, -}; +use Innmind\Immutable\Map; use PHPUnit\Framework\TestCase; class LinkTest extends TestCase @@ -22,7 +20,7 @@ public function testInterface() 'foo', $identity = $this->createMock(Identity::class), 'baz', - $parameters = new Map('string', Parameter::class) + $parameters = Map::of('string', Parameter::class) ); $this->assertSame('foo', $link->definition()); @@ -56,7 +54,7 @@ public function testNoParametersGiven() ); $this->assertInstanceOf( - MapInterface::class, + Map::class, $link->parameters() ); $this->assertSame('string', (string) $link->parameters()->keyType()); @@ -66,43 +64,40 @@ public function testNoParametersGiven() ); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 4 must be of type MapInterface - */ public function testThrowWhenInvalidParameterMap() { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 4 must be of type Map'); + new Link( 'foo', $this->createMock(Identity::class), 'baz', - new Map('string', 'string') + Map::of('string', 'string') ); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyDefinition() { + $this->expectException(DomainException::class); + new Link( '', $this->createMock(Identity::class), 'baz', - new Map('string', Parameter::class) + Map::of('string', Parameter::class) ); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptyRelationship() { + $this->expectException(DomainException::class); + new Link( 'foo', $this->createMock(Identity::class), '', - new Map('string', Parameter::class) + Map::of('string', Parameter::class) ); } } diff --git a/tests/Request/RangeTest.php b/tests/Request/RangeTest.php index e3ef7b2..ba0313d 100644 --- a/tests/Request/RangeTest.php +++ b/tests/Request/RangeTest.php @@ -3,7 +3,10 @@ namespace Tests\Innmind\Rest\Client\Request; -use Innmind\Rest\Client\Request\Range; +use Innmind\Rest\Client\{ + Request\Range, + Exception\DomainException, +}; use PHPUnit\Framework\TestCase; class RangeTest extends TestCase @@ -16,19 +19,17 @@ public function testInterface() $this->assertSame(20, $range->lastPosition()); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenFirstPositionNegative() { + $this->expectException(DomainException::class); + new Range(-1, 20); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenLastPositionLowerThanFirstOne() { + $this->expectException(DomainException::class); + new Range(10, 5); } } diff --git a/tests/Response/ExtractIdentitiesTest.php b/tests/Response/ExtractIdentitiesTest.php index c3375b9..d606052 100644 --- a/tests/Response/ExtractIdentitiesTest.php +++ b/tests/Response/ExtractIdentitiesTest.php @@ -14,7 +14,7 @@ }; use Innmind\Http\{ Message\Response, - Headers\Headers, + Headers, Header\Value, Header\Link, Header\LinkValue, @@ -23,9 +23,9 @@ use Innmind\UrlResolver\UrlResolver; use Innmind\Immutable\{ Map, - SetInterface, Set, }; +use function Innmind\Immutable\unwrap; use PHPUnit\Framework\TestCase; class ExtractIdentitiesTest extends TestCase @@ -33,7 +33,7 @@ class ExtractIdentitiesTest extends TestCase private $extract; private $definition; - public function setUp() + public function setUp(): void { $this->extract = new ExtractIdentities( new ResolveIdentity( @@ -42,11 +42,11 @@ public function setUp() ); $this->definition = new HttpResource( 'foo', - Url::fromString('http://example.com/foo'), + Url::of('http://example.com/foo'), new Identity('uuid'), - new Map('string', Property::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', Property::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), false ); } @@ -63,7 +63,7 @@ public function testDenormalizeWithoutLinks() $identities = ($this->extract)($response, $this->definition); - $this->assertInstanceOf(SetInterface::class, $identities); + $this->assertInstanceOf(Set::class, $identities); $this->assertSame( IdentityInterface::class, (string) $identities->type() @@ -81,15 +81,15 @@ public function testDenormalizeWithLinks() Headers::of( new Link( new LinkValue( - Url::fromString('/foo/42'), + Url::of('/foo/42'), 'resource' ), new LinkValue( - Url::fromString('/foo/66'), + Url::of('/foo/66'), 'resource' ), new LinkValue( - Url::fromString('/foo?range[]=10&range[]=20'), + Url::of('/foo?range[]=10&range[]=20'), 'next' ) ) @@ -98,14 +98,15 @@ public function testDenormalizeWithLinks() $identities = ($this->extract)($response, $this->definition); - $this->assertInstanceOf(SetInterface::class, $identities); + $this->assertInstanceOf(Set::class, $identities); $this->assertSame( IdentityInterface::class, (string) $identities->type() ); $this->assertCount(2, $identities); - $this->assertSame('42', (string) $identities->current()); - $identities->next(); - $this->assertSame('66', (string) $identities->current()); + $identities = unwrap($identities); + $this->assertSame('42', \current($identities)->toString()); + \next($identities); + $this->assertSame('66', \current($identities)->toString()); } } diff --git a/tests/Response/ExtractIdentityTest.php b/tests/Response/ExtractIdentityTest.php index 0401e1d..74d5fdb 100644 --- a/tests/Response/ExtractIdentityTest.php +++ b/tests/Response/ExtractIdentityTest.php @@ -15,7 +15,7 @@ }; use Innmind\Http\{ Message\Response, - Headers\Headers, + Headers, Header\Header, Header\Value\Value, Header\HeaderValue, @@ -26,7 +26,6 @@ use Innmind\UrlResolver\UrlResolver; use Innmind\Immutable\{ Map, - SetInterface, Set, }; use PHPUnit\Framework\TestCase; @@ -36,7 +35,7 @@ class ExtractIdentityTest extends TestCase private $extract; private $definition; - public function setUp() + public function setUp(): void { $this->extract = new ExtractIdentity( new ResolveIdentity( @@ -45,11 +44,11 @@ public function setUp() ); $this->definition = new HttpResource( 'foo', - Url::fromString('http://example.com/foo'), + Url::of('http://example.com/foo'), new Identity('uuid'), - new Map('string', Property::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', Property::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), false ); } @@ -99,7 +98,7 @@ public function testDenormalize() Headers::of( new Location( new LocationValue( - Url::fromString('http://example.com/foo/42') + Url::of('http://example.com/foo/42') ) ) ) @@ -108,6 +107,6 @@ public function testDenormalize() $identity = ($this->extract)($response, $this->definition); $this->assertInstanceOf(IdentityInterface::class, $identity); - $this->assertSame('42', (string) $identity); + $this->assertSame('42', $identity->toString()); } } diff --git a/tests/Serializer/Decode/JsonTest.php b/tests/Serializer/Decode/JsonTest.php index cca4c0a..b4a0d67 100644 --- a/tests/Serializer/Decode/JsonTest.php +++ b/tests/Serializer/Decode/JsonTest.php @@ -8,7 +8,7 @@ Serializer\Decode, Exception\LogicException, }; -use Innmind\Filesystem\Stream\StringStream; +use Innmind\Stream\Readable\Stream; use PHPUnit\Framework\TestCase; class JsonTest extends TestCase @@ -22,7 +22,7 @@ public function testInvokation() { $this->assertSame( ['foo' => 'bar'], - (new Json)('json', new StringStream('{"foo":"bar"}')) + (new Json)('json', Stream::ofContent('{"foo":"bar"}')) ); } @@ -30,6 +30,6 @@ public function testThrowWhenInvalidFormat() { $this->expectException(LogicException::class); - (new Json)('xml', new StringStream('{"foo":"bar"}')); + (new Json)('xml', Stream::ofContent('{"foo":"bar"}')); } } diff --git a/tests/Serializer/Denormalizer/DenormalizeCapabilitiesNamesTest.php b/tests/Serializer/Denormalizer/DenormalizeCapabilitiesNamesTest.php index ccaf7fb..587676f 100644 --- a/tests/Serializer/Denormalizer/DenormalizeCapabilitiesNamesTest.php +++ b/tests/Serializer/Denormalizer/DenormalizeCapabilitiesNamesTest.php @@ -4,7 +4,8 @@ namespace Tests\Innmind\Rest\Client\Serializer\Denormalizer; use Innmind\Rest\Client\Serializer\Denormalizer\DenormalizeCapabilitiesNames; -use Innmind\Immutable\SetInterface; +use Innmind\Immutable\Set; +use function Innmind\Immutable\unwrap; use PHPUnit\Framework\TestCase; class DenormalizeCapabilitiesNamesTest extends TestCase @@ -13,8 +14,8 @@ public function testDenormalize() { $names = (new DenormalizeCapabilitiesNames)(['foo', 'bar']); - $this->assertInstanceOf(SetInterface::class, $names); + $this->assertInstanceOf(Set::class, $names); $this->assertSame('string', (string) $names->type()); - $this->assertSame(['foo', 'bar'], $names->toPrimitive()); + $this->assertSame(['foo', 'bar'], unwrap($names)); } } diff --git a/tests/Serializer/Denormalizer/DenormalizeDefinitionTest.php b/tests/Serializer/Denormalizer/DenormalizeDefinitionTest.php index 38cf656..de76d64 100644 --- a/tests/Serializer/Denormalizer/DenormalizeDefinitionTest.php +++ b/tests/Serializer/Denormalizer/DenormalizeDefinitionTest.php @@ -8,6 +8,10 @@ Definition\HttpResource, Definition\Types, }; +use function Innmind\Immutable\{ + unwrap, + first, +}; use PHPUnit\Framework\TestCase; class DenormalizeDefinitionTest extends TestCase @@ -15,9 +19,9 @@ class DenormalizeDefinitionTest extends TestCase private $denormalize; private $raw; - public function setUp() + public function setUp(): void { - $types = new Types(...Types::defaults()); + $types = new Types(...unwrap(Types::defaults())); $this->denormalize = new DenormalizeDefinition($types); $this->raw = [ @@ -57,23 +61,23 @@ public function testDenormalize() $this->assertInstanceOf(HttpResource::class, $definition); $this->assertSame('foo', $definition->name()); - $this->assertSame('http://example.com/foo', (string) $definition->url()); - $this->assertSame('uuid', (string) $definition->identity()); + $this->assertSame('http://example.com/foo', $definition->url()->toString()); + $this->assertSame('uuid', $definition->identity()->toString()); $this->assertSame( 'uuid', $definition->properties()->get('uuid')->name() ); $this->assertSame( 'string', - (string) $definition->properties()->get('uuid')->type() + $definition->properties()->get('uuid')->type()->toString() ); $this->assertSame( ['READ'], - $definition->properties()->get('uuid')->access()->mask()->toPrimitive() + unwrap($definition->properties()->get('uuid')->access()->mask()) ); $this->assertSame( ['guid'], - $definition->properties()->get('uuid')->variants()->toPrimitive() + unwrap($definition->properties()->get('uuid')->variants()) ); $this->assertFalse( $definition->properties()->get('uuid')->isOptional() @@ -84,15 +88,15 @@ public function testDenormalize() ); $this->assertSame( 'string', - (string) $definition->properties()->get('url')->type() + $definition->properties()->get('url')->type()->toString() ); $this->assertSame( ['READ', 'CREATE', 'UPDATE'], - $definition->properties()->get('url')->access()->mask()->toPrimitive() + unwrap($definition->properties()->get('url')->access()->mask()) ); $this->assertSame( [], - $definition->properties()->get('url')->variants()->toPrimitive() + unwrap($definition->properties()->get('url')->variants()) ); $this->assertTrue( $definition->properties()->get('url')->isOptional() @@ -102,8 +106,8 @@ public function testDenormalize() $definition->metas()->get('foo') ); $this->assertCount(1, $definition->links()); - $this->assertSame('res', $definition->links()->current()->resourcePath()); - $this->assertSame('rel', $definition->links()->current()->relationship()); + $this->assertSame('res', first($definition->links())->resourcePath()); + $this->assertSame('rel', first($definition->links())->relationship()); $this->assertTrue($definition->isRangeable()); } } diff --git a/tests/Serializer/Denormalizer/DenormalizeResourceTest.php b/tests/Serializer/Denormalizer/DenormalizeResourceTest.php index 489e05d..f5eafb3 100644 --- a/tests/Serializer/Denormalizer/DenormalizeResourceTest.php +++ b/tests/Serializer/Denormalizer/DenormalizeResourceTest.php @@ -11,6 +11,7 @@ Definition\HttpResource as ResourceDefinition, Definition\Access, Definition\Types, + Exception\MissingProperty, }; use Innmind\Immutable\{ Set, @@ -23,7 +24,7 @@ class DenormalizeResourceTest extends TestCase private $denormalize; private $definition; - public function setUp() + public function setUp(): void { $this->denormalize = new DenormalizeResource; $this->definition = (new DenormalizeDefinition(new Types))( @@ -114,12 +115,11 @@ public function testDenormalizeWithOptionalProperty() ); } - /** - * @expectedException Innmind\Rest\Client\Exception\MissingProperty - * @expectedExceptionMessage Missing property "uuid" - */ public function testThrowWhenDenormalizingWithMissingProperty() { + $this->expectException(MissingProperty::class); + $this->expectExceptionMessage('Missing property "uuid"'); + ($this->denormalize)( [ 'resource' => [], diff --git a/tests/Serializer/Encode/JsonTest.php b/tests/Serializer/Encode/JsonTest.php index ef454f6..52780c9 100644 --- a/tests/Serializer/Encode/JsonTest.php +++ b/tests/Serializer/Encode/JsonTest.php @@ -24,7 +24,7 @@ public function testInvokation() $this->assertInstanceOf(Readable::class, $stream); $this->assertSame( '{"foo":"bar"}', - (string) $stream + $stream->toString(), ); } } diff --git a/tests/Serializer/Normalizer/NormalizeDefinitionTest.php b/tests/Serializer/Normalizer/NormalizeDefinitionTest.php index 199f40f..8ea070b 100644 --- a/tests/Serializer/Normalizer/NormalizeDefinitionTest.php +++ b/tests/Serializer/Normalizer/NormalizeDefinitionTest.php @@ -16,7 +16,7 @@ class NormalizeDefinitionTest extends TestCase private $normalize; private $raw; - public function setUp() + public function setUp(): void { $this->normalize = new NormalizeDefinition; $this->raw = [ diff --git a/tests/Serializer/Normalizer/NormalizeResourceTest.php b/tests/Serializer/Normalizer/NormalizeResourceTest.php index 9376d2c..2976a52 100644 --- a/tests/Serializer/Normalizer/NormalizeResourceTest.php +++ b/tests/Serializer/Normalizer/NormalizeResourceTest.php @@ -11,6 +11,7 @@ Definition\HttpResource as ResourceDefinition, Definition\Access, Definition\Types, + Exception\MissingProperty, }; use Innmind\Immutable\{ Set, @@ -23,7 +24,7 @@ class NormalizeResourceTest extends TestCase private $normalize; private $definition; - public function setUp() + public function setUp(): void { $this->normalize = new NormalizeResource; $this->definition = (new DenormalizeDefinition(new Types))( @@ -129,12 +130,11 @@ public function testNormalizeWithOptionalProperty() ); } - /** - * @expectedException Innmind\Rest\Client\Exception\MissingProperty - * @expectedExceptionMessage Missing property "onCreate" - */ public function testThrowWhenNormalizingWithMissingProperty() { + $this->expectException(MissingProperty::class); + $this->expectExceptionMessage('Missing property "onCreate"'); + ($this->normalize)( HttpResource::of('foo'), $this->definition, diff --git a/tests/Server/Capabilities/CacheCapabilitiesTest.php b/tests/Server/Capabilities/CacheCapabilitiesTest.php index fa09611..9b769c4 100644 --- a/tests/Server/Capabilities/CacheCapabilitiesTest.php +++ b/tests/Server/Capabilities/CacheCapabilitiesTest.php @@ -15,17 +15,18 @@ Serializer\Normalizer\NormalizeDefinition, }; use Innmind\Filesystem\{ - Adapter\MemoryAdapter, + Adapter\InMemory, Directory\Directory, File\File, - Stream\StringStream, + Name, }; +use Innmind\Stream\Readable\Stream; use Innmind\Url\Url; use Innmind\Immutable\{ - SetInterface, Set, - MapInterface, + Map, }; +use function Innmind\Immutable\unwrap; use PHPUnit\Framework\TestCase; class CacheCapabilitiesTest extends TestCase @@ -38,19 +39,19 @@ class CacheCapabilitiesTest extends TestCase private $definition; private $raw; - public function setUp() + public function setUp(): void { $denormalizeDefinition = new DenormalizeDefinition(new Types); $this->capabilities = new CacheCapabilities( $this->inner = $this->createMock(Capabilities::class), - $this->filesystem = new MemoryAdapter, + $this->filesystem = new InMemory, new Decode\Json, new Encode\Json, new DenormalizeCapabilitiesNames, $denormalizeDefinition, $this->normalizeDefinition = new NormalizeDefinition, - Url::fromString('http://example.com/') + Url::of('http://example.com/') ); $this->directory = md5('http://example.com/'); $this->raw = [ @@ -98,22 +99,23 @@ public function testNames() ); $names = $this->capabilities->names(); - $this->assertInstanceOf(SetInterface::class, $names); + $this->assertInstanceOf(Set::class, $names); $this->assertSame('string', (string) $names->type()); $this->assertCount(2, $names); - $this->assertSame(['foo', 'bar'], $names->toPrimitive()); + $this->assertSame(['foo', 'bar'], unwrap($names)); $this->assertSame($names, $this->capabilities->names()); - $this->assertTrue($this->filesystem->has($this->directory)); + $this->assertTrue($this->filesystem->contains(new Name($this->directory))); $this->assertTrue( - $this->filesystem->get($this->directory)->has('.names.json') + $this->filesystem->get(new Name($this->directory))->contains(new Name('.names.json')) ); $this->assertSame( '["foo","bar"]', - (string) $this + $this ->filesystem - ->get($this->directory) - ->get('.names.json') + ->get(new Name($this->directory)) + ->get(new Name('.names.json')) ->content() + ->toString() ); } @@ -126,19 +128,19 @@ public function testNamesFromCache() $this ->filesystem ->add( - (new Directory($this->directory))->add( - new File( + (Directory::named($this->directory))->add( + File::named( '.names.json', - new StringStream('["foo","bar"]') + Stream::ofContent('["foo","bar"]') ) ) ); $names = $this->capabilities->names(); - $this->assertInstanceOf(SetInterface::class, $names); + $this->assertInstanceOf(Set::class, $names); $this->assertSame('string', (string) $names->type()); $this->assertCount(2, $names); - $this->assertSame(['foo', 'bar'], $names->toPrimitive()); + $this->assertSame(['foo', 'bar'], unwrap($names)); $this->assertSame($names, $this->capabilities->names()); } @@ -155,17 +157,18 @@ public function testGet() $this->assertSame($this->definition, $definition); $this->assertSame($definition, $this->capabilities->get('foo')); - $this->assertTrue($this->filesystem->has($this->directory)); + $this->assertTrue($this->filesystem->contains(new Name($this->directory))); $this->assertTrue( - $this->filesystem->get($this->directory)->has('foo.json') + $this->filesystem->get(new Name($this->directory))->contains(new Name('foo.json')) ); $this->assertSame( json_encode($this->raw), - (string) $this + $this ->filesystem - ->get($this->directory) - ->get('foo.json') + ->get(new Name($this->directory)) + ->get(new Name('foo.json')) ->content() + ->toString() ); } @@ -178,10 +181,10 @@ public function testGetFromCache() $this ->filesystem ->add( - (new Directory($this->directory))->add( - new File( + (Directory::named($this->directory))->add( + File::named( 'foo.json', - new StringStream(\json_encode($this->raw)) + Stream::ofContent(\json_encode($this->raw)) ) ) ); @@ -238,7 +241,7 @@ public function testDefinitions() $definitions = $this->capabilities->definitions(); - $this->assertInstanceOf(MapInterface::class, $definitions); + $this->assertInstanceOf(Map::class, $definitions); $this->assertSame('string', (string) $definitions->keyType()); $this->assertSame( HttpResource::class, @@ -266,17 +269,17 @@ public function testRefresh() $this ->filesystem ->add( - (new Directory($this->directory))->add( - new File( + (Directory::named($this->directory))->add( + File::named( '.names.json', - new StringStream('["foo","bar"]') + Stream::ofContent('["foo","bar"]') ) ) ); $names = $this->capabilities->names(); - $this->assertSame($this->capabilities, $this->capabilities->refresh()); - $this->assertFalse($this->filesystem->has($this->directory)); + $this->assertNull($this->capabilities->refresh()); + $this->assertFalse($this->filesystem->contains(new Name($this->directory))); $this->assertNotSame($names, $this->capabilities->names()); } } diff --git a/tests/Server/Capabilities/CacheFactoryTest.php b/tests/Server/Capabilities/CacheFactoryTest.php index a6afd7f..a8fba71 100644 --- a/tests/Server/Capabilities/CacheFactoryTest.php +++ b/tests/Server/Capabilities/CacheFactoryTest.php @@ -15,8 +15,9 @@ Serializer\Normalizer\NormalizeDefinition, Definition\Types, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\Filesystem\Adapter; +use function Innmind\Immutable\unwrap; use PHPUnit\Framework\TestCase; class CacheFactoryTest extends TestCase @@ -24,9 +25,9 @@ class CacheFactoryTest extends TestCase private $make; private $inner; - public function setUp() + public function setUp(): void { - $types = new Types(...Types::defaults()); + $types = new Types(...unwrap(Types::defaults())); $this->make = new CacheFactory( $this->createMock(Adapter::class), @@ -49,7 +50,7 @@ public function testInterface() public function testMake() { - $url = $this->createMock(UrlInterface::class); + $url = Url::of('http://example.com'); $this ->inner ->expects($this->once()) diff --git a/tests/Server/Capabilities/CapabilitiesTest.php b/tests/Server/Capabilities/CapabilitiesTest.php index 6add7a9..c9ba4a9 100644 --- a/tests/Server/Capabilities/CapabilitiesTest.php +++ b/tests/Server/Capabilities/CapabilitiesTest.php @@ -21,8 +21,8 @@ use Innmind\Http\{ Message\Request, Message\Response, - Message\StatusCode\StatusCode, - Headers\Headers, + Message\StatusCode, + Headers, Header, Header\Value, Header\Link, @@ -30,13 +30,12 @@ Header\ContentType, Header\ContentTypeValue, }; -use Innmind\Filesystem\Stream\StringStream; +use Innmind\Stream\Readable\Stream; use Innmind\Immutable\{ - MapInterface, Map, - SetInterface, Set, }; +use function Innmind\Immutable\unwrap; use PHPUnit\Framework\TestCase; class CapabilitiesTest extends TestCase @@ -44,11 +43,11 @@ class CapabilitiesTest extends TestCase private $capabilities; private $transport; - public function setUp() + public function setUp(): void { $this->capabilities = new Capabilities( $this->transport = $this->createMock(Transport::class), - Url::fromString('http://example.com/'), + Url::of('http://example.com/'), new UrlResolver, new DefinitionFactory( new DenormalizeDefinition(new Types), @@ -57,16 +56,12 @@ public function setUp() Formats::of( new Format( 'json', - (new Set(MediaType::class))->add( - new MediaType('application/json', 0) - ), + Set::of(MediaType::class, new MediaType('application/json', 0)), 1 ), new Format( 'xml', - (new Set(MediaType::class))->add( - new MediaType('text/xml', 0) - ), + Set::of(MediaType::class, new MediaType('text/xml', 0)), 0 ) ) @@ -88,8 +83,8 @@ public function testResolveEmptyNames() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/*' && - (string) $request->method() === 'OPTIONS'; + return $request->url()->toString() === 'http://example.com/*' && + $request->method()->toString() === 'OPTIONS'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -103,7 +98,7 @@ public function testResolveEmptyNames() $names = $this->capabilities->names(); - $this->assertInstanceOf(SetInterface::class, $names); + $this->assertInstanceOf(Set::class, $names); $this->assertSame('string', (string) $names->type()); $this->assertCount(0, $names); $this->assertSame($names, $this->capabilities->names()); @@ -116,8 +111,8 @@ public function testResolveNames() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/*' && - (string) $request->method() === 'OPTIONS'; + return $request->url()->toString() === 'http://example.com/*' && + $request->method()->toString() === 'OPTIONS'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -129,11 +124,11 @@ public function testResolveNames() Headers::of( new Link( new LinkValue( - Url::fromString('/foo'), + Url::of('/foo'), 'foo' ), new LinkValue( - Url::fromString('/bar'), + Url::of('/bar'), 'bar' ) ) @@ -142,10 +137,10 @@ public function testResolveNames() $names = $this->capabilities->names(); - $this->assertInstanceOf(SetInterface::class, $names); + $this->assertInstanceOf(Set::class, $names); $this->assertSame('string', (string) $names->type()); $this->assertCount(2, $names); - $this->assertSame(['foo', 'bar'], $names->toPrimitive()); + $this->assertSame(['foo', 'bar'], unwrap($names)); $this->assertSame($names, $this->capabilities->names()); } @@ -156,8 +151,8 @@ public function testGet() ->expects($this->at(0)) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/*' && - (string) $request->method() === 'OPTIONS'; + return $request->url()->toString() === 'http://example.com/*' && + $request->method()->toString() === 'OPTIONS'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -169,11 +164,11 @@ public function testGet() Headers::of( new Link( new LinkValue( - Url::fromString('/foo'), + Url::of('/foo'), 'foo' ), new LinkValue( - Url::fromString('/bar'), + Url::of('/bar'), 'bar' ) ) @@ -184,10 +179,10 @@ public function testGet() ->expects($this->at(1)) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo' && - (string) $request->method() === 'OPTIONS' && - $request->headers()->has('Accept') && - (string) $request->headers()->get('Accept') === 'Accept: application/json, text/xml'; + return $request->url()->toString() === 'http://example.com/foo' && + $request->method()->toString() === 'OPTIONS' && + $request->headers()->contains('Accept') && + $request->headers()->get('Accept')->toString() === 'Accept: application/json, text/xml'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -212,7 +207,7 @@ public function testGet() $response ->expects($this->once()) ->method('body') - ->willReturn(new StringStream('{"url":"http://example.com/foo","identity":"uuid","properties":{"uuid":{"type":"string","access":["READ"],"variants":[],"optional":false},"url":{"type":"string","access":["READ","CREATE","UPDATE"],"variants":[],"optional":false}},"metas":[],"linkable_to":[],"rangeable":true}')); + ->willReturn(Stream::ofContent('{"url":"http://example.com/foo","identity":"uuid","properties":{"uuid":{"type":"string","access":["READ"],"variants":[],"optional":false},"url":{"type":"string","access":["READ","CREATE","UPDATE"],"variants":[],"optional":false}},"metas":[],"linkable_to":[],"rangeable":true}')); $definition = $this->capabilities->get('foo'); @@ -229,8 +224,8 @@ public function testDefinitions() ->expects($this->at(0)) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/*' && - (string) $request->method() === 'OPTIONS'; + return $request->url()->toString() === 'http://example.com/*' && + $request->method()->toString() === 'OPTIONS'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -242,11 +237,11 @@ public function testDefinitions() Headers::of( new Link( new LinkValue( - Url::fromString('/foo'), + Url::of('/foo'), 'foo' ), new LinkValue( - Url::fromString('/bar'), + Url::of('/bar'), 'bar' ) ) @@ -257,8 +252,8 @@ public function testDefinitions() ->expects($this->at(1)) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo' && - (string) $request->method() === 'OPTIONS'; + return $request->url()->toString() === 'http://example.com/foo' && + $request->method()->toString() === 'OPTIONS'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -283,14 +278,14 @@ public function testDefinitions() $response ->expects($this->once()) ->method('body') - ->willReturn(new StringStream('{"url":"http://example.com/foo","identity":"uuid","properties":{"uuid":{"type":"string","access":["READ"],"variants":[],"optional":false},"url":{"type":"string","access":["READ","CREATE","UPDATE"],"variants":[],"optional":false}},"metas":[],"linkable_to":[],"rangeable":true}')); + ->willReturn(Stream::ofContent('{"url":"http://example.com/foo","identity":"uuid","properties":{"uuid":{"type":"string","access":["READ"],"variants":[],"optional":false},"url":{"type":"string","access":["READ","CREATE","UPDATE"],"variants":[],"optional":false}},"metas":[],"linkable_to":[],"rangeable":true}')); $this ->transport ->expects($this->at(2)) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/bar' && - (string) $request->method() === 'OPTIONS'; + return $request->url()->toString() === 'http://example.com/bar' && + $request->method()->toString() === 'OPTIONS'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -315,11 +310,11 @@ public function testDefinitions() $response ->expects($this->once()) ->method('body') - ->willReturn(new StringStream('{"url":"http://example.com/foo","identity":"uuid","properties":{"uuid":{"type":"string","access":["READ"],"variants":[],"optional":false}},"metas":[],"linkable_to":[],"rangeable":true}')); + ->willReturn(Stream::ofContent('{"url":"http://example.com/foo","identity":"uuid","properties":{"uuid":{"type":"string","access":["READ"],"variants":[],"optional":false}},"metas":[],"linkable_to":[],"rangeable":true}')); $definitions = $this->capabilities->definitions(); - $this->assertInstanceOf(MapInterface::class, $definitions); + $this->assertInstanceOf(Map::class, $definitions); $this->assertSame('string', (string) $definitions->keyType()); $this->assertSame( HttpResource::class, @@ -327,7 +322,7 @@ public function testDefinitions() ); $this->assertCount(2, $definitions); $this->assertSame($definitions, $this->capabilities->definitions()); - $this->assertSame(['foo', 'bar'], $definitions->keys()->toPrimitive()); + $this->assertSame(['foo', 'bar'], unwrap($definitions->keys())); } public function testRefresh() @@ -337,8 +332,8 @@ public function testRefresh() ->expects($this->exactly(2)) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/*' && - (string) $request->method() === 'OPTIONS'; + return $request->url()->toString() === 'http://example.com/*' && + $request->method()->toString() === 'OPTIONS'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -351,10 +346,10 @@ public function testRefresh() ); $names = $this->capabilities->names(); - $this->assertSame($this->capabilities, $this->capabilities->refresh()); + $this->assertNull($this->capabilities->refresh()); $names2 = $this->capabilities->names(); $this->assertNotSame($names, $names2); - $this->assertInstanceOf(SetInterface::class, $names2); + $this->assertInstanceOf(Set::class, $names2); $this->assertSame('string', (string) $names2->type()); $this->assertCount(0, $names2); } diff --git a/tests/Server/Capabilities/Factory/FactoryTest.php b/tests/Server/Capabilities/Factory/FactoryTest.php index d3e7d51..013c0fa 100644 --- a/tests/Server/Capabilities/Factory/FactoryTest.php +++ b/tests/Server/Capabilities/Factory/FactoryTest.php @@ -16,8 +16,8 @@ Format\MediaType, }; use Innmind\HttpTransport\Transport; -use Innmind\UrlResolver\ResolverInterface; -use Innmind\Url\UrlInterface; +use Innmind\UrlResolver\Resolver; +use Innmind\Url\Url; use Innmind\Immutable\{ Map, Set, @@ -28,11 +28,11 @@ class FactoryTest extends TestCase { private $make; - public function setUp() + public function setUp(): void { $this->make = new Factory( $this->createMock(Transport::class), - $this->createMock(ResolverInterface::class), + $resolver = $this->createMock(Resolver::class), new DefinitionFactory( new DenormalizeDefinition(new Types), new Json @@ -48,6 +48,10 @@ public function setUp() ) ) ); + $resolver + ->expects($this->any()) + ->method('__invoke') + ->willReturn(Url::of('http://example.com')); } public function testInterface() @@ -63,7 +67,7 @@ public function testMake() $this->assertInstanceOf( Capabilities::class, ($this->make)( - $this->createMock(UrlInterface::class) + Url::of('http://example.com/') ) ); } diff --git a/tests/Server/Capabilities/RefreshLimitedCapabilitiesTest.php b/tests/Server/Capabilities/RefreshLimitedCapabilitiesTest.php index 632261f..8688272 100644 --- a/tests/Server/Capabilities/RefreshLimitedCapabilitiesTest.php +++ b/tests/Server/Capabilities/RefreshLimitedCapabilitiesTest.php @@ -11,10 +11,8 @@ Definition\Identity, Definition\AllowedLink, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\Immutable\{ - MapInterface, - SetInterface, Map, Set, }; @@ -41,7 +39,7 @@ public function testNames() ->expects($this->once()) ->method('names') ->willReturn( - $expected = $this->createMock(SetInterface::class) + $expected = Set::strings() ); $this->assertSame($expected, $capabilities->names()); @@ -59,11 +57,11 @@ public function testGet() ->willReturn( $expected = new HttpResource( 'foo', - $this->createMock(UrlInterface::class), + Url::of('http://example.com/'), new Identity('uuid'), - new Map('string', Property::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', Property::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), false ) ); @@ -80,7 +78,7 @@ public function testDefinitions() ->expects($this->once()) ->method('definitions') ->willReturn( - $expected = $this->createMock(MapInterface::class) + $expected = Map::of('string', HttpResource::class) ); $this->assertSame($expected, $capabilities->definitions()); @@ -95,7 +93,7 @@ public function testRefreshOnlyOnce() ->expects($this->once()) ->method('refresh'); - $this->assertSame($capabilities, $capabilities->refresh()); - $this->assertSame($capabilities, $capabilities->refresh()); + $this->assertNull($capabilities->refresh()); + $this->assertNull($capabilities->refresh()); } } diff --git a/tests/Server/Capabilities/RefreshLimitedFactoryTest.php b/tests/Server/Capabilities/RefreshLimitedFactoryTest.php index 5580b3b..89613ca 100644 --- a/tests/Server/Capabilities/RefreshLimitedFactoryTest.php +++ b/tests/Server/Capabilities/RefreshLimitedFactoryTest.php @@ -9,8 +9,7 @@ Capabilities, Capabilities\RefreshLimitedCapabilities, }; -use Innmind\Url\UrlInterface; -use Symfony\Component\Serializer\SerializerInterface; +use Innmind\Url\Url; use PHPUnit\Framework\TestCase; class RefreshLimitedFactoryTest extends TestCase @@ -18,7 +17,7 @@ class RefreshLimitedFactoryTest extends TestCase private $make; private $inner; - public function setUp() + public function setUp(): void { $this->make = new RefreshLimitedFactory( $this->inner = $this->createMock(Factory::class) @@ -35,7 +34,7 @@ public function testInterface() public function testMake() { - $url = $this->createMock(UrlInterface::class); + $url = Url::of('http://example.com/'); $this ->inner ->expects($this->once()) diff --git a/tests/Server/DefinitionFactoryTest.php b/tests/Server/DefinitionFactoryTest.php index b927b63..6092fcc 100644 --- a/tests/Server/DefinitionFactoryTest.php +++ b/tests/Server/DefinitionFactoryTest.php @@ -9,25 +9,27 @@ Definition\HttpResource, Serializer\Denormalizer\DenormalizeDefinition, Serializer\Decode\Json, + Exception\DomainException, }; use Innmind\Http\{ Message\Response, - Message\StatusCode\StatusCode, - Headers\Headers, + Message\StatusCode, + Headers, Header, Header\ContentType, Header\ContentTypeValue, }; -use Innmind\Filesystem\Stream\StringStream; +use Innmind\Stream\Readable\Stream; use Innmind\Url\Url; use Innmind\Immutable\Map; +use function Innmind\Immutable\unwrap; use PHPUnit\Framework\TestCase; class DefinitionFactoryTest extends TestCase { private $make; - public function setUp() + public function setUp(): void { $this->make = new DefinitionFactory( new DenormalizeDefinition(new Types), @@ -35,9 +37,6 @@ public function setUp() ); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenResponseNotSuccessful() { $response = $this->createMock(Response::class); @@ -45,13 +44,16 @@ public function testThrowWhenResponseNotSuccessful() ->expects($this->once()) ->method('statusCode') ->willReturn(new StatusCode(404)); + $response + ->expects($this->any()) + ->method('headers') + ->willReturn(new Headers); + + $this->expectException(DomainException::class); - ($this->make)('foo', Url::fromString('/'), $response); + ($this->make)('foo', Url::of('/'), $response); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenResponseHasNoContentType() { $response = $this->createMock(Response::class); @@ -66,12 +68,11 @@ public function testThrowWhenResponseHasNoContentType() new Headers ); - ($this->make)('foo', Url::fromString('/'), $response); + $this->expectException(DomainException::class); + + ($this->make)('foo', Url::of('/'), $response); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenResponseHasNotJson() { $response = $this->createMock(Response::class); @@ -93,7 +94,9 @@ public function testThrowWhenResponseHasNotJson() ) ); - ($this->make)('foo', Url::fromString('/'), $response); + $this->expectException(DomainException::class); + + ($this->make)('foo', Url::of('/'), $response); } public function testMake() @@ -119,33 +122,33 @@ public function testMake() $response ->expects($this->once()) ->method('body') - ->willReturn(new StringStream('{"identity":"uuid","properties":{"uuid":{"type":"string","access":["READ"],"variants":[],"optional":false},"url":{"type":"string","access":["READ","CREATE","UPDATE"],"variants":[],"optional":false}},"metas":[],"linkable_to":[],"rangeable":true}')); + ->willReturn(Stream::ofContent('{"identity":"uuid","properties":{"uuid":{"type":"string","access":["READ"],"variants":[],"optional":false},"url":{"type":"string","access":["READ","CREATE","UPDATE"],"variants":[],"optional":false}},"metas":[],"linkable_to":[],"rangeable":true}')); $definition = ($this->make)( 'foo', - Url::fromString('http://example.com/foo'), + Url::of('http://example.com/foo'), $response ); $this->assertInstanceOf(HttpResource::class, $definition); $this->assertSame('foo', $definition->name()); - $this->assertSame('http://example.com/foo', (string) $definition->url()); - $this->assertSame('uuid', (string) $definition->identity()); + $this->assertSame('http://example.com/foo', $definition->url()->toString()); + $this->assertSame('uuid', $definition->identity()->toString()); $this->assertSame( 'uuid', $definition->properties()->get('uuid')->name() ); $this->assertSame( 'string', - (string) $definition->properties()->get('uuid')->type() + $definition->properties()->get('uuid')->type()->toString() ); $this->assertSame( ['READ'], - $definition->properties()->get('uuid')->access()->mask()->toPrimitive() + unwrap($definition->properties()->get('uuid')->access()->mask()) ); $this->assertSame( [], - $definition->properties()->get('uuid')->variants()->toPrimitive() + unwrap($definition->properties()->get('uuid')->variants()) ); $this->assertFalse( $definition->properties()->get('uuid')->isOptional() @@ -156,15 +159,15 @@ public function testMake() ); $this->assertSame( 'string', - (string) $definition->properties()->get('url')->type() + $definition->properties()->get('url')->type()->toString() ); $this->assertSame( ['READ', 'CREATE', 'UPDATE'], - $definition->properties()->get('url')->access()->mask()->toPrimitive() + unwrap($definition->properties()->get('url')->access()->mask()) ); $this->assertSame( [], - $definition->properties()->get('url')->variants()->toPrimitive() + unwrap($definition->properties()->get('url')->variants()) ); $this->assertFalse( $definition->properties()->get('url')->isOptional() diff --git a/tests/Server/RetryServerFactoryTest.php b/tests/Server/RetryServerFactoryTest.php index ab5532b..7215932 100644 --- a/tests/Server/RetryServerFactoryTest.php +++ b/tests/Server/RetryServerFactoryTest.php @@ -8,7 +8,7 @@ Factory, RetryServer, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use PHPUnit\Framework\TestCase; class RetryServerFactoryTest extends TestCase @@ -28,7 +28,7 @@ public function testMake() $make = new RetryServerFactory( $inner = $this->createMock(Factory::class) ); - $url = $this->createMock(UrlInterface::class); + $url = Url::of('http://example.com/'); $inner ->expects($this->once()) ->method('__invoke') diff --git a/tests/Server/RetryServerTest.php b/tests/Server/RetryServerTest.php index d96b738..53a68de 100644 --- a/tests/Server/RetryServerTest.php +++ b/tests/Server/RetryServerTest.php @@ -19,12 +19,11 @@ use Innmind\Http\Message\{ Request, Response, - StatusCode\StatusCode, + StatusCode, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\Specification\Specification; use Innmind\Immutable\{ - SetInterface, Map, Set, }; @@ -35,7 +34,7 @@ class RetryServerTest extends TestCase private $server; private $inner; - public function setUp() + public function setUp(): void { $this->server = new RetryServer( $this->inner = $this->createMock(Server::class) @@ -59,7 +58,7 @@ public function testAll() ->expects($this->once()) ->method('all') ->with('foo', $specification, $range) - ->willReturn($expected = $this->createMock(SetInterface::class)); + ->willReturn($expected = Set::of(Identity::class)); $identities = $this->server->all('foo', $specification, $range); @@ -96,16 +95,13 @@ public function testRetryAll(\Throwable $e) ->expects($this->at(2)) ->method('all') ->with('foo', $specification, $range) - ->willReturn($expected = $this->createMock(SetInterface::class)); + ->willReturn($expected = Set::of(Identity::class)); $identities = $this->server->all('foo', $specification, $range); $this->assertSame($expected, $identities); } - /** - * @expectedException Exception - */ public function testDoesntRetryAll() { $specification = $this->createMock(Specification::class); @@ -123,6 +119,8 @@ public function testDoesntRetryAll() ->expects($this->never()) ->method('capabilities'); + $this->expectException(\Exception::class); + $this->server->all('foo', $specification, $range); } @@ -181,9 +179,6 @@ public function testRetryRead(\Throwable $e) $this->assertSame($expected, $resource); } - /** - * @expectedException Exception - */ public function testDoesntRetryRead() { $identity = $this->createMock(Identity::class); @@ -200,6 +195,8 @@ public function testDoesntRetryRead() ->expects($this->never()) ->method('capabilities'); + $this->expectException(\Exception::class); + $this->server->read('foo', $identity); } @@ -258,9 +255,6 @@ public function testRetryCreate(\Throwable $e) $this->assertSame($expected, $identity); } - /** - * @expectedException Exception - */ public function testDoesntRetryCreate() { $resource = HttpResource::of('foo'); @@ -277,6 +271,8 @@ public function testDoesntRetryCreate() ->expects($this->never()) ->method('capabilities'); + $this->expectException(\Exception::class); + $this->server->create($resource); } @@ -288,12 +284,11 @@ public function testUpdate() ->inner ->expects($this->once()) ->method('update') - ->with($identity, $resource) - ->willReturn($this->inner); + ->with($identity, $resource); $return = $this->server->update($identity, $resource); - $this->assertSame($this->server, $return); + $this->assertNull($return); } /** @@ -325,17 +320,13 @@ public function testRetryUpdate(\Throwable $e) ->inner ->expects($this->at(2)) ->method('update') - ->with($identity, $resource) - ->willReturn($this->inner); + ->with($identity, $resource); $return = $this->server->update($identity, $resource); - $this->assertSame($this->server, $return); + $this->assertNull($return); } - /** - * @expectedException Exception - */ public function testDoesntRetryUpdate() { $identity = $this->createMock(Identity::class); @@ -353,6 +344,8 @@ public function testDoesntRetryUpdate() ->expects($this->never()) ->method('capabilities'); + $this->expectException(\Exception::class); + $this->server->update($identity, $resource); } @@ -363,12 +356,11 @@ public function testRemove() ->inner ->expects($this->once()) ->method('remove') - ->with('foo', $identity) - ->willReturn($this->inner); + ->with('foo', $identity); $return = $this->server->remove('foo', $identity); - $this->assertSame($this->server, $return); + $this->assertNull($return); } /** @@ -399,17 +391,13 @@ public function testRetryRemove(\Throwable $e) ->inner ->expects($this->at(2)) ->method('remove') - ->with('foo', $identity) - ->willReturn($this->inner); + ->with('foo', $identity); $return = $this->server->remove('foo', $identity); - $this->assertSame($this->server, $return); + $this->assertNull($return); } - /** - * @expectedException Exception - */ public function testDoesntRetryRemove() { $identity = $this->createMock(Identity::class); @@ -426,6 +414,8 @@ public function testDoesntRetryRemove() ->expects($this->never()) ->method('capabilities'); + $this->expectException(\Exception::class); + $this->server->remove('foo', $identity); } @@ -452,7 +442,7 @@ public function testUrl() ->expects($this->once()) ->method('url') ->willReturn( - $expected = $this->createMock(UrlInterface::class) + $expected = Url::of('http://example.com/') ); $this->assertSame( @@ -464,15 +454,14 @@ public function testUrl() public function testLink() { $identity = $this->createMock(Identity::class); - $links = new Set(Link::class); + $links = Set::of(Link::class); $this ->inner ->expects($this->once()) ->method('link') ->with('foo', $identity, $links); - $this->assertSame( - $this->server, + $this->assertNull( $this->server->link('foo', $identity, $links) ); } @@ -483,7 +472,7 @@ public function testLink() public function testRetryLink(\Throwable $e) { $identity = $this->createMock(Identity::class); - $links = new Set(Link::class); + $links = Set::of(Link::class); $this ->inner ->expects($this->at(0)) @@ -506,19 +495,15 @@ public function testRetryLink(\Throwable $e) ->method('link') ->with('foo', $identity, $links); - $this->assertSame( - $this->server, + $this->assertNull( $this->server->link('foo', $identity, $links) ); } - /** - * @expectedException Exception - */ public function testDoesntRetryLink() { $identity = $this->createMock(Identity::class); - $links = new Set(Link::class); + $links = Set::of(Link::class); $this ->inner ->expects($this->once()) @@ -530,21 +515,22 @@ public function testDoesntRetryLink() ->expects($this->never()) ->method('capabilities'); + $this->expectException(\Exception::class); + $this->server->link('foo', $identity, $links); } public function testUnlink() { $identity = $this->createMock(Identity::class); - $links = new Set(Link::class); + $links = Set::of(Link::class); $this ->inner ->expects($this->once()) ->method('unlink') ->with('foo', $identity, $links); - $this->assertSame( - $this->server, + $this->assertNull( $this->server->unlink('foo', $identity, $links) ); } @@ -555,7 +541,7 @@ public function testUnlink() public function testRetryUnlink(\Throwable $e) { $identity = $this->createMock(Identity::class); - $links = new Set(Link::class); + $links = Set::of(Link::class); $this ->inner ->expects($this->at(0)) @@ -578,19 +564,15 @@ public function testRetryUnlink(\Throwable $e) ->method('unlink') ->with('foo', $identity, $links); - $this->assertSame( - $this->server, + $this->assertNull( $this->server->unlink('foo', $identity, $links) ); } - /** - * @expectedException Exception - */ public function testDoesntRetryUnlink() { $identity = $this->createMock(Identity::class); - $links = new Set(Link::class); + $links = Set::of(Link::class); $this ->inner ->expects($this->once()) @@ -602,6 +584,8 @@ public function testDoesntRetryUnlink() ->expects($this->never()) ->method('capabilities'); + $this->expectException(\Exception::class); + $this->server->unlink('foo', $identity, $links); } diff --git a/tests/Server/ServerFactoryTest.php b/tests/Server/ServerFactoryTest.php index 696f564..3fcbf64 100644 --- a/tests/Server/ServerFactoryTest.php +++ b/tests/Server/ServerFactoryTest.php @@ -20,9 +20,9 @@ Serializer\Encode, Serializer\Decode, }; -use Innmind\Url\UrlInterface; +use Innmind\Url\Url; use Innmind\HttpTransport\Transport; -use Innmind\UrlResolver\ResolverInterface; +use Innmind\UrlResolver\Resolver; use Innmind\Immutable\{ Map, Set, @@ -34,11 +34,11 @@ class ServerFactoryTest extends TestCase private $make; private $capabilities; - public function setUp() + public function setUp(): void { $this->make = new ServerFactory( $this->createMock(Transport::class), - $resolver = $this->createMock(ResolverInterface::class), + $resolver = $this->createMock(Resolver::class), new ExtractIdentity(new ResolveIdentity($resolver)), new ExtractIdentities(new ResolveIdentity($resolver)), new DenormalizeResource, @@ -70,7 +70,7 @@ public function testInterface() public function testMake() { - $url = $this->createMock(UrlInterface::class); + $url = Url::of('http://example.com/'); $this ->capabilities ->expects($this->once()) diff --git a/tests/Server/ServerTest.php b/tests/Server/ServerTest.php index 4c2d1dc..d6692cb 100644 --- a/tests/Server/ServerTest.php +++ b/tests/Server/ServerTest.php @@ -30,17 +30,18 @@ Response\ExtractIdentity, Response\ExtractIdentities, Visitor\ResolveIdentity, + Exception\ResourceNotRangeable, + Exception\NormalizationException, + Exception\DomainException, + Exception\UnsupportedResponse, }; use Innmind\HttpTransport\Transport; use Innmind\UrlResolver\UrlResolver; -use Innmind\Url\{ - Url, - UrlInterface, -}; +use Innmind\Url\Url; use Innmind\Http\{ Message\Request, Message\Response, - Headers\Headers, + Headers, Header, Header\ContentType, Header\ContentTypeValue, @@ -49,12 +50,12 @@ Header\Link as LinkHeader, Header\LinkValue, }; -use Innmind\Filesystem\Stream\StringStream; +use Innmind\Stream\Readable\Stream; use Innmind\Immutable\{ Map, - SetInterface, Set, }; +use function Innmind\Immutable\unwrap; use Innmind\Specification\{ Comparator, Sign, @@ -69,10 +70,10 @@ class ServerTest extends TestCase private $capabilities; private $definition; - public function setUp() + public function setUp(): void { $this->server = new Server( - $this->url = Url::fromString('http://example.com/'), + $this->url = Url::of('http://example.com/'), $this->transport = $this->createMock(Transport::class), $this->capabilities = $this->createMock(Capabilities::class), $resolver = new UrlResolver, @@ -153,9 +154,6 @@ public function testInterface() ); } - /** - * @expectedException Innmind\Rest\Client\Exception\ResourceNotRangeable - */ public function testThrowWhenRangingOnNonRangeableResource() { $this @@ -166,15 +164,17 @@ public function testThrowWhenRangingOnNonRangeableResource() ->willReturn( new HttpResourceDefinition( 'foo', - $this->createMock(UrlInterface::class), + Url::of('http://example.com'), new IdentityDefinition('uuid'), - new Map('string', PropertyDefinition::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', PropertyDefinition::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), false ) ); + $this->expectException(ResourceNotRangeable::class); + $this->server->all( 'foo', null, @@ -192,11 +192,11 @@ public function testAll() ->willReturn( $definition = new HttpResourceDefinition( 'foo', - Url::fromString('http://example.com/foo'), + Url::of('http://example.com/foo'), new IdentityDefinition('uuid'), - new Map('string', PropertyDefinition::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', PropertyDefinition::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), false ) ); @@ -205,10 +205,10 @@ public function testAll() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo' && - (string) $request->method() === 'GET' && + return $request->url()->toString() === 'http://example.com/foo' && + $request->method()->toString() === 'GET' && $request->headers()->count() === 0 && - (string) $request->body() === ''; + $request->body()->toString() === ''; })) ->willReturn( $response = $this->createMock(Response::class) @@ -219,11 +219,11 @@ public function testAll() ->willReturn(Headers::of( new LinkHeader( new LinkValue( - Url::fromString('http://example.com/foo/some-uuid'), + Url::of('http://example.com/foo/some-uuid'), 'resource' ), new LinkValue( - Url::fromString('http://example.com/foo/some-other-uuid'), + Url::of('http://example.com/foo/some-other-uuid'), 'resource' ) ) @@ -231,12 +231,13 @@ public function testAll() $all = $this->server->all('foo'); - $this->assertInstanceOf(SetInterface::class, $all); + $this->assertInstanceOf(Set::class, $all); $this->assertSame(Identity::class, (string) $all->type()); $this->assertCount(2, $all); - $this->assertSame('some-uuid', (string) $all->current()); - $all->next(); - $this->assertSame('some-other-uuid', (string) $all->current()); + $all = unwrap($all); + $this->assertSame('some-uuid', \current($all)->toString()); + \next($all); + $this->assertSame('some-other-uuid', \current($all)->toString()); } public function testAllWithRange() @@ -249,11 +250,11 @@ public function testAllWithRange() ->willReturn( $definition = new HttpResourceDefinition( 'foo', - Url::fromString('http://example.com/foo'), + Url::of('http://example.com/foo'), new IdentityDefinition('uuid'), - new Map('string', PropertyDefinition::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', PropertyDefinition::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), true ) ); @@ -262,12 +263,12 @@ public function testAllWithRange() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo' && - (string) $request->method() === 'GET' && + return $request->url()->toString() === 'http://example.com/foo' && + $request->method()->toString() === 'GET' && $request->headers()->count() === 1 && - $request->headers()->has('range') && - (string) $request->headers()->get('range') === 'Range: resource=10-20' && - (string) $request->body() === ''; + $request->headers()->contains('range') && + $request->headers()->get('range')->toString() === 'Range: resource=10-20' && + $request->body()->toString() === ''; })) ->willReturn( $response = $this->createMock(Response::class) @@ -278,11 +279,11 @@ public function testAllWithRange() ->willReturn(Headers::of( new LinkHeader( new LinkValue( - Url::fromString('http://example.com/foo/some-uuid'), + Url::of('http://example.com/foo/some-uuid'), 'resource' ), new LinkValue( - Url::fromString('http://example.com/foo/some-other-uuid'), + Url::of('http://example.com/foo/some-other-uuid'), 'resource' ) ) @@ -290,12 +291,13 @@ public function testAllWithRange() $all = $this->server->all('foo', null, new Range(10, 20)); - $this->assertInstanceOf(SetInterface::class, $all); + $this->assertInstanceOf(Set::class, $all); $this->assertSame(Identity::class, (string) $all->type()); $this->assertCount(2, $all); - $this->assertSame('some-uuid', (string) $all->current()); - $all->next(); - $this->assertSame('some-other-uuid', (string) $all->current()); + $all = unwrap($all); + $this->assertSame('some-uuid', \current($all)->toString()); + \next($all); + $this->assertSame('some-other-uuid', \current($all)->toString()); } public function testAllWithQuery() @@ -308,11 +310,11 @@ public function testAllWithQuery() ->willReturn( $definition = new HttpResourceDefinition( 'foo', - Url::fromString('http://example.com/foo'), + Url::of('http://example.com/foo'), new IdentityDefinition('uuid'), - new Map('string', PropertyDefinition::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', PropertyDefinition::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), false ) ); @@ -321,10 +323,10 @@ public function testAllWithQuery() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo?bar=baz' && - (string) $request->method() === 'GET' && + return $request->url()->toString() === 'http://example.com/foo?bar=baz' && + $request->method()->toString() === 'GET' && $request->headers()->count() === 0 && - (string) $request->body() === ''; + $request->body()->toString() === ''; })) ->willReturn( $response = $this->createMock(Response::class) @@ -348,11 +350,11 @@ public function testAllWithQuery() ->willReturn(Headers::of( new LinkHeader( new LinkValue( - Url::fromString('http://example.com/foo/some-uuid'), + Url::of('http://example.com/foo/some-uuid'), 'resource' ), new LinkValue( - Url::fromString('http://example.com/foo/some-other-uuid'), + Url::of('http://example.com/foo/some-other-uuid'), 'resource' ) ) @@ -360,12 +362,13 @@ public function testAllWithQuery() $all = $this->server->all('foo', $specification); - $this->assertInstanceOf(SetInterface::class, $all); + $this->assertInstanceOf(Set::class, $all); $this->assertSame(Identity::class, (string) $all->type()); $this->assertCount(2, $all); - $this->assertSame('some-uuid', (string) $all->current()); - $all->next(); - $this->assertSame('some-other-uuid', (string) $all->current()); + $all = unwrap($all); + $this->assertSame('some-uuid', \current($all)->toString()); + \next($all); + $this->assertSame('some-other-uuid', \current($all)->toString()); } public function testAllWithQueryAndRange() @@ -378,11 +381,11 @@ public function testAllWithQueryAndRange() ->willReturn( $definition = new HttpResourceDefinition( 'foo', - Url::fromString('http://example.com/foo'), + Url::of('http://example.com/foo'), new IdentityDefinition('uuid'), - new Map('string', PropertyDefinition::class), - new Map('scalar', 'variable'), - new Set(AllowedLink::class), + Map::of('string', PropertyDefinition::class), + Map::of('scalar', 'scalar|array'), + Set::of(AllowedLink::class), true ) ); @@ -391,12 +394,12 @@ public function testAllWithQueryAndRange() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo?bar=baz' && - (string) $request->method() === 'GET' && + return $request->url()->toString() === 'http://example.com/foo?bar=baz' && + $request->method()->toString() === 'GET' && $request->headers()->count() === 1 && - $request->headers()->has('range') && - (string) $request->headers()->get('range') === 'Range: resource=10-20' && - (string) $request->body() === ''; + $request->headers()->contains('range') && + $request->headers()->get('range')->toString() === 'Range: resource=10-20' && + $request->body()->toString() === ''; })) ->willReturn( $response = $this->createMock(Response::class) @@ -420,11 +423,11 @@ public function testAllWithQueryAndRange() ->willReturn(Headers::of( new LinkHeader( new LinkValue( - Url::fromString('http://example.com/foo/some-uuid'), + Url::of('http://example.com/foo/some-uuid'), 'resource' ), new LinkValue( - Url::fromString('http://example.com/foo/some-other-uuid'), + Url::of('http://example.com/foo/some-other-uuid'), 'resource' ) ) @@ -432,17 +435,15 @@ public function testAllWithQueryAndRange() $all = $this->server->all('foo', $specification, new Range(10, 20)); - $this->assertInstanceOf(SetInterface::class, $all); + $this->assertInstanceOf(Set::class, $all); $this->assertSame(Identity::class, (string) $all->type()); $this->assertCount(2, $all); - $this->assertSame('some-uuid', (string) $all->current()); - $all->next(); - $this->assertSame('some-other-uuid', (string) $all->current()); + $all = unwrap($all); + $this->assertSame('some-uuid', \current($all)->toString()); + \next($all); + $this->assertSame('some-other-uuid', \current($all)->toString()); } - /** - * @expectedException Innmind\Rest\Client\Exception\UnsupportedResponse - */ public function testThrowWhenReadResponseHasNoContentType() { $this @@ -465,12 +466,11 @@ public function testThrowWhenReadResponseHasNoContentType() new Headers ); + $this->expectException(UnsupportedResponse::class); + $this->server->read('foo', new Identity\Identity('uuid')); } - /** - * @expectedException Innmind\Rest\Client\Exception\UnsupportedResponse - */ public function testThrowWhenReadResponseContentTypeNotSupported() { $this @@ -500,6 +500,8 @@ public function testThrowWhenReadResponseContentTypeNotSupported() ) ); + $this->expectException(UnsupportedResponse::class); + $this->server->read('foo', new Identity\Identity('uuid')); } @@ -516,11 +518,11 @@ public function testRead() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo/bar' && - (string) $request->method() === 'GET' && + return $request->url()->toString() === 'http://example.com/foo/bar' && + $request->method()->toString() === 'GET' && $request->headers()->count() === 1 && - (string) $request->headers()->get('Accept') === 'Accept: application/json, text/xml' && - (string) $request->body() === ''; + $request->headers()->get('Accept')->toString() === 'Accept: application/json, text/xml' && + $request->body()->toString() === ''; })) ->willReturn( $response = $this->createMock(Response::class) @@ -542,7 +544,7 @@ public function testRead() ->expects($this->once()) ->method('body') ->willReturn( - new StringStream('{"resource":{"uuid":"bar","url":"example.com"}}') + Stream::ofContent('{"resource":{"uuid":"bar","url":"example.com"}}') ); $resource = $this->server->read('foo', new Identity\Identity('bar')); @@ -573,12 +575,12 @@ public function testCreate() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo' && - (string) $request->method() === 'POST' && + return $request->url()->toString() === 'http://example.com/foo' && + $request->method()->toString() === 'POST' && $request->headers()->count() === 2 && - (string) $request->headers()->get('Content-Type') === 'Content-Type: application/json' && - (string) $request->headers()->get('Accept') === 'Accept: application/json, text/xml' && - (string) $request->body() === '{"resource":{"url":"foobar"}}'; + $request->headers()->get('Content-Type')->toString() === 'Content-Type: application/json' && + $request->headers()->get('Accept')->toString() === 'Accept: application/json, text/xml' && + $request->body()->toString() === '{"resource":{"url":"foobar"}}'; })) ->willReturn( $response = $this->createMock(Response::class) @@ -589,7 +591,7 @@ public function testCreate() ->willReturn(Headers::of( new Location( new LocationValue( - Url::fromString('http://example.com/foo/some-uuid') + Url::of('http://example.com/foo/some-uuid') ) ) )); @@ -601,7 +603,7 @@ public function testCreate() ) ); - $this->assertSame('some-uuid', (string) $identity); + $this->assertSame('some-uuid', $identity->toString()); } public function testUpdate() @@ -617,12 +619,12 @@ public function testUpdate() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo/some-uuid' && - (string) $request->method() === 'PUT' && + return $request->url()->toString() === 'http://example.com/foo/some-uuid' && + $request->method()->toString() === 'PUT' && $request->headers()->count() === 2 && - (string) $request->headers()->get('Content-Type') === 'Content-Type: application/json' && - (string) $request->headers()->get('Accept') === 'Accept: application/json, text/xml' && - (string) $request->body() === '{"resource":{"url":"foobar"}}'; + $request->headers()->get('Content-Type')->toString() === 'Content-Type: application/json' && + $request->headers()->get('Accept')->toString() === 'Accept: application/json, text/xml' && + $request->body()->toString() === '{"resource":{"url":"foobar"}}'; })) ->willReturn( $this->createMock(Response::class) @@ -636,7 +638,7 @@ public function testUpdate() ) ); - $this->assertSame($this->server, $return); + $this->assertNull($return); } public function testDelete() @@ -652,10 +654,10 @@ public function testDelete() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo/some-uuid' && - (string) $request->method() === 'DELETE' && + return $request->url()->toString() === 'http://example.com/foo/some-uuid' && + $request->method()->toString() === 'DELETE' && $request->headers()->count() === 0 && - (string) $request->body() === ''; + $request->body()->toString() === ''; })) ->willReturn( $this->createMock(Response::class) @@ -666,37 +668,32 @@ public function testDelete() new Identity\Identity('some-uuid') ); - $this->assertSame($this->server, $return); + $this->assertNull($return); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 3 must be of type SetInterface - */ public function testThrowWhenInvalidSetOfLinks() { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 3 must be of type Set'); + $this->server->link( 'foo', $this->createMock(Identity::class), - new Set('string') + Set::of('string') ); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptySetOfLinks() { + $this->expectException(DomainException::class); + $this->server->link( 'foo', $this->createMock(Identity::class), - new Set(Link::class) + Set::of(Link::class) ); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - */ public function testThrowWhenLinkNotAllowedByDefinition() { $this @@ -710,6 +707,8 @@ public function testThrowWhenLinkNotAllowedByDefinition() ->expects($this->never()) ->method('__invoke'); + $this->expectException(NormalizationException::class); + $this->server->link( 'foo', new Identity\Identity('some-uuid'), @@ -744,15 +743,14 @@ public function testLink() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo/some-uuid' && - (string) $request->method() === 'LINK' && - (string) $request->headers()->get('Accept') === 'Accept: application/json, text/xml' && - (string) $request->headers()->get('Link') === 'Link: ; rel="canonical";attr=val' && - (string) $request->body() === ''; + return $request->url()->toString() === 'http://example.com/foo/some-uuid' && + $request->method()->toString() === 'LINK' && + $request->headers()->get('Accept')->toString() === 'Accept: application/json, text/xml' && + $request->headers()->get('Link')->toString() === 'Link: ; rel="canonical";attr=val' && + $request->body()->toString() === ''; })); - $this->assertSame( - $this->server, + $this->assertNull( $this->server->link( 'foo', new Identity\Identity('some-uuid'), @@ -769,34 +767,29 @@ public function testLink() ); } - /** - * @expectedException TypeError - * @expectedExceptionMessage Argument 3 must be of type SetInterface - */ public function testThrowWhenInvalidSetOfLinksToUnlink() { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Argument 3 must be of type Set'); + $this->server->unlink( 'foo', $this->createMock(Identity::class), - new Set('string') + Set::of('string') ); } - /** - * @expectedException Innmind\Rest\Client\Exception\DomainException - */ public function testThrowWhenEmptySetOfLinksToUnlink() { + $this->expectException(DomainException::class); + $this->server->unlink( 'foo', $this->createMock(Identity::class), - new Set(Link::class) + Set::of(Link::class) ); } - /** - * @expectedException Innmind\Rest\Client\Exception\NormalizationException - */ public function testThrowWhenUnlinkNotAllowedByDefinition() { $this @@ -810,6 +803,8 @@ public function testThrowWhenUnlinkNotAllowedByDefinition() ->expects($this->never()) ->method('__invoke'); + $this->expectException(NormalizationException::class); + $this->server->unlink( 'foo', new Identity\Identity('some-uuid'), @@ -844,15 +839,14 @@ public function testUnlink() ->expects($this->once()) ->method('__invoke') ->with($this->callback(function(Request $request): bool { - return (string) $request->url() === 'http://example.com/foo/some-uuid' && - (string) $request->method() === 'UNLINK' && - (string) $request->headers()->get('Accept') === 'Accept: application/json, text/xml' && - (string) $request->headers()->get('Link') === 'Link: ; rel="canonical";attr=val' && - (string) $request->body() === ''; + return $request->url()->toString() === 'http://example.com/foo/some-uuid' && + $request->method()->toString() === 'UNLINK' && + $request->headers()->get('Accept')->toString() === 'Accept: application/json, text/xml' && + $request->headers()->get('Link')->toString() === 'Link: ; rel="canonical";attr=val' && + $request->body()->toString() === ''; })); - $this->assertSame( - $this->server, + $this->assertNull( $this->server->unlink( 'foo', new Identity\Identity('some-uuid'), diff --git a/tests/Translator/Specification/SpecificationTranslatorTest.php b/tests/Translator/Specification/SpecificationTranslatorTest.php index 25ec8f2..9791ad6 100644 --- a/tests/Translator/Specification/SpecificationTranslatorTest.php +++ b/tests/Translator/Specification/SpecificationTranslatorTest.php @@ -3,9 +3,12 @@ namespace Tests\Innmind\Rest\Client\Translator\Specification; -use Innmind\Rest\Client\Translator\{ - Specification\SpecificationTranslator, - SpecificationTranslator as SpecificationTranslatorInterface, +use Innmind\Rest\Client\{ + Translator\Specification\SpecificationTranslator, + Translator\SpecificationTranslator as SpecificationTranslatorInterface, + Exception\OnlyEqualityCanBeTranslated, + Exception\OnlyAndCompositionCanBeTranslated, + Exception\SpecificationCantBeTranslated, }; use Innmind\Specification\{ Comparator, @@ -48,9 +51,6 @@ public function testTranslateComparator() $this->assertSame('bar=baz', $query); } - /** - * @expectedException Innmind\Rest\Client\Exception\OnlyEqualityCanBeTranslated - */ public function testThrowWhenUnsupportedComparison() { $spec = $this->createMock(Comparator::class); @@ -65,6 +65,8 @@ public function testThrowWhenUnsupportedComparison() ->expects($this->never()) ->method('value'); + $this->expectException(OnlyEqualityCanBeTranslated::class); + (new SpecificationTranslator)($spec); } @@ -115,9 +117,6 @@ public function testTranslateComposite() $this->assertSame('bar=baz&foo=foobar', $query); } - /** - * @expectedException Innmind\Rest\Client\Exception\OnlyAndCompositionCanBeTranslated - */ public function testThrowWhenUnsupportedComposite() { $spec = $this->createMock(Composite::class); @@ -132,24 +131,24 @@ public function testThrowWhenUnsupportedComposite() ->method('operator') ->willReturn(Operator::or()); + $this->expectException(OnlyAndCompositionCanBeTranslated::class); + (new SpecificationTranslator)($spec); } - /** - * @expectedException Innmind\Rest\Client\Exception\SpecificationCantBeTranslated - */ public function testThrowWhenTranslatingNegativeSpecification() { + $this->expectException(SpecificationCantBeTranslated::class); + (new SpecificationTranslator)( $this->createMock(Not::class) ); } - /** - * @expectedException Innmind\Rest\Client\Exception\SpecificationCantBeTranslated - */ public function testThrowWhenTranslatingUnknownSpecification() { + $this->expectException(SpecificationCantBeTranslated::class); + (new SpecificationTranslator)( $this->createMock(Specification::class) ); diff --git a/tests/Visitor/ResolveIdentityTest.php b/tests/Visitor/ResolveIdentityTest.php index a5080fb..334f5bc 100644 --- a/tests/Visitor/ResolveIdentityTest.php +++ b/tests/Visitor/ResolveIdentityTest.php @@ -22,8 +22,8 @@ public function testResolveIdentity($source, $destination, $expected) $this->assertSame( $expected, $resolve( - Url::fromString($source), - Url::fromString($destination) + Url::of($source), + Url::of($destination) ) ); }