1 /*******************************************************************************
2 * Copyright (c) 2013, 2016 Ericsson
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
10 * Matthew Khouzam - Initial API and implementation
11 * Alexandre Montplaisir - Replaced separate Condition objects by anonymous classes
12 * Patrick Tasse - Add projectElementHasChild and isEditorOpened conditions
13 *******************************************************************************/
15 package org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
;
17 import static org
.eclipse
.swtbot
.eclipse
.finder
.matchers
.WidgetMatcherFactory
.withPartName
;
19 import java
.util
.Arrays
;
20 import java
.util
.List
;
22 import org
.eclipse
.jdt
.annotation
.NonNull
;
23 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
24 import org
.eclipse
.jface
.wizard
.IWizardContainer
;
25 import org
.eclipse
.jface
.wizard
.IWizardPage
;
26 import org
.eclipse
.jface
.wizard
.Wizard
;
27 import org
.eclipse
.osgi
.util
.NLS
;
28 import org
.eclipse
.swtbot
.eclipse
.finder
.SWTWorkbenchBot
;
29 import org
.eclipse
.swtbot
.eclipse
.finder
.matchers
.WidgetMatcherFactory
;
30 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotEditor
;
31 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotView
;
32 import org
.eclipse
.swtbot
.swt
.finder
.SWTBot
;
33 import org
.eclipse
.swtbot
.swt
.finder
.finders
.UIThreadRunnable
;
34 import org
.eclipse
.swtbot
.swt
.finder
.results
.Result
;
35 import org
.eclipse
.swtbot
.swt
.finder
.utils
.TableCollection
;
36 import org
.eclipse
.swtbot
.swt
.finder
.waits
.DefaultCondition
;
37 import org
.eclipse
.swtbot
.swt
.finder
.waits
.ICondition
;
38 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTable
;
39 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTree
;
40 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTreeItem
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
46 import org
.eclipse
.tracecompass
.tmf
.ui
.editors
.TmfEventsEditor
;
47 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
.AbstractTimeGraphView
;
48 import org
.eclipse
.ui
.IEditorReference
;
49 import org
.hamcrest
.Matcher
;
52 * Is a tree node available
54 * @author Matthew Khouzam
56 public final class ConditionHelpers
{
58 private ConditionHelpers() {}
61 * Provide default implementations for some {@link ICondition} methods.
63 public abstract static class SWTBotTestCondition
implements ICondition
{
66 public abstract boolean test() throws Exception
;
69 public final void init(SWTBot bot
) {
73 public String
getFailureMessage() {
79 * Is a tree node available
82 * the name of the node
85 * @return true or false, it should swallow all exceptions
87 public static ICondition
IsTreeNodeAvailable(final String name
, final SWTBotTree tree
) {
88 return new SWTBotTestCondition() {
90 public boolean test() throws Exception
{
92 final SWTBotTreeItem
[] treeItems
= tree
.getAllItems();
93 for (SWTBotTreeItem ti
: treeItems
) {
94 final String text
= ti
.getText();
95 if (text
.equals(name
)) {
99 } catch (Exception e
) {
105 public String
getFailureMessage() {
106 return NLS
.bind("No child of tree {0} found with text {1}. Child items: {2}",
107 new String
[] { tree
.toString(), name
, Arrays
.toString(tree
.getAllItems()) });
113 * Is a table item available
116 * the name of the item
119 * @return true or false, it should swallow all exceptions
121 public static ICondition
isTableItemAvailable(final String name
, final SWTBotTable table
) {
122 return new SWTBotTestCondition() {
124 public boolean test() throws Exception
{
126 return table
.containsItem(name
);
127 } catch (Exception e
) {
133 public String
getFailureMessage() {
134 return NLS
.bind("No child of table {0} found with text '{1}'.", table
, name
);
140 * Is the treeItem's node available
143 * the name of the node
146 * @return true or false, it should swallow all exceptions
148 public static ICondition
IsTreeChildNodeAvailable(final String name
, final SWTBotTreeItem treeItem
) {
149 return new SWTBotTestCondition() {
151 public boolean test() throws Exception
{
153 return treeItem
.getNode(name
) != null;
154 } catch (Exception e
) {
160 public String
getFailureMessage() {
161 return NLS
.bind("No child of tree item {0} found with text '{1}'. Child items: {2}",
162 new String
[] { treeItem
.toString(), name
, Arrays
.toString(treeItem
.getItems()) });
168 * Is the treeItem's node removed
171 * length of the node after removal
174 * @return true or false, it should swallow all exceptions
176 public static ICondition
isTreeChildNodeRemoved(final int length
, final SWTBotTreeItem treeItem
) {
177 return new SWTBotTestCondition() {
179 public boolean test() throws Exception
{
181 return treeItem
.getNodes().size() == length
;
182 } catch (Exception e
) {
188 public String
getFailureMessage() {
189 return NLS
.bind("Child of tree item {0} found with text '{1}' not removed. Child items: {2}",
190 new String
[] { treeItem
.toString(), String
.valueOf(length
), Arrays
.toString(treeItem
.getItems()) });
196 * Condition to check if the number of direct children of the
197 * provided tree item equals the specified count.
200 * the SWTBot tree item
203 * @return ICondition for verification
205 public static ICondition
treeItemCount(final SWTBotTreeItem treeItem
, int count
) {
206 return new SWTBotTestCondition() {
208 public boolean test() throws Exception
{
209 return treeItem
.rowCount() == count
;
213 public String
getFailureMessage() {
214 return NLS
.bind("Tree item count: {0} expected: {1}",
215 treeItem
.rowCount(), count
);
221 * Checks if the wizard's shell is null
225 * @return false if either are null
227 public static ICondition
isWizardReady(final Wizard wizard
) {
228 return new SWTBotTestCondition() {
230 public boolean test() throws Exception
{
231 if (wizard
.getShell() == null) {
240 * Is the wizard on the page you want?
246 * @return true or false
248 public static ICondition
isWizardOnPage(final Wizard wizard
, final IWizardPage page
) {
249 return new SWTBotTestCondition() {
251 public boolean test() throws Exception
{
252 if (wizard
== null || page
== null) {
255 final IWizardContainer container
= wizard
.getContainer();
256 if (container
== null) {
259 IWizardPage currentPage
= container
.getCurrentPage();
260 return page
.equals(currentPage
);
266 * Wait for a view to close
269 * bot view for the view
270 * @return true if the view is closed, false if it's active.
272 public static ICondition
ViewIsClosed(final SWTBotView view
) {
273 return new SWTBotTestCondition() {
275 public boolean test() throws Exception
{
276 return (view
!= null) && (!view
.isActive());
282 * Wait till table cell has a given content.
285 * the table bot reference
287 * the content to check
289 * the row of the cell
291 * the column of the cell
292 * @return ICondition for verification
294 public static ICondition
isTableCellFilled(final SWTBotTable table
,
295 final String content
, final int row
, final int column
) {
296 return new SWTBotTestCondition() {
298 public boolean test() throws Exception
{
300 String cell
= table
.cell(row
, column
);
304 return cell
.contains(content
);
305 } catch (Exception e
) {
313 * Condition to check if a tracing project element has a child with the
314 * specified name. A project element label may have a count suffix in the
317 public static class ProjectElementHasChild
extends DefaultCondition
{
319 private final SWTBotTreeItem fParentItem
;
320 private final String fName
;
321 private final String fRegex
;
322 private SWTBotTreeItem fItem
= null;
330 * the child name to look for
332 public ProjectElementHasChild(final SWTBotTreeItem parentItem
, final String name
) {
333 fParentItem
= parentItem
;
335 /* Project element labels may have count suffix */
336 fRegex
= name
+ "(\\s\\[(\\d)+\\])?";
340 public boolean test() throws Exception
{
341 fParentItem
.expand();
342 for (SWTBotTreeItem item
: fParentItem
.getItems()) {
343 if (item
.getText().matches(fRegex
)) {
352 public String
getFailureMessage() {
353 return NLS
.bind("No child of {0} found with name {1}", fParentItem
.getText(), fName
);
357 * Returns the matching child item if the condition returned true.
359 * @return the matching item
361 public SWTBotTreeItem
getItem() {
367 * Condition to check if an editor with the specified title is opened.
373 * @return ICondition for verification
375 public static ICondition
isEditorOpened(final SWTWorkbenchBot bot
, final String title
) {
376 return new SWTBotTestCondition() {
378 public boolean test() throws Exception
{
379 Matcher
<IEditorReference
> withPartName
= withPartName(title
);
380 return !bot
.editors(withPartName
).isEmpty();
386 * Condition to check if the selection range equals the specified range.
389 * the selection range
390 * @return ICondition for verification
392 public static ICondition
selectionRange(final TmfTimeRange range
) {
393 return new SWTBotTestCondition() {
395 public boolean test() throws Exception
{
396 return TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange().equals(range
);
400 public String
getFailureMessage() {
401 return NLS
.bind("Selection range: {0} expected: {1}",
402 TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange(), range
);
408 * Condition to check if the window range equals the specified range.
412 * @return ICondition for verification
414 public static ICondition
windowRange(final TmfTimeRange range
) {
415 return new SWTBotTestCondition() {
417 public boolean test() throws Exception
{
418 return TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange().equals(range
);
422 public String
getFailureMessage() {
423 return NLS
.bind("Window range: {0} expected: {1}",
424 TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange(), range
);
430 * Condition to check if the selection contains the specified text at the
431 * specified column. The text is checked in any item of the tree selection.
439 * @return ICondition for verification
441 public static ICondition
treeSelectionContains(final SWTBotTree tree
, final int column
, final String text
) {
442 return new SWTBotTestCondition() {
444 public boolean test() throws Exception
{
445 TableCollection selection
= tree
.selection();
446 for (int row
= 0; row
< selection
.rowCount(); row
++) {
447 if (selection
.get(row
, column
).equals(text
)) {
455 public String
getFailureMessage() {
456 return NLS
.bind("Tree selection [0,{0}]: {1} expected: {2}",
457 new Object
[] { column
, tree
.selection().get(0, column
), text
});
462 private static class EventsTableSelectionCondition
extends DefaultCondition
{
463 private long fSelectionTime
;
464 private SWTWorkbenchBot fBot
;
465 private long fCurValue
;
467 private EventsTableSelectionCondition(SWTWorkbenchBot bot
, long selectionTime
) {
469 fSelectionTime
= selectionTime
;
473 public boolean test() throws Exception
{
474 StructuredSelection eventsTableSelection
= getEventsTableSelection();
475 if (eventsTableSelection
.isEmpty()) {
478 fCurValue
= ((ITmfEvent
) eventsTableSelection
.getFirstElement()).getTimestamp().getValue();
479 return fCurValue
== fSelectionTime
;
483 public String
getFailureMessage() {
484 return "The selection in the table was not an event with timestamp " + fSelectionTime
+ ". Actual is " + fCurValue
;
487 private StructuredSelection
getEventsTableSelection() {
488 return UIThreadRunnable
.syncExec(new Result
<StructuredSelection
>() {
491 public StructuredSelection
run() {
492 SWTBotEditor eventsEditor
= SWTBotUtils
.activeEventsEditor(fBot
);
493 TmfEventsEditor part
= (TmfEventsEditor
) eventsEditor
.getReference().getPart(false);
494 StructuredSelection selection
= (StructuredSelection
) part
.getSelection();
502 * Wait until the events table selection matches the specified time stamp.
507 * @param selectionTime
509 * @return ICondition for verification
511 public static ICondition
selectionInEventsTable(final SWTWorkbenchBot bot
, long selectionTime
) {
512 return new EventsTableSelectionCondition(bot
, selectionTime
);
515 private static class TimeGraphIsReadyCondition
extends DefaultCondition
{
517 private @NonNull TmfTimeRange fSelectionRange
;
518 private @NonNull ITmfTimestamp fVisibleTime
;
519 private AbstractTimeGraphView fView
;
520 private String fFailureMessage
;
522 private TimeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
524 fSelectionRange
= selectionRange
;
525 fVisibleTime
= visibleTime
;
529 public boolean test() throws Exception
{
530 ICondition selectionRangeCondition
= ConditionHelpers
.selectionRange(fSelectionRange
);
531 if (!selectionRangeCondition
.test()) {
532 fFailureMessage
= selectionRangeCondition
.getFailureMessage();
535 @NonNull TmfTimeRange curWindowRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange();
536 if (!curWindowRange
.contains(fVisibleTime
)) {
537 fFailureMessage
= "Current window range " + curWindowRange
+ " does not contain " + fVisibleTime
;
541 if (fView
.isDirty()) {
542 fFailureMessage
= "Time graph is dirty";
550 public String
getFailureMessage() {
551 return fFailureMessage
;
557 * Wait until the Time Graph view is ready. The Time Graph view is
558 * considered ready if the selectionRange is selected, the visibleTime is
559 * visible and the view is not dirty (its model is done updating).
562 * the time graph view
563 * @param selectionRange
564 * the selection that the time graph should have
566 * the visible time that the time graph should have
567 * @return ICondition for verification
569 public static ICondition
timeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
570 return new TimeGraphIsReadyCondition(view
, selectionRange
, visibleTime
);
573 private static class NumberOfEventsCondition
extends DefaultCondition
{
575 private ITmfTrace fTrace
;
576 private long fNbEvents
;
578 private NumberOfEventsCondition(ITmfTrace trace
, long nbEvents
) {
580 fNbEvents
= nbEvents
;
584 public boolean test() throws Exception
{
585 return fTrace
.getNbEvents() == fNbEvents
;
589 public String
getFailureMessage() {
590 return fTrace
.getName() + " did not contain the expected number of " + fNbEvents
+ " events. Current: " + fTrace
.getNbEvents();
595 * Wait until the trace contains the specified number of events.
600 * the number of events to wait for
601 * @return ICondition for verification
603 public static ICondition
numberOfEventsInTrace(ITmfTrace trace
, long nbEvents
) {
604 return new NumberOfEventsCondition(trace
, nbEvents
);
608 * Wait until there is an active events editor. A title can also be
609 * specified to wait until a more specific editor.
611 public static final class ActiveEventsEditor
extends DefaultCondition
{
612 private final SWTWorkbenchBot fWorkbenchBot
;
613 private SWTBotEditor fEditor
;
614 private String fEditorTitle
;
617 * Wait until there is an active events editor.
619 * @param workbenchBot
622 * If specified, wait until an active events editor with this
623 * title. Can be set to null.
625 public ActiveEventsEditor(SWTWorkbenchBot workbenchBot
, String editorTitle
) {
626 fWorkbenchBot
= workbenchBot
;
627 fEditorTitle
= editorTitle
;
631 public boolean test() throws Exception
{
632 List
<SWTBotEditor
> editors
= fWorkbenchBot
.editors(WidgetMatcherFactory
.withPartId(TmfEventsEditor
.ID
));
633 for (SWTBotEditor e
: editors
) {
634 // We are careful not to call e.getWidget() here because it actually forces the editor to show.
635 // This is especially a problem for cases where we wait until there is no active editor.
637 if (fEditorTitle
!= null && !fEditorTitle
.equals(e
.getTitle())) {
648 public String
getFailureMessage() {
649 String editorMessage
= fEditorTitle
!= null ?
" " + fEditorTitle
: "";
650 return "Active events editor" + editorMessage
+ " not found";
654 * @return The active editor found
656 public SWTBotEditor
getActiveEditor() {