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
;
50 import org
.swtchart
.Chart
;
53 * Is a tree node available
55 * @author Matthew Khouzam
57 public final class ConditionHelpers
{
59 private ConditionHelpers() {}
62 * Provide default implementations for some {@link ICondition} methods.
64 public abstract static class SWTBotTestCondition
implements ICondition
{
67 public abstract boolean test() throws Exception
;
70 public final void init(SWTBot bot
) {
74 public String
getFailureMessage() {
80 * Is a tree node available
83 * the name of the node
86 * @return true or false, it should swallow all exceptions
88 public static ICondition
IsTreeNodeAvailable(final String name
, final SWTBotTree tree
) {
89 return new SWTBotTestCondition() {
91 public boolean test() throws Exception
{
93 final SWTBotTreeItem
[] treeItems
= tree
.getAllItems();
94 for (SWTBotTreeItem ti
: treeItems
) {
95 final String text
= ti
.getText();
96 if (text
.equals(name
)) {
100 } catch (Exception e
) {
106 public String
getFailureMessage() {
107 return NLS
.bind("No child of tree {0} found with text {1}. Child items: {2}",
108 new String
[] { tree
.toString(), name
, Arrays
.toString(tree
.getAllItems()) });
114 * Is a table item available
117 * the name of the item
120 * @return true or false, it should swallow all exceptions
122 public static ICondition
isTableItemAvailable(final String name
, final SWTBotTable table
) {
123 return new SWTBotTestCondition() {
125 public boolean test() throws Exception
{
127 return table
.containsItem(name
);
128 } catch (Exception e
) {
134 public String
getFailureMessage() {
135 return NLS
.bind("No child of table {0} found with text '{1}'.", table
, name
);
141 * Is the treeItem's node available
144 * the name of the node
147 * @return true or false, it should swallow all exceptions
149 public static ICondition
IsTreeChildNodeAvailable(final String name
, final SWTBotTreeItem treeItem
) {
150 return new SWTBotTestCondition() {
152 public boolean test() throws Exception
{
154 return treeItem
.getNode(name
) != null;
155 } catch (Exception e
) {
161 public String
getFailureMessage() {
162 return NLS
.bind("No child of tree item {0} found with text '{1}'. Child items: {2}",
163 new String
[] { treeItem
.toString(), name
, Arrays
.toString(treeItem
.getItems()) });
169 * Is the treeItem's node removed
172 * length of the node after removal
175 * @return true or false, it should swallow all exceptions
177 public static ICondition
isTreeChildNodeRemoved(final int length
, final SWTBotTreeItem treeItem
) {
178 return new SWTBotTestCondition() {
180 public boolean test() throws Exception
{
182 return treeItem
.getNodes().size() == length
;
183 } catch (Exception e
) {
189 public String
getFailureMessage() {
190 return NLS
.bind("Child of tree item {0} found with text '{1}' not removed. Child items: {2}",
191 new String
[] { treeItem
.toString(), String
.valueOf(length
), Arrays
.toString(treeItem
.getItems()) });
197 * Condition to check if the number of direct children of the
198 * provided tree item equals the specified count.
201 * the SWTBot tree item
204 * @return ICondition for verification
206 public static ICondition
treeItemCount(final SWTBotTreeItem treeItem
, int count
) {
207 return new SWTBotTestCondition() {
209 public boolean test() throws Exception
{
210 return treeItem
.rowCount() == count
;
214 public String
getFailureMessage() {
215 return NLS
.bind("Tree item count: {0} expected: {1}",
216 treeItem
.rowCount(), count
);
222 * Checks if the wizard's shell is null
226 * @return false if either are null
228 public static ICondition
isWizardReady(final Wizard wizard
) {
229 return new SWTBotTestCondition() {
231 public boolean test() throws Exception
{
232 if (wizard
.getShell() == null) {
241 * Is the wizard on the page you want?
247 * @return true or false
249 public static ICondition
isWizardOnPage(final Wizard wizard
, final IWizardPage page
) {
250 return new SWTBotTestCondition() {
252 public boolean test() throws Exception
{
253 if (wizard
== null || page
== null) {
256 final IWizardContainer container
= wizard
.getContainer();
257 if (container
== null) {
260 IWizardPage currentPage
= container
.getCurrentPage();
261 return page
.equals(currentPage
);
267 * Wait for a view to close
270 * bot view for the view
271 * @return true if the view is closed, false if it's active.
273 public static ICondition
ViewIsClosed(final SWTBotView view
) {
274 return new SWTBotTestCondition() {
276 public boolean test() throws Exception
{
277 return (view
!= null) && (!view
.isActive());
283 * Wait till table cell has a given content.
286 * the table bot reference
288 * the content to check
290 * the row of the cell
292 * the column of the cell
293 * @return ICondition for verification
295 public static ICondition
isTableCellFilled(final SWTBotTable table
,
296 final String content
, final int row
, final int column
) {
297 return new SWTBotTestCondition() {
299 public boolean test() throws Exception
{
301 String cell
= table
.cell(row
, column
);
305 return cell
.contains(content
);
306 } catch (Exception e
) {
314 * Condition to check if a tracing project element has a child with the
315 * specified name. A project element label may have a count suffix in the
318 public static class ProjectElementHasChild
extends DefaultCondition
{
320 private final SWTBotTreeItem fParentItem
;
321 private final String fName
;
322 private final String fRegex
;
323 private SWTBotTreeItem fItem
= null;
331 * the child name to look for
333 public ProjectElementHasChild(final SWTBotTreeItem parentItem
, final String name
) {
334 fParentItem
= parentItem
;
336 /* Project element labels may have count suffix */
337 fRegex
= name
+ "(\\s\\[(\\d)+\\])?";
341 public boolean test() throws Exception
{
342 fParentItem
.expand();
343 for (SWTBotTreeItem item
: fParentItem
.getItems()) {
344 if (item
.getText().matches(fRegex
)) {
353 public String
getFailureMessage() {
354 return NLS
.bind("No child of {0} found with name {1}", fParentItem
.getText(), fName
);
358 * Returns the matching child item if the condition returned true.
360 * @return the matching item
362 public SWTBotTreeItem
getItem() {
368 * Condition to check if an editor with the specified title is opened.
374 * @return ICondition for verification
376 public static ICondition
isEditorOpened(final SWTWorkbenchBot bot
, final String title
) {
377 return new SWTBotTestCondition() {
379 public boolean test() throws Exception
{
380 Matcher
<IEditorReference
> withPartName
= withPartName(title
);
381 return !bot
.editors(withPartName
).isEmpty();
387 * Condition to check if the selection range equals the specified range.
390 * the selection range
391 * @return ICondition for verification
393 public static ICondition
selectionRange(final TmfTimeRange range
) {
394 return new SWTBotTestCondition() {
396 public boolean test() throws Exception
{
397 return TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange().equals(range
);
401 public String
getFailureMessage() {
402 return NLS
.bind("Selection range: {0} expected: {1}",
403 TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange(), range
);
409 * Condition to check if the window range equals the specified range.
413 * @return ICondition for verification
415 public static ICondition
windowRange(final TmfTimeRange range
) {
416 return new SWTBotTestCondition() {
418 public boolean test() throws Exception
{
419 return TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange().equals(range
);
423 public String
getFailureMessage() {
424 return NLS
.bind("Window range: {0} expected: {1}",
425 TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange(), range
);
431 * Condition to check if the selection contains the specified text at the
432 * specified column. The text is checked in any item of the tree selection.
440 * @return ICondition for verification
442 public static ICondition
treeSelectionContains(final SWTBotTree tree
, final int column
, final String text
) {
443 return new SWTBotTestCondition() {
445 public boolean test() throws Exception
{
446 TableCollection selection
= tree
.selection();
447 for (int row
= 0; row
< selection
.rowCount(); row
++) {
448 if (selection
.get(row
, column
).equals(text
)) {
456 public String
getFailureMessage() {
457 return NLS
.bind("Tree selection [0,{0}]: {1} expected: {2}",
458 new Object
[] { column
, tree
.selection().get(0, column
), text
});
463 private static class EventsTableSelectionCondition
extends DefaultCondition
{
464 private long fSelectionTime
;
465 private SWTWorkbenchBot fBot
;
466 private long fCurValue
;
468 private EventsTableSelectionCondition(SWTWorkbenchBot bot
, long selectionTime
) {
470 fSelectionTime
= selectionTime
;
474 public boolean test() throws Exception
{
475 StructuredSelection eventsTableSelection
= getEventsTableSelection();
476 if (eventsTableSelection
.isEmpty()) {
479 fCurValue
= ((ITmfEvent
) eventsTableSelection
.getFirstElement()).getTimestamp().getValue();
480 return fCurValue
== fSelectionTime
;
484 public String
getFailureMessage() {
485 return "The selection in the table was not an event with timestamp " + fSelectionTime
+ ". Actual is " + fCurValue
;
488 private StructuredSelection
getEventsTableSelection() {
489 return UIThreadRunnable
.syncExec(new Result
<StructuredSelection
>() {
492 public StructuredSelection
run() {
493 SWTBotEditor eventsEditor
= SWTBotUtils
.activeEventsEditor(fBot
);
494 TmfEventsEditor part
= (TmfEventsEditor
) eventsEditor
.getReference().getPart(false);
495 StructuredSelection selection
= (StructuredSelection
) part
.getSelection();
503 * Wait until the events table selection matches the specified time stamp.
508 * @param selectionTime
510 * @return ICondition for verification
512 public static ICondition
selectionInEventsTable(final SWTWorkbenchBot bot
, long selectionTime
) {
513 return new EventsTableSelectionCondition(bot
, selectionTime
);
516 private static class TimeGraphIsReadyCondition
extends DefaultCondition
{
518 private @NonNull TmfTimeRange fSelectionRange
;
519 private @NonNull ITmfTimestamp fVisibleTime
;
520 private AbstractTimeGraphView fView
;
521 private String fFailureMessage
;
523 private TimeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
525 fSelectionRange
= selectionRange
;
526 fVisibleTime
= visibleTime
;
530 public boolean test() throws Exception
{
531 ICondition selectionRangeCondition
= ConditionHelpers
.selectionRange(fSelectionRange
);
532 if (!selectionRangeCondition
.test()) {
533 fFailureMessage
= selectionRangeCondition
.getFailureMessage();
536 @NonNull TmfTimeRange curWindowRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange();
537 if (!curWindowRange
.contains(fVisibleTime
)) {
538 fFailureMessage
= "Current window range " + curWindowRange
+ " does not contain " + fVisibleTime
;
542 if (fView
.isDirty()) {
543 fFailureMessage
= "Time graph is dirty";
551 public String
getFailureMessage() {
552 return fFailureMessage
;
558 * Wait until the Time Graph view is ready. The Time Graph view is
559 * considered ready if the selectionRange is selected, the visibleTime is
560 * visible and the view is not dirty (its model is done updating).
563 * the time graph view
564 * @param selectionRange
565 * the selection that the time graph should have
567 * the visible time that the time graph should have
568 * @return ICondition for verification
570 public static ICondition
timeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
571 return new TimeGraphIsReadyCondition(view
, selectionRange
, visibleTime
);
574 private static class NumberOfEventsCondition
extends DefaultCondition
{
576 private ITmfTrace fTrace
;
577 private long fNbEvents
;
579 private NumberOfEventsCondition(ITmfTrace trace
, long nbEvents
) {
581 fNbEvents
= nbEvents
;
585 public boolean test() throws Exception
{
586 return fTrace
.getNbEvents() == fNbEvents
;
590 public String
getFailureMessage() {
591 return fTrace
.getName() + " did not contain the expected number of " + fNbEvents
+ " events. Current: " + fTrace
.getNbEvents();
596 * Wait until the trace contains the specified number of events.
601 * the number of events to wait for
602 * @return ICondition for verification
604 public static ICondition
numberOfEventsInTrace(ITmfTrace trace
, long nbEvents
) {
605 return new NumberOfEventsCondition(trace
, nbEvents
);
609 * Wait until there is an active events editor. A title can also be
610 * specified to wait until a more specific editor.
612 public static final class ActiveEventsEditor
extends DefaultCondition
{
613 private final SWTWorkbenchBot fWorkbenchBot
;
614 private SWTBotEditor fEditor
;
615 private String fEditorTitle
;
618 * Wait until there is an active events editor.
620 * @param workbenchBot
623 * If specified, wait until an active events editor with this
624 * title. Can be set to null.
626 public ActiveEventsEditor(SWTWorkbenchBot workbenchBot
, String editorTitle
) {
627 fWorkbenchBot
= workbenchBot
;
628 fEditorTitle
= editorTitle
;
632 public boolean test() throws Exception
{
633 List
<SWTBotEditor
> editors
= fWorkbenchBot
.editors(WidgetMatcherFactory
.withPartId(TmfEventsEditor
.ID
));
634 for (SWTBotEditor e
: editors
) {
635 // We are careful not to call e.getWidget() here because it actually forces the editor to show.
636 // This is especially a problem for cases where we wait until there is no active editor.
638 if (fEditorTitle
!= null && !fEditorTitle
.equals(e
.getTitle())) {
649 public String
getFailureMessage() {
650 String editorMessage
= fEditorTitle
!= null ?
" " + fEditorTitle
: "";
651 return "Active events editor" + editorMessage
+ " not found";
655 * @return The active editor found
657 public SWTBotEditor
getActiveEditor() {
662 private static class NumberOfSeries
extends DefaultCondition
{
663 private String fFailureMessage
;
664 private Chart fChart
;
665 private final int fNumberOfSeries
;
667 public NumberOfSeries(Chart chart
, int numberOfSeries
) {
669 fNumberOfSeries
= numberOfSeries
;
673 public boolean test() throws Exception
{
674 int length
= fChart
.getSeriesSet().getSeries().length
;
675 if (length
!= fNumberOfSeries
){
676 fFailureMessage
= "Chart did not contain the expected number series. Actual " + length
+ ", expected " + fNumberOfSeries
;
684 public String
getFailureMessage() {
685 return fFailureMessage
;
690 * Wait until the chart has the specified number of series.
694 * @param numberOfSeries
695 * the number of expected series
697 * @return ICondition for verification
699 public static ICondition
numberOfSeries(Chart chart
, int numberOfSeries
) {
700 return new NumberOfSeries(chart
, numberOfSeries
);
704 * Condition to check if the tree item has children
707 * the tree item that should have children
708 * @return ICondition for verification
710 public static ICondition
treeItemHasChildren(SWTBotTreeItem treeItem
) {
711 return new TreeItemHasChildren(treeItem
);
714 private static final class TreeItemHasChildren
extends DefaultCondition
{
715 private SWTBotTreeItem fTreeItem
;
717 public TreeItemHasChildren(SWTBotTreeItem treeItem
) {
718 fTreeItem
= treeItem
;
722 public boolean test() throws Exception
{
723 return fTreeItem
.getItems().length
> 0;
727 public String
getFailureMessage() {
728 return NLS
.bind("No child of tree item {0} found.", new String
[] { fTreeItem
.toString() });