From ef2ca13805a44096283e94f1f1f94089ab917eab Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 18 Jan 2024 15:28:34 +0100 Subject: [PATCH 1/5] Rename Response:getBody() to getContent() --- src/Redmine/Api/AbstractApi.php | 14 ++++++------- src/Redmine/Api/CustomField.php | 2 +- src/Redmine/Api/Group.php | 2 +- src/Redmine/Api/Issue.php | 2 +- src/Redmine/Api/IssueCategory.php | 2 +- src/Redmine/Api/IssuePriority.php | 2 +- src/Redmine/Api/IssueRelation.php | 2 +- src/Redmine/Api/IssueStatus.php | 2 +- src/Redmine/Api/Membership.php | 2 +- src/Redmine/Api/News.php | 2 +- src/Redmine/Api/Project.php | 2 +- src/Redmine/Api/Query.php | 2 +- src/Redmine/Api/Role.php | 2 +- src/Redmine/Api/Search.php | 2 +- src/Redmine/Api/TimeEntry.php | 2 +- src/Redmine/Api/TimeEntryActivity.php | 2 +- src/Redmine/Api/Tracker.php | 2 +- src/Redmine/Api/User.php | 2 +- src/Redmine/Api/Version.php | 2 +- src/Redmine/Api/Wiki.php | 2 +- src/Redmine/Http/Response.php | 4 ++-- tests/Unit/Api/AbstractApi/DeleteTest.php | 2 +- tests/Unit/Api/AbstractApi/GetTest.php | 2 +- tests/Unit/Api/AbstractApi/PostTest.php | 2 +- tests/Unit/Api/AbstractApi/PutTest.php | 2 +- tests/Unit/Api/Group/CreateTest.php | 6 +++--- tests/Unit/Api/Group/UpdateTest.php | 6 +++--- tests/Unit/Api/IssueTest.php | 24 +++++++++++------------ 28 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/Redmine/Api/AbstractApi.php b/src/Redmine/Api/AbstractApi.php index 3b2851c2..18d43d23 100644 --- a/src/Redmine/Api/AbstractApi.php +++ b/src/Redmine/Api/AbstractApi.php @@ -110,7 +110,7 @@ protected function get($path, $decodeIfJson = true) { $this->lastResponse = $this->getHttpClient()->request('GET', strval($path)); - $body = $this->lastResponse->getBody(); + $body = $this->lastResponse->getContent(); $contentType = $this->lastResponse->getContentType(); // if response is XML, return a SimpleXMLElement object @@ -141,7 +141,7 @@ protected function post($path, $data) { $this->lastResponse = $this->getHttpClient()->request('POST', strval($path), $data); - $body = $this->lastResponse->getBody(); + $body = $this->lastResponse->getContent(); $contentType = $this->lastResponse->getContentType(); // if response is XML, return a SimpleXMLElement object @@ -164,7 +164,7 @@ protected function put($path, $data) { $this->lastResponse = $this->getHttpClient()->request('PUT', strval($path), $data); - $body = $this->lastResponse->getBody(); + $body = $this->lastResponse->getContent(); $contentType = $this->lastResponse->getContentType(); // if response is XML, return a SimpleXMLElement object @@ -186,7 +186,7 @@ protected function delete($path) { $this->lastResponse = $this->getHttpClient()->request('DELETE', strval($path)); - return $this->lastResponse->getBody(); + return $this->lastResponse->getContent(); } /** @@ -234,7 +234,7 @@ protected function retrieveAll($endpoint, array $params = []) try { $data = $this->retrieveData(strval($endpoint), $params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } @@ -368,7 +368,7 @@ protected function attachCustomFieldXML(SimpleXMLElement $xml, array $fields) */ private function getResponseAsArray(Response $response): array { - $body = $response->getBody(); + $body = $response->getContent(); $contentType = $response->getContentType(); $returnData = null; @@ -445,7 +445,7 @@ public function getContentType(): string return $this->contentType; } - public function getBody(): string + public function getContent(): string { return $this->body; } diff --git a/src/Redmine/Api/CustomField.php b/src/Redmine/Api/CustomField.php index 1b9d10c6..fe33074a 100644 --- a/src/Redmine/Api/CustomField.php +++ b/src/Redmine/Api/CustomField.php @@ -55,7 +55,7 @@ public function all(array $params = []) try { $this->customFields = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Group.php b/src/Redmine/Api/Group.php index 4ee6442d..622695d0 100644 --- a/src/Redmine/Api/Group.php +++ b/src/Redmine/Api/Group.php @@ -59,7 +59,7 @@ public function all(array $params = []) try { $this->groups = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Issue.php b/src/Redmine/Api/Issue.php index 3d3264cc..12f7cab5 100644 --- a/src/Redmine/Api/Issue.php +++ b/src/Redmine/Api/Issue.php @@ -110,7 +110,7 @@ public function all(array $params = []) try { return $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/IssueCategory.php b/src/Redmine/Api/IssueCategory.php index d42900f2..6686c908 100644 --- a/src/Redmine/Api/IssueCategory.php +++ b/src/Redmine/Api/IssueCategory.php @@ -69,7 +69,7 @@ public function all($project, array $params = []) try { return $this->listByProject(strval($project), $params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/IssuePriority.php b/src/Redmine/Api/IssuePriority.php index e3e777b3..0fbf0523 100644 --- a/src/Redmine/Api/IssuePriority.php +++ b/src/Redmine/Api/IssuePriority.php @@ -55,7 +55,7 @@ public function all(array $params = []) try { $this->issuePriorities = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/IssueRelation.php b/src/Redmine/Api/IssueRelation.php index 113674e4..0084265c 100644 --- a/src/Redmine/Api/IssueRelation.php +++ b/src/Redmine/Api/IssueRelation.php @@ -58,7 +58,7 @@ public function all($issueId, array $params = []) try { $this->relations = $this->listByIssueId($issueId, $params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/IssueStatus.php b/src/Redmine/Api/IssueStatus.php index fa6fd577..81dcc4fc 100644 --- a/src/Redmine/Api/IssueStatus.php +++ b/src/Redmine/Api/IssueStatus.php @@ -55,7 +55,7 @@ public function all(array $params = []) try { $this->issueStatuses = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Membership.php b/src/Redmine/Api/Membership.php index 7650ea22..130decf8 100644 --- a/src/Redmine/Api/Membership.php +++ b/src/Redmine/Api/Membership.php @@ -68,7 +68,7 @@ public function all($project, array $params = []) try { $this->memberships = $this->listByProject(strval($project), $params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/News.php b/src/Redmine/Api/News.php index e6366e17..5cecbca0 100644 --- a/src/Redmine/Api/News.php +++ b/src/Redmine/Api/News.php @@ -88,7 +88,7 @@ public function all($project = null, array $params = []) $this->news = $this->listByProject(strval($project), $params); } } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Project.php b/src/Redmine/Api/Project.php index 123086e5..10113ec9 100755 --- a/src/Redmine/Api/Project.php +++ b/src/Redmine/Api/Project.php @@ -58,7 +58,7 @@ public function all(array $params = []) try { $this->projects = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Query.php b/src/Redmine/Api/Query.php index 475a551f..7b15316b 100644 --- a/src/Redmine/Api/Query.php +++ b/src/Redmine/Api/Query.php @@ -55,7 +55,7 @@ public function all(array $params = []) try { $this->query = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Role.php b/src/Redmine/Api/Role.php index 67832c89..574f856e 100644 --- a/src/Redmine/Api/Role.php +++ b/src/Redmine/Api/Role.php @@ -55,7 +55,7 @@ public function all(array $params = []) try { $this->roles = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Search.php b/src/Redmine/Api/Search.php index f286b9c6..c287d7c9 100644 --- a/src/Redmine/Api/Search.php +++ b/src/Redmine/Api/Search.php @@ -55,7 +55,7 @@ public function search($query, array $params = []) try { $this->results = $this->listByQuery($query, $params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/TimeEntry.php b/src/Redmine/Api/TimeEntry.php index 092f68e3..0d1cae16 100644 --- a/src/Redmine/Api/TimeEntry.php +++ b/src/Redmine/Api/TimeEntry.php @@ -57,7 +57,7 @@ public function all(array $params = []) try { $this->timeEntries = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/TimeEntryActivity.php b/src/Redmine/Api/TimeEntryActivity.php index 871fe789..cc2b8264 100644 --- a/src/Redmine/Api/TimeEntryActivity.php +++ b/src/Redmine/Api/TimeEntryActivity.php @@ -51,7 +51,7 @@ public function all(array $params = []) try { $this->timeEntryActivities = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Tracker.php b/src/Redmine/Api/Tracker.php index 85f3507c..c69418a4 100644 --- a/src/Redmine/Api/Tracker.php +++ b/src/Redmine/Api/Tracker.php @@ -55,7 +55,7 @@ public function all(array $params = []) try { $this->trackers = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/User.php b/src/Redmine/Api/User.php index ca719a70..f82784c2 100644 --- a/src/Redmine/Api/User.php +++ b/src/Redmine/Api/User.php @@ -58,7 +58,7 @@ public function all(array $params = []) try { $this->users = $this->list($params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Version.php b/src/Redmine/Api/Version.php index 3252c985..d5ec42f9 100644 --- a/src/Redmine/Api/Version.php +++ b/src/Redmine/Api/Version.php @@ -67,7 +67,7 @@ public function all($project, array $params = []) try { $this->versions = $this->listByProject(strval($project), $params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Api/Wiki.php b/src/Redmine/Api/Wiki.php index 7a066978..24599129 100644 --- a/src/Redmine/Api/Wiki.php +++ b/src/Redmine/Api/Wiki.php @@ -67,7 +67,7 @@ public function all($project, array $params = []) try { $this->wikiPages = $this->listByProject(strval($project), $params); } catch (Exception $e) { - if ($this->getLastResponse()->getBody() === '') { + if ($this->getLastResponse()->getContent() === '') { return false; } diff --git a/src/Redmine/Http/Response.php b/src/Redmine/Http/Response.php index 8b380c8f..cde231d4 100644 --- a/src/Redmine/Http/Response.php +++ b/src/Redmine/Http/Response.php @@ -26,7 +26,7 @@ public function getStatusCode(): int; public function getContentType(): string; /** - * Returns the body. + * Returns the body content. */ - public function getBody(): string; + public function getContent(): string; } diff --git a/tests/Unit/Api/AbstractApi/DeleteTest.php b/tests/Unit/Api/AbstractApi/DeleteTest.php index d53d5c0e..41b62ecd 100644 --- a/tests/Unit/Api/AbstractApi/DeleteTest.php +++ b/tests/Unit/Api/AbstractApi/DeleteTest.php @@ -22,7 +22,7 @@ public function testDeleteWithHttpClient() $response = $this->createMock(Response::class); $response->expects($this->any())->method('getStatusCode')->willReturn(200); $response->expects($this->any())->method('getContentType')->willReturn('application/xml'); - $response->expects($this->any())->method('getBody')->willReturn(''); + $response->expects($this->any())->method('getContent')->willReturn(''); $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1))->method('request')->with('DELETE', 'path.xml', '')->willReturn($response); diff --git a/tests/Unit/Api/AbstractApi/GetTest.php b/tests/Unit/Api/AbstractApi/GetTest.php index 29750b59..cc3de719 100644 --- a/tests/Unit/Api/AbstractApi/GetTest.php +++ b/tests/Unit/Api/AbstractApi/GetTest.php @@ -22,7 +22,7 @@ public function testGetWithHttpClient() $response = $this->createMock(Response::class); $response->expects($this->any())->method('getStatusCode')->willReturn(200); $response->expects($this->any())->method('getContentType')->willReturn('application/json'); - $response->expects($this->any())->method('getBody')->willReturn('{"foo_bar": 12345}'); + $response->expects($this->any())->method('getContent')->willReturn('{"foo_bar": 12345}'); $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1))->method('request')->with('GET', 'path.json')->willReturn($response); diff --git a/tests/Unit/Api/AbstractApi/PostTest.php b/tests/Unit/Api/AbstractApi/PostTest.php index 7f08ea62..8d3e4579 100644 --- a/tests/Unit/Api/AbstractApi/PostTest.php +++ b/tests/Unit/Api/AbstractApi/PostTest.php @@ -22,7 +22,7 @@ public function testPostWithHttpClient() $response = $this->createMock(Response::class); $response->expects($this->any())->method('getStatusCode')->willReturn(200); $response->expects($this->any())->method('getContentType')->willReturn('application/xml'); - $response->expects($this->any())->method('getBody')->willReturn(''); + $response->expects($this->any())->method('getContent')->willReturn(''); $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1))->method('request')->with('POST', 'path.xml', '')->willReturn($response); diff --git a/tests/Unit/Api/AbstractApi/PutTest.php b/tests/Unit/Api/AbstractApi/PutTest.php index 41071ecb..35e34fb2 100644 --- a/tests/Unit/Api/AbstractApi/PutTest.php +++ b/tests/Unit/Api/AbstractApi/PutTest.php @@ -22,7 +22,7 @@ public function testPutWithHttpClient() $response = $this->createMock(Response::class); $response->expects($this->any())->method('getStatusCode')->willReturn(200); $response->expects($this->any())->method('getContentType')->willReturn('application/xml'); - $response->expects($this->any())->method('getBody')->willReturn(''); + $response->expects($this->any())->method('getContent')->willReturn(''); $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1))->method('request')->with('PUT', 'path.xml', '')->willReturn($response); diff --git a/tests/Unit/Api/Group/CreateTest.php b/tests/Unit/Api/Group/CreateTest.php index 7e34cdce..3e677a23 100644 --- a/tests/Unit/Api/Group/CreateTest.php +++ b/tests/Unit/Api/Group/CreateTest.php @@ -30,7 +30,7 @@ public function testCreateWithNameCreatesGroup() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); }); @@ -62,7 +62,7 @@ public function testCreateWithNameAndUserIdsCreatesGroup() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); }); @@ -94,7 +94,7 @@ public function testCreateWithNameAndCustomFieldsCreatesGroup() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); }); diff --git a/tests/Unit/Api/Group/UpdateTest.php b/tests/Unit/Api/Group/UpdateTest.php index 08bdaed6..b8eea2ea 100644 --- a/tests/Unit/Api/Group/UpdateTest.php +++ b/tests/Unit/Api/Group/UpdateTest.php @@ -29,7 +29,7 @@ public function testUpdateWithNameUpdatesGroup() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); }); @@ -57,7 +57,7 @@ public function testUpdateWithUserIdsUpdatesGroup() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); }); @@ -85,7 +85,7 @@ public function testUpdateWithCustomFieldsUpdatesGroup() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); }); diff --git a/tests/Unit/Api/IssueTest.php b/tests/Unit/Api/IssueTest.php index 582e8c38..74df55c7 100644 --- a/tests/Unit/Api/IssueTest.php +++ b/tests/Unit/Api/IssueTest.php @@ -528,7 +528,7 @@ public function testCreateWithHttpClientRetrievesIssueStatusId() Response::class, [ 'getContentType' => 'application/json', - 'getBody' => '{"issue_statuses":[{"name":"Status Name","id":123}]}', + 'getContent' => '{"issue_statuses":[{"name":"Status Name","id":123}]}', ] ); } @@ -541,7 +541,7 @@ public function testCreateWithHttpClientRetrievesIssueStatusId() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); } @@ -582,7 +582,7 @@ public function testCreateWithHttpClientRetrievesProjectId() Response::class, [ 'getContentType' => 'application/json', - 'getBody' => '{"projects":[{"name":"Project Name","id":3}]}', + 'getContent' => '{"projects":[{"name":"Project Name","id":3}]}', ] ); } @@ -595,7 +595,7 @@ public function testCreateWithHttpClientRetrievesProjectId() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); } @@ -636,7 +636,7 @@ public function testCreateWithHttpClientRetrievesIssueCategoryId() Response::class, [ 'getContentType' => 'application/json', - 'getBody' => '{"issue_categories":[{"name":"Category Name","id":45}]}', + 'getContent' => '{"issue_categories":[{"name":"Category Name","id":45}]}', ] ); } @@ -649,7 +649,7 @@ public function testCreateWithHttpClientRetrievesIssueCategoryId() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); } @@ -690,7 +690,7 @@ public function testCreateWithHttpClientRetrievesTrackerId() Response::class, [ 'getContentType' => 'application/json', - 'getBody' => '{"trackers":[{"name":"Tracker Name","id":9}]}', + 'getContent' => '{"trackers":[{"name":"Tracker Name","id":9}]}', ] ); } @@ -703,7 +703,7 @@ public function testCreateWithHttpClientRetrievesTrackerId() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); } @@ -744,7 +744,7 @@ public function testCreateWithHttpClientRetrievesUserId() Response::class, [ 'getContentType' => 'application/json', - 'getBody' => '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}', + 'getContent' => '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}', ] ); } @@ -757,7 +757,7 @@ public function testCreateWithHttpClientRetrievesUserId() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); } @@ -1006,7 +1006,7 @@ public function testSetIssueStatusWithHttpClient() Response::class, [ 'getContentType' => 'application/json', - 'getBody' => '{"issue_statuses":[{"name":"Status Name","id":123}]}', + 'getContent' => '{"issue_statuses":[{"name":"Status Name","id":123}]}', ] ); } @@ -1019,7 +1019,7 @@ public function testSetIssueStatusWithHttpClient() Response::class, [ 'getContentType' => 'application/xml', - 'getBody' => '', + 'getContent' => '', ] ); } From 6db2ceac2c94da47748016298531cb86261e2d75 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 23 Jan 2024 13:46:08 +0100 Subject: [PATCH 2/5] Add Request interface, change HttpClient::request() to work with Request objects --- src/Redmine/Api/AbstractApi.php | 111 +++++++++++++++--- src/Redmine/Http/HttpClient.php | 4 +- src/Redmine/Http/Request.php | 34 ++++++ tests/Fixtures/AssertingHttpClient.php | 106 +++++++++++++++++ tests/Unit/Api/AbstractApi/DeleteTest.php | 23 ++-- tests/Unit/Api/AbstractApi/GetTest.php | 22 ++-- tests/Unit/Api/AbstractApi/PostTest.php | 22 ++-- tests/Unit/Api/AbstractApi/PutTest.php | 22 ++-- tests/Unit/Api/AbstractApiTest.php | 30 +++-- tests/Unit/Api/Group/CreateTest.php | 28 +++-- tests/Unit/Api/Group/UpdateTest.php | 28 +++-- tests/Unit/Api/IssueTest.php | 135 +++++++++++----------- tests/Unit/Api/Project/ArchiveTest.php | 54 ++++----- tests/Unit/Api/Project/CloseTest.php | 51 ++++---- tests/Unit/Api/Project/ReopenTest.php | 52 ++++----- tests/Unit/Api/Project/UnarchiveTest.php | 51 ++++---- 16 files changed, 493 insertions(+), 280 deletions(-) create mode 100644 src/Redmine/Http/Request.php create mode 100644 tests/Fixtures/AssertingHttpClient.php diff --git a/src/Redmine/Api/AbstractApi.php b/src/Redmine/Api/AbstractApi.php index 18d43d23..f7001a27 100644 --- a/src/Redmine/Api/AbstractApi.php +++ b/src/Redmine/Api/AbstractApi.php @@ -9,6 +9,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; use Redmine\Http\HttpClient; +use Redmine\Http\Request; use Redmine\Http\Response; use Redmine\Serializer\JsonSerializer; use Redmine\Serializer\PathSerializer; @@ -108,7 +109,11 @@ public function lastCallFailed() */ protected function get($path, $decodeIfJson = true) { - $this->lastResponse = $this->getHttpClient()->request('GET', strval($path)); + $this->lastResponse = $this->getHttpClient()->request($this->createRequest( + 'GET', + strval($path), + $this->getContentTypeFromPath(strval($path)) + )); $body = $this->lastResponse->getContent(); $contentType = $this->lastResponse->getContentType(); @@ -139,7 +144,12 @@ protected function get($path, $decodeIfJson = true) */ protected function post($path, $data) { - $this->lastResponse = $this->getHttpClient()->request('POST', strval($path), $data); + $this->lastResponse = $this->getHttpClient()->request($this->createRequest( + 'POST', + strval($path), + $this->getContentTypeFromPath(strval($path)), + $data + )); $body = $this->lastResponse->getContent(); $contentType = $this->lastResponse->getContentType(); @@ -162,7 +172,12 @@ protected function post($path, $data) */ protected function put($path, $data) { - $this->lastResponse = $this->getHttpClient()->request('PUT', strval($path), $data); + $this->lastResponse = $this->getHttpClient()->request($this->createRequest( + 'PUT', + strval($path), + $this->getContentTypeFromPath(strval($path)), + $data + )); $body = $this->lastResponse->getContent(); $contentType = $this->lastResponse->getContentType(); @@ -184,7 +199,11 @@ protected function put($path, $data) */ protected function delete($path) { - $this->lastResponse = $this->getHttpClient()->request('DELETE', strval($path)); + $this->lastResponse = $this->getHttpClient()->request($this->createRequest( + 'DELETE', + strval($path), + $this->getContentTypeFromPath(strval($path)) + )); return $this->lastResponse->getContent(); } @@ -258,7 +277,11 @@ protected function retrieveAll($endpoint, array $params = []) protected function retrieveData(string $endpoint, array $params = []): array { if (empty($params)) { - $this->lastResponse = $this->getHttpClient()->request('GET', strval($endpoint)); + $this->lastResponse = $this->getHttpClient()->request($this->createRequest( + 'GET', + strval($endpoint), + $this->getContentTypeFromPath(strval($endpoint)) + )); return $this->getResponseAsArray($this->lastResponse); } @@ -287,10 +310,11 @@ protected function retrieveData(string $endpoint, array $params = []): array $params['limit'] = $_limit; $params['offset'] = $offset; - $this->lastResponse = $this->getHttpClient()->request( + $this->lastResponse = $this->getHttpClient()->request($this->createRequest( 'GET', - PathSerializer::create($endpoint, $params)->getPath() - ); + PathSerializer::create($endpoint, $params)->getPath(), + $this->getContentTypeFromPath($endpoint) + )); $newDataSet = $this->getResponseAsArray($this->lastResponse); @@ -400,16 +424,16 @@ public function __construct(Client $client, Closure $responseFactory) $this->responseFactory = $responseFactory; } - public function request(string $method, string $path, string $body = ''): Response + public function request(Request $request): Response { - if ($method === 'POST') { - $this->client->requestPost($path, $body); - } elseif ($method === 'PUT') { - $this->client->requestPut($path, $body); - } elseif ($method === 'DELETE') { - $this->client->requestDelete($path); + if ($request->getMethod() === 'POST') { + $this->client->requestPost($request->getPath(), $request->getContent()); + } elseif ($request->getMethod() === 'PUT') { + $this->client->requestPut($request->getPath(), $request->getContent()); + } elseif ($request->getMethod() === 'DELETE') { + $this->client->requestDelete($request->getPath()); } else { - $this->client->requestGet($path); + $this->client->requestGet($request->getPath()); } return ($this->responseFactory)( @@ -451,4 +475,59 @@ public function getContent(): string } }; } + + private function createRequest(string $method, string $path, string $contentType, string $content = ''): Request + { + return new class ($method, $path, $contentType, $content) implements Request { + private $method; + private $path; + private $contentType; + private $content; + + public function __construct(string $method, string $path, string $contentType, string $content) + { + $this->method = $method; + $this->path = $path; + $this->contentType = $contentType; + $this->content = $content; + } + + public function getMethod(): string + { + return $this->method; + } + + public function getPath(): string + { + return $this->path; + } + + public function getContentType(): string + { + return $this->contentType; + } + + public function getContent(): string + { + return $this->content; + } + }; + } + + private function getContentTypeFromPath(string $path): string + { + $tmp = parse_url($path); + + $path = strtolower($path); + + if (false !== strpos($path, '/uploads.json') || false !== strpos($path, '/uploads.xml')) { + return 'application/octet-stream'; + } elseif ('json' === substr($tmp['path'], -4)) { + return 'application/json'; + } elseif ('xml' === substr($tmp['path'], -3)) { + return 'application/xml'; + } else { + return ''; + } + } } diff --git a/src/Redmine/Http/HttpClient.php b/src/Redmine/Http/HttpClient.php index 0cc74fc4..c9fc980c 100644 --- a/src/Redmine/Http/HttpClient.php +++ b/src/Redmine/Http/HttpClient.php @@ -20,9 +20,7 @@ interface HttpClient /** * Create and send a HTTP request and return the response * - * @param string $body must be empty string on 'GET' request - * * @throws ClientException If anything goes wrong on creating or sending the request */ - public function request(string $method, string $path, string $body = ''): Response; + public function request(Request $request): Response; } diff --git a/src/Redmine/Http/Request.php b/src/Redmine/Http/Request.php new file mode 100644 index 00000000..f7093bf3 --- /dev/null +++ b/src/Redmine/Http/Request.php @@ -0,0 +1,34 @@ +getMockBuilder(HttpClient::class)->getMock(); + $mock->expects($testCase->exactly(count($dataSets)))->method('request'); + + $client = new self($testCase, $mock); + + foreach ($dataSets as $data) { + $client->assertRequestData(...$data); + } + + return $client; + } + + private $testCase; + private $client; + private $fifoStack = []; + + private function __construct(TestCase $testCase, HttpClient $client) + { + $this->testCase = $testCase; + $this->client = $client; + } + + private function assertRequestData( + string $method, + string $path, + string $contentType, + string $content = '', + int $responseCode = 200, + string $responseContentType = '', + string $responseContent = '', + ) { + if ($responseContentType === '') { + $responseContentType = $contentType; + } + + array_push($this->fifoStack, [ + 'method' => $method, + 'path' => $path, + 'contentType' => $contentType, + 'content' => $content, + 'responseCode' => $responseCode, + 'responseContentType' => $responseContentType, + 'responseContent' => $responseContent, + ]); + } + + public function request(Request $request): Response + { + $this->client->request($request); + + $data = array_shift($this->fifoStack); + + if (! is_array($data)) { + throw new \Exception(sprintf( + 'Mssing request data for Request "%s %s" with Content-Type "%s".', + $request->getMethod(), + $request->getPath(), + $request->getContentType() + )); + } + + $this->testCase->assertSame($data['method'], $request->getMethod()); + $this->testCase->assertSame($data['path'], $request->getPath()); + $this->testCase->assertSame($data['contentType'], $request->getContentType()); + + if ($data['content'] !== '' && $data['contentType'] === 'application/xml') { + $this->testCase->assertXmlStringEqualsXmlString($data['content'], $request->getContent()); + } else if ($data['content'] !== '' && $data['contentType'] === 'application/json') { + $this->testCase->assertJsonStringEqualsJsonString($data['content'], $request->getContent()); + } else { + $this->testCase->assertSame($data['content'], $request->getContent()); + } + + /** @var \PHPUnit\Framework\MockObject\MockObject&Response */ + $response = $this->testCase->getMockBuilder(Response::class)->getMock(); + + $response->method('getStatusCode')->willReturn($data['responseCode']); + $response->method('getContentType')->willReturn($data['responseContentType']); + $response->method('getContent')->willReturn($data['responseContent']); + + return $response; + } +} diff --git a/tests/Unit/Api/AbstractApi/DeleteTest.php b/tests/Unit/Api/AbstractApi/DeleteTest.php index 41b62ecd..ca38f22f 100644 --- a/tests/Unit/Api/AbstractApi/DeleteTest.php +++ b/tests/Unit/Api/AbstractApi/DeleteTest.php @@ -7,10 +7,8 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\AbstractApi; use Redmine\Client\Client; -use Redmine\Http\HttpClient; -use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; use ReflectionMethod; -use SimpleXMLElement; /** * @covers \Redmine\Api\AbstractApi::delete @@ -19,13 +17,18 @@ class DeleteTest extends TestCase { public function testDeleteWithHttpClient() { - $response = $this->createMock(Response::class); - $response->expects($this->any())->method('getStatusCode')->willReturn(200); - $response->expects($this->any())->method('getContentType')->willReturn('application/xml'); - $response->expects($this->any())->method('getContent')->willReturn(''); - - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1))->method('request')->with('DELETE', 'path.xml', '')->willReturn($response); + $client = AssertingHttpClient::create( + $this, + [ + 'DELETE', + 'path.xml', + 'application/xml', + '', + 200, + 'application/xml', + '' + ] + ); $api = new class ($client) extends AbstractApi {}; diff --git a/tests/Unit/Api/AbstractApi/GetTest.php b/tests/Unit/Api/AbstractApi/GetTest.php index cc3de719..9a49a7c3 100644 --- a/tests/Unit/Api/AbstractApi/GetTest.php +++ b/tests/Unit/Api/AbstractApi/GetTest.php @@ -7,8 +7,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\AbstractApi; use Redmine\Client\Client; -use Redmine\Http\HttpClient; -use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; use ReflectionMethod; use SimpleXMLElement; @@ -19,13 +18,18 @@ class GetTest extends TestCase { public function testGetWithHttpClient() { - $response = $this->createMock(Response::class); - $response->expects($this->any())->method('getStatusCode')->willReturn(200); - $response->expects($this->any())->method('getContentType')->willReturn('application/json'); - $response->expects($this->any())->method('getContent')->willReturn('{"foo_bar": 12345}'); - - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1))->method('request')->with('GET', 'path.json')->willReturn($response); + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + 'path.json', + 'application/json', + '', + 200, + 'application/json', + '{"foo_bar": 12345}' + ] + ); $api = new class ($client) extends AbstractApi {}; diff --git a/tests/Unit/Api/AbstractApi/PostTest.php b/tests/Unit/Api/AbstractApi/PostTest.php index 8d3e4579..8facc959 100644 --- a/tests/Unit/Api/AbstractApi/PostTest.php +++ b/tests/Unit/Api/AbstractApi/PostTest.php @@ -7,8 +7,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\AbstractApi; use Redmine\Client\Client; -use Redmine\Http\HttpClient; -use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; use ReflectionMethod; use SimpleXMLElement; @@ -19,13 +18,18 @@ class PostTest extends TestCase { public function testPostWithHttpClient() { - $response = $this->createMock(Response::class); - $response->expects($this->any())->method('getStatusCode')->willReturn(200); - $response->expects($this->any())->method('getContentType')->willReturn('application/xml'); - $response->expects($this->any())->method('getContent')->willReturn(''); - - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1))->method('request')->with('POST', 'path.xml', '')->willReturn($response); + $client = AssertingHttpClient::create( + $this, + [ + 'POST', + 'path.xml', + 'application/xml', + '', + 200, + 'application/xml', + '' + ] + ); $api = new class ($client) extends AbstractApi {}; diff --git a/tests/Unit/Api/AbstractApi/PutTest.php b/tests/Unit/Api/AbstractApi/PutTest.php index 35e34fb2..61656088 100644 --- a/tests/Unit/Api/AbstractApi/PutTest.php +++ b/tests/Unit/Api/AbstractApi/PutTest.php @@ -7,8 +7,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\AbstractApi; use Redmine\Client\Client; -use Redmine\Http\HttpClient; -use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; use ReflectionMethod; use SimpleXMLElement; @@ -19,13 +18,18 @@ class PutTest extends TestCase { public function testPutWithHttpClient() { - $response = $this->createMock(Response::class); - $response->expects($this->any())->method('getStatusCode')->willReturn(200); - $response->expects($this->any())->method('getContentType')->willReturn('application/xml'); - $response->expects($this->any())->method('getContent')->willReturn(''); - - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1))->method('request')->with('PUT', 'path.xml', '')->willReturn($response); + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + 'path.xml', + 'application/xml', + '', + 200, + 'application/xml', + '' + ] + ); $api = new class ($client) extends AbstractApi {}; diff --git a/tests/Unit/Api/AbstractApiTest.php b/tests/Unit/Api/AbstractApiTest.php index 4cb0c355..479f69ad 100644 --- a/tests/Unit/Api/AbstractApiTest.php +++ b/tests/Unit/Api/AbstractApiTest.php @@ -8,7 +8,9 @@ use Redmine\Client\Client; use Redmine\Exception\SerializerException; use Redmine\Http\HttpClient; +use Redmine\Http\Request; use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; use ReflectionMethod; use SimpleXMLElement; @@ -107,17 +109,23 @@ public static function getIsNotNullReturnsCorrectBooleanData(): array */ public function testLastCallFailedPreventsRaceCondition() { - $response1 = $this->createMock(Response::class); - $response1->method('getStatusCode')->willReturn(200); - - $response2 = $this->createMock(Response::class); - $response2->method('getStatusCode')->willReturn(500); - - $client = $this->createMock(HttpClient::class); - $client->method('request')->willReturnMap([ - ['GET', '200.json', '', $response1], - ['GET', '500.json', '', $response2], - ]); + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '200.json', + 'application/json', + '', + 200 + ], + [ + 'GET', + '500.json', + 'application/json', + '', + 500 + ] + ); $api1 = new class ($client) extends AbstractApi { public function __construct($client) diff --git a/tests/Unit/Api/Group/CreateTest.php b/tests/Unit/Api/Group/CreateTest.php index 3e677a23..e301fb3f 100644 --- a/tests/Unit/Api/Group/CreateTest.php +++ b/tests/Unit/Api/Group/CreateTest.php @@ -8,6 +8,7 @@ use Redmine\Api\Group; use Redmine\Exception\MissingParameterException; use Redmine\Http\HttpClient; +use Redmine\Http\Request; use Redmine\Http\Response; use SimpleXMLElement; @@ -21,10 +22,11 @@ public function testCreateWithNameCreatesGroup() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('POST', $method); - $this->assertSame('/groups.xml', $path); - $this->assertXmlStringEqualsXmlString('Group Name', $body); + ->willReturnCallback(function (Request $request) { + $this->assertSame('POST', $request->getMethod()); + $this->assertSame('/groups.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('Group Name', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -53,10 +55,11 @@ public function testCreateWithNameAndUserIdsCreatesGroup() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('POST', $method); - $this->assertSame('/groups.xml', $path); - $this->assertXmlStringEqualsXmlString('Group Name123', $body); + ->willReturnCallback(function (Request $request) { + $this->assertSame('POST', $request->getMethod()); + $this->assertSame('/groups.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('Group Name123', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -85,10 +88,11 @@ public function testCreateWithNameAndCustomFieldsCreatesGroup() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('POST', $method); - $this->assertSame('/groups.xml', $path); - $this->assertXmlStringEqualsXmlString('Group Name5', $body); + ->willReturnCallback(function (Request $request) { + $this->assertSame('POST', $request->getMethod()); + $this->assertSame('/groups.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('Group Name5', $request->getContent()); return $this->createConfiguredMock( Response::class, diff --git a/tests/Unit/Api/Group/UpdateTest.php b/tests/Unit/Api/Group/UpdateTest.php index b8eea2ea..4d4ec21b 100644 --- a/tests/Unit/Api/Group/UpdateTest.php +++ b/tests/Unit/Api/Group/UpdateTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Group; use Redmine\Http\HttpClient; +use Redmine\Http\Request; use Redmine\Http\Response; use SimpleXMLElement; @@ -20,10 +21,11 @@ public function testUpdateWithNameUpdatesGroup() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/groups/1.xml', $path); - $this->assertXmlStringEqualsXmlString('Group Name', $body); + ->willReturnCallback(function (Request $request) { + $this->assertSame('PUT', $request->getMethod()); + $this->assertSame('/groups/1.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('Group Name', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -48,10 +50,11 @@ public function testUpdateWithUserIdsUpdatesGroup() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/groups/1.xml', $path); - $this->assertXmlStringEqualsXmlString('123', $body); + ->willReturnCallback(function (Request $request) { + $this->assertSame('PUT', $request->getMethod()); + $this->assertSame('/groups/1.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('123', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -76,10 +79,11 @@ public function testUpdateWithCustomFieldsUpdatesGroup() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(1)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/groups/1.xml', $path); - $this->assertXmlStringEqualsXmlString('5', $body); + ->willReturnCallback(function (Request $request) { + $this->assertSame('PUT', $request->getMethod()); + $this->assertSame('/groups/1.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('5', $request->getContent()); return $this->createConfiguredMock( Response::class, diff --git a/tests/Unit/Api/IssueTest.php b/tests/Unit/Api/IssueTest.php index 74df55c7..4f1cca99 100644 --- a/tests/Unit/Api/IssueTest.php +++ b/tests/Unit/Api/IssueTest.php @@ -6,7 +6,9 @@ use Redmine\Api\Issue; use Redmine\Client\Client; use Redmine\Http\HttpClient; +use Redmine\Http\Request; use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; use Redmine\Tests\Fixtures\MockClient; use SimpleXMLElement; @@ -516,38 +518,27 @@ public function testCreateWithClientCleansParameters() */ public function testCreateWithHttpClientRetrievesIssueStatusId() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(2)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - if ($method === 'GET') { - $this->assertSame('/issue_statuses.json', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/json', - 'getContent' => '{"issue_statuses":[{"name":"Status Name","id":123}]}', - ] - ); - } - - if ($method === 'POST') { - $this->assertSame('/issues.xml', $path); - $this->assertXmlStringEqualsXmlString('123', $body); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - } - - throw new \Exception(); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '/issue_statuses.json', + 'application/json', + '', + 200, + 'application/json', + '{"issue_statuses":[{"name":"Status Name","id":123}]}' + ], + [ + 'POST', + '/issues.xml', + 'application/xml', + '123', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Issue($client); @@ -573,10 +564,11 @@ public function testCreateWithHttpClientRetrievesProjectId() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(2)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - if ($method === 'GET') { - $this->assertSame('/projects.json', $path); - $this->assertSame('', $body); + ->willReturnCallback(function (Request $request) { + if ($request->getMethod() === 'GET') { + $this->assertSame('/projects.json', $request->getPath()); + $this->assertSame('application/json', $request->getContentType()); + $this->assertSame('', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -587,9 +579,10 @@ public function testCreateWithHttpClientRetrievesProjectId() ); } - if ($method === 'POST') { - $this->assertSame('/issues.xml', $path); - $this->assertXmlStringEqualsXmlString('3', $body); + if ($request->getMethod() === 'POST') { + $this->assertSame('/issues.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('3', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -627,10 +620,11 @@ public function testCreateWithHttpClientRetrievesIssueCategoryId() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(2)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - if ($method === 'GET') { - $this->assertSame('/projects/3/issue_categories.json', $path); - $this->assertSame('', $body); + ->willReturnCallback(function (Request $request) { + if ($request->getMethod() === 'GET') { + $this->assertSame('/projects/3/issue_categories.json', $request->getPath()); + $this->assertSame('application/json', $request->getContentType()); + $this->assertSame('', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -641,9 +635,10 @@ public function testCreateWithHttpClientRetrievesIssueCategoryId() ); } - if ($method === 'POST') { - $this->assertSame('/issues.xml', $path); - $this->assertXmlStringEqualsXmlString('345', $body); + if ($request->getMethod() === 'POST') { + $this->assertSame('/issues.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('345', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -681,10 +676,11 @@ public function testCreateWithHttpClientRetrievesTrackerId() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(2)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - if ($method === 'GET') { - $this->assertSame('/trackers.json', $path); - $this->assertSame('', $body); + ->willReturnCallback(function (Request $request) { + if ($request->getMethod() === 'GET') { + $this->assertSame('/trackers.json', $request->getPath()); + $this->assertSame('application/json', $request->getContentType()); + $this->assertSame('', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -695,9 +691,10 @@ public function testCreateWithHttpClientRetrievesTrackerId() ); } - if ($method === 'POST') { - $this->assertSame('/issues.xml', $path); - $this->assertXmlStringEqualsXmlString('9', $body); + if ($request->getMethod() === 'POST') { + $this->assertSame('/issues.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('9', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -735,10 +732,11 @@ public function testCreateWithHttpClientRetrievesUserId() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(2)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - if ($method === 'GET') { - $this->assertSame('/users.json', $path); - $this->assertSame('', $body); + ->willReturnCallback(function (Request $request) { + if ($request->getMethod() === 'GET') { + $this->assertSame('/users.json', $request->getPath()); + $this->assertSame('application/json', $request->getContentType()); + $this->assertSame('', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -749,9 +747,10 @@ public function testCreateWithHttpClientRetrievesUserId() ); } - if ($method === 'POST') { - $this->assertSame('/issues.xml', $path); - $this->assertXmlStringEqualsXmlString('65', $body); + if ($request->getMethod() === 'POST') { + $this->assertSame('/issues.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('65', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -997,10 +996,11 @@ public function testSetIssueStatusWithHttpClient() $client = $this->createMock(HttpClient::class); $client->expects($this->exactly(2)) ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - if ($method === 'GET') { - $this->assertSame('/issue_statuses.json', $path); - $this->assertSame('', $body); + ->willReturnCallback(function (Request $request) { + if ($request->getMethod() === 'GET') { + $this->assertSame('/issue_statuses.json', $request->getPath()); + $this->assertSame('application/json', $request->getContentType()); + $this->assertSame('', $request->getContent()); return $this->createConfiguredMock( Response::class, @@ -1011,9 +1011,10 @@ public function testSetIssueStatusWithHttpClient() ); } - if ($method === 'PUT') { - $this->assertSame('/issues/5.xml', $path); - $this->assertXmlStringEqualsXmlString('5123', $body); + if ($request->getMethod() === 'PUT') { + $this->assertSame('/issues/5.xml', $request->getPath()); + $this->assertSame('application/xml', $request->getContentType()); + $this->assertXmlStringEqualsXmlString('5123', $request->getContent()); return $this->createConfiguredMock( Response::class, diff --git a/tests/Unit/Api/Project/ArchiveTest.php b/tests/Unit/Api/Project/ArchiveTest.php index ed7622e3..25c1bb77 100644 --- a/tests/Unit/Api/Project/ArchiveTest.php +++ b/tests/Unit/Api/Project/ArchiveTest.php @@ -1,5 +1,7 @@ createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/projects/5/archive.xml', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock(Response::class, [ - 'getStatusCode' => 204, - 'getContentType' => 'application/xml', - 'getBody' => '', - ]); - }) - ; + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/projects/5/archive.xml', + 'application/xml', + '', + 204 + ] + ); $api = new Project($client); @@ -39,21 +36,16 @@ public function testArchiveReturnsTrue() public function testArchiveThrowsUnexpectedResponseException() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/projects/5/archive.xml', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock(Response::class, [ - 'getStatusCode' => 403, - 'getContentType' => 'application/xml', - 'getBody' => '', - ]); - }) - ; + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/projects/5/archive.xml', + 'application/xml', + '', + 403 + ] + ); $api = new Project($client); diff --git a/tests/Unit/Api/Project/CloseTest.php b/tests/Unit/Api/Project/CloseTest.php index 24cfc0ac..4067b769 100644 --- a/tests/Unit/Api/Project/CloseTest.php +++ b/tests/Unit/Api/Project/CloseTest.php @@ -8,6 +8,7 @@ use Redmine\Exception\UnexpectedResponseException; use Redmine\Http\HttpClient; use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; /** * @covers \Redmine\Api\Project::close @@ -16,21 +17,16 @@ class CloseTest extends TestCase { public function testCloseReturnsTrue() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/projects/5/close.xml', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock(Response::class, [ - 'getStatusCode' => 204, - 'getContentType' => 'application/xml', - 'getBody' => '', - ]); - }) - ; + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/projects/5/close.xml', + 'application/xml', + '', + 204 + ] + ); $api = new Project($client); @@ -39,21 +35,16 @@ public function testCloseReturnsTrue() public function testCloseThrowsUnexpectedResponseException() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/projects/5/close.xml', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock(Response::class, [ - 'getStatusCode' => 403, - 'getContentType' => 'application/xml', - 'getBody' => '', - ]); - }) - ; + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/projects/5/close.xml', + 'application/xml', + '', + 403 + ] + ); $api = new Project($client); diff --git a/tests/Unit/Api/Project/ReopenTest.php b/tests/Unit/Api/Project/ReopenTest.php index ca5072ba..5e64785f 100644 --- a/tests/Unit/Api/Project/ReopenTest.php +++ b/tests/Unit/Api/Project/ReopenTest.php @@ -7,7 +7,7 @@ use Redmine\Api\Project; use Redmine\Exception\UnexpectedResponseException; use Redmine\Http\HttpClient; -use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; /** * @covers \Redmine\Api\Project::reopen @@ -16,21 +16,16 @@ class ReopenTest extends TestCase { public function testReopenReturnsTrue() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/projects/5/reopen.xml', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock(Response::class, [ - 'getStatusCode' => 204, - 'getContentType' => 'application/xml', - 'getBody' => '', - ]); - }) - ; + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/projects/5/reopen.xml', + 'application/xml', + '', + 204 + ] + ); $api = new Project($client); @@ -39,21 +34,16 @@ public function testReopenReturnsTrue() public function testReopenThrowsUnexpectedResponseException() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/projects/5/reopen.xml', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock(Response::class, [ - 'getStatusCode' => 403, - 'getContentType' => 'application/xml', - 'getBody' => '', - ]); - }) - ; + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/projects/5/reopen.xml', + 'application/xml', + '', + 403 + ] + ); $api = new Project($client); diff --git a/tests/Unit/Api/Project/UnarchiveTest.php b/tests/Unit/Api/Project/UnarchiveTest.php index 45d7e901..84a16568 100644 --- a/tests/Unit/Api/Project/UnarchiveTest.php +++ b/tests/Unit/Api/Project/UnarchiveTest.php @@ -8,6 +8,7 @@ use Redmine\Exception\UnexpectedResponseException; use Redmine\Http\HttpClient; use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; /** * @covers \Redmine\Api\Project::unarchive @@ -16,21 +17,16 @@ class UnarchiveTest extends TestCase { public function testUnarchiveReturnsTrue() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/projects/5/unarchive.xml', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock(Response::class, [ - 'getStatusCode' => 204, - 'getContentType' => 'application/xml', - 'getBody' => '', - ]); - }) - ; + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/projects/5/unarchive.xml', + 'application/xml', + '', + 204 + ] + ); $api = new Project($client); @@ -39,21 +35,16 @@ public function testUnarchiveReturnsTrue() public function testUnarchiveThrowsUnexpectedResponseException() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (string $method, string $path, string $body = '') { - $this->assertSame('PUT', $method); - $this->assertSame('/projects/5/unarchive.xml', $path); - $this->assertSame('', $body); - - return $this->createConfiguredMock(Response::class, [ - 'getStatusCode' => 403, - 'getContentType' => 'application/xml', - 'getBody' => '', - ]); - }) - ; + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/projects/5/unarchive.xml', + 'application/xml', + '', + 403 + ] + ); $api = new Project($client); From 215c9c154b8e599d903b83a24f69e8268cff55c4 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 23 Jan 2024 14:27:45 +0100 Subject: [PATCH 3/5] Refactor tests, use AssertingHttpClient --- tests/Fixtures/AssertingHttpClient.php | 2 +- tests/Unit/Api/AbstractApiTest.php | 1 - tests/Unit/Api/Group/CreateTest.php | 90 ++++---- tests/Unit/Api/Group/UpdateTest.php | 92 ++++---- tests/Unit/Api/IssueTest.php | 278 ++++++++++--------------- 5 files changed, 180 insertions(+), 283 deletions(-) diff --git a/tests/Fixtures/AssertingHttpClient.php b/tests/Fixtures/AssertingHttpClient.php index be1792f5..4d6557ce 100644 --- a/tests/Fixtures/AssertingHttpClient.php +++ b/tests/Fixtures/AssertingHttpClient.php @@ -88,7 +88,7 @@ public function request(Request $request): Response if ($data['content'] !== '' && $data['contentType'] === 'application/xml') { $this->testCase->assertXmlStringEqualsXmlString($data['content'], $request->getContent()); - } else if ($data['content'] !== '' && $data['contentType'] === 'application/json') { + } elseif ($data['content'] !== '' && $data['contentType'] === 'application/json') { $this->testCase->assertJsonStringEqualsJsonString($data['content'], $request->getContent()); } else { $this->testCase->assertSame($data['content'], $request->getContent()); diff --git a/tests/Unit/Api/AbstractApiTest.php b/tests/Unit/Api/AbstractApiTest.php index 479f69ad..b3683e9c 100644 --- a/tests/Unit/Api/AbstractApiTest.php +++ b/tests/Unit/Api/AbstractApiTest.php @@ -8,7 +8,6 @@ use Redmine\Client\Client; use Redmine\Exception\SerializerException; use Redmine\Http\HttpClient; -use Redmine\Http\Request; use Redmine\Http\Response; use Redmine\Tests\Fixtures\AssertingHttpClient; use ReflectionMethod; diff --git a/tests/Unit/Api/Group/CreateTest.php b/tests/Unit/Api/Group/CreateTest.php index e301fb3f..6cc1ef3c 100644 --- a/tests/Unit/Api/Group/CreateTest.php +++ b/tests/Unit/Api/Group/CreateTest.php @@ -8,8 +8,7 @@ use Redmine\Api\Group; use Redmine\Exception\MissingParameterException; use Redmine\Http\HttpClient; -use Redmine\Http\Request; -use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; use SimpleXMLElement; /** @@ -19,23 +18,18 @@ class CreateTest extends TestCase { public function testCreateWithNameCreatesGroup() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (Request $request) { - $this->assertSame('POST', $request->getMethod()); - $this->assertSame('/groups.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('Group Name', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'POST', + '/groups.xml', + 'application/xml', + 'Group Name', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Group($client); @@ -52,23 +46,18 @@ public function testCreateWithNameCreatesGroup() public function testCreateWithNameAndUserIdsCreatesGroup() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (Request $request) { - $this->assertSame('POST', $request->getMethod()); - $this->assertSame('/groups.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('Group Name123', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'POST', + '/groups.xml', + 'application/xml', + 'Group Name123', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Group($client); @@ -85,23 +74,18 @@ public function testCreateWithNameAndUserIdsCreatesGroup() public function testCreateWithNameAndCustomFieldsCreatesGroup() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (Request $request) { - $this->assertSame('POST', $request->getMethod()); - $this->assertSame('/groups.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('Group Name5', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'POST', + '/groups.xml', + 'application/xml', + 'Group Name5', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Group($client); diff --git a/tests/Unit/Api/Group/UpdateTest.php b/tests/Unit/Api/Group/UpdateTest.php index 4d4ec21b..e75ac708 100644 --- a/tests/Unit/Api/Group/UpdateTest.php +++ b/tests/Unit/Api/Group/UpdateTest.php @@ -6,10 +6,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Group; -use Redmine\Http\HttpClient; -use Redmine\Http\Request; -use Redmine\Http\Response; -use SimpleXMLElement; +use Redmine\Tests\Fixtures\AssertingHttpClient; /** * @covers \Redmine\Api\Group::update @@ -18,23 +15,18 @@ class UpdateTest extends TestCase { public function testUpdateWithNameUpdatesGroup() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (Request $request) { - $this->assertSame('PUT', $request->getMethod()); - $this->assertSame('/groups/1.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('Group Name', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/groups/1.xml', + 'application/xml', + 'Group Name', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Group($client); @@ -47,23 +39,18 @@ public function testUpdateWithNameUpdatesGroup() public function testUpdateWithUserIdsUpdatesGroup() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (Request $request) { - $this->assertSame('PUT', $request->getMethod()); - $this->assertSame('/groups/1.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('123', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/groups/1.xml', + 'application/xml', + '123', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Group($client); @@ -76,23 +63,18 @@ public function testUpdateWithUserIdsUpdatesGroup() public function testUpdateWithCustomFieldsUpdatesGroup() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(1)) - ->method('request') - ->willReturnCallback(function (Request $request) { - $this->assertSame('PUT', $request->getMethod()); - $this->assertSame('/groups/1.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('5', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'PUT', + '/groups/1.xml', + 'application/xml', + '5', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Group($client); diff --git a/tests/Unit/Api/IssueTest.php b/tests/Unit/Api/IssueTest.php index 4f1cca99..c9607de5 100644 --- a/tests/Unit/Api/IssueTest.php +++ b/tests/Unit/Api/IssueTest.php @@ -5,9 +5,6 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Issue; use Redmine\Client\Client; -use Redmine\Http\HttpClient; -use Redmine\Http\Request; -use Redmine\Http\Response; use Redmine\Tests\Fixtures\AssertingHttpClient; use Redmine\Tests\Fixtures\MockClient; use SimpleXMLElement; @@ -561,40 +558,27 @@ public function testCreateWithHttpClientRetrievesIssueStatusId() */ public function testCreateWithHttpClientRetrievesProjectId() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(2)) - ->method('request') - ->willReturnCallback(function (Request $request) { - if ($request->getMethod() === 'GET') { - $this->assertSame('/projects.json', $request->getPath()); - $this->assertSame('application/json', $request->getContentType()); - $this->assertSame('', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/json', - 'getContent' => '{"projects":[{"name":"Project Name","id":3}]}', - ] - ); - } - - if ($request->getMethod() === 'POST') { - $this->assertSame('/issues.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('3', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - } - - throw new \Exception(); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '/projects.json', + 'application/json', + '', + 200, + 'application/json', + '{"projects":[{"name":"Project Name","id":3}]}' + ], + [ + 'POST', + '/issues.xml', + 'application/xml', + '3', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Issue($client); @@ -617,40 +601,27 @@ public function testCreateWithHttpClientRetrievesProjectId() */ public function testCreateWithHttpClientRetrievesIssueCategoryId() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(2)) - ->method('request') - ->willReturnCallback(function (Request $request) { - if ($request->getMethod() === 'GET') { - $this->assertSame('/projects/3/issue_categories.json', $request->getPath()); - $this->assertSame('application/json', $request->getContentType()); - $this->assertSame('', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/json', - 'getContent' => '{"issue_categories":[{"name":"Category Name","id":45}]}', - ] - ); - } - - if ($request->getMethod() === 'POST') { - $this->assertSame('/issues.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('345', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - } - - throw new \Exception(); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '/projects/3/issue_categories.json', + 'application/json', + '', + 200, + 'application/json', + '{"issue_categories":[{"name":"Category Name","id":45}]}' + ], + [ + 'POST', + '/issues.xml', + 'application/xml', + '345', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Issue($client); @@ -673,40 +644,27 @@ public function testCreateWithHttpClientRetrievesIssueCategoryId() */ public function testCreateWithHttpClientRetrievesTrackerId() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(2)) - ->method('request') - ->willReturnCallback(function (Request $request) { - if ($request->getMethod() === 'GET') { - $this->assertSame('/trackers.json', $request->getPath()); - $this->assertSame('application/json', $request->getContentType()); - $this->assertSame('', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/json', - 'getContent' => '{"trackers":[{"name":"Tracker Name","id":9}]}', - ] - ); - } - - if ($request->getMethod() === 'POST') { - $this->assertSame('/issues.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('9', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - } - - throw new \Exception(); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '/trackers.json', + 'application/json', + '', + 200, + 'application/json', + '{"trackers":[{"name":"Tracker Name","id":9}]}' + ], + [ + 'POST', + '/issues.xml', + 'application/xml', + '9', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Issue($client); @@ -729,40 +687,27 @@ public function testCreateWithHttpClientRetrievesTrackerId() */ public function testCreateWithHttpClientRetrievesUserId() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(2)) - ->method('request') - ->willReturnCallback(function (Request $request) { - if ($request->getMethod() === 'GET') { - $this->assertSame('/users.json', $request->getPath()); - $this->assertSame('application/json', $request->getContentType()); - $this->assertSame('', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/json', - 'getContent' => '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}', - ] - ); - } - - if ($request->getMethod() === 'POST') { - $this->assertSame('/issues.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('65', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - } - - throw new \Exception(); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '/users.json', + 'application/json', + '', + 200, + 'application/json', + '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}' + ], + [ + 'POST', + '/issues.xml', + 'application/xml', + '65', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Issue($client); @@ -993,40 +938,27 @@ public function testSetIssueStatusWithClient() */ public function testSetIssueStatusWithHttpClient() { - $client = $this->createMock(HttpClient::class); - $client->expects($this->exactly(2)) - ->method('request') - ->willReturnCallback(function (Request $request) { - if ($request->getMethod() === 'GET') { - $this->assertSame('/issue_statuses.json', $request->getPath()); - $this->assertSame('application/json', $request->getContentType()); - $this->assertSame('', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/json', - 'getContent' => '{"issue_statuses":[{"name":"Status Name","id":123}]}', - ] - ); - } - - if ($request->getMethod() === 'PUT') { - $this->assertSame('/issues/5.xml', $request->getPath()); - $this->assertSame('application/xml', $request->getContentType()); - $this->assertXmlStringEqualsXmlString('5123', $request->getContent()); - - return $this->createConfiguredMock( - Response::class, - [ - 'getContentType' => 'application/xml', - 'getContent' => '', - ] - ); - } - - throw new \Exception(); - }); + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '/issue_statuses.json', + 'application/json', + '', + 200, + 'application/json', + '{"issue_statuses":[{"name":"Status Name","id":123}]}' + ], + [ + 'PUT', + '/issues/5.xml', + 'application/xml', + '5123', + 200, + 'application/xml', + '' + ] + ); // Create the object under test $api = new Issue($client); From b7c5a13378f533273bc17e654982c815c59558fe Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 23 Jan 2024 14:29:25 +0100 Subject: [PATCH 4/5] mark HttpClient, Request and Response as internal --- src/Redmine/Http/HttpClient.php | 2 ++ src/Redmine/Http/Request.php | 2 ++ src/Redmine/Http/Response.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/Redmine/Http/HttpClient.php b/src/Redmine/Http/HttpClient.php index c9fc980c..365e0a47 100644 --- a/src/Redmine/Http/HttpClient.php +++ b/src/Redmine/Http/HttpClient.php @@ -14,6 +14,8 @@ * * The client is responsible for ensuring that all data is sent in the correct form and * that received data is processed correctly. + * + * @internal */ interface HttpClient { diff --git a/src/Redmine/Http/Request.php b/src/Redmine/Http/Request.php index f7093bf3..c2f9d528 100644 --- a/src/Redmine/Http/Request.php +++ b/src/Redmine/Http/Request.php @@ -9,6 +9,8 @@ * * The method signatures are defined with the intention that an implementing class * can implment this interface and also the PSR-7 `\Psr\Http\Message\RequestInterface` + * + * @internal */ interface Request { diff --git a/src/Redmine/Http/Response.php b/src/Redmine/Http/Response.php index cde231d4..0370fa00 100644 --- a/src/Redmine/Http/Response.php +++ b/src/Redmine/Http/Response.php @@ -9,6 +9,8 @@ * * The method signatures are defined with the intention that an implementing class * can implment this interface and also the PSR-7 `\Psr\Http\Message\ResponseInterface` + * + * @internal */ interface Response { From a9fb02175f9d4ca38edd96b7081291eaebc1ee48 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 23 Jan 2024 14:46:22 +0100 Subject: [PATCH 5/5] Fix compatability with PHP 7.4 --- tests/Fixtures/AssertingHttpClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Fixtures/AssertingHttpClient.php b/tests/Fixtures/AssertingHttpClient.php index 4d6557ce..6ba12431 100644 --- a/tests/Fixtures/AssertingHttpClient.php +++ b/tests/Fixtures/AssertingHttpClient.php @@ -50,7 +50,7 @@ private function assertRequestData( string $content = '', int $responseCode = 200, string $responseContentType = '', - string $responseContent = '', + string $responseContent = '' ) { if ($responseContentType === '') { $responseContentType = $contentType;