diff --git a/build/org.eclipse.cdt.meson.ui.tests/.classpath b/build/org.eclipse.cdt.meson.ui.tests/.classpath new file mode 100644 index 00000000000..eca7bdba8f0 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/build/org.eclipse.cdt.meson.ui.tests/.project b/build/org.eclipse.cdt.meson.ui.tests/.project new file mode 100644 index 00000000000..3e4a36b9379 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/.project @@ -0,0 +1,28 @@ + + + org.eclipse.cdt.meson.ui.tests + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/build/org.eclipse.cdt.meson.ui.tests/.settings/org.eclipse.jdt.core.prefs b/build/org.eclipse.cdt.meson.ui.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0c68a61dca8 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/build/org.eclipse.cdt.meson.ui.tests/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.meson.ui.tests/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..38493fc052e --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/META-INF/MANIFEST.MF @@ -0,0 +1,24 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Tests +Bundle-SymbolicName: org.eclipse.cdt.meson.ui.tests +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.cdt.meson.core;bundle-version="1.0.0", + org.eclipse.cdt.meson.ui;bundle-version="1.0.0", + org.eclipse.swtbot.junit4_x;bundle-version="2.6.0", + org.junit, + org.eclipse.cdt.core, + org.eclipse.swtbot.eclipse.finder, + org.eclipse.core.resources, + org.eclipse.core.runtime;bundle-version="3.13.0", + org.eclipse.ui;bundle-version="3.109.0", + org.apache.log4j;bundle-version="1.2.15", + org.eclipse.epp.logging.aeri.core;bundle-version="2.0.7", + org.hamcrest.library;bundle-version="1.3.0", + org.eclipse.launchbar.ui;bundle-version="2.2.0", + org.eclipse.launchbar.ui.controls;bundle-version="1.0.1", + org.eclipse.ui.console;bundle-version="3.8.0", + org.eclipse.ui.views;bundle-version="3.9.100", + org.eclipse.ui.views.properties.tabbed;bundle-version="3.8.100" +Import-Package: org.assertj.core.api;version="1.7.1" diff --git a/build/org.eclipse.cdt.meson.ui.tests/about.html b/build/org.eclipse.cdt.meson.ui.tests/about.html new file mode 100644 index 00000000000..d7c511887d6 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/about.html @@ -0,0 +1,24 @@ + + +About + + +

About This Content

+ +

June 22, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/build/org.eclipse.cdt.meson.ui.tests/build.properties b/build/org.eclipse.cdt.meson.ui.tests/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/build/org.eclipse.cdt.meson.ui.tests/pom.xml b/build/org.eclipse.cdt.meson.ui.tests/pom.xml new file mode 100644 index 00000000000..74639d2bc11 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 9.5.0-SNAPSHOT + ../../pom.xml + + + org.eclipse.cdt.cmake.ui.tests + 1.0.0-SNAPSHOT + eclipse-test-plugin + + + + + org.eclipse.tycho + target-platform-configuration + ${tycho-version} + + + + + p2-installable-unit + org.eclipse.cdt.feature.group + 0.0.0 + + + p2-installable-unit + org.eclipse.cdt.cmake.feature.group + 0.0.0 + + + + + + + + \ No newline at end of file diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/AutomatedIntegrationSuite.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/AutomatedIntegrationSuite.java new file mode 100644 index 00000000000..966b40d580f --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/AutomatedIntegrationSuite.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2017, 2018 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - modified for use in Meson testing + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ NewMesonProjectTest.class }) +public class AutomatedIntegrationSuite { + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/NewMesonProjectTest.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/NewMesonProjectTest.java new file mode 100644 index 00000000000..3596726785f --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/NewMesonProjectTest.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2017, 2018 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - modified for Meson testing + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests; + +import static org.eclipse.swtbot.eclipse.finder.matchers.WidgetMatcherFactory.withPartName; +import static org.junit.Assert.assertTrue; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.index.IIndexManager; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.internal.meson.ui.tests.utils.CloseWelcomePageRule; +import org.eclipse.cdt.meson.core.MesonNature; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.epp.logging.aeri.core.ISystemSettings; +import org.eclipse.epp.logging.aeri.core.SendMode; +import org.eclipse.epp.logging.aeri.core.SystemControl; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; +import org.eclipse.swtbot.swt.finder.waits.Conditions; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTableItem; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +@SuppressWarnings("nls") +public class NewMesonProjectTest { + + private static SWTWorkbenchBot bot; + + @ClassRule + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.CDT_PERSPECTIVE_ID); + + @BeforeClass + public static void beforeClass() { + SWTBotPreferences.TIMEOUT = 50000; + SWTBotPreferences.KEYBOARD_LAYOUT = "EN_US"; + bot = new SWTWorkbenchBot(); + } + + @Before + public void before() { + ISystemSettings settings = SystemControl.getSystemSettings(); + settings.setSendMode(SendMode.NEVER); + bot.resetWorkbench(); + + for (SWTBotView view : bot.views(withPartName("Welcome"))) { + view.close(); + } + + } + + @Test(timeout = 120000) + public void createCMakeProject() throws Exception { + // open C++ perspective + if (!"C/C++".equals(bot.activePerspective().getLabel())) { + bot.perspectiveByLabel("C/C++").activate(); + } + + // Activate C/C++ wizard + bot.menu("File").menu("New").menu("C/C++ Project").click(); + bot.shell("New C/C++ Project").activate(); + + // Double click on the template + SWTBotTable templateTable = bot.table(); + bot.getDisplay().syncExec(() -> { + for (int i = 0; i < templateTable.rowCount(); ++i) { + SWTBotTableItem item = templateTable.getTableItem(i); + if ("Meson Project".equals(item.widget.getData(SWTBotPreferences.DEFAULT_KEY))) { + item.doubleClick(); + break; + } + } + }); + + // Select the shell again since magic wizardry happened + SWTBotShell newProjectShell = bot.shell("New Meson Project").activate(); + + // Create the project + String projectName = "MesonTestProj"; + bot.textWithLabel("Project name:").typeText(projectName); + bot.button("Finish").click(); + + newProjectShell.setFocus(); + bot.waitUntil(Conditions.shellCloses(newProjectShell)); + +// return; + +// // Make sure it shows up in Project Explorer + SWTBotView explorer = bot.viewByPartName("Project Explorer"); + explorer.show(); + explorer.setFocus(); + explorer.bot().tree().getTreeItem(projectName).select(); + + + // Make sure the project indexer completes. At that point we're stable. + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + ICProject cproject = CoreModel.getDefault().create(project); + IIndexManager indexManager = CCorePlugin.getIndexManager(); + while (!indexManager.isProjectContentSynced(cproject)) { + Thread.sleep(1000); + } + + // Make sure it has the right nature + assertTrue(project.hasNature(MesonNature.ID)); + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/AbstractSWTBotAssertions.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/AbstractSWTBotAssertions.java new file mode 100644 index 00000000000..4299afb82ee --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/AbstractSWTBotAssertions.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.hamcrest.Matchers.notNullValue; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBot; + +/** + * Custom assertions on a given {@link AbstractSWTBot} widget + * @param + */ +public abstract class AbstractSWTBotAssertions, SWTWidget extends AbstractSWTBot> + extends AbstractAssert { + + protected AbstractSWTBotAssertions(final SWTWidget actual, final Class clazz) { + super(actual, clazz); + } + + @SuppressWarnings("unchecked") + public Assertion isEnabled() { + notNullValue(); + if(!actual.isEnabled()) { + failWithMessage("Expected widget with text '%s (%s)' to be enabled but it was not", actual.getText(), + actual.getToolTipText()); + } + return (Assertion) this; + } + + @SuppressWarnings("unchecked") + public Assertion isNotEnabled() { + notNullValue(); + if(actual.isEnabled()) { + failWithMessage("Expected widget with text '%s (%s)' to be disabled but it was not", actual.getText(), + actual.getToolTipText()); + } + return (Assertion) this; + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ButtonAssertions.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ButtonAssertions.java new file mode 100644 index 00000000000..a960e722a39 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ButtonAssertions.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton; + +/** + * Custom assertions on a given {@link SWTBotButton}. + */ +public class ButtonAssertions extends AbstractSWTBotAssertions { + + protected ButtonAssertions(final SWTBotButton actual) { + super(actual, ButtonAssertions.class); + } + + public static ButtonAssertions assertThat(final SWTBotButton actual) { + return new ButtonAssertions(actual); + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CheckBoxAssertions.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CheckBoxAssertions.java new file mode 100644 index 00000000000..d62d591d790 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CheckBoxAssertions.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.hamcrest.Matchers.notNullValue; + +import org.eclipse.swtbot.swt.finder.widgets.SWTBotCheckBox; + +/** + * Custom assertions on a given {@link SWTBotCheckBox}. + */ +public class CheckBoxAssertions extends AbstractSWTBotAssertions { + + protected CheckBoxAssertions(final SWTBotCheckBox actual) { + super(actual, CheckBoxAssertions.class); + } + + public static CheckBoxAssertions assertThat(final SWTBotCheckBox actual) { + return new CheckBoxAssertions(actual); + } + + public CheckBoxAssertions isChecked() { + notNullValue(); + if(!actual.isChecked()) { + failWithMessage("Expected checkbox with text '%s' to be checked but it was not", actual.getText()); + } + return this; + } + + public CheckBoxAssertions isNotChecked() { + notNullValue(); + if(actual.isChecked()) { + failWithMessage("Expected checkbox with text '%s' to be unchecked but it was not", actual.getText()); + } + return this; + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CloseShellRule.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CloseShellRule.java new file mode 100644 index 00000000000..8722c895037 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CloseShellRule.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; +import org.eclipse.ui.PlatformUI; +import org.junit.rules.ExternalResource; + +/** + * Closes the wizard(s) after each test, if the "Cancel" button is available + */ +public class CloseShellRule extends ExternalResource { + + private final String buttonLabel; + + public CloseShellRule(final String buttonLabel) { + this.buttonLabel = buttonLabel; + } + + @Override + protected void after() { + final SWTWorkbenchBot bot = new SWTWorkbenchBot(); + try { + while (isInDialog(bot) && getButton(bot, this.buttonLabel) != null) { + getButton(bot, this.buttonLabel).click(); + } + + } catch (WidgetNotFoundException e) { + // ignoring + } + } + + private static boolean isInDialog(final SWTWorkbenchBot bot) { + final SWTBotShell activeShell = bot.activeShell(); + final String text = SWTUtils + .syncExec(() -> PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getText()); + final String shellText = activeShell.getText(); + return text != null && !text.equals(shellText); + } + + private static SWTBotButton getButton(final SWTWorkbenchBot bot, final String buttonLabel) { + return bot.button(buttonLabel); + } +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CloseWelcomePageRule.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CloseWelcomePageRule.java new file mode 100644 index 00000000000..7e2a4341cb6 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/CloseWelcomePageRule.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; +import org.junit.rules.ExternalResource; + +/** + * Closes the Welcome page and optionally opens a given perspective + */ +public class CloseWelcomePageRule extends ExternalResource { + + public static final String DOCKER_PERSPECTIVE_ID = "org.eclipse.linuxtools.docker.ui.perspective"; + + public static final String CDT_PERSPECTIVE_ID = "org.eclipse.cdt.ui.CPerspective"; + + public static final String JAVA_PERSPECTIVE_ID = "org.eclipse.jdt.ui.JavaPerspective"; + + /** the Id of the perspective to open. */ + private final String defaultPerspectiveId; + + /** + * Custom constructor with the id of the perspective to open once the + * welcome page was closed. + * + * @param perspectiveId + * the id of the perspective to open. + */ + public CloseWelcomePageRule(final String perspectiveId) { + this.defaultPerspectiveId = perspectiveId; + } + + @Override + protected void before() { + Display.getDefault().syncExec(() -> { + final IWorkbench workbench = PlatformUI.getWorkbench(); + if (workbench.getIntroManager().getIntro() != null) { + workbench.getIntroManager().closeIntro(workbench.getIntroManager().getIntro()); + } + try { + workbench.showPerspective(defaultPerspectiveId, workbench.getActiveWorkbenchWindow()); + } catch (WorkbenchException e) { + e.printStackTrace(); + } + }); + final String PREF_ENABLE_LAUNCHBAR = "enableLaunchBar"; //$NON-NLS-1$ + final String PREF_ENABLE_TARGETSELECTOR = "enableTargetSelector"; //$NON-NLS-1$ + final String PREF_ENABLE_BUILDBUTTON = "enableBuildButton"; //$NON-NLS-1$ + + Display.getDefault().asyncExec(() -> { + final IPreferenceStore store = org.eclipse.launchbar.ui.controls.internal.Activator.getDefault() + .getPreferenceStore(); + store.setValue(PREF_ENABLE_LAUNCHBAR, false); + store.setValue(PREF_ENABLE_TARGETSELECTOR, false); + store.setValue(PREF_ENABLE_BUILDBUTTON, false); + }); + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ComboAssertions.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ComboAssertions.java new file mode 100644 index 00000000000..8833194e2bc --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ComboAssertions.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.hamcrest.Matchers.notNullValue; + +import org.eclipse.swtbot.swt.finder.widgets.SWTBotCheckBox; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotCombo; + +/** + * Custom assertions on a given {@link SWTBotCheckBox}. + */ +public class ComboAssertions extends AbstractSWTBotAssertions { + + protected ComboAssertions(final SWTBotCombo actual) { + super(actual, ComboAssertions.class); + } + + public static ComboAssertions assertThat(final SWTBotCombo actual) { + return new ComboAssertions(actual); + } + + public ComboAssertions itemSelected(final String expectedItem) { + notNullValue(); + if (actual.selectionIndex() < 0) { + failWithMessage("Expected combo to have selection to '%s' but it had none", expectedItem); + } else if (!actual.selection().equals(expectedItem)) { + failWithMessage("Expected combo to have selection to '%s' but it was '%s'", expectedItem, + actual.selection()); + } + return this; + } + + public ComboAssertions indexItemSelected(final int expectedItemIndex) { + notNullValue(); + if (actual.selectionIndex() < 0) { + failWithMessage("Expected combo to have selection index to '%s' but it had none", expectedItemIndex); + } else if (actual.selectionIndex() != expectedItemIndex) { + failWithMessage("Expected combo to have selection index to '%s' but it was '%s'", expectedItemIndex, + actual.selectionIndex()); + } + return this; + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ConsoleViewRule.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ConsoleViewRule.java new file mode 100644 index 00000000000..203c8b5c73e --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ConsoleViewRule.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import org.eclipse.swt.widgets.Display; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.ui.console.IConsoleConstants; +import org.junit.rules.ExternalResource; + +/** + * An {@link ExternalResource} to close the Console view. + */ +public class ConsoleViewRule extends ExternalResource { + + @Override + protected void before() { + Display.getDefault().syncExec(() -> { + final SWTBotView consoleView = SWTUtils.getSWTBotView(new SWTWorkbenchBot(), + IConsoleConstants.ID_CONSOLE_VIEW); + if (consoleView != null) { + consoleView.close(); + } + }); + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/MenuAssertion.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/MenuAssertion.java new file mode 100644 index 00000000000..4dafdfedbc2 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/MenuAssertion.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015, 2016 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.hamcrest.Matchers.notNullValue; + +import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; + +/** + * Custom assertions on a given {@link SWTBotButton}. + */ +public class MenuAssertion extends AbstractSWTBotAssertions { + + protected MenuAssertion(final SWTBotMenu actual) { + super(actual, MenuAssertion.class); + } + + public static MenuAssertion assertThat(final SWTBotMenu actual) { + return new MenuAssertion(actual); + } + + public MenuAssertion isVisible() { + notNullValue(); + if (!actual.isVisible()) { + failWithMessage("Expected menu with text '%s' to be visible but it was not", actual.getText()); + } + return this; + } + + public MenuAssertion isNotVisible() { + notNullValue(); + if (actual.isVisible()) { + failWithMessage("Expected menu with text '%s' to be visible but it was not", actual.getText()); + } + return this; + } +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ProjectExplorerViewRule.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ProjectExplorerViewRule.java new file mode 100644 index 00000000000..024c4860abc --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ProjectExplorerViewRule.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.junit.Rule; +import org.junit.rules.ExternalResource; + +/** + * A JUnit {@link Rule} to open the Project Explorer view. + */ +public class ProjectExplorerViewRule extends ExternalResource { + + private SWTBotView projectExplorerBotView; + + public static final String PROJECT_EXPLORER_VIEW_ID = "org.eclipse.ui.navigator.ProjectExplorer"; + + @Override + protected void before() { + final SWTWorkbenchBot bot = new SWTWorkbenchBot(); + SWTUtils.syncExec(() -> { + try { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .showView(PROJECT_EXPLORER_VIEW_ID); + } catch (PartInitException e) { + e.printStackTrace(); + return null; + } + }); + this.projectExplorerBotView = bot.viewById(PROJECT_EXPLORER_VIEW_ID); + this.projectExplorerBotView.setFocus(); + } + + public SWTBotView getProjectExplorerBotView() { + return this.projectExplorerBotView; + } +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/RadioAssertion.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/RadioAssertion.java new file mode 100644 index 00000000000..f27b18ed7f0 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/RadioAssertion.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.hamcrest.Matchers.notNullValue; + +import org.eclipse.swtbot.swt.finder.widgets.SWTBotRadio; + +/** + * Custom assertions on a given {@link SWTBotRadio}. + */ +public class RadioAssertion extends AbstractSWTBotAssertions { + + protected RadioAssertion(final SWTBotRadio actual) { + super(actual, RadioAssertion.class); + } + + public static RadioAssertion assertThat(final SWTBotRadio actual) { + return new RadioAssertion(actual); + } + + public RadioAssertion isSelected() { + notNullValue(); + if(!actual.isSelected()) { + failWithMessage("Expected checkbox with text '%s' to be checked but it was not", actual.getText()); + } + return this; + } + + public RadioAssertion isNotSelected() { + notNullValue(); + if(actual.isSelected()) { + failWithMessage("Expected checkbox with text '%s' to be unchecked but it was not", actual.getText()); + } + return this; + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTBotTreeItemAssertions.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTBotTreeItemAssertions.java new file mode 100644 index 00000000000..3bafb926768 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTBotTreeItemAssertions.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.hamcrest.Matchers.notNullValue; + +import org.assertj.core.api.Assertions; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; + +/** + * + */ +public class SWTBotTreeItemAssertions extends AbstractSWTBotAssertions { + + protected SWTBotTreeItemAssertions(final SWTBotTreeItem actual) { + super(actual, SWTBotTreeItemAssertions.class); + } + + public static SWTBotTreeItemAssertions assertThat(final SWTBotTreeItem containerPortsTreeItem) { + return new SWTBotTreeItemAssertions(containerPortsTreeItem); + } + + public SWTBotTreeItemAssertions isExpanded() { + notNullValue(); + if(!actual.isExpanded()) { + failWithMessage("Expected tree item %s to be expanded but it was not.", actual.getText()); + } + return this; + } + + /** + * Checks the number of items and also verifies that each item has an images and a text + * @param expectedCount + * @return + */ + public SWTBotTreeItemAssertions hasChildItems(final int expectedCount) { + notNullValue(); + if(actual.getItems().length != expectedCount) { + failWithMessage("Expected tree item %s to be have %s items but it had %s.", actual.getText(), expectedCount, actual.getItems().length); + } + for (SWTBotTreeItem swtBotTreeItem : actual.getItems()) { + final String treeItemText = SWTUtils.syncExec(() -> swtBotTreeItem.getText()); + final Image treeItemWidgetImage = SWTUtils.syncExec(() -> swtBotTreeItem.widget.getImage()); + Assertions.assertThat(treeItemText).isNotNull(); + Assertions.assertThat(treeItemWidgetImage).isNotNull(); + } + return this; + } + + public SWTBotTreeItemAssertions hasText(final String expectedText) { + notNullValue(); + if(!actual.getText().equals(expectedText)) { + failWithMessage("Expected node to have text %s but it was %s", expectedText, actual.getText()); + } + return this; + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTBotViewRule.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTBotViewRule.java new file mode 100644 index 00000000000..1edfaae9386 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTBotViewRule.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.PlatformUI; +import org.junit.Assert; +import org.junit.rules.ExternalResource; + +/** + * + */ +public class SWTBotViewRule extends ExternalResource { + + private final SWTWorkbenchBot bot = new SWTWorkbenchBot(); + + private final String viewId; + + private SWTBotView botView = null; + + private IViewPart view = null; + + public SWTBotViewRule(final String viewId) { + this.viewId = viewId; + } + + @Override + protected void before() { + SWTUtils.asyncExec(() -> { + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(this.viewId); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail("Failed to open view with id '" + this.viewId + "': " + e.getMessage()); + } + }); + this.botView = this.bot.viewById(this.viewId); + this.botView.show(); + this.view = this.botView.getViewReference().getView(true); + } + + public SWTBotView bot() { + return this.botView; + } + + @SuppressWarnings("unchecked") + public T view() { + return (T) view; + } + + public void close() { + this.botView.close(); + } +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTUtils.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTUtils.java new file mode 100644 index 00000000000..86dfff27b38 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/SWTUtils.java @@ -0,0 +1,508 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.assertj.core.api.Assertions.fail; + +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException; +import org.eclipse.swtbot.swt.finder.finders.ContextMenuHelper; +import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; +import org.eclipse.swtbot.swt.finder.results.Result; +import org.eclipse.swtbot.swt.finder.results.VoidResult; +import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBot; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTableItem; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; +import org.eclipse.ui.console.IConsoleConstants; +import org.eclipse.ui.progress.UIJob; +import org.junit.Assert; +import org.junit.ComparisonFailure; + +/** + * Utility class for SWT + */ +public class SWTUtils { + + /** + * Calls synchronously the given {@link Supplier} in the + * default Display and returns the result + * + * @param supplier + * the Supplier to call + * @return the supplier's result + */ + public static V syncExec(final Supplier supplier) { + final Queue result = new ArrayBlockingQueue<>(1); + Display.getDefault().syncExec(() -> result.add(supplier.get())); + return result.poll(); + } + + /** + * Executes synchronously the given {@link Runnable} in the + * default Display + * + * @param runnable + * the {@link Runnable} to execute + */ + public static void syncExec(final Runnable runnable) { + Display.getDefault().syncExec(runnable); + } + + /** + * Executes synchronously the given {@link Runnable} in the + * default Display. The given {@link Runnable} is ran into a rapping + * {@link Runnable} that will catch the {@link ComparisonFailure} that may + * be raised during an assertion. + * + * @param runnable + * the {@link Runnable} to execute + * @throws ComparisonFailure + * if an assertion failed. + * @throws SWTException + * if an {@link SWTException} occurred + */ + public static void syncAssert(final Runnable runnable) throws SWTException, ComparisonFailure { + final Queue failure = new ArrayBlockingQueue<>(1); + final Queue swtException = new ArrayBlockingQueue<>(1); + Display.getDefault().syncExec(() -> { + try { + runnable.run(); + } catch (ComparisonFailure e1) { + failure.add(e1); + } catch (SWTException e2) { + swtException.add(e2); + } + }); + if (!failure.isEmpty()) { + throw failure.poll(); + } + if (!swtException.isEmpty()) { + throw swtException.poll(); + } + } + + /** + * Executes the given {@link Runnable} asynchronously in + * the default {@link Display} and waits until all jobs are done before + * completing. + * + * @param runnable + * @throws InterruptedException + */ + public static void asyncExec(final Runnable runnable) { + asyncExec(runnable, true); + } + + /** + * Executes the given {@link Runnable} asynchronously in + * the default {@link Display} and waits until all jobs are done before + * completing. + * + * @param runnable + * the {@link Runnable} to execute + * @param waitForJobsToComplete + * boolean flag to indicate if the method should wait for all + * jobs to complete before finishing + * @throws InterruptedException + */ + public static void asyncExec(final Runnable runnable, final boolean waitForJobsToComplete) { + final Queue failure = new ArrayBlockingQueue<>(1); + final Queue swtException = new ArrayBlockingQueue<>(1); + Display.getDefault().asyncExec(() -> { + try { + runnable.run(); + } catch (ComparisonFailure e1) { + failure.add(e1); + } catch (SWTException e2) { + swtException.add(e2); + } + }); + if (waitForJobsToComplete) { + waitForJobsToComplete(); + } + if (!failure.isEmpty()) { + throw failure.poll(); + } + if (!swtException.isEmpty()) { + throw swtException.poll(); + } + } + + /** + * Waits for all {@link Job} to complete. + * + * @throws InterruptedException + */ + public static void waitForJobsToComplete() { + wait(1, TimeUnit.SECONDS); + while (!Job.getJobManager().isIdle()) { + wait(1, TimeUnit.SECONDS); + } + } + + + /** + * @param viewBot + * the {@link SWTBotView} containing the {@link Tree} to traverse + * @param paths + * the node path in the {@link SWTBotTree} associated with the + * given {@link SWTBotView} + * @return the first {@link SWTBotTreeItem} matching the given node names + */ + public static SWTBotTreeItem getTreeItem(final SWTBotView viewBot, final String... paths) { + final SWTBotTree tree = viewBot.bot().tree(); + return getTreeItem(tree.getAllItems(), paths); + } + + /** + * + * @param parentTreeItem + * the parent tree item from which to start + * @param paths + * the relative path to the item to return + * @return the {@link SWTBotTreeItem} that matches the given path from the + * given parent tree item + */ + public static SWTBotTreeItem getTreeItem(final SWTBotTreeItem parentTreeItem, final String... paths) { + if (paths.length == 1) { + return getTreeItem(parentTreeItem, paths[0]); + } + final String[] remainingPaths = new String[paths.length - 1]; + System.arraycopy(paths, 1, remainingPaths, 0, paths.length - 1); + return getTreeItem(getTreeItem(parentTreeItem, paths[0]), remainingPaths); + } + + /** + * Returns the first child node in the given parent tree item whose text + * matches (ie, begins with) the given path argument. + * + * @param parentTree + * the parent tree item + * @param path + * the text of the node that should match + * @return the first matching node or null if none could be + * found + */ + public static SWTBotTreeItem getTreeItem(final SWTBotTree parentTree, final String path) { + for (SWTBotTreeItem child : parentTree.getAllItems()) { + if (child.getText().startsWith(path)) { + return child; + } + } + return null; + } + + /** + * Returns the first child node in the given parent tree item whose text + * matches (ie, begins with) the given path argument. + * + * @param parentTreeItem + * the parent tree item + * @param path + * the text of the node that should match + * @return the first matching node or null if none could be + * found + */ + public static SWTBotTreeItem getTreeItem(final SWTBotTreeItem parentTreeItem, final String path) { + for (SWTBotTreeItem child : parentTreeItem.getItems()) { + if (child.getText().startsWith(path)) { + return child; + } + } + return null; + } + + private static SWTBotTreeItem getTreeItem(final SWTBotTreeItem[] treeItems, final String[] paths) { + final SWTBotTreeItem swtBotTreeItem = Stream.of(treeItems).filter(item -> item.getText().startsWith(paths[0])) + .findFirst().orElseThrow(() -> new RuntimeException("Only available items: " + + Stream.of(treeItems).map(item -> item.getText()).collect(Collectors.joining(", ")))); + if (paths.length > 1) { + syncExec(() -> swtBotTreeItem.expand()); + final String[] remainingPath = new String[paths.length - 1]; + System.arraycopy(paths, 1, remainingPath, 0, remainingPath.length); + return getTreeItem(swtBotTreeItem.getItems(), remainingPath); + } + return swtBotTreeItem; + } + + public static SWTBotTableItem getListItem(final SWTBotTable table, final String name) { + return Stream.iterate(0, i -> i + 1).limit(table.rowCount()).map(rowNumber -> table.getTableItem(rowNumber)) + .filter(rowItem -> { + return Stream.iterate(0, j -> j + 1).limit(table.columnCount()) + .map(colNum -> rowItem.getText(colNum)).anyMatch(colValue -> colValue.contains(name)); + }).findFirst().orElse(null); + } + + /** + * Waits for the given duration + * + * @param duration + * the duration + * @param unit + * the duration unit + */ + public static void wait(final int duration, final TimeUnit unit) { + try { + Thread.sleep(unit.toMillis(duration)); + } catch (InterruptedException e) { + fail("Failed to wait for a " + unit.toMillis(duration) + "ms", e); + } + } + + /** + * Selects all child items in the given + * parentTreeItem whose labels match the given + * items. + * + * @param parentTreeItem + * the parent tree item + * @param matchItems + * the items to select + * @return + */ + public static SWTBotTreeItem select(final SWTBotTreeItem parentTreeItem, final String... matchItems) { + final List fullyQualifiedItems = Stream.of(parentTreeItem.getItems()).filter( + treeItem -> Stream.of(matchItems).anyMatch(matchItem -> treeItem.getText().startsWith(matchItem))) + .map(item -> item.getText()).collect(Collectors.toList()); + return parentTreeItem.select(fullyQualifiedItems.toArray(new String[0])); + } + + /** + * Selects all child items in the given + * parentTreeItem whose labels match the given + * items. + * + * @param parentTree + * the parent tree + * @param matchItems + * the items to select + * @return + */ + public static SWTBotTree select(final SWTBotTree parentTree, final String... matchItems) { + final List fullyQualifiedItems = Stream.of(parentTree.getAllItems()).filter( + treeItem -> Stream.of(matchItems).anyMatch(matchItem -> treeItem.getText().startsWith(matchItem))) + .map(item -> item.getText()).collect(Collectors.toList()); + return parentTree.select(fullyQualifiedItems.toArray(new String[0])); + } + + /** + * Selects the given treeItem whose labels match the given + * items. + * + * @param treeItem + * the parent tree item + * @param matchItems + * the items to select + */ + public static void select(SWTBotTreeItem treeItem) { + treeItem.select(); + } + + /** + * @param tree + * the root {@link SWTBotTree} + * @param path + * the path for the menu + * @return the child {@link SWTBotMenu} named with the first item in the + * given path from the given {@link SWTBotTree} + */ + public static SWTBotMenu getContextMenu(final SWTBotTree tree, String... path) { + final SWTBotMenu contextMenu = tree.contextMenu(path[0]); + if (contextMenu == null) { + Assert.fail("Failed to find context menu '" + path[0] + "'."); + } + if (path.length == 1) { + return contextMenu; + } + final String[] remainingPath = new String[path.length - 1]; + System.arraycopy(path, 1, remainingPath, 0, remainingPath.length); + return getSubMenu(contextMenu, remainingPath); + } + + /** + * Hides the menu for the given tree + * + * @param tree + * the tree whose {@link Menu} should be hidden + */ + public static void hideMenu(final SWTBotTree tree) { + try { + final Menu menu = UIThreadRunnable.syncExec((Result) () -> tree.widget.getMenu()); + UIThreadRunnable.syncExec(new VoidResult() { + + @Override + public void run() { + hide(menu); + } + + private void hide(final Menu menu) { + menu.notifyListeners(SWT.Hide, new Event()); + if (menu.getParentMenu() != null) { + hide(menu.getParentMenu()); + } + } + }); + } catch (WidgetNotFoundException e) { + // ignore if widget is not found, that's probably because there's no + // tree in the + // Docker Explorer view for the test that just ran. + } + } + + /** + * @param menu + * the parent menu + * @param path + * the path for the menu + * @return the child {@link SWTBotMenu} named with the first item in the + * given path from the given {@link SWTBotMenu} + */ + public static SWTBotMenu getSubMenu(final SWTBotMenu menu, String... path) { + final SWTBotMenu subMenu = menu.menu(path[0]); + if (subMenu == null) { + Assert.fail("Failed to find submenu '" + path[0] + "'."); + } + if (path.length == 1) { + return subMenu; + } + final String[] remainingPath = new String[path.length - 1]; + System.arraycopy(path, 1, remainingPath, 0, remainingPath.length); + return getSubMenu(subMenu, remainingPath); + } + + public static SWTBotTreeItem expand(final SWTBotTree tree, final String... paths) { + final SWTBotTreeItem rootItem = getTreeItem(tree, paths[0]); + expandTreeItem(rootItem); + if (paths.length > 1) { + final String[] remainingPath = new String[paths.length - 1]; + System.arraycopy(paths, 1, remainingPath, 0, remainingPath.length); + return expand(rootItem, remainingPath); + } + return rootItem; + } + + public static SWTBotTreeItem expand(final SWTBotTreeItem treeItem, final String... paths) { + final SWTBotTreeItem childItem = getTreeItem(treeItem, paths[0]); + expandTreeItem(childItem); + if (paths.length > 1) { + final String[] remainingPath = new String[paths.length - 1]; + System.arraycopy(paths, 1, remainingPath, 0, remainingPath.length); + return expand(childItem, remainingPath); + } + return getTreeItem(treeItem, paths[0]); + } + + private static SWTBotTreeItem expandTreeItem(final SWTBotTreeItem treeItem) { + final UIJob expandJob = new UIJob("expanding tree") { + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + treeItem.expand(); + return Status.OK_STATUS; + } + }; + expandJob.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + final int maxAttempts = 30; + int currentAttempt = 0; + while (currentAttempt < maxAttempts && treeItem.getItems().length == 1 + && treeItem.getItems()[0].getText().isEmpty()) { + SWTUtils.wait(1, TimeUnit.SECONDS); + currentAttempt++; + } + + } + }); + expandJob.schedule(); + SWTUtils.wait(1, TimeUnit.SECONDS); + return treeItem; + } + + public static SWTBotView getSWTBotView(final SWTWorkbenchBot bot, final String viewId) { + return bot.views().stream().filter(v -> v.getViewReference().getId().equals(viewId)).findFirst().orElse(null); + } + + @SuppressWarnings("unchecked") + public static T getView(final SWTWorkbenchBot bot, final String viewId) { + return (T) getView(bot, viewId, false); + } + + @SuppressWarnings("unchecked") + public static T getView(final SWTWorkbenchBot bot, final String viewId, final boolean restore) { + final SWTBotView viewBot = bot.viewById(viewId); + viewBot.setFocus(); + return (T) viewBot.getReference().getView(restore); + } + + /** + * @return true if the Console view is visible in the active + * page, false otherwise. + * @throws InterruptedException + */ + public static boolean isConsoleViewVisible(final SWTWorkbenchBot bot) { + return bot.views().stream() + .anyMatch(v -> v.getViewReference().getId().equals(IConsoleConstants.ID_CONSOLE_VIEW)); + } + + public static SWTBotToolbarButton getConsoleToolbarButtonWithTooltipText(final SWTWorkbenchBot bot, final String tooltipText) { + return bot.viewById(IConsoleConstants.ID_CONSOLE_VIEW).getToolbarButtons().stream() + .filter(button -> button.getToolTipText().equals(tooltipText)).findFirst().get(); + } + + public static void closeView(final SWTWorkbenchBot bot, final String viewId) { + bot.views().stream().filter(v -> v.getReference().getId().equals(viewId)).forEach(v -> v.close()); + } + + /** + * Creates a new {@link SWTBotMenu} from the context. This avoids some + * unexpected "Widget is disposed" errors. + * + * @param bot + * the bot + * @param menuName + * the name of the menu to find + * @return the context menu + * @see Eclipse + * forum + */ + public static SWTBotMenu getContextMenu(final AbstractSWTBot bot, final String menuName) { + return new SWTBotMenu(ContextMenuHelper.contextMenu(bot, menuName)); + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TabDescriptorAssertions.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TabDescriptorAssertions.java new file mode 100644 index 00000000000..ad63cd14bf5 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TabDescriptorAssertions.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.hamcrest.Matchers.notNullValue; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.ui.views.properties.tabbed.ITabDescriptor; + +/** + * Custom assertions on a given {@link ITabDescriptor}. + */ +public class TabDescriptorAssertions extends AbstractAssert { + + protected TabDescriptorAssertions(final ITabDescriptor actual) { + super(actual, TabDescriptorAssertions.class); + } + + public static TabDescriptorAssertions assertThat(final ITabDescriptor actual) { + return new TabDescriptorAssertions(actual); + } + + public TabDescriptorAssertions hasId(final String id) { + notNullValue(); + if (!actual.getId().equals(id)) { + failWithMessage("Expected tab section with id '%s' to be selected but it was '%s'", id, actual.getId()); + } + return this; + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TestLoggerRule.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TestLoggerRule.java new file mode 100644 index 00000000000..e74744252af --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TestLoggerRule.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +/** + * + */ +public class TestLoggerRule extends TestWatcher { + + @Override + protected void starting(final Description description) { + System.out.println("Starting " + description.getClassName() + "." + description.getMethodName()); + } +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TextAssertions.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TextAssertions.java new file mode 100644 index 00000000000..1b33a1da8c6 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/TextAssertions.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import static org.hamcrest.Matchers.notNullValue; + +import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; + +/** + * Custom assertions on an {@link SWTBotText}. + */ +public class TextAssertions extends AbstractSWTBotAssertions { + + protected TextAssertions(final SWTBotText actual) { + super(actual, TextAssertions.class); + } + + public static TextAssertions assertThat(final SWTBotText actual) { + return new TextAssertions(actual); + } + + public TextAssertions isEmpty() { + notNullValue(); + if(!actual.getText().isEmpty()) { + failWithMessage("Expected text widget to be empty but it contained '%s'", actual.getText()); + } + return this; + } + + public TextAssertions textEquals(final String expectedContent) { + notNullValue(); + if(!actual.getText().equals(expectedContent)) { + failWithMessage("Expected text widget to contain '%s' but it contained '%s'", expectedContent, actual.getText()); + } + return this; + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ToolbarButtonAssertions.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ToolbarButtonAssertions.java new file mode 100644 index 00000000000..07df9e0885e --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/ToolbarButtonAssertions.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ +package org.eclipse.cdt.internal.meson.ui.tests.utils; + +import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; + +/** + * Custom assertions on a given {@link SWTBotButton}. + */ +public class ToolbarButtonAssertions extends AbstractSWTBotAssertions { + + protected ToolbarButtonAssertions(final SWTBotToolbarButton actual) { + super(actual, ToolbarButtonAssertions.class); + } + + public static ToolbarButtonAssertions assertThat(final SWTBotToolbarButton actual) { + return new ToolbarButtonAssertions(actual); + } + +} diff --git a/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/package-info.java b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/package-info.java new file mode 100644 index 00000000000..3cd97f39094 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/src/org/eclipse/cdt/internal/meson/ui/tests/utils/package-info.java @@ -0,0 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat - Initial Contribution + *******************************************************************************/ + +/** + * Classes to perform assertions on SWTBot controls. + */ +package org.eclipse.cdt.internal.meson.ui.tests.utils; \ No newline at end of file diff --git a/build/org.eclipse.cdt.meson.ui.tests/swtbot-test-plugin.properties b/build/org.eclipse.cdt.meson.ui.tests/swtbot-test-plugin.properties new file mode 100644 index 00000000000..338038b9345 --- /dev/null +++ b/build/org.eclipse.cdt.meson.ui.tests/swtbot-test-plugin.properties @@ -0,0 +1 @@ +# This file tells the Maven build to use the settings for SWTBot test plugins