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