Package com.codeborne.selenide.impl

Source Code of com.codeborne.selenide.impl.AbstractSelenideElement

package com.codeborne.selenide.impl;

import com.codeborne.selenide.*;
import com.codeborne.selenide.ex.ElementNotFound;
import com.codeborne.selenide.ex.ElementShould;
import com.codeborne.selenide.ex.ElementShouldNot;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.Select;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;

import static com.codeborne.selenide.Condition.*;
import static com.codeborne.selenide.Configuration.*;
import static com.codeborne.selenide.Selectors.byText;
import static com.codeborne.selenide.Selectors.byValue;
import static com.codeborne.selenide.Selenide.*;
import static com.codeborne.selenide.WebDriverRunner.isHtmlUnit;
import static com.codeborne.selenide.WebDriverRunner.isIE;
import static com.codeborne.selenide.impl.WebElementProxy.wrap;
import static java.lang.System.currentTimeMillis;
import static java.lang.Thread.currentThread;

abstract class AbstractSelenideElement implements InvocationHandler {
  abstract WebElement getDelegate();
  abstract WebElement getActualDelegate() throws NoSuchElementException, IndexOutOfBoundsException;
  abstract String getSearchCriteria();
  protected Exception lastError;

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if ("setValue".equals(method.getName())) {
      setValue((String) args[0]);
      return proxy;
    }
    else if ("val".equals(method.getName())) {
      if (args == null || args.length == 0) {
        return getValue();
      }
      else {
        setValue((String) args[0]);
        return proxy;
      }
    }
    else if ("attr".equals(method.getName())) {
      return getDelegate().getAttribute((String) args[0]);
    }
    else if ("name".equals(method.getName())) {
      return getDelegate().getAttribute("name");
    }
    else if ("data".equals(method.getName())) {
      return getDelegate().getAttribute("data-" + args[0]);
    }
     else if ("append".equals(method.getName())) {
      append((String) args[0]);
      return proxy;
    }
    else if ("pressEnter".equals(method.getName())) {
      getDelegate().sendKeys(Keys.ENTER);
      return proxy;
    }
    else if ("pressTab".equals(method.getName())) {
      getDelegate().sendKeys(Keys.TAB);
      return proxy;
    }
    else if ("followLink".equals(method.getName())) {
      followLink();
      return null;
    }
    else if ("text".equals(method.getName())) {
      return getDelegate().getText();
    }
    else if ("innerText".equals(method.getName())) {
      return getInnerText();
    }
    else if ("innerHtml".equals(method.getName())) {
      return getInnerHtml();
    }
    else if ("should".equals(method.getName())) {
      return invokeShould(proxy, "", args);
    }
    else if ("shouldHave".equals(method.getName())) {
      return invokeShould(proxy, "have ", args);
    }
    else if ("shouldBe".equals(method.getName())) {
      return invokeShould(proxy, "be ", args);
    }
    else if ("shouldNot".equals(method.getName())) {
      return invokeShouldNot(proxy, "", args);
    }
    else if ("shouldNotHave".equals(method.getName())) {
      return invokeShouldNot(proxy, "have ", args);
    }
    else if ("shouldNotBe".equals(method.getName())) {
      return invokeShouldNot(proxy, "be ", args);
    }
    else if ("parent".equals(method.getName())) {
      return parent((SelenideElement) proxy);
    }
    else if ("closest".equals(method.getName())) {
      return closest((SelenideElement) proxy, (String) args[0]);
    }
    else if ("find".equals(method.getName()) || "$".equals(method.getName())) {
      return args.length == 1 ?
          find((SelenideElement) proxy, args[0], 0) :
          find((SelenideElement) proxy, args[0], (Integer) args[1]);
    }
    else if ("findAll".equals(method.getName()) || "$$".equals(method.getName())) {
      final SelenideElement parent = (SelenideElement) proxy;
      return new ElementsCollection(new BySelectorCollection(parent, getSelector(args[0])));
    }
    else if ("toString".equals(method.getName())) {
      return describe();
    }
    else if ("exists".equals(method.getName())) {
      return exists();
    }
    else if ("isDisplayed".equals(method.getName())) {
      return isDisplayed();
    }
    else if ("is".equals(method.getName()) || "has".equals(method.getName())) {
      return matches((Condition) args[0]);
    }
    else if ("setSelected".equals(method.getName())) {
      setSelected((Boolean) args[0]);
      return proxy;
    }
    else if ("uploadFile".equals(method.getName())) {
      return uploadFile((SelenideElement) proxy, (File[]) args[0]);
    }
    else if ("uploadFromClasspath".equals(method.getName())) {
      return uploadFromClasspath((SelenideElement) proxy, (String[]) args[0]);
    }
    else if ("selectOption".equals(method.getName())) {
      selectOptionByText(getDelegate(), (String) args[0]);
      return null;
    }
    else if ("selectOptionByValue".equals(method.getName())) {
      selectOptionByValue(getDelegate(), (String) args[0]);
      return null;
    }
    else if ("getSelectedOption".equals(method.getName())) {
      return getSelectedOption(getDelegate());
    }
    else if ("getSelectedValue".equals(method.getName())) {
      return getSelectedValue(getDelegate());
    }
    else if ("getSelectedText".equals(method.getName())) {
      return getSelectedText(getDelegate());
    }
    else if ("toWebElement".equals(method.getName())) {
      return getActualDelegate();
    }
    else if ("waitUntil".equals(method.getName())) {
      if (args[0] instanceof String) {
        waitUntil("", (String) args[0], (Condition) args[1], (Long) args[2]);
      }
      else {
        waitUntil("", (Condition) args[0], (Long) args[1]);
      }
      return proxy;
    }
    else if ("waitWhile".equals(method.getName())) {
      if (args[0] instanceof String) {
        waitWhile("", (String) args[0], (Condition) args[1], (Long) args[2]);
      }
      else {
        waitWhile("", (Condition) args[0], (Long) args[1]);
      }
      return proxy;
    }
    else if ("scrollTo".equals(method.getName())) {
      scrollTo();
      return proxy;
    }
    else if ("download".equals(method.getName())) {
      return download();
    }
    else if ("click".equals(method.getName())) {
      click();
      return null;
    }
    else if ("contextClick".equals(method.getName())) {
      contextClick();
      return null;
    }
    else if ("hover".equals(method.getName())) {
      hover();
      return null;
    }
    else if ("dragAndDropTo".equals(method.getName())) {
      dragAndDropTo((String) args[0]);
      return null;
    }
    else if ("getWrappedElement".equals(method.getName())) {
      return getActualDelegate();
    }
    else if ("isImage".equals(method.getName())) {
      return isImage();
    }

    return delegateMethod(getDelegate(), method, args);
  }

  protected Object invokeShould(Object proxy, String prefix, Object[] args) {
    if (args[0] instanceof String) {
      return should(proxy, prefix, (String) args[0], (Condition[]) args[1]);
    }
    return should(proxy, prefix, (Condition[]) args[0]);
  }

  protected Object invokeShouldNot(Object proxy, String prefix, Object[] args) {
    if (args[0] instanceof String) {
      return shouldNot(proxy, prefix, (String) args[0], (Condition[]) args[1]);
    }
    return shouldNot(proxy, prefix, (Condition[]) args[0]);
  }

  protected Boolean isImage() {
    WebElement img = getActualDelegate();
    if (!"img".equalsIgnoreCase(img.getTagName())) {
      throw new IllegalArgumentException("Method isImage() is only applicable for img elements");
    }
    return executeJavaScript("return arguments[0].complete && " +
        "typeof arguments[0].naturalWidth != 'undefined' && " +
        "arguments[0].naturalWidth > 0", img);
  }

  protected boolean matches(Condition condition) {
    try {
      WebElement element = tryToGetElement();
      if (element != null) {
        return condition.apply(element);
      }
    }
    catch (WebDriverException elementNotFound) {
      lastError = elementNotFound;
    }
    catch (IndexOutOfBoundsException ignore) {
      lastError = ignore;
    }

    if (Cleanup.of.isInvalidSelectorError(lastError)) {
      throw Cleanup.of.wrap(lastError);
    }

    return condition.applyNull();
  }

  protected void setSelected(boolean selected) {
    WebElement element = waitForElement();
    if (element.isSelected() ^ selected) {
      element.click();
    }
  }

  protected String getInnerText() {
    WebElement element = waitUntil("", exist, timeout);
    if (isHtmlUnit()) {
      return executeJavaScript("return arguments[0].innerText", element);
    }
    else if (isIE()) {
      return element.getAttribute("innerText");
    }
    return element.getAttribute("textContent");
  }

  protected String getInnerHtml() {
    WebElement element = waitUntil("", exist, timeout);
    if (isHtmlUnit()) {
      return executeJavaScript("return arguments[0].innerHTML", element);
    }
    return element.getAttribute("innerHTML");
  }

  protected WebElement waitForElement() {
    return waitUntil("be ", visible, timeout);
  }

  protected void click() {
    waitForElement().click();
  }

  protected void contextClick() {
    actions().contextClick(waitForElement()).perform();
  }

  protected void hover() {
    actions().moveToElement(waitForElement()).perform();
  }

  protected void dragAndDropTo(String targetCssSelector) {
    SelenideElement target = $(targetCssSelector).shouldBe(visible);
    actions().dragAndDrop(waitForElement(), target).perform();
  }

  protected void followLink() {
    WebElement link = waitForElement();
    String href = link.getAttribute("href");
    link.click();

    // JavaScript $.click() doesn't take effect for <a href>
    if (href != null) {
      open(href);
    }
  }

  protected void setValue(String text) {
    WebElement element = waitForElement();
    if ("select".equalsIgnoreCase(element.getTagName())) {
      selectOptionByValue(element, text);
    }
    else if (text == null || text.isEmpty()) {
      element.clear();
    }
    else if (fastSetValue && JQuery.jQuery.isJQueryAvailable()) {
      String jsCodeToTriggerEvent =
          "arguments[0].value = arguments[1];" +
          "var element = jQuery(arguments[0]);" +

          "var e = jQuery.Event('keydown');  e.which = arguments[2]; element.trigger(e);" +
          "var e = jQuery.Event('keypress'); e.which = arguments[2]; element.trigger(e);" +
          "var e = jQuery.Event('keyup');    e.which = arguments[2]; element.trigger(e);";

      char lastChar = text.charAt(text.length() - 1);
      executeJavaScript(jsCodeToTriggerEvent, element, text, (int) lastChar);
      fireEvent(element, "change");
    }
    else if (fastSetValue) {
      executeJavaScript("arguments[0].value = arguments[1]", element, text);
      fireEvent(element, "change");
    }
    else {
      element.clear();
      element.sendKeys(text);
      fireEvent(element, "change");
    }
  }

  protected String getValue() {
    return getDelegate().getAttribute("value");
  }

  protected void append(String text) {
    WebElement element = waitForElement();
    element.sendKeys(text);
    fireEvent(element, "change");
  }

  protected void fireEvent(WebElement element, final String event) {
    final String jsCodeToTriggerEvent
        = "if (document.createEventObject) {\n" // IE
        "  var evt = document.createEventObject();\n" +
        "  return arguments[0].fireEvent('on' + arguments[1], evt);\n" +
        "}\n" +
        "else {\n" +
        "  var evt = document.createEvent('HTMLEvents');\n " +
        "  evt.initEvent(arguments[1], true, true );\n " +
        "  return !arguments[0].dispatchEvent(evt);\n" +
        '}';
    executeJavaScript(jsCodeToTriggerEvent, element, event);
  }

  protected Object should(Object proxy, String prefix, Condition... conditions) {
    return should(proxy, prefix, null, conditions);
  }

  protected Object should(Object proxy, String prefix, String message, Condition... conditions) {
    for (Condition condition : conditions) {
      waitUntil(prefix, message, condition, timeout);
    }
    return proxy;
  }

  protected Object shouldNot(Object proxy, String prefix, Condition... conditions) {
    return shouldNot(proxy, prefix, null, conditions);
  }

  protected Object shouldNot(Object proxy, String prefix, String message, Condition... conditions) {
    for (Condition condition : conditions) {
      waitWhile(prefix, message, condition, timeout);
    }
    return proxy;
  }

  protected File uploadFromClasspath(SelenideElement inputField, String... fileName) throws URISyntaxException, IOException {
    File[] files = new File[fileName.length];
    for (int i = 0; i < fileName.length; i++) {
      files[i] = findFileInClasspath(fileName[i]);
    }

    return uploadFile(inputField, files);
  }

  protected File findFileInClasspath(String name) throws URISyntaxException {
    URL resource = currentThread().getContextClassLoader().getResource(name);
    if (resource == null) {
      throw new IllegalArgumentException("File not found in classpath: " + name);
    }
    return new File(resource.toURI());
  }

  protected File uploadFile(SelenideElement inputField, File... file) throws IOException {
    if (file.length == 0) {
      throw new IllegalArgumentException("No files to upload");
    }

    File uploadedFile = uploadFile(inputField, file[0]);

    if (file.length > 1) {
      SelenideElement form = inputField.closest("form");
      for (int i = 1; i < file.length; i++) {
        uploadFile(cloneInputField(form, inputField), file[i]);
      }
    }
   
    return uploadedFile;
  }

  protected WebElement cloneInputField(SelenideElement form, SelenideElement inputField) {
    return executeJavaScript(
        "var fileInput = document.createElement('input');" +
            "fileInput.setAttribute('type', arguments[1].getAttribute('type'));" +
            "fileInput.setAttribute('name', arguments[1].getAttribute('name'));" +
            "fileInput.style.width = '1px';" +
            "fileInput.style.height = '1px';" +
            "arguments[0].appendChild(fileInput);" +
            "return fileInput;",
        form, inputField);
  }
 
  protected File uploadFile(WebElement inputField, File file) throws IOException {
    if (!"input".equalsIgnoreCase(inputField.getTagName())) {
      throw new IllegalArgumentException("Cannot upload file because " + Describe.describe(inputField) + " is not an INPUT");
    }

    if (!file.exists()) {
      throw new IllegalArgumentException("File not found: " + file.getAbsolutePath());
    }

    String canonicalPath = file.getCanonicalPath();
    inputField.sendKeys(canonicalPath);
    return new File(canonicalPath);
  }

  protected void selectOptionByText(WebElement selectField, String optionText) {
    $(selectField).should(exist).find(byText(optionText)).shouldBe(visible);
    new Select(selectField).selectByVisibleText(optionText);
  }

  protected void selectOptionByValue(WebElement selectField, String optionValue) {
    $(selectField).should(exist).find(byValue(optionValue)).shouldBe(visible);
    new Select(selectField).selectByValue(optionValue);
  }

  protected String getSelectedValue(WebElement selectElement) {
    WebElement option = getSelectedOption(selectElement);
    return option == null ? null : option.getAttribute("value");
  }

  protected String getSelectedText(WebElement selectElement) {
    WebElement option = getSelectedOption(selectElement);
    return option == null ? null : option.getText();
  }

  protected SelenideElement getSelectedOption(WebElement selectElement) {
    return wrap(new Select(selectElement).getFirstSelectedOption());
  }

  protected boolean exists() {
    try {
      return getActualDelegate() != null;
    } catch (WebDriverException elementNotFound) {
      if (Cleanup.of.isInvalidSelectorError(elementNotFound)) {
        throw Cleanup.of.wrap(elementNotFound);
      }
      return false;
    } catch (IndexOutOfBoundsException invalidElementIndex) {
      return false;
    }
  }

  protected boolean isDisplayed() {
    try {
      WebElement element = getActualDelegate();
      return element != null && element.isDisplayed();
    } catch (WebDriverException elementNotFound) {
      if (Cleanup.of.isInvalidSelectorError(elementNotFound)) {
        throw Cleanup.of.wrap(elementNotFound);
      }
      return false;
    } catch (IndexOutOfBoundsException invalidElementIndex) {
      return false;
    }
  }

  protected String describe() {
    try {
      return Describe.describe(getActualDelegate());
    } catch (WebDriverException elementDoesNotExist) {
      return Cleanup.of.webdriverExceptionMessage(elementDoesNotExist);
    } catch (IndexOutOfBoundsException invalidElementIndex) {
      return invalidElementIndex.toString();
    }
  }

  static Object delegateMethod(WebElement delegate, Method method, Object[] args) throws Throwable {
    try {
      return method.invoke(delegate, args);
    } catch (InvocationTargetException e) {
      throw e.getTargetException();
    }
  }

  protected WebElement waitUntil(String prefix, Condition condition, long timeoutMs) {
    return waitUntil(prefix, null, condition, timeoutMs);
  }

  protected WebElement waitUntil(String prefix, String message, Condition condition, long timeoutMs) {
    final long startTime = currentTimeMillis();
    WebElement element;
    do {
      lastError = null;
      element = tryToGetElement();
      if (element != null) {
        try {
          if (condition.apply(element)) {
            return element;
          }
        }
        catch (WebDriverException elementNotFound) {
          lastError = elementNotFound;
        }
        catch (IndexOutOfBoundsException ignore) {
          lastError = ignore;
        }
      }
      else if (condition.applyNull()) {
        if (Cleanup.of.isInvalidSelectorError(lastError)) {
          throw Cleanup.of.wrap(lastError);
        }
        return null;
      }
      sleep(pollingInterval);
    }
    while (currentTimeMillis() - startTime <= timeoutMs);

    if (Cleanup.of.isInvalidSelectorError(lastError)) {
      throw Cleanup.of.wrap(lastError);
    }
    else if (!exists(element)) {
      return throwElementNotFound(condition, timeoutMs);
    }
    else {
      throw new ElementShould(getSearchCriteria(), prefix, message, condition, element, lastError, timeoutMs);
    }
  }

  protected WebElement throwElementNotFound(Condition condition, long timeoutMs) {
    throw new ElementNotFound(getSearchCriteria(), condition, lastError, timeoutMs);
  }

  protected void waitWhile(String prefix, Condition condition, long timeoutMs) {
    waitWhile(prefix, null, condition, timeoutMs);
  }
  protected void waitWhile(String prefix, String message, Condition condition, long timeoutMs) {
    final long startTime = currentTimeMillis();
    WebElement element;
    do {
      lastError = null;
      element = tryToGetElement();
      if (element != null) {
        try {
          if (!condition.apply(element)) {
            return;
          }
        }
        catch (WebDriverException elementNotFound) {
          lastError = elementNotFound;
        }
        catch (IndexOutOfBoundsException ignore) {
          lastError = ignore;
        }
      }
      else if (!condition.applyNull()) {
        if (Cleanup.of.isInvalidSelectorError(lastError)) {
          throw Cleanup.of.wrap(lastError);
        }
        return;
      }
      sleep(pollingInterval);
    }
    while (currentTimeMillis() - startTime <= timeoutMs);

    if (Cleanup.of.isInvalidSelectorError(lastError)) {
      throw Cleanup.of.wrap(lastError);
    }
    else if (!exists(element)) {
      throwElementNotFound(not(condition), timeoutMs);
    }
    else {
      throw new ElementShouldNot(getSearchCriteria(), prefix, message, condition, element, lastError, timeoutMs);
    }
  }

  protected boolean exists(WebElement element) {
    try {
      if (element == null) return false;
      element.isDisplayed();
      return true;
    } catch (WebDriverException elementNotFound) {
      return false;
    }
  }

  protected WebElement tryToGetElement() {
    try {
      return getActualDelegate();
    } catch (WebDriverException elementNotFound) {
      lastError = elementNotFound;
      return null;
    } catch (IndexOutOfBoundsException ignore) {
      lastError = ignore;
      return null;
    } catch (RuntimeException e) {
      throw Cleanup.of.wrap(e);
    }
  }

  protected SelenideElement find(SelenideElement proxy, Object arg, int index) {
    return WaitingSelenideElement.wrap(proxy, getSelector(arg), index);
  }

  protected By getSelector(Object arg) {
    return arg instanceof By ? (By) arg : By.cssSelector((String) arg);
  }

  protected SelenideElement parent(SelenideElement me) {
    return find(me, By.xpath(".."), 0);
  }

  protected SelenideElement closest(SelenideElement me, String tagOrClass) {
    return tagOrClass.startsWith(".") ?
        find(me, By.xpath("ancestor::*[@class='" + tagOrClass.replaceFirst("\\.", "")+ "']"), 0) :
        find(me, By.xpath("ancestor::" + tagOrClass), 0);
  }

  protected void scrollTo() {
    Point location = getDelegate().getLocation();
    executeJavaScript("window.scrollTo(" + location.getX() + ", " + location.getY() + ')');
  }

  protected File download() throws IOException, URISyntaxException {
    return FileDownloader.instance.download(getDelegate());
  }
}
TOP

Related Classes of com.codeborne.selenide.impl.AbstractSelenideElement

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.