package com.abmash.api;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RemoteWebElement;
import com.abmash.REMOVE.api.HtmlQuery;
import com.abmash.REMOVE.core.htmlquery.condition.ElementCondition.ElementType;
import com.abmash.api.query.Query;
import com.abmash.api.query.QueryFactory;
/**
* List of {@link HtmlElement} instances.
* <p>
* Find <code>HtmlElements</code> by using the {@link Browser#query(com.abmash.core.query.predicate.Predicate...)} method.
* The {@link HtmlQuery#find()} method returns <code>HtmlElements</code>. See {@link HtmlQuery} how to find elements.
* <p>
* <strong>Example:</strong>
* <ul>
* <li><code>HtmlElement myElement = browser.query().isTitle().isClickable().has("today").findFirst();</code> directly searches
* for clickable titles labeled <em>today</em> and returns the <code>HtmlElement</code></li>
* <li>See the documentation of {@link HtmlQuery} for more examples</li>
* </ul>
* <p>
* Bulk interactions on all contained elements can be executed by calling the appropriate methods, e.g. {@link #type(String)}
* or {@link #clear()}.
*
* @author Alper Ortac
* @see HtmlElement
*/
public class HtmlElements extends ArrayList<HtmlElement> {
private static final long serialVersionUID = 1L;
/**
* Constructs new empty list.
*/
public HtmlElements() {
super();
}
/**
* Constructs new list with one element.
*
* @param element the first element in the list
* @see HtmlElement
*/
public HtmlElements(HtmlElement element) {
super();
add(element);
}
/**
/**
* Constructs new list with multiple Selenium {@code WebElement} instances.
*
* @param browser browser instance in which these elements are contained
* @param webElements list of Selenium {@link WebElement}
* @see HtmlElement
*/
public HtmlElements(Browser browser, List<WebElement> webElements) {
super();
if(webElements != null && !webElements.isEmpty()) {
for (WebElement webElement: webElements) {
RemoteWebElement renderedElement = (RemoteWebElement) webElement;
// check if element can be interacted with
if(renderedElement.isEnabled() && (renderedElement.isDisplayed() || renderedElement.getTagName() == "input" || renderedElement.getTagName() == "textarea")) {
// TODO ignore duplicates?
add(new HtmlElement(browser, renderedElement));
}
}
}
}
// element methods
/**
* Clicks all elements.
* <p>
* Warning: if clicking an element causes the page to reload, the other clicks will fail and throw an error.
*
* @return this {@link HtmlElements}
* @see HtmlElement#click()
*/
public HtmlElements click() {
for (HtmlElement element: this) {
element.click();
}
return this;
}
/**
* Hovers all elements with the mouse.
*
* @return this {@link HtmlElements}
* @see HtmlElement#hover()
*/
public HtmlElements hover() {
for (HtmlElement element: this) {
element.hover();
}
return this;
}
/**
* Drags all elements to a target element.
*
* @param targetElement the element to drag the elements to
* @return this {@link HtmlElements}
* @see HtmlElement#click()
*/
public HtmlElements dragTo(HtmlElement targetElement) {
for (HtmlElement element: this) {
element.dragTo(targetElement);
}
return this;
}
/**
* Clears the entered text in all elements.
*
* @see HtmlElement#clear()
*/
public void clear() {
// TODO return type this
for (HtmlElement element: this) {
element.clear();
}
// return this;
}
/**
* Enters text in all elements.
*
* @param text
* @return this {@link HtmlElements}
* @see HtmlElement#type(String)
*/
public HtmlElements type(String text) {
for (HtmlElement element: this) {
element.type(text);
}
return this;
}
/**
* Presses key on all elements.
*
* @param keyName
* @return this {@link HtmlElements}
* @see HtmlElement#keyPress(String)
*/
public HtmlElements keyPress(String keyName) {
for (HtmlElement element: this) {
element.keyPress(keyName);
}
return this;
}
/**
* Submits all elements.
*
* @return this {@link HtmlElements}
* @see HtmlElement#submit()
*/
public HtmlElements submit() {
for (HtmlElement element: this) {
element.submit();
}
return this;
}
/**
* Gets all inner texts of the elements.
*
* @return array of all text strings
* @see HtmlElement#getText()
*/
public ArrayList<String> getTexts() {
ArrayList<String> texts = new ArrayList<String>();
for (HtmlElement element: this) {
texts.add(element.getText());
}
return texts;
}
/**
* Gets all extracted URLs of the elements.
*
* @return array of all extracted URLs
* @see HtmlElement#getText()
*/
public ArrayList<String> getUrls() {
ArrayList<String> urls = new ArrayList<String>();
for (HtmlElement element: this) {
String url = element.getUrl();
if(url != null) urls.add(url);
}
return urls;
}
// custom methods
/**
* Sets the type of all elements.
*
* @param types
* @see HtmlElement#setTypes(ArrayList)
*/
public void setTypes(ArrayList<ElementType> types) {
for (HtmlElement element: this) {
element.setTypes(types);
}
}
// list methods
/**
* Adds an {@link HtmlElement} to the list. If you want to ignore duplicates use {@link #addAndIgnoreDuplicates(HtmlElement)}.
*
* @see java.util.ArrayList#add(java.lang.Object)
*/
@Override
public boolean add(HtmlElement element) {
return super.add(element);
}
/**
* Adds an {@link HtmlElement} if it not exists in the list yet.
*
* @see java.util.ArrayList#add(java.lang.Object)
*/
public boolean addAndIgnoreDuplicates(HtmlElement element) {
if(!contains(element)) {
return super.add(element);
}
return true;
}
/**
* Adds all {@link HtmlElements} to the list. If you want to ignore duplicates use {@link #addAllAndIgnoreDuplicates(Collection)}.
*
* @see java.util.ArrayList#addAll(java.util.Collection)
*/
@Override
public boolean addAll(Collection<? extends HtmlElement> elements) {
boolean addValid = true;
for (HtmlElement element: elements) {
addValid &= add(element);
}
return addValid;
}
/**
* Adds all {@link HtmlElements} not existing in the list yet.
*
* @see java.util.ArrayList#addAll(java.util.Collection)
*/
public boolean addAllAndIgnoreDuplicates(Collection<? extends HtmlElement> elements) {
boolean addValid = true;
for (HtmlElement element: elements) {
addValid &= addAndIgnoreDuplicates(element);
}
return addValid;
}
/**
* Checks if the list contains a HtmlElement.
*
* @param element
* @return true if list contains the element
*/
public boolean contains(HtmlElement element) {
for (HtmlElement htmlElement: this) {
if(htmlElement.equals(element)) {
return true;
}
}
return false;
}
/**
* Gets the nth item of the list.
*
* @param index number of the item, first item has index one
* @return the HtmlElement
*/
public HtmlElement nth(int index) {
return index > 0 && index <= size() ? get(index - 1) : null;
}
/**
* Gets the first item of the list.
*
* @return the HtmlElement
*/
public HtmlElement first() {
return nth(1);
}
/**
* Gets the second item of the list.
*
* @return the HtmlElement
*/
public HtmlElement second() {
return nth(2);
}
/**
* Gets the third item of the list.
*
* @return the HtmlElement
*/
public HtmlElement third() {
return nth(3);
}
/**
* Gets the last item of the list.
*
* @return the HtmlElement
*/
public HtmlElement last() {
return nth(size());
}
public String toString() {
String elementsString = "[\n";
for (HtmlElement element: this) {
elementsString += "\t" + element.toString() + "\n";
}
return elementsString + "]";
}
}