From 9d58cf743498b6f8604196872dcdfca125ad5df9 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 28 Jun 2024 16:11:20 +0200 Subject: [PATCH 1/3] Add behat test for IssueStatus::list() --- .../Bootstrap/IssueStatusContextTrait.php | 16 ++++++ tests/Behat/features/issue_status.feature | 55 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 tests/Behat/features/issue_status.feature diff --git a/tests/Behat/Bootstrap/IssueStatusContextTrait.php b/tests/Behat/Bootstrap/IssueStatusContextTrait.php index f8c8d16f..bcf2f056 100644 --- a/tests/Behat/Bootstrap/IssueStatusContextTrait.php +++ b/tests/Behat/Bootstrap/IssueStatusContextTrait.php @@ -4,6 +4,8 @@ namespace Redmine\Tests\Behat\Bootstrap; +use Redmine\Api\IssueStatus; + trait IssueStatusContextTrait { /** @@ -22,4 +24,18 @@ public function iHaveAnIssueStatusWithTheName($issueStatusName) ], ); } + + /** + * @When I list all issue statuses + */ + public function iListAllIssueStatuses() + { + /** @var IssueStatus */ + $api = $this->getNativeCurlClient()->getApi('issue_status'); + + $this->registerClientResponse( + $api->list(), + $api->getLastResponse(), + ); + } } diff --git a/tests/Behat/features/issue_status.feature b/tests/Behat/features/issue_status.feature new file mode 100644 index 00000000..ffeaaf94 --- /dev/null +++ b/tests/Behat/features/issue_status.feature @@ -0,0 +1,55 @@ +@issue_status +Feature: Interacting with the REST API for issue statuses + In order to interact with REST API for issue statuses + As a user + I want to make sure the Redmine server replies with the correct response + + Scenario: Listing of zero issue statuses + Given I have a "NativeCurlClient" client + When I list all issue statuses + Then the response has the status code "200" + And the response has the content type "application/json" + And the returned data has only the following properties + """ + issue_statuses + """ + And the returned data "issue_statuses" property is an array + And the returned data "issue_statuses" property contains "0" items + + Scenario: Listing of multiple issue statuses + Given I have a "NativeCurlClient" client + And I have an issue status with the name "New" + And I have an issue status with the name "Done" + When I list all issue statuses + Then the response has the status code "200" + And the response has the content type "application/json" + And the returned data has only the following properties + """ + issue_statuses + """ + And the returned data "issue_statuses" property is an array + And the returned data "issue_statuses" property contains "2" items + # field 'description' was added in Redmine 5.1.0, see https://www.redmine.org/issues/2568 + And the returned data "issue_statuses.0" property contains the following data with Redmine version ">= 5.1.0" + | property | value | + | id | 1 | + | name | New | + | is_closed | false | + | description | null | + But the returned data "issue_statuses.0" property contains the following data with Redmine version "< 5.1.0" + | property | value | + | id | 1 | + | name | New | + | is_closed | false | + # field 'description' was added in Redmine 5.1.0, see https://www.redmine.org/issues/2568 + And the returned data "issue_statuses.1" property contains the following data with Redmine version ">= 5.1.0" + | property | value | + | id | 2 | + | name | Done | + | is_closed | false | + | description | null | + But the returned data "issue_statuses.1" property contains the following data with Redmine version "< 5.1.0" + | property | value | + | id | 2 | + | name | Done | + | is_closed | false | From e30fcf96e5d1ff54c84021441a12a1bcc8edcde3 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 1 Jul 2024 13:11:40 +0200 Subject: [PATCH 2/3] Create IssueStatus::listNames() --- CHANGELOG.md | 1 + src/Redmine/Api/IssueStatus.php | 26 +++++ .../Bootstrap/IssueStatusContextTrait.php | 14 +++ tests/Behat/features/issue_status.feature | 14 +++ tests/Unit/Api/IssueStatus/ListNamesTest.php | 108 ++++++++++++++++++ 5 files changed, 163 insertions(+) create mode 100644 tests/Unit/Api/IssueStatus/ListNamesTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 14d56264..909e3315 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New method `Redmine\Api\CustomField::listNames()` for listing the ids and names of all custom fields. - New method `Redmine\Api\Group::listNames()` for listing the ids and names of all groups. - New method `Redmine\Api\IssueCategory::listNamesByProject()` for listing the ids and names of all issue categories of a project. +- New method `Redmine\Api\IssueStatus::listNames()` for listing the ids and names of all issue statuses. ### Deprecated diff --git a/src/Redmine/Api/IssueStatus.php b/src/Redmine/Api/IssueStatus.php index a7c076a1..e47c7224 100644 --- a/src/Redmine/Api/IssueStatus.php +++ b/src/Redmine/Api/IssueStatus.php @@ -17,6 +17,8 @@ class IssueStatus extends AbstractApi { private $issueStatuses = []; + private $issueStatusNames = null; + /** * List issue statuses. * @@ -37,6 +39,30 @@ final public function list(array $params = []): array } } + /** + * Returns an array of all issue statuses with id/name pairs. + * + * @return array list of issue statuses (id => name) + */ + final public function listNames(): array + { + if ($this->issueStatusNames !== null) { + return $this->issueStatusNames; + } + + $this->issueStatusNames = []; + + $list = $this->list(); + + if (array_key_exists('issue_statuses', $list)) { + foreach ($list['issue_statuses'] as $issueStatus) { + $this->issueStatusNames[(int) $issueStatus['id']] = (string) $issueStatus['name']; + } + } + + return $this->issueStatusNames; + } + /** * List issue statuses. * diff --git a/tests/Behat/Bootstrap/IssueStatusContextTrait.php b/tests/Behat/Bootstrap/IssueStatusContextTrait.php index bcf2f056..d0a5f401 100644 --- a/tests/Behat/Bootstrap/IssueStatusContextTrait.php +++ b/tests/Behat/Bootstrap/IssueStatusContextTrait.php @@ -38,4 +38,18 @@ public function iListAllIssueStatuses() $api->getLastResponse(), ); } + + /** + * @When I list all issue status names + */ + public function iListAllIssueStatusNames() + { + /** @var IssueStatus */ + $api = $this->getNativeCurlClient()->getApi('issue_status'); + + $this->registerClientResponse( + $api->listNames(), + $api->getLastResponse(), + ); + } } diff --git a/tests/Behat/features/issue_status.feature b/tests/Behat/features/issue_status.feature index ffeaaf94..540cd4ff 100644 --- a/tests/Behat/features/issue_status.feature +++ b/tests/Behat/features/issue_status.feature @@ -53,3 +53,17 @@ Feature: Interacting with the REST API for issue statuses | id | 2 | | name | Done | | is_closed | false | + + Scenario: Listing of multiple issue status names + Given I have a "NativeCurlClient" client + And I have an issue status with the name "New" + And I have an issue status with the name "Done" + When I list all issue status names + Then the response has the status code "200" + And the response has the content type "application/json" + And the returned data is an array + And the returned data contains "2" items + And the returned data contains the following data + | property | value | + | 1 | New | + | 2 | Done | diff --git a/tests/Unit/Api/IssueStatus/ListNamesTest.php b/tests/Unit/Api/IssueStatus/ListNamesTest.php new file mode 100644 index 00000000..231e4fc5 --- /dev/null +++ b/tests/Unit/Api/IssueStatus/ListNamesTest.php @@ -0,0 +1,108 @@ +assertSame($expectedResponse, $api->listNames()); + } + + public static function getListNamesData(): array + { + return [ + 'test without issue statuses' => [ + '/issue_statuses.json', + 201, + << [ + '/issue_statuses.json', + 201, + << "IssueStatus C", + 8 => "IssueStatus B", + 9 => "IssueStatus A", + ], + ], + ]; + } + + public function testListNamesCallsHttpClientOnlyOnce() + { + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '/issue_statuses.json', + 'application/json', + '', + 200, + 'application/json', + <<assertSame([1 => 'IssueStatus 1'], $api->listNames()); + $this->assertSame([1 => 'IssueStatus 1'], $api->listNames()); + $this->assertSame([1 => 'IssueStatus 1'], $api->listNames()); + } +} From a426080f63e207fc08d9e4872157b23957548356 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 1 Jul 2024 13:30:21 +0200 Subject: [PATCH 3/3] Deprecate IssueStatus::listing() --- CHANGELOG.md | 1 + src/Redmine/Api/IssueStatus.php | 5 +++++ tests/Unit/Api/IssueStatusTest.php | 32 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 909e3315..eb26d5f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Redmine\Api\CustomField::listing()` is deprecated, use `\Redmine\Api\CustomField::listNames()` instead. - `Redmine\Api\Group::listing()` is deprecated, use `\Redmine\Api\Group::listNames()` instead. - `Redmine\Api\IssueCategory::listing()` is deprecated, use `\Redmine\Api\IssueCategory::listNamesByProject()` instead. +- `Redmine\Api\IssueStatus::listing()` is deprecated, use `\Redmine\Api\IssueStatus::listNamesByProject()` instead. ## [v2.6.0](https://github.com/kbsali/php-redmine-api/compare/v2.5.0...v2.6.0) - 2024-03-25 diff --git a/src/Redmine/Api/IssueStatus.php b/src/Redmine/Api/IssueStatus.php index e47c7224..022b1e43 100644 --- a/src/Redmine/Api/IssueStatus.php +++ b/src/Redmine/Api/IssueStatus.php @@ -99,12 +99,17 @@ public function all(array $params = []) /** * Returns an array of issue statuses with name/id pairs. * + * @deprecated v2.7.0 Use listNames() instead. + * @see IssueStatus::listNames() + * * @param bool $forceUpdate to force the update of the statuses var * * @return array list of issue statuses (id => name) */ public function listing($forceUpdate = false) { + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); + if (empty($this->issueStatuses) || $forceUpdate) { $this->issueStatuses = $this->list(); } diff --git a/tests/Unit/Api/IssueStatusTest.php b/tests/Unit/Api/IssueStatusTest.php index 18eeb651..e292ee0b 100644 --- a/tests/Unit/Api/IssueStatusTest.php +++ b/tests/Unit/Api/IssueStatusTest.php @@ -215,6 +215,38 @@ public function testListingCallsGetEveryTimeWithForceUpdate() $this->assertSame($expectedReturn, $api->listing(true)); } + /** + * Test listing(). + */ + public function testListingTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"issue_statuses":[{"id":1,"name":"IssueStatus 1"},{"id":5,"name":"IssueStatus 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new IssueStatus($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\IssueStatus::listing()` is deprecated since v2.7.0, use `Redmine\Api\IssueStatus::listNames()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->listing(); + } + /** * Test getIdByName(). */