Skip to content

Commit

Permalink
Add User::listLogins()
Browse files Browse the repository at this point in the history
  • Loading branch information
Art4 committed Jul 8, 2024
1 parent d5baebe commit 88effb9
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New method `Redmine\Api\Project::listNames()` for listing the ids and names of all projects.
- New method `Redmine\Api\Role::listNames()` for listing the ids and names of all roles.
- New method `Redmine\Api\TimeEntryActivity::listNames()` for listing the ids and names of all time entry activities.
- New method `Redmine\Api\User::listLogins()` for listing the ids and logins of all users.

### Deprecated

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

private $userLogins = null;

/**
* List users.
*
Expand All @@ -43,6 +45,43 @@ final public function list(array $params = []): array
}
}

/**
* Returns an array of all users with id/login pairs.
*
* @return array<int,string> list of users (id => login)
*/
final public function listLogins(): array
{
if ($this->userLogins !== null) {
return $this->userLogins;
}

$this->userLogins = [];

$limit = 100;
$offset = 0;

do {
$list = $this->list([
'limit' => $limit,
'offset' => $offset,
]);

$listCount = 0;
$offset += $limit;

if (array_key_exists('users', $list)) {
$listCount = count($list['users']);

foreach ($list['users'] as $user) {
$this->userLogins[(int) $user['id']] = (string) $user['login'];
}
}
} while ($listCount === $limit);

return $this->userLogins;
}

/**
* List users.
*
Expand Down
34 changes: 34 additions & 0 deletions tests/Behat/Bootstrap/UserContextTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@

trait UserContextTrait
{
/**
* @Given I create :count users
*/
public function iCreateUsers(int $count)
{
while ($count > 0) {
$table = new TableNode([
['property', 'value'],
['login', 'testuser_' . $count],
['firstname', 'first'],
['lastname', 'last'],
['mail', 'mail.' . $count . '@example.net'],
]);

$this->iCreateAUserWithTheFollowingData($table);

$count--;
}
}

/**
* @When I create a user with the following data
*/
Expand Down Expand Up @@ -57,6 +77,20 @@ public function iListAllUsers()
);
}

/**
* @When I list all user logins
*/
public function iListAllUserLogins()
{
/** @var User */
$api = $this->getNativeCurlClient()->getApi('user');

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

/**
* @When I update the user with id :id and the following data
*/
Expand Down
25 changes: 25 additions & 0 deletions tests/Behat/features/user.feature
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,31 @@ Feature: Interacting with the REST API for users
| mail | mail@example.net |
| twofa_scheme | null |

Scenario: Listing of multiple user logins
Given I have a "NativeCurlClient" client
And I create a user with the following data
| property | value |
| login | username |
| firstname | first |
| lastname | last |
| mail | mail@example.net |
When I list all user logins
Then the response has the status code "200"
And the response has the content type "application/json"
And the returned data contains "2" items
And the returned data has proterties with the following data
| property | value |
| 1 | admin |
| 5 | username |

Scenario: Listing of multiple user logins
Given I have a "NativeCurlClient" client
And I create "108" users
When I list all user logins
Then the response has the status code "200"
And the response has the content type "application/json"
And the returned data contains "109" items

Scenario: Updating an user
Given I have a "NativeCurlClient" client
And I create a user with the following data
Expand Down
167 changes: 167 additions & 0 deletions tests/Unit/Api/User/ListLoginsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php

declare(strict_types=1);

namespace Redmine\Tests\Unit\Api\User;

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

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

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

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

public static function getListLoginsData(): array
{
return [
'test without users' => [
'/users.json?limit=100&offset=0',
201,
<<<JSON
{
"users": []
}
JSON,
[],
],
'test with multiple users' => [
'/users.json?limit=100&offset=0',
201,
<<<JSON
{
"users": [
{"id": 7, "login": "username_C"},
{"id": 8, "login": "username_B"},
{"id": 9, "login": "username_A"}
]
}
JSON,
[
7 => "username_C",
8 => "username_B",
9 => "username_A",
],
],
];
}

public function testListLoginsWithALotOfUsersHandlesPagination()
{
$assertData = [];
$usersRequest1 = [];
$usersRequest2 = [];
$usersRequest3 = [];

for ($i = 1; $i <= 100; $i++) {
$login = 'user_' . $i;

$assertData[$i] = $login;
$usersRequest1[] = ['id' => $i, 'login' => $login];
}

for ($i = 101; $i <= 200; $i++) {
$login = 'user_' . $i;

$assertData[$i] = $login;
$usersRequest2[] = ['id' => $i, 'login' => $login];
}

$client = AssertingHttpClient::create(
$this,
[
'GET',
'/users.json?limit=100&offset=0',
'application/json',
'',
200,
'application/json',
json_encode(['users' => $usersRequest1]),
],
[
'GET',
'/users.json?limit=100&offset=100',
'application/json',
'',
200,
'application/json',
json_encode(['users' => $usersRequest2]),
],
[
'GET',
'/users.json?limit=100&offset=200',
'application/json',
'',
200,
'application/json',
json_encode(['users' => $usersRequest3]),
],
);

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

// Perform the tests
$this->assertSame($assertData, $api->listLogins());
}

public function testListLoginsCallsHttpClientOnlyOnce()
{
$client = AssertingHttpClient::create(
$this,
[
'GET',
'/users.json?limit=100&offset=0',
'application/json',
'',
200,
'application/json',
<<<JSON
{
"users": [
{
"id": 1,
"login": "username"
}
]
}
JSON,
],
);

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

// Perform the tests
$this->assertSame([1 => 'username'], $api->listLogins());
$this->assertSame([1 => 'username'], $api->listLogins());
$this->assertSame([1 => 'username'], $api->listLogins());
}
}

0 comments on commit 88effb9

Please sign in to comment.