From 633fee9458b8a3f83e47f64e5a156decbd561a3c Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 22 Dec 2023 15:25:05 +0100 Subject: [PATCH 01/23] Create UnexpectedResponseException, throw it in CustomField::list() --- src/Redmine/Api/CustomField.php | 11 +++++++- .../Exception/UnexpectedResponseException.php | 19 ++++++++++++++ tests/Unit/Api/CustomField/ListTest.php | 26 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/Redmine/Exception/UnexpectedResponseException.php diff --git a/src/Redmine/Api/CustomField.php b/src/Redmine/Api/CustomField.php index 4282d925..21053d75 100644 --- a/src/Redmine/Api/CustomField.php +++ b/src/Redmine/Api/CustomField.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * Listing custom fields. @@ -29,7 +30,11 @@ class CustomField extends AbstractApi */ final public function list(array $params = []): array { - $this->customFields = $this->retrieveData('/custom_fields.json', $params); + try { + $this->customFields = $this->retrieveData('/custom_fields.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('Redmine server has delivered an unexpected response.', $th->getCode(), $th); + } return $this->customFields; } @@ -52,6 +57,10 @@ public function all(array $params = []) try { return $this->list($params); } catch (Exception $e) { + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + if ($this->client->getLastResponseBody() === '') { return false; } diff --git a/src/Redmine/Exception/UnexpectedResponseException.php b/src/Redmine/Exception/UnexpectedResponseException.php new file mode 100644 index 00000000..1eb50427 --- /dev/null +++ b/src/Redmine/Exception/UnexpectedResponseException.php @@ -0,0 +1,19 @@ +assertSame($returnDataSet, $api->list($allParameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/custom_fields.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new CustomField($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('Redmine server has delivered an unexpected response.'); + + // Perform the tests + $api->list(); + } } From fabd847604a8a1e76df7aa297bfb32c7d7a8bbeb Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 09:18:50 +0100 Subject: [PATCH 02/23] Update exception message --- src/Redmine/Api/CustomField.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/CustomField.php b/src/Redmine/Api/CustomField.php index 21053d75..d813a889 100644 --- a/src/Redmine/Api/CustomField.php +++ b/src/Redmine/Api/CustomField.php @@ -24,7 +24,7 @@ class CustomField extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of custom fields found */ @@ -33,7 +33,7 @@ final public function list(array $params = []): array try { $this->customFields = $this->retrieveData('/custom_fields.json', $params); } catch (SerializerException $th) { - throw new UnexpectedResponseException('Redmine server has delivered an unexpected response.', $th->getCode(), $th); + throw new UnexpectedResponseException('Redmine server has responded with an unexpected body.', $th->getCode(), $th); } return $this->customFields; From cfa352788b0184b74c85a34daf6c6f14e364b690 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 09:22:44 +0100 Subject: [PATCH 03/23] Fix tests --- tests/Unit/Api/CustomField/ListTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Api/CustomField/ListTest.php b/tests/Unit/Api/CustomField/ListTest.php index bbea8c90..81c8ae30 100644 --- a/tests/Unit/Api/CustomField/ListTest.php +++ b/tests/Unit/Api/CustomField/ListTest.php @@ -150,7 +150,7 @@ public function testListThrowsException() $api = new CustomField($client); $this->expectException(UnexpectedResponseException::class); - $this->expectExceptionMessage('Redmine server has delivered an unexpected response.'); + $this->expectExceptionMessage('Redmine server has responded with an unexpected body.'); // Perform the tests $api->list(); From dccdc9c01afa894d11c0c33a8c422d29c085ba5d Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 21:00:15 +0100 Subject: [PATCH 04/23] let Group::all() throw UnexpectedResponseException --- src/Redmine/Api/CustomField.php | 2 +- src/Redmine/Api/Group.php | 13 +++++++++++-- tests/Unit/Api/CustomField/ListTest.php | 2 +- tests/Unit/Api/Group/ListTest.php | 26 +++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/Redmine/Api/CustomField.php b/src/Redmine/Api/CustomField.php index d813a889..32ffa8e5 100644 --- a/src/Redmine/Api/CustomField.php +++ b/src/Redmine/Api/CustomField.php @@ -33,7 +33,7 @@ final public function list(array $params = []): array try { $this->customFields = $this->retrieveData('/custom_fields.json', $params); } catch (SerializerException $th) { - throw new UnexpectedResponseException('Redmine server has responded with an unexpected body.', $th->getCode(), $th); + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); } return $this->customFields; diff --git a/src/Redmine/Api/Group.php b/src/Redmine/Api/Group.php index 6bbfdc73..c80526d2 100644 --- a/src/Redmine/Api/Group.php +++ b/src/Redmine/Api/Group.php @@ -5,6 +5,7 @@ use Redmine\Exception; use Redmine\Exception\MissingParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\PathSerializer; use Redmine\Serializer\XmlSerializer; @@ -26,13 +27,17 @@ class Group extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of groups found */ final public function list(array $params = []): array { - $this->groups = $this->retrieveData('/groups.json', $params); + try { + $this->groups = $this->retrieveData('/groups.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->groups; } @@ -55,6 +60,10 @@ public function all(array $params = []) try { return $this->list($params); } catch (Exception $e) { + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + if ($this->client->getLastResponseBody() === '') { return false; } diff --git a/tests/Unit/Api/CustomField/ListTest.php b/tests/Unit/Api/CustomField/ListTest.php index 81c8ae30..67a0c136 100644 --- a/tests/Unit/Api/CustomField/ListTest.php +++ b/tests/Unit/Api/CustomField/ListTest.php @@ -150,7 +150,7 @@ public function testListThrowsException() $api = new CustomField($client); $this->expectException(UnexpectedResponseException::class); - $this->expectExceptionMessage('Redmine server has responded with an unexpected body.'); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); // Perform the tests $api->list(); diff --git a/tests/Unit/Api/Group/ListTest.php b/tests/Unit/Api/Group/ListTest.php index 5e8cfdaa..203c14dc 100644 --- a/tests/Unit/Api/Group/ListTest.php +++ b/tests/Unit/Api/Group/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Group; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\Group::list @@ -63,4 +64,29 @@ public function testListeWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/groups.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Group($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 5de49d4c65c76f87f8f65486943da13ba42579fb Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 21:09:52 +0100 Subject: [PATCH 05/23] let Issue::list() throw UnexpectedResponseException --- src/Redmine/Api/Issue.php | 13 +++++++++++-- tests/Unit/Api/Issue/ListTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Issue.php b/src/Redmine/Api/Issue.php index a9aae152..45e43184 100644 --- a/src/Redmine/Api/Issue.php +++ b/src/Redmine/Api/Issue.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\JsonSerializer; use Redmine\Serializer\PathSerializer; use Redmine\Serializer\XmlSerializer; @@ -40,13 +41,17 @@ class Issue extends AbstractApi * * @param array $params the additional parameters (cf available $params above) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of issues found */ final public function list(array $params = []): array { - return $this->retrieveData('/issues.json', $params); + try { + return $this->retrieveData('/issues.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } } /** @@ -77,6 +82,10 @@ public function all(array $params = []) try { return $this->list($params); } catch (Exception $e) { + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + if ($this->client->getLastResponseBody() === '') { return false; } diff --git a/tests/Unit/Api/Issue/ListTest.php b/tests/Unit/Api/Issue/ListTest.php index 94c23cbe..8245f04a 100644 --- a/tests/Unit/Api/Issue/ListTest.php +++ b/tests/Unit/Api/Issue/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Issue; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\Issue::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/issues.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Issue($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From f269a5b310b84c58f3d9789fa5e53f1f3159e218 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 21:12:26 +0100 Subject: [PATCH 06/23] Speed up deprecated all() methods a little bit --- src/Redmine/Api/CustomField.php | 8 ++++---- src/Redmine/Api/Group.php | 8 ++++---- src/Redmine/Api/Issue.php | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Redmine/Api/CustomField.php b/src/Redmine/Api/CustomField.php index 32ffa8e5..e02395e9 100644 --- a/src/Redmine/Api/CustomField.php +++ b/src/Redmine/Api/CustomField.php @@ -57,14 +57,14 @@ public function all(array $params = []) try { return $this->list($params); } catch (Exception $e) { - if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { - $e = $e->getPrevious(); - } - if ($this->client->getLastResponseBody() === '') { return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/src/Redmine/Api/Group.php b/src/Redmine/Api/Group.php index c80526d2..0598cfba 100644 --- a/src/Redmine/Api/Group.php +++ b/src/Redmine/Api/Group.php @@ -60,14 +60,14 @@ public function all(array $params = []) try { return $this->list($params); } catch (Exception $e) { - if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { - $e = $e->getPrevious(); - } - if ($this->client->getLastResponseBody() === '') { return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/src/Redmine/Api/Issue.php b/src/Redmine/Api/Issue.php index 45e43184..31f2b7a9 100644 --- a/src/Redmine/Api/Issue.php +++ b/src/Redmine/Api/Issue.php @@ -82,14 +82,14 @@ public function all(array $params = []) try { return $this->list($params); } catch (Exception $e) { - if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { - $e = $e->getPrevious(); - } - if ($this->client->getLastResponseBody() === '') { return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } From d29c098fda01ece12b78e0fe4f89ff284e001df3 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 21:17:19 +0100 Subject: [PATCH 07/23] let IssueCategory::listByProject() throw UnexpectedResponseException --- src/Redmine/Api/IssueCategory.php | 13 ++++++++-- .../Api/IssueCategory/ListByProjectTest.php | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/IssueCategory.php b/src/Redmine/Api/IssueCategory.php index d4599970..cfb44618 100644 --- a/src/Redmine/Api/IssueCategory.php +++ b/src/Redmine/Api/IssueCategory.php @@ -6,6 +6,7 @@ use Redmine\Exception\InvalidParameterException; use Redmine\Exception\MissingParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\PathSerializer; use Redmine\Serializer\XmlSerializer; @@ -29,7 +30,7 @@ class IssueCategory extends AbstractApi * @param array $params optional parameters to be passed to the api (offset, limit, ...) * * @throws InvalidParameterException if $projectIdentifier is not of type int or string - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of issue categories found */ @@ -42,7 +43,11 @@ final public function listByProject($projectIdentifier, array $params = []): arr )); } - $this->issueCategories = $this->retrieveData('/projects/'.strval($projectIdentifier).'/issue_categories.json', $params); + try { + $this->issueCategories = $this->retrieveData('/projects/'.strval($projectIdentifier).'/issue_categories.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->issueCategories; } @@ -70,6 +75,10 @@ public function all($project, array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/IssueCategory/ListByProjectTest.php b/tests/Unit/Api/IssueCategory/ListByProjectTest.php index 563a392b..2f50610d 100644 --- a/tests/Unit/Api/IssueCategory/ListByProjectTest.php +++ b/tests/Unit/Api/IssueCategory/ListByProjectTest.php @@ -6,6 +6,7 @@ use Redmine\Api\IssueCategory; use Redmine\Client\Client; use Redmine\Exception\InvalidParameterException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Tests\Fixtures\MockClient; use stdClass; @@ -93,4 +94,29 @@ public static function getInvalidProjectIdentifiers(): array 'object' => [new stdClass()], ]; } + + public function testListByProjectThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/projects/5/issue_categories.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new IssueCategory($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->listByProject(5); + } } From fa925b74f91f700addce7bf44d6042652d9703e6 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 21:20:34 +0100 Subject: [PATCH 08/23] let IssuePriority::list() throw UnexpectedResponseException --- src/Redmine/Api/IssuePriority.php | 13 ++++++++++-- tests/Unit/Api/IssuePriority/ListTest.php | 26 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/IssuePriority.php b/src/Redmine/Api/IssuePriority.php index eb1eb5e1..ebd04219 100644 --- a/src/Redmine/Api/IssuePriority.php +++ b/src/Redmine/Api/IssuePriority.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * Listing issue priorities. @@ -23,13 +24,17 @@ class IssuePriority extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of issue priorities found */ final public function list(array $params = []): array { - $this->issuePriorities = $this->retrieveData('/enumerations/issue_priorities.json', $params); + try { + $this->issuePriorities = $this->retrieveData('/enumerations/issue_priorities.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->issuePriorities; } @@ -56,6 +61,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/IssuePriority/ListTest.php b/tests/Unit/Api/IssuePriority/ListTest.php index 855f9074..3733d4eb 100644 --- a/tests/Unit/Api/IssuePriority/ListTest.php +++ b/tests/Unit/Api/IssuePriority/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\IssuePriority; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\IssuePriority::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($allParameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/enumerations/issue_priorities.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new IssuePriority($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 01c8d83ab38882926dc8517e5af1eab713e9539c Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 21:34:23 +0100 Subject: [PATCH 09/23] let IssueRelation::listByIssueId() throw UnexpectedResponseException --- src/Redmine/Api/IssueRelation.php | 13 ++++++++-- .../Api/IssueRelation/ListByIssueIdTest.php | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/IssueRelation.php b/src/Redmine/Api/IssueRelation.php index 262ebe2f..d5d4fc72 100644 --- a/src/Redmine/Api/IssueRelation.php +++ b/src/Redmine/Api/IssueRelation.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\JsonSerializer; /** @@ -25,13 +26,17 @@ class IssueRelation extends AbstractApi * @param int $issueId the issue id * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of relations found */ final public function listByIssueId(int $issueId, array $params = []): array { - $this->relations = $this->retrieveData('/issues/'.strval($issueId).'/relations.json', $params); + try { + $this->relations = $this->retrieveData('/issues/'.strval($issueId).'/relations.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->relations; } @@ -59,6 +64,10 @@ public function all($issueId, array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/IssueRelation/ListByIssueIdTest.php b/tests/Unit/Api/IssueRelation/ListByIssueIdTest.php index c05c4866..b03a5739 100644 --- a/tests/Unit/Api/IssueRelation/ListByIssueIdTest.php +++ b/tests/Unit/Api/IssueRelation/ListByIssueIdTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\IssueRelation; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\IssueRelation::listByIssueId @@ -63,4 +64,29 @@ public function testListByIssueIdWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->listByIssueId(5, $parameters)); } + + public function testListByIssueIdThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/issues/5/relations.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new IssueRelation($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->listByIssueId(5); + } } From 6f66eef292af9bbb5d168e77ce01f8ea84bcfb51 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 21:40:16 +0100 Subject: [PATCH 10/23] let IssueStatus::list() throw UnexpectedResponseException --- src/Redmine/Api/IssueStatus.php | 13 +++++++++++-- tests/Unit/Api/IssueStatus/ListTest.php | 26 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/IssueStatus.php b/src/Redmine/Api/IssueStatus.php index 3df6d5e1..8b886758 100644 --- a/src/Redmine/Api/IssueStatus.php +++ b/src/Redmine/Api/IssueStatus.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * Listing issue statuses. @@ -23,13 +24,17 @@ class IssueStatus extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of issue statuses found */ final public function list(array $params = []): array { - $this->issueStatuses = $this->retrieveData('/issue_statuses.json', $params); + try { + $this->issueStatuses = $this->retrieveData('/issue_statuses.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->issueStatuses; } @@ -56,6 +61,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/IssueStatus/ListTest.php b/tests/Unit/Api/IssueStatus/ListTest.php index 801d2b3c..ed23646a 100644 --- a/tests/Unit/Api/IssueStatus/ListTest.php +++ b/tests/Unit/Api/IssueStatus/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\IssueStatus; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\IssueStatus::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/issue_statuses.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new IssueStatus($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 6508e1f910a8ffc4baf421b6123c69d97a770476 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 28 Dec 2023 21:54:15 +0100 Subject: [PATCH 11/23] let Membership::listByProject() throw UnexpectedResponseException --- src/Redmine/Api/Membership.php | 13 ++++++++-- .../Unit/Api/Membership/ListByProjectTest.php | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Membership.php b/src/Redmine/Api/Membership.php index e1570830..0c8ebf70 100644 --- a/src/Redmine/Api/Membership.php +++ b/src/Redmine/Api/Membership.php @@ -6,6 +6,7 @@ use Redmine\Exception\InvalidParameterException; use Redmine\Exception\MissingParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\XmlSerializer; /** @@ -28,7 +29,7 @@ class Membership extends AbstractApi * @param array $params optional parameters to be passed to the api (offset, limit, ...) * * @throws InvalidParameterException if $projectIdentifier is not of type int or string - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of memberships found */ @@ -41,7 +42,11 @@ final public function listByProject($projectIdentifier, array $params = []): arr )); } - $this->memberships = $this->retrieveData('/projects/'.strval($projectIdentifier).'/memberships.json', $params); + try { + $this->memberships = $this->retrieveData('/projects/'.strval($projectIdentifier).'/memberships.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->memberships; } @@ -69,6 +74,10 @@ public function all($project, array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/Membership/ListByProjectTest.php b/tests/Unit/Api/Membership/ListByProjectTest.php index 55b4b49a..975d187e 100644 --- a/tests/Unit/Api/Membership/ListByProjectTest.php +++ b/tests/Unit/Api/Membership/ListByProjectTest.php @@ -6,6 +6,7 @@ use Redmine\Api\Membership; use Redmine\Client\Client; use Redmine\Exception\InvalidParameterException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Tests\Fixtures\MockClient; use stdClass; @@ -91,4 +92,29 @@ public static function getInvalidProjectIdentifiers(): array 'object' => [new stdClass()], ]; } + + public function testListByProjectThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/projects/5/memberships.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Membership($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->listByProject(5); + } } From 9780ffb4a61e507ccb04a92a5e166c16ae39eaab Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 29 Dec 2023 16:51:13 +0100 Subject: [PATCH 12/23] let News::list() and News::listByProject() throw UnexpectedResponseException --- src/Redmine/Api/News.php | 21 ++++++++++++++---- tests/Unit/Api/News/ListByProjectTest.php | 26 +++++++++++++++++++++++ tests/Unit/Api/News/ListTest.php | 26 +++++++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/Redmine/Api/News.php b/src/Redmine/Api/News.php index 12953c0d..0426dc83 100644 --- a/src/Redmine/Api/News.php +++ b/src/Redmine/Api/News.php @@ -5,6 +5,7 @@ use Redmine\Exception; use Redmine\Exception\InvalidParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * @see http://www.redmine.org/projects/redmine/wiki/Rest_News @@ -24,7 +25,7 @@ class News extends AbstractApi * @param array $params optional parameters to be passed to the api (offset, limit, ...) * * @throws InvalidParameterException if $projectIdentifier is not of type int or string - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of news found */ @@ -37,7 +38,11 @@ final public function listByProject($projectIdentifier, array $params = []): arr )); } - $this->news = $this->retrieveData('/projects/'.strval($projectIdentifier).'/news.json', $params); + try { + $this->news = $this->retrieveData('/projects/'.strval($projectIdentifier).'/news.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->news; } @@ -49,13 +54,17 @@ final public function listByProject($projectIdentifier, array $params = []): arr * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of news found */ final public function list(array $params = []): array { - $this->news = $this->retrieveData('/news.json', $params); + try { + $this->news = $this->retrieveData('/news.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->news; } @@ -87,6 +96,10 @@ public function all($project = null, array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/News/ListByProjectTest.php b/tests/Unit/Api/News/ListByProjectTest.php index 1b42ce5c..a2bd817f 100644 --- a/tests/Unit/Api/News/ListByProjectTest.php +++ b/tests/Unit/Api/News/ListByProjectTest.php @@ -6,6 +6,7 @@ use Redmine\Api\News; use Redmine\Client\Client; use Redmine\Exception\InvalidParameterException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Tests\Fixtures\MockClient; use stdClass; @@ -93,4 +94,29 @@ public static function getInvalidProjectIdentifiers(): array 'object' => [new stdClass()], ]; } + + public function testListByProjectThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/projects/5/news.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new News($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->listByProject(5); + } } diff --git a/tests/Unit/Api/News/ListTest.php b/tests/Unit/Api/News/ListTest.php index 80e2ef38..f4db14d8 100644 --- a/tests/Unit/Api/News/ListTest.php +++ b/tests/Unit/Api/News/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\News; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\News::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/news.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new News($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 4b984d3c24e53e3a82338f6d851cc2c1579c86f5 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 29 Dec 2023 17:02:30 +0100 Subject: [PATCH 13/23] let Project::list() throw UnexpectedResponseException --- src/Redmine/Api/Project.php | 13 +++++++++++-- tests/Unit/Api/Project/ListTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Project.php b/src/Redmine/Api/Project.php index 3a5a82c1..b5e962f3 100755 --- a/src/Redmine/Api/Project.php +++ b/src/Redmine/Api/Project.php @@ -5,6 +5,7 @@ use Redmine\Exception; use Redmine\Exception\MissingParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\PathSerializer; use Redmine\Serializer\XmlSerializer; @@ -26,13 +27,17 @@ class Project extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of projects found */ final public function list(array $params = []): array { - $this->projects = $this->retrieveData('/projects.json', $params); + try { + $this->projects = $this->retrieveData('/projects.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->projects; } @@ -59,6 +64,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/Project/ListTest.php b/tests/Unit/Api/Project/ListTest.php index ede326d0..26efd4b3 100644 --- a/tests/Unit/Api/Project/ListTest.php +++ b/tests/Unit/Api/Project/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Project; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\Project::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/projects.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Project($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 13c5a5cb6ed31b0543f09d1ddefc527beb5c93d5 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 29 Dec 2023 17:11:59 +0100 Subject: [PATCH 14/23] let Query::list() throw UnexpectedResponseException --- src/Redmine/Api/Query.php | 13 +++++++++++-- tests/Unit/Api/Query/ListTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Query.php b/src/Redmine/Api/Query.php index 18694a05..9b29b01f 100644 --- a/src/Redmine/Api/Query.php +++ b/src/Redmine/Api/Query.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * Custom queries retrieval. @@ -23,13 +24,17 @@ class Query extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of queries found */ final public function list(array $params = []): array { - $this->query = $this->retrieveData('/queries.json', $params); + try { + $this->query = $this->retrieveData('/queries.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->query; } @@ -56,6 +61,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/Query/ListTest.php b/tests/Unit/Api/Query/ListTest.php index 01e46773..5858fb3e 100644 --- a/tests/Unit/Api/Query/ListTest.php +++ b/tests/Unit/Api/Query/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Query; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\Query::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/queries.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Query($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 71e5a959438b525420c0be19e01ef96711a5a466 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 29 Dec 2023 23:56:19 +0100 Subject: [PATCH 15/23] let Role::list() throw UnexpectedResponseException --- src/Redmine/Api/Role.php | 13 +++++++++++-- tests/Unit/Api/Role/ListTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Role.php b/src/Redmine/Api/Role.php index 30b4e8a4..49488cfd 100644 --- a/src/Redmine/Api/Role.php +++ b/src/Redmine/Api/Role.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * Listing roles. @@ -23,13 +24,17 @@ class Role extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of roles found */ final public function list(array $params = []): array { - $this->roles = $this->retrieveData('/roles.json', $params); + try { + $this->roles = $this->retrieveData('/roles.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->roles; } @@ -56,6 +61,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/Role/ListTest.php b/tests/Unit/Api/Role/ListTest.php index d274a1b2..276af29d 100644 --- a/tests/Unit/Api/Role/ListTest.php +++ b/tests/Unit/Api/Role/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Role; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\Role::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/roles.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Role($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 7598de513909cd599997963100f6e2ef3946fcb1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Dec 2023 00:01:31 +0100 Subject: [PATCH 16/23] let Search::listByQuery() throw UnexpectedResponseException --- src/Redmine/Api/Search.php | 14 ++++++++++-- tests/Unit/Api/Search/ListByQueryTest.php | 26 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Search.php b/src/Redmine/Api/Search.php index c7c31c3d..cd68f23d 100644 --- a/src/Redmine/Api/Search.php +++ b/src/Redmine/Api/Search.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * @see http://www.redmine.org/projects/redmine/wiki/Rest_Search @@ -20,14 +21,19 @@ class Search extends AbstractApi * @param string $query string to search * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of results (projects, issues) */ final public function listByQuery(string $query, array $params = []): array { $params['q'] = $query; - $this->results = $this->retrieveData('/search.json', $params); + + try { + $this->results = $this->retrieveData('/search.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->results; } @@ -55,6 +61,10 @@ public function search($query, array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/Search/ListByQueryTest.php b/tests/Unit/Api/Search/ListByQueryTest.php index e4d4740c..8cc25ff2 100644 --- a/tests/Unit/Api/Search/ListByQueryTest.php +++ b/tests/Unit/Api/Search/ListByQueryTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Search; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Tests\Fixtures\MockClient; /** @@ -64,4 +65,29 @@ public function testListByQueryWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->listByQuery('query', $parameters)); } + + public function testListByQueryThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/search.json?limit=25&offset=0&q=query') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Search($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->listByQuery('query'); + } } From 22d83e7f67e7aea6a44c554f535c3c72a058d54b Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Dec 2023 00:05:23 +0100 Subject: [PATCH 17/23] let TimeEntry::list() throw UnexpectedResponseException --- src/Redmine/Api/TimeEntry.php | 13 +++++++++++-- tests/Unit/Api/TimeEntry/ListTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/TimeEntry.php b/src/Redmine/Api/TimeEntry.php index e1586271..5441c918 100644 --- a/src/Redmine/Api/TimeEntry.php +++ b/src/Redmine/Api/TimeEntry.php @@ -5,6 +5,7 @@ use Redmine\Exception; use Redmine\Exception\MissingParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\XmlSerializer; /** @@ -25,13 +26,17 @@ class TimeEntry extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of time entries found */ final public function list(array $params = []): array { - $this->timeEntries = $this->retrieveData('/time_entries.json', $params); + try { + $this->timeEntries = $this->retrieveData('/time_entries.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->timeEntries; } @@ -58,6 +63,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/TimeEntry/ListTest.php b/tests/Unit/Api/TimeEntry/ListTest.php index 126dcca4..b5b24b06 100644 --- a/tests/Unit/Api/TimeEntry/ListTest.php +++ b/tests/Unit/Api/TimeEntry/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\TimeEntry; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\TimeEntry::list @@ -67,4 +68,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/time_entries.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new TimeEntry($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From f19e9ee2f93c72b70fcba3bd8cf510fc0d3d065e Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Dec 2023 00:09:18 +0100 Subject: [PATCH 18/23] let TimeEntryActivity::list() throw UnexpectedResponseException --- src/Redmine/Api/TimeEntryActivity.php | 13 ++++++++-- tests/Unit/Api/TimeEntryActivity/ListTest.php | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/TimeEntryActivity.php b/src/Redmine/Api/TimeEntryActivity.php index 427a41ae..157671fb 100644 --- a/src/Redmine/Api/TimeEntryActivity.php +++ b/src/Redmine/Api/TimeEntryActivity.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * Listing time entry activities. @@ -21,13 +22,17 @@ class TimeEntryActivity extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of time entry activities found */ final public function list(array $params = []): array { - $this->timeEntryActivities = $this->retrieveData('/enumerations/time_entry_activities.json', $params); + try { + $this->timeEntryActivities = $this->retrieveData('/enumerations/time_entry_activities.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->timeEntryActivities; } @@ -52,6 +57,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/TimeEntryActivity/ListTest.php b/tests/Unit/Api/TimeEntryActivity/ListTest.php index d296ca0c..b5f1deb0 100644 --- a/tests/Unit/Api/TimeEntryActivity/ListTest.php +++ b/tests/Unit/Api/TimeEntryActivity/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\TimeEntryActivity; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @coversDefaultClass \Redmine\Api\TimeEntryActivity::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/enumerations/time_entry_activities.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new TimeEntryActivity($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 3791ccc2d71571ffb4e0ce1b74d732c7c6a5b07a Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Dec 2023 21:21:39 +0100 Subject: [PATCH 19/23] let Tracker::list() throw UnexpectedResponseException --- src/Redmine/Api/Tracker.php | 13 +++++++++++-- tests/Unit/Api/Tracker/ListTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Tracker.php b/src/Redmine/Api/Tracker.php index 4358ec0a..2e924ce1 100644 --- a/src/Redmine/Api/Tracker.php +++ b/src/Redmine/Api/Tracker.php @@ -4,6 +4,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; /** * Listing trackers. @@ -23,13 +24,17 @@ class Tracker extends AbstractApi * * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of trackers found */ final public function list(array $params = []): array { - $this->trackers = $this->retrieveData('/trackers.json', $params); + try { + $this->trackers = $this->retrieveData('/trackers.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->trackers; } @@ -56,6 +61,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/Tracker/ListTest.php b/tests/Unit/Api/Tracker/ListTest.php index 66ed63ed..b6a7b465 100644 --- a/tests/Unit/Api/Tracker/ListTest.php +++ b/tests/Unit/Api/Tracker/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\Tracker; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\Tracker::list @@ -63,4 +64,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/trackers.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Tracker($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 404af8c30f846874a1cba6d3f75707f6af68357c Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Dec 2023 21:22:09 +0100 Subject: [PATCH 20/23] let User::list() throw UnexpectedResponseException --- src/Redmine/Api/User.php | 13 +++++++++++-- tests/Unit/Api/User/ListTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/User.php b/src/Redmine/Api/User.php index f4008aad..6261386b 100644 --- a/src/Redmine/Api/User.php +++ b/src/Redmine/Api/User.php @@ -5,6 +5,7 @@ use Redmine\Exception; use Redmine\Exception\MissingParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\PathSerializer; use Redmine\Serializer\XmlSerializer; @@ -26,13 +27,17 @@ class User extends AbstractApi * * @param array $params to allow offset/limit (and more) to be passed * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of users found */ final public function list(array $params = []): array { - $this->users = $this->retrieveData('/users.json', $params); + try { + $this->users = $this->retrieveData('/users.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->users; } @@ -59,6 +64,10 @@ public function all(array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/User/ListTest.php b/tests/Unit/Api/User/ListTest.php index 82c554a2..7f1b016d 100644 --- a/tests/Unit/Api/User/ListTest.php +++ b/tests/Unit/Api/User/ListTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Redmine\Api\User; use Redmine\Client\Client; +use Redmine\Exception\UnexpectedResponseException; /** * @covers \Redmine\Api\User::list @@ -66,4 +67,29 @@ public function testListWithParametersReturnsResponse() // Perform the tests $this->assertSame($expectedReturn, $api->list($parameters)); } + + public function testListThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/users.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new User($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->list(); + } } From 6332525ea858a2ed9159a253fa68b7730c0aa00d Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Dec 2023 21:22:41 +0100 Subject: [PATCH 21/23] let Version::listByProject() throw UnexpectedResponseException --- src/Redmine/Api/Version.php | 13 ++++++++-- tests/Unit/Api/Version/ListByProjectTest.php | 26 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Version.php b/src/Redmine/Api/Version.php index 31863065..9d045d20 100644 --- a/src/Redmine/Api/Version.php +++ b/src/Redmine/Api/Version.php @@ -6,6 +6,7 @@ use Redmine\Exception\InvalidParameterException; use Redmine\Exception\MissingParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\XmlSerializer; /** @@ -27,7 +28,7 @@ class Version extends AbstractApi * @param string|int $projectIdentifier project id or literal identifier * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of versions found */ @@ -40,7 +41,11 @@ final public function listByProject($projectIdentifier, array $params = []): arr )); } - $this->versions = $this->retrieveData('/projects/'.strval($projectIdentifier).'/versions.json', $params); + try { + $this->versions = $this->retrieveData('/projects/'.strval($projectIdentifier).'/versions.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->versions; } @@ -68,6 +73,10 @@ public function all($project, array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/Version/ListByProjectTest.php b/tests/Unit/Api/Version/ListByProjectTest.php index 55d5e063..349347a4 100644 --- a/tests/Unit/Api/Version/ListByProjectTest.php +++ b/tests/Unit/Api/Version/ListByProjectTest.php @@ -6,6 +6,7 @@ use Redmine\Api\Version; use Redmine\Client\Client; use Redmine\Exception\InvalidParameterException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Tests\Fixtures\MockClient; use stdClass; @@ -94,4 +95,29 @@ public static function getInvalidProjectIdentifiers(): array 'object' => [new stdClass()], ]; } + + public function testListByProjectThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/projects/5/versions.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Version($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->listByProject(5); + } } From 06c68971594ddfe9b7033b8fcf364baa30e785a5 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Dec 2023 21:22:55 +0100 Subject: [PATCH 22/23] let Wiki::listByProject() throw UnexpectedResponseException --- src/Redmine/Api/Wiki.php | 13 ++++++++++-- tests/Unit/Api/Wiki/ListByProjectTest.php | 26 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Redmine/Api/Wiki.php b/src/Redmine/Api/Wiki.php index fba8abab..8f6255bb 100644 --- a/src/Redmine/Api/Wiki.php +++ b/src/Redmine/Api/Wiki.php @@ -5,6 +5,7 @@ use Redmine\Exception; use Redmine\Exception\InvalidParameterException; use Redmine\Exception\SerializerException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Serializer\PathSerializer; use Redmine\Serializer\XmlSerializer; @@ -27,7 +28,7 @@ class Wiki extends AbstractApi * @param int|string $projectIdentifier project id or slug * @param array $params optional parameters to be passed to the api (offset, limit, ...) * - * @throws SerializerException if response body could not be converted into array + * @throws UnexpectedResponseException if response body could not be converted into array * * @return array list of wiki pages found for the given project */ @@ -40,7 +41,11 @@ final public function listByProject($projectIdentifier, array $params = []): arr )); } - $this->wikiPages = $this->retrieveData('/projects/'.strval($projectIdentifier).'/wiki/index.json', $params); + try { + $this->wikiPages = $this->retrieveData('/projects/'.strval($projectIdentifier).'/wiki/index.json', $params); + } catch (SerializerException $th) { + throw new UnexpectedResponseException('The Redmine server responded with an unexpected body.', $th->getCode(), $th); + } return $this->wikiPages; } @@ -68,6 +73,10 @@ public function all($project, array $params = []) return false; } + if ($e instanceof UnexpectedResponseException && $e->getPrevious() !== null) { + $e = $e->getPrevious(); + } + return $e->getMessage(); } } diff --git a/tests/Unit/Api/Wiki/ListByProjectTest.php b/tests/Unit/Api/Wiki/ListByProjectTest.php index b08d6c2e..fc99da2d 100644 --- a/tests/Unit/Api/Wiki/ListByProjectTest.php +++ b/tests/Unit/Api/Wiki/ListByProjectTest.php @@ -6,6 +6,7 @@ use Redmine\Api\Wiki; use Redmine\Client\Client; use Redmine\Exception\InvalidParameterException; +use Redmine\Exception\UnexpectedResponseException; use Redmine\Tests\Fixtures\MockClient; use stdClass; @@ -94,4 +95,29 @@ public static function getInvalidProjectIdentifiers(): array 'object' => [new stdClass()], ]; } + + public function testListByProjectThrowsException() + { + // Create the used mock objects + $client = $this->createMock(Client::class); + $client->expects($this->exactly(1)) + ->method('requestGet') + ->with('/projects/5/wiki/index.json') + ->willReturn(true); + $client->expects($this->exactly(1)) + ->method('getLastResponseBody') + ->willReturn(''); + $client->expects($this->exactly(1)) + ->method('getLastResponseContentType') + ->willReturn('application/json'); + + // Create the object under test + $api = new Wiki($client); + + $this->expectException(UnexpectedResponseException::class); + $this->expectExceptionMessage('The Redmine server responded with an unexpected body.'); + + // Perform the tests + $api->listByProject(5); + } } From ec0296edfe43f19621541b36b013d5f24219229b Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Dec 2023 21:36:56 +0100 Subject: [PATCH 23/23] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5d1e1e5..82fe98c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New method `Redmine\Api\User::list()` to list users. - New method `Redmine\Api\Version::listByProject()` to list versions from a project. - New method `Redmine\Api\Wiki::listByProject()` to list wiki pages from a project. +- New exception `Redmine\Exception\UnexpectedResponseException` if the Redmine server responded with an unexpected body. ### Deprecated