gui-tests-framework: fixed branch after rebase (added missed fixtures); migrate to TransactionGuard policy in GuiTestBase; tests fixes

This commit is contained in:
Sergey Karashevich
2016-10-09 17:59:25 +03:00
parent e6941b799b
commit 49c5167d2c
100 changed files with 207 additions and 8595 deletions
+2 -24
View File
@@ -3,31 +3,9 @@
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/testsSrc" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="core-api" />
<orderEntry type="library" name="fest" level="project" />
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="testFramework" />
<orderEntry type="module" module-name="java-psi-api" />
<orderEntry type="module" module-name="bootstrap" />
<orderEntry type="module" module-name="external-system-rt" />
<orderEntry type="module" module-name="xdebugger-impl" />
<orderEntry type="module" module-name="external-system-impl" />
<orderEntry type="module" module-name="openapi" />
<orderEntry type="module" module-name="lint-api" />
<orderEntry type="module" module-name="testRunner" />
<orderEntry type="module" module-name="idea-ui" />
<orderEntry type="module" module-name="dvcs-impl" />
<orderEntry type="module" module-name="annotations" />
<orderEntry type="module" module-name="main_idea_tests" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="library" name="JUnit4" level="project" />
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="execution-impl" />
<orderEntry type="module" module-name="compiler-openapi" />
</component>
</module>
@@ -1,12 +0,0 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<uiDropperActions implementation="com.intellij.tests.gui.script.ScriptRecorder"/>
</extensions>
<actions>
<action class="com.intellij.tests.gui.script.ScriptRunnerAction" id="ScriptRunnerAction" text="Script Runner Action"
description="Add GUI tests to action list"/>
<action class="com.intellij.tests.gui.script.ScriptCompileAction" id="ScriptCompileAction" text="Script Compile Action"
description="Compile current script"/>
</actions>
</idea-plugin>
@@ -1,114 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.util.Ref;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.exception.ComponentLookupException;
import org.fest.swing.timing.Condition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.Collection;
import static com.intellij.tests.gui.framework.GuiTests.LONG_TIMEOUT;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static com.intellij.util.containers.ContainerUtil.getFirstItem;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.timing.Pause.pause;
public class ActionButtonFixture extends JComponentFixture<ActionButtonFixture, ActionButton> {
@NotNull
public static ActionButtonFixture findByActionId(@NotNull final String actionId,
@NotNull final Robot robot,
@NotNull final Container container) {
final Ref<ActionButton> actionButtonRef = new Ref<ActionButton>();
pause(new Condition("Find ActionButton with ID '" + actionId + "'") {
@Override
public boolean test() {
Collection<ActionButton> found = robot.finder().findAll(container, new GenericTypeMatcher<ActionButton>(ActionButton.class) {
@Override
protected boolean isMatching(@NotNull ActionButton button) {
if (button.isVisible()) {
AnAction action = button.getAction();
if (action != null) {
String id = ActionManager.getInstance().getId(action);
return actionId.equals(id);
}
}
return false;
}
});
if (found.size() == 1) {
actionButtonRef.set(getFirstItem(found));
return true;
}
return false;
}
}, SHORT_TIMEOUT);
ActionButton button = actionButtonRef.get();
if (button == null) {
throw new ComponentLookupException("Failed to find ActionButton with ID '" + actionId + "'");
}
return new ActionButtonFixture(robot, button);
}
@NotNull
public ActionButtonFixture waitUntilEnabledAndShowing() {
pause(new Condition("wait for action to be enabled and showing") {
@Override
public boolean test() {
//noinspection ConstantConditions
return execute(new GuiQuery<Boolean>() {
@Nullable
@Override
protected Boolean executeInEDT() throws Throwable {
ActionButton target = target();
if (target.getAction().getTemplatePresentation().isEnabledAndVisible()) {
return target.isShowing() && target.isVisible() && target.isEnabled();
}
return false;
}
});
}
}, LONG_TIMEOUT);
return this;
}
@NotNull
public static ActionButtonFixture findByText(@NotNull final String text, @NotNull Robot robot, @NotNull Container container) {
final ActionButton button = robot.finder().find(container, new GenericTypeMatcher<ActionButton>(ActionButton.class) {
@Override
protected boolean isMatching(@NotNull ActionButton button) {
AnAction action = button.getAction();
return text.equals(action.getTemplatePresentation().getText());
}
});
return new ActionButtonFixture(robot, button);
}
private ActionButtonFixture(@NotNull Robot robot, @NotNull ActionButton target) {
super(ActionButtonFixture.class, robot, target);
}
}
@@ -1,107 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import org.fest.swing.core.Robot;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.util.Ref;
import com.intellij.ui.components.labels.ActionLink;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.exception.ComponentLookupException;
import org.fest.swing.timing.Condition;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.Collection;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static com.intellij.util.containers.ContainerUtil.getFirstItem;
import static org.fest.swing.timing.Pause.pause;
public class ActionLinkFixture extends JComponentFixture<ActionLinkFixture, ActionLink> {
@NotNull
public static ActionLinkFixture findByActionId(@NotNull final String actionId,
@NotNull final Robot robot,
@NotNull final Container container) {
final Ref<ActionLink> actionLinkRef = new Ref<ActionLink>();
pause(new Condition("Find ActionLink with ID '" + actionId + "'") {
@Override
public boolean test() {
Collection<ActionLink> found = robot.finder().findAll(container, new GenericTypeMatcher<ActionLink>(ActionLink.class) {
@Override
protected boolean isMatching(@NotNull ActionLink actionLink) {
if (actionLink.isVisible()) {
AnAction action = actionLink.getAction();
String id = ActionManager.getInstance().getId(action);
return actionId.equals(id);
}
return false;
}
});
if (found.size() == 1) {
actionLinkRef.set(getFirstItem(found));
return true;
}
return false;
}
}, SHORT_TIMEOUT);
ActionLink actionLink = actionLinkRef.get();
if (actionLink == null) {
throw new ComponentLookupException("Failed to find ActionLink with ID '" + actionId + "'");
}
return new ActionLinkFixture(robot, actionLink);
}
@NotNull
public static ActionLinkFixture findActionLinkByName(@NotNull final String actionName,
@NotNull final Robot robot,
@NotNull final Container container) {
final Ref<ActionLink> actionLinkRef = new Ref<ActionLink>();
pause(new Condition("Find ActionLink with name '" + actionName + "'") {
@Override
public boolean test() {
Collection<ActionLink> found = robot.finder().findAll(container, new GenericTypeMatcher<ActionLink>(ActionLink.class) {
@Override
protected boolean isMatching(@NotNull ActionLink actionLink) {
if (actionLink.isVisible()) {
return actionLink.getText().equals(actionName);
}
return false;
}
});
if (found.size() == 1) {
actionLinkRef.set(getFirstItem(found));
return true;
}
return false;
}
}, SHORT_TIMEOUT);
ActionLink actionLink = actionLinkRef.get();
if (actionLink == null) {
throw new ComponentLookupException("Failed to find ActionLink with name '" + actionName + "'");
}
return new ActionLinkFixture(robot, actionLink);
}
private ActionLinkFixture(@NotNull Robot robot, @NotNull ActionLink target) {
super(ActionLinkFixture.class, robot, target);
}
}
@@ -1,158 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.ui.JBListWithHintProvider;
import com.intellij.ui.popup.PopupFactoryImpl;
import com.intellij.ui.popup.list.ListPopupModel;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.fixture.JButtonFixture;
import org.fest.swing.timing.Condition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.timing.Pause.pause;
import static org.junit.Assert.*;
public class ComboBoxActionFixture {
@NotNull private Robot myRobot;
@NotNull private JButton myTarget;
private static final Class<?> ourComboBoxButtonClass;
static {
Class<?> temp = null;
try {
temp = ComboBoxActionFixture.class.getClassLoader().loadClass(ComboBoxAction.class.getCanonicalName() + "$ComboBoxButton");
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
ourComboBoxButtonClass = temp;
}
public static ComboBoxActionFixture findComboBox(@NotNull Robot robot, @NotNull Container root) {
JButton comboBoxButton = robot.finder().find(root, new GenericTypeMatcher<JButton>(JButton.class) {
@Override
protected boolean isMatching(@NotNull JButton component) {
return ourComboBoxButtonClass.isInstance(component);
}
});
return new ComboBoxActionFixture(robot, comboBoxButton);
}
public static ComboBoxActionFixture findComboBoxByText(@NotNull Robot robot, @NotNull Container root, @NotNull final String text) {
JButton comboBoxButton = robot.finder().find(root, new GenericTypeMatcher<JButton>(JButton.class) {
@Override
protected boolean isMatching(@NotNull JButton component) {
return ourComboBoxButtonClass.isInstance(component) && component.getText().equals(text);
}
});
return new ComboBoxActionFixture(robot, comboBoxButton);
}
public ComboBoxActionFixture(@NotNull Robot robot, @NotNull JButton target) {
myRobot = robot;
myTarget = target;
}
public void selectItem(@NotNull String itemName) {
click();
selectItemByText(getPopupList(), itemName);
}
public String getSelectedItemText() {
return execute(new GuiQuery<String>() {
@Nullable
@Override
protected String executeInEDT() throws Throwable {
return myTarget.getText();
}
});
}
private void click() {
final JButtonFixture comboBoxButtonFixture = new JButtonFixture(myRobot, myTarget);
pause(new Condition("Wait until comboBoxButton is enabled") {
@Override
public boolean test() {
//noinspection ConstantConditions
return execute(new GuiQuery<Boolean>() {
@Override
protected Boolean executeInEDT() throws Throwable {
return comboBoxButtonFixture.target().isEnabled();
}
});
}
}, SHORT_TIMEOUT);
comboBoxButtonFixture.click();
}
@NotNull
private JList getPopupList() {
return myRobot.finder().findByType(JBListWithHintProvider.class);
}
private static void selectItemByText(@NotNull final JList list, @NotNull final String text) {
pause(new Condition("Wait until the list is populated.") {
@Override
public boolean test() {
ListPopupModel popupModel = (ListPopupModel)list.getModel();
for (int i = 0; i < popupModel.getSize(); ++i) {
PopupFactoryImpl.ActionItem actionItem = (PopupFactoryImpl.ActionItem)popupModel.get(i);
assertNotNull(actionItem);
if (text.equals(actionItem.getText())) {
return true;
}
}
return false;
}
}, SHORT_TIMEOUT);
final Integer appIndex = execute(new GuiQuery<Integer>() {
@Override
protected Integer executeInEDT() throws Throwable {
ListPopupModel popupModel = (ListPopupModel)list.getModel();
for (int i = 0; i < popupModel.getSize(); ++i) {
PopupFactoryImpl.ActionItem actionItem = (PopupFactoryImpl.ActionItem)popupModel.get(i);
assertNotNull(actionItem);
if (text.equals(actionItem.getText())) {
return i;
}
}
return -1;
}
});
//noinspection ConstantConditions
assertTrue(appIndex >= 0);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
list.setSelectedIndex(appIndex);
}
});
assertEquals(text, ((PopupFactoryImpl.ActionItem)list.getSelectedValue()).getText());
}
}
@@ -1,60 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import org.fest.swing.core.Robot;
import org.fest.swing.core.matcher.DialogMatcher;
import org.fest.swing.fixture.DialogFixture;
import org.fest.swing.fixture.JTableCellFixture;
import org.fest.swing.fixture.JTableFixture;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickOkButton;
import static org.fest.swing.core.matcher.DialogMatcher.withTitle;
import static org.fest.swing.data.TableCell.row;
import static org.fest.swing.finder.WindowFinder.findDialog;
public class ConfigureProjectSubsetDialogFixture {
@NotNull private DialogFixture myDialog;
@NotNull private final JTableFixture myModulesTable;
@NotNull
public static ConfigureProjectSubsetDialogFixture find(@NotNull Robot robot) {
DialogMatcher matcher = withTitle("Select Modules to Include in Project Subset").andShowing();
DialogFixture dialog = findDialog(matcher).withTimeout(SHORT_TIMEOUT.duration()).using(robot);
return new ConfigureProjectSubsetDialogFixture(dialog);
}
private ConfigureProjectSubsetDialogFixture(@NotNull DialogFixture dialog) {
myDialog = dialog;
Robot robot = dialog.robot();
myModulesTable = new JTableFixture(robot, robot.finder().findByType(dialog.target(), JTable.class, true));
}
@NotNull
public ConfigureProjectSubsetDialogFixture selectModule(@NotNull String moduleName, boolean selected) {
JTableCellFixture cell = myModulesTable.cell(moduleName);
myModulesTable.enterValue(row(cell.row()).column(0), String.valueOf(selected));
return this;
}
public void clickOk() {
findAndClickOkButton(myDialog);
}
}
@@ -1,72 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.tests.gui.framework.GuiTests;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.fixture.ContainerFixture;
import org.fest.swing.timing.Condition;
import org.fest.swing.timing.Pause;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Collection;
/**
* Created by jetbrains on 22/08/16.
*/
public class DialogFixture implements ContainerFixture<JDialog> {
private JDialog myDialog;
private Robot myRobot;
public DialogFixture(@NotNull Robot robot, JDialog selectSdkDialog) {
myRobot = robot;
myDialog = selectSdkDialog;
}
@NotNull
public static DialogFixture find(@NotNull Robot robot, String title) {
GenericTypeMatcher<JDialog> matcher = new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
return title.equals(dialog.getTitle()) && dialog.isShowing();
}
};
Pause.pause(new Condition("Finding for DialogFixture with title \"" + title + "\"") {
@Override
public boolean test() {
Collection<JDialog> dialogs = robot.finder().findAll(matcher);
return !dialogs.isEmpty();
}
}, GuiTests.SHORT_TIMEOUT);
JDialog dialog = robot.finder().find(matcher);
return new DialogFixture(robot, dialog);
}
@Override
public JDialog target() {
return myDialog;
}
@Override
public Robot robot() {
return myRobot;
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures.DialogFixtures;
import com.intellij.ide.actions.CreateFileFromTemplateDialog;
import com.intellij.tests.gui.fixtures.IdeaDialogFixture;
import com.intellij.tests.gui.framework.GuiTests;
import org.fest.swing.core.Robot;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* Created by karashevich on 20/06/16.
*/
public class CreateDialogFixture extends IdeaDialogFixture<CreateFileFromTemplateDialog> {
@NotNull
public static CreateDialogFixture find(@NotNull Robot robot) {
return new CreateDialogFixture(robot, find(robot, CreateFileFromTemplateDialog.class));
}
protected CreateDialogFixture(@NotNull Robot robot,
@NotNull JDialog target,
@NotNull CreateFileFromTemplateDialog dialogWrapper) {
super(robot, target, dialogWrapper);
}
protected CreateDialogFixture(@NotNull Robot robot,
@NotNull DialogAndWrapper<CreateFileFromTemplateDialog> dialogAndWrapper) {
super(robot, dialogAndWrapper);
}
public void clickOK(){
GuiTests.findAndClickOkButton(this);
}
}
File diff suppressed because it is too large Load Diff
@@ -1,254 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.execution.impl.ConsoleViewImpl;
import com.intellij.execution.testframework.TestTreeView;
import com.intellij.execution.ui.layout.impl.GridImpl;
import com.intellij.execution.ui.layout.impl.JBRunnerTabs;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.ui.ThreeComponentsSplitter;
import com.intellij.ui.content.Content;
import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.ui.tabs.impl.TabLabel;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.exception.ComponentLookupException;
import org.fest.swing.timing.Condition;
import org.fest.swing.timing.Pause;
import org.fest.swing.timing.Timeout;
import org.fest.swing.util.TextMatcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.List;
import static com.intellij.tests.gui.framework.GuiTests.waitUntilFound;
import static com.intellij.util.ui.UIUtil.findComponentOfType;
import static com.intellij.util.ui.UIUtil.findComponentsOfType;
import static junit.framework.Assert.assertNotNull;
import static org.fest.reflect.core.Reflection.method;
import static org.fest.swing.timing.Pause.pause;
public class ExecutionToolWindowFixture extends ToolWindowFixture {
public static class ContentFixture {
@NotNull private final ExecutionToolWindowFixture myParentToolWindow;
@NotNull private final Robot myRobot;
@NotNull private final Content myContent;
private ContentFixture(@NotNull ExecutionToolWindowFixture parentToolWindow, @NotNull Robot robot, @NotNull Content content) {
myParentToolWindow = parentToolWindow;
myRobot = robot;
myContent = content;
}
public void waitForOutput(@NotNull final TextMatcher matcher, @NotNull Timeout timeout) {
pause(new Condition("LogCat tool window output check for package name.") {
@Override
public boolean test() {
return outputMatches(matcher);
}
}, timeout);
}
/**
* Waits until it grabs the console window and then returns true if its text matches that of {@code matcher}.
* Note: The caller should wrap it in something like a org.fest.swing.timing.Pause.pause to make sure they don't hang forever if the
* console view cannot be found for some reason.
*/
public boolean outputMatches(@NotNull TextMatcher matcher) {
ConsoleViewImpl consoleView;
while ((consoleView = findConsoleView()) == null || consoleView.getEditor() == null) {
// If our handle has been replaced, find it again.
JComponent consoleComponent = getTabComponent("Console");
myRobot.click(consoleComponent);
}
return matcher.isMatching(consoleView.getEditor().getDocument().getText());
}
// Returns the console or null if it is not found.
@Nullable
private ConsoleViewImpl findConsoleView() {
try {
return myRobot.finder().findByType(myParentToolWindow.myToolWindow.getComponent(), ConsoleViewImpl.class, false);
} catch (ComponentLookupException e) {
return null;
}
}
@NotNull
public JComponent getTabComponent(@NotNull final String tabName) {
return getTabContent(myParentToolWindow.myToolWindow.getComponent(), JBRunnerTabs.class, GridImpl.class, tabName);
}
@NotNull
public UnitTestTreeFixture getUnitTestTree() {
return new UnitTestTreeFixture(this, myRobot.finder().findByType(myContent.getComponent(), TestTreeView.class));
}
// Returns the root of the debugger tree or null.
@Nullable
public XDebuggerTreeNode getDebuggerTreeRoot() {
try {
JComponent debuggerComponent = getTabComponent("Debugger");
if (debuggerComponent != null) {
myRobot.click(debuggerComponent);
}
ThreeComponentsSplitter threeComponentsSplitter =
myRobot.finder().findByType(debuggerComponent, ThreeComponentsSplitter.class, false);
JComponent innerComponent = threeComponentsSplitter.getInnerComponent();
assertNotNull(innerComponent);
return myRobot.finder().findByType(innerComponent, XDebuggerTree.class, false).getRoot();
} catch (ComponentLookupException e) {
return null;
}
}
public void clickDebuggerTreeRoot() {
try {
JComponent debuggerComponent = getTabComponent("Debugger");
myRobot.click(debuggerComponent);
} catch (ComponentLookupException e) { }
}
@NotNull
private JComponent getTabContent(@NotNull final JComponent root,
final Class<? extends JBTabsImpl> parentComponentType,
@NotNull final Class<? extends JComponent> tabContentType,
@NotNull final String tabName) {
myParentToolWindow.activate();
myParentToolWindow.waitUntilIsVisible();
TabLabel tabLabel;
if (parentComponentType == null) {
tabLabel = waitUntilFound(myRobot, new GenericTypeMatcher<TabLabel>(TabLabel.class) {
@Override
protected boolean isMatching(@NotNull TabLabel component) {
return component.toString().equals(tabName);
}
});
}
else {
final JComponent parent = myRobot.finder().findByType(root, parentComponentType, false);
tabLabel = waitUntilFound(myRobot, parent, new GenericTypeMatcher<TabLabel>(TabLabel.class) {
@Override
protected boolean isMatching(@NotNull TabLabel component) {
return component.getParent() == parent && component.toString().equals(tabName);
}
});
}
myRobot.click(tabLabel);
return myRobot.finder().findByType(tabContentType);
}
public boolean isExecutionInProgress() {
// Consider that execution is in progress if 'stop' toolbar button is enabled.
for (ActionButton button : getToolbarButtons()) {
if ("com.intellij.execution.actions.StopAction".equals(button.getAction().getClass().getCanonicalName())) {
//noinspection ConstantConditions
return method("isButtonEnabled").withReturnType(boolean.class).in(button).invoke();
}
}
return true;
}
public void rerun() {
for (ActionButton button : getToolbarButtons()) {
if ("com.intellij.execution.runners.FakeRerunAction".equals(button.getAction().getClass().getCanonicalName())) {
myRobot.click(button);
return;
}
}
throw new IllegalStateException("Could not find the Re-run button.");
}
public void rerunFailed() {
for (ActionButton button : getToolbarButtons()) {
if ("com.intellij.execution.junit2.ui.actions.RerunFailedTestsAction".equals(button.getAction().getClass().getCanonicalName())) {
myRobot.click(button);
return;
}
}
throw new IllegalStateException("Could not find the Re-run failed tests button.");
}
public void waitForExecutionToFinish(@NotNull Timeout timeout) {
Pause.pause(new Condition("Wait for execution to finish") {
@Override
public boolean test() {
return !isExecutionInProgress();
}
}, timeout);
}
@TestOnly
public boolean stop() {
for (final ActionButton button : getToolbarButtons()) {
final AnAction action = button.getAction();
if (action != null && action.getClass().getName().equals("com.intellij.execution.actions.StopAction")) {
//noinspection ConstantConditions
boolean enabled = method("isButtonEnabled").withReturnType(boolean.class).in(button).invoke();
if (enabled) {
GuiActionRunner.execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
button.click();
}
});
return true;
}
return false;
}
}
return false;
}
@NotNull
private List<ActionButton> getToolbarButtons() {
ActionToolbarImpl toolbar = findComponentOfType(myContent.getComponent(), ActionToolbarImpl.class);
assert toolbar != null;
return findComponentsOfType(toolbar, ActionButton.class);
}
} // End class ContentFixture
protected ExecutionToolWindowFixture(@NotNull String toolWindowId, @NotNull IdeFrameFixture ideFrame) {
super(toolWindowId, ideFrame.getProject(), ideFrame.robot());
}
@NotNull
public ContentFixture findContent(@NotNull String tabName) {
Content content = getContent(tabName);
assertNotNull(content);
return new ContentFixture(this, myRobot, content);
}
@NotNull
public ContentFixture findContent(@NotNull TextMatcher tabNameMatcher) {
Content content = getContent(tabNameMatcher);
assertNotNull(content);
return new ContentFixture(this, myRobot, content);
}
}
@@ -1,113 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.fileChooser.ex.FileChooserDialogImpl;
import com.intellij.openapi.fileChooser.ex.FileSystemTreeImpl;
import com.intellij.openapi.vfs.VirtualFile;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.timing.Condition;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickOkButton;
import static org.fest.reflect.core.Reflection.field;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.timing.Pause.pause;
import static org.fest.util.Strings.quote;
import static org.junit.Assert.assertNotNull;
public class FileChooserDialogFixture extends IdeaDialogFixture<FileChooserDialogImpl> {
@NotNull
public static FileChooserDialogFixture findOpenProjectDialog(@NotNull Robot robot) {
return findDialog(robot, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
return dialog.isShowing() && "Open File or Project".equals(dialog.getTitle());
}
});
}
@NotNull
public static FileChooserDialogFixture findImportProjectDialog(@NotNull Robot robot) {
return findDialog(robot, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
String title = dialog.getTitle();
return dialog.isShowing() && title != null && title.startsWith("Select") && title.endsWith("Project to Import");
}
});
}
@NotNull
public static FileChooserDialogFixture findDialog(@NotNull Robot robot, @NotNull final GenericTypeMatcher<JDialog> matcher) {
return new FileChooserDialogFixture(robot, find(robot, FileChooserDialogImpl.class, matcher));
}
private FileChooserDialogFixture(@NotNull Robot robot, @NotNull DialogAndWrapper<FileChooserDialogImpl> dialogAndWrapper) {
super(robot, dialogAndWrapper);
}
@NotNull
public FileChooserDialogFixture select(@NotNull final VirtualFile file) {
sleepWithTimeBomb();
final FileSystemTreeImpl fileSystemTree = field("myFileSystemTree").ofType(FileSystemTreeImpl.class)
.in(getDialogWrapper())
.get();
assertNotNull(fileSystemTree);
final AtomicBoolean fileSelected = new AtomicBoolean();
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
fileSystemTree.select(file, new Runnable() {
@Override
public void run() {
fileSelected.set(true);
}
});
}
});
pause(new Condition("File " + quote(file.getPath()) + " is selected") {
@Override
public boolean test() {
return fileSelected.get();
}
}, SHORT_TIMEOUT);
return this;
}
private void sleepWithTimeBomb() {
//TODO: why this bombed?
assert System.currentTimeMillis() < 1452600000000L; // 2016-01-12 12:00
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {}
}
@NotNull
public FileChooserDialogFixture clickOk() {
findAndClickOkButton(this);
return this;
}
}
@@ -1,196 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.CommonProcessors;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.timing.Condition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.util.Collection;
import static com.intellij.openapi.vfs.VfsUtilCore.virtualToIoFile;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static junit.framework.Assert.assertNotNull;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.reflect.core.Reflection.method;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.timing.Pause.pause;
import static org.fest.util.Strings.quote;
public class FileFixture {
@NotNull private final Project myProject;
@NotNull private final File myPath;
@NotNull private final VirtualFile myVirtualFile;
public FileFixture(@NotNull Project project, @NotNull VirtualFile file) {
myProject = project;
myPath = virtualToIoFile(file);
myVirtualFile = file;
}
@NotNull
public FileFixture requireOpenAndSelected() {
requireVirtualFile();
pause(new Condition("File " + quote(myPath.getPath()) + " to be opened") {
@Override
public boolean test() {
//noinspection ConstantConditions
return execute(new GuiQuery<Boolean>() {
@Override
protected Boolean executeInEDT() throws Throwable {
return isOpenAndSelected();
}
});
}
}, SHORT_TIMEOUT);
return this;
}
private boolean isOpenAndSelected() {
FileEditorManager editorManager = FileEditorManager.getInstance(myProject);
FileEditor selectedEditor = editorManager.getSelectedEditor(myVirtualFile);
if (selectedEditor != null) {
JComponent component = selectedEditor.getComponent();
if (component.isVisible() && component.isShowing()) {
Document document = FileDocumentManager.getInstance().getDocument(myVirtualFile);
if (document != null) {
PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
if (psiFile != null) {
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
//noinspection ConstantConditions
boolean isRunning = method("isRunning").withReturnType(boolean.class).in(codeAnalyzer).invoke();
return !isRunning;
}
}
}
}
return false;
}
@NotNull
public FileFixture waitUntilErrorAnalysisFinishes() {
pause(new Condition("error analysis finishes") {
@Override
public boolean test() {
//noinspection ConstantConditions
return execute(new GuiQuery<Boolean>() {
@Override
protected Boolean executeInEDT() throws Throwable {
return DaemonCodeAnalyzerEx.getInstanceEx(myProject).isErrorAnalyzingFinished(getPsiFile());
}
});
}
}, SHORT_TIMEOUT);
return this;
}
@NotNull
public FileFixture requireCodeAnalysisHighlightCount(@NotNull HighlightSeverity severity, int expected) {
Collection<HighlightInfo> highlightInfos = getHighlightInfos(severity);
assertThat(highlightInfos).hasSize(expected);
return this;
}
@NotNull
public Collection<HighlightInfo> getHighlightInfos(@NotNull final HighlightSeverity severity) {
waitUntilErrorAnalysisFinishes();
final Document document = getNotNullDocument();
Collection<HighlightInfo> highlightInfos = execute(new GuiQuery<Collection<HighlightInfo>>() {
@Override
protected Collection<HighlightInfo> executeInEDT() throws Throwable {
CommonProcessors.CollectProcessor<HighlightInfo> processor = new CommonProcessors.CollectProcessor<HighlightInfo>();
DaemonCodeAnalyzerEx.processHighlights(document, myProject, severity, 0, document.getTextLength(), processor);
return processor.getResults();
}
});
assert highlightInfos != null;
return highlightInfos;
}
@NotNull
private PsiFile getPsiFile() {
final PsiFile psiFile = execute(new GuiQuery<PsiFile>() {
@Override
protected PsiFile executeInEDT() throws Throwable {
return PsiManager.getInstance(myProject).findFile(myVirtualFile);
}
});
assertNotNull("No Psi file found for path " + quote(myVirtualFile.getPath()), psiFile);
return psiFile;
}
@NotNull
public FileFixture waitForCodeAnalysisHighlightCount(@NotNull final HighlightSeverity severity, final int expected) {
final Document document = getNotNullDocument();
pause(new Condition("Waiting for code analysis " + severity + " count to reach " + expected) {
@Override
public boolean test() {
Collection<HighlightInfo> highlightInfos = execute(new GuiQuery<Collection<HighlightInfo>>() {
@Override
protected Collection<HighlightInfo> executeInEDT() throws Throwable {
CommonProcessors.CollectProcessor<HighlightInfo> processor = new CommonProcessors.CollectProcessor<HighlightInfo>();
DaemonCodeAnalyzerEx.processHighlights(document, myProject, severity, 0, document.getTextLength(), processor);
return processor.getResults();
}
});
assertNotNull(highlightInfos);
return highlightInfos.size() == expected;
}
}, SHORT_TIMEOUT);
return this;
}
@NotNull
private Document getNotNullDocument() {
Document document = getDocument(myVirtualFile);
assertNotNull("No Document found for path " + quote(myPath.getPath()), document);
return document;
}
@NotNull
public FileFixture requireVirtualFile() {
assertNotNull("No VirtualFile found for path " + quote(myPath.getPath()), myVirtualFile);
return this;
}
@Nullable
public static Document getDocument(@NotNull final VirtualFile file) {
return execute(new GuiQuery<Document>() {
@Override
protected Document executeInEDT() throws Throwable {
return FileDocumentManager.getInstance().getDocument(file);
}
});
}
}
@@ -1,61 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.find.impl.FindDialog;
import com.intellij.openapi.ui.ComboBox;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiTask;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickButton;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.junit.Assert.assertNotNull;
public class FindDialogFixture extends IdeaDialogFixture<FindDialog> {
@NotNull
public static FindDialogFixture find(@NotNull Robot robot) {
return new FindDialogFixture(robot, find(robot, FindDialog.class));
}
private FindDialogFixture(@NotNull Robot robot, @NotNull DialogAndWrapper<FindDialog> dialogAndWrapper) {
super(robot, dialogAndWrapper);
}
@NotNull
public FindDialogFixture setTextToFind(@NotNull final String text) {
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
JComponent c = getDialogWrapper().getPreferredFocusedComponent();
assertThat(c).isInstanceOf(ComboBox.class);
ComboBox input = (ComboBox)c;
assertNotNull(input);
input.setSelectedItem(text);
}
});
return this;
}
@NotNull
public FindDialogFixture clickFind() {
findAndClickButton(this, "Find");
return this;
}
}
@@ -1,872 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.codeInspection.ui.InspectionTree;
import com.intellij.ide.RecentProjectsManager;
import com.intellij.ide.actions.ShowSettingsUtilImpl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.core.matcher.JButtonMatcher;
import org.fest.swing.core.matcher.JLabelMatcher;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.timing.Condition;
import org.fest.swing.timing.Timeout;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import javax.swing.*;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import static com.intellij.ide.impl.ProjectUtil.closeAndDispose;
import static com.intellij.openapi.util.io.FileUtil.getRelativePath;
import static com.intellij.openapi.util.io.FileUtil.toSystemDependentName;
import static com.intellij.openapi.util.text.StringUtil.isNotEmpty;
import static com.intellij.openapi.vfs.VfsUtilCore.urlToPath;
import static com.intellij.tests.gui.framework.GuiTests.*;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.fail;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.timing.Pause.pause;
import static org.fest.util.Strings.quote;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
/**
* Created by karashevich on 30/05/16.
*/
public class IdeFrameFixture extends ComponentFixture<IdeFrameFixture, IdeFrameImpl> {
@NotNull private final File myProjectPath;
private EditorFixture myEditor;
@NotNull
public static IdeFrameFixture find(@NotNull final Robot robot, @Nullable final File projectPath, @Nullable final String projectName) {
final GenericTypeMatcher<IdeFrameImpl> matcher = new GenericTypeMatcher<IdeFrameImpl>(IdeFrameImpl.class) {
@Override
protected boolean isMatching(@NotNull IdeFrameImpl frame) {
Project project = frame.getProject();
if (projectPath == null && project != null) return true;
if (project != null && PathManager.getAbsolutePath(projectPath.getPath()).equals(PathManager.getAbsolutePath(project.getBasePath()))) {
return projectName == null || projectName.equals(project.getName());
}
return false;
}
};
pause(new Condition("IdeFrame " + (projectPath != null ? quote(projectPath.getPath()) : "") + " to show up") {
@Override
public boolean test() {
Collection<IdeFrameImpl> frames = robot.finder().findAll(matcher);
return !frames.isEmpty();
}
}, LONG_TIMEOUT);
IdeFrameImpl ideFrame = robot.finder().find(matcher);
return new IdeFrameFixture(robot, ideFrame, new File(ideFrame.getProject().getBasePath()));
}
public IdeFrameFixture(@NotNull Robot robot, @NotNull IdeFrameImpl target, @NotNull File projectPath) {
super(IdeFrameFixture.class, robot, target);
myProjectPath = projectPath;
final Project project = getProject();
Disposable disposable = new NoOpDisposable();
Disposer.register(project, disposable);
//myGradleProjectEventListener = new GradleProjectEventListener();
//GradleSyncState.subscribe(project, myGradleProjectEventListener);
//PostProjectBuildTasksExecutor.subscribe(project, myGradleProjectEventListener);
}
@NotNull
public File getProjectPath() {
return myProjectPath;
}
@NotNull
public List<String> getModuleNames() {
List<String> names = Lists.newArrayList();
for (Module module : getModuleManager().getModules()) {
names.add(module.getName());
}
return names;
}
@NotNull
public IdeFrameFixture requireModuleCount(int expected) {
Module[] modules = getModuleManager().getModules();
assertThat(modules).as("Module count in project " + quote(getProject().getName())).hasSize(expected);
return this;
}
@NotNull
public Collection<String> getSourceFolderRelativePaths(@NotNull String moduleName, @NotNull final JpsModuleSourceRootType<?> sourceType) {
final Set<String> paths = Sets.newHashSet();
Module module = getModule(moduleName);
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
ModifiableRootModel rootModel = moduleRootManager.getModifiableModel();
try {
for (ContentEntry contentEntry : rootModel.getContentEntries()) {
for (SourceFolder folder : contentEntry.getSourceFolders()) {
JpsModuleSourceRootType<?> rootType = folder.getRootType();
if (rootType.equals(sourceType)) {
String path = urlToPath(folder.getUrl());
String relativePath = getRelativePath(myProjectPath, new File(toSystemDependentName(path)));
paths.add(relativePath);
}
}
}
}
finally {
rootModel.dispose();
}
}
});
return paths;
}
@NotNull
public Module getModule(@NotNull String name) {
Module module = findModule(name);
assertNotNull("Unable to find module with name " + quote(name), module);
return module;
}
@Nullable
public Module findModule(@NotNull String name) {
for (Module module : getModuleManager().getModules()) {
if (name.equals(module.getName())) {
return module;
}
}
return null;
}
@NotNull
private ModuleManager getModuleManager() {
return ModuleManager.getInstance(getProject());
}
@NotNull
public EditorFixture getEditor() {
if (myEditor == null) {
myEditor = new EditorFixture(robot(), this);
}
return myEditor;
}
//@NotNull
//public GradleInvocationResult invokeProjectMake() {
// return invokeProjectMake(null);
//}
//@NotNull
//public GradleInvocationResult invokeProjectMake(@Nullable Runnable executeAfterInvokingMake) {
// myGradleProjectEventListener.reset();
//
// final AtomicReference<GradleInvocationResult> resultRef = new AtomicReference<GradleInvocationResult>();
// AndroidProjectBuildNotifications.subscribe(getProject(), new AndroidProjectBuildNotifications.AndroidProjectBuildListener() {
// @Override
// public void buildComplete(@NotNull AndroidProjectBuildNotifications.BuildContext context) {
// if (context instanceof GradleBuildContext) {
// resultRef.set(((GradleBuildContext)context).getBuildResult());
// }
// }
// });
// selectProjectMakeAction();
//
// if (executeAfterInvokingMake != null) {
// executeAfterInvokingMake.run();
// }
//
// waitForBuildToFinish(COMPILE_JAVA);
//
// GradleInvocationResult result = resultRef.get();
// assertNotNull(result);
//
// return result;
//}
@NotNull
public IdeFrameFixture invokeProjectMakeAndSimulateFailure(@NotNull final String failure) {
Runnable failTask = new Runnable() {
@Override
public void run() {
throw new ExternalSystemException(failure);
}
};
//ApplicationManager.getApplication().putUserData(EXECUTE_BEFORE_PROJECT_BUILD_IN_GUI_TEST_KEY, failTask);
selectProjectMakeAction();
return this;
}
/**
* Finds the Run button in the IDE interface.
*
* @return ActionButtonFixture for the run button.
*/
@NotNull
public ActionButtonFixture findRunApplicationButton() {
return findActionButtonByActionId("Run");
}
public void debugApp(@NotNull String appName) throws ClassNotFoundException {
selectApp(appName);
findActionButtonByActionId("Debug").click();
}
public void runApp(@NotNull String appName) throws ClassNotFoundException {
selectApp(appName);
findActionButtonByActionId("Run").click();
}
@NotNull
public RunToolWindowFixture getRunToolWindow() {
return new RunToolWindowFixture(this);
}
@NotNull
public DebugToolWindowFixture getDebugToolWindow() {
return new DebugToolWindowFixture(this);
}
protected void selectProjectMakeAction() {
invokeMenuPath("Build", "Make Project");
}
/**
* Invokes an action by menu path
*
* @param path the series of menu names, e.g. {@link invokeActionByMenuPath("Build", "Make Project")}
*/
public void invokeMenuPath(@NotNull String... path) {
getMenuFixture().invokeMenuPath(path);
}
/**
* Invokes an action by menu path (where each segment is a regular expression). This is particularly
* useful when the menu items can change dynamically, such as the labels of Undo actions, Run actions,
* etc.
*
* @param path the series of menu name regular expressions, e.g. {@link invokeActionByMenuPath("Build", "Make( Project)?")}
*/
public void invokeMenuPathRegex(@NotNull String... path) {
getMenuFixture().invokeMenuPathRegex(path);
}
@NotNull
private MenuFixture getMenuFixture() {
return new MenuFixture(robot(), target());
}
//@NotNull
//public IdeFrameFixture waitForBuildToFinish(@NotNull final BuildMode buildMode) {
// final Project project = getProject();
// if (buildMode == SOURCE_GEN && !GradleProjectBuilder.getInstance(project).isSourceGenerationEnabled()) {
// return this;
// }
//
// pause(new Condition("Build (" + buildMode + ") for project " + quote(project.getName()) + " to finish'") {
// @Override
// public boolean test() {
// if (buildMode == SOURCE_GEN) {
// PostProjectBuildTasksExecutor tasksExecutor = PostProjectBuildTasksExecutor.getInstance(project);
// if (tasksExecutor.getLastBuildTimestamp() > -1) {
// // This will happen when creating a new project. Source generation happens before the IDE frame is found and build listeners
// // are created. It is fairly safe to assume that source generation happened if we have a timestamp for a "last performed build".
// return true;
// }
// }
// return myGradleProjectEventListener.isBuildFinished(buildMode);
// }
// }, LONG_TIMEOUT);
//
// waitForBackgroundTasksToFinish();
// robot().waitForIdle();
//
// return this;
//}
@NotNull
public FileFixture findExistingFileByRelativePath(@NotNull String relativePath) {
VirtualFile file = findFileByRelativePath(relativePath, true);
return new FileFixture(getProject(), file);
}
@Nullable
@Contract("_, true -> !null")
public VirtualFile findFileByRelativePath(@NotNull String relativePath, boolean requireExists) {
//noinspection Contract
assertFalse("Should use '/' in test relative paths, not File.separator", relativePath.contains("\\"));
Project project = getProject();
VirtualFile file = project.getBaseDir().findFileByRelativePath(relativePath);
if (requireExists) {
//noinspection Contract
assertNotNull("Unable to find file with relative path " + quote(relativePath), file);
}
return file;
}
//@NotNull
//public IdeFrameFixture requestProjectSyncAndExpectFailure() {
// requestProjectSync();
// return waitForGradleProjectSyncToFail();
//}
@NotNull
public IdeFrameFixture requestProjectSyncAndSimulateFailure(@NotNull final String failure) {
Runnable failTask = new Runnable() {
@Override
public void run() {
throw new ExternalSystemException(failure);
}
};
//ApplicationManager.getApplication().putUserData(EXECUTE_BEFORE_PROJECT_SYNC_TASK_IN_GUI_TEST_KEY, failTask);
// When simulating the error, we don't have to wait for sync to happen. Sync never happens because the error is thrown before it (sync)
// is started.
return requestProjectSync();
}
@NotNull
public IdeFrameFixture requestProjectSync() {
//myGradleProjectEventListener.reset();
// We wait until all "Run Configurations" are populated in the toolbar combo-box. Until then the "Project Sync" button is not in its
// final position, and FEST will click the wrong button.
pause(new Condition("Waiting for 'Run Configurations' to be populated") {
@Override
public boolean test() {
RunConfigurationComboBoxFixture runConfigurationComboBox = RunConfigurationComboBoxFixture.find(IdeFrameFixture.this);
return isNotEmpty(runConfigurationComboBox.getText());
}
}, SHORT_TIMEOUT);
waitForBackgroundTasksToFinish();
findGradleSyncAction().waitUntilEnabledAndShowing();
// TODO figure out why in IDEA 15 even though an action is enabled, visible and showing, clicking it (via UI testing infrastructure)
// does not work consistently
return this;
}
@NotNull
private ActionButtonFixture findGradleSyncAction() {
return findActionButtonByActionId("Android.SyncProject");
}
//@NotNull
//public IdeFrameFixture waitForGradleProjectSyncToFail() {
// try {
// waitForGradleProjectSyncToFinish(true);
// fail("Expecting project sync to fail");
// }
// catch (RuntimeException expected) {
// // expected failure.
// }
// return waitForBackgroundTasksToFinish();
//}
//@NotNull
//public IdeFrameFixture waitForGradleProjectSyncToStart() {
// Project project = getProject();
// final GradleSyncState syncState = GradleSyncState.getInstance(project);
// if (!syncState.isSyncInProgress()) {
// pause(new Condition("Syncing project " + quote(project.getName()) + " to finish") {
// @Override
// public boolean test() {
// return myGradleProjectEventListener.isSyncStarted();
// }
// }, SHORT_TIMEOUT);
// }
// return this;
//}
//@NotNull
//public IdeFrameFixture waitForGradleProjectSyncToFinish() {
// waitForGradleProjectSyncToFinish(false);
// return this;
//}
//private void waitForGradleProjectSyncToFinish(final boolean expectSyncFailure) {
// final Project project = getProject();
//
// // ensure GradleInvoker (in-process build) is always enabled.
// AndroidGradleBuildConfiguration buildConfiguration = AndroidGradleBuildConfiguration.getInstance(project);
// buildConfiguration.USE_EXPERIMENTAL_FASTER_BUILD = true;
//
// pause(new Condition("Syncing project " + quote(project.getName()) + " to finish") {
// @Override
// public boolean test() {
// GradleSyncState syncState = GradleSyncState.getInstance(project);
// boolean syncFinished =
// (myGradleProjectEventListener.isSyncFinished() || syncState.isSyncNeeded() != ThreeState.YES) && !syncState.isSyncInProgress();
// if (expectSyncFailure) {
// syncFinished = syncFinished && myGradleProjectEventListener.hasSyncError();
// }
// return syncFinished;
// }
// }, LONG_TIMEOUT);
//
// findGradleSyncAction().waitUntilEnabledAndShowing();
//
// if (myGradleProjectEventListener.hasSyncError()) {
// RuntimeException syncError = myGradleProjectEventListener.getSyncError();
// myGradleProjectEventListener.reset();
// throw syncError;
// }
//
// if (!myGradleProjectEventListener.isSyncSkipped()) {
// waitForBuildToFinish(SOURCE_GEN);
// }
//
// waitForBackgroundTasksToFinish();
//}
@NotNull
public IdeFrameFixture waitForBackgroundTasksToFinish() {
pause(new Condition("Background tasks to finish") {
@Override
public boolean test() {
ProgressManager progressManager = ProgressManager.getInstance();
return !progressManager.hasModalProgressIndicator() &&
!progressManager.hasProgressIndicator() &&
!progressManager.hasUnsafeProgressIndicator();
}
}
, LONG_TIMEOUT);
robot().waitForIdle();
return this;
}
@NotNull
private ActionButtonFixture findActionButtonByActionId(String actionId) {
return ActionButtonFixture.findByActionId(actionId, robot(), target());
}
@NotNull
public MessagesToolWindowFixture getMessagesToolWindow() {
return new MessagesToolWindowFixture(getProject(), robot());
}
@NotNull
public EditorNotificationPanelFixture requireEditorNotification(@NotNull final String message) {
final Ref<EditorNotificationPanel> notificationPanelRef = new Ref<EditorNotificationPanel>();
pause(new Condition("Notification with message '" + message + "' shows up") {
@Override
public boolean test() {
EditorNotificationPanel notificationPanel = findNotificationPanel(message);
notificationPanelRef.set(notificationPanel);
return notificationPanel != null;
}
});
EditorNotificationPanel notificationPanel = notificationPanelRef.get();
assertNotNull(notificationPanel);
return new EditorNotificationPanelFixture(robot(), notificationPanel);
}
public void requireNoEditorNotification() {
assertNull(findNotificationPanel(null));
}
/**
* Locates an editor notification with the given main message (unless the message is {@code null}, in which case we assert that there are
* no visible editor notifications. Will fail if the given notification is not found.
*/
@Nullable
private EditorNotificationPanel findNotificationPanel(@Nullable String message) {
Collection<EditorNotificationPanel> panels = robot().finder().findAll(target(), new GenericTypeMatcher<EditorNotificationPanel>(
EditorNotificationPanel.class, true) {
@Override
protected boolean isMatching(@NotNull EditorNotificationPanel panel) {
return panel.isShowing();
}
});
if (message == null) {
if (!panels.isEmpty()) {
List<String> labels = Lists.newArrayList();
for (EditorNotificationPanel panel : panels) {
labels.addAll(getEditorNotificationLabels(panel));
}
fail("Found editor notifications when none were expected" + labels);
}
return null;
}
List<String> labels = Lists.newArrayList();
for (EditorNotificationPanel panel : panels) {
List<String> found = getEditorNotificationLabels(panel);
labels.addAll(found);
for (String label : found) {
if (label.contains(message)) {
return panel;
}
}
}
return null;
}
/**
* Looks up the main label for a given editor notification panel
*/
private List<String> getEditorNotificationLabels(@NotNull EditorNotificationPanel panel) {
final List<String> allText = Lists.newArrayList();
final Collection<JLabel> labels = robot().finder().findAll(panel, JLabelMatcher.any().andShowing());
for (final JLabel label : labels) {
String text = execute(new GuiQuery<String>() {
@Override
@Nullable
protected String executeInEDT() throws Throwable {
return label.getText();
}
});
if (isNotEmpty(text)) {
allText.add(text);
}
}
return allText;
}
@NotNull
public IdeSettingsDialogFixture openIdeSettings() {
// Using invokeLater because we are going to show a *modal* dialog via API (instead of clicking a button, for example.) If we use
// GuiActionRunner the test will hang until the modal dialog is closed.
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
Project project = getProject();
ShowSettingsUtil.getInstance().showSettingsDialog(project, ShowSettingsUtilImpl.getConfigurableGroups(project, true));
}
});
return IdeSettingsDialogFixture.find(robot());
}
@NotNull
public RunConfigurationsDialogFixture invokeRunConfigurationsDialog() {
invokeMenuPath("Run", "Edit Configurations...");
return RunConfigurationsDialogFixture.find(robot());
}
@NotNull
public InspectionsFixture inspectCode() {
invokeMenuPath("Analyze", "Inspect Code...");
//final Ref<FileChooserDialogImpl> wrapperRef = new Ref<FileChooserDialogImpl>();
JDialog dialog = robot().finder().find(new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
return "Specify Inspection Scope".equals(dialog.getTitle());
}
});
JButton button = robot().finder().find(dialog, JButtonMatcher.withText("OK").andShowing());
robot().click(button);
final InspectionTree tree = waitUntilFound(robot(), new GenericTypeMatcher<InspectionTree>(InspectionTree.class) {
@Override
protected boolean isMatching(@NotNull InspectionTree component) {
return true;
}
});
return new InspectionsFixture(robot(), getProject(), tree);
}
@NotNull
public ProjectViewFixture getProjectView() {
return new ProjectViewFixture(getProject(), robot());
}
@NotNull
public Project getProject() {
Project project = target().getProject();
assertNotNull(project);
return project;
}
public void closeProject() {
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
closeAndDispose(getProject());
RecentProjectsManager.getInstance().updateLastProjectPath();
WelcomeFrame.showIfNoProjectOpened();
}
});
pause(new Condition("Waiting for 'Welcome' page to show up") {
@Override
public boolean test() {
for (Frame frame : Frame.getFrames()) {
if (frame == WelcomeFrame.getInstance() && frame.isShowing()) {
return true;
}
}
return false;
}
});
}
@NotNull
public MessagesFixture findMessageDialog(@NotNull String title) {
return MessagesFixture.findByTitle(robot(), target(), title);
}
@NotNull
public FindDialogFixture invokeFindInPathDialog() {
invokeMenuPath("Edit", "Find", "Find in Path...");
return FindDialogFixture.find(robot());
}
@NotNull
public FindToolWindowFixture getFindToolWindow() {
return new FindToolWindowFixture(this);
}
//@NotNull
//public GradleBuildModelFixture parseBuildFileForModule(@NotNull String moduleName, boolean openInEditor) {
// Module module = getModule(moduleName);
// return parseBuildFile(module, openInEditor);
//}
//
//@NotNull
//public GradleBuildModelFixture parseBuildFile(@NotNull Module module, boolean openInEditor) {
// VirtualFile buildFile = getGradleBuildFile(module);
// assertNotNull(buildFile);
// return parseBuildFile(buildFile, openInEditor);
//}
//
//@NotNull
//public GradleBuildModelFixture parseBuildFile(@NotNull final VirtualFile buildFile, boolean openInEditor) {
// if (openInEditor) {
// getEditor().open(buildFile, Tab.DEFAULT).getCurrentFile();
// }
// final Ref<GradleBuildModel> buildModelRef = new Ref<GradleBuildModel>();
// new ReadAction() {
// @Override
// protected void run(@NotNull Result result) throws Throwable {
// buildModelRef.set(GradleBuildModel.parseBuildFile(buildFile, getProject()));
// }
// }.execute();
// GradleBuildModel buildModel = buildModelRef.get();
// assertNotNull(buildModel);
// return new GradleBuildModelFixture(buildModel);
//}
private static class NoOpDisposable implements Disposable {
@Override
public void dispose() {
}
}
public void selectApp(@NotNull String appName) {
final ActionButtonFixture runButton = findRunApplicationButton();
Container actionToolbarContainer = execute(new GuiQuery<Container>() {
@Override
protected Container executeInEDT() throws Throwable {
return runButton.target().getParent();
}
});
assertNotNull(actionToolbarContainer);
ComboBoxActionFixture comboBoxActionFixture = ComboBoxActionFixture.findComboBox(robot(), actionToolbarContainer);
comboBoxActionFixture.selectItem(appName);
robot().pressAndReleaseKey(KeyEvent.VK_ENTER);
robot().waitForIdle();
}
/////////////////////////////////////////////////////////////////
//// Methods to help control debugging under a test. ///////
/////////////////////////////////////////////////////////////////
public void resumeProgram() {
invokeMenuPathOnRobotIdle(this, "Run", "Resume Program");
}
public void stepOver() {
invokeMenuPathOnRobotIdle(this, "Run", "Step Over");
}
public void stepInto() {
invokeMenuPathOnRobotIdle(this, "Run", "Step Into");
}
public void stepOut() {
invokeMenuPathOnRobotIdle(this, "Run", "Step Out");
}
/**
* Toggles breakpoints at the line numbers in {@code lines} of the source file with basename {@code fileBaseName}. This will work only
* if the fileBasename is unique in the project that's open on Android Studio.
*/
public void toggleBreakPoints(String fileBasename, int[] lines) {
// We open the file twice to bring the editor into focus. Idea 1.15 has this bug where opening a file doesn't automatically bring its
// editor window into focus.
openFile(this, fileBasename);
openFile(this, fileBasename);
for (int line : lines) {
navigateToLine(this, line);
invokeMenuPathOnRobotIdle(this, "Run", "Toggle Line Breakpoint");
}
}
// Recursively prints out the debugger tree rooted at {@code node} into {@code builder} with an indent of
// "{@code level} * {@code numIndentSpaces}" whitespaces. Each node is printed on a separate line. The indent level for every child node
// is 1 more than their parent.
private static void printNode(XDebuggerTreeNode node, StringBuilder builder, int level, int numIndentSpaces) {
int numIndent = level;
if (builder.length() > 0) {
builder.append(System.getProperty("line.separator"));
}
for (int i = 0; i < level * numIndentSpaces; ++i) {
builder.append(' ');
}
builder.append(node.getText().toString());
Enumeration<XDebuggerTreeNode> children = node.children();
while (children.hasMoreElements()) {
printNode(children.nextElement(), builder, level + 1, numIndentSpaces);
}
}
/**
* Prints out the debugger tree rooted at {@code root}.
*/
@NotNull
public static String printDebuggerTree(XDebuggerTreeNode root) {
StringBuilder builder = new StringBuilder();
printNode(root, builder, 0, 2);
return builder.toString();
}
@NotNull
private static String[] debuggerTreeRootToChildrenTexts(XDebuggerTreeNode treeRoot) {
List<? extends TreeNode> children = treeRoot.getChildren();
String[] childrenTexts = new String[children.size()];
int i = 0;
for (TreeNode child : children) {
childrenTexts[i] = ((XDebuggerTreeNode)child).getText().toString();
++i;
}
return childrenTexts;
}
/**
* Returns the subset of {@code expectedPatterns} which do not match any of the children (just the first level children, not recursive) of
* {@code treeRoot} .
*/
@NotNull
public static List<String> getUnmatchedTerminalVariableValues(String[] expectedPatterns, XDebuggerTreeNode treeRoot) {
String[] childrenTexts = debuggerTreeRootToChildrenTexts(treeRoot);
List<String> unmatchedPatterns = Lists.newArrayList();
for (String expectedPattern : expectedPatterns) {
boolean matched = false;
for (String childText : childrenTexts) {
if (childText.matches(expectedPattern)) {
matched = true;
break;
}
}
if (!matched) {
unmatchedPatterns.add(expectedPattern);
}
}
return unmatchedPatterns;
}
/**
* Returns the appropriate pattern to look for a variable named {@code name} with the type {@code type} and value {@code value} appearing
* in the Variables window in Android Studio.
*/
@NotNull
public static String variableToSearchPattern(String name, String type, String value) {
return String.format("%s = \\{%s\\} %s", name, type, value);
}
public boolean verifyVariablesAtBreakpoint(String[] expectedVariablePatterns, String debugConfigName, long tryUntilMillis) {
DebugToolWindowFixture debugToolWindowFixture = new DebugToolWindowFixture(this);
final ExecutionToolWindowFixture.ContentFixture contentFixture = debugToolWindowFixture.findContent(debugConfigName);
contentFixture.clickDebuggerTreeRoot();
// Wait for the debugger tree to appear.
pause(new Condition("Looking for debugger tree.") {
@Override
public boolean test() {
return contentFixture.getDebuggerTreeRoot() != null;
}
}, Timeout.timeout(tryUntilMillis));
// Get the debugger tree and print it.
XDebuggerTreeNode debuggerTreeRoot = contentFixture.getDebuggerTreeRoot();
if (debuggerTreeRoot == null) {
return false;
}
List<String> unmatchedPatterns = getUnmatchedTerminalVariableValues(expectedVariablePatterns, debuggerTreeRoot);
return unmatchedPatterns.isEmpty();
}
}
@@ -1,120 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Ref;
import org.fest.reflect.exception.ReflectionError;
import org.fest.reflect.reference.TypeRef;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.fixture.ContainerFixture;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.lang.ref.WeakReference;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickCancelButton;
import static com.intellij.tests.gui.framework.GuiTests.waitUntilFound;
import static junit.framework.Assert.assertNotNull;
import static org.fest.reflect.core.Reflection.field;
public abstract class IdeaDialogFixture<T extends DialogWrapper> extends ComponentFixture<IdeaDialogFixture, JDialog> implements ContainerFixture<JDialog> {
@NotNull private final T myDialogWrapper;
@Nullable
protected static <T extends DialogWrapper> T getDialogWrapperFrom(@NotNull JDialog dialog, Class<T> dialogWrapperType) {
try {
WeakReference<DialogWrapper> dialogWrapperRef = field("myDialogWrapper").ofType(new TypeRef<WeakReference<DialogWrapper>>() {})
.in(dialog)
.get();
assertNotNull(dialogWrapperRef);
DialogWrapper wrapper = dialogWrapperRef.get();
if (dialogWrapperType.isInstance(wrapper)) {
return dialogWrapperType.cast(wrapper);
}
}
catch (ReflectionError ignored) {
}
return null;
}
public static class DialogAndWrapper<T extends DialogWrapper> {
public final JDialog dialog;
public final T wrapper;
public DialogAndWrapper(@NotNull JDialog dialog, @NotNull T wrapper) {
this.dialog = dialog;
this.wrapper = wrapper;
}
}
@NotNull
public static <T extends DialogWrapper> DialogAndWrapper<T> find(@NotNull Robot robot, @NotNull final Class<T> clz) {
return find(robot, clz, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog component) {
return component.isShowing();
}
});
}
@NotNull
public static <T extends DialogWrapper> DialogAndWrapper<T> find(@NotNull Robot robot, @NotNull final Class<T> clz,
@NotNull final GenericTypeMatcher<JDialog> matcher) {
final Ref<T> wrapperRef = new Ref<T>();
JDialog dialog = waitUntilFound(robot, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
if (matcher.matches(dialog)) {
T wrapper = getDialogWrapperFrom(dialog, clz);
if (wrapper != null) {
wrapperRef.set(wrapper);
return true;
}
}
return false;
}
});
return new DialogAndWrapper<T>(dialog, wrapperRef.get());
}
protected IdeaDialogFixture(@NotNull Robot robot, @NotNull JDialog target, @NotNull T dialogWrapper) {
super(IdeaDialogFixture.class, robot, target);
myDialogWrapper = dialogWrapper;
}
protected IdeaDialogFixture(@NotNull Robot robot, @NotNull DialogAndWrapper<T> dialogAndWrapper) {
this(robot, dialogAndWrapper.dialog, dialogAndWrapper.wrapper);
}
@NotNull
protected T getDialogWrapper() {
return myDialogWrapper;
}
public void clickCancel() {
// Grab focus in case it is not automatically done by the window manager, e.g. 9wm
focus();
findAndClickCancelButton(this);
}
public void close() {
robot().close(target());
}
}
@@ -1,69 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.core.matcher.JTextComponentMatcher;
import org.fest.swing.fixture.JTextComponentFixture;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickOkButton;
import static com.intellij.tests.gui.framework.GuiTests.waitUntilFound;
import static org.junit.Assert.assertNotNull;
public class InputDialogFixture extends IdeaDialogFixture<DialogWrapper> {
@NotNull
public static InputDialogFixture findByTitle(@NotNull Robot robot, @NotNull final String title) {
final Ref<DialogWrapper> wrapperRef = new Ref<DialogWrapper>();
JDialog dialog = waitUntilFound(robot, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
if (!title.equals(dialog.getTitle()) || !dialog.isShowing()) {
return false;
}
DialogWrapper wrapper = getDialogWrapperFrom(dialog, DialogWrapper.class);
if (wrapper != null) {
String typeName = Messages.class.getName() + "$InputDialog";
if (typeName.equals(wrapper.getClass().getName())) {
wrapperRef.set(wrapper);
return true;
}
}
return false;
}
});
return new InputDialogFixture(robot, dialog, wrapperRef.get());
}
public void enterTextAndClickOk(@NotNull String text) {
JTextComponent input = robot().finder().find(target(), JTextComponentMatcher.any());
assertNotNull(input);
JTextComponentFixture inputFixture = new JTextComponentFixture(robot(), input);
inputFixture.enterText(text);
findAndClickOkButton(this);
}
private InputDialogFixture(@NotNull Robot robot, @NotNull JDialog target, @NotNull DialogWrapper dialogWrapper) {
super(robot, target, dialogWrapper);
}
}
@@ -1,117 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.ui.components.JBList;
import com.intellij.ui.popup.PopupFactoryImpl;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.MouseButton;
import org.fest.swing.core.Robot;
import org.fest.swing.timing.Condition;
import org.junit.Assert;
import javax.annotation.Nonnull;
import javax.swing.*;
import java.awt.*;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static org.fest.swing.timing.Pause.pause;
/**
* Created by jetbrains on 29/08/16.
*/
public class JBListPopupFixture extends JComponentFixture<JBListPopupFixture, JBList> {
private static final Logger LOG = Logger.getInstance("#com.intellij.tests.gui.fixtures.JBListPopupFixture");
private JBList myJBList;
private Robot myRobot;
private JBListPopupFixture(JBList jbList, Robot robot) {
super(JBListPopupFixture.class, robot, jbList);
myJBList = jbList;
myRobot = robot;
}
public static JBListPopupFixture findListPopup(Robot robot) {
pause(new Condition("Find JBList popup") {
@Override
public boolean test() {
final JBList jblist = getList(robot);
return jblist != null;
}
}, SHORT_TIMEOUT);
final JBList jblist = getList(robot);
Assert.assertNotNull(jblist);
return new JBListPopupFixture(jblist, robot);
}
private static JBList getList(Robot robot) {
return robot.finder().find(new GenericTypeMatcher<JBList>(JBList.class) {
@Override
protected boolean isMatching(@Nonnull JBList list) {
Container parent = list.getRootPane().getParent();
if (parent == null) return false;
if (parent instanceof JWindow && ((JWindow)parent).getType() == Window.Type.POPUP) {
return true;
}
return false;
}
});
}
public void assertContainsAction(String actionName) {
boolean assertion = false;
ListModel listModel = myJBList.getModel();
for (int i = 0; i < myJBList.getItemsCount(); i++) {
Object elementAt = listModel.getElementAt(i);
if (elementAt instanceof PopupFactoryImpl.ActionItem) {
if (((PopupFactoryImpl.ActionItem)elementAt).getText().toLowerCase().contains(actionName.toLowerCase())) assertion = true;
}
}
if (!assertion) LOG.error("Unable to find action \"" + actionName + "\" in popupList");
assert assertion;
}
public void invokeAction(String actionName) {
int actionIndex = -1;
ListModel listModel = myJBList.getModel();
for (int i = 0; i < myJBList.getItemsCount(); i++) {
Object elementAt = listModel.getElementAt(i);
if (elementAt instanceof PopupFactoryImpl.ActionItem) {
if (((PopupFactoryImpl.ActionItem)elementAt).getText().toLowerCase().contains(actionName.toLowerCase())) actionIndex = i;
}
}
if (actionIndex == -1) {
LOG.error("Unable to find action \"" + actionName + "\" in popupMenu");
} else {
final Rectangle cellBounds = myJBList.getCellBounds(actionIndex, actionIndex);
final Point locationOnScreen = myJBList.getLocationOnScreen();
final Point point =
new Point(locationOnScreen.x + cellBounds.x + cellBounds.width / 2,
locationOnScreen.y + cellBounds.y + cellBounds.height / 2);
robot().click(point, MouseButton.LEFT_BUTTON, 1);
}
}
}
@@ -1,151 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.actionSystem.impl.ActionMenu;
import com.intellij.openapi.actionSystem.impl.ActionMenuItem;
import com.intellij.openapi.ui.JBPopupMenu;
import com.intellij.util.ArrayUtil;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.MouseButton;
import org.fest.swing.core.Robot;
import org.fest.swing.timing.Condition;
import javax.annotation.Nonnull;
import javax.swing.*;
import java.awt.*;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static com.intellij.tests.gui.framework.GuiTests.waitUntilFound;
import static com.intellij.util.containers.ContainerUtil.getFirstItem;
import static junit.framework.Assert.assertNotNull;
import static org.fest.swing.timing.Pause.pause;
public class JBPopupFixture extends JComponentFixture<JBPopupFixture, JBPopupMenu> {
private JBPopupMenu myContextMenu;
private Robot myRobot;
private JBPopupFixture(JBPopupMenu menu, Robot robot) {
super(JBPopupFixture.class, robot, menu);
myContextMenu = menu;
myRobot = robot;
}
public static JBPopupFixture findContextMenu(Robot robot) {
pause(new Condition("Find context menu") {
@Override
public boolean test() {
final JBPopupMenu contextMenu = robot.finder().findByType(JBPopupMenu.class);
return contextMenu != null;
}
}, SHORT_TIMEOUT);
final JBPopupMenu contextMenu = robot.finder().findByType(JBPopupMenu.class);
assertNotNull(contextMenu);
return new JBPopupFixture(contextMenu, robot);
}
public void assertContainsAction(String actionName) {
boolean assertion = false;
final MenuElement[] elements = myContextMenu.getSubElements();
for (MenuElement element : elements) {
if (element instanceof ActionMenuItem) {
if (((ActionMenuItem)element).getText().toLowerCase().contains(actionName.toLowerCase())) assertion = true;
}
}
if (!assertion) System.err.println("Unable to find action \"" + actionName + "\" in popupMenu");
assert assertion;
}
public void invokeAction(String... actionPath) {
boolean assertion = false;
final MenuElement[] elements = myContextMenu.getSubElements();
if (actionPath.length > 1) {
//actionGroup
for (MenuElement element : elements) {
if (element instanceof ActionMenu) {
final ActionMenu actionMenu = (ActionMenu)element;
if (actionMenu.getText().toLowerCase().contains(actionPath[0].toLowerCase())) {
final Point locationOnScreen = myContextMenu.getLocationOnScreen();
final Rectangle bounds = actionMenu.getBounds();
final Point point =
new Point(locationOnScreen.x + bounds.x + bounds.width / 2, locationOnScreen.y + bounds.y + bounds.height / 2);
robot().click(point, MouseButton.LEFT_BUTTON, 1);
//invoke action for a new JBPopupMenu
final String actionName = actionPath[1];
final JBPopupFixture fixture = new JBPopupFixture(waitUntilFoundMenu(actionName), myRobot);
fixture.invokeAction(ArrayUtil.remove(actionPath, 0));
return;
}
}
}
}
else {
//actionMenuItem
for (MenuElement element : elements) {
if (element instanceof ActionMenuItem) {
final ActionMenuItem actionMenuItem = (ActionMenuItem)element;
if (actionMenuItem.getText().toLowerCase().contains(actionPath[0].toLowerCase())) {
pause(new Condition("Waiting to showing JBPopupMenu on screen") {
@Override
public boolean test() {
try{
myContextMenu.getLocationOnScreen();
return true;
} catch (IllegalComponentStateException e) {
return false;
}
}
}, SHORT_TIMEOUT);
final Point locationOnScreen = myContextMenu.getLocationOnScreen();
final Rectangle bounds = actionMenuItem.getBounds();
final Point point =
new Point(locationOnScreen.x + bounds.x + bounds.width / 2, locationOnScreen.y + bounds.y + bounds.height / 2);
robot().click(point, MouseButton.LEFT_BUTTON, 1);
return;
}
}
}
}
}
private JBPopupMenu waitUntilFoundMenu(final String actionName) {
return waitUntilFound(robot(), new GenericTypeMatcher<JBPopupMenu>(JBPopupMenu.class) {
@Override
protected boolean isMatching(@Nonnull JBPopupMenu menu) {
boolean found = false;
for (MenuElement menuElement : menu.getSubElements()) {
if (menuElement instanceof ActionMenu) {
if (((ActionMenu)menuElement).getText().toLowerCase().equals(actionName.toLowerCase())) {
found = true;
}
}
else if (menuElement instanceof ActionMenuItem) {
if (((ActionMenuItem)menuElement).getText().toLowerCase().equals(actionName.toLowerCase())) {
found = true;
}
}
}
return found;
}
});
}
}
@@ -1,73 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import static com.google.common.base.Strings.nullToEmpty;
import static com.intellij.tests.gui.framework.GuiTests.LONG_TIMEOUT;
import static com.intellij.tests.gui.framework.GuiTests.waitUntilFound;
import static org.fest.swing.edt.GuiActionRunner.execute;
class MessageDialogFixture extends IdeaDialogFixture<DialogWrapper> implements MessagesFixture.Delegate {
@NotNull
static MessageDialogFixture findByTitle(@NotNull Robot robot, @NotNull final String title) {
final Ref<DialogWrapper> wrapperRef = new Ref<DialogWrapper>();
JDialog dialog = waitUntilFound(robot, null, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
if (!title.equals(dialog.getTitle()) || !dialog.isShowing()) {
return false;
}
DialogWrapper wrapper = getDialogWrapperFrom(dialog, DialogWrapper.class);
if (wrapper != null) {
String typeName = Messages.class.getName() + "$MessageDialog";
if (typeName.equals(wrapper.getClass().getName())) {
wrapperRef.set(wrapper);
return true;
}
}
return false;
}
}, LONG_TIMEOUT);
return new MessageDialogFixture(robot, dialog, wrapperRef.get());
}
private MessageDialogFixture(@NotNull Robot robot, @NotNull JDialog target, @NotNull DialogWrapper dialogWrapper) {
super(robot, target, dialogWrapper);
}
@Override
@NotNull
public String getMessage() {
final JTextPane textPane = robot().finder().findByType(target(), JTextPane.class);
//noinspection ConstantConditions
return execute(new GuiQuery<String>() {
@Override
protected String executeInEDT() throws Throwable {
return nullToEmpty(textPane.getText());
}
});
}
}
@@ -1,173 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.Messages;
import com.intellij.ui.messages.SheetController;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.fixture.ContainerFixture;
import org.fest.swing.fixture.JPanelFixture;
import org.jdom.Document;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import static com.google.common.base.Strings.nullToEmpty;
import static com.intellij.openapi.util.JDOMUtil.loadDocument;
import static com.intellij.tests.gui.framework.GuiTests.*;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.reflect.core.Reflection.field;
import static org.junit.Assert.assertNotNull;
public class MessagesFixture {
@NotNull private final ContainerFixture<? extends Container> myDelegate;
@NotNull
public static MessagesFixture findByTitle(@NotNull Robot robot, @NotNull Container root, @NotNull String title) {
if (Messages.canShowMacSheetPanel()) {
return new MessagesFixture(findMacSheetByTitle(robot, root, title));
}
MessageDialogFixture dialog = MessageDialogFixture.findByTitle(robot, title);
return new MessagesFixture(dialog);
}
private MessagesFixture(@NotNull ContainerFixture<? extends Container> delegate) {
myDelegate = delegate;
}
@NotNull
public MessagesFixture clickOk() {
findAndClickOkButton(myDelegate);
return this;
}
@NotNull
public MessagesFixture clickYes() {
return click("Yes");
}
@NotNull
public MessagesFixture click(@NotNull String text) {
findAndClickButton(myDelegate, text);
return this;
}
@NotNull
public MessagesFixture requireMessageContains(@NotNull String message) {
String actual = ((Delegate)myDelegate).getMessage();
assertThat(actual).contains(message);
return this;
}
public void clickCancel() {
findAndClickCancelButton(myDelegate);
}
@NotNull
static JPanelFixture findMacSheetByTitle(@NotNull Robot robot, @NotNull Container root, @NotNull String title) {
JPanel sheetPanel = waitUntilFound(robot, root, new GenericTypeMatcher<JPanel>(JPanel.class) {
@Override
protected boolean isMatching(@NotNull JPanel panel) {
if (panel.getClass().getName().startsWith(SheetController.class.getName()) && panel.isShowing()) {
SheetController controller = findSheetController(panel);
JPanel sheetPanel = field("mySheetPanel").ofType(JPanel.class).in(controller).get();
if (sheetPanel == panel) {
return true;
}
}
return false;
}
}, LONG_TIMEOUT);
String sheetTitle = getTitle(sheetPanel, robot);
assertThat(sheetTitle).as("Sheet title").isEqualTo(title);
return new MacSheetPanelFixture(robot, sheetPanel);
}
@Nullable
private static String getTitle(@NotNull JPanel sheetPanel, @NotNull Robot robot) {
final JEditorPane messageTextPane = getMessageTextPane(sheetPanel);
JEditorPane titleTextPane = robot.finder().find(sheetPanel, new GenericTypeMatcher<JEditorPane>(JEditorPane.class) {
@Override
protected boolean isMatching(@NotNull JEditorPane editorPane) {
return editorPane != messageTextPane;
}
});
return getHtmlBody(titleTextPane.getText());
}
@Nullable
public <T extends JComponent> T find(GenericTypeMatcher<T> matcher) {
return myDelegate.robot().finder().find(myDelegate.target(), matcher);
}
interface Delegate {
@NotNull String getMessage();
}
private static class MacSheetPanelFixture extends JPanelFixture implements Delegate {
public MacSheetPanelFixture(@NotNull Robot robot, @NotNull JPanel target) {
super(robot, target);
}
@Override
@NotNull
public String getMessage() {
JEditorPane messageTextPane = getMessageTextPane(target());
String text = getHtmlBody(messageTextPane.getText());
return nullToEmpty(text);
}
}
@NotNull
private static JEditorPane getMessageTextPane(@NotNull JPanel sheetPanel) {
SheetController sheetController = findSheetController(sheetPanel);
JEditorPane messageTextPane = field("messageTextPane").ofType(JEditorPane.class).in(sheetController).get();
assertNotNull(messageTextPane);
return messageTextPane;
}
@NotNull
private static SheetController findSheetController(@NotNull JPanel sheetPanel) {
SheetController sheetController = field("this$0").ofType(SheetController.class).in(sheetPanel).get();
assertNotNull(sheetController);
return sheetController;
}
@Nullable
private static String getHtmlBody(@NotNull String html) {
try {
Document document = loadDocument(html);
Element rootElement = document.getRootElement();
String sheetTitle = rootElement.getChild("body").getText();
return sheetTitle.replace("\n", "").trim();
}
catch (Throwable e) {
Logger.getInstance(MessagesFixture.class).info("Failed to parse HTML '" + html + "'", e);
}
return null;
}
}
@@ -1,334 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.impl.AbstractProjectViewPane;
import com.intellij.ide.projectView.impl.nodes.*;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import com.intellij.ide.util.treeView.AbstractTreeStructure;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.JdkOrderEntry;
import com.intellij.openapi.roots.LibraryOrSdkOrderEntry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.util.ui.tree.TreeUtil;
import org.fest.swing.core.MouseButton;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.timing.Condition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.reflect.core.Reflection.field;
import static org.fest.swing.timing.Pause.pause;
import static org.junit.Assert.assertNotNull;
public class ProjectViewFixture extends ToolWindowFixture {
ProjectViewFixture(@NotNull Project project, @NotNull Robot robot) {
super("Project", project, robot);
}
@NotNull
public PaneFixture selectProjectPane() {
activate();
final ProjectView projectView = ProjectView.getInstance(myProject);
pause(new Condition("Project view is initialized") {
@Override
public boolean test() {
//noinspection ConstantConditions
return field("isInitialized").ofType(boolean.class).in(projectView).get();
}
}, SHORT_TIMEOUT);
final String id = "ProjectPane";
GuiActionRunner.execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
projectView.changeView(id);
}
});
return new PaneFixture(projectView.getProjectViewPaneById(id));
}
@NotNull
public PaneFixture selectAndroidPane() {
activate();
final ProjectView projectView = ProjectView.getInstance(myProject);
pause(new Condition("Project view is initialized") {
@Override
public boolean test() {
//noinspection ConstantConditions
return field("isInitialized").ofType(boolean.class).in(projectView).get();
}
}, SHORT_TIMEOUT);
final String id = "AndroidView";
GuiActionRunner.execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
projectView.changeView(id);
}
});
return new PaneFixture(projectView.getProjectViewPaneById(id));
}
public static class PaneFixture {
@NotNull private final AbstractProjectViewPane myPane;
PaneFixture(@NotNull AbstractProjectViewPane pane) {
myPane = pane;
}
@NotNull
public PaneFixture expand() {
GuiActionRunner.execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
TreeUtil.expandAll(myPane.getTree());
}
});
return this;
}
@NotNull
private AbstractTreeStructure getTreeStructure() {
final AtomicReference<AbstractTreeStructure> treeStructureRef = new AtomicReference<AbstractTreeStructure>();
pause(new Condition("Tree Structure to be built") {
@Override
public boolean test() {
AbstractTreeStructure treeStructure = GuiActionRunner.execute(new GuiQuery<AbstractTreeStructure>() {
@Override
protected AbstractTreeStructure executeInEDT() throws Throwable {
try {
return myPane.getTreeBuilder().getTreeStructure();
}
catch (NullPointerException e) {
// expected;
}
return null;
}
});
treeStructureRef.set(treeStructure);
return treeStructure != null;
}
}, SHORT_TIMEOUT);
return treeStructureRef.get();
}
@NotNull
public NodeFixture findExternalLibrariesNode() {
final AbstractTreeStructure treeStructure = getTreeStructure();
ExternalLibrariesNode node = GuiActionRunner.execute(new GuiQuery<ExternalLibrariesNode>() {
@Nullable
@Override
protected ExternalLibrariesNode executeInEDT() throws Throwable {
Object[] childElements = treeStructure.getChildElements(treeStructure.getRootElement());
for (Object child : childElements) {
if (child instanceof ExternalLibrariesNode) {
return (ExternalLibrariesNode)child;
}
}
return null;
}
});
if (node != null) {
return new NodeFixture(node, treeStructure, myPane);
}
throw new AssertionError("Unable to find 'External Libraries' node");
}
public NodeFixture selectByPath(@NotNull final String... paths) {
final AbstractTreeStructure treeStructure = getTreeStructure();
final BasePsiNode node = GuiActionRunner.execute(new GuiQuery<BasePsiNode>() {
@Nullable
@Override
protected BasePsiNode executeInEDT() throws Throwable {
Object root = treeStructure.getRootElement();
final List<Object> treePath = Lists.newArrayList(root);
for (String path : paths) {
Object[] childElements = treeStructure.getChildElements(root);
Object newRoot = null;
for (Object child : childElements) {
if (child instanceof PsiDirectoryNode) {
PsiDirectory dir = ((PsiDirectoryNode)child).getValue();
if (dir != null && path.equals(dir.getName())) {
newRoot = child;
treePath.add(newRoot);
break;
}
}
if (child instanceof PsiFileNode) {
PsiFile file = ((PsiFileNode)child).getValue();
if (file != null && path.equals(file.getName())) {
newRoot = child;
treePath.add(newRoot);
break;
}
}
}
if (newRoot != null) {
root = newRoot;
}
else {
return null;
}
}
if (root == treeStructure.getRootElement()) {
return null;
}
myPane.expand(treePath.toArray(), true);
myPane.select(root, ((BasePsiNode)root).getVirtualFile(), true);
return (BasePsiNode)root;
}
});
assertNotNull(node);
pause(new Condition("Node to be selected") {
@Override
public boolean test() {
return node.equals(GuiActionRunner.execute(new GuiQuery<Object>() {
@Override
protected Object executeInEDT() throws Throwable {
DefaultMutableTreeNode selectedNode = myPane.getSelectedNode();
if (selectedNode != null) {
return selectedNode.getUserObject();
}
return null;
}
}));
}
}, SHORT_TIMEOUT);
return (new NodeFixture(node, treeStructure, myPane));
}
public void getSelectedNodeLocation() {
}
}
public static class NodeFixture {
@NotNull private final ProjectViewNode<?> myNode;
@NotNull private final AbstractTreeStructure myTreeStructure;
@NotNull private final AbstractProjectViewPane myPane;
NodeFixture(@NotNull ProjectViewNode<?> node, @NotNull AbstractTreeStructure treeStructure, @NotNull AbstractProjectViewPane pane) {
myNode = node;
myTreeStructure = treeStructure;
myPane = pane;
}
@NotNull
public List<NodeFixture> getChildren() {
final List<NodeFixture> children = Lists.newArrayList();
GuiActionRunner.execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
for (Object child : myTreeStructure.getChildElements(myNode)) {
if (child instanceof ProjectViewNode) {
children.add(new NodeFixture((ProjectViewNode<?>)child, myTreeStructure, myPane));
}
}
}
});
return children;
}
public Point getLocation() {
myPane.getTree();
final JTree tree = myPane.getTree();
final DefaultMutableTreeNode dmtn = TreeUtil.findNodeWithObject((DefaultMutableTreeNode)tree.getModel().getRoot(), myNode);
final TreePath path = TreeUtil.getPathFromRoot(dmtn);
final Rectangle bounds = tree.getPathBounds(path);
assertNotNull(bounds);
return new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
}
public Point getLocationOnScreen() {
final Point locationOnScreen = myPane.getComponentToFocus().getLocationOnScreen();
final Point location = getLocation();
return new Point(locationOnScreen.x + location.x, locationOnScreen.y + location.y);
}
public void click(Robot robot) {
robot.click(getLocationOnScreen(), MouseButton.LEFT_BUTTON, 1);
}
public void doubleClick(Robot robot) {
robot.click(getLocationOnScreen(), MouseButton.LEFT_BUTTON, 2);
}
public void rightClick(Robot robot) {
invokeContextMenu(robot);
}
public void invokeContextMenu(Robot robot) {
robot.click(getLocationOnScreen(), MouseButton.RIGHT_BUTTON, 1);
}
public boolean isJdk() {
if (myNode instanceof NamedLibraryElementNode) {
NamedLibraryElement value = ((NamedLibraryElementNode)myNode).getValue();
assertNotNull(value);
LibraryOrSdkOrderEntry orderEntry = value.getOrderEntry();
if (orderEntry instanceof JdkOrderEntry) {
Sdk sdk = ((JdkOrderEntry)orderEntry).getJdk();
return sdk.getSdkType() instanceof JavaSdk;
}
}
return false;
}
@NotNull
public NodeFixture requireDirectory(@NotNull String name) {
assertThat(myNode).isInstanceOf(PsiDirectoryNode.class);
VirtualFile file = myNode.getVirtualFile();
assertNotNull(file);
assertThat(file.getName()).isEqualTo(name);
return this;
}
@Override
public String toString() {
return Strings.nullToEmpty(myNode.getName());
}
}
}
@@ -1,138 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.rename.RenameDialog;
import com.intellij.refactoring.rename.RenameHandler;
import com.intellij.ui.EditorTextField;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.intellij.tests.gui.framework.GuiTests.waitUntilFound;
import static org.fest.reflect.core.Reflection.field;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.junit.Assert.assertNotNull;
public class RenameDialogFixture extends IdeaDialogFixture<RenameDialog> {
public RenameDialogFixture(@NotNull Robot robot, @NotNull JDialog target, @NotNull RenameDialog dialogWrapper) {
super(robot, target, dialogWrapper);
}
/**
* Starts 'rename' refactoring for the given data.
* <p/>
* <b>Note:</b> proper way would be to write dedicated 'project view fixture' and emulate user actions like 'expand nodes until
* we find a target one' but that IJ component (project view) is rather complex and it's much easier to start the refactoring
* programmatically.
*
* @param element target PSI element for which 'rename' refactoring should begin
* @param handler rename refactoring handler to use
* @param robot robot to use
* @return a fixture for the 'rename dialog' which occurs when we start 'rename' refactoring for the given data
*/
@NotNull
public static RenameDialogFixture startFor(@NotNull final PsiElement element,
@NotNull final RenameHandler handler,
@NotNull Robot robot)
{
// We use SwingUtilities instead of FEST here because RenameDialog is modal and GuiActionRunner doesn't return until
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
handler.invoke(element.getProject(), new PsiElement[] { element }, SimpleDataContext.getProjectContext(element.getProject()));
}
});
final Ref<RenameDialog> ref = new Ref<RenameDialog>();
JDialog dialog = waitUntilFound(robot, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
if (!RefactoringBundle.message("rename.title").equals(dialog.getTitle()) || !dialog.isShowing()) {
return false;
}
RenameDialog renameDialog = getDialogWrapperFrom(dialog, RenameDialog.class);
if (renameDialog == null) {
return false;
}
ref.set(renameDialog);
return true;
}
});
return new RenameDialogFixture(robot, dialog, ref.get());
}
@NotNull
public String getNewName() {
//noinspection ConstantConditions
return execute(new GuiQuery<String>() {
@Override
protected String executeInEDT() throws Throwable {
String text = robot().finder().findByType(target(), EditorTextField.class).getText();
return text == null ? "" : text;
}
});
}
public void setNewName(@NotNull final String newName) {
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
robot().finder().findByType(target(), EditorTextField.class).setText(newName);
}
});
}
/**
* Allows to check if a warning exists at the target 'rename dialog'
*
* @param warningText <code>null</code> as a wildcard to match any non-empty warning text;
* non-null text which is evaluated to be a part of the target dialog's warning text
* @return <code>true</code> if the target 'rename dialog' has a warning and given text matches it according to the
* rules described above; <code>false</code> otherwise
*/
public boolean warningExists(@Nullable final String warningText) {
//noinspection ConstantConditions
return execute(new GuiQuery<Boolean>() {
@Override
protected Boolean executeInEDT() throws Throwable {
JComponent errorTextPane = field("myErrorText").ofType(JComponent.class).in(getDialogWrapper()).get();
assertNotNull(errorTextPane);
if (!errorTextPane.isVisible()) {
return false;
}
JLabel errorLabel = field("myLabel").ofType(JLabel.class).in(errorTextPane).get();
assertNotNull(errorLabel);
String text = errorLabel.getText();
if (isNullOrEmpty(text)) {
return false;
}
return warningText == null || text.contains(warningText);
}
});
}
}
@@ -1,110 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.android.tools.lint.detector.api.TextFormat;
import com.intellij.refactoring.rename.RenameDialog;
import com.intellij.refactoring.ui.ConflictsDialog;
import com.intellij.ui.EditorTextField;
import org.fest.swing.core.Robot;
import org.fest.swing.core.matcher.JTextComponentMatcher;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.jetbrains.annotations.NotNull;
import javax.swing.text.JTextComponent;
import java.awt.event.KeyEvent;
import java.util.regex.Pattern;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickButton;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class RenameRefactoringDialogFixture extends IdeaDialogFixture<RenameDialog> {
@NotNull
public static RenameRefactoringDialogFixture find(@NotNull Robot robot) {
return new RenameRefactoringDialogFixture(robot, find(robot, RenameDialog.class));
}
private RenameRefactoringDialogFixture(@NotNull Robot robot, @NotNull DialogAndWrapper<RenameDialog> dialogAndWrapper) {
super(robot, dialogAndWrapper);
}
@NotNull
public RenameRefactoringDialogFixture setNewName(@NotNull final String newName) {
final EditorTextField field = robot().finder().findByType(target(), EditorTextField.class);
GuiActionRunner.execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
field.requestFocus();
}
});
robot().pressAndReleaseKey(KeyEvent.VK_BACK_SPACE); // to make sure we don't append to existing item on Linux
robot().enterText(newName);
return this;
}
@NotNull
public RenameRefactoringDialogFixture clickRefactor() {
findAndClickButton(this, "Refactor");
return this;
}
public static class ConflictsDialogFixture extends IdeaDialogFixture<ConflictsDialog> {
protected ConflictsDialogFixture(@NotNull Robot robot, @NotNull DialogAndWrapper<ConflictsDialog> dialogAndWrapper) {
super(robot, dialogAndWrapper);
}
@NotNull
public static ConflictsDialogFixture find(@NotNull Robot robot) {
return new ConflictsDialogFixture(robot, find(robot, ConflictsDialog.class));
}
@NotNull
public ConflictsDialogFixture clickContinue() {
findAndClickButton(this, "Continue");
return this;
}
public String getHtml() {
final JTextComponent component = robot().finder().find(target(), JTextComponentMatcher.any());
return GuiActionRunner.execute(new GuiQuery<String>() {
@Override
protected String executeInEDT() throws Throwable {
return component.getText();
}
});
}
public String getText() {
String html = getHtml();
return TextFormat.HTML.convertTo(html, TextFormat.TEXT).trim();
}
public void requireMessageText(@NotNull String text) {
assertEquals(text, getText());
}
public void requireMessageTextContains(@NotNull String text) {
assertTrue(getText() + " does not contain expected message fragment " + text, getText().contains(text));
}
public void requireMessageTextMatches(@NotNull String regexp) {
assertTrue(getText() + " does not match " + regexp, Pattern.matches(regexp, getText()));
}
}
}
@@ -1,59 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import org.fest.swing.core.Robot;
import org.fest.swing.core.matcher.DialogMatcher;
import org.fest.swing.core.matcher.JLabelMatcher;
import org.fest.swing.driver.JTextComponentDriver;
import org.fest.swing.fixture.ContainerFixture;
import org.jetbrains.annotations.NotNull;
import javax.swing.text.JTextComponent;
import java.awt.*;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickOkButton;
public class ResourceChooserDialogFixture extends ComponentFixture<ResourceChooserDialogFixture, Dialog>
implements ContainerFixture<Dialog> {
@NotNull
public static ResourceChooserDialogFixture findDialog(@NotNull Robot robot) {
Dialog jDialog = robot.finder().find(DialogMatcher.withTitle("Select Resource Directory").andShowing());
return new ResourceChooserDialogFixture(robot, jDialog);
}
private ResourceChooserDialogFixture(@NotNull Robot robot, Dialog target) {
super(ResourceChooserDialogFixture.class, robot, target);
}
public void setDirectoryName(@NotNull String directory) {
Container parent = robot().finder().find(target(), JLabelMatcher.withText("Directory name:")).getParent();
JTextComponent directoryField = robot().finder().findByType(parent, JTextComponent.class, true);
JTextComponentDriver driver = new JTextComponentDriver(robot());
driver.selectAll(directoryField);
driver.setText(directoryField, directory);
}
@NotNull
public ResourceChooserDialogFixture clickOK() {
findAndClickOkButton(this);
return this;
}
}
@@ -1,153 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.tests.gui.matcher.ClassNameMatcher;
import com.intellij.ui.components.JBList;
import com.intellij.ui.popup.PopupFactoryImpl.ActionItem;
import com.intellij.ui.treeStructure.Tree;
import org.fest.swing.cell.JTreeCellReader;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.core.matcher.DialogMatcher;
import org.fest.swing.core.matcher.JButtonMatcher;
import org.fest.swing.driver.BasicJListCellReader;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.fixture.JListFixture;
import org.fest.swing.fixture.JTreeFixture;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import static com.intellij.tests.gui.framework.GuiTests.waitUntilFound;
import static org.fest.reflect.core.Reflection.method;
/**
* Controls the Run Configurations dialog
*/
public class RunConfigurationsDialogFixture extends ComponentFixture<RunConfigurationsDialogFixture, JDialog> {
public RunConfigurationsDialogFixture(@NotNull Robot robot, @NotNull JDialog target) {
super(RunConfigurationsDialogFixture.class, robot, target);
}
@NotNull
public static RunConfigurationsDialogFixture find(@NotNull Robot robot) {
JDialog frame = waitUntilFound(robot, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
return "Run/Debug Configurations".equals(dialog.getTitle()) && dialog.isShowing();
}
});
return new RunConfigurationsDialogFixture(robot, frame);
}
@NotNull
private JButton findButtonByText(@NotNull String text) {
return robot().finder().find(target(), JButtonMatcher.withText(text).andShowing());
}
public void save() {
robot().click(findButtonByText("OK"));
}
public JTreeFixture getTreeFixture() {
Tree tree = robot().finder().findByType(target(), Tree.class, true);
JTreeFixture fixture = new JTreeFixture(robot(), tree);
fixture.replaceCellReader(new RunConfigurationsJTreeCellReader());
return fixture;
}
public void select(String path) {
getTreeFixture().selectPath(path);
}
public void useGradleAwareMake() {
JBList stepsList = robot().finder().findByType(target(), JBList.class);
JListFixture stepsFixture = new JListFixture(robot(), stepsList);
// Find ActionToolbarImpl and ActionButtons inside.
if (!stepsFixture.contents()[0].equals("Make")) {
throw new IllegalStateException("There should be only only one make step, 'Make'.");
}
stepsFixture.clickItem(0);
JPanel beforeRunStepsPanel = robot().finder().find(
target(),
ClassNameMatcher.forClass("com.intellij.execution.impl.BeforeRunStepsPanel", JPanel.class, true));
ActionButtonFixture.findByText("Remove", robot(), beforeRunStepsPanel).click();
ActionButtonFixture.findByText("Add", robot(), beforeRunStepsPanel).click();
JBList popupList = robot().finder().find(
target(),
ClassNameMatcher.forClass("com.intellij.ui.popup.list.ListPopupImpl$MyList", JBList.class, true));
click(popupList, "Gradle-aware Make");
Dialog gradleMakeDialog = robot().finder().find(DialogMatcher.withTitle("Select Gradle Task").andShowing());
robot().click(robot().finder().find(gradleMakeDialog, JButtonMatcher.withText("OK")));
}
private void click(final JBList popupList, String text) {
JListFixture popupFixture = new JListFixture(robot(), popupList);
popupFixture.replaceCellReader(new MakeStepsCellReader());
final int index = popupFixture.item(text).index();
// For some reason calling popupFixture.click(...) doesn't work, but this does:
GuiActionRunner.execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
popupList.setSelectedIndex(index);
}
});
robot().pressAndReleaseKey(KeyEvent.VK_ENTER);
}
/** {@link JTreeCellReader} that works with this particular tree. */
private static class RunConfigurationsJTreeCellReader implements JTreeCellReader {
@Nullable
@Override
public String valueAt(@NotNull JTree tree, Object modelValue) {
Object userObject = method("getUserObject").withReturnType(Object.class).in(modelValue).invoke();
if (userObject == null) {
return null;
}
if (userObject instanceof ConfigurationType) {
return ((ConfigurationType)userObject).getDisplayName();
}
return userObject.toString();
}
}
private static class MakeStepsCellReader extends BasicJListCellReader {
@Nullable
@Override
public String valueAt(@NotNull JList list, int index) {
Object element = list.getModel().getElementAt(index);
if (element instanceof ActionItem) {
return ((ActionItem)element).getText();
}
return super.valueAt(list, index);
}
}
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Ref;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.fixture.JRadioButtonFixture;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickOkButton;
import static com.intellij.tests.gui.framework.GuiTests.waitUntilFound;
public class SelectRefactoringDialogFixture extends IdeaDialogFixture<DialogWrapper> {
@NotNull
public static SelectRefactoringDialogFixture findByTitle(@NotNull Robot robot) {
final Ref<DialogWrapper> wrapperRef = new Ref<DialogWrapper>();
JDialog dialog = waitUntilFound(robot, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
if (!"Select Refactoring".equals(dialog.getTitle()) || !dialog.isShowing()) {
return false;
}
DialogWrapper wrapper = getDialogWrapperFrom(dialog, DialogWrapper.class);
if (wrapper != null) {
wrapperRef.set(wrapper);
return true;
}
return false;
}
});
return new SelectRefactoringDialogFixture(robot, dialog, wrapperRef.get());
}
public void selectRenameModule() {
JRadioButton renameModuleCheckbox = robot().finder().find(target(), new GenericTypeMatcher<JRadioButton>(JRadioButton.class) {
@Override
protected boolean isMatching(@NotNull JRadioButton checkBox) {
return "Rename module".equals(checkBox.getText());
}
});
JRadioButtonFixture renameModuleRadioButton = new JRadioButtonFixture(robot(), renameModuleCheckbox);
renameModuleRadioButton.select();
}
public void clickOk() {
findAndClickOkButton(this);
}
private SelectRefactoringDialogFixture(@NotNull Robot robot, @NotNull JDialog target, @NotNull DialogWrapper dialogWrapper) {
super(robot, target, dialogWrapper);
}
}
@@ -1,144 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.projectWizard.ProjectJdkStep;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import com.intellij.openapi.fileChooser.PathChooserDialog;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.tests.gui.fixtures.newProjectWizard.NewProjectWizardFixture;
import com.intellij.tests.gui.framework.GuiTests;
import com.intellij.ui.treeStructure.Tree;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.fixture.ContainerFixture;
import org.fest.swing.timing.Condition;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.timing.Pause.pause;
public class SelectSdkDialogFixture implements ContainerFixture<JDialog>{
private JDialog myDialog;
private Robot myRobot;
public SelectSdkDialogFixture(@NotNull Robot robot, JDialog selectSdkDialog) {
myRobot = robot;
myDialog = selectSdkDialog;
}
@NotNull
public static SelectSdkDialogFixture find(@NotNull Robot robot, String sdkType) {
JDialog dialog = robot.finder().find(new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
return ProjectBundle.message("sdk.configure.home.title", sdkType).equals(dialog.getTitle()) && dialog.isShowing();
}
});
return new SelectSdkDialogFixture(robot, dialog);
}
public SelectSdkDialogFixture selectPathToSdk(@NotNull File pathToSdk) {
final JTextField textField = myRobot.finder().findByType(JTextField.class);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
textField.setText(pathToSdk.getPath());
}
});
final Tree tree = myRobot.finder().findByType(myDialog, Tree.class);
final AbstractTreeBuilder builder = AbstractTreeBuilder.getBuilderFor(tree);
pause(new Condition("Wait until path is updated") {
@Override
public boolean test() {
//noinspection ConstantConditions
return execute(new GuiQuery<Boolean>() {
@Override
protected Boolean executeInEDT() throws Throwable {
return (textField.getText().equals(pathToSdk.getPath()) && !builder.getUi().getUpdater().hasNodesToUpdate()) ;
}
});
}
}, SHORT_TIMEOUT);
return this;
}
public void clickOk(){
pause(new Condition("Waiting when ok button at SDK select dialog will be ready for a click") {
@Override
public boolean test() {
JButton button = GuiTests.findButton(SelectSdkDialogFixture.this, "OK", myRobot);
return button.isEnabled();
}
}, GuiTests.SHORT_TIMEOUT);
GuiTests.findAndClickOkButton(this);
}
@Override
public JDialog target() {
return myDialog;
}
@Override
public Robot robot() {
return myRobot;
}
}
//extends IdeaDialogFixture<SelectSdkDialog> {
//@NotNull
//public static SelectSdkDialogFixture find(@NotNull Robot robot) {
// return new SelectSdkDialogFixture(robot, find(robot, SelectSdkDialog.class));
//}
//
//private SelectSdkDialogFixture(@NotNull Robot robot, @NotNull DialogAndWrapper<SelectSdkDialog> dialogAndWrapper) {
// super(robot, dialogAndWrapper);
//}
//
//@NotNull
//public SelectSdkDialogFixture setJdkPath(@NotNull final File path) {
// final JLabel label = robot().finder().find(target(), JLabelMatcher.withText("Select Java JDK:").andShowing());
// execute(new GuiTask() {
// @Override
// protected void executeInEDT() throws Throwable {
// Component textField = label.getLabelFor();
// assertThat(textField).isInstanceOf(JTextField.class);
// ((JTextField)textField).setText(path.getPath());
// }
// });
// return this;
//}
//
//@NotNull
//public SelectSdkDialogFixture clickOk() {
// findAndClickOkButton(this);
// return this;
//}
@@ -1,264 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.StatusBarWidget;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.impl.StripeButton;
import com.intellij.ui.content.Content;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.timing.Condition;
import org.fest.swing.timing.Timeout;
import org.fest.swing.util.TextMatcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nonnull;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import static com.intellij.tests.gui.framework.GuiTests.SHORT_TIMEOUT;
import static com.intellij.tests.gui.framework.GuiTests.THIRTY_SEC_TIMEOUT;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.timing.Pause.pause;
public abstract class ToolWindowFixture {
@NotNull protected final String myToolWindowId;
@NotNull protected final Project myProject;
@NotNull protected final Robot myRobot;
@NotNull protected final ToolWindow myToolWindow;
protected ToolWindowFixture(@NotNull final String toolWindowId, @NotNull final Project project, @NotNull Robot robot) {
myToolWindowId = toolWindowId;
myProject = project;
final Ref<ToolWindow> toolWindowRef = new Ref<ToolWindow>();
pause(new Condition("Find tool window with ID '" + toolWindowId + "'") {
@Override
public boolean test() {
ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(toolWindowId);
toolWindowRef.set(toolWindow);
return toolWindow != null;
}
}, SHORT_TIMEOUT);
myRobot = robot;
myToolWindow = toolWindowRef.get();
}
@Nullable
protected Content getContent(@NotNull final String displayName) {
activateAndWaitUntilIsVisible();
final Ref<Content> contentRef = new Ref<Content>();
pause(new Condition("finding content '" + displayName + "'") {
@Override
public boolean test() {
Content[] contents = getContents();
for (Content content : contents) {
if (displayName.equals(content.getDisplayName())) {
contentRef.set(content);
return true;
}
}
return false;
}
}, SHORT_TIMEOUT);
return contentRef.get();
}
@Nullable
protected Content getContent(@NotNull final String displayName, @NotNull Timeout timeout) {
long now = System.currentTimeMillis();
long budget = timeout.duration();
activateAndWaitUntilIsVisible(Timeout.timeout(budget));
long revisedNow = System.currentTimeMillis();
budget -= (revisedNow - now);
final Ref<Content> contentRef = new Ref<Content>();
pause(new Condition("finding content with display name " + displayName) {
@Override
public boolean test() {
Content[] contents = getContents();
for (Content content : contents) {
if (displayName.equals(content.getDisplayName())) {
contentRef.set(content);
return true;
}
}
return false;
}
}, Timeout.timeout(budget));
return contentRef.get();
}
@Nullable
protected Content getContent(@NotNull final TextMatcher displayNameMatcher) {
return getContent(displayNameMatcher, SHORT_TIMEOUT);
}
@Nullable
protected Content getContent(@NotNull final TextMatcher displayNameMatcher, @NotNull Timeout timeout) {
long now = System.currentTimeMillis();
long budget = timeout.duration();
activateAndWaitUntilIsVisible(Timeout.timeout(budget));
long revisedNow = System.currentTimeMillis();
budget -= (revisedNow - now);
now = revisedNow;
final Ref<Content> contentRef = new Ref<Content>();
pause(new Condition("finding content matching " + displayNameMatcher.formattedValues()) {
@Override
public boolean test() {
Content[] contents = getContents();
for (Content content : contents) {
String displayName = content.getDisplayName();
if (displayNameMatcher.isMatching(displayName)) {
contentRef.set(content);
return true;
}
}
return false;
}
}, Timeout.timeout(budget));
return contentRef.get();
}
private void activateAndWaitUntilIsVisible() {
activateAndWaitUntilIsVisible(SHORT_TIMEOUT);
}
private void activateAndWaitUntilIsVisible(@NotNull Timeout timeout) {
long now = System.currentTimeMillis();
long budget = timeout.duration();
activate();
budget -= System.currentTimeMillis() - now;
waitUntilIsVisible(Timeout.timeout(budget));
}
@NotNull
private Content[] getContents() {
return myToolWindow.getContentManager().getContents();
}
protected boolean isActive() {
//noinspection ConstantConditions
return execute(new GuiQuery<Boolean>() {
@Override
protected Boolean executeInEDT() throws Throwable {
return myToolWindow.isActive();
}
});
}
public void activate() {
if (isActive()) {
return;
}
final Callback callback = new Callback();
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
myToolWindow.activate(callback);
}
});
pause(new Condition("Wait for ToolWindow '" + myToolWindowId + "' to be activated") {
@Override
public boolean test() {
return callback.finished;
}
}, SHORT_TIMEOUT);
}
protected void waitUntilIsVisible() {
waitUntilIsVisible(THIRTY_SEC_TIMEOUT);
}
protected void waitUntilIsVisible(@NotNull Timeout timeout) {
pause(new Condition("Wait for ToolWindow '" + myToolWindowId + "' to be visible") {
@Override
public boolean test() {
if (!isActive()) {
activate();
}
return isVisible();
}
}, timeout);
}
private boolean isVisible() {
//noinspection ConstantConditions
return execute(new GuiQuery<Boolean>() {
@Override
protected Boolean executeInEDT() throws Throwable {
if (!myToolWindow.isVisible()) {
return false;
}
JComponent component = myToolWindow.getComponent();
return component.isVisible() && component.isShowing();
}
});
}
public static void clickToolwindowButton(String toolWindowStripeButtonName, Robot robot){
final StripeButton stripeButton = robot.finder().find(new GenericTypeMatcher<StripeButton>(StripeButton.class) {
@Override
protected boolean isMatching(@Nonnull StripeButton button) {
return (button.getText().equals(toolWindowStripeButtonName));
}
});
robot.click(stripeButton);
}
public static void showToolwindowStripes(Robot robot){
if (UISettings.getInstance().HIDE_TOOL_STRIPES) {
final JLabel toolwindowsWidget = robot.finder().find(new GenericTypeMatcher<JLabel>(JLabel.class) {
@Override
protected boolean isMatching(@Nonnull JLabel label) {
if (label instanceof StatusBarWidget) {
StatusBarWidget statusBarWidget = (StatusBarWidget)label;
if (statusBarWidget.ID().equals("ToolWindows Widget")) {
return true;
}
}
return false;
}
});
if (toolwindowsWidget == null) return;
else {
robot.click(toolwindowsWidget);
}
}
}
private static class Callback implements Runnable {
volatile boolean finished;
@Override
public void run() {
finished = true;
}
}
}
@@ -1,105 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures.newProjectWizard;
import com.intellij.tests.gui.fixtures.ComponentFixture;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.fixture.ContainerFixture;
import org.fest.swing.fixture.JButtonFixture;
import org.fest.swing.fixture.JLabelFixture;
import org.fest.swing.fixture.JTextComponentFixture;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import static com.intellij.tests.gui.framework.GuiTests.*;
/**
* Base class for fixtures which control wizards that extend {@link DynamicWizard}
*/
public abstract class AbstractWizardFixture<S> extends ComponentFixture<S, JDialog> implements ContainerFixture<JDialog> {
public AbstractWizardFixture(@NotNull Class<S> selfType, @NotNull Robot robot, @NotNull JDialog target) {
super(selfType, robot, target);
}
@NotNull
protected JRootPane findStepWithTitle(@NotNull final String title) {
JRootPane rootPane = target().getRootPane();
waitUntilFound(robot(), rootPane, new GenericTypeMatcher<JLabel>(JLabel.class) {
@Override
protected boolean isMatching(@NotNull JLabel label) {
if (!label.isShowing()) {
return false;
}
return title.equals(label.getText());
}
});
return rootPane;
}
@NotNull
public S clickNext() {
findAndClickButton(this, "Next");
return myself();
}
@NotNull
public S clickFinish() {
findAndClickButton(this, "Finish");
return myself();
}
@NotNull
public S clickCancel() {
findAndClickCancelButton(this);
return myself();
}
@NotNull
public JTextComponentFixture findTextField(@NotNull final String labelText) {
return new JTextComponentFixture(robot(), robot().finder().findByLabel(labelText, JTextComponent.class));
}
@NotNull
public JButtonFixture findWizardButton(@NotNull final String text) {
JButton button = robot().finder().find(target(), new GenericTypeMatcher<JButton>(JButton.class) {
@Override
protected boolean isMatching(@NotNull JButton button) {
String buttonText = button.getText();
if (buttonText != null) {
return buttonText.trim().equals(text) && button.isShowing();
}
return false;
}
});
return new JButtonFixture(robot(), button);
}
@NotNull
public JLabelFixture findLabel(@NotNull final String text) {
JLabel label = waitUntilFound(robot(), target(), new GenericTypeMatcher<JLabel>(JLabel.class) {
@Override
protected boolean isMatching(@NotNull JLabel label) {
return text.equals(label.getText().replaceAll("(?i)<.?html>", ""));
}
});
return new JLabelFixture(robot(), label);
}
}
@@ -1,176 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures.newProjectWizard;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ui.configuration.JdkComboBox;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.tests.gui.fixtures.FrameworksTreeFixture;
import com.intellij.tests.gui.fixtures.SelectSdkDialogFixture;
import com.intellij.tests.gui.framework.GuiTests;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.components.JBList;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.exception.ComponentLookupException;
import org.fest.swing.fixture.DialogFixture;
import org.fest.swing.fixture.JListFixture;
import org.fest.swing.fixture.JTextComponentFixture;
import org.fest.swing.fixture.JTreeFixture;
import org.fest.swing.timing.Condition;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import static com.intellij.tests.gui.framework.GuiTests.LONG_TIMEOUT;
import static com.intellij.tests.gui.framework.GuiTests.getSystemJdk;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.finder.WindowFinder.findDialog;
import static org.fest.swing.timing.Pause.pause;
public class NewProjectWizardFixture extends AbstractWizardFixture<NewProjectWizardFixture> {
@NotNull
public static NewProjectWizardFixture find(@NotNull Robot robot) {
final DialogFixture newProjectDialog = findDialog(new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
return IdeBundle.message("title.new.project").equals(dialog.getTitle()) && dialog.isShowing();
}
}).withTimeout(LONG_TIMEOUT.duration()).using(robot);
return new NewProjectWizardFixture(robot, (JDialog)newProjectDialog.target());
}
private NewProjectWizardFixture(@NotNull Robot robot, @NotNull JDialog target) {
super(NewProjectWizardFixture.class, robot, target);
}
@NotNull
public boolean isJdkEmpty() {
final JdkComboBox jdkComboBox = robot().finder().findByType(JdkComboBox.class);
return (jdkComboBox.getSelectedJdk() == null);
}
@NotNull
public NewProjectWizardFixture selectProjectType(String projectTypeName) {
JListFixture projectTypeList = new JListFixture(robot(), robot().finder().findByType(this.target(), JBList.class, true));
projectTypeList.clickItem(projectTypeName);
return this;
}
@NotNull
public NewProjectWizardFixture selectFramework(String frameworkName) {
final FrameworksTreeFixture frameworksTreeFixture = FrameworksTreeFixture.find(robot());
frameworksTreeFixture.selectFramework(frameworkName);
return this;
}
public NewProjectWizardFixture selectSdkPath(@NotNull File sdkPath, String sdkType) {
final SelectSdkDialogFixture sdkDialogFixture = SelectSdkDialogFixture.find(robot(), sdkType);
sdkDialogFixture.selectPathToSdk(sdkPath).clickOk();
pause(new Condition("Waiting for the returning of focus to dialog: " + target().getTitle()) {
@Override
public boolean test() {
return target().isFocused();
}
}, GuiTests.SHORT_TIMEOUT);
return this;
}
@NotNull
public NewProjectWizardFixture setProjectName(@NotNull String projectName) {
String labelText = GuiTests.adduction(IdeBundle.message("label.project.name"));
pause(new Condition("Waiting for the sliding to project name settings") {
@Override
public boolean test() {
final Component label;
try {
label = robot().finder().findByLabel(labelText);
}
catch (ComponentLookupException componentLookupException) {
return false;
}
return true;
}
}, GuiTests.SHORT_TIMEOUT);
final JTextComponentFixture textField = findTextField(labelText);
robot().click(textField.target());
textField.setText(projectName);
return this;
}
@NotNull
public File getLocationInFileSystem() {
String labelText = GuiTests.adduction(IdeBundle.message("label.project.files.location"));
//noinspection ConstantConditions
final JTextComponentFixture locationTextField = findTextField(labelText);
return execute(new GuiQuery<File>() {
@Override
protected File executeInEDT() throws Throwable {
String location = locationTextField.text();
assertThat(location).isNotNull().isNotEmpty();
return new File(location);
}
});
}
public NewProjectWizardFixture setupJdk() {
if (this.isJdkEmpty()) {
JButton newButton = GuiTests.findButton(this,
GuiTests.adduction(ApplicationBundle.message("button.new")),
robot());
robot().click(newButton);
File javaSdkPath = new File(getSystemJdk());
String sdkType = GuiTests.adduction(ProjectBundle.message("sdk.java.name"));
GuiTests.clickPopupMenuItem(sdkType, newButton, robot());
this.selectSdkPath(javaSdkPath, sdkType);
}
return this;
}
@NotNull
public ConfigureAndroidProjectStepFixture getConfigureAndroidProjectStep() {
JRootPane rootPane = findStepWithTitle("Configure your new project");
return new ConfigureAndroidProjectStepFixture(robot(), rootPane);
}
@NotNull
public ConfigureFormFactorStepFixture getConfigureFormFactorStep() {
JRootPane rootPane = findStepWithTitle("Select the form factors your app will run on");
return new ConfigureFormFactorStepFixture(robot(), rootPane);
}
@NotNull
public ChooseOptionsForNewFileStepFixture getChooseOptionsForNewFileStep() {
JRootPane rootPane = findStepWithTitle("Customize the Activity");
return new ChooseOptionsForNewFileStepFixture(robot(), rootPane);
}
}
@@ -1,427 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
/**
* Created by karashevich on 30/05/16.
*/
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.WindowManagerImpl;
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
import com.intellij.tests.gui.fixtures.IdeFrameFixture;
import com.intellij.tests.gui.fixtures.WelcomeFrameFixture;
import com.intellij.tests.gui.fixtures.newProjectWizard.NewProjectWizardFixture;
import com.intellij.util.net.HttpConfigurable;
import org.fest.swing.core.AdvancedRobot;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.timing.Condition;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import static com.intellij.ide.impl.ProjectUtil.closeAndDispose;
import static com.intellij.openapi.util.io.FileUtil.copyDir;
import static com.intellij.openapi.util.io.FileUtil.toSystemDependentName;
import static com.intellij.openapi.util.io.FileUtilRt.delete;
import static com.intellij.openapi.vfs.VfsUtil.findFileByIoFile;
import static com.intellij.tests.gui.framework.GuiTestRunner.canRunGuiTests;
import static com.intellij.tests.gui.framework.GuiTests.*;
import static junit.framework.Assert.assertNotNull;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.timing.Pause.pause;
import static org.fest.util.Strings.quote;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@RunWith(GuiTestRunner.class)
public abstract class GuiTestCase {
protected Robot myRobot;
@SuppressWarnings("UnusedDeclaration") // This field is set via reflection.
private String myTestName;
protected IdeFrameFixture myProjectFrame;
/**
* @return the name of the test method being executed.
*/
protected String getTestName() {
return myTestName;
}
public void setRobot(Robot robot){
myRobot = robot;
}
public GuiTestCase(){
}
public GuiTestCase(Robot robot) {
myRobot = robot;
}
@Before
public void setUp() throws Exception {
if (!canRunGuiTests()) {
return;
}
Application application = ApplicationManager.getApplication();
assertNotNull(application); // verify that we are using the IDE's ClassLoader.
setUpDefaultProjectCreationLocationPath();
//myRobot = BasicRobot.robotWithCurrentAwtHierarchy();
myRobot = new AdvancedRobot();
//myRobot.settings().delayBetweenEvents(30);
setIdeSettings();
setUpSdks();
// There is a race condition between reloading the configuration file after file deletion detected and the serialization of IDEA model
// we just customized so that modules can't be loaded correctly.
// This is a hack to prevent StoreAwareProjectManager from doing any reloading during test.
ProjectManagerEx.getInstanceEx().blockReloadingProjectOnExternalChanges();
refreshFiles();
}
private static void setIdeSettings() {
// Clear HTTP proxy settings, in case a test changed them.
HttpConfigurable ideSettings = HttpConfigurable.getInstance();
ideSettings.USE_HTTP_PROXY = false;
ideSettings.PROXY_HOST = "";
ideSettings.PROXY_PORT = 80;
}
@After
public void tearDown() throws InvocationTargetException, InterruptedException {
if (myProjectFrame != null) {
DumbService.getInstance(myProjectFrame.getProject()).repeatUntilPassesInSmartMode(new Runnable() {
@Override
public void run() {
myProjectFrame.waitForBackgroundTasksToFinish();
}
});
}
if (myRobot != null) {
myRobot.cleanUpWithoutDisposingWindows();
// We close all modal dialogs left over, because they block the AWT thread and could trigger a deadlock in the next test.
for (Window window : Window.getWindows()) {
if (window.isShowing() && window instanceof Dialog) {
if (((Dialog)window).getModalityType() == Dialog.ModalityType.APPLICATION_MODAL) {
fail("Modal dialog still active: " + window);
myRobot.close(window);
}
}
}
}
ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges();
}
@NotNull
protected WelcomeFrameFixture findWelcomeFrame() {
return WelcomeFrameFixture.find(myRobot);
}
@NotNull
protected NewProjectWizardFixture findNewProjectWizard() {
return NewProjectWizardFixture.find(myRobot);
}
@NotNull
protected IdeFrameFixture findIdeFrame(@NotNull String projectName, @NotNull File projectPath) {
return IdeFrameFixture.find(myRobot, projectPath, projectName);
}
@SuppressWarnings("UnusedDeclaration")
// Called by GuiTestRunner via reflection.
protected void closeAllProjects() {
pause(new Condition("Close all projects") {
@Override
public boolean test() {
final Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
for (Project project : openProjects) {
assertTrue("Failed to close project " + quote(project.getName()), closeAndDispose(project));
}
}
});
return ProjectManager.getInstance().getOpenProjects().length == 0;
}
}, SHORT_TIMEOUT);
//noinspection ConstantConditions
boolean welcomeFrameShown = execute(new GuiQuery<Boolean>() {
@Override
protected Boolean executeInEDT() throws Throwable {
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
if (openProjects.length == 0) {
WelcomeFrame.showNow();
WindowManagerImpl windowManager = (WindowManagerImpl)WindowManager.getInstance();
windowManager.disposeRootFrame();
return true;
}
return false;
}
});
if (welcomeFrameShown) {
pause(new Condition("'Welcome' frame to show up") {
@Override
public boolean test() {
for (Frame frame : Frame.getFrames()) {
if (frame == WelcomeFrame.getInstance() && frame.isShowing()) {
return true;
}
}
return false;
}
}, SHORT_TIMEOUT);
}
}
@NotNull
protected IdeFrameFixture importSimpleApplication() throws IOException {
return importProjectAndWaitForProjectSyncToFinish("SimpleApplication");
}
@NotNull
protected IdeFrameFixture importMultiModule() throws IOException {
return importProjectAndWaitForProjectSyncToFinish("MultiModule");
}
@NotNull
protected IdeFrameFixture importProjectAndWaitForProjectSyncToFinish(@NotNull String projectDirName) throws IOException {
return importProjectAndWaitForProjectSyncToFinish(projectDirName, null);
}
@NotNull
protected IdeFrameFixture importProjectAndWaitForProjectSyncToFinish(@NotNull String projectDirName, @Nullable String gradleVersion)
throws IOException {
File projectPath = setUpProject(projectDirName, false);
VirtualFile toSelect = findFileByIoFile(projectPath, false);
assertNotNull(toSelect);
doImportProject(toSelect);
IdeFrameFixture projectFrame = findIdeFrame(projectPath);
//TODO: add wait to open project
return projectFrame;
}
@NotNull
protected File importProject(@NotNull String projectDirName) throws IOException {
File projectPath = setUpProject(projectDirName, false);
VirtualFile toSelect = findFileByIoFile(projectPath, false);
assertNotNull(toSelect);
doImportProject(toSelect);
return projectPath;
}
private static void doImportProject(@NotNull final VirtualFile projectDir) {
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
ProjectUtil.openOrImport(projectDir.getPath(), null, false);
}
});
}
/**
* Sets up a project before using it in a UI test:
* <ul>
* <li>Makes a copy of the project in testData/guiTests/newProjects (deletes any existing copy of the project first.) This copy is
* the one the test will use.</li>
* <li>Creates a Gradle wrapper for the test project.</li>
* <li>Updates the version of the Android Gradle plug-in used by the project, if applicable</li>
* <li>Creates a local.properties file pointing to the Android SDK path specified by the system property (or environment variable)
* 'ADT_TEST_SDK_PATH'</li>
* <li>Copies over missing files to the .idea directory (if the project will be opened, instead of imported.)</li>
* <li>Deletes .idea directory, .iml files and build directories, if the project will be imported.</li>
* <p/>
* </ul>
*
* @param projectDirName the name of the project's root directory. Tests are located in testData/guiTests.
* @param forOpen indicates whether the project will be opened by the IDE, or imported.
* @param updateAndroidPluginVersion indicates if the latest supported version of the Android Gradle plug-in should be set in the
* project.
* @param gradleVersion the Gradle version to use in the wrapper. If {@code null} is passed, this method will use the latest supported
* version of Gradle.
* @return the path of project's root directory (the copy of the project, not the original one.)
* @throws IOException if an unexpected I/O error occurs.
*/
@NotNull
private File setUpProject(@NotNull String projectDirName,
boolean forOpen) throws IOException {
File projectPath = copyProjectBeforeOpening(projectDirName);
assertNotNull(projectPath);
//*********************************************************
//******* In case we want to pick out commom files
//*********************************************************
//if (forOpen) {
// File toDotIdea = new File(projectPath, Project.DIRECTORY_STORE_FOLDER);
// ensureExists(toDotIdea);
//
// File fromDotIdea = new File(getTestProjectsRootDirPath(), join("commonFiles", Project.DIRECTORY_STORE_FOLDER));
// assertThat(fromDotIdea).isDirectory();
//
//
// for (File from : notNullize(fromDotIdea.listFiles())) {
// if (from.isDirectory()) {
// File destination = new File(toDotIdea, from.getName());
// if (!destination.isDirectory()) {
// copyDirContent(from, destination);
// }
// continue;
// }
// File to = new File(toDotIdea, from.getName());
// if (!to.isFile()) {
// copy(from, to);
// }
// }
//}
//else {
// cleanUpProjectForImport(projectPath);
//}
return projectPath;
}
private void updateLocalProperties(File path) {
}
@NotNull
protected File copyProjectBeforeOpening(@NotNull String projectDirName) throws IOException {
File masterProjectPath = getMasterProjectDirPath(projectDirName);
File projectPath = getTestProjectDirPath(projectDirName);
if (projectPath.isDirectory()) {
delete(projectPath);
System.out.println(String.format("Deleted project path '%1$s'", projectPath.getPath()));
}
copyDir(masterProjectPath, projectPath);
System.out.println(String.format("Copied project '%1$s' to path '%2$s'", projectDirName, projectPath.getPath()));
return projectPath;
}
@NotNull
protected File getMasterProjectDirPath(@NotNull String projectDirName) {
return new File(getTestProjectsRootDirPath(), projectDirName);
}
@NotNull
protected File getTestProjectDirPath(@NotNull String projectDirName) {
return new File(getProjectCreationDirPath(), projectDirName);
}
protected void cleanUpProjectForImport(@NotNull File projectPath) {
File dotIdeaFolderPath = new File(projectPath, Project.DIRECTORY_STORE_FOLDER);
if (dotIdeaFolderPath.isDirectory()) {
File modulesXmlFilePath = new File(dotIdeaFolderPath, "modules.xml");
if (modulesXmlFilePath.isFile()) {
SAXBuilder saxBuilder = new SAXBuilder();
try {
Document document = saxBuilder.build(modulesXmlFilePath);
XPath xpath = XPath.newInstance("//*[@fileurl]");
//noinspection unchecked
java.util.List<Element> modules = xpath.selectNodes(document);
int urlPrefixSize = "file://$PROJECT_DIR$/".length();
for (Element module : modules) {
String fileUrl = module.getAttributeValue("fileurl");
if (!StringUtil.isEmpty(fileUrl)) {
String relativePath = toSystemDependentName(fileUrl.substring(urlPrefixSize));
File imlFilePath = new File(projectPath, relativePath);
if (imlFilePath.isFile()) {
delete(imlFilePath);
}
// It is likely that each module has a "build" folder. Delete it as well.
File buildFilePath = new File(imlFilePath.getParentFile(), "build");
if (buildFilePath.isDirectory()) {
delete(buildFilePath);
}
}
}
}
catch (Throwable ignored) {
// if something goes wrong, just ignore. Most likely it won't affect project import in any way.
}
}
delete(dotIdeaFolderPath);
}
}
@NotNull
protected IdeFrameFixture findIdeFrame(@NotNull File projectPath) {
return IdeFrameFixture.find(myRobot, projectPath, null);
}
protected IdeFrameFixture findIdeFrame(){
return IdeFrameFixture.find(myRobot, null, null);
}
protected void refreshFiles() {
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
LocalFileSystem.getInstance().refresh(false /* synchronous */);
}
});
}
});
}
}
@@ -1,180 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
import com.google.common.base.Strings;
import org.fest.swing.image.ScreenshotTaker;
import org.jetbrains.annotations.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.ReflectiveCallable;
import org.junit.internal.runners.statements.Fail;
import org.junit.internal.runners.statements.RunAfters;
import org.junit.internal.runners.statements.RunBefores;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;
import java.awt.*;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import static org.junit.Assert.assertNotNull;
public class GuiTestRunner extends BlockJUnit4ClassRunner {
private TestClass myTestClass;
private final List<GarbageCollectorMXBean> myGarbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();
private final MemoryMXBean myMemoryMXBean = ManagementFactory.getMemoryMXBean();
@Nullable private final ScreenshotTaker myScreenshotTaker;
public GuiTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
myScreenshotTaker = canRunGuiTests() ? new ScreenshotTaker() : null;
// UI_TEST_MODE is set whenever we run UI tests on top of a Studio build. In that case, we
// assume the classpath has been properly configured. Otherwise, if we're running from the
// IDE or an Ant build, we need to check we have access to the classpath of community-main.
if (Strings.isNullOrEmpty(System.getenv("UI_TEST_MODE"))) {
//try {
// A random class which is reachable from module community-main's classpath but not
// module android's classpath.
//Class.forName("git4idea.repo.GitConfig", false, testClass.getClassLoader());
//don't check for git module here
}
//catch (ClassNotFoundException e) {
// throw new InitializationError("Invalid test run configuration. Edit your test configuration and make sure that " +
// "\"Use classpath of module\" is set to \"community-main\", *NOT* \"android\"!");
//}
//}
}
@Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
if (!canRunGuiTests()) {
notifier.fireTestAssumptionFailed(new Failure(describeChild(method), new AssumptionViolatedException("Headless environment")));
System.out.println(String.format("Skipping test '%1$s'. UI tests cannot run in a headless environment.", method.getName()));
} else if (MethodInvoker.doesIdeHaveFatalErrors()) {
notifier.fireTestIgnored(describeChild(method)); // TODO: can we restart the IDE at this point, instead of giving up?
System.out.println(String.format("Skipping test '%1$s': a fatal error has occurred in the IDE", method.getName()));
notifier.pleaseStop();
} else {
printPerfStats();
printTimestamp();
super.runChild(method, notifier);
printTimestamp();
printPerfStats();
}
}
private void printTimestamp() {
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
System.out.println(dateFormat.format(new Date()));
}
private void printPerfStats() {
long gcCount = 0, gcTime = 0;
for (GarbageCollectorMXBean garbageCollectorMXBean : myGarbageCollectorMXBeans) {
gcCount += garbageCollectorMXBean.getCollectionCount();
gcTime += garbageCollectorMXBean.getCollectionTime();
}
System.out.printf("%d garbage collections; cumulative %d ms%n", gcCount, gcTime);
myMemoryMXBean.gc();
System.out.printf("heap: %s%n", myMemoryMXBean.getHeapMemoryUsage());
System.out.printf("non-heap: %s%n", myMemoryMXBean.getNonHeapMemoryUsage());
}
@Override
protected Statement methodBlock(FrameworkMethod method) {
FrameworkMethod newMethod;
try {
loadClassesWithIdeClassLoader();
Method methodFromClassLoader = myTestClass.getJavaClass().getMethod(method.getName());
newMethod = new FrameworkMethod(methodFromClassLoader);
}
catch (Exception e) {
return new Fail(e);
}
Object test;
try {
test = new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return createTest();
}
}.run();
}
catch (Throwable e) {
return new Fail(e);
}
Statement statement = methodInvoker(newMethod, test);
List<FrameworkMethod> beforeMethods = myTestClass.getAnnotatedMethods(Before.class);
if (!beforeMethods.isEmpty()) {
statement = new RunBefores(statement, beforeMethods, test);
}
List<FrameworkMethod> afterMethods = myTestClass.getAnnotatedMethods(After.class);
if (!afterMethods.isEmpty()) {
statement = new RunAfters(statement, afterMethods, test);
}
return statement;
}
public static boolean canRunGuiTests() {
return !GraphicsEnvironment.isHeadless();
}
private void loadClassesWithIdeClassLoader() throws Exception {
ClassLoader ideClassLoader = IdeTestApplication.getInstance().getIdeClassLoader();
Thread.currentThread().setContextClassLoader(ideClassLoader);
Class<?> testClass = getTestClass().getJavaClass();
myTestClass = new TestClass(ideClassLoader.loadClass(testClass.getName()));
}
@Override
protected Object createTest() throws Exception {
return myTestClass != null ? myTestClass.getJavaClass().newInstance() : super.createTest();
}
@Override
protected Statement methodInvoker(final FrameworkMethod method, Object test) {
try {
assertNotNull(myScreenshotTaker);
return new MethodInvoker(method, test, myScreenshotTaker);
}
catch (Throwable e) {
return new Fail(e);
}
}
}
@@ -1,846 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
import com.google.common.collect.Lists;
import com.intellij.diagnostic.AbstractMessage;
import com.intellij.diagnostic.MessagePool;
import com.intellij.ide.GeneralSettings;
import com.intellij.ide.PrivacyPolicy;
import com.intellij.ide.RecentProjectsManager;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerAdapter;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SwitchBootJdkAction;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
import com.intellij.tests.gui.fixtures.IdeFrameFixture;
import com.intellij.ui.components.JBList;
import com.intellij.ui.popup.PopupFactoryImpl;
import com.intellij.ui.popup.list.ListPopupModel;
import com.intellij.util.JdkBundle;
import com.intellij.util.ui.EdtInvocationManager;
import org.fest.swing.core.BasicRobot;
import org.fest.swing.core.ComponentFinder;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.exception.WaitTimedOutError;
import org.fest.swing.fixture.ContainerFixture;
import org.fest.swing.fixture.DialogFixture;
import org.fest.swing.fixture.JListFixture;
import org.fest.swing.fixture.JTextComponentFixture;
import org.fest.swing.timing.Condition;
import org.fest.swing.timing.Pause;
import org.fest.swing.timing.Timeout;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nonnull;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.base.Joiner.on;
import static com.google.common.io.Files.createTempDir;
import static com.intellij.openapi.projectRoots.JdkUtil.checkForJdk;
import static com.intellij.openapi.util.io.FileUtil.pathsEqual;
import static com.intellij.openapi.util.io.FileUtil.toCanonicalPath;
import static com.intellij.openapi.util.io.FileUtilRt.toSystemDependentName;
import static com.intellij.openapi.util.text.StringUtil.isNotEmpty;
import static com.intellij.util.containers.ContainerUtil.getFirstItem;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.finder.WindowFinder.findDialog;
import static org.fest.swing.finder.WindowFinder.findFrame;
import static org.fest.swing.timing.Pause.pause;
import static org.fest.swing.timing.Timeout.timeout;
import static org.fest.util.Strings.isNullOrEmpty;
import static org.fest.util.Strings.quote;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
public final class GuiTests {
private static final Logger LOG = Logger.getInstance("#com.intellij.tests.gui.framework.GuiTests");
public static final Timeout THIRTY_SEC_TIMEOUT = timeout(30, SECONDS);
public static final Timeout MINUTE_TIMEOUT = timeout(1, MINUTES);
public static final Timeout SHORT_TIMEOUT = timeout(2, MINUTES);
public static final Timeout LONG_TIMEOUT = timeout(5, MINUTES);
public static final String GUI_TESTS_RUNNING_IN_SUITE_PROPERTY = "gui.tests.running.in.suite";
/**
* Environment variable pointing to the JDK to be used for tests
*/
public static final String JDK_HOME_FOR_TESTS = "JDK_HOME_FOR_TESTS";
private static final EventQueue SYSTEM_EVENT_QUEUE = Toolkit.getDefaultToolkit().getSystemEventQueue();
private static final File TMP_PROJECT_ROOT = createTempProjectCreationDir();
// Called by MethodInvoker via reflection
@SuppressWarnings("unused")
public static void failIfIdeHasFatalErrors() {
final MessagePool messagePool = MessagePool.getInstance();
List<AbstractMessage> fatalErrors = messagePool.getFatalErrors(true, true);
int fatalErrorCount = fatalErrors.size();
for (int i = 0; i < fatalErrorCount; i++) {
System.err.println("** Fatal Error " + (i + 1) + " of " + fatalErrorCount);
AbstractMessage error = fatalErrors.get(i);
System.err.println("* Message: ");
System.err.println(error.getMessage());
String additionalInfo = error.getAdditionalInfo();
if (isNotEmpty(additionalInfo)) {
System.err.println("* Additional Info: ");
System.err.println(additionalInfo);
}
String throwableText = error.getThrowableText();
if (isNotEmpty(throwableText)) {
System.err.println("* Throwable: ");
System.err.println(throwableText);
}
System.err.println();
}
if (fatalErrorCount > 0) {
throw new AssertionError(fatalErrorCount + " fatal errors found. Stopping test execution.");
}
}
// Called by MethodInvoker via reflection
@SuppressWarnings("unused")
public static boolean doesIdeHaveFatalErrors() {
final MessagePool messagePool = MessagePool.getInstance();
List<AbstractMessage> fatalErrors = messagePool.getFatalErrors(true, true);
return !fatalErrors.isEmpty();
}
// Called by IdeTestApplication via reflection.
@SuppressWarnings("unused")
public static void setUpDefaultGeneralSettings() {
//setGuiTestingMode(true);
GeneralSettings.getInstance().setShowTipsOnStartup(false);
setUpDefaultProjectCreationLocationPath();
setUpSdks();
}
public static String getSystemJdk() {
String jdkHome = getSystemPropertyOrEnvironmentVariable(JDK_HOME_FOR_TESTS);
if (isNullOrEmpty(jdkHome) || !checkForJdk(jdkHome)) {
//than use bundled JDK
jdkHome = getBundledJdLocation();
}
if (isNullOrEmpty(jdkHome) || !checkForJdk(jdkHome)) {
fail("Please specify the path to a valid JDK using system property " + JDK_HOME_FOR_TESTS);
}
return jdkHome;
}
public static void setupGitPath(){
//GitVcsApplicationSettings settings = GitVcsApplicationSettings.getInstance();
//settings.setPathToGit(GitExecutor.PathHolder.GIT_EXECUTABLE);
}
public static void setUpSdks() {
String jdkHome = getSystemPropertyOrEnvironmentVariable(JDK_HOME_FOR_TESTS);
if (isNullOrEmpty(jdkHome) || !checkForJdk(jdkHome)) {
//than use bundled JDK
jdkHome = getBundledJdLocation();
}
final File jdkPath = new File(jdkHome);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
LOG.info(String.format("Setting JDK: '%1$s'", jdkPath.getPath()));
setJdkPath(jdkPath);
}
});
}
});
}
public static void setJdkPath(@NotNull File path) {
if (JavaSdk.checkForJdk(path)) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
Sdk chosenJdk = null;
for (Sdk jdk : ProjectJdkTable.getInstance().getSdksOfType(JavaSdk.getInstance())) {
if (pathsEqual(jdk.getHomePath(), path.getPath())) {
chosenJdk = jdk;
break;
}
}
if (chosenJdk == null) {
if (path.isDirectory()) {
JavaSdk javaSdk = JavaSdk.getInstance();
String jdk_name = "JDK";
final Sdk newJdk = javaSdk.createJdk(jdk_name, path.toString(), false);
final Sdk foundJdk = ProjectJdkTable.getInstance().findJdk(newJdk.getName(), newJdk.getSdkType().getName());
if (foundJdk == null) {
ApplicationManager.getApplication().runWriteAction(() -> {
ProjectJdkTable.getInstance().addJdk(newJdk);
});
}
ApplicationManager.getApplication().runWriteAction(() -> {
SdkModificator modificator = newJdk.getSdkModificator();
JavaSdkImpl.attachJdkAnnotations(modificator);
modificator.commitChanges();
});
}
else {
throw new IllegalStateException("The resolved path '" + path.getPath() + "' was not found");
}
}
}
}
@Nullable
public static File getGradleHomePath() {
return getFilePathProperty("supported.gradle.home.path", "the path of a local Gradle 2.2.1 distribution", true);
}
@Nullable
public static File getUnsupportedGradleHome() {
return getGradleHomeFromSystemProperty("unsupported.gradle.home.path", "2.1");
}
@Nullable
public static File getGradleHomeFromSystemProperty(@NotNull String propertyName, @NotNull String gradleVersion) {
String description = "the path of a Gradle " + gradleVersion + " distribution";
return getFilePathProperty(propertyName, description, true);
}
@Nullable
public static File getFilePathProperty(@NotNull String propertyName,
@NotNull String description,
boolean isDirectory) {
String pathValue = System.getProperty(propertyName);
if (!isNullOrEmpty(pathValue)) {
File path = new File(pathValue);
if (isDirectory && path.isDirectory() || !isDirectory && path.isFile()) {
return path;
}
}
System.out.println("Please specify " + description + ", using system property " + quote(propertyName));
return null;
}
public static void setUpDefaultProjectCreationLocationPath() {
RecentProjectsManager.getInstance().setLastProjectCreationLocation(getProjectCreationDirPath().getPath());
}
// Called by IdeTestApplication via reflection.
@SuppressWarnings("UnusedDeclaration")
public static void waitForIdeToStart() {
GuiActionRunner.executeInEDT(false);
Robot robot = null;
try {
robot = BasicRobot.robotWithCurrentAwtHierarchy();
final MyProjectManagerListener listener = new MyProjectManagerListener();
//[ACCEPT IntelliJ IDEA Privacy Policy Agreement]
acceptAgreementIfNeeded(robot);
findFrame(new GenericTypeMatcher<Frame>(Frame.class) {
@Override
protected boolean isMatching(@NotNull Frame frame) {
if (frame instanceof IdeFrame) {
if (frame instanceof IdeFrameImpl) {
listener.myActive = true;
ProjectManager.getInstance().addProjectManagerListener(listener);
}
return true;
}
return false;
}
}).withTimeout(LONG_TIMEOUT.duration()).using(robot);
//TODO: clarify here what the hell is going on?
// We know the IDE event queue was pushed in front of the AWT queue. Some JDKs will leave a dummy event in the AWT queue, which
// we attempt to clear here. All other events, including those posted by the Robot, will go through the IDE event queue.
//try {
// if (SYSTEM_EVENT_QUEUE.peekEvent() != null) {
// SYSTEM_EVENT_QUEUE.getNextEvent();
// }
//}
//catch (InterruptedException ex) {
// // Ignored.
//}
if (listener.myActive) {
pause(new Condition("Project to be opened") {
@Override
public boolean test() {
boolean notified = listener.myNotified;
if (notified) {
ProgressManager progressManager = ProgressManager.getInstance();
boolean isIdle = !progressManager.hasModalProgressIndicator() &&
!progressManager.hasProgressIndicator() &&
!progressManager.hasUnsafeProgressIndicator();
if (isIdle) {
ProjectManager.getInstance().removeProjectManagerListener(listener);
}
return isIdle;
}
return false;
}
}, LONG_TIMEOUT);
}
}
finally {
GuiActionRunner.executeInEDT(true);
if (robot != null) {
robot.cleanUpWithoutDisposingWindows();
}
}
}
private static void acceptAgreementIfNeeded(Robot robot) {
final String policyAgreement = "Privacy Policy Agreement";
Pair<PrivacyPolicy.Version, String> policy = PrivacyPolicy.getContent();
boolean showPrivacyPolicyAgreement = !PrivacyPolicy.isVersionAccepted(policy.getFirst());
if (!showPrivacyPolicyAgreement) {
LOG.info(policyAgreement + " dialog should be skipped on this system.");
return;
}
try {
final DialogFixture
privacyDialogFixture = findDialog(new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
if (dialog.getTitle() == null) return false;
return dialog.getTitle().contains(policyAgreement) && dialog.isShowing();
}
}).withTimeout(LONG_TIMEOUT.duration()).using(robot);
String buttonText = "Accept";
JButton acceptButton = privacyDialogFixture.button(new GenericTypeMatcher<JButton>(JButton.class) {
@Override
protected boolean isMatching(@Nonnull JButton button) {
if (button.getText() == null) return false;
return button.getText().equals(buttonText);
}
}).target();
//we clicking this button to avoid NPE org.fest.util.Preconditions.checkNotNull(Preconditions.java:71)
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
EdtInvocationManager.getInstance().invokeLater(new Runnable() {
@Override
public void run() {
acceptButton.doClick();
}
});
}
});
}
catch (WaitTimedOutError we) {
LOG.warn("Timed out waiting for \"" + policyAgreement + "\" JDialog. Continue...");
}
}
private static void completeInstallation(Robot robot) {
final String dialogName = ApplicationBundle.message("title.complete.installation");
try {
final DialogFixture
completeInstallationDialog = findDialog(dialogName)
.withTimeout(THIRTY_SEC_TIMEOUT.duration()).using(robot);
completeInstallationDialog.button("OK").click();
}
catch (WaitTimedOutError we) {
LOG.warn("Timed out waiting for \"" + dialogName + "\" JDialog. Continue...");
}
}
private static void evaluateIdea(Robot robot) {
final String dialogName = ApplicationNamesInfo.getInstance().getFullProductName() + " License Activation";
try {
final DialogFixture
completeInstallationDialog = findDialog(dialogName)
.withTimeout(THIRTY_SEC_TIMEOUT.duration()).using(robot);
completeInstallationDialog.button("Evaluate for free for 30 days").click();
}
catch (WaitTimedOutError we) {
System.out.println("Timed out waiting for \"" + dialogName + "\" JDialog. Continue...");
}
}
private static void acceptLicenseAgreement(Robot robot) {
final String dialogName = "License Agreement for" + ApplicationInfoImpl.getShadowInstance().getFullApplicationName();
try {
final DialogFixture
completeInstallationDialog = findDialog(dialogName)
.withTimeout(THIRTY_SEC_TIMEOUT.duration()).using(robot);
completeInstallationDialog.button("Evaluate for free for 30 days").click();
}
catch (WaitTimedOutError we) {
System.out.println("Timed out waiting for \"" + dialogName + "\" JDialog. Continue...");
}
}
private static void customizeIdea(Robot robot) {
final String dialogName = "Customize " + ApplicationNamesInfo.getInstance().getFullProductName();
try {
final DialogFixture
completeInstallationDialog = findDialog(dialogName)
.withTimeout(THIRTY_SEC_TIMEOUT.duration()).using(robot);
completeInstallationDialog.button("Skip All and Set Defaults").click();
}
catch (WaitTimedOutError we) {
System.out.println("Timed out waiting for \"" + dialogName + "\" JDialog. Continue...");
}
}
@NotNull
public static File getProjectCreationDirPath() {
return TMP_PROJECT_ROOT;
}
@NotNull
public static File createTempProjectCreationDir() {
try {
// The temporary location might contain symlinks, such as /var@ -> /private/var on MacOS.
// EditorFixture seems to require a canonical path when opening the file.
return createTempDir().getCanonicalFile();
}
catch (IOException ex) {
// For now, keep the original behavior and point inside the source tree.
ex.printStackTrace();
return new File(getTestProjectsRootDirPath(), "newProjects");
}
}
@NotNull
public static File getTestProjectsRootDirPath() {
String testDataPath = PathManager.getHomePath() + "/community/community-tests/testData";
assertNotNull(testDataPath);
assertThat(testDataPath).isNotEmpty();
testDataPath = toCanonicalPath(toSystemDependentName(testDataPath));
return new File(testDataPath, "guiTests");
}
private GuiTests() {
}
public static void deleteFile(@Nullable final VirtualFile file) {
// File deletion must happen on UI thread under write lock
if (file != null) {
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
file.delete(this);
}
catch (IOException e) {
// ignored
}
}
});
}
});
}
}
/**
* Waits until an IDE popup is shown (and returns it
*/
public static JBList waitForPopup(@NotNull Robot robot) {
return waitUntilFound(robot, null, new GenericTypeMatcher<JBList>(JBList.class) {
@Override
protected boolean isMatching(@NotNull JBList list) {
ListModel model = list.getModel();
return model instanceof ListPopupModel;
}
});
}
/**
* Clicks an IntelliJ/Studio popup menu item with the given label prefix
*
* @param labelPrefix the target menu item label prefix
* @param component a component in the same window that the popup menu is associated with
* @param robot the robot to drive it with
*/
public static void clickPopupMenuItem(@NotNull String labelPrefix, @NotNull Component component, @NotNull Robot robot) {
clickPopupMenuItemMatching(new PrefixMatcher(labelPrefix), component, robot);
}
public static void clickPopupMenuItemMatching(@NotNull Matcher<String> labelMatcher, @NotNull Component component, @NotNull Robot robot) {
// IntelliJ doesn't seem to use a normal JPopupMenu, so this won't work:
// JPopupMenu menu = myRobot.findActivePopupMenu();
// Instead, it uses a JList (technically a JBList), which is placed somewhere
// under the root pane.
Container root = getRootContainer(component);
// First find the JBList which holds the popup. There could be other JBLists in the hierarchy,
// so limit it to one that is actually used as a popup, as identified by its model being a ListPopupModel:
assertNotNull(root);
JBList list = robot.finder().find(root, new GenericTypeMatcher<JBList>(JBList.class) {
@Override
protected boolean isMatching(@NotNull JBList list) {
ListModel model = list.getModel();
return model instanceof ListPopupModel;
}
});
// We can't use the normal JListFixture method to click by label since the ListModel items are
// ActionItems whose toString does not reflect the text, so search through the model items instead:
ListPopupModel model = (ListPopupModel)list.getModel();
List<String> items = Lists.newArrayList();
for (int i = 0; i < model.getSize(); i++) {
Object elementAt = model.getElementAt(i);
if (elementAt instanceof PopupFactoryImpl.ActionItem) {
PopupFactoryImpl.ActionItem item = (PopupFactoryImpl.ActionItem)elementAt;
String s = item.getText();
if (labelMatcher.matches(s)) {
new JListFixture(robot, list).clickItem(i);
return;
}
items.add(s);
}
else { // For example package private class IntentionActionWithTextCaching used in quickfix popups
String s = elementAt.toString();
if (labelMatcher.matches(s)) {
new JListFixture(robot, list).clickItem(i);
return;
}
items.add(s);
}
}
if (items.isEmpty()) {
fail("Could not find any menu items in popup");
}
fail("Did not find menu item '" + labelMatcher + "' among " + on(", ").join(items));
}
/**
* Returns the root container containing the given component
*/
@Nullable
public static Container getRootContainer(@NotNull final Component component) {
return execute(new GuiQuery<Container>() {
@Override
@Nullable
protected Container executeInEDT() throws Throwable {
return (Container)SwingUtilities.getRoot(component);
}
});
}
public static void findAndClickOkButton(@NotNull ContainerFixture<? extends Container> container) {
findAndClickButton(container, "OK");
}
public static void findAndClickCancelButton(@NotNull ContainerFixture<? extends Container> container) {
findAndClickButton(container, "Cancel");
}
public static void findAndClickButton(@NotNull ContainerFixture<? extends Container> container, @NotNull final String text) {
final boolean[] checkClick = {false};
Robot robot = container.robot();
JButton button = findButton(container, text, robot);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
checkClick[0] = true;
}
});
robot.click(button);
//click button again if previous action is missed
if (!checkClick[0]) robot.click(button);
}
public static void findAndClickButtonWhenEnabled(@NotNull ContainerFixture<? extends Container> container, @NotNull final String text) {
Robot robot = container.robot();
final JButton button = findButton(container, text, robot);
pause(new Condition("Wait for button " + text + " to be enabled.") {
@Override
public boolean test() {
return button.isEnabled() && button.isVisible() && button.isShowing();
}
}, SHORT_TIMEOUT);
robot.click(button);
}
public static void invokeMenuPathOnRobotIdle(IdeFrameFixture projectFrame, String... path) {
projectFrame.robot().waitForIdle();
projectFrame.invokeMenuPath(path);
}
/**
* Opens the file with basename {@code fileBasename}
*/
public static void openFile(IdeFrameFixture projectFrame, String fileBasename) {
invokeMenuPathOnRobotIdle(projectFrame, "Navigate", "File...");
projectFrame.robot().waitForIdle();
typeText("multifunction-jni.c", projectFrame.robot(), 30);
projectFrame.robot().pressAndReleaseKey(KeyEvent.VK_ENTER);
}
/**
* Navigates to line number {@code lineNum} of the currently active editor window.
*/
public static void navigateToLine(IdeFrameFixture projectFrame, int lineNum) {
invokeMenuPathOnRobotIdle(projectFrame, "Navigate", "Line...");
projectFrame.robot().enterText(Integer.toString(lineNum));
projectFrame.robot().waitForIdle();
projectFrame.robot().pressAndReleaseKey(KeyEvent.VK_ENTER);
}
private static void typeText(String text, Robot robot, long delayAfterEachCharacterMillis) {
robot.waitForIdle();
for (int i = 0; i < text.length(); ++i) {
robot.type(text.charAt(i));
Pause.pause(delayAfterEachCharacterMillis, TimeUnit.MILLISECONDS);
}
}
@Nullable
public static JLabel findBoundedLabel(@NotNull Container container, @NotNull JTextField textField, @NotNull Robot robot) {
Collection<JLabel> labels = robot.finder().findAll(container, new GenericTypeMatcher<JLabel>(JLabel.class) {
@Override
protected boolean isMatching(@Nonnull JLabel label) {
return (label.getLabelFor() != null && label.getLabelFor().equals(textField));
}
});
if (labels != null && !labels.isEmpty()) {
return labels.iterator().next();
}
else {
return null;
}
}
@NotNull
public static JButton findButton(@NotNull ContainerFixture<? extends Container> container, @NotNull final String text, Robot robot) {
GenericTypeMatcher<JButton> matcher = new GenericTypeMatcher<JButton>(JButton.class) {
@Override
protected boolean isMatching(@NotNull JButton button) {
String buttonText = button.getText();
if (buttonText != null) {
return buttonText.trim().equals(text) && button.isShowing();
}
return false;
}
};
pause(new Condition("Finding for a button with text \"" + text + "\"") {
@Override
public boolean test() {
Collection<JButton> buttons = robot.finder().findAll(matcher);
return !buttons.isEmpty();
}
}, SHORT_TIMEOUT);
return robot.finder().find(container.target(), matcher);
}
/** Returns a full path to the GUI data directory in the user's AOSP source tree, if known, or null */
//@Nullable
//public static File getTestDataDir() {
// File aosp = getAospSourceDir();
// return aosp != null ? new File(aosp, RELATIVE_DATA_PATH) : null;
//}
/**
* Waits for a first component which passes the given matcher to become visible
*/
@NotNull
public static <T extends Component> T waitUntilFound(@NotNull final Robot robot, @NotNull final GenericTypeMatcher<T> matcher) {
return waitUntilFound(robot, null, matcher);
}
public static void skip(@NotNull String testName) {
System.out.println("Skipping test '" + testName + "'");
}
/**
* Waits for a first component which passes the given matcher under the given root to become visible.
*/
@NotNull
public static <T extends Component> T waitUntilFound(@NotNull final Robot robot,
@Nullable final Container root,
@NotNull final GenericTypeMatcher<T> matcher) {
return waitUntilFound(robot, root, matcher, SHORT_TIMEOUT);
}
/**
* Waits for a first component which passes the given matcher under the given root to become visible.
*/
@NotNull
public static <T extends Component> T waitUntilFound(@NotNull final Robot robot,
@Nullable final Container root,
@NotNull final GenericTypeMatcher<T> matcher,
@NotNull Timeout timeout) {
final AtomicReference<T> reference = new AtomicReference<T>();
pause(new Condition("Find component using " + matcher.toString()) {
@Override
public boolean test() {
ComponentFinder finder = robot.finder();
Collection<T> allFound = root != null ? finder.findAll(root, matcher) : finder.findAll(matcher);
boolean found = allFound.size() == 1;
if (found) {
reference.set(getFirstItem(allFound));
}
else if (allFound.size() > 1) {
// Only allow a single component to be found, otherwise you can get some really confusing
// test failures; the matcher should pick a specific enough instance
fail("Found more than one " + matcher.supportedType().getSimpleName() + " which matches the criteria: " + allFound);
}
return found;
}
}, timeout);
return reference.get();
}
/**
* Waits until no components match the given criteria under the given root
*/
public static <T extends Component> void waitUntilGone(@NotNull final Robot robot,
@NotNull final Container root,
@NotNull final GenericTypeMatcher<T> matcher) {
pause(new Condition("Find component using " + matcher.toString()) {
@Override
public boolean test() {
Collection<T> allFound = robot.finder().findAll(root, matcher);
return allFound.isEmpty();
}
}, SHORT_TIMEOUT);
}
@Nullable
public static String getSystemPropertyOrEnvironmentVariable(@NotNull String name) {
String s = System.getProperty(name);
return s == null ? System.getenv(name) : s;
}
private static class MyProjectManagerListener extends ProjectManagerAdapter {
boolean myActive;
boolean myNotified;
@Override
public void projectOpened(Project project) {
myNotified = true;
}
}
private static class PrefixMatcher extends BaseMatcher<String> {
private final String prefix;
public PrefixMatcher(String prefix) {
this.prefix = prefix;
}
@Override
public boolean matches(Object item) {
return item instanceof String && ((String)item).startsWith(prefix);
}
@Override
public void describeTo(Description description) {
description.appendText("with prefix '" + prefix + "'");
}
}
public static String adduction(String s) {
char ESCAPE_SYMBOL = '\u001B';
String ESCAPE_SYMBOL_STRING = "" + ESCAPE_SYMBOL;
if (s.contains(ESCAPE_SYMBOL_STRING)) {
return StringUtil.replace(s, ESCAPE_SYMBOL_STRING, "");
}
else {
return s;
}
}
public static String getBundledJdLocation() {
ArrayList<JdkBundle> bundleList = SwitchBootJdkAction.findJdkPaths().toArrayList();
//we believe that Idea has at least one bundled jdk
JdkBundle jdkBundle = bundleList.get(0);
String homeSubPath = SystemInfo.isMac ? "/Contents/Home" : "";
return jdkBundle.getLocation().getAbsolutePath() + homeSubPath;
}
@NotNull
public static JTextComponentFixture findTextField(@NotNull Robot robot, @NotNull final String labelText) {
return new JTextComponentFixture(robot, robot.finder().findByLabel(labelText, JTextComponent.class));
}
}
@@ -1,31 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Settings to be applied when executing every test method in a class.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IdeGuiTestSetup {
boolean skipSourceGenerationOnSync() default false;
boolean takeScreenshotOnTestFailure() default true;
}
@@ -1,275 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.ide.BootstrapClassLoaderUtil;
import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.WindowsCommandLineProcessor;
import com.intellij.ide.startup.StartupActionScriptManager;
import com.intellij.idea.Main;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.SystemProperties;
import com.intellij.util.lang.UrlClassLoader;
import com.intellij.util.text.StringTokenizer;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import static com.intellij.openapi.application.PathManager.PROPERTY_CONFIG_PATH;
import static com.intellij.openapi.util.io.FileUtil.*;
import static com.intellij.openapi.util.text.StringUtil.isNotEmpty;
import static com.intellij.tests.gui.framework.GuiTests.getProjectCreationDirPath;
import static com.intellij.util.ArrayUtil.EMPTY_STRING_ARRAY;
import static com.intellij.util.ui.UIUtil.initDefaultLAF;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.reflect.core.Reflection.method;
import static org.junit.Assert.assertNotNull;
public class IdeTestApplication implements Disposable {
private static final Logger LOG = Logger.getInstance(IdeTestApplication.class);
private static final String PROPERTY_IGNORE_CLASSPATH = "ignore.classpath";
private static final String PROPERTY_ALLOW_BOOTSTRAP_RESOURCES = "idea.allow.bootstrap.resources";
private static final String PROPERTY_ADDITIONAL_CLASSPATH = "idea.additional.classpath";
private static IdeTestApplication ourInstance;
@NotNull private final ClassLoader myIdeClassLoader;
@NotNull
public static synchronized IdeTestApplication getInstance() throws Exception {
//System.setProperty(PLATFORM_PREFIX_KEY, "AndroidStudio");
//System.setProperty(PLATFORM_PREFIX_KEY, "idea");
File configDirPath = getConfigDirPath();
System.setProperty(PROPERTY_CONFIG_PATH, configDirPath.getPath());
// Force Swing FileChooser on Mac (instead of native one) to be able to use FEST to drive it.
System.setProperty("native.mac.file.chooser.enabled", "false");
//We are using this property to skip testProjectLeak in _LastSuiteTests
System.setProperty("idea.test.guimode", "true");
if (!isLoaded()) {
ourInstance = new IdeTestApplication();
recreateDirectory(configDirPath);
File newProjectsRootDirPath = getProjectCreationDirPath();
recreateDirectory(newProjectsRootDirPath);
ClassLoader ideClassLoader = ourInstance.getIdeClassLoader();
Class<?> clazz = ideClassLoader.loadClass(GuiTests.class.getCanonicalName());
method("waitForIdeToStart").in(clazz).invoke();
method("setUpDefaultGeneralSettings").in(clazz).invoke();
}
return ourInstance;
}
@NotNull
private static File getConfigDirPath() throws IOException {
File dirPath = new File(getGuiTestRootDirPath(), "config");
ensureExists(dirPath);
return dirPath;
}
@NotNull
public static File getFailedTestScreenshotDirPath() throws IOException {
File dirPath = new File(getGuiTestRootDirPath(), "failures");
ensureExists(dirPath);
return dirPath;
}
@NotNull
private static File getGuiTestRootDirPath() throws IOException {
String guiTestRootDirPathProperty = System.getProperty("gui.tests.root.dir.path");
if (isNotEmpty(guiTestRootDirPathProperty)) {
File rootDirPath = new File(guiTestRootDirPathProperty);
if (rootDirPath.isDirectory()) {
return rootDirPath;
}
}
String homeDirPath = toSystemDependentName(PathManager.getHomePath());
assertThat(homeDirPath).isNotEmpty();
File rootDirPath = new File(homeDirPath, join("community-tests", "gui-tests"));
ensureExists(rootDirPath);
return rootDirPath;
}
private static void recreateDirectory(@NotNull File path) throws IOException {
delete(path);
ensureExists(path);
}
private IdeTestApplication() throws Exception {
String[] args = EMPTY_STRING_ARRAY;
LOG.assertTrue(ourInstance == null, "Only one instance allowed.");
ourInstance = this;
pluginManagerStart(args);
mainMain();
myIdeClassLoader = createClassLoader();
//myIdeClassLoader = BootstrapClassLoaderUtil.initClassLoader(false);
WindowsCommandLineProcessor.ourMirrorClass = Class.forName(WindowsCommandLineProcessor.class.getName(), true, myIdeClassLoader);
// We turn on "GUI Testing Mode" right away, even before loading the IDE.
//Class<?> androidPluginClass = Class.forName("org.jetbrains.android.AndroidPlugin", true, myIdeClassLoader);
//method("setGuiTestingMode").withParameterTypes(boolean.class).in(androidPluginClass).invoke(true);
Class<?> classUtilCoreClass = Class.forName("com.intellij.ide.ClassUtilCore", true, myIdeClassLoader);
method("clearJarURLCache").in(classUtilCoreClass).invoke();
Class<?> pluginManagerClass = Class.forName("com.intellij.ide.plugins.PluginManager", true, myIdeClassLoader);
method("start").withParameterTypes(String.class, String.class, String[].class)
.in(pluginManagerClass)
.invoke("com.intellij.idea.MainImpl", "start", args);
}
// This method replaces BootstrapClassLoaderUtil.initClassLoader. The reason behind it is that when running UI tests the ClassLoader
// containing the URLs for the plugin jars is loaded by a different ClassLoader and it gets ignored. The result is test failing because
// classes like AndroidPlugin cannot be found.
@NotNull
private static ClassLoader createClassLoader() throws MalformedURLException, URISyntaxException {
Collection<URL> classpath = Sets.newLinkedHashSet();
addIdeaLibraries(classpath);
addAdditionalClassPath(classpath);
UrlClassLoader.Builder builder = UrlClassLoader.build()
.urls(filterClassPath(Lists.newArrayList(classpath)))
.parent(IdeTestApplication.class.getClassLoader())
.allowLock(false)
.usePersistentClasspathIndexForLocalClassDirectories();
if (SystemProperties.getBooleanProperty(PROPERTY_ALLOW_BOOTSTRAP_RESOURCES, true)) {
builder.allowBootstrapResources();
}
UrlClassLoader newClassLoader = builder.get();
// prepare plugins
try {
StartupActionScriptManager.executeActionScript();
}
catch (IOException e) {
Main.showMessage("Plugin Installation Error", e);
}
Thread.currentThread().setContextClassLoader(newClassLoader);
return newClassLoader;
}
private static void addIdeaLibraries(@NotNull Collection<URL> classpath) throws MalformedURLException {
Class<BootstrapClassLoaderUtil> aClass = BootstrapClassLoaderUtil.class;
String selfRoot = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
assertNotNull(selfRoot);
URL selfRootUrl = new File(selfRoot).getAbsoluteFile().toURI().toURL();
classpath.add(selfRootUrl);
File libFolder = new File(PathManager.getLibPath());
addLibraries(classpath, libFolder, selfRootUrl);
addLibraries(classpath, new File(libFolder, "ext"), selfRootUrl);
addLibraries(classpath, new File(libFolder, "ant/lib"), selfRootUrl);
}
private static void addLibraries(@NotNull Collection<URL> classPath, @NotNull File fromDir, @NotNull URL selfRootUrl)
throws MalformedURLException {
for (File file : notNullize(fromDir.listFiles())) {
if (isJarOrZip(file)) {
URL url = file.toURI().toURL();
if (!selfRootUrl.equals(url)) {
classPath.add(url);
}
}
}
}
private static void addAdditionalClassPath(@NotNull Collection<URL> classpath) throws MalformedURLException {
StringTokenizer tokenizer = new StringTokenizer(System.getProperty(PROPERTY_ADDITIONAL_CLASSPATH, ""), File.pathSeparator, false);
while (tokenizer.hasMoreTokens()) {
String pathItem = tokenizer.nextToken();
classpath.add(new File(pathItem).toURI().toURL());
}
}
private static List<URL> filterClassPath(@NotNull List<URL> classpath) {
String ignoreProperty = System.getProperty(PROPERTY_IGNORE_CLASSPATH);
if (ignoreProperty != null) {
Pattern pattern = Pattern.compile(ignoreProperty);
for (Iterator<URL> i = classpath.iterator(); i.hasNext(); ) {
String url = i.next().toExternalForm();
if (pattern.matcher(url).matches()) {
i.remove();
}
}
}
return classpath;
}
private static void pluginManagerStart(@NotNull String[] args) {
// Duplicates what PluginManager#start does.
Main.setFlags(args);
initDefaultLAF();
}
private static void mainMain() {
// Duplicates what Main#main does.
method("installPatch").in(Main.class).invoke();
}
@NotNull
public ClassLoader getIdeClassLoader() {
return myIdeClassLoader;
}
@Override
public void dispose() {
disposeInstance();
}
public static synchronized void disposeInstance() {
if (!isLoaded()) {
return;
}
IdeEventQueue.getInstance().flushQueue();
final Application application = ApplicationManager.getApplication();
((ApplicationImpl)application).exit(true, true, false, false);
ourInstance = null;
}
public static synchronized boolean isLoaded() {
return ourInstance != null;
}
}
@@ -1,151 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
import org.fest.swing.image.ScreenshotTaker;
import org.jetbrains.annotations.NotNull;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import java.io.File;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import static com.intellij.tests.gui.framework.GuiTestRunner.canRunGuiTests;
import static com.intellij.tests.gui.framework.IdeTestApplication.getFailedTestScreenshotDirPath;
import static org.fest.reflect.core.Reflection.field;
import static org.fest.reflect.core.Reflection.method;
public class MethodInvoker extends Statement {
@NotNull private final GuiTestConfigurator myTestConfigurator;
@NotNull private final FrameworkMethod myTestMethod;
@NotNull private final Object myTest;
@NotNull private final ScreenshotTaker myScreenshotTaker;
MethodInvoker(@NotNull FrameworkMethod testMethod, @NotNull Object test, @NotNull ScreenshotTaker screenshotTaker) throws Throwable {
myTestConfigurator = GuiTestConfigurator.createNew(testMethod.getMethod(), test);
myTestMethod = testMethod;
myTest = test;
myScreenshotTaker = screenshotTaker;
}
@Override
public void evaluate() throws Throwable {
//if (myTestConfigurator.shouldSkipTest()) {
// Message already printed in console.
//return;
//}
String testFqn = getTestFqn();
if (doesIdeHaveFatalErrors()) {
// Fatal errors were caused by previous test. Skipping this test.
System.out.println(String.format("Skipping test '%1$s': a fatal error has occurred in the IDE", testFqn));
return;
}
System.out.println(String.format("Executing test '%1$s'", testFqn));
int retryCount = myTestConfigurator.getRetryCount();
for (int i = 0; i <= retryCount; i++) {
if (i > 0) {
System.out.println(String.format("Retrying execution of test '%1$s'", testFqn));
}
try {
runTest(i);
break; // no need to retry.
}
catch (Throwable throwable) {
if (retryCount == i) {
throw throwable; // Last run, throw any exceptions caught.
}
else {
throwable.printStackTrace();
failIfIdeHasFatalErrors();
}
}
}
failIfIdeHasFatalErrors();
}
public static boolean doesIdeHaveFatalErrors() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
Class<?> guiTestsType = Class.forName(GuiTests.class.getCanonicalName(), true, classLoader);
//noinspection ConstantConditions
return method("doesIdeHaveFatalErrors").withReturnType(boolean.class).in(guiTestsType).invoke();
} catch (ClassNotFoundException ex) {
// ignore exception
return true;
}
}
private static void failIfIdeHasFatalErrors() throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?> guiTestsType = Class.forName(GuiTests.class.getCanonicalName(), true, classLoader);
method("failIfIdeHasFatalErrors").in(guiTestsType).invoke();
}
private void runTest(int executionIndex) throws Throwable {
myTestConfigurator.executeSetupTasks();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?> guiTestCaseType = Class.forName(GuiTestCase.class.getCanonicalName(), true, classLoader);
if (guiTestCaseType.isInstance(myTest)) {
if (!canRunGuiTests()) {
// We don't run tests in headless environment.
return;
}
field("myTestName").ofType(String.class).in(myTest).set(myTestMethod.getName());
}
try {
myTestMethod.invokeExplosively(myTest);
}
catch (Throwable e) {
e.printStackTrace();
takeScreenshot(executionIndex);
throw e;
}
}
@NotNull
private String getTestFqn() {
return myTestMethod.getMethod().getDeclaringClass() + "#" + myTestMethod.getName();
}
private void takeScreenshot(int executionIndex) {
if (myTestConfigurator.shouldTakeScreenshotOnFailure()) {
Method method = myTestMethod.getMethod();
String fileNamePrefix = method.getDeclaringClass().getSimpleName() + "." + (executionIndex + 1) + "." + method.getName();
String extension = ".png";
try {
File rootDir = getFailedTestScreenshotDirPath();
File screenshotFilePath = new File(rootDir, fileNamePrefix + extension);
if (screenshotFilePath.isFile()) {
SimpleDateFormat format = new SimpleDateFormat("MM-dd-yyyy.HH:mm:ss");
String now = format.format(new GregorianCalendar().getTime());
screenshotFilePath = new File(rootDir, fileNamePrefix + "." + now + extension);
}
myScreenshotTaker.saveDesktopAsPng(screenshotFilePath.getPath());
System.out.println("Screenshot of failed test taken and stored at " + screenshotFilePath.getPath());
}
catch (Throwable ignored) {
System.out.println("Failed to take screenshot. Cause: " + ignored.getMessage());
}
}
}
}
@@ -1,34 +0,0 @@
package com.intellij.tests.gui.framework
import com.intellij.tests.gui.fixtures.WelcomeFrameFixture
import com.intellij.ui.components.JBList
import org.fest.swing.core.Robot
import org.fest.swing.fixture.JListFixture
import org.fest.swing.timing.Condition
import org.fest.swing.timing.Pause
import java.awt.Container
/**
We presume that IDEA is already started, shows "Welcome dialog" and we could create a new project
!!UNFINISHED!!
**/
fun GuiTestCase.createNewProject(): WelcomeFrameFixture {
return findWelcomeFrame().createNewProject()
}
fun pause(time: Long, root: Robot) {
Pause.pause(object : Condition("Wait for user actions") {
override fun test(): Boolean {
return false
}
}, time)
}
fun clickListItem(itemName: String, robot: Robot, parentContainer: Container) {
val listFixture = JListFixture(robot, robot.finder().findByType(parentContainer, JBList::class.java, true))
listFixture.clickItem(itemName)
}
@@ -1,20 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
public enum TestGroup {
PROJECT
}
@@ -1,42 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.script
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.tests.gui.framework.GuiTestCase
import org.fest.swing.core.AdvancedRobot
/**
* Created by jetbrains on 12/09/16.
*/
class ScriptAction(val scriptName: String) : AnAction("guiTest." + scriptName){
override fun actionPerformed(e: AnActionEvent?) {
val myPackage = "com.intellij.tests.gui.test"
val loadedClass = this.javaClass.classLoader.loadClass("${myPackage}.${scriptName}")
val guiTest = loadedClass.newInstance() as GuiTestCase
//setting advanced robot
guiTest.setRobot(AdvancedRobot())
val testsInClass = loadedClass.methods.filter { it.name.contains("test") }
ApplicationManager.getApplication().executeOnPooledThread { testsInClass.get(0).invoke(guiTest) }
}
}
@@ -1,60 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.script
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.compiler.CompilerManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFileManager
/**
* Created by @author Sergey Karashevich on 12/09/16.
*/
class ScriptCompileAction: AnAction(){
fun homePath() = PathManager.getHomePath()
//we have to load idea project to compile kotlin files on the fly. Let's do it in a lazy manner.
val project: Project? by lazy {
ProjectManagerEx.getInstanceEx().loadProject("${homePath()}/idea.iml");
}
val srcPath = "community/community-tests/src"
val myPackage = "com.intellij.tests.gui.test"
override fun actionPerformed(e: AnActionEvent?) {
compileAndRun()
}
fun compileAndRun() {
val myPackagePath = myPackage.replace(".", "/")
val url = VfsUtil.pathToUrl("${homePath()}/${srcPath}/${myPackagePath}/CurrentTest.kt")
val virtualFile = VirtualFileManager.getInstance().findFileByUrl(url)
CompilerManager.getInstance(project).compile(arrayOf(virtualFile), { aborted, errors, warnings, compileContext ->
if (!aborted) {
print("Compilation done")
ScriptAction("CurrentTest").actionPerformed(AnActionEvent.createFromDataContext("nothing", null, DataContext.EMPTY_CONTEXT))
}
})
}
}
@@ -1,168 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.script
import com.intellij.internal.inspector.UiDropperActionExtension
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.tests.gui.framework.GuiTests
import org.fest.swing.core.BasicRobot
import java.awt.Component
import java.awt.Container
import javax.swing.*
/**
* Created by jetbrains on 18/08/16.
*/
/**
* ScriptRecorder needs to create GUI Tests quickly. For recording UI actions like click, text entering, checkbox marking we using UI dropper.
*/
class ScriptRecorder() : AnAction(), UiDropperActionExtension {
override fun getAnAction(): com.intellij.openapi.actionSystem.AnAction? {
return this
}
var currentContextComponent: Component? = null
private var currentContext = Contexts()
override fun actionPerformed(e: com.intellij.openapi.actionSystem.AnActionEvent?) {
//get action type for script: click, enter text, mark checkbox
val component = e!!.getDataContext().getData("Component") as Component
checkContext(component)
clickCmp(component, e)
}
//registering custom actions for a UI Dropper by ctrl + alt + click
fun registerUiDropperAction() {
com.intellij.internal.inspector.UiDropperAction.setClickAction(this)
}
fun recordAction() {
}
fun clickCmp(cmp: Component, e: com.intellij.openapi.actionSystem.AnActionEvent) {
when (cmp) {
is JButton -> write(Templates.findAndClickButton(cmp.text))
is com.intellij.ui.components.labels.ActionLink -> write(Templates.clickActionLink(cmp.text))
is JTextField -> {
val label = getLabel(currentContextComponent as Container, cmp)
if (label == null)
write(Templates.findJTextField())
else
write(Templates.findJTextFieldByLabel(label.text))
}
is com.intellij.ui.components.JBList -> {
val itemName = e.dataContext.getData("ItemName") as String
if (isPopupList(cmp))
write(Templates.clickPopupItem(itemName))
else
write(Templates.clickListItem(itemName))
}
}
}
private fun isPopupList(cmp: Component) = cmp.javaClass.name.toLowerCase().contains("listpopup")
private fun getLabel(container: Container, jTextField: JTextField): JLabel? {
val robot = BasicRobot.robotWithCurrentAwtHierarchyWithoutScreenLock()
return GuiTests.findBoundedLabel(container, jTextField, robot)
}
fun checkContext(cmp: Component) {
cmp as JComponent
if (isPopupList(cmp)) return //dont' change context for a popup menu
if (currentContextComponent != null && !cmp.rootPane.equals(currentContextComponent)) {
write(currentContext.closeContext())
}
if (currentContextComponent == null || !cmp.rootPane.equals(currentContextComponent)) {
currentContextComponent = cmp.rootPane
when (cmp.rootPane.parent) {
is JDialog -> {
if ((cmp.rootPane.parent as JDialog).title.equals(com.intellij.ide.IdeBundle.message("title.new.project")))
write(currentContext.projectWizardContextStart())
else
write(currentContext.dialogContextStart((cmp.rootPane.parent as JDialog).title))
}
is com.intellij.openapi.wm.impl.welcomeScreen.FlatWelcomeFrame -> write(currentContext.welcomeFrameStart())
is JFrame -> println("is JFrame")
}
}
}
fun write(str: String) {
println(str)
}
}
//TEMPLATES
private object Templates {
fun findDialog(name: String, title: String?) = "val ${name} = DialogFixture.find(robot(), \"${title}\")"
fun withDialog(name: String) = "with (${name}){"
fun findProjectWizard(name: String) = "val ${name} = findNewProjectWizard()"
fun withProjectWizard(name: String) = "with (${name}){"
fun findWelcomeFrame(name: String) = "val ${name} = findWelcomeFrame()"
fun withWelcomeFrame(name: String) = "with (${name}){"
fun findAndClickButton(text: String) = "GuiTests.findAndClickButton(this, \"${text}\")"
fun clickActionLink(text: String) = "ActionLinkFixture.findActionLinkByName(\"${text}\", robot(), this.target()).click()"
fun clickPopupItem(itemName: String) = "GuiTests.clickPopupMenuItem(\"${itemName}\", this.target(), robot())"
fun clickListItem(name: String) = "clickListItem(\"${name}\", robot(), this.target())"
fun findJTextField() = "val textField = myRobot.finder().findByType(JTextField::class.java)"
fun findJTextFieldByLabel(labelText: String) = "val textField = findTextField(\"${labelText}\").click()"
}
private class Contexts() {
enum class Type {DIALOG, WELCOME_FRAME, PROJECT_WIZARD, IDE_FRAME}
var dialogCount = 0
var currentContextType: Type? = null
fun dialogContextStart(title: String): String {
currentContextType = Type.DIALOG
val name = "dialog${dialogCount++}"
val findDialog = Templates.findDialog(name, title)
val withDialog = Templates.withDialog(name)
return findDialog + "\n" + withDialog
}
fun projectWizardContextStart(): String {
currentContextType = Type.PROJECT_WIZARD
val name = "projectWizard"
val findProjectWizard = Templates.findProjectWizard(name)
val withProjectWizard = Templates.withProjectWizard(name)
return findProjectWizard + "\n" + withProjectWizard
}
fun welcomeFrameStart(): String {
currentContextType = Type.WELCOME_FRAME
val name = "welcomeFrame"
val findWelcomeFrame = Templates.findWelcomeFrame(name)
var withWelcomeFrame = Templates.withWelcomeFrame(name)
return findWelcomeFrame + "\n" + withWelcomeFrame
}
fun closeContext() = "}"
}
@@ -1,34 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.test
import com.intellij.tests.gui.framework.GuiTestCase
import org.junit.Test
/**
* Created by jetbrains on 12/09/16.
*/
class CurrentTest: GuiTestCase(){
@Test
fun testMe() {
val ideFrame = findIdeFrame()
ideFrame.waitForBackgroundTasksToFinish()
ideFrame.editor.enterText("Hello!")
}
}
@@ -1,85 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.test
import com.intellij.dvcs.ui.CloneDvcsDialog
import com.intellij.dvcs.ui.DvcsBundle
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.vcs.VcsBundle
import com.intellij.tests.gui.fixtures.*
import com.intellij.tests.gui.framework.GuiTestCase
import com.intellij.tests.gui.framework.GuiTests
import com.intellij.ui.EditorComboBox
import org.fest.swing.edt.GuiActionRunner
import org.fest.swing.edt.GuiTask
import org.fest.swing.fixture.DialogFixture
import org.junit.Test
/**
* Created by karashevich on 18/06/16.
*/
class GitGuiTest : GuiTestCase() {
@Test
fun testGitImport(){
val vcsName = "Git"
val gitPath = "https://github.com/karashevich/test.git"
val welcomeFrame = WelcomeFrameFixture.find(myRobot)
welcomeFrame.checkoutFrom()
JBListPopupFixture.findListPopup(myRobot).invokeAction(vcsName)
val cloneVcsDialog = DialogFixture(myRobot, IdeaDialogFixture.find(myRobot, CloneDvcsDialog::class.java).dialog) //don't miss robot as the first argument or you'll stuck with a deadlock
with(cloneVcsDialog) {
val labelText = DvcsBundle.message("clone.repository.url", vcsName)
val editorComboBox = myRobot.finder().findByLabel(this.target(), labelText, EditorComboBox::class.java)
GuiActionRunner.execute(object : GuiTask() {
@Throws(Throwable::class)
override fun executeInEDT() {
editorComboBox.text = gitPath
}
})
GuiTests.findAndClickButton(this, DvcsBundle.getString("clone.button"))
}
MessagesFixture.findByTitle(myRobot, welcomeFrame.target(), VcsBundle.message("checkout.title")).clickYes()
val dialog1 = com.intellij.tests.gui.fixtures.DialogFixture.find(myRobot, "Import Project")
with (dialog1) {
GuiTests.findAndClickButton(this, "Next")
val textField = GuiTests.findTextField(myRobot, "Project name:").click()
// textField.setText("test-project")
GuiTests.findAndClickButton(this, "Next")
GuiTests.findAndClickButton(this, "Next")
GuiTests.findAndClickButton(this, "Next") //libraries
GuiTests.findAndClickButton(this, "Next") //module dependencies
GuiTests.findAndClickButton(this, "Next") //select sdk
GuiTests.findAndClickButton(this, "Finish")
}
val ideFrame = findIdeFrame()
ideFrame.waitForBackgroundTasksToFinish()
val projectView = ideFrame.projectView
val testJavaPath = "src/Test.java"
val editor = ideFrame.editor
editor.open(testJavaPath)
ToolWindowFixture.showToolwindowStripes(myRobot)
//prevent from ProjectLeak (if the project is closed during the indexing
DumbService.getInstance(ideFrame.project).waitForSmartMode()
}
}
@@ -1,101 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.test;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.tests.gui.fixtures.ProjectViewFixture;
import com.intellij.tests.gui.fixtures.ToolWindowFixture;
import com.intellij.tests.gui.fixtures.WelcomeFrameFixture;
import com.intellij.tests.gui.fixtures.newProjectWizard.NewProjectWizardFixture;
import com.intellij.tests.gui.framework.GuiTestCase;
import com.intellij.tests.gui.framework.GuiTests;
import com.intellij.tests.gui.framework.IdeGuiTest;
import org.junit.Test;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.intellij.tests.gui.framework.GuiTests.getSystemJdk;
/**
* Created by karashevich on 27/05/16.
*/
public class JavaEEProjectTest extends GuiTestCase {
//Should run with main_idea_tests module classpath
@Test @IdeGuiTest
public void testJavaEEProject() throws IOException, InterruptedException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm");
Date date = new Date();
String projectName = "smoke-test-project-" + dateFormat.format(date);
WelcomeFrameFixture welcomeFrame = findWelcomeFrame();
welcomeFrame.createNewProject();
NewProjectWizardFixture newProjectWizard = findNewProjectWizard();
setupJdk(newProjectWizard);
//select project type and framework
newProjectWizard.
selectProjectType("Java").
selectFramework("JavaEE Persistence");
newProjectWizard.clickNext();
newProjectWizard.setProjectName(projectName);
final File locationInFileSystem = newProjectWizard.getLocationInFileSystem();
newProjectWizard.clickFinish();
myProjectFrame = findIdeFrame(projectName, locationInFileSystem);
myProjectFrame.waitForBackgroundTasksToFinish();
final ProjectViewFixture projectView = myProjectFrame.getProjectView();
final ProjectViewFixture.PaneFixture paneFixture = projectView.selectProjectPane();
paneFixture.selectByPath(projectName, "src", "META-INF", "persistence.xml");
ToolWindowFixture.showToolwindowStripes(myRobot);
//prevent from ProjectLeak (if the project is closed during the indexing
DumbService.getInstance(myProjectFrame.getProject()).waitForSmartMode();
//final JToggleButtonFixture persistence = (new JToggleButtonFinder("Persistence")).withTimeout(THIRTY_SEC_TIMEOUT.duration()).using(myRobot);
//persistence.click();
//ToolWindowFixture.clickToolwindowButton("Persistence", myRobot);
//ToolWindowFixture.clickToolwindowButton("Java Enterprise", myRobot);
}
private void setupJdk(NewProjectWizardFixture newProjectWizard) {
if (newProjectWizard.isJdkEmpty()) {
JButton newButton = GuiTests.findButton(newProjectWizard,
GuiTests.adduction(ApplicationBundle.message("button.new")),
myRobot);
myRobot.click(newButton);
File javaSdkPath = new File(getSystemJdk());
String sdkType = GuiTests.adduction(ProjectBundle.message("sdk.java.name"));
GuiTests.clickPopupMenuItem(sdkType, newButton, myRobot);
newProjectWizard.selectSdkPath(javaSdkPath, sdkType);
}
}
}
@@ -1,101 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.test;
import com.intellij.dvcs.ui.CloneDvcsDialog;
import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.tests.gui.fixtures.*;
import com.intellij.tests.gui.framework.GuiTestCase;
import com.intellij.ui.EditorComboBox;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiTask;
import org.junit.Ignore;
import org.junit.Test;
import static com.intellij.tests.gui.framework.GuiTests.findAndClickButton;
/**
* Created by jetbrains on 06/09/16.
*/
public class JavaGitGuiTest extends GuiTestCase {
@Ignore
@Test
public void testGitImport(){
String gitPath = "https://github.com/karashevich/test.git";
//wait welcome frame
//get welcome frame
WelcomeFrameFixture welcomeFrameFixture = WelcomeFrameFixture.find(myRobot);
//click ActionLink "Check out from Version Control"
welcomeFrameFixture.checkoutFrom();
//click ListPopup menu item "Git"
String vcsName = "Git";
JBListPopupFixture.findListPopup(myRobot).invokeAction(vcsName);
//find new dialog "Clone Repository"
DialogFixture dialogFixture = new DialogFixture(myRobot, IdeaDialogFixture.find(myRobot, CloneDvcsDialog.class).dialog);
//find EditorComboBox near label "Git Repository URL:"
String message = DvcsBundle.message("clone.repository.url", vcsName);
EditorComboBox editorComboBox = myRobot.finder().findByLabel(dialogFixture.target(), message, EditorComboBox.class);
//enter gitPath
GuiActionRunner.execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
editorComboBox.setText(gitPath);
}
});
//click button "Clone"
findAndClickButton(dialogFixture, DvcsBundle.message("clone.button"));
//find message with title "Checkout From Version Control"
//click "Yes"
MessagesFixture.findByTitle(myRobot, welcomeFrameFixture.target(), VcsBundle.message("checkout.title")).clickYes();
//find new dialog "Import Project"
DialogFixture importProjectFixture = DialogFixture.find(myRobot, "Import Project");
//click "Next"
findAndClickButton(importProjectFixture, "Next");
//click "Next"
findAndClickButton(importProjectFixture, "Next");
//click "Next"
findAndClickButton(importProjectFixture, "Next");
//click "Next"
findAndClickButton(importProjectFixture, "Next");
//click "Next"
findAndClickButton(importProjectFixture, "Next");
//click "Next"
findAndClickButton(importProjectFixture, "Next");
//find message with title "No SDK Specified"
//click "Ok"
MessagesFixture.findByTitle(myRobot, welcomeFrameFixture.target(), IdeBundle.message("title.no.jdk.specified")).clickOk();
//click "Finish"
findAndClickButton(importProjectFixture, "Finish");
//wait ideFrame
IdeFrameFixture ideFrame = findIdeFrame();
//wait background processes (indexing)
ideFrame.waitForBackgroundTasksToFinish();
//check java class "src/Test.java"
//open Test.java in editor
String testJavaPath = "src/Test.java";
EditorFixture editor = ideFrame.getEditor();
editor.open(testJavaPath);
}
}
@@ -1,87 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.test
import com.intellij.tests.gui.fixtures.DialogFixtures.CreateDialogFixture
import com.intellij.tests.gui.fixtures.EditorFixture
import com.intellij.tests.gui.fixtures.JBPopupFixture
import com.intellij.tests.gui.framework.GuiTestCase
import com.intellij.tests.gui.framework.clickListItem
import com.intellij.tests.gui.framework.createNewProject
import org.junit.Ignore
import org.junit.Test
import java.io.File
import javax.swing.text.JTextComponent
/**
* Created by karashevich on 18/06/16.
*/
class JavaProjectTest: GuiTestCase() {
@Test
@Ignore
fun testJavaProject(){
var locationFile: File? = null
val projectName = "smoke-test"
createNewProject()
val newProjectWizard = findNewProjectWizard()
with(newProjectWizard){
setupJdk()
// selectProjectType("Java")
clickListItem("Java", robot(), this.target())
selectFramework("JavaEE Persistence")
clickNext()
setProjectName(projectName);
locationFile = locationInFileSystem
clickFinish()
}
requireNotNull(locationFile) {
"Unable to determine location for \"$projectName\" project"
}
val ideFrame = findIdeFrame(projectName, locationFile!!)
with(ideFrame){
val paneFixture = projectView.selectProjectPane()
paneFixture.selectByPath(projectName, "src", "META-INF", "persistence.xml").doubleClick(robot())
val node = paneFixture.selectByPath(projectName, "src")
node.invokeContextMenu(robot())
val contextMenu = JBPopupFixture.findContextMenu(robot())
waitForBackgroundTasksToFinish()
with(contextMenu) {
assertContainsAction("Cut")
invokeAction("New", "Java Class")
}
val newDialog = CreateDialogFixture.find(robot())
with(newDialog) {
val jTextComponent = robot().finder().findByLabel("Name:", JTextComponent::class.java)
jTextComponent.setText("Test")
clickOK()
}
with(editor) {
invokeAction(EditorFixture.EditorAction.COMPLETE_CURRENT_STATEMENT)
enterText("psvm")
invokeAction(EditorFixture.EditorAction.TAB)
}
waitForBackgroundTasksToFinish()
}
}
}
@@ -1,93 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.test;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.tests.gui.fixtures.ProjectViewFixture;
import com.intellij.tests.gui.fixtures.newProjectWizard.NewProjectWizardFixture;
import com.intellij.tests.gui.framework.GuiTestCase;
import com.intellij.tests.gui.framework.GuiTests;
import com.intellij.tests.gui.framework.IdeGuiTest;
import org.junit.Ignore;
import org.junit.Test;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.intellij.tests.gui.framework.GuiTests.getSystemJdk;
/**
* Created by karashevich on 27/05/16.
*/
public class NewProjectTest extends GuiTestCase {
//Should run with main_idea_tests module classpath
@Test @IdeGuiTest
@Ignore
public void testNewProject() throws IOException, InterruptedException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm");
Date date = new Date();
String projectName = "smoke-test-project-" + dateFormat.format(date);
findWelcomeFrame().createNewProject();
NewProjectWizardFixture newProjectWizard = findNewProjectWizard();
//check Project SDK is not Empty
setupJdkIfNeeded(newProjectWizard);
//select project type and framework
newProjectWizard.
selectProjectType("Java").
selectFramework("JavaEE Persistence");
newProjectWizard.clickNext();
newProjectWizard.setProjectName(projectName);
final File locationInFileSystem = newProjectWizard.getLocationInFileSystem();
newProjectWizard.clickFinish();
myProjectFrame = findIdeFrame(projectName, locationInFileSystem);
final ProjectViewFixture projectView = myProjectFrame.getProjectView();
final ProjectViewFixture.PaneFixture paneFixture = projectView.selectProjectPane();
paneFixture.selectByPath(projectName, "src", "META-INF", "persistence.xml");
Thread.sleep(10000);
}
private void setupJdkIfNeeded(NewProjectWizardFixture newProjectWizard) {
if (newProjectWizard.isJdkEmpty()) {
JButton newButton = GuiTests.findButton(newProjectWizard,
GuiTests.adduction(ApplicationBundle.message("button.new")),
myRobot);
myRobot.click(newButton);
File javaSdkPath = new File(getSystemJdk());
String sdkType = GuiTests.adduction(ProjectBundle.message("sdk.java.name"));
GuiTests.clickPopupMenuItem(sdkType, newButton, myRobot);
newProjectWizard.selectSdkPath(javaSdkPath, sdkType);
}
}
}
@@ -1,40 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.test
import com.intellij.tests.gui.fixtures.WelcomeFrameFixture
import com.intellij.tests.gui.framework.GuiTestCase
import com.intellij.tests.gui.framework.createNewProject
import org.junit.Assert
import org.junit.Test
/**
* Created by karashevich on 18/06/16.
*/
class ShortGuiTest: GuiTestCase() {
@Test
fun testJavaProject(){
val createNewProject = createNewProject()
val newProjectWizard = findNewProjectWizard()
with(newProjectWizard) {
clickCancel()
}
val find = WelcomeFrameFixture.find(myRobot)
Assert.assertNotNull(find)
}
}
@@ -1,32 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.test
import com.intellij.tests.gui.framework.GuiTestCase
import com.intellij.tests.gui.framework.IdeGuiTest
import org.junit.Test
/**
* Created by karashevich on 21/06/16.
*/
class SimpleApplicationImportTest: GuiTestCase() {
@Test @IdeGuiTest
fun testSimpleApplication(){
val app = importSimpleApplication()
app.waitForBackgroundTasksToFinish()
}
}
@@ -1,79 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fest.swing.core;
import org.fest.swing.hierarchy.ComponentHierarchy;
import org.fest.swing.hierarchy.ExistingHierarchy;
import org.fest.swing.timing.Pause;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Created by jetbrains on 09/09/16.
*/
public class AdvancedRobot extends BasicRobot {
public AdvancedRobot(){
super((Object)null, new ExistingHierarchy());
}
AdvancedRobot(@Nullable Object screenLockOwner,
@Nonnull ComponentHierarchy hierarchy) {
super(screenLockOwner, hierarchy);
}
volatile boolean isIdle = false;
@Override
public void waitForIdle() {
//do not wait for idle
//if (!myKeyboardBusy && myKeyEventDispatcher.isReady()) return;
//
//isIdle = false;
//
//this.waitIfNecessary();
//IdeEventQueue.getInstance().doWhenReady(new Runnable() {
// @Override
// public void run() {
// isIdle = true;
// }
//});
//
//assert !EventQueue.isDispatchThread();
//Pause.pause(new Condition("Waiting for idle...") {
// @Override
// public boolean test() {
// return isIdle;
// }
//}, 120000L);
}
private void waitIfNecessary() {
int delayBetweenEvents = settings().delayBetweenEvents();
int eventPostingDelay = settings().eventPostingDelay();
if(eventPostingDelay > delayBetweenEvents) {
Pause.pause((long)(eventPostingDelay - delayBetweenEvents));
}
}
}
@@ -3,7 +3,7 @@
org.jetbrains.idea.svn.*
org.jetbrains.idea.svn16.*
com.intellij.util.net.ssl.*
com.intellij.tasks.live.*
com.intellij.tasks.integration.live.*
[GIT_TESTS]
git4idea.*
@@ -86,7 +86,6 @@ com.android.tools.idea.editors.AndroidGeneratedSourcesFilterTest
com.android.tools.idea.editors.theme.ThemeEditorStyleTest
com.android.tools.idea.editors.theme.ThemeEditorUtilsTest
com.android.tools.idea.editors.theme.ConfiguredThemeEditorStyleTest
com.android.tools.idea.editors.theme.ResolutionUtilsTest
com.android.tools.idea.editors.theme.qualifiers.QualifierUtilsTest
com.android.tools.idea.gradle.IdeaAndroidProjectTest
com.android.tools.idea.gradle.project.AndroidGradleProjectImportingTest
@@ -127,8 +126,6 @@ com.android.tools.idea.gradle.service.notification.errors.UnknownHostErrorHandle
com.android.tools.idea.wizard.AsyncValidatorTest
org.jetbrains.jps.android.AndroidBuilderTest
com.android.tools.idea.gradle.service.notification.hyperlink.CustomNotificationListenerTest
com.android.repository.impl.installer.BasicInstallerTest
org.jetbrains.android.AndroidLintTest
[GRADLE_INTEGRATION_TESTS]
org.jetbrains.plugins.gradle.importing.*
@@ -141,6 +138,3 @@ org.jetbrains.idea.maven.project.importing.*
org.jetbrains.idea.maven.compiler.*
org.jetbrains.idea.maven.dom.*
org.jetbrains.idea.maven.indices.*
[TASKS_INTEGRATION_TESTS]
com.intellij.tasks.integration.*
@@ -1,3 +0,0 @@
<component name="CopyrightManager">
<settings default="" />
</component>
@@ -13,37 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fest.swing.core;
package com.intellij.notification;
import org.fest.swing.hierarchy.ComponentHierarchy;
import org.fest.swing.hierarchy.ExistingHierarchy;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAwareAction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Sergey Karashevich
* @author Alexander Lobas
*/
public class FastRobot extends BasicRobot {
public FastRobot(){
super((Object)null, new ExistingHierarchy());
public abstract class NotificationAction extends DumbAwareAction {
public NotificationAction(@Nullable String text) {
super(text);
}
FastRobot(@Nullable Object screenLockOwner,
@NotNull ComponentHierarchy hierarchy) {
super(screenLockOwner, hierarchy);
}
volatile boolean isIdle = false;
@Override
public void waitForIdle() {
//do not wait for idle
public void actionPerformed(AnActionEvent e) {
actionPerformed(e, Notification.get(e));
}
public void superWaitForIdle(){
super.waitForIdle();
}
}
public abstract void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification);
}
@@ -771,11 +771,8 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
saveSettings();
if (allowListenersToCancel && !canExit()) {
return false;
}
final boolean success = disposeSelf(allowListenersToCancel);
boolean success = disposeSelf(!force);
if (!success || isUnitTestMode() || Boolean.getBoolean("idea.test.guimode")) {
if (Boolean.getBoolean("idea.test.guimode")) {
IdeaApplication.getInstance().shutdown();
@@ -15,12 +15,12 @@
*/
import com.intellij.execution.process.ProcessIOExecutorService;
import com.intellij.ide.IdeEventQueue;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.testFramework.LeakHunter;
@@ -37,6 +37,7 @@ import java.util.concurrent.TimeUnit;
/**
* This must be the last test.
*
* @author max
*/
@SuppressWarnings("JUnitTestClassNamingConvention")
@@ -48,7 +49,8 @@ public class _LastInSuiteTest extends TestCase {
@Override
public void run() {
try {
LightPlatformTestCase.initApplication(); // in case nobody cared to init. LightPlatformTestCase.disposeApplication() would not work otherwise.
LightPlatformTestCase
.initApplication(); // in case nobody cared to init. LightPlatformTestCase.disposeApplication() would not work otherwise.
}
catch (RuntimeException e) {
throw e;
@@ -56,64 +58,64 @@ public class _LastInSuiteTest extends TestCase {
catch (Exception e) {
throw new RuntimeException(e);
}
// disposes default projects too
PlatformTestUtil.cleanupAllProjects();
ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication();
System.out.println(application.writeActionStatistics());
System.out.println(ActionUtil.ActionPauses.STAT.statistics());
System.out.println(((AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService()).statistics());
System.out.println("ProcessIOExecutorService threads created: " +
((ProcessIOExecutorService)ProcessIOExecutorService.INSTANCE).getThreadCounter());
application.setDisposeInProgress(true);
LightPlatformTestCase.disposeApplication();
UIUtil.dispatchAllInvocationEvents();
}
});
// disposes default projects too
PlatformTestUtil.cleanupAllProjects();
ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication();
System.out.println(application.writeActionStatistics());
System.out.println(ActionUtil.ActionPauses.STAT.statistics());
System.out.println(((AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService()).statistics());
System.out.println("ProcessIOExecutorService threads created: "+((ProcessIOExecutorService)ProcessIOExecutorService.INSTANCE).getThreadCounter());
application.setDisposeInProgress(true);
LightPlatformTestCase.disposeApplication();
UIUtil.dispatchAllInvocationEvents();
try {
LeakHunter.checkProjectLeak();
Disposer.assertIsEmpty(true);
}
});
catch (AssertionError | Exception e) {
captureMemorySnapshot();
throw e;
}
try {
Disposer.assertIsEmpty(true);
}
catch (AssertionError e) {
captureMemorySnapshot();
throw e;
}
catch (Exception e) {
captureMemorySnapshot();
throw e;
}
} else{
final Application application = ApplicationManager.getApplication();
try {
LeakHunter.checkProjectLeak();
Disposer.assertIsEmpty(true);
application.invokeAndWait(new Runnable() {
@Override
public void run() {
IdeEventQueue.getInstance().flushQueue();
((ApplicationImpl)application).exit(true, true, false, false);
}
}, ModalityState.any());
ShutDownTracker.getInstance().waitFor(100, TimeUnit.SECONDS);
}
}
catch (AssertionError | Exception e) {
captureMemorySnapshot();
throw e;
}
try {
Disposer.assertIsEmpty(true);
}
catch (AssertionError e) {
captureMemorySnapshot();
throw e;
}
catch (Exception e) {
captureMemorySnapshot();
throw e;
}
else {
final Application application = ApplicationManager.getApplication();
application.invokeAndWait(new Runnable() {
@Override
public void run() {
IdeEventQueue.getInstance().flushQueue();
((ApplicationImpl)application).exit(true, true, false, false);
}
}, ModalityState.any());
ShutDownTracker.getInstance().waitFor(100, TimeUnit.SECONDS);
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public void testStatistics () throws Exception {
if (_FirstInSuiteTest.suiteStarted != 0) {
long testSuiteDuration = System.nanoTime() - _FirstInSuiteTest.suiteStarted;
System.out.println(String.format("##teamcity[buildStatisticValue key='ideaTests.totalTimeMs' value='%d']",
testSuiteDuration / 1000000));
}
LightPlatformTestCase.reportTestExecutionStatistics();
}
}
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public void testStatistics() throws Exception {
if (_FirstInSuiteTest.suiteStarted != 0) {
long testSuiteDuration = System.nanoTime() - _FirstInSuiteTest.suiteStarted;
System.out.println(String.format("##teamcity[buildStatisticValue key='ideaTests.totalTimeMs' value='%d']",
testSuiteDuration / 1000000));
}
LightPlatformTestCase.reportTestExecutionStatistics();
}
private static void captureMemorySnapshot() {
try {
@@ -123,6 +125,7 @@ public class _LastInSuiteTest extends TestCase {
System.out.println("Memory snapshot captured");
}
}
catch (Exception ignored) { }
catch (Exception ignored) {
}
}
}
@@ -1,11 +1,11 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.driver;
package com.intellij.testGuiFramework.driver;
import com.intellij.ui.SearchTextField;
import org.fest.swing.annotation.RunsInEDT;
@@ -13,14 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.finder;
package com.intellij.testGuiFramework.finder;
import com.intellij.openapi.wm.impl.StripeButton;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.finder.ComponentFinderTemplate;
import org.fest.swing.finder.DialogFinder;
import org.fest.swing.fixture.AbstractComponentFixture;
import org.fest.swing.fixture.JToggleButtonFixture;
import javax.annotation.Nonnegative;
@@ -70,8 +70,8 @@ public class ActionLinkFixture extends JComponentFixture<ActionLinkFixture, Acti
@NotNull
public static ActionLinkFixture findActionLinkByName(@NotNull final String actionName,
@NotNull final Robot robot,
@NotNull final Container container) {
@NotNull final Robot robot,
@NotNull final Container container) {
final Ref<ActionLink> actionLinkRef = new Ref<ActionLink>();
pause(new Condition("Find ActionLink with name '" + actionName + "'") {
@Override
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import org.fest.swing.core.Robot;
import org.fest.swing.driver.ComponentDriver;
@@ -23,9 +23,8 @@ import org.jetbrains.annotations.Nullable;
import java.awt.*;
/**
* Created by karashevich on 30/05/16.
* @author Sergey Karashevich
*/
public class ComponentFixture<S, C extends Component> extends AbstractComponentFixture<S, C, ComponentDriver> {
public ComponentFixture(@NotNull Class<S> selfType, @NotNull Robot robot, @NotNull Class<? extends C> type) {
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import org.jetbrains.annotations.NotNull;
@@ -859,7 +859,7 @@ public class EditorFixture {
ComponentDriver driver = new ComponentDriver(robot);
System.out.println("Invoking editor action " + actionId + " via shortcut "
+ KeyEvent.getKeyModifiersText(firstKeyStroke.getModifiers())
+ KeyEvent.getKeyText(firstKeyStroke.getKeyCode()));
+ KeyEvent.getKeyText(firstKeyStroke.getKeyCode()));
driver.pressAndReleaseKey(component, firstKeyStroke.getKeyCode(), new int[]{firstKeyStroke.getModifiers()});
KeyStroke secondKeyStroke = cs.getSecondKeyStroke();
if (secondKeyStroke != null) {
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.ui.HyperlinkLabel;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.intellij.ide.OccurenceNavigatorSupport;
import com.intellij.ui.content.Content;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.intellij.ide.projectView.impl.ProjectViewTree;
import com.intellij.ide.util.newProjectWizard.FrameworkSupportNode;
@@ -35,7 +35,7 @@ import java.awt.*;
import java.util.Vector;
/**
* Created by karashevich on 01/06/16.
* @author Sergey Karashevich
*/
public class FrameworksTreeFixture {
@@ -479,14 +479,14 @@ public class IdeFrameFixture extends ComponentFixture<IdeFrameFixture, IdeFrameI
@NotNull
public IdeFrameFixture waitForBackgroundTasksToFinish() {
Pause.pause(new Condition("Background tasks to finish") {
@Override
public boolean test() {
ProgressManager progressManager = ProgressManager.getInstance();
return !progressManager.hasModalProgressIndicator() &&
!progressManager.hasProgressIndicator() &&
!progressManager.hasUnsafeProgressIndicator();
}
}
@Override
public boolean test() {
ProgressManager progressManager = ProgressManager.getInstance();
return !progressManager.hasModalProgressIndicator() &&
!progressManager.hasProgressIndicator() &&
!progressManager.hasUnsafeProgressIndicator();
}
}
, GuiTestUtil.LONG_TIMEOUT);
robot().waitForIdle();
return this;
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.google.common.collect.Lists;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurableGroup;
import com.intellij.openapi.options.newEditor.SettingsDialog;
@@ -28,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
@@ -52,7 +52,7 @@ public class IdeSettingsDialogFixture extends IdeaDialogFixture<SettingsDialog>
@NotNull
public List<String> getProjectSettingsNames() {
List<String> names = Lists.newArrayList();
List<String> names = new ArrayList<>();
JPanel optionsEditor = field("myEditor").ofType(JPanel.class).in(getDialogWrapper()).get();
assertNotNull(optionsEditor);
@@ -76,7 +76,7 @@ public class IdeSettingsDialogFixture extends IdeaDialogFixture<SettingsDialog>
@NotNull
private static List<JComponent> findComponentsOfType(@NotNull JComponent parent, @NotNull String typeName) {
List<JComponent> result = Lists.newArrayList();
List<JComponent> result = new ArrayList<>();
findComponentsOfType(typeName, result, parent);
return result;
}
@@ -42,8 +42,8 @@ public abstract class IdeaDialogFixture<T extends DialogWrapper> extends Compone
protected static <T extends DialogWrapper> T getDialogWrapperFrom(@NotNull JDialog dialog, Class<T> dialogWrapperType) {
try {
WeakReference<DialogWrapper> dialogWrapperRef = field("myDialogWrapper").ofType(new TypeRef<WeakReference<DialogWrapper>>() {})
.in(dialog)
.get();
.in(dialog)
.get();
assertNotNull(dialogWrapperRef);
DialogWrapper wrapper = dialogWrapperRef.get();
if (dialogWrapperType.isInstance(wrapper)) {
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.google.common.collect.Lists;
import com.intellij.codeInspection.ui.InspectionTree;
import com.intellij.codeInspection.ui.InspectionTreeNode;
import com.intellij.openapi.project.Project;
@@ -25,6 +24,7 @@ import org.fest.swing.edt.GuiQuery;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -66,7 +66,7 @@ public class InspectionsFixture extends ToolWindowFixture {
// The exact order of the results sometimes varies so sort the children alphabetically
// instead to ensure stable test output
List<InspectionTreeNode> children = Lists.newArrayListWithExpectedSize(node.getChildCount());
List<InspectionTreeNode> children = new ArrayList<>(node.getChildCount());
for (int i = 0, n = node.getChildCount(); i < n; i++) {
children.add((InspectionTreeNode)node.getChildAt(i));
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import org.fest.swing.core.Robot;
import org.fest.swing.driver.JComponentDriver;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.intellij.openapi.roots.JavadocOrderRootType;
import com.intellij.openapi.roots.libraries.Library;
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.google.common.collect.Lists;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
@@ -27,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -71,7 +71,7 @@ class MenuFixture {
int segmentCount = path.length;
// We keep the list of previously found pop-up menus, so we don't look for menu items in the same pop-up more than once.
List<JPopupMenu> previouslyFoundPopups = Lists.newArrayList();
List<JPopupMenu> previouslyFoundPopups = new ArrayList<>();
Container root = myContainer;
for (int i = 0; i < segmentCount; i++) {
@@ -37,19 +37,19 @@ class MessageDialogFixture extends IdeaDialogFixture<DialogWrapper> implements M
JDialog dialog = waitUntilFound(robot, null, new GenericTypeMatcher<JDialog>(JDialog.class) {
@Override
protected boolean isMatching(@NotNull JDialog dialog) {
if (!title.equals(dialog.getTitle()) || !dialog.isShowing()) {
return false;
}
DialogWrapper wrapper = getDialogWrapperFrom(dialog, DialogWrapper.class);
if (wrapper != null) {
String typeName = Messages.class.getName() + "$MessageDialog";
if (typeName.equals(wrapper.getClass().getName())) {
wrapperRef.set(wrapper);
return true;
}
}
if (!title.equals(dialog.getTitle()) || !dialog.isShowing()) {
return false;
}
DialogWrapper wrapper = getDialogWrapperFrom(dialog, DialogWrapper.class);
if (wrapper != null) {
String typeName = Messages.class.getName() + "$MessageDialog";
if (typeName.equals(wrapper.getClass().getName())) {
wrapperRef.set(wrapper);
return true;
}
}
return false;
}
}, LONG_TIMEOUT);
return new MessageDialogFixture(robot, dialog, wrapperRef.get());
}
@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.intellij.ide.errorTreeView.*;
import com.intellij.openapi.externalSystem.service.notification.EditableNotificationMessageElement;
import com.intellij.openapi.externalSystem.service.notification.NotificationMessageElement;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.pom.Navigatable;
import com.intellij.ui.content.Content;
@@ -264,8 +263,8 @@ public class MessagesToolWindowFixture extends ToolWindowFixture {
assertThat(endBodyIndex).isGreaterThan(startBodyIndex);
String body = html.substring(startBodyIndex + 6 /* 6 = length of '<body>' */, endBodyIndex);
List<String> lines = Splitter.on('\n').omitEmptyStrings().trimResults().splitToList(body);
body = Joiner.on(' ').join(lines);
List<String> lines = StringUtil.split(body, "\n", false, true);
body = StringUtil.join(lines, " ");
return body;
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import org.fest.swing.core.ComponentFinder;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import org.jetbrains.annotations.NotNull;
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.intellij.tests.gui.driver.SearchTextFieldDriver;
import com.intellij.testGuiFramework.driver.SearchTextFieldDriver;
import com.intellij.ui.SearchTextField;
import org.fest.swing.core.Robot;
import org.fest.swing.fixture.AbstractJComponentFixture;
@@ -104,34 +104,3 @@ public class SelectSdkDialogFixture implements ContainerFixture<JDialog>{
return myRobot;
}
}
//extends IdeaDialogFixture<SelectSdkDialog> {
//@NotNull
//public static SelectSdkDialogFixture find(@NotNull Robot robot) {
// return new SelectSdkDialogFixture(robot, find(robot, SelectSdkDialog.class));
//}
//
//private SelectSdkDialogFixture(@NotNull Robot robot, @NotNull DialogAndWrapper<SelectSdkDialog> dialogAndWrapper) {
// super(robot, dialogAndWrapper);
//}
//
//@NotNull
//public SelectSdkDialogFixture setJdkPath(@NotNull final File path) {
// final JLabel label = robot().finder().find(target(), JLabelMatcher.withText("Select Java JDK:").andShowing());
// execute(new GuiTask() {
// @Override
// protected void executeInEDT() throws Throwable {
// Component textField = label.getLabelFor();
// assertThat(textField).isInstanceOf(JTextField.class);
// ((JTextField)textField).setText(path.getPath());
// }
// });
// return this;
//}
//
//@NotNull
//public SelectSdkDialogFixture clickOk() {
// findAndClickOkButton(this);
// return this;
//}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.intellij.execution.testframework.AbstractTestProxy;
import com.intellij.execution.testframework.TestFrameworkRunningModel;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures;
package com.intellij.testGuiFramework.fixtures;
import com.intellij.openapi.wm.impl.welcomeScreen.FlatWelcomeFrame;
import org.fest.swing.core.Robot;
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures.newProjectWizard;
package com.intellij.testGuiFramework.fixtures.newProjectWizard;
import com.intellij.tests.gui.fixtures.JComponentFixture;
import com.intellij.testGuiFramework.fixtures.JComponentFixture;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.core.Robot;
import org.fest.swing.driver.JTextComponentDriver;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures.newProjectWizard;
package com.intellij.testGuiFramework.fixtures.newProjectWizard;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures.newProjectWizard;
package com.intellij.testGuiFramework.fixtures.newProjectWizard;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import org.fest.swing.core.Robot;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.fixtures.newProjectWizard;
package com.intellij.testGuiFramework.fixtures.newProjectWizard;
import org.fest.swing.core.Robot;
import org.jetbrains.annotations.NotNull;
@@ -18,12 +18,11 @@ package com.intellij.testGuiFramework.framework;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.WindowManagerImpl;
@@ -101,12 +100,6 @@ public abstract class GuiTestBase {
Application application = ApplicationManager.getApplication();
assertNotNull(application); // verify that we are using the IDE's ClassLoader.
// There is a race condition between reloading the configuration file after file deletion detected and the serialization of IDEA model
// we just customized so that modules can't be loaded correctly.
// This is a hack to prevent StoreAwareProjectManager from doing any reloading during test.
ProjectManagerEx.getInstanceEx().blockReloadingProjectOnExternalChanges();
refreshFiles();
}
@After
@@ -131,7 +124,6 @@ public abstract class GuiTestBase {
}
}
}
ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges();
}
@NotNull
@@ -242,7 +234,9 @@ public abstract class GuiTestBase {
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
ProjectUtil.openOrImport(projectDir.getPath(), null, false);
TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> {
ProjectUtil.openOrImport(projectDir.getPath(), null, false);
});
}
});
}
@@ -329,18 +323,6 @@ public abstract class GuiTestBase {
return IdeFrameFixture.find(myRobot, null, null);
}
protected void refreshFiles() {
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
LocalFileSystem.getInstance().refresh(false /* synchronous */);
}
});
}
});
}
}
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
package com.intellij.testGuiFramework.framework;
import com.google.common.collect.Maps;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
@@ -24,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import static org.fest.reflect.core.Reflection.method;
@@ -57,9 +57,9 @@ class GuiTestConfigurator {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?> target = classLoader.loadClass(GuiTestConfigurator.class.getCanonicalName());
Map<String, Object> testConfig = method("extractTestConfiguration").withReturnType(new TypeRef<Map<String, Object>>() {})
.withParameterTypes(Method.class)
.in(target)
.invoke(testMethod);
.withParameterTypes(Method.class)
.in(target)
.invoke(testMethod);
assertNotNull(testConfig);
return new GuiTestConfigurator(testConfig, testMethod.getName(), test, classLoader);
}
@@ -67,18 +67,16 @@ class GuiTestConfigurator {
// Invoked using reflection and the IDE's ClassLoader.
@NotNull
private static Map<String, Object> extractTestConfiguration(@NotNull Method testMethod) {
Map<String, Object> config = Maps.newHashMap();
Map<String, Object> config = new HashMap<String, Object>();
IdeGuiTest guiTest = testMethod.getAnnotation(IdeGuiTest.class);
if (guiTest != null) {
config.put(CLOSE_PROJECT_BEFORE_EXECUTION_KEY, guiTest.closeProjectBeforeExecution());
config.put(RUN_WITH_MINIMUM_JDK_VERSION_KEY, guiTest.runWithMinimumJdkVersion());
config.put(RETRY_COUNT_KEY, guiTest.retryCount());
}
IdeGuiTestSetup guiTestSetup = testMethod.getDeclaringClass().getAnnotation(IdeGuiTestSetup.class);
if (guiTestSetup != null) {
config.put(SKIP_SOURCE_GENERATION_ON_SYNC_KEY, guiTestSetup.skipSourceGenerationOnSync());
config.put(TAKE_SCREENSHOT_ON_TEST_FAILURE_KEY, guiTestSetup.takeScreenshotOnTestFailure());
}
//TODO: replace with system properties (or VM options)
config.put(SKIP_SOURCE_GENERATION_ON_SYNC_KEY, false);
config.put(TAKE_SCREENSHOT_ON_TEST_FAILURE_KEY, true);
return config;
}
@@ -150,9 +148,9 @@ class GuiTestConfigurator {
Class<?> target = loadMyClassWithTestClassLoader();
Class<?> javaSdkVersionClass = myClassLoader.loadClass(JavaSdkVersion.class.getCanonicalName());
Boolean hasRequiredJdk = method("hasRequiredJdk").withReturnType(boolean.class)
.withParameterTypes(javaSdkVersionClass)
.in(target)
.invoke(myMinimumJdkVersion);
.withParameterTypes(javaSdkVersionClass)
.in(target)
.invoke(myMinimumJdkVersion);
assertNotNull(hasRequiredJdk);
if (!hasRequiredJdk) {
String jdkVersion = method("getDescription").withReturnType(String.class).in(myMinimumJdkVersion).invoke();
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.framework;
package com.intellij.testGuiFramework.framework;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
@@ -134,7 +134,6 @@ public class IdeTestApplication {
ourInstance = this;
pluginManagerStart(args);
mainMain();
myIdeClassLoader = createClassLoader();
@@ -235,11 +234,6 @@ public class IdeTestApplication {
initDefaultLAF();
}
private static void mainMain() {
// Duplicates what Main#main does.
method("installPatch").in(Main.class).invoke();
}
public void dispose() {
disposeInstance();
}
@@ -46,7 +46,7 @@ public class MethodInvoker extends Statement {
@Override
public void evaluate() throws Throwable {
if (myTestConfigurator.shouldSkipTest()) {
//Message already printed in console.
//Message already printed in console.
return;
}
String testFqn = getTestFqn();
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.matcher;
package com.intellij.testGuiFramework.matcher;
import org.fest.swing.core.GenericTypeMatcher;
import org.jetbrains.annotations.NotNull;
@@ -18,6 +18,7 @@ package com.intellij.testGuiFramework.script
import com.intellij.internal.inspector.UiDropperActionExtension
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.ui.components.JBList
import org.fest.swing.core.BasicRobot
import java.awt.Component
import java.awt.Container
@@ -65,7 +66,7 @@ class ScriptRecorder() : AnAction(), UiDropperActionExtension {
else
write(Templates.findJTextFieldByLabel(label.text))
}
is com.intellij.ui.components.JBList -> {
is JBList<*> -> {
val itemName = e.dataContext.getData("ItemName") as String
if (isPopupList(cmp))
write(Templates.clickPopupItem(itemName))
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.tests.gui.script
package com.intellij.testGuiFramework.script
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.AnAction
@@ -27,7 +27,7 @@ class ScriptRunnerAction() : AnAction(){
override fun actionPerformed(e: AnActionEvent?) {
val myPackage = "com.intellij.tests.gui.test"
val packagePath = myPackage.replace(".", "/")
val packagePath = myPackage.replace("", "/")
val testFolder = this.javaClass.classLoader.getResource(packagePath)
val testFiles = File(testFolder.file).listFiles().filter { !it.name.contains("$") } //remove inlined classes
val actionManager = ActionManager.getInstance()
@@ -35,7 +35,7 @@ class ScriptRunnerAction() : AnAction(){
testFiles.forEach {
val testName = it.name.substring(0, it.name.indexOf('.'))
val genId = "guiTest." + testName
val script = ScriptAction(testName)
val script = com.intellij.testGuiFramework.script.ScriptAction(testName)
if (actionManager.getAction(genId) != null)
actionManager.unregisterAction(genId)
actionManager.registerAction(genId, script)
@@ -0,0 +1,48 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fest.swing.core;
import org.fest.swing.hierarchy.ComponentHierarchy;
import org.fest.swing.hierarchy.ExistingHierarchy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Sergey Karashevich
*/
public class FastRobot extends BasicRobot {
public FastRobot(){
super((Object)null, new ExistingHierarchy());
}
FastRobot(@Nullable Object screenLockOwner,
@NotNull ComponentHierarchy hierarchy) {
super(screenLockOwner, hierarchy);
}
@Override
public void waitForIdle() {
//do not wait for idle
}
public void superWaitForIdle(){
super.waitForIdle();
}
}