Skip to content

Commit

Permalink
Merge pull request #409 from Art4/add-issuestatus-listnames
Browse files Browse the repository at this point in the history
Add `IssueStatus::listNames()` method as replacement for `IssueStatus::listing()`
  • Loading branch information
Art4 authored Jul 3, 2024
2 parents 35bb710 + a426080 commit 066212f
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ 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

- `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

Expand Down
31 changes: 31 additions & 0 deletions src/Redmine/Api/IssueStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class IssueStatus extends AbstractApi
{
private $issueStatuses = [];

private $issueStatusNames = null;

/**
* List issue statuses.
*
Expand All @@ -37,6 +39,30 @@ final public function list(array $params = []): array
}
}

/**
* Returns an array of all issue statuses with id/name pairs.
*
* @return array<int,string> 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.
*
Expand Down Expand Up @@ -73,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();
}
Expand Down
30 changes: 30 additions & 0 deletions tests/Behat/Bootstrap/IssueStatusContextTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Redmine\Tests\Behat\Bootstrap;

use Redmine\Api\IssueStatus;

trait IssueStatusContextTrait
{
/**
Expand All @@ -22,4 +24,32 @@ 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(),
);
}

/**
* @When I list all issue status names
*/
public function iListAllIssueStatusNames()
{
/** @var IssueStatus */
$api = $this->getNativeCurlClient()->getApi('issue_status');

$this->registerClientResponse(
$api->listNames(),
$api->getLastResponse(),
);
}
}
69 changes: 69 additions & 0 deletions tests/Behat/features/issue_status.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
@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 |

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 |
108 changes: 108 additions & 0 deletions tests/Unit/Api/IssueStatus/ListNamesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

declare(strict_types=1);

namespace Redmine\Tests\Unit\Api\IssueStatus;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Redmine\Api\IssueStatus;
use Redmine\Tests\Fixtures\AssertingHttpClient;

#[CoversClass(IssueStatus::class)]
class ListNamesTest extends TestCase
{
/**
* @dataProvider getListNamesData
*/
#[DataProvider('getListNamesData')]
public function testListNamesReturnsCorrectResponse($expectedPath, $responseCode, $response, $expectedResponse)
{
$client = AssertingHttpClient::create(
$this,
[
'GET',
$expectedPath,
'application/json',
'',
$responseCode,
'application/json',
$response,
],
);

// Create the object under test
$api = new IssueStatus($client);

// Perform the tests
$this->assertSame($expectedResponse, $api->listNames());
}

public static function getListNamesData(): array
{
return [
'test without issue statuses' => [
'/issue_statuses.json',
201,
<<<JSON
{
"issue_statuses": []
}
JSON,
[],
],
'test with multiple issue statuses' => [
'/issue_statuses.json',
201,
<<<JSON
{
"issue_statuses": [
{"id": 7, "name": "IssueStatus C"},
{"id": 8, "name": "IssueStatus B"},
{"id": 9, "name": "IssueStatus A"}
]
}
JSON,
[
7 => "IssueStatus C",
8 => "IssueStatus B",
9 => "IssueStatus A",
],
],
];
}

public function testListNamesCallsHttpClientOnlyOnce()
{
$client = AssertingHttpClient::create(
$this,
[
'GET',
'/issue_statuses.json',
'application/json',
'',
200,
'application/json',
<<<JSON
{
"issue_statuses": [
{
"id": 1,
"name": "IssueStatus 1"
}
]
}
JSON,
],
);

// Create the object under test
$api = new IssueStatus($client);

// Perform the tests
$this->assertSame([1 => 'IssueStatus 1'], $api->listNames());
$this->assertSame([1 => 'IssueStatus 1'], $api->listNames());
$this->assertSame([1 => 'IssueStatus 1'], $api->listNames());
}
}
32 changes: 32 additions & 0 deletions tests/Unit/Api/IssueStatusTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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().
*/
Expand Down

0 comments on commit 066212f

Please sign in to comment.