package com.codeborne.selenide.impl;
import com.codeborne.selenide.SelenideElement;
import org.openqa.selenium.*;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import static com.codeborne.selenide.Selenide.executeJavaScript;
import static com.codeborne.selenide.WebDriverRunner.isHtmlUnit;
import static com.codeborne.selenide.WebDriverRunner.supportsJavascript;
public class Describe {
private WebElement element;
private StringBuilder sb = new StringBuilder();
private Describe(WebElement element) {
this.element = element;
sb.append('<').append(element.getTagName());
}
private Describe appendAttributes() {
try {
if (supportsJavascriptAttributes()) {
return appendAllAttributes();
}
}
catch (UnsupportedOperationException browserDoesNotSupportJavaScript) {
}
return appendPredefinedAttributes();
}
private Describe appendAllAttributes() {
Map<String, String> map = executeJavaScript(
"var s = {};" +
"var attrs = arguments[0].attributes;" +
"for (var i = 0; i < attrs.length; i++) {" +
" var a = attrs[i]; " +
" if (a.name != 'style') {" +
" s[a.name] = a.value;" +
" }" +
"}" +
"return s;", element);
SortedMap<String, String> sortedByName = new TreeMap<>();
if (map != null) {
sortedByName.putAll(map);
}
sortedByName.put("value", element.getAttribute("value"));
if (!sortedByName.containsKey("type")) {
sortedByName.put("type", element.getAttribute("type"));
}
for (Map.Entry<String, String> entry : sortedByName.entrySet()) {
attr(entry.getKey(), entry.getValue());
}
return this;
}
private Describe appendPredefinedAttributes() {
return attr("class").attr("disabled").attr("href").attr("id").attr("name")
.attr("onclick").attr("onchange").attr("placeholder")
.attr("type").attr("value");
}
private boolean supportsJavascriptAttributes() {
return supportsJavascript() && !isHtmlUnit();
}
private Describe attr(String attributeName) {
String attributeValue = element.getAttribute(attributeName);
return attr(attributeName, attributeValue);
}
private Describe attr(String attributeName, String attributeValue) {
if (attributeValue != null && attributeValue.length() > 0) {
sb.append(' ').append(attributeName).append("=\"").append(attributeValue).append('"');
}
return this;
}
private String serialize() {
String text = element.getText();
sb.append('>').append(text == null ? "" : text).append("</").append(element.getTagName()).append('>');
return sb.toString();
}
@Override
public String toString() {
return sb.toString();
}
private String flush() {
return sb.append('>').toString();
}
public static String describe(WebElement element) {
try {
if (element == null) {
return "null";
}
return new Describe(element)
.appendAttributes()
.isSelected(element)
.isDisplayed(element)
.serialize();
} catch (WebDriverException elementDoesNotExist) {
return Cleanup.of.webdriverExceptionMessage(elementDoesNotExist);
}
catch (IndexOutOfBoundsException e) {
return e.toString();
}
}
static String shortly(WebElement element) {
try {
if (element == null) {
return "null";
}
if (element instanceof SelenideElement) {
return shortly(((SelenideElement) element).toWebElement());
}
return new Describe(element).attr("id").attr("name").flush();
} catch (WebDriverException elementDoesNotExist) {
return Cleanup.of.webdriverExceptionMessage(elementDoesNotExist);
}
catch (IndexOutOfBoundsException e) {
return e.toString();
}
}
private Describe isSelected(WebElement element) {
try {
if (element.isSelected()) {
sb.append(' ').append("selected:true");
}
} catch (UnsupportedOperationException ignore) {
} catch (InvalidElementStateException ignore) {
}
return this;
}
private Describe isDisplayed(WebElement element) {
try {
if (!element.isDisplayed()) {
sb.append(' ').append("displayed:false");
}
} catch (UnsupportedOperationException e) {
sb.append(' ').append("displayed:").append(e);
} catch (InvalidElementStateException e) {
sb.append(' ').append("displayed:").append(e);
}
return this;
}
static String shortly(By selector) {
if (selector instanceof By.ByCssSelector) {
return selector.toString()
.replaceFirst("By\\.selector:\\s*(.*)", "$1")
.replaceFirst("By\\.cssSelector:\\s*(.*)", "$1");
}
return selector.toString();
}
public static String selector(By selector) {
return selector.toString()
.replaceFirst("By\\.selector:\\s*", "")
.replaceFirst("By\\.cssSelector:\\s*", "");
}
public static String describe(WebDriver webDriver) {
return webDriver.getClass().getSimpleName();
}
}