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