summaryrefslogtreecommitdiffstats
path: root/testbench-api/src
diff options
context:
space:
mode:
authorArtur <artur@vaadin.com>2016-12-22 10:24:01 +0200
committerHenri Sara <henri.sara@gmail.com>2016-12-22 10:24:01 +0200
commit67222eb13b85d5b479e83c2449f64eb762f41d01 (patch)
treef453127975be34ea11a95182d38702d507ddb22c /testbench-api/src
parentc72373114c53c6eb8fe68a846e20e330977a9677 (diff)
downloadvaadin-framework-67222eb13b85d5b479e83c2449f64eb762f41d01.tar.gz
vaadin-framework-67222eb13b85d5b479e83c2449f64eb762f41d01.zip
Include Framework Element API for TestBench in the project (#8014)
This makes it possible to use the latest Element classes in the framework tests and to simplify the build process. The license for the included element classes are changed to Apache2
Diffstat (limited to 'testbench-api/src')
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbsoluteLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractColorPickerElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractComponentContainerElement.java24
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractComponentElement.java84
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractEmbeddedElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractFieldElement.java50
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractJavaScriptComponentElement.java24
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractMediaElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractOrderedLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSelectElement.java31
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSingleComponentContainerElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSplitPanelElement.java86
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractTextFieldElement.java50
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AccordionElement.java31
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/AudioElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/BrowserFrameElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ButtonElement.java59
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/CalendarElement.java74
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/CheckBoxElement.java90
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/CheckBoxGroupElement.java94
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerAreaElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerElement.java30
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerPreviewElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ComboBoxElement.java233
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/CssLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/CustomComponentElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/CustomFieldElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/CustomLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/DateFieldElement.java62
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/EmbeddedElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/FlashElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/FormElement.java24
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/FormLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/GridElement.java444
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/GridLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/HorizontalLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/HorizontalSplitPanelElement.java31
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ImageElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/InlineDateFieldElement.java42
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/LabelElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/LegacyWindowElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/LinkElement.java39
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ListSelectElement.java119
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/MenuBarElement.java168
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/NativeButtonElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/NativeSelectElement.java75
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/NotificationElement.java100
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/OptionGroupElement.java95
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/PanelElement.java35
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/PasswordFieldElement.java32
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/PopupDateFieldElement.java24
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/PopupViewElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ProgressBarElement.java42
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/ProgressIndicatorElement.java24
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/RadioButtonGroupElement.java94
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/RichTextAreaElement.java22
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/SelectElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/SliderElement.java57
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TabSheetElement.java210
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TableElement.java150
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TableHeaderElement.java43
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TableRowElement.java49
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TextAreaElement.java46
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TextFieldElement.java25
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TreeElement.java43
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TreeTableElement.java31
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TreeTableRowElement.java36
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/TwinColSelectElement.java134
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/UIElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/UploadElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/VerticalLayoutElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/VerticalSplitPanelElement.java31
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/VideoElement.java23
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/elements/WindowElement.java94
-rw-r--r--testbench-api/src/main/java/com/vaadin/testbench/exceptions/NoSuchColumnException.java20
76 files changed, 4091 insertions, 0 deletions
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbsoluteLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbsoluteLayoutElement.java
new file mode 100644
index 0000000000..26620b0af0
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbsoluteLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbsoluteLayout")
+public class AbsoluteLayoutElement extends AbstractLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractColorPickerElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractColorPickerElement.java
new file mode 100644
index 0000000000..6f6631a52b
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractColorPickerElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractColorPicker")
+public class AbstractColorPickerElement extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractComponentContainerElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractComponentContainerElement.java
new file mode 100644
index 0000000000..5224920470
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractComponentContainerElement.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractComponentContainer")
+public class AbstractComponentContainerElement
+ extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractComponentElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractComponentElement.java
new file mode 100644
index 0000000000..9b4a4344f8
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractComponentElement.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elementsbase.AbstractElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractComponent")
+public class AbstractComponentElement extends AbstractElement {
+ /**
+ * Returns the caption of the Component element
+ *
+ * @since
+ * @return
+ */
+ public String getCaption() {
+ final String GWT_ID_ATTRIBUTE = "aria-labelledby";
+ WebElement captElem = null;
+ String captionId = null;
+ captionId = getAttribute(GWT_ID_ATTRIBUTE);
+ // IE8 getAttribute returns empty string instead of null
+ // when there is no attribute with specified name
+ if (captionId == null || captionId.equals("")) {
+ WebElement elem = findElement(
+ By.xpath(".//*[@" + GWT_ID_ATTRIBUTE + "]"));
+ captionId = elem.getAttribute(GWT_ID_ATTRIBUTE);
+ }
+ // element ids are unique, we can search the whole page
+ captElem = getDriver().findElement(By.id(captionId));
+ return captElem.getText();
+ }
+
+ public String getHTML() {
+ return getWrappedElement().getAttribute("innerHTML");
+ }
+
+ public boolean isReadOnly() {
+ final String READONLY_CSS_CLASS = "v-readonly";
+ String readonlyClass = getAttribute("class");
+ // lookin for READONLY_CSS_CLASS string
+ String[] cssSelectors = readonlyClass.split("\\s");
+ for (String selector : cssSelectors) {
+ if (selector.equals(READONLY_CSS_CLASS)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected String getStyleAttribute(WebElement element, String styleName) {
+ String style = element.getAttribute("style");
+
+ String[] styles = style.split(";");
+ for (String stylePart : styles) {
+ // IE8 has uppercased styles
+ String lowercasePart = stylePart.toLowerCase();
+ if (lowercasePart.startsWith(styleName + ":")) {
+ return lowercasePart.substring(styleName.length() + 1).trim();
+ }
+ }
+
+ return null;
+ }
+
+ public class ReadOnlyException extends RuntimeException {
+
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractEmbeddedElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractEmbeddedElement.java
new file mode 100644
index 0000000000..406b42db35
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractEmbeddedElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractEmbedded")
+public class AbstractEmbeddedElement extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractFieldElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractFieldElement.java
new file mode 100644
index 0000000000..3980d263d8
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractFieldElement.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractField")
+public class AbstractFieldElement extends AbstractComponentElement {
+
+ /**
+ * Select contents of TextField Element
+ *
+ * NOTE: When testing with firefox browser window should have focus in it
+ *
+ * @since
+ * @param elem
+ * element which context will be select
+ */
+ protected void clientSelectElement(WebElement elem) {
+ JavascriptExecutor js = (JavascriptExecutor) getDriver();
+ String script = "window.focus();" + "var elem=arguments[0];"
+ + "elem.select();elem.focus();";
+ js.executeScript(script, elem);
+ }
+
+ protected void clearElementClientSide(WebElement elem) {
+ // clears without triggering an event (on client side)
+ JavascriptExecutor js = (JavascriptExecutor) getDriver();
+ String script = "window.focus(); var elem=arguments[0];"
+ + "elem.value=\"\";";
+ js.executeScript(script, elem);
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractJavaScriptComponentElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractJavaScriptComponentElement.java
new file mode 100644
index 0000000000..9cf17ece9c
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractJavaScriptComponentElement.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractJavaScriptComponent")
+public class AbstractJavaScriptComponentElement
+ extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractLayoutElement.java
new file mode 100644
index 0000000000..08d9fe4f6e
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractLayout")
+public class AbstractLayoutElement extends AbstractComponentContainerElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractMediaElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractMediaElement.java
new file mode 100644
index 0000000000..dad016fdc1
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractMediaElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractMedia")
+public class AbstractMediaElement extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractOrderedLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractOrderedLayoutElement.java
new file mode 100644
index 0000000000..35bdd15ae1
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractOrderedLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractOrderedLayout")
+public class AbstractOrderedLayoutElement extends AbstractLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSelectElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSelectElement.java
new file mode 100644
index 0000000000..cb90f238b2
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSelectElement.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractSelect")
+public class AbstractSelectElement extends AbstractFieldElement {
+
+ /**
+ * Clear operation is not supported for select element classes. This
+ * operation has no effect on select element
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSingleComponentContainerElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSingleComponentContainerElement.java
new file mode 100644
index 0000000000..5dffcdad06
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSingleComponentContainerElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractSingleComponentContainer")
+public class AbstractSingleComponentContainerElement
+ extends AbstractComponentElement {
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSplitPanelElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSplitPanelElement.java
new file mode 100644
index 0000000000..7e5ed87c5e
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractSplitPanelElement.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBench;
+import com.vaadin.testbench.elementsbase.AbstractElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractSplitPanel")
+public class AbstractSplitPanelElement
+ extends AbstractComponentContainerElement {
+
+ private static org.openqa.selenium.By byFirstContainer = By
+ .xpath("./div/div[contains(normalize-space(concat(@class, ' ')), "
+ + "normalize-space('-first-container '))]/*");
+ private static org.openqa.selenium.By bySecondContainer = By
+ .xpath("./div/div[contains(normalize-space(concat(@class, ' ')), "
+ + "normalize-space('-second-container '))]/*");
+
+ /**
+ * Gets the first component of a split panel and wraps it in given class.
+ *
+ * @param clazz
+ * Components element class
+ * @return First component wrapped in given class
+ */
+ public <T extends AbstractElement> T getFirstComponent(Class<T> clazz) {
+ return getContainedComponent(clazz, byFirstContainer);
+ }
+
+ /**
+ * Gets the second component of a split panel and wraps it in given class.
+ *
+ * @param clazz
+ * Components element class
+ * @return Second component wrapped in given class
+ */
+ public <T extends AbstractElement> T getSecondComponent(Class<T> clazz) {
+ return getContainedComponent(clazz, bySecondContainer);
+ }
+
+ /**
+ * Gets a component of a split panel and wraps it in the given class.
+ *
+ * @param clazz
+ * Components element class
+ * @param byContainer
+ * A locator that specifies the container (first or second) whose
+ * component is looked for
+ * @return A component wrapped in the given class
+ */
+ private <T extends AbstractElement> T getContainedComponent(Class<T> clazz,
+ org.openqa.selenium.By byContainer) {
+ List<AbstractComponentElement> containedComponents = $$(
+ AbstractComponentElement.class).all();
+ List<WebElement> componentsInSelectedContainer = findElements(
+ byContainer);
+ for (AbstractComponentElement component : containedComponents) {
+ WebElement elem = component.getWrappedElement();
+ if (componentsInSelectedContainer.contains(elem)) {
+ return TestBench.createElement(clazz, elem,
+ getCommandExecutor());
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractTextFieldElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractTextFieldElement.java
new file mode 100644
index 0000000000..6435f4a096
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AbstractTextFieldElement.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.AbstractTextField")
+public class AbstractTextFieldElement extends AbstractFieldElement {
+
+ /**
+ * Return value of the field element
+ *
+ * @return value of the field element
+ */
+ public String getValue() {
+ return findElement(By.tagName("input")).getAttribute("value");
+ }
+
+ /**
+ * Set value of the field element
+ *
+ * @param chars
+ * new value of the field
+ */
+ public void setValue(CharSequence chars) throws ReadOnlyException {
+ if (isReadOnly()) {
+ throw new ReadOnlyException();
+ }
+ clearElementClientSide(this);
+ focus();
+ sendKeys(chars);
+ sendKeys(Keys.TAB);
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AccordionElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AccordionElement.java
new file mode 100644
index 0000000000..f8a2451e1e
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AccordionElement.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Accordion")
+public class AccordionElement extends TabSheetElement {
+
+ {
+ // Only difference in using Accordion vs. TabSheet is CSS class name for
+ // items
+ byTabCell = By.className("v-accordion-item");
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/AudioElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/AudioElement.java
new file mode 100644
index 0000000000..60164e2913
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/AudioElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Audio")
+public class AudioElement extends AbstractMediaElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/BrowserFrameElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/BrowserFrameElement.java
new file mode 100644
index 0000000000..a27a08449c
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/BrowserFrameElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.BrowserFrame")
+public class BrowserFrameElement extends AbstractEmbeddedElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ButtonElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ButtonElement.java
new file mode 100644
index 0000000000..5da9753367
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ButtonElement.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Button")
+public class ButtonElement extends AbstractComponentElement {
+
+ @Override
+ public String getCaption() {
+ WebElement captElem = findElement(By.className("v-button-caption"));
+ return captElem.getText();
+ }
+
+ private boolean tryClickChild(WebElement e) {
+ List<WebElement> children = e.findElements(By.xpath(".//*"));
+ for (WebElement c : children) {
+ if (c.isDisplayed()) {
+ c.click();
+ return true;
+ } else {
+ if (tryClickChild(c)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void click() {
+ if (!isDisplayed()) {
+ if (tryClickChild(this)) {
+ return;
+ }
+ }
+
+ super.click();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/CalendarElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/CalendarElement.java
new file mode 100644
index 0000000000..bd1c3c53e5
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/CalendarElement.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Calendar")
+@Deprecated
+public class CalendarElement extends AbstractComponentElement {
+ public List<WebElement> getWeekNumbers() {
+ return findElements(By.className("v-calendar-week-number"));
+ }
+
+ public boolean hasMonthView() {
+ return isElementPresent(By.className("v-calendar-week-numbers"));
+ }
+
+ public boolean hasWeekView() {
+ return isElementPresent(By.className("v-calendar-header-week"));
+ }
+
+ public List<WebElement> getDayNumbers() {
+ return findElements(By.className("v-calendar-day-number"));
+ }
+
+ public List<WebElement> getMonthDays() {
+ return findElements(By.className("v-calendar-month-day"));
+ }
+
+ public boolean hasDayView() {
+ return getDayHeaders().size() == 1;
+ }
+
+ public List<WebElement> getDayHeaders() {
+ return findElements(By.className("v-calendar-header-day"));
+ }
+
+ public void back() {
+ if (hasWeekView() || hasDayView()) {
+ findElement(By.className("v-calendar-back")).click();
+ } else {
+ throw new IllegalStateException(
+ "Navigation only available in week or day view");
+ }
+ }
+
+ public void next() {
+ if (hasWeekView() || hasDayView()) {
+ findElement(By.className("v-calendar-next")).click();
+ } else {
+ throw new IllegalStateException(
+ "Navigation only available in week or day view");
+ }
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/CheckBoxElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/CheckBoxElement.java
new file mode 100644
index 0000000000..6263ce5b0f
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/CheckBoxElement.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.commands.TestBenchElementCommands;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.CheckBox")
+public class CheckBoxElement extends AbstractFieldElement {
+
+ /**
+ * Return string representation of value of the checkbox Return either
+ * checked or unchecked
+ */
+ public String getValue() {
+ if (isChecked()) {
+ return "checked";
+ } else {
+ return "unchecked";
+ }
+ }
+
+ /**
+ * Checks if the checkbox is checked.
+ *
+ * @return <code>true</code> if the checkbox is checked, <code>false</code>
+ * otherwise.
+ */
+ public boolean isChecked() {
+ return getInputElement().isSelected();
+ }
+
+ /**
+ * Clears the check box, setting unchecked value. The check box is unchecked
+ * by sending a click event on it.
+ *
+ */
+ @Override
+ public void clear() {
+ if (isChecked()) {
+ click();
+ }
+ }
+
+ @Override
+ public String getCaption() {
+ WebElement elem = findElement(By.xpath(".."))
+ .findElement(By.tagName("label"));
+ return elem.getText();
+ }
+
+ @Override
+ public void click() {
+ WebElement input = getInputElement();
+ if (isFirefox()) {
+ // When using Valo, the input element is covered by a
+ // pseudo-element, which Firefox will complain about
+ getCommandExecutor().executeScript("arguments[0].click()", input);
+ } else if (isChrome()) {
+ ((TestBenchElementCommands) (input)).click(0, 0);
+ } else {
+ input.click();
+ }
+ }
+
+ /**
+ * Gets the &lt;input&gt; element of the checkbox.
+ *
+ * @return the input element
+ */
+ public WebElement getInputElement() {
+ return findElement(By.tagName("input"));
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/CheckBoxGroupElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/CheckBoxGroupElement.java
new file mode 100644
index 0000000000..ed657c085d
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/CheckBoxGroupElement.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.CheckBoxGroup")
+public class CheckBoxGroupElement extends AbstractSelectElement {
+
+ private static org.openqa.selenium.By bySelectOption = By
+ .className("v-select-option");
+ private static org.openqa.selenium.By byLabel = By.tagName("label");
+ private static org.openqa.selenium.By byRadioInput = By.tagName("input");
+
+ public List<String> getOptions() {
+ List<String> optionTexts = new ArrayList<String>();
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ optionTexts.add(option.findElement(byLabel).getText());
+ }
+ return optionTexts;
+ }
+
+ public void selectByText(String text) throws ReadOnlyException {
+ if (isReadOnly()) {
+ throw new ReadOnlyException();
+ }
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ if (text.equals(option.findElement(byLabel).getText())) {
+ WebElement input = option.findElement(byRadioInput);
+ ((TestBenchElement) (input)).clickHiddenElement();
+ }
+ }
+ }
+
+ /**
+ * Return value of the selected option in the option group
+ *
+ * @return value of the selected option in the option group
+ */
+ public String getValue() {
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ WebElement checkedItem;
+ checkedItem = option.findElement(By.tagName("input"));
+ String checked = checkedItem.getAttribute("checked");
+ if (checked != null
+ && checkedItem.getAttribute("checked").equals("true")) {
+ return option.findElement(By.tagName("label")).getText();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Select option in the option group with the specified value
+ *
+ * @param chars
+ * value of the option in the option group which will be selected
+ */
+ public void setValue(CharSequence chars) throws ReadOnlyException {
+ selectByText((String) chars);
+ }
+
+ /**
+ * Clear operation is not supported for Option Group. This operation has no
+ * effect on Option Group element.
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerAreaElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerAreaElement.java
new file mode 100644
index 0000000000..9679ee839d
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerAreaElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.ColorPickerArea")
+public class ColorPickerAreaElement extends AbstractColorPickerElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerElement.java
new file mode 100644
index 0000000000..bbbfe79af9
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerElement.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.ColorPicker")
+public class ColorPickerElement extends AbstractColorPickerElement {
+ @Override
+ public String getCaption() {
+ WebElement captElem = findElement(By.className("v-button-caption"));
+ return captElem.getText();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerPreviewElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerPreviewElement.java
new file mode 100644
index 0000000000..62a91eb50c
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ColorPickerPreviewElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.ColorPickerPreview")
+public class ColorPickerPreviewElement extends CssLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ComboBoxElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ComboBoxElement.java
new file mode 100644
index 0000000000..980c4a1e7f
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ComboBoxElement.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.ComboBox")
+public class ComboBoxElement extends AbstractSelectElement {
+
+ private static org.openqa.selenium.By bySuggestionPopup = By
+ .vaadin("#popup");
+ private static org.openqa.selenium.By byNextPage = By
+ .className("v-filterselect-nextpage");
+ private static org.openqa.selenium.By byPrevPage = By
+ .className("v-filterselect-prevpage");
+
+ /**
+ * Selects the first option in the ComboBox which matches the given text.
+ *
+ * @param text
+ * the text of the option to select
+ */
+ public void selectByText(String text) {
+ if (!isTextInputAllowed()) {
+ selectByTextFromPopup(text);
+ return;
+ }
+ getInputField().clear();
+ sendInputFieldKeys(text);
+
+ selectSuggestion(text);
+ }
+
+ /**
+ * Selects, without filtering, the first option in the ComboBox which
+ * matches the given text.
+ *
+ * @param text
+ * the text of the option to select
+ */
+ private void selectByTextFromPopup(String text) {
+ // This method assumes there is no need to touch the filter string
+
+ // 1. Find first page
+ // 2. Select first matching text if found
+ // 3. Iterate towards end
+
+ while (openPrevPage()) {
+ // Scroll until beginning
+ }
+
+ do {
+ if (selectSuggestion(text)) {
+ return;
+ }
+ } while (openNextPage());
+ }
+
+ private boolean selectSuggestion(String text) {
+ for (WebElement suggestion : getPopupSuggestionElements()) {
+ if (text.equals(suggestion.getText())) {
+ suggestion.click();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isReadOnly(WebElement elem) {
+ JavascriptExecutor js = (JavascriptExecutor) getDriver();
+ return (Boolean) js.executeScript("return arguments[0].readOnly", elem);
+ }
+
+ /**
+ * Checks if text input is allowed for the combo box.
+ *
+ * @return <code>true</code> if text input is allowed, <code>false</code>
+ * otherwise
+ */
+ public boolean isTextInputAllowed() {
+ return !isReadOnly(getInputField());
+ }
+
+ /*
+ * Workaround selenium's bug: sendKeys() will not send left parentheses
+ * properly. See #14048.
+ */
+ private void sendInputFieldKeys(String text) {
+ WebElement textBox = getInputField();
+ if (!text.contains("(")) {
+ textBox.sendKeys(text);
+ return;
+ }
+
+ String OPEN_PARENTHESES = "_OPEN_PARENT#H#ESES_";
+ String tamperedText = text.replaceAll("\\(", OPEN_PARENTHESES);
+ textBox.sendKeys(tamperedText);
+
+ JavascriptExecutor js = getCommandExecutor();
+ String jsScript = String.format(
+ "arguments[0].value = arguments[0].value.replace(/%s/g, '(')",
+ OPEN_PARENTHESES);
+ js.executeScript(jsScript, textBox);
+
+ // refresh suggestions popupBox
+ textBox.sendKeys("a" + Keys.BACK_SPACE);
+ }
+
+ /**
+ * Open the suggestion popup
+ */
+ public void openPopup() {
+ findElement(By.vaadin("#button")).click();
+ }
+
+ /**
+ * Gets the text representation of all suggestions on the current page
+ *
+ * @return List of suggestion texts
+ */
+ public List<String> getPopupSuggestions() {
+ List<String> suggestionsTexts = new ArrayList<String>();
+ List<WebElement> suggestions = getPopupSuggestionElements();
+ for (WebElement suggestion : suggestions) {
+ String text = suggestion.getText();
+ if (!text.isEmpty()) {
+ suggestionsTexts.add(text);
+ }
+ }
+ return suggestionsTexts;
+ }
+
+ /**
+ * Gets the elements of all suggestions on the current page.
+ * <p>
+ * Opens the popup if not already open.
+ *
+ * @return a list of elements for the suggestions on the current page
+ */
+ public List<WebElement> getPopupSuggestionElements() {
+ List<WebElement> tables = getSuggestionPopup()
+ .findElements(By.tagName("table"));
+ if (tables == null || tables.isEmpty()) {
+ return Collections.emptyList();
+ }
+ WebElement table = tables.get(0);
+ return table.findElements(By.tagName("td"));
+ }
+
+ /**
+ * Opens next popup page.
+ *
+ * @return True if next page opened. false if doesn't have next page
+ */
+ public boolean openNextPage() {
+ try {
+ getSuggestionPopup().findElement(byNextPage).click();
+ return true;
+ } catch (NoSuchElementException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Open previous popup page.
+ *
+ * @return True if previous page opened. False if doesn't have previous page
+ */
+ public boolean openPrevPage() {
+ try {
+ getSuggestionPopup().findElement(byPrevPage).click();
+ return true;
+ } catch (NoSuchElementException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the suggestion popup element
+ */
+ public WebElement getSuggestionPopup() {
+ ensurePopupOpen();
+ return findElement(bySuggestionPopup);
+ }
+
+ /**
+ * Return value of the combo box element
+ *
+ * @return value of the combo box element
+ */
+ public String getValue() {
+ return getInputField().getAttribute("value");
+ }
+
+ /**
+ * Returns the text input field element, used for entering text into the
+ * combo box.
+ *
+ * @return the input field element
+ */
+ public WebElement getInputField() {
+ return findElement(By.xpath("input"));
+ }
+
+ private void ensurePopupOpen() {
+ if (!isElementPresent(bySuggestionPopup)) {
+ openPopup();
+ }
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/CssLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/CssLayoutElement.java
new file mode 100644
index 0000000000..fdf54e4f00
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/CssLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.CssLayout")
+public class CssLayoutElement extends AbstractLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomComponentElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomComponentElement.java
new file mode 100644
index 0000000000..05c2b64045
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomComponentElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.CustomComponent")
+public class CustomComponentElement extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomFieldElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomFieldElement.java
new file mode 100644
index 0000000000..3d6ff9a5f1
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomFieldElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.CustomField")
+public class CustomFieldElement extends AbstractFieldElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomLayoutElement.java
new file mode 100644
index 0000000000..4ae4170c24
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/CustomLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.CustomLayout")
+public class CustomLayoutElement extends AbstractLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/DateFieldElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/DateFieldElement.java
new file mode 100644
index 0000000000..740e2a6a68
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/DateFieldElement.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.DateField")
+public class DateFieldElement extends AbstractFieldElement {
+
+ /**
+ * Clear DateField element
+ */
+ @Override
+ public void clear() {
+ WebElement elem = findElement(By.tagName("input"));
+ elem.clear();
+ }
+
+ /**
+ * Return value of the date field element
+ *
+ * @return value of the date field element
+ */
+ public String getValue() {
+ return findElement(By.tagName("input")).getAttribute("value");
+ }
+
+ /**
+ * Set value of the date field element
+ *
+ * @param chars
+ * new value of the date field
+ */
+ public void setValue(CharSequence chars) throws ReadOnlyException {
+ if (isReadOnly()) {
+ throw new ReadOnlyException();
+ }
+ WebElement elem = findElement(By.tagName("input"));
+ TestBenchElement tbElement = (TestBenchElement) elem;
+ clearElementClientSide(tbElement);
+ tbElement.sendKeys(chars);
+ tbElement.sendKeys(Keys.TAB);
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/EmbeddedElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/EmbeddedElement.java
new file mode 100644
index 0000000000..92225b4da7
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/EmbeddedElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Embedded")
+public class EmbeddedElement extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/FlashElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/FlashElement.java
new file mode 100644
index 0000000000..f0c5ef525c
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/FlashElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Flash")
+public class FlashElement extends AbstractEmbeddedElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/FormElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/FormElement.java
new file mode 100644
index 0000000000..2f4ebd1980
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/FormElement.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Form")
+@Deprecated
+public class FormElement extends AbstractFieldElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/FormLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/FormLayoutElement.java
new file mode 100644
index 0000000000..b3ef17046d
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/FormLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.FormLayout")
+public class FormLayoutElement extends AbstractOrderedLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/GridElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/GridElement.java
new file mode 100644
index 0000000000..f4959e1531
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/GridElement.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.AbstractElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+/**
+ * TestBench Element API for Grid
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@ServerClass("com.vaadin.ui.Grid")
+public class GridElement extends AbstractComponentElement {
+
+ public static class GridCellElement extends AbstractElement {
+
+ private static final String FOCUSED_CELL_CLASS_NAME = "-cell-focused";
+ private static final String FROZEN_CLASS_NAME = "frozen";
+
+ public boolean isFocused() {
+ return getAttribute("class").contains(FOCUSED_CELL_CLASS_NAME);
+ }
+
+ public boolean isFrozen() {
+ return getAttribute("class").contains(FROZEN_CLASS_NAME);
+ }
+ }
+
+ public static class GridRowElement extends AbstractElement {
+
+ private static final String FOCUSED_CLASS_NAME = "-row-focused";
+ private static final String SELECTED_CLASS_NAME = "-row-selected";
+
+ public boolean isFocused() {
+ return getAttribute("class").contains(FOCUSED_CLASS_NAME);
+ }
+
+ @Override
+ public boolean isSelected() {
+ return getAttribute("class").contains(SELECTED_CLASS_NAME);
+ }
+
+ public GridCellElement getCell(int columnIndex) {
+ TestBenchElement e = (TestBenchElement) findElement(
+ By.xpath("./td[" + (columnIndex + 1) + "]"));
+ return e.wrap(GridCellElement.class);
+ }
+ }
+
+ public static class GridEditorElement extends AbstractElement {
+
+ private GridElement grid;
+
+ private GridEditorElement setGrid(GridElement grid) {
+ this.grid = grid;
+ return this;
+ }
+
+ /**
+ * Gets the editor field for column in given index.
+ *
+ * @param colIndex
+ * the column index
+ * @return the editor field for given location
+ *
+ * @throws NoSuchElementException
+ * if {@code isEditable(colIndex) == false}
+ */
+ public TestBenchElement getField(int colIndex) {
+ return grid.getSubPart("#editor[" + colIndex + "]");
+ }
+
+ /**
+ * Gets whether the column with the given index is editable, that is,
+ * has an associated editor field.
+ *
+ * @param colIndex
+ * the column index
+ * @return {@code true} if the column has an editor field, {@code false}
+ * otherwise
+ */
+ public boolean isEditable(int colIndex) {
+ return grid
+ .isElementPresent(By.vaadin("#editor[" + colIndex + "]"));
+ }
+
+ /**
+ * Checks whether a field is marked with an error.
+ *
+ * @param colIndex
+ * column index
+ * @return <code>true</code> iff the field is marked with an error
+ */
+ public boolean isFieldErrorMarked(int colIndex) {
+ return getField(colIndex).getAttribute("class").contains("error");
+ }
+
+ /**
+ * Saves the fields of this editor.
+ * <p>
+ * <em>Note:</em> that this closes the editor making this element
+ * useless.
+ */
+ public void save() {
+ findElement(By.className("v-grid-editor-save")).click();
+ }
+
+ /**
+ * Cancels this editor.
+ * <p>
+ * <em>Note:</em> that this closes the editor making this element
+ * useless.
+ */
+ public void cancel() {
+ findElement(By.className("v-grid-editor-cancel")).click();
+ }
+
+ /**
+ * Gets the error message text, or <code>null</code> if no message is
+ * present.
+ */
+ public String getErrorMessage() {
+ WebElement messageWrapper = findElement(
+ By.className("v-grid-editor-message"));
+ List<WebElement> divs = messageWrapper
+ .findElements(By.tagName("div"));
+ if (divs.isEmpty()) {
+ return null;
+ } else {
+ return divs.get(0).getText();
+ }
+ }
+ }
+
+ /**
+ * Scrolls Grid element so that wanted row is displayed
+ *
+ * @param index
+ * Target row
+ */
+ public void scrollToRow(int index) {
+ try {
+ getSubPart("#cell[" + index + "]");
+ } catch (NoSuchElementException e) {
+ // Expected, ignore it.
+ }
+ }
+
+ /**
+ * Gets cell element with given row and column index.
+ *
+ * @param rowIndex
+ * Row index
+ * @param colIndex
+ * Column index
+ * @return Cell element with given indices.
+ */
+ public GridCellElement getCell(int rowIndex, int colIndex) {
+ scrollToRow(rowIndex);
+ return getSubPart("#cell[" + rowIndex + "][" + colIndex + "]")
+ .wrap(GridCellElement.class);
+ }
+
+ /**
+ * Gets row element with given row index.
+ *
+ * @param index
+ * Row index
+ * @return Row element with given index.
+ */
+ public GridRowElement getRow(int index) {
+ scrollToRow(index);
+ return getSubPart("#cell[" + index + "]").wrap(GridRowElement.class);
+ }
+
+ /**
+ * Gets header cell element with given row and column index.
+ *
+ * @param rowIndex
+ * Row index
+ * @param colIndex
+ * Column index
+ * @return Header cell element with given indices.
+ */
+ public GridCellElement getHeaderCell(int rowIndex, int colIndex) {
+ return getSubPart("#header[" + rowIndex + "][" + colIndex + "]")
+ .wrap(GridCellElement.class);
+ }
+
+ /**
+ * Gets footer cell element with given row and column index.
+ *
+ * @param rowIndex
+ * Row index
+ * @param colIndex
+ * Column index
+ * @return Footer cell element with given indices.
+ */
+ public GridCellElement getFooterCell(int rowIndex, int colIndex) {
+ return getSubPart("#footer[" + rowIndex + "][" + colIndex + "]")
+ .wrap(GridCellElement.class);
+ }
+
+ /**
+ * Gets list of header cell elements on given row.
+ *
+ * @param rowIndex
+ * Row index
+ * @return Header cell elements on given row.
+ */
+ public List<GridCellElement> getHeaderCells(int rowIndex) {
+ List<GridCellElement> headers = new ArrayList<GridCellElement>();
+ for (TestBenchElement e : TestBenchElement.wrapElements(
+ getSubPart("#header[" + rowIndex + "]").findElements(
+ By.xpath("./th")),
+ getCommandExecutor())) {
+ headers.add(e.wrap(GridCellElement.class));
+ }
+ return headers;
+ }
+
+ /**
+ * Gets list of header cell elements on given row.
+ *
+ * @param rowIndex
+ * Row index
+ * @return Header cell elements on given row.
+ */
+ public List<GridCellElement> getFooterCells(int rowIndex) {
+ List<GridCellElement> footers = new ArrayList<GridCellElement>();
+ for (TestBenchElement e : TestBenchElement.wrapElements(
+ getSubPart("#footer[" + rowIndex + "]").findElements(
+ By.xpath("./td")),
+ getCommandExecutor())) {
+ footers.add(e.wrap(GridCellElement.class));
+ }
+ return footers;
+ }
+
+ /**
+ * Get header row count
+ *
+ * @return Header row count
+ */
+ public int getHeaderCount() {
+ return getSubPart("#header").findElements(By.xpath("./tr")).size();
+ }
+
+ /**
+ * Get footer row count
+ *
+ * @return Footer row count
+ */
+ public int getFooterCount() {
+ return getSubPart("#footer").findElements(By.xpath("./tr")).size();
+ }
+
+ /**
+ * Get a header row by index
+ *
+ * @param rowIndex
+ * Row index
+ * @return The th element of the row
+ */
+ public TestBenchElement getHeaderRow(int rowIndex) {
+ return getSubPart("#header[" + rowIndex + "]");
+ }
+
+ /**
+ * Get a footer row by index
+ *
+ * @param rowIndex
+ * Row index
+ * @return The tr element of the row
+ */
+ public TestBenchElement getFooterRow(int rowIndex) {
+ return getSubPart("#footer[" + rowIndex + "]");
+ }
+
+ /**
+ * Get the vertical scroll element
+ *
+ * @return The element representing the vertical scrollbar
+ */
+ public TestBenchElement getVerticalScroller() {
+ List<WebElement> rootElements = findElements(By.xpath("./div"));
+ return (TestBenchElement) rootElements.get(0);
+ }
+
+ /**
+ * Get the horizontal scroll element
+ *
+ * @return The element representing the horizontal scrollbar
+ */
+ public TestBenchElement getHorizontalScroller() {
+ List<WebElement> rootElements = findElements(By.xpath("./div"));
+ return (TestBenchElement) rootElements.get(1);
+ }
+
+ /**
+ * Get the header element
+ *
+ * @return The thead element
+ */
+ public TestBenchElement getHeader() {
+ return getSubPart("#header");
+ }
+
+ /**
+ * Get the body element
+ *
+ * @return the tbody element
+ */
+ public TestBenchElement getBody() {
+ return getSubPart("#cell");
+ }
+
+ /**
+ * Get the footer element
+ *
+ * @return the tfoot element
+ */
+ public TestBenchElement getFooter() {
+ return getSubPart("#footer");
+ }
+
+ /**
+ * Get the element wrapping the table element
+ *
+ * @return The element that wraps the table element
+ */
+ public TestBenchElement getTableWrapper() {
+ List<WebElement> rootElements = findElements(By.xpath("./div"));
+ return (TestBenchElement) rootElements.get(2);
+ }
+
+ public GridEditorElement getEditor() {
+ return getSubPart("#editor").wrap(GridEditorElement.class)
+ .setGrid(this);
+ }
+
+ /**
+ * Helper function to get Grid subparts wrapped correctly
+ *
+ * @param subPartSelector
+ * SubPart to be used in ComponentLocator
+ * @return SubPart element wrapped in TestBenchElement class
+ */
+ private TestBenchElement getSubPart(String subPartSelector) {
+ return (TestBenchElement) findElement(By.vaadin(subPartSelector));
+ }
+
+ /**
+ * Gets the element that contains the details of a row.
+ *
+ * @since
+ * @param rowIndex
+ * the index of the row for the details
+ * @return the element that contains the details of a row. <code>null</code>
+ * if no widget is defined for the details row
+ * @throws NoSuchElementException
+ * if the given details row is currently not open
+ */
+ public TestBenchElement getDetails(int rowIndex)
+ throws NoSuchElementException {
+ return getSubPart("#details[" + rowIndex + "]");
+ }
+
+ /**
+ * Gets the total number of data rows in the grid.
+ *
+ * @return the number of data rows in the grid,
+ */
+ public long getRowCount() {
+ Long res = (Long) getCommandExecutor()
+ .executeScript("return arguments[0].getBodyRowCount()", this);
+ if (res == null) {
+ throw new IllegalStateException("getBodyRowCount returned null");
+ }
+
+ return res.longValue();
+ }
+
+ /**
+ * Gets all the data rows in the grid.
+ * <p>
+ * Returns an iterable which will lazily scroll rows into views and lazy
+ * load data as needed.
+ *
+ * @return an iterable of all the data rows in the grid.
+ */
+ public Iterable<GridRowElement> getRows() {
+ return new Iterable<GridElement.GridRowElement>() {
+ public Iterator<GridRowElement> iterator() {
+ return new Iterator<GridElement.GridRowElement>() {
+ int nextIndex = 0;
+
+ public GridRowElement next() {
+ return getRow(nextIndex++);
+ }
+
+ public boolean hasNext() {
+ try {
+ getRow(nextIndex);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException(
+ "remove not supported");
+ }
+
+ };
+ }
+ };
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/GridLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/GridLayoutElement.java
new file mode 100644
index 0000000000..31ebca721d
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/GridLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.GridLayout")
+public class GridLayoutElement extends AbstractLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/HorizontalLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/HorizontalLayoutElement.java
new file mode 100644
index 0000000000..ab03ef7ade
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/HorizontalLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.HorizontalLayout")
+public class HorizontalLayoutElement extends AbstractOrderedLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/HorizontalSplitPanelElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/HorizontalSplitPanelElement.java
new file mode 100644
index 0000000000..db8922e622
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/HorizontalSplitPanelElement.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.HorizontalSplitPanel")
+public class HorizontalSplitPanelElement extends AbstractSplitPanelElement {
+
+ private static By bySplit = By.className("v-splitpanel-hsplitter");
+
+ public TestBenchElement getSplitter() {
+ return wrapElement(findElement(bySplit), getCommandExecutor());
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ImageElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ImageElement.java
new file mode 100644
index 0000000000..18a8244595
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ImageElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Image")
+public class ImageElement extends AbstractEmbeddedElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/InlineDateFieldElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/InlineDateFieldElement.java
new file mode 100644
index 0000000000..1cb88a1865
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/InlineDateFieldElement.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.InlineDateField")
+public class InlineDateFieldElement extends DateFieldElement {
+
+ /**
+ * Operation is not supported
+ *
+ * @throws UnsupportedOperationException
+ */
+ @Override
+ public String getValue() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Operation is not supported
+ *
+ * @throws UnsupportedOperationException
+ */
+ @Override
+ public void setValue(CharSequence chars) throws ReadOnlyException {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/LabelElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/LabelElement.java
new file mode 100644
index 0000000000..da891ecc84
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/LabelElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Label")
+public class LabelElement extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/LegacyWindowElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/LegacyWindowElement.java
new file mode 100644
index 0000000000..28c81467e2
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/LegacyWindowElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.LegacyWindow")
+public class LegacyWindowElement extends UIElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/LinkElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/LinkElement.java
new file mode 100644
index 0000000000..da87eb0abc
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/LinkElement.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Link")
+public class LinkElement extends AbstractComponentElement {
+
+ @Override
+ public void click() {
+ getAnchor().click();
+ }
+
+ private WebElement getAnchor() {
+ return findElement(By.tagName("a"));
+ }
+
+ @Override
+ public String getCaption() {
+ return getAnchor().getText();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ListSelectElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ListSelectElement.java
new file mode 100644
index 0000000000..4ce4c9008f
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ListSelectElement.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.Select;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.ListSelect")
+public class ListSelectElement extends AbstractSelectElement {
+
+ private Select select;
+ private static By bySelect = By.tagName("select");
+ private WebElement selectElement;
+
+ @Override
+ protected void init() {
+ super.init();
+ selectElement = findElement(bySelect);
+ select = new Select(selectElement);
+ }
+
+ /**
+ * Selects the option(s) with the given text.
+ * <p>
+ * For a ListSelect in multi select mode, adds the given option(s) to the
+ * current selection.
+ *
+ * @param text
+ * the text of the option
+ */
+ public void selectByText(String text) {
+ select.selectByVisibleText(text);
+ if (isPhantomJS() && select.isMultiple()) {
+ // Phantom JS does not fire a change event when
+ // selecting/deselecting items in a multi select
+ fireChangeEvent(selectElement);
+ }
+ }
+
+ /**
+ * Deselects the option(s) with the given text.
+ *
+ * @param text
+ * the text of the option
+ */
+ public void deselectByText(String text) {
+ select.deselectByVisibleText(text);
+ if (isPhantomJS() && select.isMultiple()) {
+ // Phantom JS does not fire a change event when
+ // selecting/deselecting items in a multi select
+ fireChangeEvent(selectElement);
+ }
+ }
+
+ /**
+ * Gets a list of the texts shown for all options.
+ *
+ * @return a list of option texts
+ */
+ public List<String> getOptions() {
+ List<String> options = new ArrayList<String>();
+ for (WebElement webElement : select.getOptions()) {
+ options.add(webElement.getText());
+ }
+ return options;
+ }
+
+ /**
+ * Clear operation is not supported for List Select. This operation has no
+ * effect on List Select element.
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ }
+
+ /**
+ * Return value of the list select element
+ *
+ * @return value of the list select element
+ */
+ public String getValue() {
+ return select.getFirstSelectedOption().getText();
+ }
+
+ private void fireChangeEvent(WebElement target) {
+ if (!(getDriver() instanceof JavascriptExecutor)) {
+ return;
+ }
+
+ ((JavascriptExecutor) getDriver()).executeScript(
+ "var ev = document.createEvent('HTMLEvents');" //
+ + "ev.initEvent('change', false, true);" //
+ + "arguments[0].dispatchEvent(ev);", //
+ target);
+
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/MenuBarElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/MenuBarElement.java
new file mode 100644
index 0000000000..18b4240578
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/MenuBarElement.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.Point;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.MenuBar")
+public class MenuBarElement extends AbstractComponentElement {
+
+ private Point lastItemLocationMovedTo = null;
+
+ /**
+ * Clicks on a visible item.<br>
+ * If the item is a top level menu, the submenu is opened if it was closed,
+ * or closed if it was opened.<br>
+ * If the item is another submenu, that submenu is opened.<br>
+ * If the item is not a submenu, it will be clicked and trigger any actions
+ * associated to it.
+ *
+ * @param item
+ * name of the item to click
+ * @throws NullPointerException
+ * if item does not exist or is not visible
+ */
+ private void clickItem(String item) {
+ WebElement webElement = getVisibleItem("#" + item);
+ if (webElement == null) {
+ throw new NoSuchElementException(
+ "Menu item " + item + " is not available.");
+ }
+ activateOrOpenSubmenu(webElement, true);
+ }
+
+ /**
+ * Clicks the item specified by a full path given as variable arguments.<br>
+ * Fails if path given is not full (ie: last submenu is already opened, and
+ * path given is last item only).
+ * <p>
+ * Example:
+ * </p>
+ *
+ * <pre>
+ * // clicks on &quot;File&quot; item
+ * menuBarElement.click(&quot;File&quot;);
+ * // clicks on &quot;Copy&quot; item in &quot;File&quot; top level menu.
+ * menuBarElement.click(&quot;File&quot;, &quot;Copy&quot;);
+ * </pre>
+ *
+ * @param path
+ * Array of items to click through
+ */
+ public void clickItem(String... path) {
+ if (path.length > 1) {
+ closeAll();
+ }
+ for (String itemName : path) {
+ clickItem(itemName);
+ }
+ }
+
+ /**
+ * Closes all submenus, if any is open.<br>
+ * This is done by clicking on the currently selected top level item.
+ */
+ private void closeAll() {
+ lastItemLocationMovedTo = null;
+ WebElement selectedItem = getSelectedTopLevelItem();
+ if (selectedItem != null) {
+ activateOrOpenSubmenu(selectedItem, true);
+ }
+ }
+
+ private WebElement getSelectedTopLevelItem() {
+ List<WebElement> selectedItems = findElements(
+ By.className("v-menubar-menuitem-selected"));
+ if (selectedItems.size() == 0) {
+ return null;
+ }
+ return selectedItems.get(0);
+ }
+
+ private WebElement getVisibleItem(String item) {
+ return findElement(com.vaadin.testbench.By.vaadin(item));
+ }
+
+ private void activateOrOpenSubmenu(WebElement item, boolean alwaysClick) {
+
+ if (lastItemLocationMovedTo == null || !isAnySubmenuVisible()) {
+ item.click();
+ if (hasSubmenu(item)) {
+ lastItemLocationMovedTo = item.getLocation();
+ }
+ return;
+ }
+
+ // Assumes mouse is still at position of last clicked element
+ Actions action = new Actions(getDriver());
+ action.moveToElement(item);
+ action.build().perform();
+
+ if (isLeaf(item) || isSelectedTopLevelItem(item)) {
+ lastItemLocationMovedTo = null;
+ } else {
+ lastItemLocationMovedTo = item.getLocation();
+ }
+
+ if (alwaysClick || isLeaf(item) || !isAnySubmenuVisible()) {
+ action = new Actions(getDriver());
+ action.click();
+ action.build().perform();
+ }
+ }
+
+ private boolean isSelectedTopLevelItem(WebElement item) {
+ WebElement selectedItem = getSelectedTopLevelItem();
+ if (selectedItem == null) {
+ return false;
+ }
+
+ String itemCaption = item
+ .findElements(By.className("v-menubar-menuitem-caption")).get(0)
+ .getAttribute("innerHTML");
+ String selectedItemCaption = selectedItem
+ .findElements(By.className("v-menubar-menuitem-caption")).get(0)
+ .getAttribute("innerHTML");
+ return itemCaption.equals(selectedItemCaption);
+ }
+
+ private boolean isAnySubmenuVisible() {
+ WebElement selectedItem = getSelectedTopLevelItem();
+ if (selectedItem == null) {
+ return false;
+ }
+ return hasSubmenu(selectedItem);
+ }
+
+ private boolean hasSubmenu(WebElement item) {
+ List<WebElement> submenuIndicatorElements = item
+ .findElements(By.className("v-menubar-submenu-indicator"));
+ return submenuIndicatorElements.size() != 0;
+ }
+
+ private boolean isLeaf(WebElement item) {
+ return !hasSubmenu(item);
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/NativeButtonElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/NativeButtonElement.java
new file mode 100644
index 0000000000..7bbfb67a42
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/NativeButtonElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.NativeButton")
+public class NativeButtonElement extends ButtonElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/NativeSelectElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/NativeSelectElement.java
new file mode 100644
index 0000000000..99becf125e
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/NativeSelectElement.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+
+import org.openqa.selenium.support.ui.Select;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.NativeSelect")
+public class NativeSelectElement extends AbstractSelectElement {
+ private Select selectElement;
+
+ @Override
+ protected void init() {
+ super.init();
+ selectElement = new Select(findElement(By.tagName("select")));
+ }
+
+ public List<TestBenchElement> getOptions() {
+ return wrapElements(selectElement.getOptions(), getCommandExecutor());
+ }
+
+ public void selectByText(String text) throws ReadOnlyException {
+ if (isReadOnly()) {
+ throw new ReadOnlyException();
+ }
+ selectElement.selectByVisibleText(text);
+ waitForVaadin();
+ }
+
+ /**
+ * Clear operation is not supported for Native Select. This operation has no
+ * effect on Native Select element.
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ }
+
+ /**
+ * Return value of the selected item in the native select element
+ *
+ * @return value of the selected item in the native select element
+ */
+ public String getValue() {
+ return selectElement.getFirstSelectedOption().getText();
+ }
+
+ /**
+ * Select item of the native select element with the specified value
+ *
+ * @param chars
+ * value of the native select item will be selected
+ */
+ public void setValue(CharSequence chars) throws ReadOnlyException {
+ selectByText((String) chars);
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/NotificationElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/NotificationElement.java
new file mode 100644
index 0000000000..bc97194fda
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/NotificationElement.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.TimeoutException;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import com.vaadin.testbench.elementsbase.AbstractElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Notification")
+public class NotificationElement extends AbstractElement {
+ /**
+ * Closes a notification
+ *
+ * @throws TimeoutException
+ * If a notification can not be closed and the timeout expires.
+ */
+ public void close() {
+ click();
+ WebDriverWait wait = new WebDriverWait(getDriver(), 10);
+ wait.until(ExpectedConditions
+ .not(ExpectedConditions.presenceOfAllElementsLocatedBy(
+ By.className("v-Notification"))));
+
+ }
+
+ /**
+ * Returns the caption of the Notification element
+ *
+ * @since
+ * @return the caption of the Notification element
+ */
+ public String getCaption() {
+ WebElement popup = findElement(By.className("popupContent"));
+ WebElement caption = popup.findElement(By.tagName("h1"));
+ return caption.getText();
+ }
+
+ /**
+ * Returns description of the Notification element
+ *
+ * @return description of the Notification element
+ */
+ public String getDescription() {
+ WebElement popup = findElement(By.className("popupContent"));
+ WebElement caption = popup.findElement(By.tagName("p"));
+ return caption.getText();
+ }
+
+ /**
+ * Returns type of the Notification element
+ *
+ * @return type of the Notification element
+ */
+ public String getType() {
+ // The info about notification type can be taken only from css rule of
+ // the notification
+ // To get type we search for css rules which represent notification type
+ // This map maps css style rule to type of a notification
+ HashMap<String, String> styleToTypeMap = initStyleToTypeMap();
+ for (Map.Entry<String, String> entry : styleToTypeMap.entrySet()) {
+ String notifType = entry.getKey();
+ // Check notification has css style which describes notification
+ // type
+ if (getAttribute("class").contains(notifType)) {
+ return entry.getValue();
+ }
+ }
+ return "";
+ }
+
+ private HashMap<String, String> initStyleToTypeMap() {
+ HashMap<String, String> styleToType = new HashMap<String, String>();
+ styleToType.put("v-Notification-error", "error");
+ styleToType.put("v-Notification-warning", "warning");
+ styleToType.put("v-Notification-humanized", "humanized");
+ styleToType.put("v-Notification-tray", "tray_notification");
+ return styleToType;
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/OptionGroupElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/OptionGroupElement.java
new file mode 100644
index 0000000000..8c5dcea181
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/OptionGroupElement.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.OptionGroup")
+@Deprecated
+public class OptionGroupElement extends AbstractSelectElement {
+
+ private static org.openqa.selenium.By bySelectOption = By
+ .className("v-select-option");
+ private static org.openqa.selenium.By byLabel = By.tagName("label");
+ private static org.openqa.selenium.By byRadioInput = By.tagName("input");
+
+ public List<String> getOptions() {
+ List<String> optionTexts = new ArrayList<String>();
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ optionTexts.add(option.findElement(byLabel).getText());
+ }
+ return optionTexts;
+ }
+
+ public void selectByText(String text) throws ReadOnlyException {
+ if (isReadOnly()) {
+ throw new ReadOnlyException();
+ }
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ if (text.equals(option.findElement(byLabel).getText())) {
+ WebElement input = option.findElement(byRadioInput);
+ ((TestBenchElement) (input)).clickHiddenElement();
+ }
+ }
+ }
+
+ /**
+ * Return value of the selected option in the option group
+ *
+ * @return value of the selected option in the option group
+ */
+ public String getValue() {
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ WebElement checkedItem;
+ checkedItem = option.findElement(By.tagName("input"));
+ String checked = checkedItem.getAttribute("checked");
+ if (checked != null
+ && checkedItem.getAttribute("checked").equals("true")) {
+ return option.findElement(By.tagName("label")).getText();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Select option in the option group with the specified value
+ *
+ * @param chars
+ * value of the option in the option group which will be selected
+ */
+ public void setValue(CharSequence chars) throws ReadOnlyException {
+ selectByText((String) chars);
+ }
+
+ /**
+ * Clear operation is not supported for Option Group. This operation has no
+ * effect on Option Group element.
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/PanelElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/PanelElement.java
new file mode 100644
index 0000000000..9f340bf428
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/PanelElement.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Panel")
+public class PanelElement extends AbstractSingleComponentContainerElement {
+ @Override
+ public void scroll(int scrollTop) {
+ ((TestBenchElement) findElement(By.className("v-scrollable")))
+ .scroll(scrollTop);
+ }
+
+ @Override
+ public void scrollLeft(int scrollLeft) {
+ ((TestBenchElement) findElement(By.className("v-scrollable")))
+ .scrollLeft(scrollLeft);
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/PasswordFieldElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/PasswordFieldElement.java
new file mode 100644
index 0000000000..3866aa797e
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/PasswordFieldElement.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.PasswordField")
+public class PasswordFieldElement extends AbstractTextFieldElement {
+ /**
+ * Return value of the password element
+ *
+ * @since
+ * @return value of the password element
+ */
+ @Override
+ public String getValue() {
+ return getAttribute("value");
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/PopupDateFieldElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/PopupDateFieldElement.java
new file mode 100644
index 0000000000..3b9d65f416
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/PopupDateFieldElement.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.PopupDateField")
+@Deprecated
+public class PopupDateFieldElement extends DateFieldElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/PopupViewElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/PopupViewElement.java
new file mode 100644
index 0000000000..7c5bd5512d
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/PopupViewElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.PopupView")
+public class PopupViewElement extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ProgressBarElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ProgressBarElement.java
new file mode 100644
index 0000000000..f567dbf904
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ProgressBarElement.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.ProgressBar")
+public class ProgressBarElement extends AbstractFieldElement {
+
+ /**
+ * Retrns the value of the progress bar
+ *
+ * @return
+ */
+ public double getValue() {
+ WebElement indicator = findElement(
+ By.className("v-progressbar-indicator"));
+ String width = getStyleAttribute(indicator, "width");
+ if (!width.endsWith("%")) {
+ return 0;
+ }
+
+ return Double.parseDouble(width.replace("%", "")) / 100.0;
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/ProgressIndicatorElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/ProgressIndicatorElement.java
new file mode 100644
index 0000000000..6d3d476d3a
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/ProgressIndicatorElement.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.ProgressIndicator")
+@Deprecated
+public class ProgressIndicatorElement extends ProgressBarElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/RadioButtonGroupElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/RadioButtonGroupElement.java
new file mode 100644
index 0000000000..4feeaae6ff
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/RadioButtonGroupElement.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.RadioButtonGroup")
+public class RadioButtonGroupElement extends AbstractSelectElement {
+
+ private static org.openqa.selenium.By bySelectOption = By
+ .className("v-select-option");
+ private static org.openqa.selenium.By byLabel = By.tagName("label");
+ private static org.openqa.selenium.By byRadioInput = By.tagName("input");
+
+ public List<String> getOptions() {
+ List<String> optionTexts = new ArrayList<String>();
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ optionTexts.add(option.findElement(byLabel).getText());
+ }
+ return optionTexts;
+ }
+
+ public void selectByText(String text) throws ReadOnlyException {
+ if (isReadOnly()) {
+ throw new ReadOnlyException();
+ }
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ if (text.equals(option.findElement(byLabel).getText())) {
+ WebElement input = option.findElement(byRadioInput);
+ ((TestBenchElement) (input)).clickHiddenElement();
+ }
+ }
+ }
+
+ /**
+ * Return value of the selected option in the option group
+ *
+ * @return value of the selected option in the option group
+ */
+ public String getValue() {
+ List<WebElement> options = findElements(bySelectOption);
+ for (WebElement option : options) {
+ WebElement checkedItem;
+ checkedItem = option.findElement(By.tagName("input"));
+ String checked = checkedItem.getAttribute("checked");
+ if (checked != null
+ && checkedItem.getAttribute("checked").equals("true")) {
+ return option.findElement(By.tagName("label")).getText();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Select option in the option group with the specified value
+ *
+ * @param chars
+ * value of the option in the option group which will be selected
+ */
+ public void setValue(CharSequence chars) throws ReadOnlyException {
+ selectByText((String) chars);
+ }
+
+ /**
+ * Clear operation is not supported for Option Group. This operation has no
+ * effect on Option Group element.
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/RichTextAreaElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/RichTextAreaElement.java
new file mode 100644
index 0000000000..d5cc9e9a8a
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/RichTextAreaElement.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.RichTextArea")
+public class RichTextAreaElement extends AbstractFieldElement {
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/SelectElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/SelectElement.java
new file mode 100644
index 0000000000..c3b74bddd2
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/SelectElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Select")
+@Deprecated
+public class SelectElement extends ComboBoxElement {
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/SliderElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/SliderElement.java
new file mode 100644
index 0000000000..396a2435b3
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/SliderElement.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.remote.BrowserType;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Slider")
+public class SliderElement extends AbstractFieldElement {
+ /**
+ * Get value of the slider
+ *
+ * Warning! This method cause slider popup to appear on the screen. To hide
+ * this popup just focus any other element on the page.
+ */
+ public String getValue() {
+ List<WebElement> popupElems = findElements(By.vaadin("#popup"));
+ // SubPartAware was implemented after 7.2.6, not sure in which release
+ // it will be included
+ if (popupElems.isEmpty()) {
+ throw new UnsupportedOperationException(
+ "Current version of vaadin doesn't support geting values from sliderElement");
+
+ }
+ WebElement popupElem = popupElems.get(0);
+
+ if (BrowserType.IE.equals(getCapabilities().getBrowserName())
+ && "8".equals(getCapabilities().getVersion())) {
+ return popupElem.getAttribute("innerText");
+ } else {
+ return popupElem.getAttribute("textContent");
+ }
+
+ }
+
+ public WebElement getHandle() {
+ return findElement(By.className("v-slider-handle"));
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TabSheetElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TabSheetElement.java
new file mode 100644
index 0000000000..54c7291d51
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TabSheetElement.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBench;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.AbstractElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.TabSheet")
+public class TabSheetElement extends AbstractComponentContainerElement {
+
+ // a locator that does not lead to selecting tabs from a contained inner
+ // TabSheet (#13735)
+ protected org.openqa.selenium.By byTabCell = By
+ .xpath("./div/table/tbody/tr/td[contains(normalize-space(concat(' ', @class, ' ')),"
+ + "normalize-space(' v-tabsheet-tabitem '))]");
+ private static org.openqa.selenium.By byCaption = By
+ .className("v-captiontext");
+ private static org.openqa.selenium.By byClosable = By
+ .className("v-tabsheet-caption-close");
+
+ /**
+ * Gets a list of Tabs inside the Tab container.
+ *
+ * @return List of tabs
+ */
+ public List<String> getTabCaptions() {
+ List<String> tabCaptions = new ArrayList<String>();
+ for (WebElement tab : findElements(byTabCell)) {
+ tabCaptions.add(getTabCaption(tab));
+ }
+ return tabCaptions;
+ }
+
+ /**
+ * Gets the number of tabs contained in this tab sheet.
+ *
+ * @return Number of tabs.
+ */
+ public int getTabCount() {
+ return findElements(byTabCell).size();
+ }
+
+ /**
+ * Opens the tab with the given index.
+ *
+ * @param index
+ * The zero-based index of the tab to be opened.
+ */
+ public void openTab(int index) {
+ List<WebElement> tabs = findElements(byTabCell);
+ if (index < 0 || index >= tabs.size()) {
+ throw new NoSuchElementException(
+ "The tab sheet does not contain a tab with index " + index
+ + ".");
+ }
+ openTab(tabs.get(index));
+ }
+
+ /**
+ * Opens a Tab that has caption equal to given tabCaption.
+ *
+ * @param tabCaption
+ * Caption of the tab to be opened
+ */
+ public void openTab(String tabCaption) {
+ for (WebElement tabCell : findElements(byTabCell)) {
+ String currentCaption = getTabCaption(tabCell);
+ boolean captionMatches = (currentCaption != null
+ && currentCaption.equals(tabCaption))
+ || (currentCaption == null && tabCaption == null);
+ if (captionMatches) {
+ openTab(tabCell);
+ return;
+ }
+ }
+ throw new NoSuchElementException(
+ "Tab with caption " + tabCaption + " was not found.");
+ }
+
+ /**
+ * Opens the given tab by clicking its caption text or icon. If the tab has
+ * neither text caption nor icon, clicks at a fixed position.
+ *
+ * @param tabCell
+ * The tab to be opened.
+ */
+ private void openTab(WebElement tabCell) {
+ // Open the tab by clicking its caption text if it exists.
+ List<WebElement> tabCaptions = tabCell.findElements(byCaption);
+ if (tabCaptions.size() > 0) {
+ tabCaptions.get(0).click();
+ return;
+ }
+ // If no caption text was found, click the icon of the tab.
+ List<WebElement> tabIcons = tabCell
+ .findElements(By.className("v-icon"));
+ if (tabIcons.size() > 0) {
+ tabIcons.get(0).click();
+ return;
+ }
+ // If neither text nor icon caption was found, click at a position that
+ // is unlikely to close the tab.
+ ((TestBenchElement) tabCell).click(10, 10);
+ }
+
+ /**
+ * If the tab with given index is closable, closes it.
+ *
+ * @param index
+ * The index of the tab to be closed
+ */
+ public void closeTab(int index) {
+ List<WebElement> tabs = findElements(byTabCell);
+ if (index < 0 || index >= tabs.size()) {
+ throw new NoSuchElementException(
+ "The tab sheet does not contain a tab with index " + index
+ + ".");
+ }
+ WebElement tabCell = tabs.get(index);
+ closeTab(tabCell);
+ }
+
+ /**
+ * If tab with given caption is closable, closes it.
+ *
+ * @param tabCaption
+ * Caption of the tab to be closed
+ */
+ public void closeTab(String tabCaption) {
+ for (WebElement tabCell : findElements(byTabCell)) {
+ String currentCaption = getTabCaption(tabCell);
+ boolean captionMatches = (currentCaption != null
+ && currentCaption.equals(tabCaption))
+ || (currentCaption == null && tabCaption == null);
+ if (captionMatches) {
+ closeTab(tabCell);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Closes the given tab if it is closable.
+ *
+ * @param tabCell
+ * The tab to be closed
+ */
+ private void closeTab(WebElement tabCell) {
+ try {
+ tabCell.findElement(byClosable).click();
+ // Going further causes a StaleElementReferenceException.
+ return;
+ } catch (NoSuchElementException e) {
+ // Do nothing.
+ }
+ }
+
+ /**
+ * Gets TabSheet content and wraps it in given class.
+ *
+ * @param clazz
+ * Components element class
+ * @return TabSheet content wrapped in given class
+ */
+ public <T extends AbstractElement> T getContent(Class<T> clazz) {
+ return TestBench.createElement(clazz,
+ $$(AbstractComponentElement.class).first().getWrappedElement(),
+ getCommandExecutor());
+ }
+
+ /**
+ * Returns the caption text of the given tab. If the tab has no caption,
+ * returns null.
+ *
+ * @param tabCell
+ * A web element representing a tab, as given by
+ * findElements(byTabCell).get(index).
+ * @return The caption of tabCell or null if tabCell has no caption.
+ */
+ private String getTabCaption(WebElement tabCell) {
+ List<WebElement> captionElements = tabCell.findElements(byCaption);
+ if (captionElements.size() == 0) {
+ return null;
+ } else {
+ return captionElements.get(0).getText();
+ }
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TableElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TableElement.java
new file mode 100644
index 0000000000..68a42533b1
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TableElement.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebDriverException;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.AbstractElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Table")
+@Deprecated
+public class TableElement extends AbstractSelectElement {
+
+ /**
+ * Function to find a Table cell. Looking for a cell that is currently not
+ * visible will throw NoSuchElementException
+ *
+ * @param row
+ * 0 based row index
+ * @param column
+ * 0 based column index
+ * @return TestBenchElement containing wanted cell.
+ * @throws NoSuchElementException
+ * if the cell (row, column) is not found.
+ */
+ public TestBenchElement getCell(int row, int column) {
+
+ TestBenchElement cell = wrapElement(
+ findElement(By.vaadin("#row[" + row + "]/col[" + column + "]")),
+ getCommandExecutor());
+
+ return cell;
+ }
+
+ /**
+ * Return table row element by zero-based index
+ *
+ * @return table row element by zero-based index
+ */
+ public TableRowElement getRow(int row) {
+ TestBenchElement rowElem = wrapElement(
+ findElement(By.vaadin("#row[" + row + "]")),
+ getCommandExecutor());
+ return rowElem.wrap(TableRowElement.class);
+ }
+
+ /**
+ * Returns the header cell with the given column index.
+ *
+ * @param column
+ * 0 based column index
+ * @return TableHeaderElement containing the wanted header cell
+ */
+ public TableHeaderElement getHeaderCell(int column) {
+ TestBenchElement headerCell = wrapElement(
+ findElement(By.vaadin("#header[" + column + "]")),
+ getCommandExecutor());
+ return headerCell.wrap(TableHeaderElement.class);
+ }
+
+ /**
+ * Function to get footer cell with given column index
+ *
+ * @param column
+ * 0 based column index
+ * @return TestBenchElement containing wanted footer cell
+ */
+ public TestBenchElement getFooterCell(int column) {
+ TestBenchElement footerCell = wrapElement(
+ findElement(By.vaadin("#footer[" + column + "]")),
+ getCommandExecutor());
+ return footerCell;
+ }
+
+ @Override
+ public void scroll(int scrollTop) {
+ ((TestBenchElement) findElement(By.className("v-scrollable")))
+ .scroll(scrollTop);
+ }
+
+ @Override
+ public void scrollLeft(int scrollLeft) {
+ ((TestBenchElement) findElement(By.className("v-scrollable")))
+ .scrollLeft(scrollLeft);
+ }
+
+ @Override
+ public void contextClick() {
+ WebElement tbody = findElement(By.className("v-table-body"));
+ // There is a problem in with phantomjs driver, just calling
+ // contextClick() doesn't work. We have to use javascript.
+ if (isPhantomJS()) {
+ JavascriptExecutor js = getCommandExecutor();
+ String scr = "var element=arguments[0];"
+ + "var ev = document.createEvent('HTMLEvents');"
+ + "ev.initEvent('contextmenu', true, false);"
+ + "element.dispatchEvent(ev);";
+ js.executeScript(scr, tbody);
+ } else {
+ new Actions(getDriver()).contextClick(tbody).build().perform();
+ }
+ }
+
+ public static class ContextMenuElement extends AbstractElement {
+
+ public WebElement getItem(int index) {
+ return findElement(
+ By.xpath(".//table//tr[" + (index + 1) + "]//td/*"));
+ }
+
+ }
+
+ /**
+ * Fetches the context menu for the table
+ *
+ * @return {@link com.vaadin.testbench.elements.TableElement.ContextMenuElement}
+ * @throws java.util.NoSuchElementException
+ * if the menu isn't open
+ */
+ public ContextMenuElement getContextMenu() {
+ try {
+ WebElement cm = getDriver()
+ .findElement(By.className("v-contextmenu"));
+ return wrapElement(cm, getCommandExecutor())
+ .wrap(ContextMenuElement.class);
+ } catch (WebDriverException e) {
+ throw new NoSuchElementException("Context menu not found", e);
+ }
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TableHeaderElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TableHeaderElement.java
new file mode 100644
index 0000000000..5715d3fcfa
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TableHeaderElement.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+@Deprecated
+public class TableHeaderElement extends AbstractComponentElement {
+
+ @Override
+ public String getCaption() {
+ WebElement captionElement = findElement(
+ By.className("v-table-caption-container"));
+ return captionElement.getText();
+ }
+
+ /**
+ * Returns column resize handle.
+ *
+ * You can resize column by using selenium Actions i.e. new
+ * Actions(getDriver()).clickAndHold(handle).moveByOffset(x,
+ * y).release().build().perform();
+ *
+ * @return column resize handle
+ */
+ public WebElement getResizeHandle() {
+ return findElement(By.className("v-table-resizer"));
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TableRowElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TableRowElement.java
new file mode 100644
index 0000000000..25a656599d
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TableRowElement.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.exceptions.NoSuchColumnException;
+
+@Deprecated
+public class TableRowElement extends AbstractComponentElement {
+
+ /**
+ * Returns cell from current row by index. Returns the same element as
+ * $(TableElement.class).first().getCell(row, col).
+ *
+ * @see com.vaadin.testbench.elements.TableElement#getCell(int, int)
+ * @param col
+ * column index
+ * @return cell from current row by index.
+ */
+ public TestBenchElement getCell(int col) {
+ List<WebElement> cells = getWrappedElement()
+ .findElements(By.tagName("td"));
+ if (col >= cells.size()) {
+ throw new NoSuchColumnException();
+ }
+
+ WebElement cellContent = cells.get(col);
+ return wrapElement(cellContent.findElement(By.xpath("./*")),
+ getCommandExecutor());
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TextAreaElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TextAreaElement.java
new file mode 100644
index 0000000000..e5e5ee90f4
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TextAreaElement.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.Keys;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.TextArea")
+public class TextAreaElement extends AbstractTextFieldElement {
+ /**
+ * Return value of the field element
+ *
+ * @since
+ * @return value of the field element
+ */
+ @Override
+ public String getValue() {
+ return getAttribute("value");
+ }
+
+ @Override
+ public void setValue(CharSequence chars) {
+ if (isReadOnly()) {
+ throw new ReadOnlyException();
+ }
+ // clears without triggering an event
+ clearElementClientSide(this);
+ focus();
+ sendKeys(chars);
+ sendKeys(Keys.TAB);
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TextFieldElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TextFieldElement.java
new file mode 100644
index 0000000000..aab5d474aa
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TextFieldElement.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.TextField")
+public class TextFieldElement extends AbstractTextFieldElement {
+ public String getValue() {
+ return getAttribute("value");
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeElement.java
new file mode 100644
index 0000000000..d879749c24
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeElement.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Tree")
+@Deprecated
+public class TreeElement extends AbstractSelectElement {
+ /**
+ * Returns selected item of the tree. In multiselect mode returns first
+ * selected item. If there is no selected item returns empty string
+ *
+ * @return selected item of the tree
+ */
+ public String getValue() {
+ List<WebElement> selectedElements = findElements(
+ By.className("v-tree-node-selected"));
+ if (selectedElements.isEmpty()) {
+ return "";
+ } else {
+ return selectedElements.get(0).getText();
+ }
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeTableElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeTableElement.java
new file mode 100644
index 0000000000..2331cbc9f0
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeTableElement.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.TreeTable")
+@Deprecated
+public class TreeTableElement extends TableElement {
+
+ @Override
+ public TreeTableRowElement getRow(int row) {
+ TestBenchElement element = super.getRow(row);
+ return element.wrap(TreeTableRowElement.class);
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeTableRowElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeTableRowElement.java
new file mode 100644
index 0000000000..be6bf144a3
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TreeTableRowElement.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.List;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+@Deprecated
+public class TreeTableRowElement extends TableRowElement {
+
+ /**
+ * Either expand collapsed row or collapse expanded row.
+ */
+ public void toggleExpanded() {
+ List<WebElement> expandButtons = getWrappedElement()
+ .findElements(By.className("v-treetable-treespacer"));
+ if (expandButtons.size() > 0) {
+ expandButtons.get(0).click();
+ }
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/TwinColSelectElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/TwinColSelectElement.java
new file mode 100644
index 0000000000..c68ade8ff4
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/TwinColSelectElement.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.Select;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.TwinColSelect")
+public class TwinColSelectElement extends AbstractSelectElement {
+
+ private Select options;
+ private Select selectedOptions;
+ private WebElement deselButton;
+ private WebElement selButton;
+ private static org.openqa.selenium.By bySelect = By.tagName("select");
+ private static org.openqa.selenium.By byButton = By.className("v-button");
+
+ @Override
+ protected void init() {
+ super.init();
+ List<WebElement> selectElements = findElements(bySelect);
+ options = new Select(selectElements.get(0));
+ selectedOptions = new Select(selectElements.get(1));
+ List<WebElement> buttons = findElements(byButton);
+ selButton = buttons.get(0);
+ deselButton = buttons.get(1);
+ }
+
+ private void deselectAll() {
+ if (selectedOptions.isMultiple()) {
+ if (selectedOptions.getAllSelectedOptions()
+ .size() != selectedOptions.getOptions().size()) {
+ for (int i = 0, l = selectedOptions.getOptions()
+ .size(); i < l; ++i) {
+ selectedOptions.selectByIndex(i);
+ }
+ }
+ deselButton.click();
+ }
+ while (selectedOptions.getOptions().size() > 0) {
+ selectedOptions.selectByIndex(0);
+ deselButton.click();
+ }
+ }
+
+ public void deselectByText(String text) {
+ selectedOptions.deselectAll();
+ selectedOptions.selectByVisibleText(text);
+ deselButton.click();
+ }
+
+ /**
+ * Functionality to find option texts of all currently selected options.
+ *
+ * @return List of visible text for all selected options
+ */
+ public List<String> getValues() {
+ return getOptionsFromSelect(selectedOptions);
+ }
+
+ /**
+ * Functionality to find all option texts.
+ *
+ * @return List of visible text for all options
+ */
+ public List<String> getOptions() {
+ List<String> optionTexts = getOptionsFromSelect(options);
+ optionTexts.addAll(getValues());
+ return optionTexts;
+ }
+
+ /**
+ * Gets the available option texts, i.e. all values which have not been
+ * selected.
+ *
+ * @return List of visible text for available options
+ */
+ public List<String> getAvailableOptions() {
+ return getOptionsFromSelect(options);
+ }
+
+ public void selectByText(String text) {
+ options.deselectAll();
+ options.selectByVisibleText(text);
+ selButton.click();
+ }
+
+ private List<String> getOptionsFromSelect(Select select) {
+ List<String> optionTexts = new ArrayList<String>();
+ for (WebElement option : select.getOptions()) {
+ optionTexts.add(option.getText());
+ }
+ return optionTexts;
+ }
+
+ /**
+ * Return first selected item (item in the right part of component)
+ */
+ public String getValue() {
+ String value = "";
+ WebElement selectedElement = findElement(
+ By.className("v-select-twincol-selections"));
+ List<WebElement> optionElements = selectedElement
+ .findElements(By.tagName("option"));
+ if (!optionElements.isEmpty()) {
+ value = optionElements.get(0).getText();
+ }
+ return value;
+ }
+
+ @Override
+ public void clear() {
+ deselectAll();
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/UIElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/UIElement.java
new file mode 100644
index 0000000000..f942497e6d
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/UIElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.UI")
+public class UIElement extends AbstractSingleComponentContainerElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/UploadElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/UploadElement.java
new file mode 100644
index 0000000000..b9f3341196
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/UploadElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Upload")
+public class UploadElement extends AbstractComponentElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/VerticalLayoutElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/VerticalLayoutElement.java
new file mode 100644
index 0000000000..3c75a91b68
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/VerticalLayoutElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.VerticalLayout")
+public class VerticalLayoutElement extends AbstractOrderedLayoutElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/VerticalSplitPanelElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/VerticalSplitPanelElement.java
new file mode 100644
index 0000000000..a2d72ce50f
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/VerticalSplitPanelElement.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.VerticalSplitPanel")
+public class VerticalSplitPanelElement extends AbstractSplitPanelElement {
+
+ private static By bySplit = By.className("v-splitpanel-vsplitter");
+
+ public TestBenchElement getSplitter() {
+ return wrapElement(findElement(bySplit), getCommandExecutor());
+ }
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/VideoElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/VideoElement.java
new file mode 100644
index 0000000000..0dd32820ea
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/VideoElement.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Video")
+public class VideoElement extends AbstractMediaElement {
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/elements/WindowElement.java b/testbench-api/src/main/java/com/vaadin/testbench/elements/WindowElement.java
new file mode 100644
index 0000000000..08c1a2f28d
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/elements/WindowElement.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+/**
+ * Element API for the Window class.
+ *
+ * Note that parts of the Window element API has limitations on IE8 and Phantom.
+ */
+@ServerClass("com.vaadin.ui.Window")
+public class WindowElement extends PanelElement {
+
+ private static final String HEADER_CLASS = "v-window-header";
+ private static final String RESTORE_BOX_CLASS = "v-window-restorebox";
+ private static final String MAXIMIZE_BOX_CLASS = "v-window-maximizebox";
+ private static final String CLOSE_BOX_CLASS = "v-window-closebox";
+
+ /**
+ * Clicks the close button of the window
+ */
+ public void close() {
+ getCloseButton().click();
+ }
+
+ /**
+ * Clicks the restore button of the window
+ */
+ public void restore() {
+ if (isMaximized()) {
+ getRestoreButton().click();
+ } else {
+ throw new IllegalStateException(
+ "Window is not maximized, cannot be restored.");
+ }
+ }
+
+ /**
+ * Check if this window is currently maximized
+ */
+ public boolean isMaximized() {
+ return isElementPresent(By.className(RESTORE_BOX_CLASS));
+ }
+
+ /**
+ * Clicks the maximize button of the window
+ */
+ public void maximize() {
+ if (!isMaximized()) {
+ getMaximizeButton().click();
+ } else {
+ throw new IllegalStateException(
+ "Window is already maximized, cannot maximize.");
+ }
+ }
+
+ private WebElement getRestoreButton() {
+ return findElement(By.className(RESTORE_BOX_CLASS));
+ }
+
+ private WebElement getMaximizeButton() {
+ return findElement(By.className(MAXIMIZE_BOX_CLASS));
+ }
+
+ private WebElement getCloseButton() {
+ return findElement(By.className(CLOSE_BOX_CLASS));
+ }
+
+ /**
+ * @return the caption of the window
+ */
+ @Override
+ public String getCaption() {
+ return findElement(By.className(HEADER_CLASS)).getText();
+ }
+
+}
diff --git a/testbench-api/src/main/java/com/vaadin/testbench/exceptions/NoSuchColumnException.java b/testbench-api/src/main/java/com/vaadin/testbench/exceptions/NoSuchColumnException.java
new file mode 100644
index 0000000000..a9e9cbfba3
--- /dev/null
+++ b/testbench-api/src/main/java/com/vaadin/testbench/exceptions/NoSuchColumnException.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.exceptions;
+
+public class NoSuchColumnException extends RuntimeException {
+
+}