diff --git a/src/Api/GroupsMilestones.php b/src/Api/GroupsMilestones.php index f870f78c..fad1c5d8 100644 --- a/src/Api/GroupsMilestones.php +++ b/src/Api/GroupsMilestones.php @@ -14,6 +14,8 @@ namespace Gitlab\Api; +use Symfony\Component\OptionsResolver\Options; + class GroupsMilestones extends AbstractApi { /** @@ -32,7 +34,9 @@ class GroupsMilestones extends AbstractApi * * @var int[] $iids return only the milestones having the given iids * @var string $state return only active or closed milestones - * @var string $search Return only milestones with a title or description matching the provided string. + * @var string $search Return only milestones with a title or description matching the provided string + * @var \DateTimeInterface $updated_after Return only milestones updated on or after the given datetime. Expected in ISO 8601 format (2019-03-15T08:00:00Z) + * @var \DateTimeInterface $updated_before Return only milestones updated on or before the given datetime. Expected in ISO 8601 format (2019-03-15T08:00:00Z) * } * * @return mixed @@ -40,6 +44,11 @@ class GroupsMilestones extends AbstractApi public function all($group_id, array $parameters = []) { $resolver = $this->createOptionsResolver(); + $datetimeNormalizer = function (Options $resolver, \DateTimeInterface $value): string { + $utc = (new \DateTimeImmutable($value->format(\DateTimeImmutable::RFC3339_EXTENDED)))->setTimezone(new \DateTimeZone('UTC')); + + return $utc->format('Y-m-d\TH:i:s.v\Z'); + }; $resolver->setDefined('iids') ->setAllowedTypes('iids', 'array') ->setAllowedValues('iids', function (array $value) { @@ -51,6 +60,13 @@ public function all($group_id, array $parameters = []) ; $resolver->setDefined('search'); + $resolver->setDefined('updated_after') + ->setAllowedTypes('updated_after', \DateTimeInterface::class) + ->setNormalizer('updated_after', $datetimeNormalizer); + $resolver->setDefined('updated_before') + ->setAllowedTypes('updated_before', \DateTimeInterface::class) + ->setNormalizer('updated_before', $datetimeNormalizer); + return $this->get('groups/'.self::encodePath($group_id).'/milestones', $resolver->resolve($parameters)); } diff --git a/tests/Api/GroupsMilestonesTest.php b/tests/Api/GroupsMilestonesTest.php index 3dc5d7a7..9fcd80cf 100644 --- a/tests/Api/GroupsMilestonesTest.php +++ b/tests/Api/GroupsMilestonesTest.php @@ -38,6 +38,106 @@ public function shouldGetAllMilestones(): void $this->assertEquals($expectedArray, $api->all(1)); } + /** + * @test + */ + public function shouldGetAllMilestonesWithParameterOneIidsValue(): void + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/milestones', ['iids' => [456]]) + ; + + $api->all(1, ['iids' => [456]]); + } + + /** + * @test + */ + public function shouldGetAllMilestonesWithParameterTwoIidsValues(): void + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/milestones', ['iids' => [456, 789]]) + ; + + $api->all(1, ['iids' => [456, 789]]); + } + + public static function getAllMilestonesWithParameterStateDataProvider() + { + return [ + GroupsMilestones::STATE_ACTIVE => [GroupsMilestones::STATE_ACTIVE], + GroupsMilestones::STATE_CLOSED => [GroupsMilestones::STATE_CLOSED], + ]; + } + + /** + * @test + * + * @dataProvider getAllMilestonesWithParameterStateDataProvider + */ + public function shouldGetAllMilestonesWithParameterState(string $state): void + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/milestones', ['state' => $state]) + ; + + $api->all(1, ['state' => $state]); + } + + /** + * @test + */ + public function shouldGetAllMilestonesWithParameterSearch(): void + { + $searchValue = 'abc'; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/milestones', ['search' => $searchValue]) + ; + + $api->all(1, ['search' => $searchValue]); + } + + /** + * @test + */ + public function shouldGetAllMilestonesWithParameterUpdatedBefore(): void + { + $updatedBefore = new \DateTimeImmutable('2023-11-25T08:00:00Z'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/milestones', ['updated_before' => '2023-11-25T08:00:00.000Z']) + ; + + $api->all(1, ['updated_before' => $updatedBefore]); + } + + /** + * @test + */ + public function shouldGetAllMilestonesWithParameterUpdatedAfter(): void + { + $updatedAfter = new \DateTimeImmutable('2023-11-25T08:00:00Z'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/milestones', ['updated_after' => '2023-11-25T08:00:00.000Z']) + ; + + $api->all(1, ['updated_after' => $updatedAfter]); + } + /** * @test */