Make sure shell is not disposed in closeSecondaryShells
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui.swtbot.tests / shared / org / eclipse / tracecompass / tmf / ui / swtbot / tests / shared / SWTBotUtils.java
CommitLineData
306e18d0 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2014, 2015 Ericsson
306e18d0
MK
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 *******************************************************************************/
12
fa24d78b 13package org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared;
306e18d0
MK
14
15import static org.junit.Assert.assertNotNull;
21e5206c 16import static org.junit.Assert.assertTrue;
306e18d0
MK
17import static org.junit.Assert.fail;
18
1b9a8a8c 19import java.util.Arrays;
306e18d0 20import java.util.List;
6941941d 21import java.util.TimeZone;
675b1249 22import java.util.concurrent.atomic.AtomicBoolean;
306e18d0 23
1dfcd42b 24import org.apache.log4j.Logger;
29fe7911 25import org.eclipse.core.resources.IFolder;
306e18d0 26import org.eclipse.core.resources.IProject;
93c91230 27import org.eclipse.core.resources.IResource;
29fe7911 28import org.eclipse.core.resources.IResourceVisitor;
93c91230
MAL
29import org.eclipse.core.resources.ResourcesPlugin;
30import org.eclipse.core.runtime.CoreException;
b4290931 31import org.eclipse.core.runtime.IPath;
306e18d0 32import org.eclipse.core.runtime.NullProgressMonitor;
40ba27e1 33import org.eclipse.jdt.annotation.NonNull;
328e5fe4
MK
34import org.eclipse.jface.bindings.keys.IKeyLookup;
35import org.eclipse.jface.bindings.keys.KeyStroke;
36import org.eclipse.jface.bindings.keys.ParseException;
675b1249
PT
37import org.eclipse.swt.events.ControlAdapter;
38import org.eclipse.swt.events.ControlEvent;
328e5fe4
MK
39import org.eclipse.swt.graphics.Point;
40import org.eclipse.swt.graphics.Rectangle;
306e18d0 41import org.eclipse.swt.widgets.Display;
5785ab49 42import org.eclipse.swt.widgets.Shell;
328e5fe4
MK
43import org.eclipse.swt.widgets.Table;
44import org.eclipse.swt.widgets.TableItem;
306e18d0 45import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
693ec829
BH
46import org.eclipse.swtbot.eclipse.finder.matchers.WidgetMatcherFactory;
47import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
306e18d0 48import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
bbdb3d6d 49import org.eclipse.swtbot.swt.finder.SWTBot;
306e18d0 50import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
1c9b6343
MAL
51import org.eclipse.swtbot.swt.finder.keyboard.Keyboard;
52import org.eclipse.swtbot.swt.finder.keyboard.Keystrokes;
328e5fe4 53import org.eclipse.swtbot.swt.finder.results.Result;
306e18d0 54import org.eclipse.swtbot.swt.finder.results.VoidResult;
1dfcd42b 55import org.eclipse.swtbot.swt.finder.utils.MessageFormat;
747d62e1 56import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
93c91230 57import org.eclipse.swtbot.swt.finder.waits.Conditions;
a345ad25 58import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
93c91230
MAL
59import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
60import org.eclipse.swtbot.swt.finder.widgets.SWTBotCheckBox;
61import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
306e18d0 62import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
328e5fe4 63import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
93c91230
MAL
64import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
65import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
65416c44 66import org.eclipse.swtbot.swt.finder.widgets.TimeoutException;
40ba27e1 67import org.eclipse.tracecompass.internal.tmf.ui.project.operations.NewExperimentOperation;
2bdf0193 68import org.eclipse.tracecompass.tmf.ui.editors.TmfEventsEditor;
40ba27e1
BH
69import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
70import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentFolder;
2bdf0193 71import org.eclipse.tracecompass.tmf.ui.project.model.TmfOpenTraceHelper;
29fe7911 72import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
2bdf0193 73import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
29fe7911 74import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
2bdf0193 75import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
b4290931 76import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder;
21e5206c 77import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers.ProjectElementHasChild;
f0beeb4a 78import org.eclipse.tracecompass.tmf.ui.tests.shared.WaitUtils;
2bdf0193 79import org.eclipse.tracecompass.tmf.ui.views.TracingPerspectiveFactory;
693ec829
BH
80import org.eclipse.ui.IEditorPart;
81import org.eclipse.ui.IEditorReference;
93c91230 82import org.eclipse.ui.IPageLayout;
2470d687 83import org.eclipse.ui.PartInitException;
306e18d0
MK
84import org.eclipse.ui.PlatformUI;
85import org.eclipse.ui.WorkbenchException;
693ec829 86import org.hamcrest.Matcher;
306e18d0
MK
87
88/**
89 * SWTBot Helper functions
90 *
91 * @author Matthew Khouzam
92 */
40ba27e1 93@SuppressWarnings("restriction")
fa24d78b
AM
94public final class SWTBotUtils {
95
747d62e1
MAL
96 private static final String WINDOW_MENU = "Window";
97 private static final String PREFERENCES_MENU_ITEM = "Preferences";
2ad409b3 98 private static boolean fPrintedEnvironment = false;
1dfcd42b 99 private static Logger log = Logger.getLogger(SWTBotUtils.class);
747d62e1 100
328e5fe4 101 private SWTBotUtils() {
1dfcd42b 102
328e5fe4 103 }
fa24d78b 104
306e18d0
MK
105 private static final String TRACING_PERSPECTIVE_ID = TracingPerspectiveFactory.ID;
106
107 /**
fd5f786c 108 * Waits for all Eclipse jobs to finish. Times out after
f0beeb4a 109 * WaitUtils#MAX_JOBS_WAIT_TIME by default.
fd5f786c 110 *
217d5c81 111 * @throws RuntimeException
fd5f786c 112 * once the waiting time passes the default maximum value
f0beeb4a
MAL
113 *
114 * @deprecated Use {@link WaitUtils#waitForJobs()} instead
306e18d0 115 */
f0beeb4a 116 @Deprecated
306e18d0 117 public static void waitForJobs() {
f0beeb4a 118 WaitUtils.waitForJobs();
fd5f786c
MAL
119 }
120
306e18d0
MK
121 /**
122 * Sleeps current thread for a given time.
123 *
124 * @param waitTimeMillis
125 * time in milliseconds to wait
126 */
127 public static void delay(final long waitTimeMillis) {
128 try {
129 Thread.sleep(waitTimeMillis);
130 } catch (final InterruptedException e) {
131 // Ignored
132 }
133 }
134
135 /**
136 * Create a tracing project
137 *
138 * @param projectName
139 * the name of the tracing project
140 */
141 public static void createProject(final String projectName) {
142 /*
143 * Make a new test
144 */
145 UIThreadRunnable.syncExec(new VoidResult() {
146 @Override
147 public void run() {
148 IProject project = TmfProjectRegistry.createProject(projectName, null, new NullProgressMonitor());
149 assertNotNull(project);
150 }
151 });
152
f0beeb4a 153 WaitUtils.waitForJobs();
306e18d0
MK
154 }
155
93c91230 156 /**
bbdb3d6d 157 * Deletes a project
93c91230
MAL
158 *
159 * @param projectName
160 * the name of the tracing project
bbdb3d6d
MAL
161 * @param deleteResources
162 * whether or not to deleted resources under the project
93c91230
MAL
163 * @param bot
164 * the workbench bot
165 */
bbdb3d6d 166 public static void deleteProject(final String projectName, boolean deleteResources, SWTWorkbenchBot bot) {
7777d5f0
MK
167 // Wait for any analysis to complete because it might create
168 // supplementary files
f0beeb4a 169 WaitUtils.waitForJobs();
93c91230
MAL
170 try {
171 ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).refreshLocal(IResource.DEPTH_INFINITE, null);
172 } catch (CoreException e) {
173 }
174
f0beeb4a 175 WaitUtils.waitForJobs();
93c91230 176
1dfcd42b 177 closeSecondaryShells(bot);
f0beeb4a 178 WaitUtils.waitForJobs();
1dfcd42b 179
93c91230
MAL
180 final SWTBotView projectViewBot = bot.viewById(IPageLayout.ID_PROJECT_EXPLORER);
181 projectViewBot.setFocus();
182
693ec829 183 SWTBotTree treeBot = projectViewBot.bot().tree();
93c91230
MAL
184 SWTBotTreeItem treeItem = treeBot.getTreeItem(projectName);
185 SWTBotMenu contextMenu = treeItem.contextMenu("Delete");
186 contextMenu.click();
187
bbdb3d6d
MAL
188 if (deleteResources) {
189 bot.shell("Delete Resources").setFocus();
190 final SWTBotCheckBox checkBox = bot.checkBox();
191 bot.waitUntil(Conditions.widgetIsEnabled(checkBox));
192 checkBox.click();
193 }
93c91230
MAL
194
195 final SWTBotButton okButton = bot.button("OK");
196 bot.waitUntil(Conditions.widgetIsEnabled(okButton));
197 okButton.click();
198
f0beeb4a 199 WaitUtils.waitForJobs();
93c91230
MAL
200 }
201
bbdb3d6d
MAL
202 /**
203 * Deletes a project and its resources
204 *
205 * @param projectName
206 * the name of the tracing project
207 * @param bot
208 * the workbench bot
209 */
210 public static void deleteProject(String projectName, SWTWorkbenchBot bot) {
211 deleteProject(projectName, true, bot);
212 }
213
40ba27e1
BH
214 /**
215 * Creates an experiment
216 *
217 * @param bot
218 * a given workbench bot
219 * @param projectName
220 * the name of the project, creates the project if needed
221 * @param expName
222 * the experiment name
223 */
224 public static void createExperiment(SWTWorkbenchBot bot, String projectName, final @NonNull String expName) {
225 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
226 TmfProjectElement tmfProject = TmfProjectRegistry.getProject(project, true);
227 TmfExperimentFolder expFolder = tmfProject.getExperimentsFolder();
228 assertNotNull(expFolder);
229 NewExperimentOperation operation = new NewExperimentOperation(expFolder, expName);
230 operation.run(new NullProgressMonitor());
231
232 bot.waitUntil(new DefaultCondition() {
233 @Override
234 public boolean test() throws Exception {
235 TmfExperimentElement experiment = expFolder.getExperiment(expName);
236 return experiment != null;
237 }
238
239 @Override
240 public String getFailureMessage() {
241 return "Experiment (" + expName + ") couldn't be created";
242 }
243 });
244 }
245
246
306e18d0
MK
247 /**
248 * Focus on the main window
249 *
250 * @param shellBots
251 * swtbotshells for all the shells
252 */
253 public static void focusMainWindow(SWTBotShell[] shellBots) {
1dfcd42b
MAL
254 SWTBotShell mainShell = getMainShell(shellBots);
255 if (mainShell != null) {
256 mainShell.activate();
257 }
258 }
259
260 private static SWTBotShell getMainShell(SWTBotShell[] shellBots) {
261 SWTBotShell mainShell = null;
306e18d0
MK
262 for (SWTBotShell shellBot : shellBots) {
263 if (shellBot.getText().toLowerCase().contains("eclipse")) {
1dfcd42b 264 mainShell = shellBot;
306e18d0
MK
265 }
266 }
1dfcd42b
MAL
267 return mainShell;
268 }
269
270 /**
271 * Close all non-main shells that are visible.
272 *
273 * @param bot
274 * the workbench bot
275 */
276 public static void closeSecondaryShells(SWTWorkbenchBot bot) {
277 SWTBotShell[] shells = bot.shells();
278 SWTBotShell mainShell = getMainShell(shells);
279 if (mainShell == null) {
280 return;
281 }
282
283 // Close all non-main shell but make sure we don't close an invisible
284 // shell such the special "limbo shell" that Eclipse needs to work
285 Arrays.stream(shells)
286 .filter(shell -> shell != mainShell)
d7ac6294 287 .filter(s -> !s.widget.isDisposed())
1dfcd42b 288 .filter(SWTBotShell::isVisible)
a463a9ba 289 .peek(shell -> log.debug(MessageFormat.format("Closing lingering shell with title {0}", shell.getText())))
1dfcd42b 290 .forEach(SWTBotShell::close);
306e18d0
MK
291 }
292
293 /**
294 * Close a view with a title
295 *
296 * @param title
297 * the title, like "welcome"
298 * @param bot
299 * the workbench bot
300 */
301 public static void closeView(String title, SWTWorkbenchBot bot) {
302 final List<SWTBotView> openViews = bot.views();
303 for (SWTBotView view : openViews) {
304 if (view.getTitle().equalsIgnoreCase(title)) {
305 view.close();
306 bot.waitUntil(ConditionHelpers.ViewIsClosed(view));
307 }
308 }
309 }
310
e4d15418
MAL
311 /**
312 * Close a view with an id
313 *
314 * @param viewId
315 * the view id, like "org.eclipse.linuxtools.tmf.ui.views.histogram"
316 * @param bot
317 * the workbench bot
318 */
319 public static void closeViewById(String viewId, SWTWorkbenchBot bot) {
320 final SWTBotView view = bot.viewById(viewId);
321 view.close();
322 bot.waitUntil(ConditionHelpers.ViewIsClosed(view));
323 }
324
306e18d0
MK
325 /**
326 * Switch to the tracing perspective
327 */
328 public static void switchToTracingPerspective() {
664fa59c
MK
329 switchToPerspective(TRACING_PERSPECTIVE_ID);
330 }
331
332 /**
333 * Switch to a given perspective
334 *
335 * @param id
336 * the perspective id (like
337 * "org.eclipse.linuxtools.tmf.ui.perspective"
338 */
339 public static void switchToPerspective(final String id) {
306e18d0
MK
340 UIThreadRunnable.syncExec(new VoidResult() {
341 @Override
342 public void run() {
343 try {
664fa59c 344 PlatformUI.getWorkbench().showPerspective(id, PlatformUI.getWorkbench().getActiveWorkbenchWindow());
306e18d0
MK
345 } catch (WorkbenchException e) {
346 fail(e.getMessage());
347 }
348 }
349 });
350 }
351
5785ab49
MAL
352 /**
353 * Initialize the environment for SWTBot
354 */
355 public static void initialize() {
356 failIfUIThread();
357
358 SWTWorkbenchBot bot = new SWTWorkbenchBot();
359 UIThreadRunnable.syncExec(() -> {
2ad409b3 360 printEnvironment();
5475ad49
MAL
361
362 // There seems to be problems on some system where the main shell is
363 // not in focus initially. This was seen using Xvfb and Xephyr on some occasions.
364 focusMainWindow(bot.shells());
365
5785ab49
MAL
366 Shell shell = bot.activeShell().widget;
367
368 // Only adjust shell if it appears to be the top-most
369 if (shell.getParent() == null) {
370 makeShellFullyVisible(shell);
371 }
372 });
373 }
374
2ad409b3
MAL
375 private static void printEnvironment() {
376 if (fPrintedEnvironment) {
377 return;
378 }
379
380 // Print some information about the environment that could affect test outcome
381 Rectangle bounds = Display.getDefault().getBounds();
382 System.out.println("Display size: " + bounds.width + "x" + bounds.height);
383
384 String osVersion = System.getProperty("os.version");
385 if (osVersion != null) {
386 System.out.println("OS version=" + osVersion);
387 }
388 String gtkVersion = System.getProperty("org.eclipse.swt.internal.gtk.version");
389 if (gtkVersion != null) {
390 System.out.println("GTK version=" + gtkVersion);
7df209fa
MAL
391 // Try to print the GTK theme information as behavior can change depending on the theme
392 String gtkTheme = System.getProperty("org.eclipse.swt.internal.gtk.theme");
393 System.out.println("GTK theme=" + (gtkTheme == null ? "unknown" : gtkTheme));
394
2ad409b3
MAL
395 String overlayScrollbar = System.getenv("LIBOVERLAY_SCROLLBAR");
396 if (overlayScrollbar != null) {
397 System.out.println("LIBOVERLAY_SCROLLBAR=" + overlayScrollbar);
398 }
399 String ubuntuMenuProxy = System.getenv("UBUNTU_MENUPROXY");
400 if (ubuntuMenuProxy != null) {
401 System.out.println("UBUNTU_MENUPROXY=" + ubuntuMenuProxy);
402 }
403 }
404
6941941d
MAL
405 System.out.println("Time zone: " + TimeZone.getDefault().getDisplayName());
406
2ad409b3
MAL
407 fPrintedEnvironment = true;
408 }
409
306e18d0
MK
410 /**
411 * If the test is running in the UI thread then fail
412 */
5785ab49 413 private static void failIfUIThread() {
306e18d0
MK
414 if (Display.getCurrent() != null && Display.getCurrent().getThread() == Thread.currentThread()) {
415 fail("SWTBot test needs to run in a non-UI thread. Make sure that \"Run in UI thread\" is unchecked in your launch configuration or"
416 + " that useUIThread is set to false in the pom.xml");
417 }
5785ab49 418 }
306e18d0 419
5785ab49
MAL
420 /**
421 * Try to make the shell fully visible in the display. If the shell cannot
422 * fit the display, it will be positioned so that top-left corner is at
423 * <code>(0, 0)</code> in display-relative coordinates.
424 *
425 * @param shell
426 * the shell to make fully visible
427 */
428 private static void makeShellFullyVisible(Shell shell) {
429 Rectangle displayBounds = shell.getDisplay().getBounds();
430 Point absCoord = shell.toDisplay(0, 0);
431 Point shellSize = shell.getSize();
432
433 Point newLocation = new Point(absCoord.x, absCoord.y);
434 newLocation.x = Math.max(0, Math.min(absCoord.x, displayBounds.width - shellSize.x));
435 newLocation.y = Math.max(0, Math.min(absCoord.y, displayBounds.height - shellSize.y));
436 if (!newLocation.equals(absCoord)) {
437 shell.setLocation(newLocation);
438 }
306e18d0 439 }
7777d5f0
MK
440
441 /**
442 * Open a trace, this does not perform any validation though
443 *
444 * @param projectName
445 * The project name
446 * @param tracePath
447 * the path of the trace file (absolute or relative)
448 * @param traceType
328e5fe4 449 * the trace type id (eg: org.eclipse.linuxtools.btf.trace)
7777d5f0
MK
450 */
451 public static void openTrace(final String projectName, final String tracePath, final String traceType) {
a3d7df19
BH
452 openTrace(projectName, tracePath, traceType, true);
453 }
454
455 /**
456 * Open a trace, this does not perform any validation though
457 *
458 * @param projectName
459 * The project name
460 * @param tracePath
461 * the path of the trace file (absolute or relative)
462 * @param traceType
328e5fe4 463 * the trace type id (eg: org.eclipse.linuxtools.btf.trace)
a3d7df19
BH
464 * @param delay
465 * delay and wait for jobs
466 */
467 public static void openTrace(final String projectName, final String tracePath, final String traceType, boolean delay) {
7777d5f0
MK
468 final Exception exception[] = new Exception[1];
469 exception[0] = null;
470 UIThreadRunnable.syncExec(new VoidResult() {
471 @Override
472 public void run() {
473 try {
474 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
475 TmfTraceFolder destinationFolder = TmfProjectRegistry.getProject(project, true).getTracesFolder();
476 TmfOpenTraceHelper.openTraceFromPath(destinationFolder, tracePath, PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), traceType);
477 } catch (CoreException e) {
478 exception[0] = e;
479 }
480 }
481 });
482 if (exception[0] != null) {
483 fail(exception[0].getMessage());
484 }
485
a3d7df19
BH
486 if (delay) {
487 delay(1000);
f0beeb4a 488 WaitUtils.waitForJobs();
a3d7df19 489 }
7777d5f0 490 }
693ec829
BH
491
492 /**
b4290931 493 * Finds an editor and sets focus to the editor
693ec829
BH
494 *
495 * @param bot
496 * the workbench bot
497 * @param editorName
498 * the editor name
499 * @return the corresponding SWTBotEditor
500 */
b4290931 501 public static SWTBotEditor activateEditor(SWTWorkbenchBot bot, String editorName) {
693ec829
BH
502 Matcher<IEditorReference> matcher = WidgetMatcherFactory.withPartName(editorName);
503 final SWTBotEditor editorBot = bot.editor(matcher);
504 IEditorPart iep = editorBot.getReference().getEditor(true);
505 final TmfEventsEditor tmfEd = (TmfEventsEditor) iep;
506 editorBot.show();
507 UIThreadRunnable.syncExec(new VoidResult() {
508 @Override
509 public void run() {
510 tmfEd.setFocus();
511 }
512 });
513
f0beeb4a 514 WaitUtils.waitForJobs();
fa24d78b 515 SWTBotUtils.delay(1000);
693ec829
BH
516 assertNotNull(tmfEd);
517 return editorBot;
518 }
b4290931
MAL
519
520 /**
521 * Opens a trace in an editor and get the TmfEventsEditor
522 *
523 * @param bot
524 * the workbench bot
525 * @param projectName
526 * the name of the project that contains the trace
527 * @param elementPath
528 * the trace element path (relative to Traces folder)
529 * @return TmfEventsEditor the opened editor
530 */
531 public static TmfEventsEditor openEditor(SWTWorkbenchBot bot, String projectName, IPath elementPath) {
5b6c8456
MAL
532 final SWTBotView projectExplorerView = bot.viewById(IPageLayout.ID_PROJECT_EXPLORER);
533 projectExplorerView.setFocus();
534 SWTBot projectExplorerBot = projectExplorerView.bot();
b4290931 535
5b6c8456
MAL
536 final SWTBotTree tree = projectExplorerBot.tree();
537 projectExplorerBot.waitUntil(ConditionHelpers.IsTreeNodeAvailable(projectName, tree));
b4290931
MAL
538 final SWTBotTreeItem treeItem = tree.getTreeItem(projectName);
539 treeItem.expand();
540
5b6c8456 541 SWTBotTreeItem tracesNode = getTraceProjectItem(projectExplorerBot, treeItem, TmfTracesFolder.TRACES_FOLDER_NAME);
b4290931
MAL
542 tracesNode.expand();
543
21e5206c 544 SWTBotTreeItem currentItem = tracesNode;
b4290931 545 for (String segment : elementPath.segments()) {
5b6c8456 546 currentItem = getTraceProjectItem(projectExplorerBot, currentItem, segment);
21e5206c 547 currentItem.doubleClick();
b4290931
MAL
548 }
549
21e5206c
PT
550 SWTBotEditor editor = bot.editorByTitle(elementPath.toString());
551 IEditorPart editorPart = editor.getReference().getEditor(false);
552 assertTrue(editorPart instanceof TmfEventsEditor);
553 return (TmfEventsEditor) editorPart;
b4290931
MAL
554 }
555
cdfe10e7
PT
556 /**
557 * Returns the child tree item of the specified item at the given sub-path.
558 * The project element labels may have a count suffix in the format ' [n]'.
559 *
560 * @param bot
561 * a given workbench bot
562 * @param parentItem
563 * the parent tree item
564 * @param path
565 * the desired child element sub-path (without suffix)
566 * @return the a {@link SWTBotTreeItem} with the specified name
567 */
568 public static SWTBotTreeItem getTraceProjectItem(SWTBot bot, final SWTBotTreeItem parentItem, final String... path) {
569 SWTBotTreeItem item = parentItem;
570 for (String name : path) {
571 item = getTraceProjectItem(bot, item, name);
572 }
573 return item;
574 }
575
21e5206c
PT
576 /**
577 * Returns the child tree item of the specified item with the given name.
578 * The project element label may have a count suffix in the format ' [n]'.
579 *
580 * @param bot
581 * a given workbench bot
582 * @param parentItem
583 * the parent tree item
584 * @param name
585 * the desired child element name (without suffix)
586 * @return the a {@link SWTBotTreeItem} with the specified name
587 */
5b6c8456 588 public static SWTBotTreeItem getTraceProjectItem(SWTBot bot, final SWTBotTreeItem parentItem, final String name) {
21e5206c
PT
589 ProjectElementHasChild condition = new ProjectElementHasChild(parentItem, name);
590 bot.waitUntil(condition);
591 return condition.getItem();
b4290931 592 }
34c0fc10
MK
593
594 /**
595 * Select the traces folder
596 *
597 * @param bot
598 * a given workbench bot
599 * @param projectName
328e5fe4
MK
600 * the name of the project (it needs to exist or else it would
601 * time out)
21e5206c 602 * @return a {@link SWTBotTreeItem} of the "Traces" folder
34c0fc10
MK
603 */
604 public static SWTBotTreeItem selectTracesFolder(SWTWorkbenchBot bot, String projectName) {
bbdb3d6d 605 SWTBotTreeItem projectTreeItem = selectProject(bot, projectName);
21e5206c
PT
606 projectTreeItem.select();
607 SWTBotTreeItem tracesFolderItem = getTraceProjectItem(bot, projectTreeItem, TmfTracesFolder.TRACES_FOLDER_NAME);
608 tracesFolderItem.select();
609 return tracesFolderItem;
34c0fc10 610 }
2470d687 611
29fe7911
MAL
612 /**
613 * Clear the traces folder
614 *
615 * @param bot
616 * a given workbench bot
617 * @param projectName
618 * the name of the project (needs to exist)
619 */
620 public static void clearTracesFolder(SWTWorkbenchBot bot, String projectName) {
621 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
622 TmfProjectElement tmfProject = TmfProjectRegistry.getProject(project, false);
623 TmfTraceFolder tracesFolder = tmfProject.getTracesFolder();
624 try {
625 for (TmfTraceElement traceElement : tracesFolder.getTraces()) {
626 traceElement.delete(null);
627 }
628
629 final IFolder resource = tracesFolder.getResource();
630 resource.accept(new IResourceVisitor() {
631 @Override
632 public boolean visit(IResource visitedResource) throws CoreException {
633 if (visitedResource != resource) {
634 visitedResource.delete(true, null);
635 }
636 return true;
637 }
638 }, IResource.DEPTH_ONE, 0);
639 } catch (CoreException e) {
640 fail(e.getMessage());
641 }
642
643 bot.waitUntil(new DefaultCondition() {
644 private int fTraceNb = 0;
645
646 @Override
647 public boolean test() throws Exception {
648 List<TmfTraceElement> traces = tracesFolder.getTraces();
649 fTraceNb = traces.size();
650 return fTraceNb == 0;
651 }
652
653 @Override
654 public String getFailureMessage() {
655 return "Traces Folder not empty (" + fTraceNb + ")";
656 }
657 });
40ba27e1
BH
658 }
659
450daec8
MAL
660 /**
661 * Clear the trace folder (using the UI)
662 *
663 * @param bot
664 * a given workbench bot
665 * @param projectName
666 * the name of the project (needs to exist)
667 */
668 public static void clearTracesFolderUI(SWTWorkbenchBot bot, String projectName) {
669 SWTBotTreeItem tracesFolder = selectTracesFolder(bot, projectName);
670 tracesFolder.contextMenu().menu("Clear").click();
671 String CONFIRM_CLEAR_DIALOG_TITLE = "Confirm Clear";
672 bot.waitUntil(Conditions.shellIsActive(CONFIRM_CLEAR_DIALOG_TITLE));
673
674 SWTBotShell shell = bot.shell(CONFIRM_CLEAR_DIALOG_TITLE);
675 shell.bot().button("Yes").click();
676 bot.waitUntil(Conditions.shellCloses(shell));
677 bot.waitWhile(ConditionHelpers.treeItemHasChildren(tracesFolder));
678 }
679
40ba27e1
BH
680 /**
681 * Clear the experiment folder
682 *
683 * @param bot
684 * a given workbench bot
685 * @param projectName
686 * the name of the project (needs to exist)
687 */
688 public static void clearExperimentFolder(SWTWorkbenchBot bot, String projectName) {
689 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
690 TmfProjectElement tmfProject = TmfProjectRegistry.getProject(project, false);
691 TmfExperimentFolder expFolder = tmfProject.getExperimentsFolder();
692 expFolder.getExperiments().forEach(experiment -> {
693 IResource resource = experiment.getResource();
694 try {
695 // Close the experiment if open
696 experiment.closeEditors();
697
698 IPath path = resource.getLocation();
699 if (path != null) {
700 // Delete supplementary files
701 experiment.deleteSupplementaryFolder();
702 }
703 // Finally, delete the experiment
704 resource.delete(true, null);
705 } catch (CoreException e) {
706 fail(e.getMessage());
707 }
708 });
709
710 bot.waitUntil(new DefaultCondition() {
711 private int fExperimentNb = 0;
29fe7911 712
40ba27e1
BH
713 @Override
714 public boolean test() throws Exception {
715 List<TmfExperimentElement> experiments = expFolder.getExperiments();
716 fExperimentNb = experiments.size();
717 return fExperimentNb == 0;
718 }
719
720 @Override
721 public String getFailureMessage() {
722 return "Experiment Folder not empty (" + fExperimentNb + ")";
723 }
724 });
29fe7911
MAL
725 }
726
bbdb3d6d
MAL
727 /**
728 * Select the project in Project Explorer
729 *
730 * @param bot
731 * a given workbench bot
732 * @param projectName
733 * the name of the project (it needs to exist or else it would time out)
734 * @return a {@link SWTBotTreeItem} of the project
735 */
736 public static SWTBotTreeItem selectProject(SWTWorkbenchBot bot, String projectName) {
737 SWTBotView projectExplorerBot = bot.viewByTitle("Project Explorer");
738 projectExplorerBot.show();
e834a6b4
MAL
739 // FIXME: Bug 496519. Sometimes, the tree becomes disabled for a certain
740 // amount of time. This can happen during a long running operation
741 // (BusyIndicator.showWhile) which brings up the modal dialog "operation
742 // in progress" and this disables all shells
743 projectExplorerBot.bot().waitUntil(Conditions.widgetIsEnabled(projectExplorerBot.bot().tree()));
bbdb3d6d
MAL
744 SWTBotTreeItem treeItem = projectExplorerBot.bot().tree().getTreeItem(projectName);
745 treeItem.select();
746 return treeItem;
747 }
748
2470d687
MK
749 /**
750 * Open a view by id.
751 *
752 * @param id
753 * view id.
754 */
755 public static void openView(final String id) {
756 final PartInitException res[] = new PartInitException[1];
757 UIThreadRunnable.syncExec(new VoidResult() {
758 @Override
759 public void run() {
760 try {
761 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(id);
762 } catch (PartInitException e) {
763 res[0] = e;
764 }
765 }
766 });
767 if (res[0] != null) {
768 fail(res[0].getMessage());
769 }
f0beeb4a 770 WaitUtils.waitForJobs();
2470d687 771 }
328e5fe4
MK
772
773 /**
774 * Maximize a table
775 *
776 * @param tableBot
777 * the {@link SWTBotTable} table
778 */
779 public static void maximizeTable(SWTBotTable tableBot) {
675b1249
PT
780 final AtomicBoolean controlResized = new AtomicBoolean();
781 UIThreadRunnable.syncExec(new VoidResult() {
782 @Override
783 public void run() {
784 tableBot.widget.addControlListener(new ControlAdapter() {
785 @Override
786 public void controlResized(ControlEvent e) {
787 tableBot.widget.removeControlListener(this);
788 controlResized.set(true);
789 }
790 });
791 }
792 });
328e5fe4
MK
793 try {
794 tableBot.pressShortcut(KeyStroke.getInstance(IKeyLookup.CTRL_NAME + "+"), KeyStroke.getInstance("M"));
795 } catch (ParseException e) {
796 fail();
797 }
675b1249
PT
798 new SWTBot().waitUntil(new DefaultCondition() {
799 @Override
800 public boolean test() throws Exception {
801 return controlResized.get();
802 }
803
804 @Override
805 public String getFailureMessage() {
806 return "Control was not resized";
807 }
808 });
328e5fe4
MK
809 }
810
811 /**
812 * Get the bounds of a cell (SWT.Rectangle) for the specified row and column
813 * index in a table
814 *
815 * @param table
816 * the table
817 * @param row
818 * the row of the table to look up
819 * @param col
820 * the column of the table to look up
821 * @return the bounds in display relative coordinates
822 */
823 public static Rectangle getCellBounds(final Table table, final int row, final int col) {
824 return UIThreadRunnable.syncExec(new Result<Rectangle>() {
825 @Override
826 public Rectangle run() {
827 TableItem item = table.getItem(row);
828 Rectangle bounds = item.getBounds(col);
829 Point p = table.toDisplay(bounds.x, bounds.y);
830 Rectangle rect = new Rectangle(p.x, p.y, bounds.width, bounds.height);
831 return rect;
832 }
833 });
834 }
bbdb3d6d
MAL
835
836 /**
837 * Get the tree item from a tree at the specified location
838 *
839 * @param bot
840 * the SWTBot
841 * @param tree
842 * the tree to find the tree item in
843 * @param nodeNames
844 * the path to the tree item, in the form of node names (from
845 * parent to child).
846 * @return the tree item
847 */
848 public static SWTBotTreeItem getTreeItem(SWTBot bot, SWTBotTree tree, String... nodeNames) {
849 if (nodeNames.length == 0) {
850 return null;
851 }
852
853 bot.waitUntil(ConditionHelpers.IsTreeNodeAvailable(nodeNames[0], tree));
854 SWTBotTreeItem currentNode = tree.getTreeItem(nodeNames[0]);
1b9a8a8c
MAL
855 return getTreeItem(bot, currentNode, Arrays.copyOfRange(nodeNames, 1, nodeNames.length));
856 }
857
858 /**
859 * Get the tree item from a parent tree item at the specified location
860 *
861 * @param bot
862 * the SWTBot
863 * @param treeItem
864 * the treeItem to find the tree item under
865 * @param nodeNames
866 * the path to the tree item, in the form of node names (from
867 * parent to child).
868 * @return the tree item
869 */
870 public static SWTBotTreeItem getTreeItem(SWTBot bot, SWTBotTreeItem treeItem, String... nodeNames) {
871 if (nodeNames.length == 0) {
872 return treeItem;
873 }
874
875 SWTBotTreeItem currentNode = treeItem;
876 for (int i = 0; i < nodeNames.length; i++) {
877 bot.waitUntil(ConditionHelpers.treeItemHasChildren(treeItem));
bbdb3d6d
MAL
878 currentNode.expand();
879
880 String nodeName = nodeNames[i];
65416c44
MAL
881 try {
882 bot.waitUntil(ConditionHelpers.IsTreeChildNodeAvailable(nodeName, currentNode));
883 } catch (TimeoutException e) {
884 //FIXME: Sometimes in a JFace TreeViewer, it expands to nothing. Need to find out why.
885 currentNode.collapse();
886 currentNode.expand();
887 bot.waitUntil(ConditionHelpers.IsTreeChildNodeAvailable(nodeName, currentNode));
888 }
889
bbdb3d6d
MAL
890 SWTBotTreeItem newNode = currentNode.getNode(nodeName);
891 currentNode = newNode;
892 }
893
894 return currentNode;
895 }
a345ad25 896
1c9b6343
MAL
897 /**
898 * Press the keyboard shortcut that goes to the top of a tree widget. The
899 * key combination can differ on different platforms.
900 *
901 * @param keyboard
902 * the keyboard to use
903 */
904 public static void pressShortcutGoToTreeTop(Keyboard keyboard) {
905 if (SWTUtils.isMac()) {
906 keyboard.pressShortcut(Keystrokes.ALT, Keystrokes.UP);
907 } else {
908 keyboard.pressShortcut(Keystrokes.HOME);
909 }
910 }
911
a345ad25
MAL
912 /**
913 * Get the active events editor. Note that this will wait until such editor
914 * is available.
915 *
916 * @param workbenchBot
917 * a given workbench bot
918 * @return the active events editor
919 */
920 public static SWTBotEditor activeEventsEditor(final SWTWorkbenchBot workbenchBot) {
e834a6b4
MAL
921 ConditionHelpers.ActiveEventsEditor condition = new ConditionHelpers.ActiveEventsEditor(workbenchBot, null);
922 workbenchBot.waitUntil(condition);
923 return condition.getActiveEditor();
924 }
a345ad25 925
e834a6b4
MAL
926 /**
927 * Get the active events editor. Note that this will wait until such editor
928 * is available.
929 *
930 * @param workbenchBot
931 * a given workbench bot
932 * @param editorTitle
933 * the desired editor title. If null, any active events editor
934 * will be considered valid.
935 * @return the active events editor
936 */
937 public static SWTBotEditor activeEventsEditor(final SWTWorkbenchBot workbenchBot, String editorTitle) {
938 ConditionHelpers.ActiveEventsEditor condition = new ConditionHelpers.ActiveEventsEditor(workbenchBot, editorTitle);
939 workbenchBot.waitUntil(condition);
940 return condition.getActiveEditor();
a345ad25 941 }
747d62e1
MAL
942
943 /**
944 * Open the preferences dialog and return the corresponding shell.
945 *
946 * @param bot
947 * a given workbench bot
948 * @return the preferences shell
949 */
950 public static SWTBotShell openPreferences(SWTBot bot) {
951 if (SWTUtils.isMac()) {
952 // On Mac, the Preferences menu item is under the application name.
953 // For some reason, we can't access the application menu anymore so
954 // we use the keyboard shortcut.
955 try {
956 bot.activeShell().pressShortcut(KeyStroke.getInstance(IKeyLookup.COMMAND_NAME + "+"), KeyStroke.getInstance(","));
957 } catch (ParseException e) {
958 fail();
959 }
960 } else {
961 bot.menu(WINDOW_MENU).menu(PREFERENCES_MENU_ITEM).click();
962 }
963
964 bot.waitUntil(Conditions.shellIsActive(PREFERENCES_MENU_ITEM));
965 return bot.activeShell();
966 }
306e18d0 967}
This page took 0.120104 seconds and 5 git commands to generate.