diff --git a/its/org.sonarlint.eclipse.its.connected.sc/src/org/sonarlint/eclipse/its/connected/sc/SonarCloudConnectedModeTest.java b/its/org.sonarlint.eclipse.its.connected.sc/src/org/sonarlint/eclipse/its/connected/sc/SonarCloudConnectedModeTest.java index 097abc153..128ac273c 100644 --- a/its/org.sonarlint.eclipse.its.connected.sc/src/org/sonarlint/eclipse/its/connected/sc/SonarCloudConnectedModeTest.java +++ b/its/org.sonarlint.eclipse.its.connected.sc/src/org/sonarlint/eclipse/its/connected/sc/SonarCloudConnectedModeTest.java @@ -19,24 +19,51 @@ */ package org.sonarlint.eclipse.its.connected.sc; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; import java.time.Instant; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import org.assertj.core.groups.Tuple; import org.eclipse.reddeer.common.wait.TimePeriod; import org.eclipse.reddeer.common.wait.WaitUntil; +import org.eclipse.reddeer.swt.impl.link.DefaultLink; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.sonarlint.eclipse.its.shared.AbstractSonarLintTest; +import org.sonarlint.eclipse.its.shared.reddeer.conditions.ConfirmConnectionCreationDialogOpened; import org.sonarlint.eclipse.its.shared.reddeer.conditions.DialogMessageIsExpected; +import org.sonarlint.eclipse.its.shared.reddeer.conditions.FileNotFoundDialogOpened; +import org.sonarlint.eclipse.its.shared.reddeer.conditions.FixSuggestionAvailableDialogOpened; +import org.sonarlint.eclipse.its.shared.reddeer.conditions.FixSuggestionUnavailableDialogOpened; import org.sonarlint.eclipse.its.shared.reddeer.conditions.ProjectBindingWizardIsOpened; +import org.sonarlint.eclipse.its.shared.reddeer.conditions.ProjectSelectionDialogOpened; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.ConfirmConnectionCreationDialog; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.FileNotFoundDialog; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.FixSuggestionAvailableDialog; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.FixSuggestionUnavailableDialog; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.ProjectSelectionDialog; +import org.sonarlint.eclipse.its.shared.reddeer.views.BindingsView; import org.sonarlint.eclipse.its.shared.reddeer.wizards.ProjectBindingWizard; import org.sonarlint.eclipse.its.shared.reddeer.wizards.ServerConnectionWizard; +import org.sonarqube.ws.ProjectBranches.Branch; import org.sonarqube.ws.client.HttpConnector; import org.sonarqube.ws.client.WsClient; import org.sonarqube.ws.client.WsClientFactories; +import org.sonarqube.ws.client.projectbranches.ListRequest; import org.sonarqube.ws.client.usertokens.GenerateRequest; import org.sonarqube.ws.client.usertokens.RevokeRequest; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; public class SonarCloudConnectedModeTest extends AbstractSonarLintTest { private static final String TIMESTAMP = Long.toString(Instant.now().toEpochMilli()); @@ -44,13 +71,15 @@ public class SonarCloudConnectedModeTest extends AbstractSonarLintTest { private static final String SONARCLOUD_ORGANIZATION_KEY = "sonarlint-it"; private static final String SONARCLOUD_USER = "sonarlint-it"; private static final String SONARCLOUD_PASSWORD = System.getenv("SONARCLOUD_IT_PASSWORD"); - private static final String TOKEN_NAME = "SLE-IT-" + TIMESTAMP; - private static final String CONNECTION_NAME = "connection"; + private static final String SAMPLE_JAVA_ISSUES_KEY = "sonarlint-its-sample-java-issues"; private static WsClient adminWsClient; private static String token; + private static String firstSonarCloudProjectKey; + private static String firstSonarCloudIssueKey; + private static String firstSonarCloudBranch; @BeforeClass public static void prepare() { @@ -62,6 +91,17 @@ public static void prepare() { token = adminWsClient.userTokens() .generate(new GenerateRequest().setName(TOKEN_NAME)) .getToken(); + + try { + var sonarCloudProjectKeys = getProjectKeys(); + var keyAndProject = getFirstProjectAndIssueKey(sonarCloudProjectKeys); + firstSonarCloudIssueKey = (String) keyAndProject.toList().get(0); + firstSonarCloudProjectKey = (String) keyAndProject.toList().get(1); + } catch (InterruptedException | IOException err) { + fail("Cannot query the project keys and / or first issue and project key from SonarCloud!", err); + } + + firstSonarCloudBranch = getFirstBranch(firstSonarCloudProjectKey).getName(); } @AfterClass @@ -70,6 +110,13 @@ public static void cleanupOrchestrator() { .revoke(new RevokeRequest().setName(TOKEN_NAME)); } + @Before + public void cleanBindings() { + var bindingsView = new BindingsView(); + bindingsView.open(); + bindingsView.removeAllBindings(); + } + @Test public void configureServerWithTokenAndOrganization() throws InterruptedException { var wizard = new ServerConnectionWizard(); @@ -130,4 +177,186 @@ public void configureServerWithTokenAndOrganization() throws InterruptedExceptio new ProjectBindingWizard.BoundProjectsPage(projectBindingWizard); projectBindingWizard.cancel(); } + + @Test + public void fixSuggestion_with_ConnectionSetup_noProject() throws InterruptedException, IOException { + triggerOpenFixSuggestion(firstSonarCloudProjectKey, + firstSonarCloudIssueKey, + "NotExisting.txt", + "fixSuggestion_with_ConnectionSetup_noProject", + "before", + "after", + 0, 1); + + new WaitUntil(new ConfirmConnectionCreationDialogOpened(true)); + new ConfirmConnectionCreationDialog(true).trust(); + + shellByName("SonarLint - No mathing open project found") + .ifPresent(shell -> { + new DefaultLink(shell, "Open Troubleshooting documentation").click(); + }); + } + + @Test + public void fixSuggestion_with_ConnectionSetup_fileNotFound() throws InterruptedException, IOException { + importExistingProjectIntoWorkspace("connected-sc/" + SAMPLE_JAVA_ISSUES_KEY, SAMPLE_JAVA_ISSUES_KEY); + + triggerOpenFixSuggestion(firstSonarCloudProjectKey, + firstSonarCloudIssueKey, + "NotExisting.txt", + "fixSuggestion_with_ConnectionSetup_fileNotFound", + "before", + "after", + 0, 1); + + new WaitUntil(new ConfirmConnectionCreationDialogOpened(true)); + new ConfirmConnectionCreationDialog(true).trust(); + + new WaitUntil(new ProjectSelectionDialogOpened()); + new ProjectSelectionDialog().ok(); + + new WaitUntil(new FileNotFoundDialogOpened()); + new FileNotFoundDialog().ok(); + } + + @Test + public void fixSuggestion_with_fixes() throws InterruptedException, IOException { + final var file = "FileExists.txt"; + final var explanation = "This is common knowledge!"; + final var before = "Eclipse IDE is the best!"; + final var after = "IntelliJ IDEA is not the best!"; + final var startLine = 0; + final var endLine = 1; + + importExistingProjectIntoWorkspace("connected-sc/" + SAMPLE_JAVA_ISSUES_KEY, SAMPLE_JAVA_ISSUES_KEY); + + // 1) Cancel the suggestion (available) + triggerOpenFixSuggestion(firstSonarCloudProjectKey, firstSonarCloudIssueKey, file, explanation, before, after, startLine, endLine); + + new WaitUntil(new ConfirmConnectionCreationDialogOpened(true)); + new ConfirmConnectionCreationDialog(true).trust(); + + new WaitUntil(new ProjectSelectionDialogOpened()); + new ProjectSelectionDialog().ok(); + + new WaitUntil(new FixSuggestionAvailableDialogOpened(0, 1)); + new FixSuggestionAvailableDialog(0, 1).cancel(); + + // 2) Decline the suggestion + triggerOpenFixSuggestion(firstSonarCloudProjectKey, firstSonarCloudIssueKey, file, explanation, before, after, startLine, endLine); + + new WaitUntil(new FixSuggestionAvailableDialogOpened(0, 1)); + new FixSuggestionAvailableDialog(0, 1).declineTheChange(); + + // 3) Apply the suggestion + triggerOpenFixSuggestion(firstSonarCloudProjectKey, firstSonarCloudIssueKey, file, explanation, before, after, startLine, endLine); + + new WaitUntil(new FixSuggestionAvailableDialogOpened(0, 1)); + new FixSuggestionAvailableDialog(0, 1).applyTheChange(); + + // 4) Cancel the suggestion (unavailable) + triggerOpenFixSuggestion(firstSonarCloudProjectKey, firstSonarCloudIssueKey, file, explanation, before, after, startLine, endLine); + + new WaitUntil(new FixSuggestionUnavailableDialogOpened(0, 1)); + new FixSuggestionUnavailableDialog(0, 1).cancel(); + + // 5) Suggestion not found + triggerOpenFixSuggestion(firstSonarCloudProjectKey, firstSonarCloudIssueKey, file, explanation, before, after, startLine, endLine); + + new WaitUntil(new FixSuggestionUnavailableDialogOpened(0, 1)); + new FixSuggestionUnavailableDialog(0, 1).proceed(); + } + + private static List getProjectKeys() throws InterruptedException, IOException { + assertThat(hotspotServerPort).isNotEqualTo(-1); + + var request = HttpRequest.newBuilder() + .uri(URI.create(SONARCLOUD_STAGING_URL + "/api/projects/search?organization=" + SONARCLOUD_ORGANIZATION_KEY + + "&analyzedBefore=" + LocalDate.now())) + .header("Authorization", "Bearer " + token) + .GET() + .build(); + + var response = HttpClient.newHttpClient().send(request, java.net.http.HttpResponse.BodyHandlers.ofString()); + assertThat(response.statusCode()).isEqualTo(200); + + var jsonObject = (JsonObject) JsonParser.parseString(response.body()); + + var projectKeys = new ArrayList(); + var projectsList = jsonObject.get("components").getAsJsonArray(); + for (var project : projectsList) { + var key = project.getAsJsonObject().get("key").getAsString(); + if (key.contains(SAMPLE_JAVA_ISSUES_KEY)) { + projectKeys.add(key); + } + } + return projectKeys; + } + + private static Tuple getFirstProjectAndIssueKey(List projectKeys) throws IOException, InterruptedException { + assertThat(hotspotServerPort).isNotEqualTo(-1); + + var request = HttpRequest.newBuilder() + .uri(URI.create(SONARCLOUD_STAGING_URL + "/api/issues/search?organization=" + SONARCLOUD_ORGANIZATION_KEY + + "&componentKeys=" + String.join(",", projectKeys))) + .header("Authorization", "Bearer " + token) + .GET() + .build(); + + var response = HttpClient.newHttpClient().send(request, java.net.http.HttpResponse.BodyHandlers.ofString()); + assertThat(response.statusCode()).isEqualTo(200); + + var jsonObject = (JsonObject) JsonParser.parseString(response.body()); + var firstIssueKey = jsonObject.get("issues").getAsJsonArray().get(0).getAsJsonObject().get("key").getAsString(); + var firstProjectKey = jsonObject.get("issues").getAsJsonArray().get(0).getAsJsonObject().get("project").getAsString(); + return new Tuple(firstIssueKey, firstProjectKey); + } + + private static Branch getFirstBranch(String projectKey) { + var response = adminWsClient.projectBranches() + .list(new ListRequest().setProject(projectKey)); + assertThat(response.getBranchesCount()).isPositive(); + + return response.getBranches(0); + } + + private void triggerOpenFixSuggestion(String projectKey, String issueKey, String relativePath, String explanation, + String before, String after, int startLine, int endLine) throws InterruptedException, IOException { + assertThat(hotspotServerPort).isNotEqualTo(-1); + + var body = "{" + + "\"suggestionId\":\"9689b623-708e-4128-ae90-8432206c61fe\"," + + "\"explanation\":\"" + explanation + "\"," + + "\"fileEdit\":{" + + "\"path\":\"" + relativePath + "\"," + + "\"changes\":[" + + "{" + + "\"before\":\"" + before + "\"," + + "\"after\":\"" + after + "\"," + + "\"beforeLineRange\":{" + + "\"startLine\":" + startLine + "," + + "\"endLine\":" + endLine + + "}" + + "}" + + "]" + + "}" + + "}"; + + var request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + hotspotServerPort + + "/sonarlint/api/fix/show" + + "?project=" + projectKey + + "&issue=" + issueKey + + "&organizationKey=" + SONARCLOUD_ORGANIZATION_KEY + + "&tokenName=" + TOKEN_NAME + + "&tokenValue=" + token + + "&branch=" + firstSonarCloudBranch)) + .header("Content-Type", "application/json") + .header("Origin", SONARCLOUD_STAGING_URL) + .POST(BodyPublishers.ofString(body)) + .build(); + + var response = HttpClient.newHttpClient().send(request, java.net.http.HttpResponse.BodyHandlers.ofString()); + assertThat(response.statusCode()).isEqualTo(200); + } } diff --git a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/AbstractSonarQubeConnectedModeTest.java b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/AbstractSonarQubeConnectedModeTest.java index 7b19cb137..861d657f3 100644 --- a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/AbstractSonarQubeConnectedModeTest.java +++ b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/AbstractSonarQubeConnectedModeTest.java @@ -40,7 +40,6 @@ import org.junit.Before; import org.osgi.framework.FrameworkUtil; import org.sonarlint.eclipse.its.shared.AbstractSonarLintTest; -import org.sonarlint.eclipse.its.shared.reddeer.conditions.AnalysisReadyAfterUnready; import org.sonarlint.eclipse.its.shared.reddeer.conditions.ProjectBindingWizardIsOpened; import org.sonarlint.eclipse.its.shared.reddeer.dialogs.ProjectSelectionDialog; import org.sonarlint.eclipse.its.shared.reddeer.views.BindingsView; @@ -207,9 +206,4 @@ protected static void bindProjectFromContextMenu(Project project, String project serverProjectSelectionPage.setProjectKey(projectKey); projectBindingWizard.finish(); } - - /** When binding project it will move to unready state before going to ready state again */ - protected static void waitForAnalysisReady(String projectName) { - new WaitUntil(new AnalysisReadyAfterUnready(projectName), TimePeriod.getCustom(60)); - } } diff --git a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/OpenInIdeTest.java b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/OpenInIdeTest.java index 410de4e1f..c9420a87f 100644 --- a/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/OpenInIdeTest.java +++ b/its/org.sonarlint.eclipse.its.connected.sq/src/org/sonarlint/eclipse/its/connected/sq/OpenInIdeTest.java @@ -134,13 +134,13 @@ public void test_open_in_ide_assist_manual_binding() throws IOException, Interru // 3) trigger "Open in IDE" feature, but cancel triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s101.getKey()); - new WaitUntil(new ConfirmConnectionCreationDialogOpened(), TimePeriod.DEFAULT); - new ConfirmConnectionCreationDialog().donottrust(); + new WaitUntil(new ConfirmConnectionCreationDialogOpened(false), TimePeriod.DEFAULT); + new ConfirmConnectionCreationDialog(false).donottrust(); // 4) trigger "Open in IDE" feature, but accept this time triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s101.getKey()); - new WaitUntil(new ConfirmConnectionCreationDialogOpened(), TimePeriod.DEFAULT); - new ConfirmConnectionCreationDialog().trust(); + new WaitUntil(new ConfirmConnectionCreationDialogOpened(false), TimePeriod.DEFAULT); + new ConfirmConnectionCreationDialog(false).trust(); var wizard = new ServerConnectionWizard(); assertThat(new ServerConnectionWizard.ServerTypePage(wizard).isSonarQubeSelected()).isTrue(); @@ -217,8 +217,8 @@ public void test_open_in_ide_assist_automated_binding_empty_workspace() throws I // 3) trigger "Open in IDE" feature and accept triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s101.getKey(), tokenName, tokenValue); - new WaitUntil(new ConfirmConnectionCreationDialogOpened(), TimePeriod.DEFAULT); - new ConfirmConnectionCreationDialog().trust(); + new WaitUntil(new ConfirmConnectionCreationDialogOpened(false), TimePeriod.DEFAULT); + new ConfirmConnectionCreationDialog(false).trust(); // 4) await pop-up saying that automatic binding is not possible var popUp = new DefaultShell("SonarLint - No mathing open project found"); @@ -258,8 +258,8 @@ public void test_open_in_ide_assist_automated_binding() throws IOException, Inte // 4) trigger "Open in IDE" feature, but cancel triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s101.getKey(), tokenName, tokenValue); - new WaitUntil(new ConfirmConnectionCreationDialogOpened(), TimePeriod.DEFAULT); - new ConfirmConnectionCreationDialog().donottrust(); + new WaitUntil(new ConfirmConnectionCreationDialogOpened(false), TimePeriod.DEFAULT); + new ConfirmConnectionCreationDialog(false).donottrust(); // 5) Check that token was revoked var userTokens = adminWsClient @@ -276,8 +276,8 @@ public void test_open_in_ide_assist_automated_binding() throws IOException, Inte // 7) trigger "Open in IDE" feature, but accept this time triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s101.getKey(), tokenName, tokenValue); - new WaitUntil(new ConfirmConnectionCreationDialogOpened(), TimePeriod.DEFAULT); - new ConfirmConnectionCreationDialog().trust(); + new WaitUntil(new ConfirmConnectionCreationDialogOpened(false), TimePeriod.DEFAULT); + new ConfirmConnectionCreationDialog(false).trust(); try { var projectSelectionDialog = new ProjectSelectionDialog(); diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/AbstractSonarLintTest.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/AbstractSonarLintTest.java index 0dfabe0f8..1d3dfd34d 100644 --- a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/AbstractSonarLintTest.java +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/AbstractSonarLintTest.java @@ -76,6 +76,7 @@ import org.osgi.framework.Version; import org.osgi.service.prefs.BackingStoreException; import org.sonarlint.eclipse.its.shared.reddeer.conditions.AnalysisReady; +import org.sonarlint.eclipse.its.shared.reddeer.conditions.AnalysisReadyAfterUnready; import org.sonarlint.eclipse.its.shared.reddeer.preferences.FileAssociationsPreferences; import org.sonarlint.eclipse.its.shared.reddeer.preferences.RuleConfigurationPreferences; import org.sonarlint.eclipse.its.shared.reddeer.preferences.SonarLintPreferences; @@ -462,4 +463,9 @@ protected final void ignoreMacOS() { protected static String getNotificationText(DefaultShell shell) { return new DefaultLabel(shell, 3).getText(); } + + /** When binding project it will move to unready state before going to ready state again */ + protected static void waitForAnalysisReady(String projectName) { + new WaitUntil(new AnalysisReadyAfterUnready(projectName), TimePeriod.getCustom(60)); + } } diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/ConfirmConnectionCreationDialogOpened.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/ConfirmConnectionCreationDialogOpened.java index 9bb2a4b96..c382035e0 100644 --- a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/ConfirmConnectionCreationDialogOpened.java +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/ConfirmConnectionCreationDialogOpened.java @@ -23,10 +23,16 @@ import org.sonarlint.eclipse.its.shared.reddeer.dialogs.ConfirmConnectionCreationDialog; public class ConfirmConnectionCreationDialogOpened implements WaitCondition { + private final boolean isSonarCloud; + + public ConfirmConnectionCreationDialogOpened(boolean isSonarCloud) { + this.isSonarCloud = isSonarCloud; + } + @Override public boolean test() { try { - new ConfirmConnectionCreationDialog().isEnabled(); + new ConfirmConnectionCreationDialog(isSonarCloud).isEnabled(); return true; } catch (Exception ignored) { return false; @@ -35,7 +41,7 @@ public boolean test() { @Override public ConfirmConnectionCreationDialog getResult() { - return new ConfirmConnectionCreationDialog(); + return new ConfirmConnectionCreationDialog(isSonarCloud); } @Override diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FileNotFoundDialogOpened.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FileNotFoundDialogOpened.java new file mode 100644 index 000000000..fd81e2652 --- /dev/null +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FileNotFoundDialogOpened.java @@ -0,0 +1,55 @@ +/* + * SonarLint for Eclipse ITs + * Copyright (C) 2009-2024 SonarSource SA + * sonarlint@sonarsource.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. + */ +package org.sonarlint.eclipse.its.shared.reddeer.conditions; + +import org.eclipse.reddeer.common.condition.WaitCondition; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.FileNotFoundDialog; + +public class FileNotFoundDialogOpened implements WaitCondition { + @Override + public boolean test() { + try { + new FileNotFoundDialog().isEnabled(); + return true; + } catch (Exception ignored) { + return false; + } + } + + @Override + public FileNotFoundDialog getResult() { + return new FileNotFoundDialog(); + } + + @Override + public String description() { + return "'File not found' dialog is opened"; + } + + @Override + public String errorMessageWhile() { + return "'File not found' dialog is still opened"; + } + + @Override + public String errorMessageUntil() { + return "'File not found' dialog is not yet opened"; + } +} diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FixSuggestionAvailableDialogOpened.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FixSuggestionAvailableDialogOpened.java new file mode 100644 index 000000000..21467d4e2 --- /dev/null +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FixSuggestionAvailableDialogOpened.java @@ -0,0 +1,63 @@ +/* + * SonarLint for Eclipse ITs + * Copyright (C) 2009-2024 SonarSource SA + * sonarlint@sonarsource.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. + */ +package org.sonarlint.eclipse.its.shared.reddeer.conditions; + +import org.eclipse.reddeer.common.condition.WaitCondition; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.FixSuggestionAvailableDialog; + +public class FixSuggestionAvailableDialogOpened implements WaitCondition { + private final int index; + private final int all; + + public FixSuggestionAvailableDialogOpened(int index, int all) { + this.index = index; + this.all = all; + } + + @Override + public boolean test() { + try { + new FixSuggestionAvailableDialog(index, all).isEnabled(); + return true; + } catch (Exception ignored) { + return false; + } + } + + @Override + public FixSuggestionAvailableDialog getResult() { + return new FixSuggestionAvailableDialog(index, all); + } + + @Override + public String description() { + return "'Fix Suggestion (available)' dialog is opened"; + } + + @Override + public String errorMessageWhile() { + return "'Fix Suggestion (available)' dialog is still opened"; + } + + @Override + public String errorMessageUntil() { + return "'Fix Suggestion (available)' dialog is not yet opened"; + } +} diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FixSuggestionUnavailableDialogOpened.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FixSuggestionUnavailableDialogOpened.java new file mode 100644 index 000000000..972c737cc --- /dev/null +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/FixSuggestionUnavailableDialogOpened.java @@ -0,0 +1,63 @@ +/* + * SonarLint for Eclipse ITs + * Copyright (C) 2009-2024 SonarSource SA + * sonarlint@sonarsource.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. + */ +package org.sonarlint.eclipse.its.shared.reddeer.conditions; + +import org.eclipse.reddeer.common.condition.WaitCondition; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.FixSuggestionUnavailableDialog; + +public class FixSuggestionUnavailableDialogOpened implements WaitCondition { + private final int index; + private final int all; + + public FixSuggestionUnavailableDialogOpened(int index, int all) { + this.index = index; + this.all = all; + } + + @Override + public boolean test() { + try { + new FixSuggestionUnavailableDialog(index, all).isEnabled(); + return true; + } catch (Exception ignored) { + return false; + } + } + + @Override + public FixSuggestionUnavailableDialog getResult() { + return new FixSuggestionUnavailableDialog(index, all); + } + + @Override + public String description() { + return "'Fix Suggestion (unavailable)' dialog is opened"; + } + + @Override + public String errorMessageWhile() { + return "'Fix Suggestion (unavailable)' dialog is still opened"; + } + + @Override + public String errorMessageUntil() { + return "'Fix Suggestion (unavailable)' dialog is not yet opened"; + } +} diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/ProjectSelectionDialogOpened.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/ProjectSelectionDialogOpened.java new file mode 100644 index 000000000..dc2133677 --- /dev/null +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/conditions/ProjectSelectionDialogOpened.java @@ -0,0 +1,55 @@ +/* + * SonarLint for Eclipse ITs + * Copyright (C) 2009-2024 SonarSource SA + * sonarlint@sonarsource.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. + */ +package org.sonarlint.eclipse.its.shared.reddeer.conditions; + +import org.eclipse.reddeer.common.condition.WaitCondition; +import org.sonarlint.eclipse.its.shared.reddeer.dialogs.ProjectSelectionDialog; + +public class ProjectSelectionDialogOpened implements WaitCondition { + @Override + public boolean test() { + try { + new ProjectSelectionDialog().isEnabled(); + return true; + } catch (Exception ignored) { + return false; + } + } + + @Override + public ProjectSelectionDialog getResult() { + return new ProjectSelectionDialog(); + } + + @Override + public String description() { + return "'Project selection for binding' dialog is opened"; + } + + @Override + public String errorMessageWhile() { + return "'Project selection for binding' dialog is still opened"; + } + + @Override + public String errorMessageUntil() { + return "'Project selection for binding' dialog is not yet opened"; + } +} diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/ConfirmConnectionCreationDialog.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/ConfirmConnectionCreationDialog.java index fdaa7fd40..3cf8e30f0 100644 --- a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/ConfirmConnectionCreationDialog.java +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/ConfirmConnectionCreationDialog.java @@ -22,12 +22,17 @@ import org.eclipse.reddeer.swt.impl.shell.DefaultShell; public class ConfirmConnectionCreationDialog extends DefaultShell { - public ConfirmConnectionCreationDialog() { - super("Do you trust this SonarQube server?"); + private final boolean isSonarCloud; + + public ConfirmConnectionCreationDialog(boolean isSonarCloud) { + super(isSonarCloud + ? "Do you trust SonarCloud?" + : "Do you trust this SonarQube server?"); + this.isSonarCloud = isSonarCloud; } public void trust() { - new TrustButton(this).click(); + new TrustButton(this, isSonarCloud).click(); } public void donottrust() { diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FileNotFoundDialog.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FileNotFoundDialog.java new file mode 100644 index 000000000..8013e861d --- /dev/null +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FileNotFoundDialog.java @@ -0,0 +1,33 @@ +/* + * SonarLint for Eclipse ITs + * Copyright (C) 2009-2024 SonarSource SA + * sonarlint@sonarsource.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. + */ +package org.sonarlint.eclipse.its.shared.reddeer.dialogs; + +import org.eclipse.reddeer.swt.impl.button.OkButton; +import org.eclipse.reddeer.swt.impl.shell.DefaultShell; + +public class FileNotFoundDialog extends DefaultShell { + public FileNotFoundDialog() { + super("File not found"); + } + + public void ok() { + new OkButton(this).click(); + } +} diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FixSuggestionAvailableDialog.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FixSuggestionAvailableDialog.java new file mode 100644 index 000000000..5eaa06fda --- /dev/null +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FixSuggestionAvailableDialog.java @@ -0,0 +1,61 @@ +/* + * SonarLint for Eclipse ITs + * Copyright (C) 2009-2024 SonarSource SA + * sonarlint@sonarsource.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. + */ +package org.sonarlint.eclipse.its.shared.reddeer.dialogs; + +import org.eclipse.reddeer.core.reference.ReferencedComposite; +import org.eclipse.reddeer.swt.impl.button.PredefinedButton; +import org.eclipse.reddeer.swt.impl.shell.DefaultShell; +import org.eclipse.swt.SWT; + +public class FixSuggestionAvailableDialog extends DefaultShell { + public FixSuggestionAvailableDialog(int index, int all) { + super(String.format("SonarLint Fix Suggestion (%d/%d)", index + 1, all)); + } + + public void applyTheChange() { + new ApplyTheChangeButton(this).click(); + } + + public void declineTheChange() { + new DeclineTheChangeButton(this).click(); + } + + public void cancel() { + new CancelButton(this).click(); + } + + private static class ApplyTheChangeButton extends PredefinedButton { + public ApplyTheChangeButton(ReferencedComposite referencedComposite) { + super(referencedComposite, 0, "Apply the change", SWT.PUSH); + } + } + + private static class DeclineTheChangeButton extends PredefinedButton { + public DeclineTheChangeButton(ReferencedComposite referencedComposite) { + super(referencedComposite, 0, "Decline the change", SWT.PUSH); + } + } + + private static class CancelButton extends PredefinedButton { + public CancelButton(ReferencedComposite referencedComposite) { + super(referencedComposite, 0, "Cancel", SWT.PUSH); + } + } +} diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FixSuggestionUnavailableDialog.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FixSuggestionUnavailableDialog.java new file mode 100644 index 000000000..61ae8a88b --- /dev/null +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/FixSuggestionUnavailableDialog.java @@ -0,0 +1,51 @@ +/* + * SonarLint for Eclipse ITs + * Copyright (C) 2009-2024 SonarSource SA + * sonarlint@sonarsource.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. + */ +package org.sonarlint.eclipse.its.shared.reddeer.dialogs; + +import org.eclipse.reddeer.core.reference.ReferencedComposite; +import org.eclipse.reddeer.swt.impl.button.PredefinedButton; +import org.eclipse.reddeer.swt.impl.shell.DefaultShell; +import org.eclipse.swt.SWT; + +public class FixSuggestionUnavailableDialog extends DefaultShell { + public FixSuggestionUnavailableDialog(int index, int all) { + super(String.format("SonarLint Fix Suggestion (%d/%d)", index + 1, all)); + } + + public void proceed() { + new ProceedButton(this).click(); + } + + public void cancel() { + new CancelButton(this).click(); + } + + private static class ProceedButton extends PredefinedButton { + public ProceedButton(ReferencedComposite referencedComposite) { + super(referencedComposite, 0, "Proceed", SWT.PUSH); + } + } + + private static class CancelButton extends PredefinedButton { + public CancelButton(ReferencedComposite referencedComposite) { + super(referencedComposite, 0, "Cancel", SWT.PUSH); + } + } +} diff --git a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/TrustButton.java b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/TrustButton.java index cd98e1325..37c6788be 100644 --- a/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/TrustButton.java +++ b/its/org.sonarlint.eclipse.its.shared/src/org/sonarlint/eclipse/its/shared/reddeer/dialogs/TrustButton.java @@ -24,14 +24,16 @@ import org.eclipse.swt.SWT; public class TrustButton extends PredefinedButton { - - public TrustButton(ReferencedComposite referencedComposite) { - this(referencedComposite, 0); - + public TrustButton(ReferencedComposite referencedComposite, boolean isSonarCloud) { + this(referencedComposite, 0, isSonarCloud); } - public TrustButton(ReferencedComposite referencedComposite, int index) { - super(referencedComposite, index, "Connect to this SonarQube server", SWT.PUSH); + public TrustButton(ReferencedComposite referencedComposite, int index, boolean isSonarCloud) { + super(referencedComposite, + index, + isSonarCloud + ? "Connect to SonarCloud" + : "Connect to this SonarQube server", + SWT.PUSH); } - } diff --git a/its/projects/connected-sc/sonarlint-its-sample-java-issues/.project b/its/projects/connected-sc/sonarlint-its-sample-java-issues/.project new file mode 100644 index 000000000..2c463165b --- /dev/null +++ b/its/projects/connected-sc/sonarlint-its-sample-java-issues/.project @@ -0,0 +1,11 @@ + + + sonarlint-its-sample-java-issues + + + + + + + + diff --git a/its/projects/connected-sc/sonarlint-its-sample-java-issues/FileExists.txt b/its/projects/connected-sc/sonarlint-its-sample-java-issues/FileExists.txt new file mode 100644 index 000000000..e19c62736 --- /dev/null +++ b/its/projects/connected-sc/sonarlint-its-sample-java-issues/FileExists.txt @@ -0,0 +1 @@ +Eclipse IDE is the best!