Skip to content

Commit

Permalink
Merge pull request #406 from Art4/add-issuecategory-listnamesbyproject
Browse files Browse the repository at this point in the history
Add `IssueCategory::listNamesByProject()` method as replacement for `IssueCategory::listing()`
  • Loading branch information
Art4 authored Jun 28, 2024
2 parents be7c256 + 92da0f0 commit b118039
Show file tree
Hide file tree
Showing 14 changed files with 374 additions and 94 deletions.
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

0 comments on commit b118039

Please sign in to comment.