diff --git a/.idea/modules.xml b/.idea/modules.xml
index 8f16bb372d09..5201ba96b116 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -59,6 +59,7 @@
+
diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml
index e093416f9e51..2298a387ff7a 100644
--- a/plugins/git4idea/src/META-INF/plugin.xml
+++ b/plugins/git4idea/src/META-INF/plugin.xml
@@ -160,9 +160,10 @@
serviceImplementation="git4idea.remote.GitRememberedInputs"/>
-
+
diff --git a/plugins/git4idea/src/git4idea/DialogManager.java b/plugins/git4idea/src/git4idea/DialogManager.java
new file mode 100644
index 000000000000..585862165c0a
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/DialogManager.java
@@ -0,0 +1,25 @@
+package git4idea;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.ui.DialogWrapper;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Use {@link DialogManager#show(DialogWrapper) DialogManager.show(DialogWrapper)} instead of {@link DialogWrapper#show()}
+ * to make the code testable:
+ * in the test environment such calls will be transferred to the TestDialogManager and can be handled by tests;
+ * in the production environment they will be simply delegated to DialogWrapper#show().
+ *
+ * @author Kirill Likhodedov
+ */
+public class DialogManager {
+
+ public static void show(@NotNull DialogWrapper dialog) {
+ ServiceManager.getService(DialogManager.class).showDialog(dialog);
+ }
+
+ protected void showDialog(@NotNull DialogWrapper dialog) {
+ dialog.show();
+ }
+
+}
diff --git a/plugins/git4idea/testFramework/META-INF/plugin.xml b/plugins/git4idea/testFramework/META-INF/plugin.xml
index 90ca43720e5c..6ecf51797de2 100644
--- a/plugins/git4idea/testFramework/META-INF/plugin.xml
+++ b/plugins/git4idea/testFramework/META-INF/plugin.xml
@@ -10,6 +10,9 @@
+
{
+public interface TestDialogHandler {
+
/**
- * Do something with dialog fields and return the exit code - as if user pressed one of exit buttons.
+ * Do something with the dialog (modify its instance fields, for example)
+ * and return the exit code - as if user pressed one of exit buttons.
+ *
* @param dialog dialog to be handled.
- * @return DialogWrapper exit code, for example, {@link com.intellij.openapi.ui.DialogWrapper#OK_EXIT_CODE}.
+ * @return DialogWrapper exit code, for example, {@link DialogWrapper#OK_EXIT_CODE}.
*/
int handleDialog(T dialog);
+
}
diff --git a/plugins/git4idea/testFramework/git4idea/test/TestDialogManager.java b/plugins/git4idea/testFramework/git4idea/test/TestDialogManager.java
index 0bb946986463..513c4f964cf3 100644
--- a/plugins/git4idea/testFramework/git4idea/test/TestDialogManager.java
+++ b/plugins/git4idea/testFramework/git4idea/test/TestDialogManager.java
@@ -16,27 +16,16 @@
package git4idea.test;
import com.intellij.openapi.ui.DialogWrapper;
-import org.jetbrains.annotations.Nullable;
+import com.intellij.util.containers.ContainerUtil;
+import git4idea.DialogManager;
+import org.jetbrains.annotations.NotNull;
-import java.lang.reflect.Field;
-import java.util.HashMap;
import java.util.Map;
/**
- * TestDialogManager instead of showing the dialog, gives the control to a {@link TestDialogHandler} which can specify the dialog exit code
- * (thus simulation different user choices) or even change other elements in the dialog.
- * To use it a test should:
- *
- * - register {@link TestDialogManager} as the {@link DialogManager} implementation:
- *
- * String key = "git4idea.DialogManager";
- * MutablePicoContainer picoContainer = (MutablePicoContainer) myProject.getPicoContainer();
- * picoContainer.unregisterComponent(key);
- * picoContainer.registerComponentImplementation(key, TestDialogManager.class);
- * TestDialogManager dialogManager = (TestDialogManager)DialogManager.getInstance(myProject);
- *
- *
- * - register its {@link TestDialogHandler}:
+ *
TestDialogManager instead of showing the dialog, gives the control to a {@link git4idea.test.TestDialogHandler} which can specify the dialog exit code
+ * (thus simulation different user choices) or even change other elements in the dialog.
+ * To use it a test should register the {@link TestDialogHandler} implementation. For example:
*
* myDialogManager.registerDialogHandler(GitConvertFilesDialog.class, new TestDialogHandler() {
* @Override public int handleDialog(GitConvertFilesDialog dialog) {
@@ -44,48 +33,24 @@ import java.util.Map;
* return GitConvertFilesDialog.OK_EXIT_CODE;
* }
* });
- *
+ *
+ * Only one TestDialogHandler can be registered per test for a certain DialogWrapper class.
* @see TestDialogHandler
* @author Kirill Likhodedov
*/
-public class TestDialogManager {
+public class TestDialogManager extends DialogManager {
- private Map myHandlers = new HashMap();
+ private final Map myHandlers = ContainerUtil.newHashMap();
- private DialogWrapper myLastShownDialog;
-
- public void show(DialogWrapper dialog) throws IllegalAccessException, NoSuchFieldException {
- final TestDialogHandler handler = myHandlers.get(dialog.getClass());
- int exitCode = DialogWrapper.OK_EXIT_CODE;
- if (handler != null) {
- exitCode = handler.handleDialog(dialog);
- }
- closeDialog(dialog, exitCode);
- myLastShownDialog = dialog;
+ @Override
+ protected void showDialog(@NotNull DialogWrapper dialog) {
+ TestDialogHandler handler = myHandlers.get(dialog.getClass());
+ int exitCode = handler != null ? handler.handleDialog(dialog) : DialogWrapper.OK_EXIT_CODE;
+ dialog.close(exitCode, exitCode == DialogWrapper.OK_EXIT_CODE);
}
- private static void closeDialog(DialogWrapper dialog, int exitCode) throws NoSuchFieldException, IllegalAccessException {
- Field exitCodeField = DialogWrapper.class.getDeclaredField("myExitCode");
- exitCodeField.setAccessible(true);
- exitCodeField.set(dialog, exitCode);
-
- Field closedField = DialogWrapper.class.getDeclaredField("myClosed");
- closedField.setAccessible(true);
- closedField.set(dialog, true);
- }
-
- /**
- * Registers the dialog handler. Note that a test may register only one handler for one dialog type.
- * For different dialog types it may register different handlers.
- * @param dialogClass class of the dialog which will be handled instead of showing (dialog itself have to support this in its show() method).
- * @param handler handler which will be invoked when dialog is about to show.
- */
- public void registerDialogHandler(Class dialogClass, TestDialogHandler handler) {
+ public void registerDialogHandler(@NotNull Class extends DialogWrapper> dialogClass, @NotNull TestDialogHandler handler) {
myHandlers.put(dialogClass, handler);
}
- @Nullable
- public DialogWrapper getLastShownDialog() {
- return myLastShownDialog;
- }
}
diff --git a/plugins/git4idea/testFramework/git4idea/test/TestNotificator.java b/plugins/git4idea/testFramework/git4idea/test/TestNotificator.java
index 143d6f0d93c7..5ec1af3ae81c 100644
--- a/plugins/git4idea/testFramework/git4idea/test/TestNotificator.java
+++ b/plugins/git4idea/testFramework/git4idea/test/TestNotificator.java
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable;
*/
public class TestNotificator extends Notificator {
- private static final String TEST_NOTIFICATION_GROUP = "Test";
+ public static final String TEST_NOTIFICATION_GROUP = "Test";
private Notification myLastNotification;
public TestNotificator(@NotNull Project project) {
@@ -40,6 +40,10 @@ public class TestNotificator extends Notificator {
return myLastNotification;
}
+ public void notify(@NotNull Notification notification) {
+ myLastNotification = notification;
+ }
+
public void notify(@NotNull NotificationGroup notificationGroup, @NotNull String title, @NotNull String message, @NotNull NotificationType type) {
notify(notificationGroup, title, message, type, null);
}
diff --git a/plugins/github/github-test/github-test.iml b/plugins/github/github-test/github-test.iml
new file mode 100644
index 000000000000..2924f3eb6f79
--- /dev/null
+++ b/plugins/github/github-test/github-test.iml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/github/github-test/test/org/jetbrains/plugins/github/GithubShareTest.java b/plugins/github/github-test/test/org/jetbrains/plugins/github/GithubShareTest.java
new file mode 100644
index 000000000000..14a52112f308
--- /dev/null
+++ b/plugins/github/github-test/test/org/jetbrains/plugins/github/GithubShareTest.java
@@ -0,0 +1,57 @@
+package org.jetbrains.plugins.github;
+
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.testFramework.TestActionEvent;
+import git4idea.test.TestDialogHandler;
+import git4idea.test.TestNotificator;
+import org.jetbrains.plugins.github.test.GithubTest;
+import org.jetbrains.plugins.github.ui.GithubShareDialog;
+
+import static git4idea.test.GitTestUtil.assertNotification;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class GithubShareTest extends GithubTest {
+
+ private static final String PROJECT_NAME = "new_project_from_test";
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ removeCreatedProject();
+ super.tearDown();
+ }
+
+ private void removeCreatedProject() {
+ // TODO: send a request to GitHub to remove the created project
+ }
+
+ public void testSimpleCase() throws Throwable {
+ myDialogManager.registerDialogHandler(GithubShareDialog.class, new TestDialogHandler() {
+ @Override
+ public int handleDialog(GithubShareDialog dialog) {
+ dialog.setRepositoryName(PROJECT_NAME);
+ return DialogWrapper.OK_EXIT_CODE;
+ }
+ });
+
+ // TODO: refactor the production code to avoid programmatically invoking the action with a fake data context
+ AnAction shareAction = ActionManager.getInstance().getAction("Github.Share");
+ shareAction.actionPerformed(new TestActionEvent(shareAction));
+
+ assertNotification(myProject, new Notification(TestNotificator.TEST_NOTIFICATION_GROUP, "Success",
+ "Successfully created project '" + PROJECT_NAME + "' on GitHub",
+ NotificationType.INFORMATION));
+ // TODO check that the project was created on github, and the repository was created locally and pushed there
+ }
+
+}
diff --git a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java b/plugins/github/github-test/test/org/jetbrains/plugins/github/test/GithubTest.java
similarity index 51%
rename from plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
rename to plugins/github/github-test/test/org/jetbrains/plugins/github/test/GithubTest.java
index f64d9e466739..1c90ea791b25 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
+++ b/plugins/github/github-test/test/org/jetbrains/plugins/github/test/GithubTest.java
@@ -15,40 +15,56 @@
*/
package org.jetbrains.plugins.github.test;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
+import com.intellij.util.PlatformUtilsCore;
+import git4idea.DialogManager;
+import git4idea.Notificator;
import git4idea.config.GitVcsSettings;
import git4idea.test.GitExecutor;
+import git4idea.test.TestDialogManager;
+import git4idea.test.TestNotificator;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.github.GithubSettings;
-import static com.intellij.dvcs.test.Executor.cd;
-import static git4idea.test.GitExecutor.git;
+import static org.junit.Assume.assumeNotNull;
/**
- * The base class for JUnit platform tests of the github plugin.
- * Extend this test to write a test on GitHub which has the following features/limitations:
+ * The base class for JUnit platform tests of the github plugin.
+ * Extend this test to write a test on GitHub which has the following features/limitations:
*
* - This is a "platform test case", which means that IDEA [almost] production platform is set up before the test starts.
* - Project base directory is the root of everything.
- *
+ *
+ * All tests inherited from this class are required to have a login and a password to access the Github server.
+ * They are set up in System properties:
+ * -Dtest.github.login=mylogin
+ * -Dtest.github.password=mypassword
+ *
*
* @author Kirill Likhodedov
*/
public abstract class GithubTest extends UsefulTestCase {
+ @NotNull protected static final String HOST = "github.com";
+
@NotNull protected Project myProject;
@NotNull protected VirtualFile myProjectRoot;
- @NotNull protected GitVcsSettings mySettings;
+ @NotNull protected GitVcsSettings myGitSettings;
+ @NotNull protected GithubSettings myGitHubSettings;
+
+ @NotNull protected TestDialogManager myDialogManager;
+ @NotNull protected TestNotificator myNotificator;
@NotNull private IdeaProjectTestFixture myProjectFixture;
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors", "UnusedDeclaration"})
protected GithubTest() {
- PlatformTestCase.initPlatformLangPrefix();
+ System.setProperty(PlatformUtilsCore.PLATFORM_PREFIX_KEY, "PlatformLangXml");
}
@Override
@@ -60,11 +76,23 @@ public abstract class GithubTest extends UsefulTestCase {
myProject = myProjectFixture.getProject();
myProjectRoot = myProject.getBaseDir();
- cd(myProjectRoot);
- git("version");
+ String login = System.getProperty("test.github.login");
+ String password = System.getProperty("test.github.password");
- mySettings = GitVcsSettings.getInstance(myProject);
- mySettings.getAppSettings().setPathToGit(GitExecutor.GIT_EXECUTABLE);
+ // TODO change to assert when a stable Github testing server is ready
+ assumeNotNull(login);
+ assumeNotNull(password);
+
+ myGitSettings = GitVcsSettings.getInstance(myProject);
+ myGitSettings.getAppSettings().setPathToGit(GitExecutor.GIT_EXECUTABLE);
+
+ myGitHubSettings = GithubSettings.getInstance();
+ myGitHubSettings.setHost(HOST);
+ myGitHubSettings.setLogin(login);
+ myGitHubSettings.setPassword(password);
+
+ myDialogManager = (TestDialogManager)ServiceManager.getService(DialogManager.class);
+ myNotificator = (TestNotificator)ServiceManager.getService(myProject, Notificator.class);
}
@Override
diff --git a/plugins/github/github.iml b/plugins/github/github.iml
index ea922cfeadc6..2ed64b7ebcd6 100644
--- a/plugins/github/github.iml
+++ b/plugins/github/github.iml
@@ -5,7 +5,7 @@
-
+
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
index 12c193802a92..cfbcc6367fb3 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
@@ -28,13 +28,13 @@ import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsShowConfirmationOption;
import com.intellij.openapi.vcs.changes.ui.SelectFilesDialog;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ThrowableConsumer;
import com.intellij.util.containers.HashSet;
+import git4idea.DialogManager;
import git4idea.GitLocalBranch;
import git4idea.GitUtil;
import git4idea.GitVcs;
@@ -162,7 +162,8 @@ public class GithubShareAction extends DumbAwareAction {
// Show dialog (window)
final GithubShareDialog shareDialog =
new GithubShareDialog(project, repoNamesRef.get(), userInfoRef.get().getMaxPrivateRepos() > userInfoRef.get().getPrivateRepos());
- shareDialog.show();
+ //shareDialog.show();
+ DialogManager.show(shareDialog);
if (!shareDialog.isOK()) {
return;
}
@@ -342,7 +343,7 @@ public class GithubShareAction extends DumbAwareAction {
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
- dialog.show();
+ DialogManager.show(dialog);
}
}, indicator.getModalityState());
final Collection files2add = dialog.getSelectedFiles();
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java
index 1ace8a699d98..974fb4192980 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java
@@ -4,6 +4,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.Set;
@@ -83,4 +84,9 @@ public class GithubShareDialog extends DialogWrapper {
public String getDescription() {
return myGithubSharePanel.getDescription();
}
+
+ @TestOnly
+ public void setRepositoryName(@NotNull String name) {
+ myGithubSharePanel.setRepositoryName(name);
+ }
}