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
;
21 import java
.util
.regex
.Pattern
;
23 import org
.eclipse
.jdt
.annotation
.NonNull
;
24 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
25 import org
.eclipse
.jface
.wizard
.IWizardContainer
;
26 import org
.eclipse
.jface
.wizard
.IWizardPage
;
27 import org
.eclipse
.jface
.wizard
.Wizard
;
28 import org
.eclipse
.osgi
.util
.NLS
;
29 import org
.eclipse
.swtbot
.eclipse
.finder
.SWTWorkbenchBot
;
30 import org
.eclipse
.swtbot
.eclipse
.finder
.matchers
.WidgetMatcherFactory
;
31 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotEditor
;
32 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotView
;
33 import org
.eclipse
.swtbot
.swt
.finder
.SWTBot
;
34 import org
.eclipse
.swtbot
.swt
.finder
.finders
.UIThreadRunnable
;
35 import org
.eclipse
.swtbot
.swt
.finder
.results
.Result
;
36 import org
.eclipse
.swtbot
.swt
.finder
.utils
.TableCollection
;
37 import org
.eclipse
.swtbot
.swt
.finder
.waits
.DefaultCondition
;
38 import org
.eclipse
.swtbot
.swt
.finder
.waits
.ICondition
;
39 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTable
;
40 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTree
;
41 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTreeItem
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
46 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
47 import org
.eclipse
.tracecompass
.tmf
.ui
.editors
.TmfEventsEditor
;
48 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.xycharts
.TmfXYChartViewer
;
49 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
.AbstractTimeGraphView
;
50 import org
.eclipse
.ui
.IEditorReference
;
51 import org
.hamcrest
.Matcher
;
52 import org
.swtchart
.Chart
;
55 * Is a tree node available
57 * @author Matthew Khouzam
59 public final class ConditionHelpers
{
61 private ConditionHelpers() {}
64 * Provide default implementations for some {@link ICondition} methods.
66 public abstract static class SWTBotTestCondition
implements ICondition
{
69 public abstract boolean test() throws Exception
;
72 public final void init(SWTBot bot
) {
76 public String
getFailureMessage() {
82 * Is a tree node available
85 * the name of the node
88 * @return true or false, it should swallow all exceptions
90 public static ICondition
IsTreeNodeAvailable(final String name
, final SWTBotTree tree
) {
91 return new SWTBotTestCondition() {
93 public boolean test() throws Exception
{
95 final SWTBotTreeItem
[] treeItems
= tree
.getAllItems();
96 for (SWTBotTreeItem ti
: treeItems
) {
97 final String text
= ti
.getText();
98 if (text
.equals(name
)) {
102 } catch (Exception e
) {
108 public String
getFailureMessage() {
109 return NLS
.bind("No child of tree {0} found with text {1}. Child items: {2}",
110 new String
[] { tree
.toString(), name
, Arrays
.toString(tree
.getAllItems()) });
116 * Is a table item available
119 * the name of the item
122 * @return true or false, it should swallow all exceptions
124 public static ICondition
isTableItemAvailable(final String name
, final SWTBotTable table
) {
125 return new SWTBotTestCondition() {
127 public boolean test() throws Exception
{
129 return table
.containsItem(name
);
130 } catch (Exception e
) {
136 public String
getFailureMessage() {
137 return NLS
.bind("No child of table {0} found with text ''{1}''.", table
, name
);
143 * Is the treeItem's node available
146 * the name of the node
149 * @return true or false, it should swallow all exceptions
151 public static ICondition
IsTreeChildNodeAvailable(final String name
, final SWTBotTreeItem treeItem
) {
152 return new SWTBotTestCondition() {
154 public boolean test() throws Exception
{
156 return treeItem
.getNode(name
) != null;
157 } catch (Exception e
) {
163 public String
getFailureMessage() {
164 return NLS
.bind("No child of tree item {0} found with text ''{1}''. Child items: {2}",
165 new String
[] { treeItem
.toString(), name
, Arrays
.toString(treeItem
.getItems()) });
171 * Is the treeItem's node removed
174 * length of the node after removal
177 * @return true or false, it should swallow all exceptions
179 public static ICondition
isTreeChildNodeRemoved(final int length
, final SWTBotTreeItem treeItem
) {
180 return new SWTBotTestCondition() {
182 public boolean test() throws Exception
{
184 return treeItem
.getNodes().size() == length
;
185 } catch (Exception e
) {
191 public String
getFailureMessage() {
192 return NLS
.bind("Child of tree item {0} found with text ''{1}'' not removed. Child items: {2}",
193 new String
[] { treeItem
.toString(), String
.valueOf(length
), Arrays
.toString(treeItem
.getItems()) });
199 * Condition to check if the number of direct children of the
200 * provided tree item equals the specified count.
203 * the SWTBot tree item
206 * @return ICondition for verification
208 public static ICondition
treeItemCount(final SWTBotTreeItem treeItem
, int count
) {
209 return new SWTBotTestCondition() {
211 public boolean test() throws Exception
{
212 return treeItem
.rowCount() == count
;
216 public String
getFailureMessage() {
217 return NLS
.bind("Tree item count: {0} expected: {1}",
218 treeItem
.rowCount(), count
);
224 * Checks if the wizard's shell is null
228 * @return false if either are null
230 public static ICondition
isWizardReady(final Wizard wizard
) {
231 return new SWTBotTestCondition() {
233 public boolean test() throws Exception
{
234 if (wizard
.getShell() == null) {
243 * Is the wizard on the page you want?
249 * @return true or false
251 public static ICondition
isWizardOnPage(final Wizard wizard
, final IWizardPage page
) {
252 return new SWTBotTestCondition() {
254 public boolean test() throws Exception
{
255 if (wizard
== null || page
== null) {
258 final IWizardContainer container
= wizard
.getContainer();
259 if (container
== null) {
262 IWizardPage currentPage
= container
.getCurrentPage();
263 return page
.equals(currentPage
);
269 * Wait for a view to close
272 * bot view for the view
273 * @return true if the view is closed, false if it's active.
275 public static ICondition
ViewIsClosed(final SWTBotView view
) {
276 return new SWTBotTestCondition() {
278 public boolean test() throws Exception
{
279 return (view
!= null) && (!view
.isActive());
285 * Wait till table cell has a given content.
288 * the table bot reference
290 * the content to check
292 * the row of the cell
294 * the column of the cell
295 * @return ICondition for verification
297 public static ICondition
isTableCellFilled(final SWTBotTable table
,
298 final String content
, final int row
, final int column
) {
299 return new SWTBotTestCondition() {
301 public boolean test() throws Exception
{
303 String cell
= table
.cell(row
, column
);
307 return cell
.contains(content
);
308 } catch (Exception e
) {
316 * Condition to check if a tracing project element has a child with the
317 * specified name. A project element label may have a count suffix in the
320 public static class ProjectElementHasChild
extends DefaultCondition
{
322 private final SWTBotTreeItem fParentItem
;
323 private final String fName
;
324 private final String fRegex
;
325 private SWTBotTreeItem fItem
= null;
333 * the child name to look for
335 public ProjectElementHasChild(final SWTBotTreeItem parentItem
, final String name
) {
336 fParentItem
= parentItem
;
338 /* Project element labels may have count suffix */
339 fRegex
= Pattern
.quote(name
) + "(\\s\\[(\\d)+\\])?";
343 public boolean test() throws Exception
{
344 fParentItem
.expand();
345 for (SWTBotTreeItem item
: fParentItem
.getItems()) {
346 if (item
.getText().matches(fRegex
)) {
355 public String
getFailureMessage() {
356 return NLS
.bind("No child of {0} found with name {1}", fParentItem
.getText(), fName
);
360 * Returns the matching child item if the condition returned true.
362 * @return the matching item
364 public SWTBotTreeItem
getItem() {
370 * Condition to check if an editor with the specified title is opened.
376 * @return ICondition for verification
378 public static ICondition
isEditorOpened(final SWTWorkbenchBot bot
, final String title
) {
379 return new SWTBotTestCondition() {
381 public boolean test() throws Exception
{
382 Matcher
<IEditorReference
> withPartName
= withPartName(title
);
383 return !bot
.editors(withPartName
).isEmpty();
389 * Condition to check if the selection range equals the specified range.
392 * the selection range
393 * @return ICondition for verification
395 public static ICondition
selectionRange(final TmfTimeRange range
) {
396 return new SWTBotTestCondition() {
398 public boolean test() throws Exception
{
399 return TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange().equals(range
);
403 public String
getFailureMessage() {
404 return NLS
.bind("Selection range: {0} expected: {1}",
405 TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange(), range
);
411 * Condition to check if the window range equals the specified range.
415 * @return ICondition for verification
417 public static ICondition
windowRange(final TmfTimeRange range
) {
418 return new SWTBotTestCondition() {
420 public boolean test() throws Exception
{
421 return TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange().equals(range
);
425 public String
getFailureMessage() {
426 return NLS
.bind("Window range: {0} expected: {1}",
427 TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange(), range
);
433 * Condition to check if the selection contains the specified text at the
434 * specified column. The text is checked in any item of the tree selection.
442 * @return ICondition for verification
444 public static ICondition
treeSelectionContains(final SWTBotTree tree
, final int column
, final String text
) {
445 return new SWTBotTestCondition() {
447 public boolean test() throws Exception
{
448 TableCollection selection
= tree
.selection();
449 for (int row
= 0; row
< selection
.rowCount(); row
++) {
450 if (selection
.get(row
, column
).equals(text
)) {
458 public String
getFailureMessage() {
459 return NLS
.bind("Tree selection [0,{0}]: {1} expected: {2}",
460 new Object
[] { column
, tree
.selection().get(0, column
), text
});
465 private static class EventsTableSelectionCondition
extends DefaultCondition
{
466 private long fSelectionTime
;
467 private SWTWorkbenchBot fBot
;
468 private long fCurValue
;
470 private EventsTableSelectionCondition(SWTWorkbenchBot bot
, long selectionTime
) {
472 fSelectionTime
= selectionTime
;
476 public boolean test() throws Exception
{
477 StructuredSelection eventsTableSelection
= getEventsTableSelection();
478 if (eventsTableSelection
.isEmpty()) {
481 fCurValue
= ((ITmfEvent
) eventsTableSelection
.getFirstElement()).getTimestamp().getValue();
482 return fCurValue
== fSelectionTime
;
486 public String
getFailureMessage() {
487 return "The selection in the table was not an event with timestamp " + fSelectionTime
+ ". Actual is " + fCurValue
;
490 private StructuredSelection
getEventsTableSelection() {
491 return UIThreadRunnable
.syncExec(new Result
<StructuredSelection
>() {
494 public StructuredSelection
run() {
495 SWTBotEditor eventsEditor
= SWTBotUtils
.activeEventsEditor(fBot
);
496 TmfEventsEditor part
= (TmfEventsEditor
) eventsEditor
.getReference().getPart(false);
497 StructuredSelection selection
= (StructuredSelection
) part
.getSelection();
505 * Wait until the events table selection matches the specified time stamp.
510 * @param selectionTime
512 * @return ICondition for verification
514 public static ICondition
selectionInEventsTable(final SWTWorkbenchBot bot
, long selectionTime
) {
515 return new EventsTableSelectionCondition(bot
, selectionTime
);
518 private static class TimeGraphIsReadyCondition
extends DefaultCondition
{
520 private @NonNull TmfTimeRange fSelectionRange
;
521 private @NonNull ITmfTimestamp fVisibleTime
;
522 private AbstractTimeGraphView fView
;
523 private String fFailureMessage
;
525 private TimeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
527 fSelectionRange
= selectionRange
;
528 fVisibleTime
= visibleTime
;
532 public boolean test() throws Exception
{
533 ICondition selectionRangeCondition
= ConditionHelpers
.selectionRange(fSelectionRange
);
534 if (!selectionRangeCondition
.test()) {
535 fFailureMessage
= selectionRangeCondition
.getFailureMessage();
538 @NonNull TmfTimeRange curWindowRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange();
539 if (!curWindowRange
.contains(fVisibleTime
)) {
540 fFailureMessage
= "Current window range " + curWindowRange
+ " does not contain " + fVisibleTime
;
544 if (fView
.isDirty()) {
545 fFailureMessage
= "Time graph is dirty";
553 public String
getFailureMessage() {
554 return fFailureMessage
;
560 * Wait until the Time Graph view is ready. The Time Graph view is
561 * considered ready if the selectionRange is selected, the visibleTime is
562 * visible and the view is not dirty (its model is done updating).
565 * the time graph view
566 * @param selectionRange
567 * the selection that the time graph should have
569 * the visible time that the time graph should have
570 * @return ICondition for verification
572 public static ICondition
timeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
573 return new TimeGraphIsReadyCondition(view
, selectionRange
, visibleTime
);
576 private static class XYViewerIsReadyCondition
extends DefaultCondition
{
578 private TmfXYChartViewer fViewer
;
579 private String fFailureMessage
;
581 private XYViewerIsReadyCondition(TmfXYChartViewer view
) {
586 public boolean test() throws Exception
{
588 if (fViewer
.isDirty()) {
589 fFailureMessage
= "Time graph is dirty";
596 public String
getFailureMessage() {
597 return fFailureMessage
;
603 * Wait until the XY chart viewer is ready. The XY chart viewer is
604 * considered ready when it is not updating.
607 * the XY chart viewer
608 * @return ICondition for verification
610 public static ICondition
xyViewerIsReadyCondition(TmfXYChartViewer viewer
) {
611 return new XYViewerIsReadyCondition(viewer
);
614 private static class NumberOfEventsCondition
extends DefaultCondition
{
616 private ITmfTrace fTrace
;
617 private long fNbEvents
;
619 private NumberOfEventsCondition(ITmfTrace trace
, long nbEvents
) {
621 fNbEvents
= nbEvents
;
625 public boolean test() throws Exception
{
626 return fTrace
.getNbEvents() == fNbEvents
;
630 public String
getFailureMessage() {
631 return fTrace
.getName() + " did not contain the expected number of " + fNbEvents
+ " events. Current: " + fTrace
.getNbEvents();
636 * Wait until the trace contains the specified number of events.
641 * the number of events to wait for
642 * @return ICondition for verification
644 public static ICondition
numberOfEventsInTrace(ITmfTrace trace
, long nbEvents
) {
645 return new NumberOfEventsCondition(trace
, nbEvents
);
649 * Wait until there is an active events editor. A title can also be
650 * specified to wait until a more specific editor.
652 public static final class ActiveEventsEditor
extends DefaultCondition
{
653 private final SWTWorkbenchBot fWorkbenchBot
;
654 private SWTBotEditor fEditor
;
655 private String fEditorTitle
;
658 * Wait until there is an active events editor.
660 * @param workbenchBot
663 * If specified, wait until an active events editor with this
664 * title. Can be set to null.
666 public ActiveEventsEditor(SWTWorkbenchBot workbenchBot
, String editorTitle
) {
667 fWorkbenchBot
= workbenchBot
;
668 fEditorTitle
= editorTitle
;
672 public boolean test() throws Exception
{
673 List
<SWTBotEditor
> editors
= fWorkbenchBot
.editors(WidgetMatcherFactory
.withPartId(TmfEventsEditor
.ID
));
674 for (SWTBotEditor e
: editors
) {
675 // We are careful not to call e.getWidget() here because it actually forces the editor to show.
676 // This is especially a problem for cases where we wait until there is no active editor.
678 if (fEditorTitle
!= null && !fEditorTitle
.equals(e
.getTitle())) {
689 public String
getFailureMessage() {
690 String editorMessage
= fEditorTitle
!= null ?
" " + fEditorTitle
: "";
691 return "Active events editor" + editorMessage
+ " not found";
695 * @return The active editor found
697 public SWTBotEditor
getActiveEditor() {
702 private static class NumberOfSeries
extends DefaultCondition
{
703 private String fFailureMessage
;
704 private Chart fChart
;
705 private final int fNumberOfSeries
;
707 public NumberOfSeries(Chart chart
, int numberOfSeries
) {
709 fNumberOfSeries
= numberOfSeries
;
713 public boolean test() throws Exception
{
714 int length
= fChart
.getSeriesSet().getSeries().length
;
715 if (length
!= fNumberOfSeries
){
716 fFailureMessage
= "Chart did not contain the expected number series. Actual " + length
+ ", expected " + fNumberOfSeries
;
724 public String
getFailureMessage() {
725 return fFailureMessage
;
730 * Wait until the chart has the specified number of series.
734 * @param numberOfSeries
735 * the number of expected series
737 * @return ICondition for verification
739 public static ICondition
numberOfSeries(Chart chart
, int numberOfSeries
) {
740 return new NumberOfSeries(chart
, numberOfSeries
);
744 * Condition to check if the tree item has children
747 * the tree item that should have children
748 * @return ICondition for verification
750 public static ICondition
treeItemHasChildren(SWTBotTreeItem treeItem
) {
751 return new TreeItemHasChildren(treeItem
);
754 private static final class TreeItemHasChildren
extends DefaultCondition
{
755 private SWTBotTreeItem fTreeItem
;
757 public TreeItemHasChildren(SWTBotTreeItem treeItem
) {
758 fTreeItem
= treeItem
;
762 public boolean test() throws Exception
{
763 return fTreeItem
.getItems().length
> 0;
767 public String
getFailureMessage() {
768 return NLS
.bind("No child of tree item {0} found.", new String
[] { fTreeItem
.toString() });