diff --git a/plugins/plugin-github/che-plugin-github-ide/pom.xml b/plugins/plugin-github/che-plugin-github-ide/pom.xml
index 2cdefba643..95b5770dc4 100644
--- a/plugins/plugin-github/che-plugin-github-ide/pom.xml
+++ b/plugins/plugin-github/che-plugin-github-ide/pom.xml
@@ -50,6 +50,10 @@
org.eclipse.che.core
che-core-api-dto
+
+ org.eclipse.che.core
+ che-core-api-git-shared
+
org.eclipse.che.core
che-core-api-ssh-shared
@@ -75,6 +79,10 @@
org.eclipse.che.core
che-core-ide-ui
+
+ org.eclipse.che.plugin
+ che-plugin-git-ext-git
+
org.eclipse.che.plugin
che-plugin-github-shared
diff --git a/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/GitHubExtension.java b/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/GitHubExtension.java
index 08286974f0..9209f8e037 100644
--- a/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/GitHubExtension.java
+++ b/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/GitHubExtension.java
@@ -11,9 +11,15 @@
*/
package org.eclipse.che.plugin.github.ide;
+import static org.eclipse.che.ide.api.action.IdeActions.GROUP_EDITOR_CONTEXT_MENU;
+import static org.eclipse.che.ide.api.action.IdeActions.GROUP_MAIN_CONTEXT_MENU;
+
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import org.eclipse.che.ide.api.action.ActionManager;
+import org.eclipse.che.ide.api.action.DefaultActionGroup;
import org.eclipse.che.ide.api.extension.Extension;
+import org.eclipse.che.plugin.github.ide.action.OpenOnGitHubAction;
import org.eclipse.che.plugin.ssh.key.client.SshKeyUploaderRegistry;
/**
@@ -29,7 +35,18 @@ public class GitHubExtension {
@Inject
public GitHubExtension(
- SshKeyUploaderRegistry registry, GitHubSshKeyUploader gitHubSshKeyProvider) {
+ SshKeyUploaderRegistry registry,
+ GitHubSshKeyUploader gitHubSshKeyProvider,
+ ActionManager actionManager,
+ OpenOnGitHubAction openOnGitHubAction) {
+
registry.registerUploader(GITHUB_HOST, gitHubSshKeyProvider);
+ actionManager.registerAction("openOnGitHub", openOnGitHubAction);
+ DefaultActionGroup mainContextMenuGroup =
+ (DefaultActionGroup) actionManager.getAction(GROUP_MAIN_CONTEXT_MENU);
+ mainContextMenuGroup.add(openOnGitHubAction);
+ DefaultActionGroup editorContextMenuGroup =
+ (DefaultActionGroup) actionManager.getAction(GROUP_EDITOR_CONTEXT_MENU);
+ editorContextMenuGroup.add(openOnGitHubAction);
}
}
diff --git a/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/GitHubLocalizationConstant.java b/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/GitHubLocalizationConstant.java
index ca23bc67c9..2ed86ec768 100644
--- a/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/GitHubLocalizationConstant.java
+++ b/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/GitHubLocalizationConstant.java
@@ -101,4 +101,8 @@ public interface GitHubLocalizationConstant extends Messages {
@Key("view.import.githubImporterPage.branch")
String githubImporterPageBranch();
+
+ @Key("open.on.github.action")
+ @DefaultMessage("Open on GitHub")
+ String openOnGitHubAction();
}
diff --git a/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/action/OpenOnGitHubAction.java b/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/action/OpenOnGitHubAction.java
new file mode 100644
index 0000000000..1987674d58
--- /dev/null
+++ b/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/action/OpenOnGitHubAction.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.plugin.github.ide.action;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.web.bindery.event.shared.EventBus;
+import java.util.Collections;
+import org.eclipse.che.ide.api.action.ActionEvent;
+import org.eclipse.che.ide.api.action.BaseAction;
+import org.eclipse.che.ide.api.app.AppContext;
+import org.eclipse.che.ide.api.editor.EditorAgent;
+import org.eclipse.che.ide.api.editor.EditorPartPresenter;
+import org.eclipse.che.ide.api.editor.document.Document;
+import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
+import org.eclipse.che.ide.api.notification.NotificationManager;
+import org.eclipse.che.ide.api.parts.ActivePartChangedEvent;
+import org.eclipse.che.ide.api.parts.ActivePartChangedHandler;
+import org.eclipse.che.ide.api.resources.Project;
+import org.eclipse.che.ide.api.resources.Resource;
+import org.eclipse.che.ide.ext.git.client.GitServiceClient;
+import org.eclipse.che.ide.resource.Path;
+import org.eclipse.che.ide.util.browser.BrowserUtils;
+import org.eclipse.che.plugin.github.ide.GitHubLocalizationConstant;
+import org.eclipse.che.plugin.github.shared.GitHubUrlUtils;
+
+/** @author Vitalii Parfonov */
+@Singleton
+public class OpenOnGitHubAction extends BaseAction implements ActivePartChangedHandler {
+
+ private EditorAgent editorAgent;
+ private GitServiceClient gitServiceClient;
+ private final AppContext appContext;
+ private NotificationManager notificationManager;
+ private boolean editorInFocus;
+
+ @Inject
+ public OpenOnGitHubAction(
+ EditorAgent editorAgent,
+ GitHubLocalizationConstant locale,
+ GitServiceClient gitServiceClient,
+ EventBus eventBus,
+ AppContext appContext,
+ NotificationManager notificationManager) {
+ super(locale.openOnGitHubAction());
+ this.editorAgent = editorAgent;
+ this.gitServiceClient = gitServiceClient;
+ this.appContext = appContext;
+ this.notificationManager = notificationManager;
+ eventBus.addHandler(ActivePartChangedEvent.TYPE, this);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void update(ActionEvent event) {
+ final Resource resources = appContext.getResource();
+ String gitRepoUrl = resources.getProject().getAttribute("git.repository.remotes");
+ if (GitHubUrlUtils.isGitHubUrl(gitRepoUrl)) {
+ event.getPresentation().setEnabledAndVisible(true);
+ } else {
+ event.getPresentation().setEnabledAndVisible(false);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ if (editorInFocus) {
+ final EditorPartPresenter editorPart = editorAgent.getActiveEditor();
+ if (editorPart == null || !(editorPart instanceof TextEditor)) {
+ return;
+ }
+ Document document = ((TextEditor) editorPart).getDocument();
+ openOnGitHubUrl(document);
+ } else {
+ Resource resource = appContext.getResource();
+ openOnGitHubUrl(resource);
+ }
+ }
+
+ private void openOnGitHubUrl(Document document) {
+ Resource file = (Resource) document.getFile();
+ Project project = file.getProject();
+ Path projectPath = project.getLocation();
+ String httpsUrl = getGitHubRepositoryUrl(project);
+ String filePath = file.getLocation().makeRelativeTo(projectPath).toString();
+ int lineStart;
+ int lineEnd;
+ if (document.getSelectedTextRange() != null) {
+ lineStart = document.getSelectedTextRange().getFrom().getLine() + 1;
+ lineEnd = document.getSelectedTextRange().getTo().getLine() + 1;
+ } else {
+ lineStart = lineEnd = document.getCursorPosition().getLine() + 1;
+ }
+
+ gitServiceClient
+ .getStatus(projectPath, Collections.emptyList())
+ .then(
+ status -> {
+ String refName = status.getRefName();
+ String blobUrl =
+ GitHubUrlUtils.getBlobUrl(httpsUrl, refName, filePath, lineStart, lineEnd);
+ BrowserUtils.openInNewTab(blobUrl);
+ })
+ .catchError(
+ error -> {
+ notificationManager.notify("", error.getMessage());
+ });
+ }
+
+ private void openOnGitHubUrl(Resource resource) {
+ final Project project = resource.getProject();
+ Path projectPath = project.getLocation();
+ String httpsUrl = getGitHubRepositoryUrl(project);
+ String path = resource.getLocation().makeRelativeTo(projectPath).toString();
+ gitServiceClient
+ .getStatus(projectPath, Collections.emptyList())
+ .then(
+ status -> {
+ String url;
+ if (resource.isFile()) {
+ url = GitHubUrlUtils.getBlobUrl(httpsUrl, status.getRefName(), path);
+ } else {
+ url = GitHubUrlUtils.getTreeUrl(httpsUrl, status.getRefName(), path);
+ }
+ BrowserUtils.openInNewTab(url);
+ })
+ .catchError(
+ error -> {
+ notificationManager.notify("", error.getMessage());
+ });
+ }
+
+ private String getGitHubRepositoryUrl(Project project) {
+ String gitRepoUrl = project.getAttribute("git.repository.remotes");
+ return GitHubUrlUtils.toHttpsIfNeed(gitRepoUrl);
+ }
+
+ @Override
+ public void onActivePartChanged(ActivePartChangedEvent event) {
+ editorInFocus = event.getActivePart() instanceof EditorPartPresenter;
+ }
+}
diff --git a/plugins/plugin-github/che-plugin-github-shared/pom.xml b/plugins/plugin-github/che-plugin-github-shared/pom.xml
index c929ade8aa..758a6d0f1d 100644
--- a/plugins/plugin-github/che-plugin-github-shared/pom.xml
+++ b/plugins/plugin-github/che-plugin-github-shared/pom.xml
@@ -22,6 +22,10 @@
che-plugin-github-shared
Che Plugin :: Github :: Shared
+
+ com.google.guava
+ guava
+
org.eclipse.che.core
che-core-api-dto
@@ -30,5 +34,10 @@
org.eclipse.che.core
che-core-commons-annotations
+
+ org.testng
+ testng
+ test
+
diff --git a/plugins/plugin-github/che-plugin-github-shared/src/main/java/org/eclipse/che/plugin/github/shared/GitHubUrlUtils.java b/plugins/plugin-github/che-plugin-github-shared/src/main/java/org/eclipse/che/plugin/github/shared/GitHubUrlUtils.java
new file mode 100644
index 0000000000..369ddb396e
--- /dev/null
+++ b/plugins/plugin-github/che-plugin-github-shared/src/main/java/org/eclipse/che/plugin/github/shared/GitHubUrlUtils.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.plugin.github.shared;
+
+import com.google.common.base.Strings;
+
+public class GitHubUrlUtils {
+
+ /**
+ * normalize git@ and https:git@ urls
+ *
+ * @param gitUrl
+ * @return
+ */
+ public static String toHttpsIfNeed(String gitUrl) {
+ if (Strings.isNullOrEmpty(gitUrl)) {
+ return gitUrl;
+ }
+ String gitRepoUrl = gitUrl;
+
+ if (gitUrl.startsWith("git@")) {
+ // normalize git@ and https:git@ urls
+ gitRepoUrl = gitUrl.replaceFirst("git@", "https://");
+ gitRepoUrl = gitRepoUrl.replaceFirst(".com:", ".com/");
+ }
+ if (gitRepoUrl.endsWith(".git")) {
+ gitRepoUrl = gitRepoUrl.substring(0, gitRepoUrl.lastIndexOf(".git"));
+ }
+ return gitRepoUrl;
+ }
+
+ public static String getBlobUrl(String rootGitRepoUrl, String ref, String path) {
+ return getBlobUrl(rootGitRepoUrl, ref, path, 0, 0);
+ }
+
+ public static String getBlobUrl(
+ String rootGitRepoUrl, String ref, String path, int lineStart, int lineEnd) {
+ return rootGitRepoUrl
+ + "/blob/"
+ + ref
+ + "/"
+ + path
+ + (lineStart > 0 ? "#L" + lineStart : "")
+ + (lineEnd > 0 ? "-L" + lineEnd : "");
+ }
+
+ public static String getTreeUrl(String rootGitRepoUrl, String ref, String path) {
+ return rootGitRepoUrl + "/tree/" + ref + "/" + path;
+ }
+
+ public static boolean isGitHubUrl(String rootGitRepoUrl) {
+ if (Strings.isNullOrEmpty(rootGitRepoUrl)) {
+ return false;
+ }
+ return rootGitRepoUrl.startsWith("git@") || rootGitRepoUrl.startsWith("https://github.com");
+ }
+}
diff --git a/plugins/plugin-github/che-plugin-github-shared/src/test/java/org/eclipse/che/plugin/github/GitHUbUrlUtilsTest.java b/plugins/plugin-github/che-plugin-github-shared/src/test/java/org/eclipse/che/plugin/github/GitHUbUrlUtilsTest.java
new file mode 100644
index 0000000000..9772dbf9b6
--- /dev/null
+++ b/plugins/plugin-github/che-plugin-github-shared/src/test/java/org/eclipse/che/plugin/github/GitHUbUrlUtilsTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.plugin.github;
+
+import static org.testng.Assert.assertEquals;
+
+import org.eclipse.che.plugin.github.shared.GitHubUrlUtils;
+import org.testng.annotations.Test;
+
+public class GitHUbUrlUtilsTest {
+
+ private String HTTPS_URL = "https://github.com/che-samples/web-java-spring-petclinic";
+ private String SOME_PATH = "che/samples/web-java-spring-petclinic";
+ private String SSH_URL = "git@github.com:che-samples/web-java-spring-petclinic.git";
+ private String BLOB_URL =
+ "https://github.com/che-samples/web-java-spring-petclinic/blob/mysql/src/test/java/org/springframework"
+ + "/samples/petclinic/service/ClinicServiceJdbcTests.java";
+ private String FILE =
+ "src/test/java/org/springframework"
+ + "/samples/petclinic/service/ClinicServiceJdbcTests.java";
+
+ @Test
+ public void shouldConvertToHttps() {
+ String https = GitHubUrlUtils.toHttpsIfNeed(SSH_URL);
+ assertEquals(https, HTTPS_URL);
+ }
+
+ @Test
+ public void shouldReturnSameUrl() {
+ String https = GitHubUrlUtils.toHttpsIfNeed(HTTPS_URL);
+ assertEquals(https, HTTPS_URL);
+ }
+
+ @Test
+ public void blobUrl() {
+ String blobUrl =
+ GitHubUrlUtils.getBlobUrl(
+ HTTPS_URL,
+ "mysql",
+ "src/test/java/org/springframework"
+ + "/samples/petclinic/service/ClinicServiceJdbcTests.java");
+ assertEquals(blobUrl, BLOB_URL);
+ }
+
+ @Test
+ public void blobUrlWithLines() {
+ String blobUrl =
+ GitHubUrlUtils.getBlobUrl(
+ HTTPS_URL,
+ "mysql",
+ "src/test/java/org/springframework"
+ + "/samples/petclinic/service/ClinicServiceJdbcTests.java",
+ 10,
+ 20);
+ assertEquals(blobUrl, BLOB_URL + "#L10-L20");
+ }
+
+ @Test
+ public void getTreeUrl() {
+ String rootGitRepoUrl = "https://github.com/eclipse/che/";
+ String ref = "master";
+ String path = "assembly/assembly-wsmaster-war";
+ String getTreeUrl = GitHubUrlUtils.getTreeUrl(rootGitRepoUrl, ref, path);
+ assertEquals(getTreeUrl, rootGitRepoUrl + "/tree/" + ref + "/" + path);
+ }
+}
diff --git a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/client/TestProjectServiceClient.java b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/client/TestProjectServiceClient.java
index e37f4aadd0..adaf409425 100644
--- a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/client/TestProjectServiceClient.java
+++ b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/client/TestProjectServiceClient.java
@@ -25,10 +25,12 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.che.api.core.model.workspace.config.ProjectConfig;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
+import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.commons.lang.IoUtil;
import org.eclipse.che.commons.lang.ZipUtils;
import org.eclipse.che.selenium.core.provider.TestWorkspaceAgentApiEndpointUrlProvider;
@@ -147,6 +149,35 @@ public class TestProjectServiceClient {
importZipProject(workspaceId, zip, projectName, template);
}
+ /** Import project from file system into a user workspace */
+ public void importProject(
+ String workspaceId,
+ String projectName,
+ String location,
+ String type,
+ Map parameters)
+ throws Exception {
+ SourceStorageDto source = getInstance().createDto(SourceStorageDto.class);
+ source.setLocation(location);
+ source.setType(type);
+ source.setParameters(parameters);
+
+ importProject(workspaceId, projectName, source);
+ }
+
+ /** Import project from file system into a user workspace */
+ public void importProject(String workspaceId, String projectName, SourceStorageDto source)
+ throws Exception {
+
+ requestFactory
+ .fromUrl(
+ workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project/import/" + projectName)
+ .usePostMethod()
+ .setAuthorizationHeader(machineServiceClient.getMachineApiToken(workspaceId))
+ .setBody(source)
+ .request();
+ }
+
/** Creates file in the project. */
public void createFileInProject(
String workspaceId, String parentFolder, String fileName, String content) throws Exception {
diff --git a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/webdriver/SeleniumWebDriverHelper.java b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/webdriver/SeleniumWebDriverHelper.java
index 4446cd1472..c68de67ce5 100644
--- a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/webdriver/SeleniumWebDriverHelper.java
+++ b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/webdriver/SeleniumWebDriverHelper.java
@@ -1393,4 +1393,9 @@ public class SeleniumWebDriverHelper {
public void waitSuccessCondition(ExpectedCondition expression) {
waitSuccessCondition(expression, DEFAULT_TIMEOUT);
}
+
+ public void closeCurrentWindowAndSwitchToAnother(String windowToSwitch) {
+ seleniumWebDriver.close();
+ seleniumWebDriver.switchTo().window(windowToSwitch);
+ }
}
diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/constant/TestProjectExplorerContextMenuConstants.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/constant/TestProjectExplorerContextMenuConstants.java
index 59dc705531..b757fb379a 100644
--- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/constant/TestProjectExplorerContextMenuConstants.java
+++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/constant/TestProjectExplorerContextMenuConstants.java
@@ -27,6 +27,7 @@ public final class TestProjectExplorerContextMenuConstants {
GO_INTO("gwt-debug-contextMenu/goInto"),
GO_BACK("gwt-debug-contextMenu/goInto"),
OPEN_IN_TERMINAL("gwt-debug-contextMenu/openInTerminal"),
+ OPEN_ON_GITHUB("gwt-debug-contextMenu/openOnGitHub"),
CUT("gwt-debug-contextMenu/cut"),
COPY("gwt-debug-contextMenu/copy"),
PASTE("gwt-debug-contextMenu/paste"),
diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/CodenvyEditor.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/CodenvyEditor.java
index 6610a3d74f..e18459d13a 100644
--- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/CodenvyEditor.java
+++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/CodenvyEditor.java
@@ -269,6 +269,7 @@ public class CodenvyEditor {
OPEN_DECLARATION(By.id("contextMenu/Open Declaration")),
NAVIGATE_FILE_STRUCTURE(By.id("contextMenu/Navigate File Structure")),
FIND(By.id("contextMenu/Find")),
+ OPEN_ON_GITHUB(By.id("contextMenu/Open on GitHub")),
CLOSE(By.id("contextMenu/Close"));
@SuppressWarnings("ImmutableEnumChecker")
@@ -655,6 +656,23 @@ public class CodenvyEditor {
waitCursorPosition(positionLine, positionChar);
}
+ /**
+ * Select text in defined interval
+ *
+ * @param fromLine beginning of first line for selection
+ * @param numberOfLine end of first line for selection
+ */
+ public void selectLines(int fromLine, int numberOfLine) {
+ Actions action = seleniumWebDriverHelper.getAction(seleniumWebDriver);
+ setCursorToLine(fromLine);
+ action.keyDown(SHIFT).perform();
+ for (int i = 0; i < numberOfLine; i++) {
+ typeTextIntoEditor(Keys.ARROW_DOWN.toString());
+ }
+ action.keyUp(SHIFT).perform();
+ action.sendKeys(Keys.END.toString()).keyUp(SHIFT).perform();
+ }
+
/**
* Sets cursor to specified {@code positionLine} and {@code positionChar}.
*
diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/ProjectExplorer.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/ProjectExplorer.java
index 7f051ff6d3..6f6a444c8a 100644
--- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/ProjectExplorer.java
+++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/ProjectExplorer.java
@@ -681,6 +681,13 @@ public class ProjectExplorer {
By.id(ContextMenuFirstLevelItems.NEW.get()), WIDGET_TIMEOUT_SEC);
}
+ /** Waits on context menu item is not visible */
+ public void waitContexMenuItemIsNotVisible(ContextMenuItems item) {
+ waitContextMenu();
+ seleniumWebDriverHelper.waitInvisibility(
+ By.xpath(format("//tr[@item-enabled='true' and @id='%s']", item.get())));
+ }
+
/**
* Clicks on element from context menu by specified {@code itemId}
*
diff --git a/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/git/OpenOnGitHubTest.java b/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/git/OpenOnGitHubTest.java
new file mode 100644
index 0000000000..1601eb474a
--- /dev/null
+++ b/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/git/OpenOnGitHubTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.selenium.git;
+
+import static org.eclipse.che.commons.lang.NameGenerator.generate;
+import static org.eclipse.che.selenium.pageobject.CodenvyEditor.ContextMenuLocator.OPEN_ON_GITHUB;
+import static org.eclipse.che.selenium.pageobject.Wizard.TypeProject.BLANK;
+import static org.openqa.selenium.support.ui.ExpectedConditions.*;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.eclipse.che.selenium.core.SeleniumWebDriver;
+import org.eclipse.che.selenium.core.client.TestGitHubRepository;
+import org.eclipse.che.selenium.core.client.TestProjectServiceClient;
+import org.eclipse.che.selenium.core.client.TestUserPreferencesServiceClient;
+import org.eclipse.che.selenium.core.constant.TestProjectExplorerContextMenuConstants;
+import org.eclipse.che.selenium.core.project.ProjectTemplates;
+import org.eclipse.che.selenium.core.user.DefaultTestUser;
+import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverHelper;
+import org.eclipse.che.selenium.core.workspace.TestWorkspace;
+import org.eclipse.che.selenium.pageobject.CheTerminal;
+import org.eclipse.che.selenium.pageobject.CodenvyEditor;
+import org.eclipse.che.selenium.pageobject.Ide;
+import org.eclipse.che.selenium.pageobject.ProjectExplorer;
+import org.eclipse.che.selenium.pageobject.git.Git;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Test "Open on Github" action. Will check action calling from context menu on selected project,
+ * folder and file
+ *
+ * @author Vitalii Parfonov
+ */
+public class OpenOnGitHubTest {
+ private static final String PROJECT_NAME = generate("project", 4);
+ private static final String PROJECT_WITHOUT_GIT_FOLDER = "projectWithoutGitCVS";
+ private static final String PATH_TO_EXPAND = "src/main/java/che/eclipse/sample";
+ private String mainBrowserTabHandle;
+
+ @Inject private TestWorkspace workspace;
+
+ @SuppressWarnings("unused")
+ @Inject
+ private Ide ide;
+
+ @SuppressWarnings("unused")
+ @Inject
+ private ProjectExplorer projectExplorer;
+
+ @SuppressWarnings("unused")
+ @Inject
+ private TestProjectServiceClient testProjectServiceClient;
+
+ @SuppressWarnings("unused")
+ @Inject
+ private CheTerminal terminal;
+
+ @SuppressWarnings("unused")
+ @Inject
+ private SeleniumWebDriverHelper seleniumWebDriverHelper;
+
+ @SuppressWarnings("unused")
+ @Inject
+ private SeleniumWebDriver seleniumWebDriver;
+
+ @Inject private CodenvyEditor editor;
+
+ @Inject private TestUserPreferencesServiceClient testUserPreferencesServiceClient;
+
+ @Inject private DefaultTestUser productUser;
+
+ @Inject private TestGitHubRepository testRepo;
+
+ @Inject
+ @Named("github.username")
+ private String gitHubUsername;
+
+ @Inject private Git git;
+
+ @BeforeClass
+ public void setUp() throws Exception {
+ testUserPreferencesServiceClient.addGitCommitter(gitHubUsername, productUser.getEmail());
+ Path entryPath =
+ Paths.get(getClass().getResource("/projects/default-spring-project").getPath());
+ testProjectServiceClient.importProject(
+ workspace.getId(), entryPath, PROJECT_WITHOUT_GIT_FOLDER, ProjectTemplates.MAVEN_SPRING);
+
+ testRepo.addContent(entryPath);
+ ide.open(workspace);
+ mainBrowserTabHandle = seleniumWebDriver.getWindowHandle();
+ git.importJavaApp(testRepo.getHtmlUrl(), PROJECT_NAME, BLANK);
+ projectExplorer.waitItem(PROJECT_NAME);
+ projectExplorer.quickExpandWithJavaScript();
+ }
+
+ @AfterMethod
+ public void returnToMainWindow() {
+ if (seleniumWebDriver.getWindowHandles().size() > 1) {
+ seleniumWebDriverHelper.closeCurrentWindowAndSwitchToAnother(mainBrowserTabHandle);
+ }
+ }
+
+ @Test
+ public void checkProjectWithoutGitFolder() {
+ projectExplorer.openContextMenuByPathSelectedItem(PROJECT_WITHOUT_GIT_FOLDER);
+ projectExplorer.waitContexMenuItemIsNotVisible(
+ TestProjectExplorerContextMenuConstants.ContextMenuFirstLevelItems.OPEN_ON_GITHUB);
+ // for closing context menu
+ projectExplorer.clickOnItemInContextMenu(
+ TestProjectExplorerContextMenuConstants.ContextMenuFirstLevelItems.COPY);
+ }
+
+ @Test(priority = 1)
+ public void openProjectOnGitHubTest() {
+ projectExplorer.waitAndSelectItem(PROJECT_NAME, 5);
+ projectExplorer.openContextMenuByPathSelectedItem(PROJECT_NAME);
+ projectExplorer.waitContextMenu();
+ projectExplorer.clickOnItemInContextMenu(
+ TestProjectExplorerContextMenuConstants.ContextMenuFirstLevelItems.OPEN_ON_GITHUB);
+ seleniumWebDriverHelper.switchToNextWindow(seleniumWebDriver.getWindowHandle());
+ seleniumWebDriverHelper.waitSuccessCondition(urlToBe(testRepo.getHtmlUrl() + "/tree/master/"));
+ }
+
+ @Test(priority = 2)
+ public void openFolderOnGitHubTest() {
+ projectExplorer.waitAndSelectItem(PROJECT_NAME + "/" + PATH_TO_EXPAND, 5);
+ projectExplorer.waitAndSelectItem(PROJECT_NAME + "/" + PATH_TO_EXPAND, 5);
+ projectExplorer.openContextMenuByPathSelectedItem(PROJECT_NAME + "/" + PATH_TO_EXPAND);
+ projectExplorer.waitContextMenu();
+ projectExplorer.clickOnItemInContextMenu(
+ TestProjectExplorerContextMenuConstants.ContextMenuFirstLevelItems.OPEN_ON_GITHUB);
+ seleniumWebDriverHelper.switchToNextWindow(seleniumWebDriver.getWindowHandle());
+ seleniumWebDriverHelper.waitSuccessCondition(
+ urlToBe(testRepo.getHtmlUrl() + "/tree/master/" + PATH_TO_EXPAND));
+ }
+
+ @Test(priority = 3)
+ public void openFileOnGitHubTest() {
+ projectExplorer.openItemByPath(PROJECT_NAME + "/" + PATH_TO_EXPAND + "/Aclass.java");
+ editor.selectLines(14, 1);
+ editor.openContextMenuInEditor();
+ editor.clickOnItemInContextMenu(OPEN_ON_GITHUB);
+ seleniumWebDriverHelper.switchToNextWindow(seleniumWebDriver.getWindowHandle());
+ seleniumWebDriverHelper.waitSuccessCondition(
+ urlToBe(testRepo.getHtmlUrl() + "/blob/master/" + PATH_TO_EXPAND + "/Aclass.java#L15-L15"));
+ }
+}