/* * 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.testGuiFramework.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.testGuiFramework.framework.GuiTestUtil.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); } }