From f9e1ea88569362509bc1d42d52a4babca1d25a8e Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 5 Jul 2024 09:46:09 +0200 Subject: [PATCH 1/4] Update user and group ids in behat tests Pinging the redmine server for the health check create a new AnonymousUser with id 4 refs #410 --- tests/Behat/features/groups.feature | 28 ++++++++++++++-------------- tests/Behat/features/user.feature | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/Behat/features/groups.feature b/tests/Behat/features/groups.feature index fbe9cd34..15ca5474 100644 --- a/tests/Behat/features/groups.feature +++ b/tests/Behat/features/groups.feature @@ -17,7 +17,7 @@ Feature: Interacting with the REST API for groups """ And the returned data has proterties with the following data | property | value | - | id | 4 | + | id | 5 | | name | Test Group | Scenario: Listing of zero groups @@ -52,7 +52,7 @@ Feature: Interacting with the REST API for groups """ And the returned data "groups.0" property contains the following data | property | value | - | id | 4 | + | id | 5 | | name | Test Group | Scenario: Listing names of all groups @@ -69,16 +69,16 @@ Feature: Interacting with the REST API for groups And the returned data contains "5" items And the returned data contains the following data | property | value | - | 4 | Test Group D | - | 5 | Test Group E | - | 6 | Test Group C | - | 7 | Test Group B | - | 8 | Test Group A | + | 5 | Test Group D | + | 6 | Test Group E | + | 7 | Test Group C | + | 8 | Test Group B | + | 9 | Test Group A | Scenario: Showing a specific group Given I have a "NativeCurlClient" client And I create a group with name "Test Group" - When I show the group with id "4" + When I show the group with id "5" 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 @@ -93,7 +93,7 @@ Feature: Interacting with the REST API for groups """ And the returned data "group" property contains the following data | property | value | - | id | 4 | + | id | 5 | | name | Test Group | @error @@ -110,7 +110,7 @@ Feature: Interacting with the REST API for groups And I create a group with the following data | property | value | | name | Test Group | - When I update the group with id "4" with the following data + When I update the group with id "5" with the following data | property | value | | name | new group name | Then the response has the status code "204" @@ -121,7 +121,7 @@ Feature: Interacting with the REST API for groups Scenario: Adding an user to a group Given I have a "NativeCurlClient" client And I create a group with name "Test Group" - When I add the user with id "1" to the group with id "4" + When I add the user with id "1" to the group with id "5" Then the response has the status code "204" And the response has an empty content type And the response has the content "" @@ -130,8 +130,8 @@ Feature: Interacting with the REST API for groups Scenario: Removing an user from a group Given I have a "NativeCurlClient" client And I create a group with name "Test Group" - And I add the user with id "1" to the group with id "4" - When I remove the user with id "1" from the group with id "4" + And I add the user with id "1" to the group with id "5" + When I remove the user with id "1" from the group with id "5" Then the response has the status code "204" And the response has an empty content type And the response has the content "" @@ -140,7 +140,7 @@ Feature: Interacting with the REST API for groups Scenario: Deleting a group Given I have a "NativeCurlClient" client And I create a group with name "Test Group" - When I remove the group with id "4" + When I remove the group with id "5" Then the response has the status code "204" And the response has an empty content type And the response has the content "" diff --git a/tests/Behat/features/user.feature b/tests/Behat/features/user.feature index b4d7b969..367f03c9 100644 --- a/tests/Behat/features/user.feature +++ b/tests/Behat/features/user.feature @@ -34,7 +34,7 @@ Feature: Interacting with the REST API for users """ And the returned data has proterties with the following data | property | value | - | id | 4 | + | id | 5 | | login | username | | admin | false | | firstname | first | @@ -53,7 +53,7 @@ Feature: Interacting with the REST API for users | firstname | first | | lastname | last | | mail | mail@example.com | - When I update the user with id "4" and the following data + When I update the user with id "5" and the following data | property | value | | firstname | new_first | | lastname | new_last | @@ -121,7 +121,7 @@ Feature: Interacting with the REST API for users | firstname | first | | lastname | last | | mail | mail@example.com | - When I remove the user with id "4" + When I remove the user with id "5" Then the response has the status code "204" And the response has an empty content type And the response has the content "" From 7620e52ce7e565c0c1cdaf249a45679ae1070629 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 5 Jul 2024 10:13:54 +0200 Subject: [PATCH 2/4] Create behat tests for listing time entry activities --- .../TimeEntryActivityContextTrait.php | 18 +++++- tests/Behat/features/time_entry.feature | 4 ++ .../features/time_entry_activity.feature | 61 +++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/Behat/features/time_entry_activity.feature diff --git a/tests/Behat/Bootstrap/TimeEntryActivityContextTrait.php b/tests/Behat/Bootstrap/TimeEntryActivityContextTrait.php index 34e24355..48c7687d 100644 --- a/tests/Behat/Bootstrap/TimeEntryActivityContextTrait.php +++ b/tests/Behat/Bootstrap/TimeEntryActivityContextTrait.php @@ -4,6 +4,8 @@ namespace Redmine\Tests\Behat\Bootstrap; +use Redmine\Api\TimeEntryActivity; + trait TimeEntryActivityContextTrait { /** @@ -18,10 +20,24 @@ public function iHaveATimeEntryActiviyWithName(string $activityName) [ ':name' => $activityName, ':position' => 1, - ':is_default' => 1, + ':is_default' => 0, ':type' => 'TimeEntryActivity', ':active' => 1, ], ); } + + /** + * @When I list all time entry activities + */ + public function iListAllTimeEntryActivities() + { + /** @var TimeEntryActivity */ + $api = $this->getNativeCurlClient()->getApi('time_entry_activity'); + + $this->registerClientResponse( + $api->list(), + $api->getLastResponse(), + ); + } } diff --git a/tests/Behat/features/time_entry.feature b/tests/Behat/features/time_entry.feature index bf0a5eba..db891bed 100644 --- a/tests/Behat/features/time_entry.feature +++ b/tests/Behat/features/time_entry.feature @@ -12,6 +12,7 @@ Feature: Interacting with the REST API for time_entries | property | value | | project_id | 1 | | hours | 1 | + | activity_id | 1 | Then the response has the status code "201" And the response has the content type "application/xml" And the returned data is an instance of "SimpleXMLElement" @@ -77,6 +78,7 @@ Feature: Interacting with the REST API for time_entries | property | value | | project_id | 1 | | hours | 1 | + | activity_id | 1 | When I update the time entry with id "1" and the following data | property | value | | project_id | 1 | @@ -94,6 +96,7 @@ Feature: Interacting with the REST API for time_entries | property | value | | project_id | 1 | | hours | 1 | + | activity_id | 1 | When I show the time entry with the id "1" Then the response has the status code "200" And the response has the content type "application/json" @@ -168,6 +171,7 @@ Feature: Interacting with the REST API for time_entries | property | value | | project_id | 1 | | hours | 1 | + | activity_id | 1 | When I remove the time entry with id "1" Then the response has the status code "204" And the response has an empty content type diff --git a/tests/Behat/features/time_entry_activity.feature b/tests/Behat/features/time_entry_activity.feature new file mode 100644 index 00000000..d8544cdf --- /dev/null +++ b/tests/Behat/features/time_entry_activity.feature @@ -0,0 +1,61 @@ +@time_entry_activity +Feature: Interacting with the REST API for time entry activities + In order to interact with REST API for time entry activities + As a user + I want to make sure the Redmine server replies with the correct response + + Scenario: Listing of zero time entry activities + Given I have a "NativeCurlClient" client + When I list all time entry activities + 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 + """ + time_entry_activities + """ + And the returned data "time_entry_activities" property is an array + And the returned data "time_entry_activities" property contains "0" items + + @wip + Scenario: Listing of multiple time entry activities + Given I have a "NativeCurlClient" client + And I have a time entry activiy with name "Development" + And I have a time entry activiy with name "Support" + When I list all time entry activities + 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 + """ + time_entry_activities + """ + And the returned data "time_entry_activities" property is an array + And the returned data "time_entry_activities" property contains "2" items + And the returned data "time_entry_activities.0" property is an array + And the returned data "time_entry_activities.0" property has only the following properties + """ + id + name + is_default + active + """ + And the returned data "time_entry_activities.0" property contains the following data + | property | value | + | id | 1 | + | name | Development | + | is_default | false | + | active | true | + And the returned data "time_entry_activities.1" property is an array + And the returned data "time_entry_activities.1" property has only the following properties + """ + id + name + is_default + active + """ + And the returned data "time_entry_activities.1" property contains the following data + | property | value | + | id | 2 | + | name | Support | + | is_default | false | + | active | true | + From 420baa041112e6f10811f7b242f14950a7c85af1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 5 Jul 2024 10:52:58 +0200 Subject: [PATCH 3/4] Create TimeEntryActivity::listNames() --- CHANGELOG.md | 1 + src/Redmine/Api/TimeEntryActivity.php | 25 ++++ .../TimeEntryActivityContextTrait.php | 14 +++ .../features/time_entry_activity.feature | 15 ++- .../Api/TimeEntryActivity/ListNamesTest.php | 108 ++++++++++++++++++ 5 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 tests/Unit/Api/TimeEntryActivity/ListNamesTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d75c3fa5..9490c8d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New method `Redmine\Api\IssueStatus::listNames()` for listing the ids and names of all issue statuses. - 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. ### Deprecated diff --git a/src/Redmine/Api/TimeEntryActivity.php b/src/Redmine/Api/TimeEntryActivity.php index 71e623da..d9f59159 100644 --- a/src/Redmine/Api/TimeEntryActivity.php +++ b/src/Redmine/Api/TimeEntryActivity.php @@ -17,6 +17,8 @@ class TimeEntryActivity extends AbstractApi { private $timeEntryActivities = []; + private $timeEntryActivityNames = null; + /** * List time entry activities. * @@ -35,6 +37,29 @@ final public function list(array $params = []): array } } + /** + * Returns an array of all time entry activities with id/name pairs. + * + * @return array list of time entry activities (id => name) + */ + final public function listNames(): array + { + if ($this->timeEntryActivityNames !== null) { + return $this->timeEntryActivityNames; + } + + $this->timeEntryActivityNames = []; + $list = $this->list(); + + if (array_key_exists('time_entry_activities', $list)) { + foreach ($list['time_entry_activities'] as $activity) { + $this->timeEntryActivityNames[(int) $activity['id']] = $activity['name']; + } + } + + return $this->timeEntryActivityNames; + } + /** * List time entry activities. * diff --git a/tests/Behat/Bootstrap/TimeEntryActivityContextTrait.php b/tests/Behat/Bootstrap/TimeEntryActivityContextTrait.php index 48c7687d..9bcd9081 100644 --- a/tests/Behat/Bootstrap/TimeEntryActivityContextTrait.php +++ b/tests/Behat/Bootstrap/TimeEntryActivityContextTrait.php @@ -40,4 +40,18 @@ public function iListAllTimeEntryActivities() $api->getLastResponse(), ); } + + /** + * @When I list all time entry activity names + */ + public function iListAllTimeEntryActivityNames() + { + /** @var TimeEntryActivity */ + $api = $this->getNativeCurlClient()->getApi('time_entry_activity'); + + $this->registerClientResponse( + $api->listNames(), + $api->getLastResponse(), + ); + } } diff --git a/tests/Behat/features/time_entry_activity.feature b/tests/Behat/features/time_entry_activity.feature index d8544cdf..eafa8ae8 100644 --- a/tests/Behat/features/time_entry_activity.feature +++ b/tests/Behat/features/time_entry_activity.feature @@ -16,7 +16,6 @@ Feature: Interacting with the REST API for time entry activities And the returned data "time_entry_activities" property is an array And the returned data "time_entry_activities" property contains "0" items - @wip Scenario: Listing of multiple time entry activities Given I have a "NativeCurlClient" client And I have a time entry activiy with name "Development" @@ -59,3 +58,17 @@ Feature: Interacting with the REST API for time entry activities | is_default | false | | active | true | + Scenario: Listing of multiple time entry activity names + Given I have a "NativeCurlClient" client + And I have a time entry activiy with name "Development" + And I have a time entry activiy with name "Support" + When I list all time entry activity 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 | Development | + | 2 | Support | + diff --git a/tests/Unit/Api/TimeEntryActivity/ListNamesTest.php b/tests/Unit/Api/TimeEntryActivity/ListNamesTest.php new file mode 100644 index 00000000..9fbc5600 --- /dev/null +++ b/tests/Unit/Api/TimeEntryActivity/ListNamesTest.php @@ -0,0 +1,108 @@ +assertSame($expectedResponse, $api->listNames()); + } + + public static function getListNamesData(): array + { + return [ + 'test without time entry activities' => [ + '/enumerations/time_entry_activities.json', + 201, + << [ + '/enumerations/time_entry_activities.json', + 201, + << "TimeEntryActivity 3", + 8 => "TimeEntryActivity 2", + 9 => "TimeEntryActivity 1", + ], + ], + ]; + } + + public function testListNamesCallsHttpClientOnlyOnce() + { + $client = AssertingHttpClient::create( + $this, + [ + 'GET', + '/enumerations/time_entry_activities.json', + 'application/json', + '', + 200, + 'application/json', + <<assertSame([1 => 'TimeEntryActivity 1'], $api->listNames()); + $this->assertSame([1 => 'TimeEntryActivity 1'], $api->listNames()); + $this->assertSame([1 => 'TimeEntryActivity 1'], $api->listNames()); + } +} From 7161d2769c4b359887464144648a8692025018e5 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 5 Jul 2024 10:57:25 +0200 Subject: [PATCH 4/4] Deprecate TimeEntryActivity::listing() --- CHANGELOG.md | 7 +++--- src/Redmine/Api/TimeEntryActivity.php | 5 ++++ tests/Unit/Api/TimeEntryActivityTest.php | 32 ++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9490c8d7..2ca827ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,9 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `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. -- `Redmine\Api\Project::listing()` is deprecated, use `\Redmine\Api\Project::listNamesByProject()` instead. -- `Redmine\Api\Role::listing()` is deprecated, use `\Redmine\Api\Role::listNamesByProject()` instead. +- `Redmine\Api\IssueStatus::listing()` is deprecated, use `\Redmine\Api\IssueStatus::listNames()` instead. +- `Redmine\Api\Project::listing()` is deprecated, use `\Redmine\Api\Project::listNames()` instead. +- `Redmine\Api\Role::listing()` is deprecated, use `\Redmine\Api\Role::listNames()` instead. +- `Redmine\Api\TimeEntryActivity::listing()` is deprecated, use `\Redmine\Api\TimeEntryActivity::listNames()` instead. ## [v2.6.0](https://github.com/kbsali/php-redmine-api/compare/v2.5.0...v2.6.0) - 2024-03-25 diff --git a/src/Redmine/Api/TimeEntryActivity.php b/src/Redmine/Api/TimeEntryActivity.php index d9f59159..511d5e21 100644 --- a/src/Redmine/Api/TimeEntryActivity.php +++ b/src/Redmine/Api/TimeEntryActivity.php @@ -94,12 +94,17 @@ public function all(array $params = []) /** * Returns an array of time entry activities with name/id pairs. * + * @deprecated v2.7.0 Use listNames() instead. + * @see TimeEntryActivity::listNames() + * * @param bool $forceUpdate to force the update of the statuses var * * @return array list of time entry activities (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->timeEntryActivities) || $forceUpdate) { $this->timeEntryActivities = $this->list(); } diff --git a/tests/Unit/Api/TimeEntryActivityTest.php b/tests/Unit/Api/TimeEntryActivityTest.php index a8d46c0b..841042cd 100644 --- a/tests/Unit/Api/TimeEntryActivityTest.php +++ b/tests/Unit/Api/TimeEntryActivityTest.php @@ -166,6 +166,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('{"time_entry_activities":[{"id":1,"name":"TimeEntryActivity 1"},{"id":5,"name":"TimeEntryActivity 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new TimeEntryActivity($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\TimeEntryActivity::listing()` is deprecated since v2.7.0, use `Redmine\Api\TimeEntryActivity::listNames()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->listing(); + } + public function testGetIdByNameMakesGetRequest() { $response = '{"time_entry_activities":[{"id":2,"name":"TimeEntryActivities 2"}]}';