From 80c104ff73485fd898d0a59b5a4a5dbcaa01a50c Mon Sep 17 00:00:00 2001 From: Greg Slonim Date: Tue, 26 Sep 2023 16:46:47 +0100 Subject: [PATCH] Initial revision --- .../IResourceLabelEventsClient.cs | 31 +++++++++++ .../Responses/EventResourceType.cs | 25 +++++++++ .../LabelEvents/Responses/LabelEvent.cs | 18 +++++++ src/GitLabApiClient/Models/Resource.cs | 22 ++++++++ .../ResourceLabelEventsClient.cs | 36 +++++++++++++ .../ResourceLabelEventsClientTest.cs | 54 +++++++++++++++++++ 6 files changed, 186 insertions(+) create mode 100644 src/GitLabApiClient/IResourceLabelEventsClient.cs create mode 100644 src/GitLabApiClient/Models/LabelEvents/Responses/EventResourceType.cs create mode 100644 src/GitLabApiClient/Models/LabelEvents/Responses/LabelEvent.cs create mode 100644 src/GitLabApiClient/Models/Resource.cs create mode 100644 src/GitLabApiClient/ResourceLabelEventsClient.cs create mode 100644 test/GitLabApiClient.Test/ResourceLabelEventsClientTest.cs diff --git a/src/GitLabApiClient/IResourceLabelEventsClient.cs b/src/GitLabApiClient/IResourceLabelEventsClient.cs new file mode 100644 index 00000000..658e0cd4 --- /dev/null +++ b/src/GitLabApiClient/IResourceLabelEventsClient.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using GitLabApiClient.Internal.Paths; +using GitLabApiClient.Models.LabelEvents.Responses; +using GitLabApiClient.Models.Projects.Responses; + +namespace GitLabApiClient +{ + public interface IResourceLabelEventsClient + { + /// + /// Retrieves label events from issues. + /// + /// The ID, path or of the project. + /// Resource type (supported resources: Issues, Epics, MergeRequests) + /// The IID of an issue, ID of an Epic, or IID of a Merge Request + /// Label Events for the given resource type and id + Task> GetAllAsync(ProjectId projectId, EventResourceType eventResourceType, int resourceId); + + /// + /// Retrieves a single label event from issues. + /// + /// The ID, path or of the project. + /// Resource type (supported resources: Issues, Epics, MergeRequests) + /// The IID of an issue, ID of an Epic, or IID of a Merge Request + /// The ID of a label event + /// Label Events for the given issue Id + Task> GetAsync(ProjectId projectId, EventResourceType eventResourceType, int resourceId, + int eventId); + } +} diff --git a/src/GitLabApiClient/Models/LabelEvents/Responses/EventResourceType.cs b/src/GitLabApiClient/Models/LabelEvents/Responses/EventResourceType.cs new file mode 100644 index 00000000..5163c8d8 --- /dev/null +++ b/src/GitLabApiClient/Models/LabelEvents/Responses/EventResourceType.cs @@ -0,0 +1,25 @@ +using System; +using System.ComponentModel; + +namespace GitLabApiClient.Models.LabelEvents.Responses +{ + public enum EventResourceType + { + [Description("issues")] + Issues, + [Description("epics")] + Epics, + [Description("merge_requests")] + MergeRequests + } + + internal static class EnumExtensions + { + public static string GetDescription(this Enum value) + { + var field = value.GetType().GetField(value.ToString()); + var attributes = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false); + return attributes.Length > 0 ? attributes[0].Description : value.ToString(); + } + } +} diff --git a/src/GitLabApiClient/Models/LabelEvents/Responses/LabelEvent.cs b/src/GitLabApiClient/Models/LabelEvents/Responses/LabelEvent.cs new file mode 100644 index 00000000..52868bea --- /dev/null +++ b/src/GitLabApiClient/Models/LabelEvents/Responses/LabelEvent.cs @@ -0,0 +1,18 @@ +using GitLabApiClient.Models.Projects.Responses; +using GitLabApiClient.Models.Users.Responses; +using Newtonsoft.Json; + +namespace GitLabApiClient.Models.LabelEvents.Responses +{ + public class LabelEvent : Resource + { + [JsonProperty("user")] + public User User { get; set; } + + [JsonProperty("label")] + public Label Label { get; set; } + + [JsonProperty("action")] + public string Action { get; set; } + } +} diff --git a/src/GitLabApiClient/Models/Resource.cs b/src/GitLabApiClient/Models/Resource.cs new file mode 100644 index 00000000..fd3b6cfd --- /dev/null +++ b/src/GitLabApiClient/Models/Resource.cs @@ -0,0 +1,22 @@ +using System; +using Newtonsoft.Json; + +namespace GitLabApiClient.Models +{ + public class Resource + { + internal Resource() { } + + [JsonProperty("id")] + public int Id { get; set; } + + [JsonProperty("created_at")] + public DateTime CreatedAt { get; set; } + + [JsonProperty("resource_type")] + public string ResourceType { get; set; } + + [JsonProperty("resource_id")] + public string ResourceId { get; set; } + } +} diff --git a/src/GitLabApiClient/ResourceLabelEventsClient.cs b/src/GitLabApiClient/ResourceLabelEventsClient.cs new file mode 100644 index 00000000..7593e0d7 --- /dev/null +++ b/src/GitLabApiClient/ResourceLabelEventsClient.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using GitLabApiClient.Internal.Http; +using GitLabApiClient.Internal.Paths; +using GitLabApiClient.Models.LabelEvents.Responses; + +namespace GitLabApiClient +{ + public sealed class ResourceLabelEventsClient : IResourceLabelEventsClient + { + private readonly GitLabHttpFacade _httpFacade; + + internal ResourceLabelEventsClient(GitLabHttpFacade httpFacade) => + _httpFacade = httpFacade; + + public async Task> GetAllAsync( + ProjectId projectId, + EventResourceType eventResourceType, + int resourceId) + { + string query = + $"projects/{projectId}/{eventResourceType.GetDescription()}/{resourceId}/resource_label_events"; + return await _httpFacade.GetPagedList(query); + } + + public async Task> GetAsync(ProjectId projectId, + EventResourceType eventResourceType, + int resourceId, + int eventId) + { + string query = + $"projects/{projectId}/{eventResourceType.GetDescription()}/{resourceId}/resource_label_events/{eventId}"; + return await _httpFacade.GetPagedList(query); + } + } +} diff --git a/test/GitLabApiClient.Test/ResourceLabelEventsClientTest.cs b/test/GitLabApiClient.Test/ResourceLabelEventsClientTest.cs new file mode 100644 index 00000000..05215efd --- /dev/null +++ b/test/GitLabApiClient.Test/ResourceLabelEventsClientTest.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using FluentAssertions; +using GitLabApiClient.Internal.Queries; +using GitLabApiClient.Models.Issues.Requests; +using GitLabApiClient.Models.LabelEvents.Responses; +using GitLabApiClient.Test.Utilities; +using Xunit; + +namespace GitLabApiClient.Test +{ + [Trait("Category", "LinuxIntegration")] + [Collection("GitLabContainerFixture")] + public class ResourceLabelEventsClientTest : IAsyncLifetime + { + private readonly MergeRequestsClient _mergeRequestsClient = new MergeRequestsClient( + GitLabApiHelper.GetFacade(), new MergeRequestsQueryBuilder(), new ProjectMergeRequestsQueryBuilder(), + new ProjectMergeRequestsNotesQueryBuilder()); + + private readonly IssuesClient _issuesClient = new IssuesClient( + GitLabApiHelper.GetFacade(), new IssuesQueryBuilder(), new ProjectIssueNotesQueryBuilder()); + + private readonly ResourceLabelEventsClient _sut = new ResourceLabelEventsClient(GitLabApiHelper.GetFacade()); + + [Fact] + public async Task IssuesLabelEventsCanBeRetrieved() + { + var createdIssue = await _issuesClient.CreateAsync( + GitLabApiHelper.TestProjectTextId, new CreateIssueRequest("Title1") + { + Assignees = new List { 1 }, + Confidential = true, + Description = "Description1", + Labels = new[] { "Label1" }, + MilestoneId = 2, + DiscussionToResolveId = 3, + MergeRequestIdToResolveDiscussions = 4 + }); + + var labelEvents = await _sut.GetAllAsync( + GitLabApiHelper.TestProjectTextId, + EventResourceType.Issues, + createdIssue.Iid + ); + + labelEvents.Single().Should().Match(actual => + actual.Label.Name == "Label1"); + } + + public Task InitializeAsync() => throw new System.NotImplementedException(); + public Task DisposeAsync() => throw new System.NotImplementedException(); + } +}