Skip to content

Commit 352a8dc

Browse files
committed
Add Projects::listNames()
1 parent 066212f commit 352a8dc

File tree

5 files changed

+162
-0
lines changed

5 files changed

+162
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- New method `Redmine\Api\Group::listNames()` for listing the ids and names of all groups.
1414
- New method `Redmine\Api\IssueCategory::listNamesByProject()` for listing the ids and names of all issue categories of a project.
1515
- New method `Redmine\Api\IssueStatus::listNames()` for listing the ids and names of all issue statuses.
16+
- New method `Redmine\Api\Project::listNames()` for listing the ids and names of all projects.
1617

1718
### Deprecated
1819

src/Redmine/Api/Project.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class Project extends AbstractApi
2424
{
2525
private $projects = [];
2626

27+
private $projectNames = null;
28+
2729
/**
2830
* List projects.
2931
*
@@ -44,6 +46,30 @@ final public function list(array $params = []): array
4446
}
4547
}
4648

49+
/**
50+
* Returns an array of all projects with id/name pairs.
51+
*
52+
* @return array<int,string> list of projects (id => name)
53+
*/
54+
final public function listNames(): array
55+
{
56+
if ($this->projectNames !== null) {
57+
return $this->projectNames;
58+
}
59+
60+
$this->projectNames = [];
61+
62+
$list = $this->list();
63+
64+
if (array_key_exists('projects', $list)) {
65+
foreach ($list['projects'] as $issueStatus) {
66+
$this->projectNames[(int) $issueStatus['id']] = (string) $issueStatus['name'];
67+
}
68+
}
69+
70+
return $this->projectNames;
71+
}
72+
4773
/**
4874
* List projects.
4975
*

tests/Behat/Bootstrap/ProjectContextTrait.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,20 @@ public function iListAllProjects()
5757
);
5858
}
5959

60+
/**
61+
* @When I list all project names
62+
*/
63+
public function iListAllProjectNames()
64+
{
65+
/** @var Project */
66+
$api = $this->getNativeCurlClient()->getApi('project');
67+
68+
$this->registerClientResponse(
69+
$api->listNames(),
70+
$api->getLastResponse(),
71+
);
72+
}
73+
6074
/**
6175
* @When I show the project with identifier :identifier
6276
*/

tests/Behat/features/projects.feature

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,19 @@ Feature: Interacting with the REST API for projects
150150
updated_on
151151
"""
152152

153+
Scenario: Listing of multiple project names
154+
Given I have a "NativeCurlClient" client
155+
And I create a project with name "Test Project B" and identifier "test-project1"
156+
And I create a project with name "Test Project A" and identifier "test-project2"
157+
When I list all project names
158+
Then the response has the status code "200"
159+
And the response has the content type "application/json"
160+
And the returned data contains "2" items
161+
And the returned data has proterties with the following data
162+
| property | value |
163+
| 1 | Test Project B |
164+
| 2 | Test Project A |
165+
153166
Scenario: Updating a project
154167
Given I have a "NativeCurlClient" client
155168
And I create a project with name "Test Project" and identifier "test-project"
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Redmine\Tests\Unit\Api\Project;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use PHPUnit\Framework\TestCase;
10+
use Redmine\Api\Project;
11+
use Redmine\Tests\Fixtures\AssertingHttpClient;
12+
13+
#[CoversClass(Project::class)]
14+
class ListNamesTest extends TestCase
15+
{
16+
/**
17+
* @dataProvider getListNamesData
18+
*/
19+
#[DataProvider('getListNamesData')]
20+
public function testListNamesReturnsCorrectResponse($expectedPath, $responseCode, $response, $expectedResponse)
21+
{
22+
$client = AssertingHttpClient::create(
23+
$this,
24+
[
25+
'GET',
26+
$expectedPath,
27+
'application/json',
28+
'',
29+
$responseCode,
30+
'application/json',
31+
$response,
32+
],
33+
);
34+
35+
// Create the object under test
36+
$api = new Project($client);
37+
38+
// Perform the tests
39+
$this->assertSame($expectedResponse, $api->listNames());
40+
}
41+
42+
public static function getListNamesData(): array
43+
{
44+
return [
45+
'test without projects' => [
46+
'/projects.json',
47+
201,
48+
<<<JSON
49+
{
50+
"projects": []
51+
}
52+
JSON,
53+
[],
54+
],
55+
'test with multiple projects' => [
56+
'/projects.json',
57+
201,
58+
<<<JSON
59+
{
60+
"projects": [
61+
{"id": 7, "name": "Project C"},
62+
{"id": 8, "name": "Project B"},
63+
{"id": 9, "name": "Project A"}
64+
]
65+
}
66+
JSON,
67+
[
68+
7 => "Project C",
69+
8 => "Project B",
70+
9 => "Project A",
71+
],
72+
],
73+
];
74+
}
75+
76+
public function testListNamesCallsHttpClientOnlyOnce()
77+
{
78+
$client = AssertingHttpClient::create(
79+
$this,
80+
[
81+
'GET',
82+
'/projects.json',
83+
'application/json',
84+
'',
85+
200,
86+
'application/json',
87+
<<<JSON
88+
{
89+
"projects": [
90+
{
91+
"id": 1,
92+
"name": "Project 1"
93+
}
94+
]
95+
}
96+
JSON,
97+
],
98+
);
99+
100+
// Create the object under test
101+
$api = new Project($client);
102+
103+
// Perform the tests
104+
$this->assertSame([1 => 'Project 1'], $api->listNames());
105+
$this->assertSame([1 => 'Project 1'], $api->listNames());
106+
$this->assertSame([1 => 'Project 1'], $api->listNames());
107+
}
108+
}

0 commit comments

Comments
 (0)