Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IssueCategory::listNamesByProject() method as replacement for IssueCategory::listing() #406

Merged
merged 10 commits into from
Jun 28, 2024
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

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

### Deprecated

- `Redmine\Api\Group::listing()` is deprecated, use `\Redmine\Api\Group::listNames()` instead.
- `Redmine\Api\IssueCategory::listing()` is deprecated, use `\Redmine\Api\IssueCategory::listNamesByProject()` instead.

## [v2.6.0](https://github.com/kbsali/php-redmine-api/compare/v2.5.0...v2.6.0) - 2024-03-25

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

private $issueCategoriesNames = [];

/**
* List issue categories for a given project.
*
Expand Down Expand Up @@ -53,6 +55,41 @@ final public function listByProject($projectIdentifier, array $params = []): arr
}
}

/**
* Returns an array of all issue categories by a project with id/name pairs.
*
* @param string|int $projectIdentifier project id or literal identifier
*
* @throws InvalidParameterException if $projectIdentifier is not of type int or string
*
* @return array<int,string> list of issue category names (id => name)
*/
final public function listNamesByProject($projectIdentifier): array
{
if (! is_int($projectIdentifier) && ! is_string($projectIdentifier)) {
throw new InvalidParameterException(sprintf(
'%s(): Argument #1 ($projectIdentifier) must be of type int or string',
__METHOD__,
));
}

if (array_key_exists($projectIdentifier, $this->issueCategoriesNames)) {
return $this->issueCategoriesNames[$projectIdentifier];
}

$this->issueCategoriesNames[$projectIdentifier] = [];

$list = $this->listByProject($projectIdentifier);

if (array_key_exists('issue_categories', $list)) {
foreach ($list['issue_categories'] as $category) {
$this->issueCategoriesNames[$projectIdentifier][(int) $category['id']] = $category['name'];
}
}

return $this->issueCategoriesNames[$projectIdentifier];
}

/**
* List issue categories.
*
Expand Down Expand Up @@ -88,13 +125,18 @@ public function all($project, array $params = [])
/**
* Returns an array of categories with name/id pairs.
*
* @deprecated v2.7.0 Use listNamesByProject() instead.
* @see IssueCategory::listNamesByProject()
*
* @param string|int $project project id or literal identifier
* @param bool $forceUpdate to force the update of the projects var
*
* @return array list of projects (id => project name)
*/
public function listing($project, $forceUpdate = false)
{
@trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNamesByProject()` instead.', E_USER_DEPRECATED);

if (true === $forceUpdate || empty($this->issueCategories)) {
$this->issueCategories = $this->listByProject($project);
}
Expand Down
28 changes: 28 additions & 0 deletions tests/Behat/Bootstrap/IssueCategoryContextTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,34 @@ public function iCreateAnIssueCategoryForProjectIdentifierAndWithTheFollowingDat
);
}

/**
* @When I list all issue categories for project identifier :identifier
*/
public function iListAllIssueCategoriesForProjectIdentifier($identifier)
{
/** @var IssueCategory */
$api = $this->getNativeCurlClient()->getApi('issue_category');

$this->registerClientResponse(
$api->listByProject($identifier),
$api->getLastResponse(),
);
}

/**
* @When I list all issue category names for project identifier :identifier
*/
public function iListAllIssueCategoryNamesForProjectIdentifier($identifier)
{
/** @var IssueCategory */
$api = $this->getNativeCurlClient()->getApi('issue_category');

$this->registerClientResponse(
$api->listNamesByProject($identifier),
$api->getLastResponse(),
);
}

/**
* @When I update the issue category with id :id and the following data
*/
Expand Down
20 changes: 10 additions & 10 deletions tests/Behat/features/groups.feature
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,23 @@ Feature: Interacting with the REST API for groups

Scenario: Listing names of all groups
Given I have a "NativeCurlClient" client
And I create a group with name "Test Group 1"
And I create a group with name "Test Group 2"
And I create a group with name "Test Group 3"
And I create a group with name "Test Group 4"
And I create a group with name "Test Group 5"
And I create a group with name "Test Group D"
And I create a group with name "Test Group E"
And I create a group with name "Test Group C"
And I create a group with name "Test Group B"
And I create a group with name "Test Group A"
When I list the names of all groups
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 "5" items
And the returned data contains the following data
| property | value |
| 4 | Test Group 1 |
| 5 | Test Group 2 |
| 6 | Test Group 3 |
| 7 | Test Group 4 |
| 8 | Test Group 5 |
| 4 | Test Group D |
| 5 | Test Group E |
| 6 | Test Group C |
| 7 | Test Group B |
| 8 | Test Group A |

Scenario: Showing a specific group
Given I have a "NativeCurlClient" client
Expand Down
86 changes: 86 additions & 0 deletions tests/Behat/features/issue_category.feature
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,92 @@ Feature: Interacting with the REST API for issue categories
| id | 1 |
| name | Redmine Admin |

Scenario: Listing of zero issue categories
Given I have a "NativeCurlClient" client
And I create a project with name "Test Project" and identifier "test-project"
When I list all issue categories for project identifier "test-project"
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_categories
total_count
"""
And the returned data contains the following data
| property | value |
| issue_categories | [] |
| total_count | 0 |

Scenario: Listing of multiple issue categories
Given I have a "NativeCurlClient" client
And I create a project with name "Test Project" and identifier "test-project"
And I create an issue category for project identifier "test-project" and with the following data
| property | value |
| name | Category name B |
And I create an issue category for project identifier "test-project" and with the following data
| property | value |
| name | Category name A |
When I list all issue categories for project identifier "test-project"
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_categories
total_count
"""
And the returned data contains the following data
| property | value |
| total_count | 2 |
And the returned data "issue_categories" property is an array
And the returned data "issue_categories" property contains "2" items
And the returned data "issue_categories.0" property is an array
And the returned data "issue_categories.0" property has only the following properties
"""
id
project
name
"""
And the returned data "issue_categories.0" property contains the following data
| property | value |
| id | 2 |
| name | Category name A |
And the returned data "issue_categories.0.project" property contains the following data
| property | value |
| id | 1 |
| name | Test Project |
And the returned data "issue_categories.1" property is an array
And the returned data "issue_categories.1" property has only the following properties
"""
id
project
name
"""
And the returned data "issue_categories.1" property contains the following data
| property | value |
| id | 1 |
| name | Category name B |
And the returned data "issue_categories.1.project" property contains the following data
| property | value |
| id | 1 |
| name | Test Project |

Scenario: Listing of multiple issue category names
Given I have a "NativeCurlClient" client
And I create a project with name "Test Project" and identifier "test-project"
And I create an issue category for project identifier "test-project" and with the following data
| property | value |
| name | Category name B |
And I create an issue category for project identifier "test-project" and with the following data
| property | value |
| name | Category name A |
When I list all issue category names for project identifier "test-project"
Then the response has the status code "200"
And the response has the content type "application/json"
And the returned data contains the following data
| property | value |
| 1 | Category name B |
| 2 | Category name A |

Scenario: Updating an issue category with all data
Given I have a "NativeCurlClient" client
And I create a project with name "Test Project" and identifier "test-project"
Expand Down
22 changes: 22 additions & 0 deletions tests/Fixtures/TestDataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Redmine\Tests\Fixtures;

use stdClass;

final class TestDataProvider
{
public static function getInvalidProjectIdentifiers(): array
{
return [
'null' => [null],
'true' => [true],
'false' => [false],
'float' => [0.0],
'array' => [[]],
'object' => [new stdClass()],
];
}
}
8 changes: 4 additions & 4 deletions tests/Unit/Api/Group/ListNamesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ public static function getListNamesData(): array
<<<JSON
{
"groups": [
{"id": 9, "name": "Group 1"},
{"id": 7, "name": "Group 3"},
{"id": 8, "name": "Group 2"},
{"id": 7, "name": "Group 3"}
{"id": 9, "name": "Group 1"}
]
}
JSON,
[
9 => "Group 1",
8 => "Group 2",
7 => "Group 3",
8 => "Group 2",
9 => "Group 1",
],
],
];
Expand Down
20 changes: 4 additions & 16 deletions tests/Unit/Api/IssueCategory/ListByProjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
namespace Redmine\Tests\Unit\Api\IssueCategory;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\TestCase;
use Redmine\Api\IssueCategory;
use Redmine\Client\Client;
use Redmine\Exception\InvalidParameterException;
use Redmine\Exception\UnexpectedResponseException;
use Redmine\Tests\Fixtures\MockClient;
use stdClass;
use Redmine\Tests\Fixtures\TestDataProvider;

#[CoversClass(IssueCategory::class)]
class ListByProjectTest extends TestCase
Expand Down Expand Up @@ -71,9 +71,9 @@ public function testListByProjectWithParametersReturnsResponse()
}

/**
* @dataProvider getInvalidProjectIdentifiers
* @dataProvider Redmine\Tests\Fixtures\TestDataProvider::getInvalidProjectIdentifiers
*/
#[DataProvider('getInvalidProjectIdentifiers')]
#[DataProviderExternal(TestDataProvider::class, 'getInvalidProjectIdentifiers')]
public function testListByProjectWithWrongProjectIdentifierThrowsException($projectIdentifier)
{
$api = new IssueCategory(MockClient::create());
Expand All @@ -84,18 +84,6 @@ public function testListByProjectWithWrongProjectIdentifierThrowsException($proj
$api->listByProject($projectIdentifier);
}

public static function getInvalidProjectIdentifiers(): array
{
return [
'null' => [null],
'true' => [true],
'false' => [false],
'float' => [0.0],
'array' => [[]],
'object' => [new stdClass()],
];
}

public function testListByProjectThrowsException()
{
// Create the used mock objects
Expand Down
Loading
Loading