Skip to content

Commit

Permalink
SLE-779 Add a confirmation popup before creating connection
Browse files Browse the repository at this point in the history
  • Loading branch information
henryju committed Dec 18, 2023
1 parent ca04ece commit 3755dff
Show file tree
Hide file tree
Showing 24 changed files with 676 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
import org.eclipse.swt.widgets.Label;
import org.junit.Before;
import org.osgi.framework.FrameworkUtil;
import org.sonarlint.eclipse.its.reddeer.dialogs.ProjectSelectionDialog;
import org.sonarlint.eclipse.its.reddeer.views.BindingsView;
import org.sonarlint.eclipse.its.reddeer.wizards.ProjectBindingWizard;
import org.sonarlint.eclipse.its.reddeer.wizards.ProjectSelectionDialog;
import org.sonarlint.eclipse.its.reddeer.wizards.ServerConnectionWizard;
import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.project.CreateRequest;
Expand Down Expand Up @@ -144,7 +144,7 @@ protected static void createConnectionAndBindProject(OrchestratorRule orchestrat
projectsToBindPage.clickAdd();

var projectSelectionDialog = new ProjectSelectionDialog();
projectSelectionDialog.setProjectName(projectKey);
projectSelectionDialog.filterProjectName(projectKey);
projectSelectionDialog.ok();

projectBindingWizard.next();
Expand Down
170 changes: 128 additions & 42 deletions its/src/org/sonarlint/eclipse/its/OpenInIdeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.sonarlint.eclipse.its;

import com.sonar.orchestrator.container.Edition;
import com.sonar.orchestrator.container.Server;
import com.sonar.orchestrator.junit4.OrchestratorRule;
import java.io.IOException;
import java.net.URI;
Expand All @@ -30,22 +31,30 @@
import java.util.Map;
import org.eclipse.reddeer.common.wait.TimePeriod;
import org.eclipse.reddeer.common.wait.WaitUntil;
import org.eclipse.reddeer.core.condition.WidgetIsFound;
import org.eclipse.reddeer.core.exception.CoreLayerException;
import org.eclipse.reddeer.core.matcher.WithTextMatcher;
import org.eclipse.reddeer.eclipse.ui.perspectives.JavaPerspective;
import org.eclipse.reddeer.swt.impl.shell.DefaultShell;
import org.eclipse.reddeer.workbench.impl.editor.TextEditor;
import org.eclipse.swt.widgets.Label;
import org.junit.After;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.sonarlint.eclipse.its.reddeer.conditions.ConfirmConnectionCreationDialogOpened;
import org.sonarlint.eclipse.its.reddeer.conditions.OpenInIdeDialogOpened;
import org.sonarlint.eclipse.its.reddeer.conditions.RuleDescriptionViewOpenedWithContent;
import org.sonarlint.eclipse.its.reddeer.conditions.SonarLintTaintVulnerabilitiesViewOpened;
import org.sonarlint.eclipse.its.reddeer.dialogs.ConfirmConnectionCreationDialog;
import org.sonarlint.eclipse.its.reddeer.dialogs.OpenInIdeDialog;
import org.sonarlint.eclipse.its.reddeer.dialogs.ProjectSelectionDialog;
import org.sonarlint.eclipse.its.reddeer.preferences.SonarLintPreferences.IssueFilter;
import org.sonarlint.eclipse.its.reddeer.preferences.SonarLintPreferences.IssuePeriod;
import org.sonarlint.eclipse.its.reddeer.views.RuleDescriptionView;
import org.sonarlint.eclipse.its.reddeer.views.SonarLintTaintVulnerabilitiesView;
import org.sonarlint.eclipse.its.reddeer.wizards.OpenInIdeDialog;
import org.sonarlint.eclipse.its.reddeer.wizards.ServerConnectionWizard;
import org.sonarqube.ws.Issues.Issue;
import org.sonarqube.ws.WsBranches.Branch;
import org.sonarqube.ws.client.issue.SearchWsRequest;
Expand All @@ -62,7 +71,7 @@ public class OpenInIdeTest extends AbstractSonarQubeConnectedModeTest {
private static final String S106 = "java:S106";
private static final String S1481 = "java:S1481";
private static final String S2083 = "javasecurity:S2083";

/** Orchestrator to not be re-used in order for ITs to not fail -> always use latest release locally (not LTS) */
@ClassRule
public static final OrchestratorRule orchestrator = OrchestratorRule.builderEnv()
Expand All @@ -77,56 +86,132 @@ public class OpenInIdeTest extends AbstractSonarQubeConnectedModeTest {
.setServerProperty("sonar.pushevents.polling.period", "1")
.setServerProperty("sonar.pushevents.polling.last.timestamp", "1")
.build();

@BeforeClass
public static void prepare() {
prepare(orchestrator);
}

/** as we re-use the same project we have to delete it on SonarQube after every test */
@After
public void deleteSonarQubeProjects() {
if (orchestrator.getServer().version().isGreaterThanOrEquals(10, 2)) {
adminWsClient.projects().delete(DeleteRequest.builder().setKey(MAVEN_TAINT_PROJECT_KEY).build());
}
}

/** integration test for when the feature fails due to the local file not being found */

@Test
public void test_open_in_ide_without_corner_cases() throws IOException, InterruptedException {
public void test_open_in_ide_assist_binding() throws IOException, InterruptedException {
// Only available since SonarQube 10.2+ (LATEST_RELEASE / locally)
Assume.assumeTrue(orchestrator.getServer().version().isGreaterThanOrEquals(10, 2));

// 1) create project on server / run first analysis
createProjectOnSonarQube(orchestrator, MAVEN_TAINT_PROJECT_KEY, "SonarLint IT New Code");
runMavenBuild(orchestrator, MAVEN_TAINT_PROJECT_KEY, "projects", "java/maven-taint/pom.xml",
Map.of("sonar.branch.name", "main"));


// 2) import project
new JavaPerspective().open();
var rootProject = importExistingProjectIntoWorkspace("java/maven-taint", MAVEN_TAINT_PROJECT_KEY);

// 3) get S1481 issue key / branch name from SonarQube
var s101 = getFirstIssue(S101);
assertThat(s101).isNotNull();

var branch = getFirstBranch();
assertThat(branch).isNotNull();

// 4) trigger "Open in IDE" feature, but cancel
triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s101.getKey());
new WaitUntil(new ConfirmConnectionCreationDialogOpened(), TimePeriod.DEFAULT);
new ConfirmConnectionCreationDialog().donottrust();

// 5) 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();

var wizard = new ServerConnectionWizard();
assertThat(new ServerConnectionWizard.ServerTypePage(wizard).isSonarQubeSelected()).isTrue();
wizard.next();

var serverUrlPage = new ServerConnectionWizard.ServerUrlPage(wizard);
assertThat(serverUrlPage.getUrl()).isEqualTo(orchestrator.getServer().getUrl());
wizard.next();

var authenticationModePage = new ServerConnectionWizard.AuthenticationModePage(wizard);
authenticationModePage.selectUsernamePasswordMode();
wizard.next();

var authenticationPage = new ServerConnectionWizard.AuthenticationPage(wizard);
authenticationPage.setUsername(Server.ADMIN_LOGIN);
authenticationPage.setPassword(Server.ADMIN_PASSWORD);
wizard.next();

// as login can take time, wait for the next page to appear
new WaitUntil(new WidgetIsFound(Label.class, new WithTextMatcher("SonarQube Connection Identifier")));
var connectionNamePage = new ServerConnectionWizard.ConnectionNamePage(wizard);

connectionNamePage.setConnectionName("from open IDE");
wizard.next();

wizard.next();
wizard.finish();

var projectSelectionDialog = new ProjectSelectionDialog();
assertThat(projectSelectionDialog.getMessage()).contains("This Eclipse project will be bound to the Sonar project 'maven-taint' using connection 'from open IDE'");
projectSelectionDialog.filterProjectName(MAVEN_TAINT_PROJECT_KEY);
projectSelectionDialog.ok();

var ruleDescriptionView = new RuleDescriptionView();
new WaitUntil(new RuleDescriptionViewOpenedWithContent(ruleDescriptionView, S101), TimePeriod.DEFAULT);

closeTaintPopupIfAny();
}

private void closeTaintPopupIfAny() {
try {
new DefaultShell("SonarLint - Taint vulnerability found").close();
} catch (CoreLayerException notFound) {

}
}

@Test
public void test_open_in_ide_when_project_already_bound() throws IOException, InterruptedException {
// Only available since SonarQube 10.2+ (LATEST_RELEASE / locally)
Assume.assumeTrue(orchestrator.getServer().version().isGreaterThanOrEquals(10, 2));

// 1) create project on server / run first analysis
createProjectOnSonarQube(orchestrator, MAVEN_TAINT_PROJECT_KEY, "SonarLint IT New Code");
runMavenBuild(orchestrator, MAVEN_TAINT_PROJECT_KEY, "projects", "java/maven-taint/pom.xml",
Map.of("sonar.branch.name", "main"));

// 2) import project and bind to SonarQube
new JavaPerspective().open();
var rootProject = importExistingProjectIntoWorkspace("java/maven-taint", MAVEN_TAINT_PROJECT_KEY);
createConnectionAndBindProject(orchestrator, MAVEN_TAINT_PROJECT_KEY);
try {
new DefaultShell("SonarLint Binding Suggestion").close();
} catch (Exception ignored) { }

} catch (Exception ignored) {
}

// 3) delete file
rootProject.getResource("src/main/java", "taint", "Variables.java").delete();

// 4) get S1481 issue key / branch name from SonarQube
var s101 = getFirstIssue(S1481);
assertThat(s101).isNotNull();
var s1481 = getFirstIssue(S1481);
assertThat(s1481).isNotNull();

var branch = getFirstBranch();
assertThat(branch).isNotNull();

// 5) trigger "Open in IDE" feature: issue not found because file not found
// -> because the API is quite slow we have to await the opening of the error dialog
triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s101.getKey());
// -> because the API is quite slow we have to await the opening of the error dialog
triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s1481.getKey());
new WaitUntil(new OpenInIdeDialogOpened(), TimePeriod.DEFAULT);
new OpenInIdeDialog().ok();

// 6) change preferences regarding new code / issue filter + change file content
setNewCodePreference(IssuePeriod.NEW_CODE);
openFileAndWaitForAnalysisCompletion(rootProject.getResource("src/main/java", "taint", "SysOut.java"));
Expand All @@ -140,59 +225,60 @@ public void test_open_in_ide_without_corner_cases() throws IOException, Interrup
+ "");
textEditor.save();
Thread.sleep(1000); // we have to wait for the analysis to finish

// 7) get S106 issue key from SonarQube
var s106 = getFirstIssue(S106);
assertThat(s106).isNotNull();

// 8) trigger "Open in IDE" feature: issue not found because workspace preferences
// -> after we acknowledge SL to change preferences the dialog will open again
// -> after we acknowledge SL to change preferences the dialog will open again
triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s106.getKey());
new WaitUntil(new OpenInIdeDialogOpened(), TimePeriod.DEFAULT);
new OpenInIdeDialog().yes();

Thread.sleep(500); // we have to wait for the preference page to open and to get the job data
setIssueFilterPreference(IssueFilter.ALL_ISSUES);

new WaitUntil(new OpenInIdeDialogOpened(), TimePeriod.DEFAULT);
new OpenInIdeDialog().ok();

// 9) get S101 issue key from SonarQube
var s1481 = getFirstIssue(S101);
assertThat(s1481).isNotNull();
var s101 = getFirstIssue(S101);
assertThat(s101).isNotNull();

// 10) trigger "Open in IDE" feature: issue opens correctly including On-The-Fly / Rule Description view
triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s1481.getKey());
triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s101.getKey());
var ruleDescriptionView = new RuleDescriptionView();
new WaitUntil(new RuleDescriptionViewOpenedWithContent(ruleDescriptionView, S101), TimePeriod.DEFAULT);
ruleDescriptionView.open();

// 11) get S2083 issue key from SonarQube
var s2083 = getFirstIssue(S2083);
assertThat(s2083).isNotNull();

// 12) trigger "Open in IDE" feature: taint vulnerability opens correctly including Taint Vulnerabilities view
triggerOpenInIDE(orchestrator.getServer().getUrl(), branch.getName(), s2083.getKey());
var sonarLintTaintVulnerabilitiesView = new SonarLintTaintVulnerabilitiesView();
new WaitUntil(new SonarLintTaintVulnerabilitiesViewOpened(sonarLintTaintVulnerabilitiesView), TimePeriod.DEFAULT);
sonarLintTaintVulnerabilitiesView.open();
assertThat(sonarLintTaintVulnerabilitiesView.getItems()).isNotEmpty();
new DefaultShell("SonarLint - Taint vulnerability found").close();

closeTaintPopupIfAny();
}

/**
* To emulate a user clicking on "Open in IDE" on their SonarQube on an issue
*
*
* @param serverURL the server URL to be passed to the web request ???
* @param branch issue branch
* @param projectKey project containing the issue
* @param issueKey specific issue
* @throws IOException when connection fails
* @throws InterruptedException
* @throws InterruptedException
*/
private void triggerOpenInIDE(String serverURL, String branch, String issueKey) throws InterruptedException, IOException {
assertThat(hotspotServerPort).isNotEqualTo(-1);

var request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:" + hotspotServerPort + "/sonarlint/api/issues/show?server=" + URLEncoder.encode(serverURL)
+ "&project=" + MAVEN_TAINT_PROJECT_KEY
Expand All @@ -201,26 +287,26 @@ private void triggerOpenInIDE(String serverURL, String branch, String issueKey)
.header("Origin", serverURL)
.header("Referer", serverURL)
.GET().build();

var response = HttpClient.newHttpClient().send(request, java.net.http.HttpResponse.BodyHandlers.ofString());
assertThat(response.statusCode()).isEqualTo(200);
}

/** Get first issue from project matching the rule key provided (does not contain branch information???) */
private static Issue getFirstIssue(String ruleKey) {
var response = adminWsClient.issues().search(new SearchWsRequest()
.setRules(List.of(ruleKey))
.setProjects(List.of(MAVEN_TAINT_PROJECT_KEY)));

assertThat(response.getIssuesCount()).isPositive();
return response.getIssues(0);
}

/** Get first branch from project */
private static Branch getFirstBranch() {
var response = adminWsClient.projectBranches().list(MAVEN_TAINT_PROJECT_KEY);
assertThat(response.getBranchesCount()).isPositive();

return response.getBranches(0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.sonarlint.eclipse.its.reddeer.conditions.DialogMessageIsExpected;
import org.sonarlint.eclipse.its.reddeer.dialogs.ProjectSelectionDialog;
import org.sonarlint.eclipse.its.reddeer.views.BindingsView;
import org.sonarlint.eclipse.its.reddeer.views.BindingsView.Binding;
import org.sonarlint.eclipse.its.reddeer.wizards.ProjectBindingWizard;
import org.sonarlint.eclipse.its.reddeer.wizards.ProjectSelectionDialog;
import org.sonarlint.eclipse.its.reddeer.wizards.ServerConnectionWizard;
import org.sonarqube.ws.client.HttpConnector;
import org.sonarqube.ws.client.WsClient;
Expand Down Expand Up @@ -141,7 +141,7 @@ public void configureServerWithTokenAndOrganization() {
projectsToBindPage.clickAdd();

var projectSelectionDialog = new ProjectSelectionDialog();
projectSelectionDialog.setProjectName(IMPORTED_PROJECT_NAME);
projectSelectionDialog.filterProjectName(IMPORTED_PROJECT_NAME);
projectSelectionDialog.ok();

projectBindingWizard.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@
import org.junit.Test;
import org.sonarlint.eclipse.its.reddeer.conditions.DialogMessageIsExpected;
import org.sonarlint.eclipse.its.reddeer.conditions.RuleDescriptionViewIsLoaded;
import org.sonarlint.eclipse.its.reddeer.dialogs.MarkIssueAsDialog;
import org.sonarlint.eclipse.its.reddeer.preferences.SonarLintPreferences.IssuePeriod;
import org.sonarlint.eclipse.its.reddeer.views.BindingsView;
import org.sonarlint.eclipse.its.reddeer.views.BindingsView.Binding;
import org.sonarlint.eclipse.its.reddeer.views.OnTheFlyView;
import org.sonarlint.eclipse.its.reddeer.views.RuleDescriptionView;
import org.sonarlint.eclipse.its.reddeer.views.SonarLintIssueMarker;
import org.sonarlint.eclipse.its.reddeer.views.SonarLintTaintVulnerabilitiesView;
import org.sonarlint.eclipse.its.reddeer.wizards.MarkIssueAsDialog;
import org.sonarlint.eclipse.its.reddeer.wizards.ProjectBindingWizard;
import org.sonarlint.eclipse.its.reddeer.wizards.ServerConnectionWizard;
import org.sonarlint.eclipse.its.reddeer.wizards.ServerConnectionWizard.AuthenticationPage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.sonarlint.eclipse.its.reddeer.conditions.OnTheFlyViewIsEmpty;
import org.sonarlint.eclipse.its.reddeer.dialogs.EnhancedWithConnectedModeInformationDialog;
import org.sonarlint.eclipse.its.reddeer.perspectives.PhpPerspective;
import org.sonarlint.eclipse.its.reddeer.perspectives.PydevPerspective;
import org.sonarlint.eclipse.its.reddeer.preferences.SonarLintPreferences;
Expand All @@ -64,7 +65,6 @@
import org.sonarlint.eclipse.its.reddeer.views.PydevPackageExplorer;
import org.sonarlint.eclipse.its.reddeer.views.ReportView;
import org.sonarlint.eclipse.its.reddeer.views.SonarLintIssueMarker;
import org.sonarlint.eclipse.its.reddeer.wizards.EnhancedWithConnectedModeInformationDialog;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
Expand Down

0 comments on commit 3755dff

Please sign in to comment.