diff --git a/.gitignore b/.gitignore index 4dba517..a53c0f8 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,10 @@ /tests/files/api.log /coverage/* /index.html +/phpcs.xml /phpstan.neon /phpunit.xml +/psalm.xml /provision/* /vendor/* !/vendor/.gitkeep diff --git a/composer.json b/composer.json index 804f193..4ba3381 100644 --- a/composer.json +++ b/composer.json @@ -25,10 +25,10 @@ "woohoolabs/yang": "^3.0" }, "require-dev": { - "cakephp/cakephp-codesniffer": "^3.0", + "cakephp/cakephp-codesniffer": "^5.0", "josegonzalez/dotenv": "2.*", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.0", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^10.5.5 || ^11.1.3", "psy/psysh": "@stable", "vimeo/psalm": "^5.18" }, @@ -64,6 +64,9 @@ }, "prefer-stable": true, "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index c270ddf..a6f6536 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,10 @@ - + ./src/ - + diff --git a/psalm.xml.dist b/psalm.xml.dist new file mode 100644 index 0000000..597e73c --- /dev/null +++ b/psalm.xml.dist @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/src/BEditaClient.php b/src/BEditaClient.php index 4aaeaaa..1266115 100644 --- a/src/BEditaClient.php +++ b/src/BEditaClient.php @@ -1,5 +1,6 @@ setDefaultHeaders($headers); } + $body = (string)json_encode(compact('username', 'password') + ['grant_type' => 'password']); - return $this->post('/auth', json_encode(compact('username', 'password') + ['grant_type' => 'password']), ['Content-Type' => 'application/json']); + return $this->post('/auth', $body, ['Content-Type' => 'application/json']); } /** @@ -51,13 +55,13 @@ public function getObjects(string $type = 'objects', ?array $query = null, ?arra /** * GET a single object of a given type * - * @param int|string $id Object id + * @param string|int $id Object id * @param string $type Object type name * @param array|null $query Optional query string * @param array|null $headers Custom request headers * @return array|null Response in array format */ - public function getObject($id, string $type = 'objects', ?array $query = null, ?array $headers = null): ?array + public function getObject(string|int $id, string $type = 'objects', ?array $query = null, ?array $headers = null): ?array { return $this->get(sprintf('/%s/%s', $type, $id), $query, $headers); } @@ -65,14 +69,14 @@ public function getObject($id, string $type = 'objects', ?array $query = null, ? /** * Get a list of related resources or objects * - * @param int|string $id Resource id or object uname/id + * @param string|int $id Resource id or object uname/id * @param string $type Type name * @param string $relation Relation name * @param array|null $query Optional query string * @param array|null $headers Custom request headers * @return array|null Response in array format */ - public function getRelated($id, string $type, string $relation, ?array $query = null, ?array $headers = null): ?array + public function getRelated(string|int $id, string $type, string $relation, ?array $query = null, ?array $headers = null): ?array { return $this->get(sprintf('/%s/%s/%s', $type, $id, $relation), $query, $headers); } @@ -80,14 +84,14 @@ public function getRelated($id, string $type, string $relation, ?array $query = /** * Add a list of related resources or objects * - * @param int|string $id Resource id or object uname/id + * @param string|int $id Resource id or object uname/id * @param string $type Type name * @param string $relation Relation name * @param array $data Related resources or objects to add, MUST contain id and type * @param array|null $headers Custom request headers * @return array|null Response in array format */ - public function addRelated($id, string $type, string $relation, array $data, ?array $headers = null): ?array + public function addRelated(string|int $id, string $type, string $relation, array $data, ?array $headers = null): ?array { return $this->post(sprintf('/%s/%s/relationships/%s', $type, $id, $relation), json_encode(compact('data')), $headers); } @@ -95,14 +99,14 @@ public function addRelated($id, string $type, string $relation, array $data, ?ar /** * Remove a list of related resources or objects * - * @param int|string $id Resource id or object uname/id + * @param string|int $id Resource id or object uname/id * @param string $type Type name * @param string $relation Relation name * @param array $data Related resources or objects to remove from relation * @param array|null $headers Custom request headers * @return array|null Response in array format */ - public function removeRelated($id, string $type, string $relation, array $data, ?array $headers = null): ?array + public function removeRelated(string|int $id, string $type, string $relation, array $data, ?array $headers = null): ?array { return $this->delete(sprintf('/%s/%s/relationships/%s', $type, $id, $relation), json_encode(compact('data')), $headers); } @@ -110,14 +114,14 @@ public function removeRelated($id, string $type, string $relation, array $data, /** * Replace a list of related resources or objects: previuosly related are removed and replaced with these. * - * @param int|string $id Object id + * @param string|int $id Object id * @param string $type Object type name * @param string $relation Relation name * @param array $data Related resources or objects to insert * @param array|null $headers Custom request headers * @return array|null Response in array format */ - public function replaceRelated($id, string $type, string $relation, array $data, ?array $headers = null): ?array + public function replaceRelated(string|int $id, string $type, string $relation, array $data, ?array $headers = null): ?array { return $this->patch(sprintf('/%s/%s/relationships/%s', $type, $id, $relation), json_encode(compact('data')), $headers); } @@ -170,11 +174,11 @@ public function saveObject(string $type, array $data, ?array $headers = null): ? /** * Delete an object (DELETE) => move to trashcan. * - * @param int|string $id Object id + * @param string|int $id Object id * @param string $type Object type name * @return array|null Response in array format */ - public function deleteObject($id, string $type): ?array + public function deleteObject(string|int $id, string $type): ?array { return $this->delete(sprintf('/%s/%s', $type, $id)); } @@ -191,7 +195,7 @@ public function deleteObjects(array $ids, string $type = 'objects'): ?array $response = null; try { $response = $this->delete(sprintf('/%s?ids=%s', $type, implode(',', $ids))); - } catch (\Exception $e) { + } catch (Exception $e) { // fallback to delete one by one, to be retrocompatible foreach ($ids as $id) { $response = !empty($response) ? $response : $this->deleteObject($id, $type); @@ -204,10 +208,10 @@ public function deleteObjects(array $ids, string $type = 'objects'): ?array /** * Remove an object => permanently remove object from trashcan. * - * @param int|string $id Object id + * @param string|int $id Object id * @return array|null Response in array format */ - public function remove($id): ?array + public function remove(string|int $id): ?array { return $this->delete(sprintf('/trash/%s', $id)); } @@ -223,7 +227,7 @@ public function removeObjects(array $ids): ?array $response = null; try { $response = $this->delete(sprintf('/trash?ids=%s', implode(',', $ids))); - } catch (\Exception $e) { + } catch (Exception $e) { // fallback to delete one by one, to be retrocompatible foreach ($ids as $id) { $response = !empty($response) ? $response : $this->remove($id); @@ -270,7 +274,7 @@ public function upload(string $filename, string $filepath, ?array $headers = nul * @return array|null Response in array format * @throws \BEdita\SDK\BEditaClientException */ - public function createMediaFromStream($streamId, string $type, array $body): ?array + public function createMediaFromStream(string $streamId, string $type, array $body): ?array { $id = $this->createMedia($type, $body); $this->addStreamToMedia($streamId, $id, $type); @@ -335,7 +339,7 @@ public function addStreamToMedia(string $streamId, string $id, string $type): vo * @param array $query The query params for thumbs call. * @return array|null Response in array format */ - public function thumbs($id = null, $query = []): ?array + public function thumbs(?int $id = null, array $query = []): ?array { if (empty($id) && empty($query['ids'])) { throw new BEditaClientException('Invalid empty id|ids for thumbs'); @@ -377,11 +381,11 @@ public function relationData(string $name): ?array /** * Restore object from trash * - * @param int|string $id Object id + * @param string|int $id Object id * @param string $type Object type name * @return array|null Response in array format */ - public function restoreObject($id, string $type): ?array + public function restoreObject(string|int $id, string $type): ?array { return $this->patch( sprintf('/trash/%s', $id), diff --git a/src/BEditaClientException.php b/src/BEditaClientException.php index aef4196..efe4ce6 100644 --- a/src/BEditaClientException.php +++ b/src/BEditaClientException.php @@ -1,4 +1,6 @@ defaultCode; diff --git a/src/BaseClient.php b/src/BaseClient.php index 1968602..77f9c0a 100644 --- a/src/BaseClient.php +++ b/src/BaseClient.php @@ -1,5 +1,6 @@ 'application/vnd.api+json', ]; @@ -56,7 +58,7 @@ class BaseClient * * @var array */ - private $defaultContentTypeHeader = [ + private array $defaultContentTypeHeader = [ 'Content-Type' => 'application/json', ]; @@ -65,14 +67,14 @@ class BaseClient * * @var array */ - private $tokens = []; + private array $tokens = []; /** * JSON API BEdita client * * @var \WoohooLabs\Yang\JsonApi\Client\JsonApiClient */ - private $jsonApiClient = null; + private JsonApiClient $jsonApiClient; /** * Setup main client options: @@ -89,7 +91,7 @@ class BaseClient public function __construct(string $apiUrl, ?string $apiKey = null, array $tokens = [], array $guzzleConfig = []) { $this->apiBaseUrl = $apiUrl; - $this->apiKey = $apiKey; + $this->apiKey = (string)$apiKey; $this->defaultHeaders['X-Api-Key'] = $this->apiKey; $this->setupTokens($tokens); @@ -159,11 +161,11 @@ public function getTokens(): array /** * Get last HTTP response * - * @return ResponseInterface|null Response PSR interface + * @return \Psr\Http\Message\ResponseInterface|null Response PSR interface */ public function getResponse(): ?ResponseInterface { - return $this->response; + return $this->response ?? null; } /** @@ -174,7 +176,7 @@ public function getResponse(): ?ResponseInterface */ public function getStatusCode(): ?int { - return $this->response ? $this->response->getStatusCode() : null; + return !empty($this->getResponse()) ? $this->response->getStatusCode() : null; } /** @@ -185,7 +187,7 @@ public function getStatusCode(): ?int */ public function getStatusMessage(): ?string { - return $this->response ? $this->response->getReasonPhrase() : null; + return !empty($this->getResponse()) ? $this->response->getReasonPhrase() : null; } /** @@ -216,7 +218,7 @@ public function getResponseBody(): ?array public function refreshTokens(): void { if (empty($this->tokens['renew'])) { - throw new \BadMethodCallException('You must be logged in to renew token'); + throw new BadMethodCallException('You must be logged in to renew token'); } $headers = [ @@ -239,8 +241,8 @@ public function refreshTokens(): void * @param string $method HTTP Method. * @param string $path Endpoint URL path. * @param array|null $query Query string parameters. - * @param string[]|null $headers Custom request headers. - * @param string|resource|\Psr\Http\Message\StreamInterface|null $body Request body. + * @param array|null $headers Custom request headers. + * @param \Psr\Http\Message\StreamInterface|resource|string|null $body Request body. * @return \Psr\Http\Message\ResponseInterface */ protected function sendRequestRetry(string $method, string $path, ?array $query = null, ?array $headers = null, $body = null): ResponseInterface @@ -269,8 +271,8 @@ protected function sendRequestRetry(string $method, string $path, ?array $query * @param string $method HTTP Method. * @param string $path Endpoint URL path. * @param array|null $query Query string parameters. - * @param string[]|null $headers Custom request headers. - * @param string|resource|\Psr\Http\Message\StreamInterface|null $body Request body. + * @param array|null $headers Custom request headers. + * @param \Psr\Http\Message\StreamInterface|resource|string|null $body Request body. * @return \Psr\Http\Message\ResponseInterface */ protected function refreshAndRetry(string $method, string $path, ?array $query = null, ?array $headers = null, $body = null): ResponseInterface @@ -287,8 +289,8 @@ protected function refreshAndRetry(string $method, string $path, ?array $query = * @param string $method HTTP Method. * @param string $path Endpoint URL path (with or without starting `/`) or absolute API path * @param array|null $query Query string parameters. - * @param string[]|null $headers Custom request headers. - * @param string|resource|\Psr\Http\Message\StreamInterface|null $body Request body. + * @param array|null $headers Custom request headers. + * @param \Psr\Http\Message\StreamInterface|resource|string|null $body Request body. * @return \Psr\Http\Message\ResponseInterface * @throws \BEdita\SDK\BEditaClientException Throws an exception if server response code is not 20x. */ @@ -326,7 +328,7 @@ protected function sendRequest(string $method, string $path, ?array $query = nul * * @param string $path Endpoint URL path (with or without starting `/`) or absolute API path * @param array|null $query Query string parameters. - * @return Uri + * @return \GuzzleHttp\Psr7\Uri */ protected function requestUri(string $path, ?array $query = null): Uri { @@ -380,11 +382,11 @@ public function get(string $path, ?array $query = null, ?array $headers = null): * Send a PATCH request to modify a single resource or object * * @param string $path Endpoint URL path to invoke - * @param mixed $body Request body + * @param string|null $body Request body * @param array|null $headers Custom request headers * @return array|null Response in array format */ - public function patch(string $path, $body, ?array $headers = null): ?array + public function patch(string $path, ?string $body = null, ?array $headers = null): ?array { $this->sendRequestRetry('PATCH', $path, null, $headers, $body); @@ -395,11 +397,11 @@ public function patch(string $path, $body, ?array $headers = null): ?array * Send a POST request for creating resources or objects or other operations like /auth * * @param string $path Endpoint URL path to invoke - * @param mixed $body Request body + * @param string|null $body Request body * @param array|null $headers Custom request headers * @return array|null Response in array format */ - public function post(string $path, $body, ?array $headers = null): ?array + public function post(string $path, ?string $body = null, ?array $headers = null): ?array { $this->sendRequestRetry('POST', $path, null, $headers, $body); @@ -410,11 +412,11 @@ public function post(string $path, $body, ?array $headers = null): ?array * Send a DELETE request * * @param string $path Endpoint URL path to invoke. - * @param mixed $body Request body + * @param string|null $body Request body * @param array|null $headers Custom request headers * @return array|null Response in array format. */ - public function delete(string $path, $body = null, ?array $headers = null): ?array + public function delete(string $path, ?string $body = null, ?array $headers = null): ?array { $this->sendRequestRetry('DELETE', $path, null, $headers, $body); diff --git a/src/LogTrait.php b/src/LogTrait.php index 263ab9a..8886cc6 100644 --- a/src/LogTrait.php +++ b/src/LogTrait.php @@ -1,4 +1,6 @@ getBody(); - if (empty((string)$body)) { + $body = $request->getBody()->getContents(); + if (empty($body)) { return '(empty)'; } - $data = json_decode($body, true); + $data = (array)json_decode($body, true); foreach (['password', 'old_password', 'confirm-password'] as $field) { $this->maskPasswordField($data, $field); } @@ -121,7 +123,7 @@ public function maskPasswordField(array &$data, string $field): void /** * Return request headers as string without sensitive information. * - * @param RequestInterface $request The request to log + * @param \Psr\Http\Message\RequestInterface $request The request to log * @return string */ protected function requestHeadersCleanup(RequestInterface $request): string @@ -139,7 +141,7 @@ protected function requestHeadersCleanup(RequestInterface $request): string /** * Perform response log * - * @param ResponseInterface $response The response to log + * @param \Psr\Http\Message\ResponseInterface $response The response to log * @return void */ public function logResponse(ResponseInterface $response): void @@ -161,17 +163,17 @@ public function logResponse(ResponseInterface $response): void /** * Return response body without sensitive information. * - * @param ResponseInterface $response The response to log + * @param \Psr\Http\Message\ResponseInterface $response The response to log * @return string */ protected function responseBodyCleanup(ResponseInterface $response): string { - $body = $response->getBody(); - if (empty((string)$body)) { + $body = $response->getBody()->getContents(); + if (empty($body)) { return '(empty)'; } - $data = json_decode($body, true); + $data = (array)json_decode($body, true); foreach (['jwt', 'renew'] as $tok) { if (!empty($data['meta'][$tok])) { $data['meta'][$tok] = '***************'; diff --git a/tests/TestCase/BEditaClientExceptionTest.php b/tests/TestCase/BEditaClientExceptionTest.php index 1f32578..49210a1 100644 --- a/tests/TestCase/BEditaClientExceptionTest.php +++ b/tests/TestCase/BEditaClientExceptionTest.php @@ -1,4 +1,6 @@ defaultCode = 500; - } - /** * Data provider for `testConstruct` */ - public function exceptionsProvider(): array + public static function exceptionsProvider(): array { return [ '400' => [ ['File not found', 400], - new BEditaClientException('File not found', 400), + ['File not found', 400], ], '401' => [ ['Unauthorized', 401], - new BEditaClientException('Unauthorized', 401), + ['Unauthorized', 401], ], '403' => [ ['Forbidden', 403], - new BEditaClientException('Forbidden', 403), + ['Forbidden', 403], ], '500' => [ [['System error', 'Something very bad happened'], 500], - new BEditaClientException(['System error', 'Something very bad happened'], 500), + [['System error', 'Something very bad happened'], 500], ], 'null' => [ ['File not found', null], - new BEditaClientException('File not found', $this->defaultCode), + ['File not found', 503], ], ]; } @@ -71,13 +55,14 @@ public function exceptionsProvider(): array /** * Test exception constructor * + * @param array $input Input data + * @param array $expected Expected data for exception * @return void - * - * @covers ::__construct() - * @dataProvider exceptionsProvider() */ - public function testConstruct($input, $expected): void + #[DataProvider('exceptionsProvider')] + public function testConstruct(array $input, array $expected): void { + $expected = new BEditaClientException($expected[0], $expected[1]); $this->expectException(get_class($expected)); $this->expectExceptionCode($expected->getCode()); $this->expectExceptionMessage($expected->getMessage()); @@ -87,13 +72,14 @@ public function testConstruct($input, $expected): void /** * Test `getAttributes()` * + * @param array $input Input data + * @param array $expected Expected data for exception * @return void - * - * @covers ::getAttributes() - * @dataProvider exceptionsProvider() */ - public function testAttributes($input, $expected): void + #[DataProvider('exceptionsProvider')] + public function testAttributes(array $input, array $expected): void { + $expected = new BEditaClientException($expected[0], $expected[1]); $this->expectException(get_class($expected)); if (is_array($input[0])) { static::assertEquals($expected->getAttributes(), $input[0]); diff --git a/tests/TestCase/BEditaClientTest.php b/tests/TestCase/BEditaClientTest.php index 50b61b9..fdc0676 100644 --- a/tests/TestCase/BEditaClientTest.php +++ b/tests/TestCase/BEditaClientTest.php @@ -1,5 +1,6 @@ apiBaseUrl = getenv('BEDITA_API'); - $this->apiKey = getenv('BEDITA_API_KEY'); - $this->adminUser = getenv('BEDITA_ADMIN_USR'); - $this->adminPassword = getenv('BEDITA_ADMIN_PWD'); + $this->apiBaseUrl = (string)getenv('BEDITA_API'); + $this->apiKey = (string)getenv('BEDITA_API_KEY'); + $this->adminUser = (string)getenv('BEDITA_ADMIN_USR'); + $this->adminPassword = (string)getenv('BEDITA_ADMIN_PWD'); $this->client = new BEditaClient($this->apiBaseUrl, $this->apiKey); $this->myclient = new MyBEditaClient($this->apiBaseUrl, $this->apiKey); } @@ -108,7 +86,6 @@ public function setUp(): void * Test client constructor * * @return void - * @covers ::__construct() */ public function testConstruct(): void { @@ -121,8 +98,6 @@ public function testConstruct(): void * Test `authenticate` method * * @return void - * @covers ::authenticate() - * @covers ::setDefaultHeaders() */ public function testAuthenticate(): void { @@ -140,7 +115,6 @@ public function testAuthenticate(): void * Test `authenticate` method failure * * @return void - * @covers ::authenticate() */ public function testAuthenticateFail(): void { @@ -165,7 +139,6 @@ private function authenticate(): void * Test `getObjects` method * * @return void - * @covers ::getObjects() */ public function testGetObjects(): void { @@ -182,7 +155,6 @@ public function testGetObjects(): void * Test `getObject` method * * @return void - * @covers ::getObject() */ public function testGetObject(): void { @@ -198,7 +170,7 @@ public function testGetObject(): void /** * Data provider for `testGetRelated` */ - public function getRelatedProvider(): array + public static function getRelatedProvider(): array { return [ '200 OK, User 1 Roles' => [ @@ -221,9 +193,8 @@ public function getRelatedProvider(): array * @param mixed $input Input data * @param mixed $expected Expected result * @return void - * @covers ::getRelated() - * @dataProvider getRelatedProvider */ + #[DataProvider('getRelatedProvider')] public function testGetRelated($input, $expected): void { $this->authenticate(); @@ -237,7 +208,7 @@ public function testGetRelated($input, $expected): void /** * Data provider for `testRelated` */ - public function relatedProvider(): array + public static function relatedProvider(): array { return [ 'folder => parent => folder' => [ @@ -265,7 +236,7 @@ public function relatedProvider(): array } /** - * Test `addRelated` method + * Test `addRelated`, `removeRelated`, `replaceRelated` methods * * @param mixed $parentType Parent object type * @param mixed $parentData Parent object data @@ -274,11 +245,8 @@ public function relatedProvider(): array * @param mixed $relation Relationship name * @param mixed $expected Expected result * @return void - * @covers ::addRelated() - * @covers ::removeRelated() - * @covers ::replaceRelated() - * @dataProvider relatedProvider */ + #[DataProvider('relatedProvider')] public function testRelated($parentType, $parentData, $childType, $childData, $relation, $expected): void { $this->authenticate(); @@ -357,8 +325,6 @@ public function testRelated($parentType, $parentData, $childType, $childData, $r * Test `upload` and `createMediaFromStream` methods * * @return void - * @covers ::upload() - * @covers ::createMediaFromStream() */ public function testUploadCreate(): void { @@ -407,7 +373,7 @@ public function testUploadCreate(): void /** * Data provider for `testUpload` */ - public function uploadProvider(): array + public static function uploadProvider(): array { return [ '500 File not found' => [ @@ -457,14 +423,12 @@ public function uploadProvider(): array * @param mixed $input Input data for upload * @param mixed $expected Expected result * @return void - * @dataProvider uploadProvider - * @covers ::upload() - * @covers ::createMediaFromStream() */ + #[DataProvider('uploadProvider')] public function testUpload($input, $expected): void { $this->authenticate(); - if ($expected instanceof \Exception) { + if ($expected instanceof Exception) { $this->expectException(get_class($expected)); $this->expectExceptionMessage($expected->getMessage()); } @@ -478,11 +442,9 @@ public function testUpload($input, $expected): void } /** - * Test `createMedia` + * Test `createMedia` and `addStreamToMedia` methods * * @return void - * @covers ::createMedia() - * @covers ::addStreamToMedia() */ public function testCreateMediaAndAddToStream(): void { @@ -510,13 +472,12 @@ public function testCreateMediaAndAddToStream(): void * Test `createMedia` when post return empty array * * @return void - * @covers ::createMedia() */ public function testCreateMediaException(): void { // mock post to return empty array $client = new class ($this->apiBaseUrl, $this->apiKey) extends BEditaClient { - public function post(string $path, $body, ?array $headers = null): ?array + public function post(string $path, ?string $body = null, ?array $headers = null): ?array { return []; } @@ -538,13 +499,12 @@ public function post(string $path, $body, ?array $headers = null): ?array * Test `addStreamToMedia` when patch return empty array * * @return void - * @covers ::addStreamToMedia() */ public function testAddStreamToMediaException(): void { // mock patch to return empty array $client = new class ($this->apiBaseUrl, $this->apiKey) extends BEditaClient { - public function patch(string $path, $body, ?array $headers = null): ?array + public function patch(string $path, ?string $body = null, ?array $headers = null): ?array { return []; } @@ -559,7 +519,6 @@ public function patch(string $path, $body, ?array $headers = null): ?array * Test `thumbs` method * * @return void - * @covers ::thumbs() */ public function testThumbs(): void { @@ -573,7 +532,7 @@ public function testThumbs(): void // test thumbs(:id, :query) $query = ['preset' => 'default']; foreach ($ids as $id) { - $response = $this->client->thumbs($id, $query); + $response = $this->client->thumbs(intval($id), $query); static::assertNotEmpty($response['meta']); static::assertNotEmpty($response['meta']['thumbnails']); } @@ -619,7 +578,7 @@ private function _image(): string /** * Data provider for `testSave` */ - public function saveProvider(): array + public static function saveProvider(): array { return [ 'document' => [ @@ -650,9 +609,8 @@ public function saveProvider(): array * @param mixed $input Input data for save * @param mixed $expected Expected result * @return void - * @dataProvider saveProvider - * @covers ::save() */ + #[DataProvider('saveProvider')] public function testSave($input, $expected): void { $this->authenticate(); @@ -682,7 +640,7 @@ public function testSave($input, $expected): void /** * Data provider for `testDeleteObject` */ - public function deleteObjectProvider(): array + public static function deleteObjectProvider(): array { return [ 'document' => [ @@ -707,9 +665,8 @@ public function deleteObjectProvider(): array * @param array $input Input data for delete * @param array $expected Expected result * @return void - * @dataProvider deleteObjectProvider - * @covers ::deleteObject() */ + #[DataProvider('deleteObjectProvider')] public function testDeleteObject(array $input, array $expected): void { $this->authenticate(); @@ -722,12 +679,8 @@ public function testDeleteObject(array $input, array $expected): void /** * Test `deleteObjects`, `removeObjects` and `restoreObjects. - * Skip on be4 (delete multiple available from BEdita v5.28.0). * * @return void - * @covers ::deleteObjects() - * @covers ::restoreObjects() - * @covers ::getObject() */ public function testDeleteRemoveRestore(): void { @@ -766,7 +719,6 @@ public function testDeleteRemoveRestore(): void * Test `deleteObjects` on exception. * * @return void - * @covers ::deleteObjects() */ public function testDeleteObjects(): void { @@ -809,7 +761,7 @@ public function testDeleteObjectsOnException(): void /** * Data provider for `testRestoreObject` */ - public function restoreObjectProvider(): array + public static function restoreObjectProvider(): array { return [ 'document' => [ @@ -834,9 +786,8 @@ public function restoreObjectProvider(): array * @param mixed $input Input data for restore * @param mixed $expected Expected result * @return void - * @dataProvider restoreObjectProvider - * @covers ::restoreObject() */ + #[DataProvider('restoreObjectProvider')] public function testRestoreObject($input, $expected): void { $this->authenticate(); @@ -851,10 +802,8 @@ public function testRestoreObject($input, $expected): void /** * Test `restoreObjects`. - * Skip on be4 (delete multiple available from BEdita v5.28.0). * * @return void - * @covers ::restoreObjects() */ public function testRestoreObjects(): void { @@ -877,7 +826,7 @@ public function testRestoreObjects(): void /** * Data provider for `testRemove` */ - public function removeProvider(): array + public static function removeProvider(): array { return [ 'document' => [ @@ -902,9 +851,8 @@ public function removeProvider(): array * @param mixed $input Input data for remove * @param mixed $expected Expected result * @return void - * @dataProvider removeProvider - * @covers ::remove() */ + #[DataProvider('removeProvider')] public function testRemove($input, $expected): void { $this->authenticate(); @@ -921,7 +869,6 @@ public function testRemove($input, $expected): void * Test `removeObjects` on exception. * * @return void - * @covers ::removeObjects() */ public function testRemoveObjects(): void { @@ -970,7 +917,6 @@ public function testRemoveObjectsOnException(): void * Test `schema`. * * @return void - * @covers ::schema() */ public function testSchema(): void { @@ -986,7 +932,6 @@ public function testSchema(): void * Test `relationData`. * * @return void - * @covers ::relationData() */ public function testRelationData(): void { @@ -1033,7 +978,7 @@ public function testRelationData(): void /** * Data provider for `testSendRequest` */ - public function sendRequestProvider(): array + public static function sendRequestProvider(): array { return [ 'get users' => [ @@ -1116,18 +1061,16 @@ public function sendRequestProvider(): array } /** - * Test `sendRequest`. + * Test `sendRequest` and `requestUri` methods. * * @param mixed $input Input data * @param mixed $expected Expected result * @return void - * @covers ::sendRequest() - * @covers ::requestUri() - * @dataProvider sendRequestProvider() */ + #[DataProvider('sendRequestProvider')] public function testSendRequest($input, $expected): void { - if ($expected instanceof \Exception) { + if ($expected instanceof Exception) { $this->expectException(get_class($expected)); $this->expectExceptionCode($expected->getCode()); $this->expectExceptionMessage($expected->getMessage()); @@ -1142,7 +1085,7 @@ public function testSendRequest($input, $expected): void static::assertEquals($expected['code'], $this->myclient->getStatusCode()); static::assertEquals($expected['message'], $this->myclient->getStatusMessage()); static::assertNotEmpty($responseBody); - foreach ($expected['fields'] as $key => $val) { + foreach ($expected['fields'] as $val) { static::assertNotEmpty($responseBody[$val]); } } @@ -1161,25 +1104,26 @@ private function newObject($input): int } /** - * Test several methods in sequence + * Test several methods in sequence: + * + * - save + * - addRelated + * - getRelated + * - getObject + * - removeRelated + * - deleteObject + * - remove + * - restoreObject + * - upload + * - createMediaFromStream + * - createMedia + * - addStreamToMedia + * - thumbs + * - schema + * - relationData + * - clone * * @return void - * @covers ::save() - * @covers ::addRelated() - * @covers ::getRelated() - * @covers ::getObject() - * @covers ::removeRelated() - * @covers ::deleteObject() - * @covers ::remove() - * @covers ::restoreObject() - * @covers ::upload() - * @covers ::createMediaFromStream() - * @covers ::createMedia() - * @covers ::addStreamToMedia() - * @covers ::thumbs() - * @covers ::schema() - * @covers ::relationData() - * @covers ::clone() */ public function testMultipurpose(): void { @@ -1403,7 +1347,7 @@ function ($document) { static::assertSame($streamId, $media['included'][0]['id']); // get thumbs - $thumbs = $this->client->thumbs($mediaId, ['preset' => 'default']); + $thumbs = $this->client->thumbs(intval($mediaId), ['preset' => 'default']); static::assertNotEmpty($thumbs['meta']['thumbnails']); static::assertStringContainsString('/_files/thumbs/', $thumbs['meta']['thumbnails'][0]['url']); diff --git a/tests/TestCase/BaseClientTest.php b/tests/TestCase/BaseClientTest.php index 809e10f..cda298c 100644 --- a/tests/TestCase/BaseClientTest.php +++ b/tests/TestCase/BaseClientTest.php @@ -1,5 +1,6 @@ apiBaseUrl = getenv('BEDITA_API'); - $this->apiKey = getenv('BEDITA_API_KEY'); - $this->adminUser = getenv('BEDITA_ADMIN_USR'); - $this->adminPassword = getenv('BEDITA_ADMIN_PWD'); + $this->apiBaseUrl = (string)getenv('BEDITA_API'); + $this->apiKey = (string)getenv('BEDITA_API_KEY'); + $this->adminUser = (string)getenv('BEDITA_ADMIN_USR'); + $this->adminPassword = (string)getenv('BEDITA_ADMIN_PWD'); $this->client = new BaseClient($this->apiBaseUrl, $this->apiKey); $this->myclient = new MyBaseClient($this->apiBaseUrl, $this->apiKey); $this->beditaClient = new BEditaClient($this->apiBaseUrl, $this->apiKey); @@ -127,7 +98,6 @@ public function setUp(): void * Test client constructor * * @return void - * @covers ::__construct() */ public function testConstruct(): void { @@ -140,7 +110,6 @@ public function testConstruct(): void * Test `setupTokens` method * * @return void - * @covers ::setupTokens() */ public function testSetupTokens(): void { @@ -160,10 +129,6 @@ public function testSetupTokens(): void * Test getters * * @return void - * @covers ::getDefaultHeaders() - * @covers ::getApiBaseUrl() - * @covers ::getTokens() - * @covers ::getResponse() */ public function testGetters(): void { @@ -187,9 +152,6 @@ public function testGetters(): void * Test code/message/response body method * * @return void - * @covers ::getStatusCode() - * @covers ::getStatusMessage() - * @covers ::getResponseBody() */ public function testCodeMessageResponse(): void { @@ -207,7 +169,7 @@ public function testCodeMessageResponse(): void /** * Data provider for `testGetResponseBody` */ - public function responseBodyProvider(): array + public static function responseBodyProvider(): array { return [ 'get users' => [ @@ -243,15 +205,13 @@ public function responseBodyProvider(): array * @param mixed $input Input data * @param mixed $expected Expected result * @return void - * - * @covers ::getResponseBody() - * @dataProvider responseBodyProvider() */ + #[DataProvider('responseBodyProvider')] public function testGetResponseBody($input, $expected): void { $response = $this->beditaClient->authenticate($this->adminUser, $this->adminPassword); $this->myclient->setupTokens($response['meta']); - if ($expected instanceof \Exception) { + if ($expected instanceof Exception) { $this->expectException(get_class($expected)); $this->expectExceptionCode($expected->getCode()); } @@ -260,7 +220,7 @@ public function testGetResponseBody($input, $expected): void static::assertEquals($expected['code'], $this->myclient->getStatusCode()); static::assertEquals($expected['message'], $this->myclient->getStatusMessage()); static::assertNotEmpty($response); - foreach ($expected['fields'] as $key => $val) { + foreach ($expected['fields'] as $val) { static::assertNotEmpty($response[$val]); } } @@ -268,7 +228,7 @@ public function testGetResponseBody($input, $expected): void /** * Data provider for `testSendRequest` */ - public function sendRequestProvider(): array + public static function sendRequestProvider(): array { return [ 'get users' => [ @@ -356,14 +316,11 @@ public function sendRequestProvider(): array * @param mixed $input Input data * @param mixed $expected Expected result * @return void - * - * @covers ::sendRequest() - * @covers ::requestUri() - * @dataProvider sendRequestProvider() */ + #[DataProvider('sendRequestProvider')] public function testSendRequest($input, $expected): void { - if ($expected instanceof \Exception) { + if ($expected instanceof Exception) { $this->expectException(get_class($expected)); $this->expectExceptionCode($expected->getCode()); $this->expectExceptionMessage($expected->getMessage()); @@ -378,7 +335,7 @@ public function testSendRequest($input, $expected): void static::assertEquals($expected['code'], $this->myclient->getStatusCode()); static::assertEquals($expected['message'], $this->myclient->getStatusMessage()); static::assertNotEmpty($responseBody); - foreach ($expected['fields'] as $key => $val) { + foreach ($expected['fields'] as $val) { static::assertNotEmpty($responseBody[$val]); } } @@ -386,7 +343,7 @@ public function testSendRequest($input, $expected): void /** * Data provider for `testSendRequestRetry` */ - public function sendRequestRetryProvider(): array + public static function sendRequestRetryProvider(): array { return [ 'get users' => [ @@ -432,12 +389,11 @@ public function sendRequestRetryProvider(): array * @param mixed $input Input data * @param mixed $expected Expected result * @return void - * @covers ::sendRequestRetry() - * @dataProvider sendRequestRetryProvider() */ + #[DataProvider('sendRequestRetryProvider')] public function testSendRequestRetry($input, $expected): void { - if ($expected instanceof \Exception) { + if ($expected instanceof Exception) { $this->expectException(get_class($expected)); $this->expectExceptionCode($expected->getCode()); } @@ -462,7 +418,6 @@ public function testSendRequestRetry($input, $expected): void * Test `sendRequestRetry` on exception. * * @return void - * @covers ::sendRequestRetry() */ public function testSendRequestRetryOnException(): void { @@ -505,7 +460,6 @@ public function getAttributes(): array * Test `refreshAndRetry`. * * @return void - * @covers ::refreshAndRetry() */ public function testRefreshAndRetry(): void { @@ -543,12 +497,12 @@ public function testRefreshAndRetry(): void /** * Data provider for `testRefreshTokens` */ - public function refreshTokensProvider(): array + public static function refreshTokensProvider(): array { return [ 'renew token as not logged' => [ ['authenticate' => false], - new \BadMethodCallException('You must be logged in to renew token'), + new BadMethodCallException('You must be logged in to renew token'), ], 'wrong renew token' => [ ['authenticate' => true, 'token' => 'gustavo' ], @@ -571,17 +525,15 @@ public function refreshTokensProvider(): array * @param mixed $input Input data * @param mixed $expected Expected result * @return void - * - * @covers ::refreshTokens() - * @dataProvider refreshTokensProvider() */ + #[DataProvider('refreshTokensProvider')] public function testRefreshTokens($input, $expected): void { if (is_string($expected)) { $this->expectException(BEditaClientException::class); $this->expectExceptionCode($expected); } - if ($expected instanceof \Exception) { + if ($expected instanceof Exception) { $this->expectException(get_class($expected)); $this->expectExceptionCode($expected->getCode()); $this->expectExceptionMessage($expected->getMessage()); @@ -607,7 +559,6 @@ public function testRefreshTokens($input, $expected): void * Test `refreshTokens` on Invalid response from server. * * @return void - * @covers ::refreshTokens() */ public function testRefreshTokenInvalidResponseFromServer(): void { @@ -630,20 +581,19 @@ public function getResponseBody(): array * Test `unsetAuthorization` * * @return void - * @covers ::unsetAuthorization() */ public function testUnsetAuthorization(): void { // test unset on empty headers Authorization $this->invokeMethod($this->client, 'unsetAuthorization', []); - $property = new \ReflectionProperty($this->client, 'defaultHeaders'); + $property = new ReflectionProperty($this->client, 'defaultHeaders'); $property->setAccessible(true); static::assertArrayNotHasKey('Authorization', $property->getValue($this->client)); // populate headers Authorization then test unset $property->setValue($this->client, ['Authorization' => 'Bearer *****************']); $this->invokeMethod($this->client, 'unsetAuthorization', []); - $property = new \ReflectionProperty($this->client, 'defaultHeaders'); + $property = new ReflectionProperty($this->client, 'defaultHeaders'); $property->setAccessible(true); static::assertArrayNotHasKey('Authorization', $property->getValue($this->client)); } @@ -658,7 +608,7 @@ public function testUnsetAuthorization(): void */ protected function invokeMethod(&$object, $methodName, array $parameters = []) { - $reflection = new \ReflectionClass(get_class($object)); + $reflection = new ReflectionClass(get_class($object)); $method = $reflection->getMethod($methodName); $method->setAccessible(true); @@ -688,7 +638,6 @@ private function authenticate(): void * Test `get` method * * @return void - * @covers ::get() */ public function testGet(): void { @@ -700,7 +649,7 @@ public function testGet(): void /** * Data provider for `testPatch` */ - public function patchProvider(): array + public static function patchProvider(): array { return [ 'document' => [ @@ -726,9 +675,8 @@ public function patchProvider(): array * @param mixed $input Input data for patch * @param mixed $expected Expected result * @return void - * @dataProvider patchProvider - * @covers ::patch() */ + #[DataProvider('patchProvider')] public function testPatch($input, $expected): void { $this->authenticate(); @@ -763,7 +711,7 @@ public function testPatch($input, $expected): void /** * Data provider for `testPost` */ - public function postProvider(): array + public static function postProvider(): array { return [ 'document' => [ @@ -789,9 +737,8 @@ public function postProvider(): array * @param mixed $input Input data for post * @param mixed $expected Expected result * @return void - * @dataProvider postProvider - * @covers ::post() */ + #[DataProvider('postProvider')] public function testPost($input, $expected): void { $this->authenticate(); @@ -814,7 +761,7 @@ public function testPost($input, $expected): void /** * Data provider for `testDelete` */ - public function deleteProvider(): array + public static function deleteProvider(): array { return [ 'document' => [ @@ -840,9 +787,8 @@ public function deleteProvider(): array * @param mixed $input Input data for delete * @param mixed $expected Expected result * @return void - * @dataProvider deleteProvider - * @covers ::delete() */ + #[DataProvider('deleteProvider')] public function testDelete($input, $expected): void { $this->authenticate(); diff --git a/tests/TestCase/LogTraitTest.php b/tests/TestCase/LogTraitTest.php index 94d835f..ff4b705 100644 --- a/tests/TestCase/LogTraitTest.php +++ b/tests/TestCase/LogTraitTest.php @@ -1,4 +1,6 @@ $mask, 'confirm-password' => $mask, ]; - $dummy = new Dummy(); + $dummy = new class { + use LogTrait; + }; $dummy->maskPasswordField($data, 'password'); $dummy->maskPasswordField($data, 'old_password'); $dummy->maskPasswordField($data, 'confirm-password'); @@ -144,8 +131,6 @@ public function testMaskPasswordField(): void * Test empty logRequest` & `logResponse` * * @return void - * @covers ::logRequest() - * @covers ::logResponse() */ public function testEmptyLogRequestResponse(): void { @@ -155,12 +140,9 @@ public function testEmptyLogRequestResponse(): void } /** - * Test `requestBodyCleanup` & `responseBodyCleanup()` + * Test `requestBodyCleanup` & `responseBodyCleanup()` (+ maskPasswordField) * * @return void - * @covers ::requestBodyCleanup() - * @covers ::responseBodyCleanup() - * @covers ::maskPasswordField() */ public function testBodyCleanup(): void { @@ -178,7 +160,6 @@ public function testBodyCleanup(): void * Test empty `responseBodyCleanup` * * @return void - * @covers ::responseBodyCleanup() */ public function testEmptyResponseBodyCleanup(): void { diff --git a/tests/TestCase/MyBEditaClient.php b/tests/TestCase/MyBEditaClient.php new file mode 100644 index 0000000..30573fc --- /dev/null +++ b/tests/TestCase/MyBEditaClient.php @@ -0,0 +1,42 @@ + for more details. + */ + +namespace BEdita\SDK\Test\TestCase; + +use BEdita\SDK\BEditaClient; +use Psr\Http\Message\ResponseInterface; + +/** + * A simple class that extends BEditaClient. + * Used to test protected methods. + */ +class MyBEditaClient extends BEditaClient +{ + /** + * @inheritDoc + */ + public function sendRequestRetry(string $method, string $path, ?array $query = null, ?array $headers = null, $body = null): ResponseInterface + { + return parent::sendRequestRetry($method, $path, $query, $headers, $body); + } + + /** + * @inheritDoc + */ + public function sendRequest(string $method, string $path, ?array $query = null, ?array $headers = null, $body = null): ResponseInterface + { + return parent::sendRequest($method, $path, $query, $headers, $body); + } +} diff --git a/tests/TestCase/MyBaseClient.php b/tests/TestCase/MyBaseClient.php new file mode 100644 index 0000000..b5160c8 --- /dev/null +++ b/tests/TestCase/MyBaseClient.php @@ -0,0 +1,52 @@ + for more details. + */ + +namespace BEdita\SDK\Test\TestCase; + +use BEdita\SDK\BaseClient; +use Psr\Http\Message\ResponseInterface; + +/** + * A simple class that extends BaseClient. + * Used to test protected methods. + */ +class MyBaseClient extends BaseClient +{ + /** + * @inheritDoc + */ + public function sendRequestRetry( + string $method, + string $path, + ?array $query = null, + ?array $headers = null, + $body = null + ): ResponseInterface { + return parent::sendRequestRetry($method, $path, $query, $headers, $body); + } + + /** + * @inheritDoc + */ + public function sendRequest( + string $method, + string $path, + ?array $query = null, + ?array $headers = null, + $body = null + ): ResponseInterface { + return parent::sendRequest($method, $path, $query, $headers, $body); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 8a6abe1..f68bd13 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,4 +1,7 @@ parse() ->putenv() ->toEnv()