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
.views
.timegraph
.AbstractTimeGraphView
;
49 import org
.eclipse
.ui
.IEditorReference
;
50 import org
.hamcrest
.Matcher
;
51 import org
.swtchart
.Chart
;
54 * Is a tree node available
56 * @author Matthew Khouzam
58 public final class ConditionHelpers
{
60 private ConditionHelpers() {}
63 * Provide default implementations for some {@link ICondition} methods.
65 public abstract static class SWTBotTestCondition
implements ICondition
{
68 public abstract boolean test() throws Exception
;
71 public final void init(SWTBot bot
) {
75 public String
getFailureMessage() {
81 * Is a tree node available
84 * the name of the node
87 * @return true or false, it should swallow all exceptions
89 public static ICondition
IsTreeNodeAvailable(final String name
, final SWTBotTree tree
) {
90 return new SWTBotTestCondition() {
92 public boolean test() throws Exception
{
94 final SWTBotTreeItem
[] treeItems
= tree
.getAllItems();
95 for (SWTBotTreeItem ti
: treeItems
) {
96 final String text
= ti
.getText();
97 if (text
.equals(name
)) {
101 } catch (Exception e
) {
107 public String
getFailureMessage() {
108 return NLS
.bind("No child of tree {0} found with text {1}. Child items: {2}",
109 new String
[] { tree
.toString(), name
, Arrays
.toString(tree
.getAllItems()) });
115 * Is a table item available
118 * the name of the item
121 * @return true or false, it should swallow all exceptions
123 public static ICondition
isTableItemAvailable(final String name
, final SWTBotTable table
) {
124 return new SWTBotTestCondition() {
126 public boolean test() throws Exception
{
128 return table
.containsItem(name
);
129 } catch (Exception e
) {
135 public String
getFailureMessage() {
136 return NLS
.bind("No child of table {0} found with text ''{1}''.", table
, name
);
142 * Is the treeItem's node available
145 * the name of the node
148 * @return true or false, it should swallow all exceptions
150 public static ICondition
IsTreeChildNodeAvailable(final String name
, final SWTBotTreeItem treeItem
) {
151 return new SWTBotTestCondition() {
153 public boolean test() throws Exception
{
155 return treeItem
.getNode(name
) != null;
156 } catch (Exception e
) {
162 public String
getFailureMessage() {
163 return NLS
.bind("No child of tree item {0} found with text ''{1}''. Child items: {2}",
164 new String
[] { treeItem
.toString(), name
, Arrays
.toString(treeItem
.getItems()) });
170 * Is the treeItem's node removed
173 * length of the node after removal
176 * @return true or false, it should swallow all exceptions
178 public static ICondition
isTreeChildNodeRemoved(final int length
, final SWTBotTreeItem treeItem
) {
179 return new SWTBotTestCondition() {
181 public boolean test() throws Exception
{
183 return treeItem
.getNodes().size() == length
;
184 } catch (Exception e
) {
190 public String
getFailureMessage() {
191 return NLS
.bind("Child of tree item {0} found with text ''{1}'' not removed. Child items: {2}",
192 new String
[] { treeItem
.toString(), String
.valueOf(length
), Arrays
.toString(treeItem
.getItems()) });
198 * Condition to check if the number of direct children of the
199 * provided tree item equals the specified count.
202 * the SWTBot tree item
205 * @return ICondition for verification
207 public static ICondition
treeItemCount(final SWTBotTreeItem treeItem
, int count
) {
208 return new SWTBotTestCondition() {
210 public boolean test() throws Exception
{
211 return treeItem
.rowCount() == count
;
215 public String
getFailureMessage() {
216 return NLS
.bind("Tree item count: {0} expected: {1}",
217 treeItem
.rowCount(), count
);
223 * Checks if the wizard's shell is null
227 * @return false if either are null
229 public static ICondition
isWizardReady(final Wizard wizard
) {
230 return new SWTBotTestCondition() {
232 public boolean test() throws Exception
{
233 if (wizard
.getShell() == null) {
242 * Is the wizard on the page you want?
248 * @return true or false
250 public static ICondition
isWizardOnPage(final Wizard wizard
, final IWizardPage page
) {
251 return new SWTBotTestCondition() {
253 public boolean test() throws Exception
{
254 if (wizard
== null || page
== null) {
257 final IWizardContainer container
= wizard
.getContainer();
258 if (container
== null) {
261 IWizardPage currentPage
= container
.getCurrentPage();
262 return page
.equals(currentPage
);
268 * Wait for a view to close
271 * bot view for the view
272 * @return true if the view is closed, false if it's active.
274 public static ICondition
ViewIsClosed(final SWTBotView view
) {
275 return new SWTBotTestCondition() {
277 public boolean test() throws Exception
{
278 return (view
!= null) && (!view
.isActive());
284 * Wait till table cell has a given content.
287 * the table bot reference
289 * the content to check
291 * the row of the cell
293 * the column of the cell
294 * @return ICondition for verification
296 public static ICondition
isTableCellFilled(final SWTBotTable table
,
297 final String content
, final int row
, final int column
) {
298 return new SWTBotTestCondition() {
300 public boolean test() throws Exception
{
302 String cell
= table
.cell(row
, column
);
306 return cell
.contains(content
);
307 } catch (Exception e
) {
315 * Condition to check if a tracing project element has a child with the
316 * specified name. A project element label may have a count suffix in the
319 public static class ProjectElementHasChild
extends DefaultCondition
{
321 private final SWTBotTreeItem fParentItem
;
322 private final String fName
;
323 private final String fRegex
;
324 private SWTBotTreeItem fItem
= null;
332 * the child name to look for
334 public ProjectElementHasChild(final SWTBotTreeItem parentItem
, final String name
) {
335 fParentItem
= parentItem
;
337 /* Project element labels may have count suffix */
338 fRegex
= Pattern
.quote(name
) + "(\\s\\[(\\d)+\\])?";
342 public boolean test() throws Exception
{
343 fParentItem
.expand();
344 for (SWTBotTreeItem item
: fParentItem
.getItems()) {
345 if (item
.getText().matches(fRegex
)) {
354 public String
getFailureMessage() {
355 return NLS
.bind("No child of {0} found with name {1}", fParentItem
.getText(), fName
);
359 * Returns the matching child item if the condition returned true.
361 * @return the matching item
363 public SWTBotTreeItem
getItem() {
369 * Condition to check if an editor with the specified title is opened.
375 * @return ICondition for verification
377 public static ICondition
isEditorOpened(final SWTWorkbenchBot bot
, final String title
) {
378 return new SWTBotTestCondition() {
380 public boolean test() throws Exception
{
381 Matcher
<IEditorReference
> withPartName
= withPartName(title
);
382 return !bot
.editors(withPartName
).isEmpty();
388 * Condition to check if the selection range equals the specified range.
391 * the selection range
392 * @return ICondition for verification
394 public static ICondition
selectionRange(final TmfTimeRange range
) {
395 return new SWTBotTestCondition() {
397 public boolean test() throws Exception
{
398 return TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange().equals(range
);
402 public String
getFailureMessage() {
403 return NLS
.bind("Selection range: {0} expected: {1}",
404 TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange(), range
);
410 * Condition to check if the window range equals the specified range.
414 * @return ICondition for verification
416 public static ICondition
windowRange(final TmfTimeRange range
) {
417 return new SWTBotTestCondition() {
419 public boolean test() throws Exception
{
420 return TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange().equals(range
);
424 public String
getFailureMessage() {
425 return NLS
.bind("Window range: {0} expected: {1}",
426 TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange(), range
);
432 * Condition to check if the selection contains the specified text at the
433 * specified column. The text is checked in any item of the tree selection.
441 * @return ICondition for verification
443 public static ICondition
treeSelectionContains(final SWTBotTree tree
, final int column
, final String text
) {
444 return new SWTBotTestCondition() {
446 public boolean test() throws Exception
{
447 TableCollection selection
= tree
.selection();
448 for (int row
= 0; row
< selection
.rowCount(); row
++) {
449 if (selection
.get(row
, column
).equals(text
)) {
457 public String
getFailureMessage() {
458 return NLS
.bind("Tree selection [0,{0}]: {1} expected: {2}",
459 new Object
[] { column
, tree
.selection().get(0, column
), text
});
464 private static class EventsTableSelectionCondition
extends DefaultCondition
{
465 private long fSelectionTime
;
466 private SWTWorkbenchBot fBot
;
467 private long fCurValue
;
469 private EventsTableSelectionCondition(SWTWorkbenchBot bot
, long selectionTime
) {
471 fSelectionTime
= selectionTime
;
475 public boolean test() throws Exception
{
476 StructuredSelection eventsTableSelection
= getEventsTableSelection();
477 if (eventsTableSelection
.isEmpty()) {
480 fCurValue
= ((ITmfEvent
) eventsTableSelection
.getFirstElement()).getTimestamp().getValue();
481 return fCurValue
== fSelectionTime
;
485 public String
getFailureMessage() {
486 return "The selection in the table was not an event with timestamp " + fSelectionTime
+ ". Actual is " + fCurValue
;
489 private StructuredSelection
getEventsTableSelection() {
490 return UIThreadRunnable
.syncExec(new Result
<StructuredSelection
>() {
493 public StructuredSelection
run() {
494 SWTBotEditor eventsEditor
= SWTBotUtils
.activeEventsEditor(fBot
);
495 TmfEventsEditor part
= (TmfEventsEditor
) eventsEditor
.getReference().getPart(false);
496 StructuredSelection selection
= (StructuredSelection
) part
.getSelection();
504 * Wait until the events table selection matches the specified time stamp.
509 * @param selectionTime
511 * @return ICondition for verification
513 public static ICondition
selectionInEventsTable(final SWTWorkbenchBot bot
, long selectionTime
) {
514 return new EventsTableSelectionCondition(bot
, selectionTime
);
517 private static class TimeGraphIsReadyCondition
extends DefaultCondition
{
519 private @NonNull TmfTimeRange fSelectionRange
;
520 private @NonNull ITmfTimestamp fVisibleTime
;
521 private AbstractTimeGraphView fView
;
522 private String fFailureMessage
;
524 private TimeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
526 fSelectionRange
= selectionRange
;
527 fVisibleTime
= visibleTime
;
531 public boolean test() throws Exception
{
532 ICondition selectionRangeCondition
= ConditionHelpers
.selectionRange(fSelectionRange
);
533 if (!selectionRangeCondition
.test()) {
534 fFailureMessage
= selectionRangeCondition
.getFailureMessage();
537 @NonNull TmfTimeRange curWindowRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange();
538 if (!curWindowRange
.contains(fVisibleTime
)) {
539 fFailureMessage
= "Current window range " + curWindowRange
+ " does not contain " + fVisibleTime
;
543 if (fView
.isDirty()) {
544 fFailureMessage
= "Time graph is dirty";
552 public String
getFailureMessage() {
553 return fFailureMessage
;
559 * Wait until the Time Graph view is ready. The Time Graph view is
560 * considered ready if the selectionRange is selected, the visibleTime is
561 * visible and the view is not dirty (its model is done updating).
564 * the time graph view
565 * @param selectionRange
566 * the selection that the time graph should have
568 * the visible time that the time graph should have
569 * @return ICondition for verification
571 public static ICondition
timeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
572 return new TimeGraphIsReadyCondition(view
, selectionRange
, visibleTime
);
575 private static class NumberOfEventsCondition
extends DefaultCondition
{
577 private ITmfTrace fTrace
;
578 private long fNbEvents
;
580 private NumberOfEventsCondition(ITmfTrace trace
, long nbEvents
) {
582 fNbEvents
= nbEvents
;
586 public boolean test() throws Exception
{
587 return fTrace
.getNbEvents() == fNbEvents
;
591 public String
getFailureMessage() {
592 return fTrace
.getName() + " did not contain the expected number of " + fNbEvents
+ " events. Current: " + fTrace
.getNbEvents();
597 * Wait until the trace contains the specified number of events.
602 * the number of events to wait for
603 * @return ICondition for verification
605 public static ICondition
numberOfEventsInTrace(ITmfTrace trace
, long nbEvents
) {
606 return new NumberOfEventsCondition(trace
, nbEvents
);
610 * Wait until there is an active events editor. A title can also be
611 * specified to wait until a more specific editor.
613 public static final class ActiveEventsEditor
extends DefaultCondition
{
614 private final SWTWorkbenchBot fWorkbenchBot
;
615 private SWTBotEditor fEditor
;
616 private String fEditorTitle
;
619 * Wait until there is an active events editor.
621 * @param workbenchBot
624 * If specified, wait until an active events editor with this
625 * title. Can be set to null.
627 public ActiveEventsEditor(SWTWorkbenchBot workbenchBot
, String editorTitle
) {
628 fWorkbenchBot
= workbenchBot
;
629 fEditorTitle
= editorTitle
;
633 public boolean test() throws Exception
{
634 List
<SWTBotEditor
> editors
= fWorkbenchBot
.editors(WidgetMatcherFactory
.withPartId(TmfEventsEditor
.ID
));
635 for (SWTBotEditor e
: editors
) {
636 // We are careful not to call e.getWidget() here because it actually forces the editor to show.
637 // This is especially a problem for cases where we wait until there is no active editor.
639 if (fEditorTitle
!= null && !fEditorTitle
.equals(e
.getTitle())) {
650 public String
getFailureMessage() {
651 String editorMessage
= fEditorTitle
!= null ?
" " + fEditorTitle
: "";
652 return "Active events editor" + editorMessage
+ " not found";
656 * @return The active editor found
658 public SWTBotEditor
getActiveEditor() {
663 private static class NumberOfSeries
extends DefaultCondition
{
664 private String fFailureMessage
;
665 private Chart fChart
;
666 private final int fNumberOfSeries
;
668 public NumberOfSeries(Chart chart
, int numberOfSeries
) {
670 fNumberOfSeries
= numberOfSeries
;
674 public boolean test() throws Exception
{
675 int length
= fChart
.getSeriesSet().getSeries().length
;
676 if (length
!= fNumberOfSeries
){
677 fFailureMessage
= "Chart did not contain the expected number series. Actual " + length
+ ", expected " + fNumberOfSeries
;
685 public String
getFailureMessage() {
686 return fFailureMessage
;
691 * Wait until the chart has the specified number of series.
695 * @param numberOfSeries
696 * the number of expected series
698 * @return ICondition for verification
700 public static ICondition
numberOfSeries(Chart chart
, int numberOfSeries
) {
701 return new NumberOfSeries(chart
, numberOfSeries
);
705 * Condition to check if the tree item has children
708 * the tree item that should have children
709 * @return ICondition for verification
711 public static ICondition
treeItemHasChildren(SWTBotTreeItem treeItem
) {
712 return new TreeItemHasChildren(treeItem
);
715 private static final class TreeItemHasChildren
extends DefaultCondition
{
716 private SWTBotTreeItem fTreeItem
;
718 public TreeItemHasChildren(SWTBotTreeItem treeItem
) {
719 fTreeItem
= treeItem
;
723 public boolean test() throws Exception
{
724 return fTreeItem
.getItems().length
> 0;
728 public String
getFailureMessage() {
729 return NLS
.bind("No child of tree item {0} found.", new String
[] { fTreeItem
.toString() });