1 /*******************************************************************************
2 * Copyright (c) 2013, 2015 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
;
21 import org
.eclipse
.jdt
.annotation
.NonNull
;
22 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
23 import org
.eclipse
.jface
.wizard
.IWizardContainer
;
24 import org
.eclipse
.jface
.wizard
.IWizardPage
;
25 import org
.eclipse
.jface
.wizard
.Wizard
;
26 import org
.eclipse
.osgi
.util
.NLS
;
27 import org
.eclipse
.swtbot
.eclipse
.finder
.SWTWorkbenchBot
;
28 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotEditor
;
29 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotView
;
30 import org
.eclipse
.swtbot
.swt
.finder
.SWTBot
;
31 import org
.eclipse
.swtbot
.swt
.finder
.finders
.UIThreadRunnable
;
32 import org
.eclipse
.swtbot
.swt
.finder
.results
.Result
;
33 import org
.eclipse
.swtbot
.swt
.finder
.utils
.TableCollection
;
34 import org
.eclipse
.swtbot
.swt
.finder
.waits
.DefaultCondition
;
35 import org
.eclipse
.swtbot
.swt
.finder
.waits
.ICondition
;
36 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTable
;
37 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTree
;
38 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTreeItem
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
43 import org
.eclipse
.tracecompass
.tmf
.ui
.editors
.TmfEventsEditor
;
44 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
.AbstractTimeGraphView
;
45 import org
.eclipse
.ui
.IEditorReference
;
46 import org
.hamcrest
.Matcher
;
49 * Is a tree node available
51 * @author Matthew Khouzam
53 public final class ConditionHelpers
{
55 private ConditionHelpers() {}
58 * Provide default implementations for some {@link ICondition} methods.
60 public abstract static class SWTBotTestCondition
implements ICondition
{
63 public abstract boolean test() throws Exception
;
66 public final void init(SWTBot bot
) {
70 public String
getFailureMessage() {
76 * Is a tree node available
79 * the name of the node
82 * @return true or false, it should swallow all exceptions
84 public static ICondition
IsTreeNodeAvailable(final String name
, final SWTBotTree tree
) {
85 return new SWTBotTestCondition() {
87 public boolean test() throws Exception
{
89 final SWTBotTreeItem
[] treeItems
= tree
.getAllItems();
90 for (SWTBotTreeItem ti
: treeItems
) {
91 final String text
= ti
.getText();
92 if (text
.equals(name
)) {
96 } catch (Exception e
) {
102 public String
getFailureMessage() {
103 return NLS
.bind("No child of tree {0} found with text '{1}'. Child items: {2}",
104 new String
[] { tree
.toString(), name
, Arrays
.toString(tree
.getAllItems()) });
110 * Is a table item available
113 * the name of the item
116 * @return true or false, it should swallow all exceptions
118 public static ICondition
isTableItemAvailable(final String name
, final SWTBotTable table
) {
119 return new SWTBotTestCondition() {
121 public boolean test() throws Exception
{
123 return table
.containsItem(name
);
124 } catch (Exception e
) {
130 public String
getFailureMessage() {
131 return NLS
.bind("No child of table {0} found with text '{1}'.", table
, name
);
137 * Is the treeItem's node available
140 * the name of the node
143 * @return true or false, it should swallow all exceptions
145 public static ICondition
IsTreeChildNodeAvailable(final String name
, final SWTBotTreeItem treeItem
) {
146 return new SWTBotTestCondition() {
148 public boolean test() throws Exception
{
150 return treeItem
.getNode(name
) != null;
151 } catch (Exception e
) {
157 public String
getFailureMessage() {
158 return NLS
.bind("No child of tree item {0} found with text '{1}'. Child items: {2}",
159 new String
[] { treeItem
.toString(), name
, Arrays
.toString(treeItem
.getItems()) });
165 * Is the treeItem's node removed
168 * length of the node after removal
171 * @return true or false, it should swallow all exceptions
173 public static ICondition
isTreeChildNodeRemoved(final int length
, final SWTBotTreeItem treeItem
) {
174 return new SWTBotTestCondition() {
176 public boolean test() throws Exception
{
178 return treeItem
.getNodes().size() == length
;
179 } catch (Exception e
) {
185 public String
getFailureMessage() {
186 return NLS
.bind("Child of tree item {0} found with text '{1}' not removed. Child items: {2}",
187 new String
[] { treeItem
.toString(), String
.valueOf(length
), Arrays
.toString(treeItem
.getItems()) });
193 * Checks if the wizard's shell is null
197 * @return false if either are null
199 public static ICondition
isWizardReady(final Wizard wizard
) {
200 return new SWTBotTestCondition() {
202 public boolean test() throws Exception
{
203 if (wizard
.getShell() == null) {
212 * Is the wizard on the page you want?
218 * @return true or false
220 public static ICondition
isWizardOnPage(final Wizard wizard
, final IWizardPage page
) {
221 return new SWTBotTestCondition() {
223 public boolean test() throws Exception
{
224 if (wizard
== null || page
== null) {
227 final IWizardContainer container
= wizard
.getContainer();
228 if (container
== null) {
231 IWizardPage currentPage
= container
.getCurrentPage();
232 return page
.equals(currentPage
);
238 * Wait for a view to close
241 * bot view for the view
242 * @return true if the view is closed, false if it's active.
244 public static ICondition
ViewIsClosed(final SWTBotView view
) {
245 return new SWTBotTestCondition() {
247 public boolean test() throws Exception
{
248 return (view
!= null) && (!view
.isActive());
254 * Wait till table cell has a given content.
257 * the table bot reference
259 * the content to check
261 * the row of the cell
263 * the column of the cell
264 * @return ICondition for verification
266 public static ICondition
isTableCellFilled(final SWTBotTable table
,
267 final String content
, final int row
, final int column
) {
268 return new SWTBotTestCondition() {
270 public boolean test() throws Exception
{
272 String cell
= table
.cell(row
, column
);
276 return cell
.contains(content
);
277 } catch (Exception e
) {
285 * Condition to check if a tracing project element has a child with the
286 * specified name. A project element label may have a count suffix in the
289 public static class ProjectElementHasChild
extends DefaultCondition
{
291 private final SWTBotTreeItem fParentItem
;
292 private final String fName
;
293 private final String fRegex
;
294 private SWTBotTreeItem fItem
= null;
302 * the child name to look for
304 public ProjectElementHasChild(final SWTBotTreeItem parentItem
, final String name
) {
305 fParentItem
= parentItem
;
307 /* Project element labels may have count suffix */
308 fRegex
= name
+ "(\\s\\[(\\d)+\\])?";
312 public boolean test() throws Exception
{
313 fParentItem
.expand();
314 for (SWTBotTreeItem item
: fParentItem
.getItems()) {
315 if (item
.getText().matches(fRegex
)) {
324 public String
getFailureMessage() {
325 return NLS
.bind("No child of {0} found with name {1}", fParentItem
.getText(), fName
);
329 * Returns the matching child item if the condition returned true.
331 * @return the matching item
333 public SWTBotTreeItem
getItem() {
339 * Condition to check if an editor with the specified title is opened.
345 * @return ICondition for verification
347 public static ICondition
isEditorOpened(final SWTWorkbenchBot bot
, final String title
) {
348 return new SWTBotTestCondition() {
350 public boolean test() throws Exception
{
351 Matcher
<IEditorReference
> withPartName
= withPartName(title
);
352 return !bot
.editors(withPartName
).isEmpty();
358 * Condition to check if the selection range equals the specified range.
361 * the selection range
362 * @return ICondition for verification
364 public static ICondition
selectionRange(final TmfTimeRange range
) {
365 return new SWTBotTestCondition() {
367 public boolean test() throws Exception
{
368 return TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange().equals(range
);
372 public String
getFailureMessage() {
373 return NLS
.bind("Selection range: {0} expected: {1}",
374 TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange(), range
);
380 * Condition to check if the window range equals the specified range.
384 * @return ICondition for verification
386 public static ICondition
windowRange(final TmfTimeRange range
) {
387 return new SWTBotTestCondition() {
389 public boolean test() throws Exception
{
390 return TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange().equals(range
);
394 public String
getFailureMessage() {
395 return NLS
.bind("Window range: {0} expected: {1}",
396 TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange(), range
);
402 * Condition to check if the selection contains the specified text at the
403 * specified column. The text is checked in any item of the tree selection.
411 * @return ICondition for verification
413 public static ICondition
treeSelectionContains(final SWTBotTree tree
, final int column
, final String text
) {
414 return new SWTBotTestCondition() {
416 public boolean test() throws Exception
{
417 TableCollection selection
= tree
.selection();
418 for (int row
= 0; row
< selection
.rowCount(); row
++) {
419 if (selection
.get(row
, column
).equals(text
)) {
427 public String
getFailureMessage() {
428 return NLS
.bind("Tree selection [0,{0}]: {1} expected: {2}",
429 new Object
[] { column
, tree
.selection().get(0, column
), text
});
434 private static class EventsTableSelectionCondition
extends DefaultCondition
{
435 private long fSelectionTime
;
436 private SWTWorkbenchBot fBot
;
437 private long fCurValue
;
439 private EventsTableSelectionCondition(SWTWorkbenchBot bot
, long selectionTime
) {
441 fSelectionTime
= selectionTime
;
445 public boolean test() throws Exception
{
446 StructuredSelection eventsTableSelection
= getEventsTableSelection();
447 if (eventsTableSelection
.isEmpty()) {
450 fCurValue
= ((ITmfEvent
) eventsTableSelection
.getFirstElement()).getTimestamp().getValue();
451 return fCurValue
== fSelectionTime
;
455 public String
getFailureMessage() {
456 return "The selection in the table was not an event with timestamp " + fSelectionTime
+ ". Actual is " + fCurValue
;
459 private StructuredSelection
getEventsTableSelection() {
460 return UIThreadRunnable
.syncExec(new Result
<StructuredSelection
>() {
463 public StructuredSelection
run() {
464 SWTBotEditor eventsEditor
= SWTBotUtils
.activeEventsEditor(fBot
);
465 TmfEventsEditor part
= (TmfEventsEditor
) eventsEditor
.getReference().getPart(false);
466 StructuredSelection selection
= (StructuredSelection
) part
.getSelection();
474 * Wait until the events table selection matches the specified time stamp.
479 * @param selectionTime
481 * @return ICondition for verification
483 public static ICondition
selectionInEventsTable(final SWTWorkbenchBot bot
, long selectionTime
) {
484 return new EventsTableSelectionCondition(bot
, selectionTime
);
487 private static class TimeGraphIsReadyCondition
extends DefaultCondition
{
489 private @NonNull TmfTimeRange fSelectionRange
;
490 private @NonNull ITmfTimestamp fVisibleTime
;
491 private AbstractTimeGraphView fView
;
492 private String fFailureMessage
;
494 private TimeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
496 fSelectionRange
= selectionRange
;
497 fVisibleTime
= visibleTime
;
501 public boolean test() throws Exception
{
502 ICondition selectionRangeCondition
= ConditionHelpers
.selectionRange(fSelectionRange
);
503 if (!selectionRangeCondition
.test()) {
504 fFailureMessage
= selectionRangeCondition
.getFailureMessage();
507 @NonNull TmfTimeRange curWindowRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange();
508 if (!curWindowRange
.contains(fVisibleTime
)) {
509 fFailureMessage
= "Current window range " + curWindowRange
+ " does not contain " + fVisibleTime
;
513 if (fView
.isDirty()) {
514 fFailureMessage
= "Time graph is dirty";
522 public String
getFailureMessage() {
523 return fFailureMessage
;
529 * Wait until the Time Graph view is ready. The Time Graph view is
530 * considered ready if the selectionRange is selected, the visibleTime is
531 * visible and the view is not dirty (its model is done updating).
534 * the time graph view
535 * @param selectionRange
536 * the selection that the time graph should have
538 * the visible time that the time graph should have
539 * @return ICondition for verification
541 public static ICondition
timeGraphIsReadyCondition(AbstractTimeGraphView view
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
542 return new TimeGraphIsReadyCondition(view
, selectionRange
, visibleTime
);