From 8c02b5ae197e72d0874fa7a2c1a2bae9c8628093 Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh Date: Thu, 18 Jan 2024 16:03:34 +0100 Subject: [PATCH 1/4] Fix muting of incorrect issues when bound to SonarCloud --- .../Api/V7_20/GetIssuesRequestTests.cs | 5 +- .../Api/V7_20/GetIssuesRequestWrapperTests.cs | 113 ++++++++++++------ .../V7_20/GetIssuesSonarCloudRequestTests.cs | 92 ++++++++++++++ .../V7_20/GetIssuesSonarQubeRequestTests.cs | 92 ++++++++++++++ ...> DefaultConfiguration_Configure_Tests.cs} | 7 +- .../SonarQubeService_GetIssuesBase.cs | 2 +- .../Api/DefaultConfiguration.cs | 5 +- .../Api/V10_2/GetIssuesWithCCTRequest.cs | 6 +- .../Api/V5_10/GetIssuesRequest.cs | 2 + .../Api/V7_20/GetIssuesRequest.cs | 9 +- .../Api/V7_20/GetIssuesRequestWrapper.cs | 5 +- .../V7_20/GetIssuesWithComponentRequest.cs | 56 +++++++++ .../V8_6/GetTaintVulnerabilitiesRequest.cs | 2 +- .../Api/V9_6/GetIssuesWithContextRequest.cs | 5 +- ...tTaintVulnerabilitiesWithContextRequest.cs | 2 +- .../Requests/RequestFactory.cs | 6 +- .../Requests/UnversionedRequestFactory.cs | 4 +- 17 files changed, 353 insertions(+), 60 deletions(-) create mode 100644 src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarCloudRequestTests.cs create mode 100644 src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarQubeRequestTests.cs rename src/SonarQube.Client.Tests/Requests/{DefaultConfiguration_Configure.cs => DefaultConfiguration_Configure_Tests.cs} (98%) create mode 100644 src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs index 5515d4a663..236004ebef 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs @@ -448,7 +448,7 @@ public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedI } [TestMethod] - public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQueryString() + public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreNotIncludedInQueryString() { var testSubject = CreateTestSubject("any", "any", componentKey: "project1"); @@ -462,7 +462,7 @@ public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQuery _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("components=project1").Should().BeTrue(); + actualQueryString.Contains("components=project1").Should().BeFalse(); } private static GetIssuesRequest CreateTestSubject(string projectKey, string statusesToRequest, string branch = null, string[] issueKeys = null, string ruleId = null, string componentKey = null) @@ -475,7 +475,6 @@ private static GetIssuesRequest CreateTestSubject(string projectKey, string stat Branch = branch, IssueKeys = issueKeys, RuleId = ruleId, - ComponentKey = componentKey }; return testSubject; diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs index 6ebdece57b..a32a6b4000 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs @@ -25,6 +25,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; +using SonarQube.Client.Api; using SonarQube.Client.Api.V7_20; using SonarQube.Client.Tests.Infra; using static SonarQube.Client.Tests.Infra.MocksHelper; @@ -34,10 +35,15 @@ namespace SonarQube.Client.Tests.Requests.Api.V7_20 [TestClass] public class GetIssuesRequestWrapperTests { - [TestMethod] - public async Task InvokeAsync_NoIssueKeys_ExpectedPropertiesArePassedInMultipleRequests() + private const string SonarQubeComponentPropertyName = "components"; + private const string SonarCloudComponentPropertyName = "componentKeys"; + + [DataTestMethod] + [DataRow(SonarQubeComponentPropertyName, DisplayName = "SonarQube")] + [DataRow(SonarCloudComponentPropertyName, DisplayName = "SonarCloud")] + public async Task InvokeAsync_SonarQube_NoIssueKeys_ExpectedPropertiesArePassedInMultipleRequests(string componentPropertyName) { - var testSubject = CreateTestSubject("aaaProject", "xStatus", "yBranch", null, "rule1", "project1"); + var testSubject = CreateTestSubject(componentPropertyName, "aaaProject", "xStatus", "yBranch", null, "rule1", "project1"); var handlerMock = new Mock(MockBehavior.Strict); var httpClient = new HttpClient(handlerMock.Object) @@ -51,15 +57,18 @@ public async Task InvokeAsync_NoIssueKeys_ExpectedPropertiesArePassedInMultipleR // The wrapper is expected to make three calls, for code smells, bugs, then vulnerabilities handlerMock.Invocations.Count.Should().Be(3); - CheckExpectedQueryStringsParameters(handlerMock, 0, "aaaProject", "xStatus", "yBranch", "CODE_SMELL", "rule1", "project1"); - CheckExpectedQueryStringsParameters(handlerMock, 1, "aaaProject", "xStatus", "yBranch", "BUG", "rule1", "project1"); - CheckExpectedQueryStringsParameters(handlerMock, 2, "aaaProject", "xStatus", "yBranch", "VULNERABILITY", "rule1", "project1"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, "aaaProject", "xStatus", "yBranch", "rule1", "project1", expectedTypes: "CODE_SMELL"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 1, "aaaProject", "xStatus", "yBranch", "rule1", "project1", expectedTypes: "BUG"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 2, "aaaProject", "xStatus", "yBranch", "rule1", "project1", expectedTypes: "VULNERABILITY"); } - [TestMethod] - public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleRequest() + [DataTestMethod] + [DataRow(SonarQubeComponentPropertyName, DisplayName = "SonarQube")] + [DataRow(SonarCloudComponentPropertyName, DisplayName = "SonarCloud")] + public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleRequest(string componentPropertyName) { - var testSubject = CreateTestSubject("aaaProject", "xStatus", "yBranch", new[] { "issue1", "issue2" }, "rule1", "project1"); + var issueKeys = new[] { "issue1", "issue2" }; + var testSubject = CreateTestSubject(componentPropertyName,"aaaProject", "xStatus", "yBranch", issueKeys, "rule1", "project1"); var handlerMock = new Mock(MockBehavior.Strict); var httpClient = new HttpClient(handlerMock.Object) @@ -74,44 +83,76 @@ public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleR // The wrapper is expected to make one call with the given issueKeys handlerMock.Invocations.Count.Should().Be(1); - var actualQueryString = GetActualQueryStringForInvocation(handlerMock, 0); - actualQueryString.Contains("?projects=aaaProject").Should().BeTrue(); - actualQueryString.Contains("&statuses=xStatus&").Should().BeTrue(); - actualQueryString.Contains("&branch=yBranch&").Should().BeTrue(); - actualQueryString.Contains("&issues=issue1%2Cissue2&").Should().BeTrue(); - actualQueryString.Contains("&rules=rule1").Should().BeTrue(); - actualQueryString.Contains("&components=project1").Should().BeTrue(); - actualQueryString.Contains("types").Should().BeFalse(); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, "aaaProject", "xStatus", "yBranch", "rule1", "project1", expectedKeys: issueKeys); } - private static GetIssuesRequestWrapper CreateTestSubject(string projectKey, string statusesToRequest, string branch, string[] issueKeys, string ruleId, string componentKey) + private static IGetIssuesRequest CreateTestSubject(string componentPropertyName, string projectKey, string statusesToRequest, string branch, string[] issueKeys, string ruleId, string componentKey) { - var testSubject = new GetIssuesRequestWrapper + return componentPropertyName switch { - Logger = new TestLogger(), - ProjectKey = projectKey, - Statuses = statusesToRequest, - Branch = branch, - IssueKeys = issueKeys, - RuleId = ruleId, - ComponentKey = componentKey + SonarQubeComponentPropertyName => new GetIssuesRequestWrapper + { + Logger = new TestLogger(), + ProjectKey = projectKey, + Statuses = statusesToRequest, + Branch = branch, + IssueKeys = issueKeys, + RuleId = ruleId, + ComponentKey = componentKey + }, + SonarCloudComponentPropertyName => new GetIssuesRequestWrapper + { + Logger = new TestLogger(), + ProjectKey = projectKey, + Statuses = statusesToRequest, + Branch = branch, + IssueKeys = issueKeys, + RuleId = ruleId, + ComponentKey = componentKey + }, + _ => throw new ArgumentOutOfRangeException() }; - - return testSubject; } - private static void CheckExpectedQueryStringsParameters(Mock handlerMock, int invocationIndex, - string expectedProject, string expectedStatues, string expectedBranch, string expectedTypes, string expectedRule, string expectedComponent) + private static void CheckExpectedQueryStringsParameters(string componentKeyName, + Mock handlerMock, + int invocationIndex, + string expectedProject, + string expectedStatues, + string expectedBranch, + string expectedRule, + string expectedComponent, + string expectedTypes = null, + string[] expectedKeys = null) { var actualQueryString = GetActualQueryStringForInvocation(handlerMock, invocationIndex); Console.WriteLine($"Invocation [{invocationIndex}]: {actualQueryString}"); - actualQueryString.Contains($"?projects={expectedProject}").Should().BeTrue(); - actualQueryString.Contains($"&statuses={expectedStatues}&").Should().BeTrue(); - actualQueryString.Contains($"&branch={expectedBranch}&").Should().BeTrue(); - actualQueryString.Contains($"&types={expectedTypes}&").Should().BeTrue(); - actualQueryString.Contains($"&rules={expectedRule}&").Should().BeTrue(); - actualQueryString.Contains($"&components={expectedComponent}&").Should().BeTrue(); + actualQueryString.Contains($"?{componentKeyName}={expectedComponent}").Should().BeTrue(); + actualQueryString.Contains($"&projects={expectedProject}").Should().BeTrue(); + actualQueryString.Contains($"&statuses={expectedStatues}").Should().BeTrue(); + actualQueryString.Contains($"&branch={expectedBranch}").Should().BeTrue(); + actualQueryString.Contains($"&rules={expectedRule}").Should().BeTrue(); + + if (expectedTypes != null) + { + actualQueryString.Contains($"&types={expectedTypes}").Should().BeTrue(); + } + else + { + actualQueryString.Contains("types").Should().BeFalse(); + } + + if (expectedKeys != null) + { + var keys = string.Join("%2C", expectedKeys); + actualQueryString.Contains($"&issues={keys}").Should().BeTrue(); + } + else + { + actualQueryString.Contains("issues").Should().BeFalse(); + } + } private static string GetActualQueryStringForInvocation(Mock handlerMock, int invocationIndex) diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarCloudRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarCloudRequestTests.cs new file mode 100644 index 0000000000..9596ad27d8 --- /dev/null +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarCloudRequestTests.cs @@ -0,0 +1,92 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SonarQube.Client.Api.V7_20; +using SonarQube.Client.Tests.Infra; +using static SonarQube.Client.Tests.Infra.MocksHelper; + +namespace SonarQube.Client.Tests.Requests.Api.V7_20; + +[TestClass] +public class GetIssuesSonarCloudRequestTests +{ + [TestMethod] + public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedInQueryString() + { + var testSubject = CreateTestSubject("any", "any", componentKey: null); + + var handlerMock = new Mock(); + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri(ValidBaseAddress) + }; + + SetupHttpRequest(handlerMock, EmptyGetIssuesResponse); + _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); + + var actualQueryString = GetSingleActualQueryString(handlerMock); + actualQueryString.Contains("components").Should().BeFalse(); + } + + [TestMethod] + public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQueryString() + { + var testSubject = CreateTestSubject("any", "any", componentKey: "project1"); + + var handlerMock = new Mock(); + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri(ValidBaseAddress) + }; + + SetupHttpRequest(handlerMock, EmptyGetIssuesResponse); + _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); + + var actualQueryString = GetSingleActualQueryString(handlerMock); + actualQueryString.Contains("componentKeys=project1").Should().BeTrue(); + } + + private static GetIssuesWithComponentSonarCloudRequest CreateTestSubject(string projectKey, string statusesToRequest, string componentKey = null) + { + var testSubject = new GetIssuesWithComponentSonarCloudRequest + { + Logger = new TestLogger(), + ProjectKey = projectKey, + Statuses = statusesToRequest, + ComponentKey = componentKey + }; + + return testSubject; + } + + private static string GetSingleActualQueryString(Mock handlerMock) + { + handlerMock.Invocations.Count.Should().Be(1); + var requestMessage = (HttpRequestMessage)handlerMock.Invocations[0].Arguments[0]; + return requestMessage.RequestUri.Query; + } +} diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarQubeRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarQubeRequestTests.cs new file mode 100644 index 0000000000..9d1cba0fc0 --- /dev/null +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarQubeRequestTests.cs @@ -0,0 +1,92 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SonarQube.Client.Api.V7_20; +using SonarQube.Client.Tests.Infra; +using static SonarQube.Client.Tests.Infra.MocksHelper; + +namespace SonarQube.Client.Tests.Requests.Api.V7_20; + +[TestClass] +public class GetIssuesSonarQubeRequestTests +{ + [TestMethod] + public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedInQueryString() + { + var testSubject = CreateTestSubject("any", "any", componentKey: null); + + var handlerMock = new Mock(); + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri(ValidBaseAddress) + }; + + SetupHttpRequest(handlerMock, EmptyGetIssuesResponse); + _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); + + var actualQueryString = GetSingleActualQueryString(handlerMock); + actualQueryString.Contains("components").Should().BeFalse(); + } + + [TestMethod] + public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQueryString() + { + var testSubject = CreateTestSubject("any", "any", componentKey: "project1"); + + var handlerMock = new Mock(); + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri(ValidBaseAddress) + }; + + SetupHttpRequest(handlerMock, EmptyGetIssuesResponse); + _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); + + var actualQueryString = GetSingleActualQueryString(handlerMock); + actualQueryString.Contains("components=project1").Should().BeTrue(); + } + + private static GetIssuesWithComponentSonarQubeRequest CreateTestSubject(string projectKey, string statusesToRequest, string componentKey = null) + { + var testSubject = new GetIssuesWithComponentSonarQubeRequest + { + Logger = new TestLogger(), + ProjectKey = projectKey, + Statuses = statusesToRequest, + ComponentKey = componentKey + }; + + return testSubject; + } + + private static string GetSingleActualQueryString(Mock handlerMock) + { + handlerMock.Invocations.Count.Should().Be(1); + var requestMessage = (HttpRequestMessage)handlerMock.Invocations[0].Arguments[0]; + return requestMessage.RequestUri.Query; + } +} diff --git a/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure.cs b/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs similarity index 98% rename from src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure.cs rename to src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs index 85244a231d..b5d4f3be9a 100644 --- a/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure.cs +++ b/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs @@ -20,6 +20,7 @@ using System; using System.Diagnostics; +using System.Linq; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using SonarQube.Client.Api; @@ -29,7 +30,7 @@ namespace SonarQube.Client.Tests.Requests { [TestClass] - public class DefaultConfiguration_Configure + public class DefaultConfiguration_Configure_Tests { [TestMethod] public void ConfigureSonarQube_Writes_Debug_Messages() @@ -62,7 +63,7 @@ public void ConfigureSonarQube_Writes_Debug_Messages() "Registered SonarQube.Client.Api.V6_60.GetRoslynExportProfileRequest for 6.6", "Registered SonarQube.Client.Api.V6_60.GetProjectBranchesRequest for 6.6", "Registered SonarQube.Client.Api.V7_00.GetOrganizationsRequest for 7.0", - "Registered SonarQube.Client.Api.V7_20.GetIssuesRequestWrapper for 7.2", + "Registered SonarQube.Client.Api.V7_20.GetIssuesRequestWrapper`1[SonarQube.Client.Api.V7_20.GetIssuesWithComponentSonarQubeRequest] for 7.2", "Registered SonarQube.Client.Api.V8_6.GetHotspotRequest for 8.6", "Registered SonarQube.Client.Api.V8_6.GetTaintVulnerabilitiesRequest for 8.6", "Registered SonarQube.Client.Api.V7_20.GetExclusionsRequest for 7.2", @@ -111,7 +112,7 @@ public void ConfigureSonarCloud_Writes_Debug_Messages() "Registered SonarQube.Client.Api.V6_60.GetRoslynExportProfileRequest", "Registered SonarQube.Client.Api.V6_60.GetProjectBranchesRequest", "Registered SonarQube.Client.Api.V7_00.GetOrganizationsRequest", - "Registered SonarQube.Client.Api.V7_20.GetIssuesRequestWrapper", + "Registered SonarQube.Client.Api.V7_20.GetIssuesRequestWrapper`1[SonarQube.Client.Api.V7_20.GetIssuesWithComponentSonarCloudRequest]", "Registered SonarQube.Client.Api.V8_6.GetHotspotRequest", "Registered SonarQube.Client.Api.V10_2.GetTaintVulnerabilitiesWithCCTRequest", "Registered SonarQube.Client.Api.V7_20.GetExclusionsRequest", diff --git a/src/SonarQube.Client.Tests/SonarQubeService_GetIssuesBase.cs b/src/SonarQube.Client.Tests/SonarQubeService_GetIssuesBase.cs index 85509d84c6..31963575c6 100644 --- a/src/SonarQube.Client.Tests/SonarQubeService_GetIssuesBase.cs +++ b/src/SonarQube.Client.Tests/SonarQubeService_GetIssuesBase.cs @@ -77,7 +77,7 @@ protected void SetupPageOfResponses(string projectName, string ruleId, string co componentJson = CreateComponentJson(); } - SetupRequest($"api/issues/search?projects={projectName}&rules={ruleId}&components={componentKey}&branch={branch}&types={issueType}&p={pageNumber}&ps={PageSize}", $@" + SetupRequest($"api/issues/search?components={componentKey}&projects={projectName}&rules={ruleId}&branch={branch}&types={issueType}&p={pageNumber}&ps={PageSize}", $@" {{ ""paging"": {{ ""pageIndex"": {pageNumber}, diff --git a/src/SonarQube.Client/Api/DefaultConfiguration.cs b/src/SonarQube.Client/Api/DefaultConfiguration.cs index 100c150204..7c098a06c1 100644 --- a/src/SonarQube.Client/Api/DefaultConfiguration.cs +++ b/src/SonarQube.Client/Api/DefaultConfiguration.cs @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +using SonarQube.Client.Api.V7_20; using SonarQube.Client.Requests; namespace SonarQube.Client.Api @@ -51,7 +52,7 @@ public static RequestFactory ConfigureSonarQube(RequestFactory requestFactory) .RegisterRequest("6.6") .RegisterRequest("6.6") .RegisterRequest("7.0") - .RegisterRequest("7.2") + .RegisterRequest>("7.2") .RegisterRequest("8.6") .RegisterRequest("8.6") .RegisterRequest("7.2") @@ -90,7 +91,7 @@ public static UnversionedRequestFactory ConfigureSonarCloud(UnversionedRequestFa .RegisterRequest() .RegisterRequest() .RegisterRequest() - .RegisterRequest() + .RegisterRequest>() .RegisterRequest() .RegisterRequest() .RegisterRequest() diff --git a/src/SonarQube.Client/Api/V10_2/GetIssuesWithCCTRequest.cs b/src/SonarQube.Client/Api/V10_2/GetIssuesWithCCTRequest.cs index 6c3e03769d..0b7ceee283 100644 --- a/src/SonarQube.Client/Api/V10_2/GetIssuesWithCCTRequest.cs +++ b/src/SonarQube.Client/Api/V10_2/GetIssuesWithCCTRequest.cs @@ -22,13 +22,17 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SonarQube.Client.Api.Common; +using SonarQube.Client.Api.V7_20; using SonarQube.Client.Api.V9_6; using SonarQube.Client.Helpers; using SonarQube.Client.Models; namespace SonarQube.Client.Api.V10_2 { - public class GetIssuesWithCCTRequest : GetIssuesWithContextRequest + /// + /// This class does not support component-based search. See for more information + /// + internal class GetIssuesWithCCTRequest : GetIssuesWithContextRequest { protected override SonarQubeIssue[] ParseResponse(string response) { diff --git a/src/SonarQube.Client/Api/V5_10/GetIssuesRequest.cs b/src/SonarQube.Client/Api/V5_10/GetIssuesRequest.cs index 4451538f48..699e7064a5 100644 --- a/src/SonarQube.Client/Api/V5_10/GetIssuesRequest.cs +++ b/src/SonarQube.Client/Api/V5_10/GetIssuesRequest.cs @@ -56,8 +56,10 @@ public string Statuses protected override string Path => "batch/issues"; + [JsonIgnore] // We decided not to support it for API calls older than v7.20 public string RuleId { get; set; } + [JsonIgnore] // We decided not to support it for API calls older than v7.20 public string ComponentKey { get; set; } [JsonIgnore] diff --git a/src/SonarQube.Client/Api/V7_20/GetIssuesRequest.cs b/src/SonarQube.Client/Api/V7_20/GetIssuesRequest.cs index 0c53815a64..f6b0d57c5e 100644 --- a/src/SonarQube.Client/Api/V7_20/GetIssuesRequest.cs +++ b/src/SonarQube.Client/Api/V7_20/GetIssuesRequest.cs @@ -31,7 +31,11 @@ namespace SonarQube.Client.Api.V7_20 { - public class GetIssuesRequest : PagedRequestBase, IGetIssuesRequest + /// + /// Generic get issues class. It does not support as it is server-type-specific. + /// See and for more details. + /// + internal class GetIssuesRequest : PagedRequestBase { [JsonProperty("projects")] public virtual string ProjectKey { get; set; } @@ -50,9 +54,6 @@ public class GetIssuesRequest : PagedRequestBase, IGetIssuesRequ [JsonProperty("rules")] public string RuleId { get; set; } - [JsonProperty("components")] - public string ComponentKey { get; set; } - [JsonIgnore] public bool IncludeTaint { get; set; } = true; diff --git a/src/SonarQube.Client/Api/V7_20/GetIssuesRequestWrapper.cs b/src/SonarQube.Client/Api/V7_20/GetIssuesRequestWrapper.cs index b66f3451f2..8c44b38718 100644 --- a/src/SonarQube.Client/Api/V7_20/GetIssuesRequestWrapper.cs +++ b/src/SonarQube.Client/Api/V7_20/GetIssuesRequestWrapper.cs @@ -39,9 +39,10 @@ namespace SonarQube.Client.Api.V7_20 /// /// This class should be removed if/when SonarQube removes the 10k API result limitation. /// - public class GetIssuesRequestWrapper : IGetIssuesRequest + internal class GetIssuesRequestWrapper : IGetIssuesRequest + where T : GetIssuesWithComponentRequest, new() { - private readonly GetIssuesRequest innerRequest = new GetIssuesRequest(); + private readonly T innerRequest = new T(); public string ProjectKey { get; set; } diff --git a/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs b/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs new file mode 100644 index 0000000000..ebe2dba6e2 --- /dev/null +++ b/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs @@ -0,0 +1,56 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using Newtonsoft.Json; + +namespace SonarQube.Client.Api.V7_20 +{ + internal class GetIssuesWithComponentRequest : GetIssuesRequest + { + // this class should not be used on it's own + private protected GetIssuesWithComponentRequest(){} + + public virtual string ComponentKey { get; set; } + } + + /// + /// This class is used to override the query string property name for for + /// + /// + /// Reason to create this class https://github.com/SonarSource/sonarlint-visualstudio/issues/5181 + /// + internal class GetIssuesWithComponentSonarCloudRequest : GetIssuesWithComponentRequest, IGetIssuesRequest + { + [JsonProperty("componentKeys")] + public override string ComponentKey { get; set; } + } + + /// + /// This class is used to override the query string property name for for + /// + /// + /// Reason to create this class https://github.com/SonarSource/sonarlint-visualstudio/issues/5181 + /// + internal class GetIssuesWithComponentSonarQubeRequest : GetIssuesWithComponentRequest, IGetIssuesRequest + { + [JsonProperty("components")] + public override string ComponentKey { get; set; } + } +} diff --git a/src/SonarQube.Client/Api/V8_6/GetTaintVulnerabilitiesRequest.cs b/src/SonarQube.Client/Api/V8_6/GetTaintVulnerabilitiesRequest.cs index cd6cd513e7..30b0b41fac 100644 --- a/src/SonarQube.Client/Api/V8_6/GetTaintVulnerabilitiesRequest.cs +++ b/src/SonarQube.Client/Api/V8_6/GetTaintVulnerabilitiesRequest.cs @@ -28,7 +28,7 @@ namespace SonarQube.Client.Api.V8_6 { - public class GetTaintVulnerabilitiesRequest : IGetTaintVulnerabilitiesRequest + internal class GetTaintVulnerabilitiesRequest : IGetTaintVulnerabilitiesRequest { protected GetIssuesRequest getIssuesRequest = new GetIssuesRequest(); diff --git a/src/SonarQube.Client/Api/V9_6/GetIssuesWithContextRequest.cs b/src/SonarQube.Client/Api/V9_6/GetIssuesWithContextRequest.cs index def7e33298..e66c094eb0 100644 --- a/src/SonarQube.Client/Api/V9_6/GetIssuesWithContextRequest.cs +++ b/src/SonarQube.Client/Api/V9_6/GetIssuesWithContextRequest.cs @@ -23,7 +23,10 @@ namespace SonarQube.Client.Api.V9_6 { - public class GetIssuesWithContextRequest : GetIssuesRequest + /// + /// This class does not support component-based search. See for more information + /// + internal class GetIssuesWithContextRequest : GetIssuesRequest { [JsonProperty("additionalFields")] public string AdditionalFields => "ruleDescriptionContextKey"; diff --git a/src/SonarQube.Client/Api/V9_6/GetTaintVulnerabilitiesWithContextRequest.cs b/src/SonarQube.Client/Api/V9_6/GetTaintVulnerabilitiesWithContextRequest.cs index 85114035aa..ebecb3993d 100644 --- a/src/SonarQube.Client/Api/V9_6/GetTaintVulnerabilitiesWithContextRequest.cs +++ b/src/SonarQube.Client/Api/V9_6/GetTaintVulnerabilitiesWithContextRequest.cs @@ -26,7 +26,7 @@ namespace SonarQube.Client.Api.V9_6 { - public class GetTaintVulnerabilitiesWithContextRequest : GetTaintVulnerabilitiesRequest + internal class GetTaintVulnerabilitiesWithContextRequest : GetTaintVulnerabilitiesRequest { public override async Task InvokeAsync(HttpClient httpClient, CancellationToken token) { diff --git a/src/SonarQube.Client/Requests/RequestFactory.cs b/src/SonarQube.Client/Requests/RequestFactory.cs index 8a816eb8f0..486ae2e881 100644 --- a/src/SonarQube.Client/Requests/RequestFactory.cs +++ b/src/SonarQube.Client/Requests/RequestFactory.cs @@ -61,7 +61,7 @@ public RequestFactory RegisterRequest(string version) return RegisterRequest(version, () => new TRequestImpl()); } - private RequestFactory RegisterRequest(string version, Func factory) + public RequestFactory RegisterRequest(string version, Func factory) where TRequest : IRequest where TRequestImpl : TRequest { @@ -85,7 +85,7 @@ private RequestFactory RegisterRequest(string version, F } versionRequestMap[parsedVersion] = () => factory(); - logger.Debug($"Registered {typeof(TRequestImpl).FullName} for {parsedVersion}"); + logger.Debug($"Registered {typeof(TRequestImpl)} for {parsedVersion}"); return this; } @@ -117,7 +117,7 @@ public TRequest Create(ServerInfo serverInfo) var request = (TRequest)factory(); request.Logger = logger; - logger.Debug($"Created request of type '{request.GetType().FullName}'."); + logger.Debug($"Created request of type '{request.GetType()}'."); return request; } diff --git a/src/SonarQube.Client/Requests/UnversionedRequestFactory.cs b/src/SonarQube.Client/Requests/UnversionedRequestFactory.cs index ea8cf38b6a..001f7ea94b 100644 --- a/src/SonarQube.Client/Requests/UnversionedRequestFactory.cs +++ b/src/SonarQube.Client/Requests/UnversionedRequestFactory.cs @@ -58,7 +58,7 @@ public UnversionedRequestFactory RegisterRequest() } requestToFactoryMap[typeof(TRequest)] = () => new TRequestImpl(); - logger.Debug($"Registered {typeof(TRequestImpl).FullName}"); + logger.Debug($"Registered {typeof(TRequestImpl)}"); return this; } @@ -72,7 +72,7 @@ public TRequest Create(ServerInfo serverInfo) where TRequest : IReques var request = (TRequest)factory(); request.Logger = logger; - logger.Debug($"Created request of type '{request.GetType().FullName}'."); + logger.Debug($"Created request of type '{request.GetType()}'."); return request; } From 2cf254ca0254595df5cb2328f354e51505c07685 Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh Date: Fri, 19 Jan 2024 13:56:32 +0100 Subject: [PATCH 2/4] Fix CR issues --- .../Api/V7_20/GetIssuesRequestTests.cs | 4 +- .../Api/V7_20/GetIssuesRequestWrapperTests.cs | 45 +++++++++---------- ...uesWithComponentSonarCloudRequestTests.cs} | 6 +-- ...suesWithComponentSonarQubeRequestTests.cs} | 6 +-- .../DefaultConfiguration_Configure_Tests.cs | 1 - .../Api/DefaultConfiguration.cs | 5 +-- .../V7_20/GetIssuesWithComponentRequest.cs | 10 ++--- .../Requests/RequestFactory.cs | 2 +- 8 files changed, 35 insertions(+), 44 deletions(-) rename src/SonarQube.Client.Tests/Requests/Api/V7_20/{GetIssuesSonarCloudRequestTests.cs => GetIssuesWithComponentSonarCloudRequestTests.cs} (94%) rename src/SonarQube.Client.Tests/Requests/Api/V7_20/{GetIssuesSonarQubeRequestTests.cs => GetIssuesWithComponentSonarQubeRequestTests.cs} (94%) diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs index 236004ebef..ff109b4bab 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs @@ -444,7 +444,7 @@ public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedI _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("components").Should().BeFalse(); + actualQueryString.Should().Contain("component"); } [TestMethod] @@ -462,7 +462,7 @@ public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreNotIncludedInQu _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("components=project1").Should().BeFalse(); + actualQueryString.Should().Contain("component"); } private static GetIssuesRequest CreateTestSubject(string projectKey, string statusesToRequest, string branch = null, string[] issueKeys = null, string ruleId = null, string componentKey = null) diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs index a32a6b4000..fb3465b55f 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs @@ -35,15 +35,15 @@ namespace SonarQube.Client.Tests.Requests.Api.V7_20 [TestClass] public class GetIssuesRequestWrapperTests { - private const string SonarQubeComponentPropertyName = "components"; - private const string SonarCloudComponentPropertyName = "componentKeys"; + private const string ComponentPropertyNameSonarQube = "components"; + private const string ComponentPropertyNameSonarCloud = "componentKeys"; [DataTestMethod] - [DataRow(SonarQubeComponentPropertyName, DisplayName = "SonarQube")] - [DataRow(SonarCloudComponentPropertyName, DisplayName = "SonarCloud")] - public async Task InvokeAsync_SonarQube_NoIssueKeys_ExpectedPropertiesArePassedInMultipleRequests(string componentPropertyName) + [DataRow(ComponentPropertyNameSonarQube, DisplayName = "SonarQube")] + [DataRow(ComponentPropertyNameSonarCloud, DisplayName = "SonarCloud")] + public async Task InvokeAsync_NoIssueKeys_ExpectedPropertiesArePassedInMultipleRequests(string componentPropertyName) { - var testSubject = CreateTestSubject(componentPropertyName, "aaaProject", "xStatus", "yBranch", null, "rule1", "project1"); + var testSubject = CreateTestSubject(componentPropertyName, "aaaProject", "xStatus", "yBranch", null, "rule1", "component1"); var handlerMock = new Mock(MockBehavior.Strict); var httpClient = new HttpClient(handlerMock.Object) @@ -57,18 +57,18 @@ public async Task InvokeAsync_SonarQube_NoIssueKeys_ExpectedPropertiesArePassedI // The wrapper is expected to make three calls, for code smells, bugs, then vulnerabilities handlerMock.Invocations.Count.Should().Be(3); - CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, "aaaProject", "xStatus", "yBranch", "rule1", "project1", expectedTypes: "CODE_SMELL"); - CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 1, "aaaProject", "xStatus", "yBranch", "rule1", "project1", expectedTypes: "BUG"); - CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 2, "aaaProject", "xStatus", "yBranch", "rule1", "project1", expectedTypes: "VULNERABILITY"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, expectedTypes: "CODE_SMELL"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 1, expectedTypes: "BUG"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 2, expectedTypes: "VULNERABILITY"); } [DataTestMethod] - [DataRow(SonarQubeComponentPropertyName, DisplayName = "SonarQube")] - [DataRow(SonarCloudComponentPropertyName, DisplayName = "SonarCloud")] + [DataRow(ComponentPropertyNameSonarQube, DisplayName = "SonarQube")] + [DataRow(ComponentPropertyNameSonarCloud, DisplayName = "SonarCloud")] public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleRequest(string componentPropertyName) { var issueKeys = new[] { "issue1", "issue2" }; - var testSubject = CreateTestSubject(componentPropertyName,"aaaProject", "xStatus", "yBranch", issueKeys, "rule1", "project1"); + var testSubject = CreateTestSubject(componentPropertyName,"aaaProject", "xStatus", "yBranch", issueKeys, "rule1", "component1"); var handlerMock = new Mock(MockBehavior.Strict); var httpClient = new HttpClient(handlerMock.Object) @@ -83,14 +83,14 @@ public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleR // The wrapper is expected to make one call with the given issueKeys handlerMock.Invocations.Count.Should().Be(1); - CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, "aaaProject", "xStatus", "yBranch", "rule1", "project1", expectedKeys: issueKeys); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, expectedKeys: issueKeys); } private static IGetIssuesRequest CreateTestSubject(string componentPropertyName, string projectKey, string statusesToRequest, string branch, string[] issueKeys, string ruleId, string componentKey) { return componentPropertyName switch { - SonarQubeComponentPropertyName => new GetIssuesRequestWrapper + ComponentPropertyNameSonarQube => new GetIssuesRequestWrapper { Logger = new TestLogger(), ProjectKey = projectKey, @@ -100,7 +100,7 @@ private static IGetIssuesRequest CreateTestSubject(string componentPropertyName, RuleId = ruleId, ComponentKey = componentKey }, - SonarCloudComponentPropertyName => new GetIssuesRequestWrapper + ComponentPropertyNameSonarCloud => new GetIssuesRequestWrapper { Logger = new TestLogger(), ProjectKey = projectKey, @@ -117,22 +117,17 @@ private static IGetIssuesRequest CreateTestSubject(string componentPropertyName, private static void CheckExpectedQueryStringsParameters(string componentKeyName, Mock handlerMock, int invocationIndex, - string expectedProject, - string expectedStatues, - string expectedBranch, - string expectedRule, - string expectedComponent, string expectedTypes = null, string[] expectedKeys = null) { var actualQueryString = GetActualQueryStringForInvocation(handlerMock, invocationIndex); Console.WriteLine($"Invocation [{invocationIndex}]: {actualQueryString}"); - actualQueryString.Contains($"?{componentKeyName}={expectedComponent}").Should().BeTrue(); - actualQueryString.Contains($"&projects={expectedProject}").Should().BeTrue(); - actualQueryString.Contains($"&statuses={expectedStatues}").Should().BeTrue(); - actualQueryString.Contains($"&branch={expectedBranch}").Should().BeTrue(); - actualQueryString.Contains($"&rules={expectedRule}").Should().BeTrue(); + actualQueryString.Contains($"?{componentKeyName}=component1").Should().BeTrue(); + actualQueryString.Contains("&projects=aaaProject").Should().BeTrue(); + actualQueryString.Contains("&statuses=xStatus").Should().BeTrue(); + actualQueryString.Contains("&branch=yBranch").Should().BeTrue(); + actualQueryString.Contains("&rules=rule1").Should().BeTrue(); if (expectedTypes != null) { diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarCloudRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs similarity index 94% rename from src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarCloudRequestTests.cs rename to src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs index 9596ad27d8..ce3a0f7050 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarCloudRequestTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs @@ -32,7 +32,7 @@ namespace SonarQube.Client.Tests.Requests.Api.V7_20; [TestClass] -public class GetIssuesSonarCloudRequestTests +public class GetIssuesWithComponentSonarCloudRequestTests { [TestMethod] public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedInQueryString() @@ -49,7 +49,7 @@ public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedI _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("components").Should().BeFalse(); + actualQueryString.Should().Contain("component"); } [TestMethod] @@ -67,7 +67,7 @@ public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQuery _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("componentKeys=project1").Should().BeTrue(); + actualQueryString.Should().Contain("componentKeys=project1"); } private static GetIssuesWithComponentSonarCloudRequest CreateTestSubject(string projectKey, string statusesToRequest, string componentKey = null) diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarQubeRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs similarity index 94% rename from src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarQubeRequestTests.cs rename to src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs index 9d1cba0fc0..bd1298d448 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesSonarQubeRequestTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs @@ -32,7 +32,7 @@ namespace SonarQube.Client.Tests.Requests.Api.V7_20; [TestClass] -public class GetIssuesSonarQubeRequestTests +public class GetIssuesWithComponentSonarQubeRequestTests { [TestMethod] public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedInQueryString() @@ -49,7 +49,7 @@ public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedI _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("components").Should().BeFalse(); + actualQueryString.Should().Contain("component"); } [TestMethod] @@ -67,7 +67,7 @@ public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQuery _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("components=project1").Should().BeTrue(); + actualQueryString.Should().Contain("components=project1"); } private static GetIssuesWithComponentSonarQubeRequest CreateTestSubject(string projectKey, string statusesToRequest, string componentKey = null) diff --git a/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs b/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs index b5d4f3be9a..2405cbe246 100644 --- a/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs +++ b/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs @@ -20,7 +20,6 @@ using System; using System.Diagnostics; -using System.Linq; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using SonarQube.Client.Api; diff --git a/src/SonarQube.Client/Api/DefaultConfiguration.cs b/src/SonarQube.Client/Api/DefaultConfiguration.cs index 7c098a06c1..638088b768 100644 --- a/src/SonarQube.Client/Api/DefaultConfiguration.cs +++ b/src/SonarQube.Client/Api/DefaultConfiguration.cs @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -using SonarQube.Client.Api.V7_20; using SonarQube.Client.Requests; namespace SonarQube.Client.Api @@ -52,7 +51,7 @@ public static RequestFactory ConfigureSonarQube(RequestFactory requestFactory) .RegisterRequest("6.6") .RegisterRequest("6.6") .RegisterRequest("7.0") - .RegisterRequest>("7.2") + .RegisterRequest>("7.2") .RegisterRequest("8.6") .RegisterRequest("8.6") .RegisterRequest("7.2") @@ -91,7 +90,7 @@ public static UnversionedRequestFactory ConfigureSonarCloud(UnversionedRequestFa .RegisterRequest() .RegisterRequest() .RegisterRequest() - .RegisterRequest>() + .RegisterRequest>() .RegisterRequest() .RegisterRequest() .RegisterRequest() diff --git a/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs b/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs index ebe2dba6e2..e4faf7ec5b 100644 --- a/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs +++ b/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs @@ -22,14 +22,12 @@ namespace SonarQube.Client.Api.V7_20 { - internal class GetIssuesWithComponentRequest : GetIssuesRequest + // This class should not be used on it's own + internal abstract class GetIssuesWithComponentRequest : GetIssuesRequest { - // this class should not be used on it's own - private protected GetIssuesWithComponentRequest(){} - - public virtual string ComponentKey { get; set; } + public abstract string ComponentKey { get; set; } } - + /// /// This class is used to override the query string property name for for /// diff --git a/src/SonarQube.Client/Requests/RequestFactory.cs b/src/SonarQube.Client/Requests/RequestFactory.cs index 486ae2e881..611d838263 100644 --- a/src/SonarQube.Client/Requests/RequestFactory.cs +++ b/src/SonarQube.Client/Requests/RequestFactory.cs @@ -61,7 +61,7 @@ public RequestFactory RegisterRequest(string version) return RegisterRequest(version, () => new TRequestImpl()); } - public RequestFactory RegisterRequest(string version, Func factory) + private RequestFactory RegisterRequest(string version, Func factory) where TRequest : IRequest where TRequestImpl : TRequest { From a65cca7a04ec4d0a03e97b8727af796968cf2ba2 Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh Date: Fri, 19 Jan 2024 14:16:16 +0100 Subject: [PATCH 3/4] Fix tests --- .../Requests/Api/V7_20/GetIssuesRequestTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs index ff109b4bab..b0203f0141 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs @@ -444,7 +444,7 @@ public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedI _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Should().Contain("component"); + actualQueryString.Should().NotContain("component"); } [TestMethod] @@ -462,7 +462,7 @@ public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreNotIncludedInQu _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Should().Contain("component"); + actualQueryString.Should().NotContain("component"); } private static GetIssuesRequest CreateTestSubject(string projectKey, string statusesToRequest, string branch = null, string[] issueKeys = null, string ruleId = null, string componentKey = null) From 4ddb5844bb8888d881a7fc10119dccd89f807a7c Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh Date: Fri, 19 Jan 2024 14:30:58 +0100 Subject: [PATCH 4/4] Fix tests --- .../Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs | 2 +- .../Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs index ce3a0f7050..ed25c5fe0f 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs @@ -49,7 +49,7 @@ public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedI _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Should().Contain("component"); + actualQueryString.Should().NotContain("component"); } [TestMethod] diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs index bd1298d448..4c8620c582 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs @@ -49,7 +49,7 @@ public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedI _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Should().Contain("component"); + actualQueryString.Should().NotContain("component"); } [TestMethod]