diff --git a/src/ChangeLog.Test/Integrations/GitLab/GitLabLinkTaskTest.cs b/src/ChangeLog.Test/Integrations/GitLab/GitLabLinkTaskTest.cs index 187e2895..557aa4a6 100644 --- a/src/ChangeLog.Test/Integrations/GitLab/GitLabLinkTaskTest.cs +++ b/src/ChangeLog.Test/Integrations/GitLab/GitLabLinkTaskTest.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Reflection; using System.Threading.Tasks; using GitLabApiClient; using GitLabApiClient.Internal.Paths; @@ -64,6 +65,43 @@ private ProjectId MatchProjectId(string expected) return It.Is((ProjectId actual) => actual.ToString() == ((ProjectId)expected).ToString()); } + /// + /// Helper method to test if an Action performs the expected changes to an object + /// + /// The type of object the changes are applied to. + /// The action to apply to the object. + /// The assertions to apply to the object after applying + private bool AssertAction(Action actionToVerify, params Action[] assertions) + { + // I'm not sure this is a good idea + // but the only way we can make any assertions about an action + // is calling it an afterwards checking if it made the expected + // changes to the instance. + // The instance in turn needs to be created through reflection because + // GitLabApiClient's query types are sealed with an internal constructor + + var type = typeof(T); + var instance = (T)type.Assembly.CreateInstance( + type.FullName!, false, + BindingFlags.Instance | BindingFlags.NonPublic, + null, null, null, null)!; + + if (instance == null) + throw new InvalidOperationException($"Failed to create instance of '{type.FullName}'"); + + // Apply the action we want to verify + actionToVerify.Invoke(instance); + + // Apply the assertions to the instance + foreach (var assertion in assertions) + { + assertion.Invoke(instance); + } + + return true; + } + + [Fact] public async Task Run_does_nothing_if_repository_does_not_have_remotes() { @@ -355,8 +393,21 @@ public async Task Run_adds_merge_request_links_to_footers(string footerText, int }); - m_MergeRequestsClientMock.Verify(x => x.GetAsync(It.IsAny(), It.IsAny>()), Times.Once); - m_MergeRequestsClientMock.Verify(x => x.GetAsync(MatchProjectId(projectPath), It.IsAny>()), Times.Once); + m_MergeRequestsClientMock.Verify( + x => x.GetAsync(It.IsAny(), It.IsAny>()), + Times.Once); + + m_MergeRequestsClientMock.Verify( + x => x.GetAsync( + MatchProjectId(projectPath), + It.Is>( + action => + AssertAction( + action, + opts => Assert.Equal(id, Assert.Single(opts.MergeRequestsIds)), + opts => Assert.Equal(QueryMergeRequestState.All, opts.State) + ))), + Times.Once); } [Theory] @@ -473,8 +524,20 @@ public async Task Run_adds_milestone_links_to_footers(string footerText, int id, }); - m_ProjectsClientMock.Verify(x => x.GetMilestonesAsync(It.IsAny(), It.IsAny>()), Times.Once); - m_ProjectsClientMock.Verify(x => x.GetMilestonesAsync(MatchProjectId(projectPath), It.IsAny>()), Times.Once); + m_ProjectsClientMock.Verify( + x => x.GetMilestonesAsync(It.IsAny(), It.IsAny>()), + Times.Once); + + m_ProjectsClientMock.Verify( + x => x.GetMilestonesAsync( + MatchProjectId(projectPath), + It.Is>(action => + AssertAction( + action, + opts => Assert.Equal(id, Assert.Single(opts.MilestoneIds)), + opts => Assert.Equal(MilestoneState.All, opts.State) + ))), + Times.Once); } [Theory] diff --git a/src/ChangeLog/Integrations/GitLab/GitLabLinkTask.cs b/src/ChangeLog/Integrations/GitLab/GitLabLinkTask.cs index 960b460e..dafeb91a 100644 --- a/src/ChangeLog/Integrations/GitLab/GitLabLinkTask.cs +++ b/src/ChangeLog/Integrations/GitLab/GitLabLinkTask.cs @@ -5,6 +5,8 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using GitLabApiClient; +using GitLabApiClient.Models.MergeRequests.Requests; +using GitLabApiClient.Models.Milestones.Responses; using Grynwald.ChangeLog.Git; using Grynwald.ChangeLog.Model; using Grynwald.ChangeLog.Tasks; @@ -227,7 +229,12 @@ private bool TryParseReference(string input, [NotNullWhen(true)] out GitLabRefer try { - var mergeRequests = await gitlabClient.MergeRequests.GetAsync(projectPath, query => { query.MergeRequestsIds.Add(id); }); + var mergeRequests = await gitlabClient.MergeRequests.GetAsync(projectPath, queryOptions => + { + queryOptions.MergeRequestsIds = new[] { id }; + queryOptions.State = QueryMergeRequestState.All; + }); + if (mergeRequests.Count == 1) { return new Uri(mergeRequests.Single().WebUrl); ; @@ -255,9 +262,10 @@ private bool TryParseReference(string input, [NotNullWhen(true)] out GitLabRefer // within the project, but some other id. // Instead, use GetMilestonesAsync() and query for a single milestone id // for which we can use the id in the reference. - var milestones = await gitlabClient.Projects.GetMilestonesAsync(projectPath, options => + var milestones = await gitlabClient.Projects.GetMilestonesAsync(projectPath, queryOptions => { - options.MilestoneIds = new[] { id }; + queryOptions.MilestoneIds = new[] { id }; + queryOptions.State = MilestoneState.All; }); if (milestones.Count == 1)