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