All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openqa.selenium.SeleneseCommandExecutor Maven / Gradle / Ivy

There is a newer version: 4.19.1
Show newest version
/*
Copyright 2007-2009 WebDriver committers
Copyright 2007-2009 Google Inc.

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 org.openqa.selenium;

import static org.openqa.selenium.remote.DriverCommand.CLEAR_ELEMENT;
import static org.openqa.selenium.remote.DriverCommand.CLICK_ELEMENT;
import static org.openqa.selenium.remote.DriverCommand.CLOSE;
import static org.openqa.selenium.remote.DriverCommand.EXECUTE_ASYNC_SCRIPT;
import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT;
import static org.openqa.selenium.remote.DriverCommand.FIND_CHILD_ELEMENT;
import static org.openqa.selenium.remote.DriverCommand.FIND_CHILD_ELEMENTS;
import static org.openqa.selenium.remote.DriverCommand.FIND_ELEMENT;
import static org.openqa.selenium.remote.DriverCommand.FIND_ELEMENTS;
import static org.openqa.selenium.remote.DriverCommand.GET;
import static org.openqa.selenium.remote.DriverCommand.GET_ACTIVE_ELEMENT;
import static org.openqa.selenium.remote.DriverCommand.GET_CURRENT_URL;
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_ATTRIBUTE;
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_SIZE;
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_TAG_NAME;
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_TEXT;
import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_VALUE;
import static org.openqa.selenium.remote.DriverCommand.GET_PAGE_SOURCE;
import static org.openqa.selenium.remote.DriverCommand.GET_TITLE;
import static org.openqa.selenium.remote.DriverCommand.IMPLICITLY_WAIT;
import static org.openqa.selenium.remote.DriverCommand.IS_ELEMENT_DISPLAYED;
import static org.openqa.selenium.remote.DriverCommand.IS_ELEMENT_ENABLED;
import static org.openqa.selenium.remote.DriverCommand.IS_ELEMENT_SELECTED;
import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION;
import static org.openqa.selenium.remote.DriverCommand.QUIT;
import static org.openqa.selenium.remote.DriverCommand.SCREENSHOT;
import static org.openqa.selenium.remote.DriverCommand.SEND_KEYS_TO_ELEMENT;
import static org.openqa.selenium.remote.DriverCommand.SET_SCRIPT_TIMEOUT;
import static org.openqa.selenium.remote.DriverCommand.SUBMIT_ELEMENT;
import static org.openqa.selenium.remote.DriverCommand.SWITCH_TO_FRAME;

import com.google.common.collect.Maps;

import com.thoughtworks.selenium.CommandProcessor;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.HttpCommandProcessor;
import com.thoughtworks.selenium.Selenium;
import com.thoughtworks.selenium.SeleniumException;

import org.openqa.selenium.internal.selenesedriver.ClearElement;
import org.openqa.selenium.internal.selenesedriver.ClickElement;
import org.openqa.selenium.internal.selenesedriver.Close;
import org.openqa.selenium.internal.selenesedriver.ExecuteAsyncScript;
import org.openqa.selenium.internal.selenesedriver.ExecuteScript;
import org.openqa.selenium.internal.selenesedriver.FindElement;
import org.openqa.selenium.internal.selenesedriver.FindElements;
import org.openqa.selenium.internal.selenesedriver.GetActiveElement;
import org.openqa.selenium.internal.selenesedriver.GetCurrentUrl;
import org.openqa.selenium.internal.selenesedriver.GetElementAttribute;
import org.openqa.selenium.internal.selenesedriver.GetElementText;
import org.openqa.selenium.internal.selenesedriver.GetElementValue;
import org.openqa.selenium.internal.selenesedriver.GetPageSource;
import org.openqa.selenium.internal.selenesedriver.GetSize;
import org.openqa.selenium.internal.selenesedriver.GetTagName;
import org.openqa.selenium.internal.selenesedriver.GetTitle;
import org.openqa.selenium.internal.selenesedriver.GetUrl;
import org.openqa.selenium.internal.selenesedriver.IsElementDisplayed;
import org.openqa.selenium.internal.selenesedriver.IsElementEnabled;
import org.openqa.selenium.internal.selenesedriver.IsElementSelected;
import org.openqa.selenium.internal.selenesedriver.NewSession;
import org.openqa.selenium.internal.selenesedriver.QuitSelenium;
import org.openqa.selenium.internal.selenesedriver.SeleneseFunction;
import org.openqa.selenium.internal.selenesedriver.SendKeys;
import org.openqa.selenium.internal.selenesedriver.SubmitElement;
import org.openqa.selenium.internal.selenesedriver.SwitchToFrame;
import org.openqa.selenium.internal.selenesedriver.TakeScreenshot;
import org.openqa.selenium.remote.BeanToJsonConverter;
import org.openqa.selenium.remote.Command;
import org.openqa.selenium.remote.CommandExecutor;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.ErrorCodes;
import org.openqa.selenium.remote.JsonToBeanConverter;
import org.openqa.selenium.remote.Response;

import java.io.File;
import java.net.URL;
import java.util.Map;

public class SeleneseCommandExecutor implements CommandExecutor {
  private final ErrorCodes errorCodes;
  private final Selenium instance;
  private Map functions = Maps.newHashMap();

  public SeleneseCommandExecutor(URL seleniumServer, URL remoteAddress, Capabilities capabilities) {
    this(new HttpCommandProcessor(
        seleniumServer.getHost(), seleniumServer.getPort(),
        startCommand(capabilities), remoteAddress.toString()));
  }

  public SeleneseCommandExecutor(CommandProcessor processor) {
    this(new DefaultSelenium(processor));
  }

  public SeleneseCommandExecutor(Selenium instance) {
    this.instance = instance;
    errorCodes = new ErrorCodes();

    prepareCommands();
  }

  public Selenium getWrappedSelenium() {
    return instance;
  }

  public Response execute(Command command) {
    SeleneseFunction function = functions.get(command.getName());
    if (function == null) {
      throw new UnsupportedOperationException("cannot execute: " + command.getName());
    }

    try {
      Response response = new Response();
      response.setValue(function.apply(instance, command.getParameters()));
      return response;
    } catch (Exception e) {
      return prepareExceptionResponse(e);
    }
  }

  private Response prepareExceptionResponse(Exception e) {
    Response response = new Response();

    Exception toUse = e;
    if (e instanceof SeleniumException) {
      // World of fragility. *sigh*
      if (e.getMessage().matches("ERROR: (Threw an exception: )?Element .+ not found")) {
        toUse = new StaleElementReferenceException(e.getMessage(), e);
      }
    }
    response.setStatus(errorCodes.toStatusCode(toUse));

    // It's like a lesson in inefficiency
    Object raw =
        new JsonToBeanConverter().convert(Map.class, new BeanToJsonConverter().convert(toUse));
    response.setValue(raw);
    return response;
  }

  public void addCommand(String methodName, SeleneseFunction command) {
    functions.put(methodName, command);
  }

  private void prepareCommands() {
    FindElement findElement = new FindElement();
    FindElements findElements = new FindElements();
    SelenseTimeouts timeouts = new SelenseTimeouts(
        findElement.implicitlyWait(), findElements.implicitlyWait());
    ExecuteAsyncScript executeAsyncScript = new ExecuteAsyncScript();

    addCommand(CLEAR_ELEMENT, new ClearElement());
    addCommand(CLICK_ELEMENT, new ClickElement());
    addCommand(CLOSE, new Close());
    addCommand(GET_CURRENT_URL, new GetCurrentUrl());
    addCommand(EXECUTE_SCRIPT, new ExecuteScript());
    addCommand(EXECUTE_ASYNC_SCRIPT, executeAsyncScript);
    addCommand(SET_SCRIPT_TIMEOUT, executeAsyncScript.setScriptTimeout());
    addCommand(FIND_CHILD_ELEMENT, findElement);
    addCommand(FIND_CHILD_ELEMENTS, findElements);
    addCommand(FIND_ELEMENT, findElement);
    addCommand(FIND_ELEMENTS, findElements);
    addCommand(IMPLICITLY_WAIT, timeouts);
    addCommand(GET, new GetUrl());
    addCommand(GET_ACTIVE_ELEMENT, new GetActiveElement());
    addCommand(GET_ELEMENT_ATTRIBUTE, new GetElementAttribute());
    addCommand(GET_ELEMENT_SIZE, new GetSize());
    addCommand(GET_ELEMENT_TEXT, new GetElementText());
    addCommand(GET_ELEMENT_VALUE, new GetElementValue());
    addCommand(GET_ELEMENT_TAG_NAME, new GetTagName());
    addCommand(GET_TITLE, new GetTitle());
    addCommand(IS_ELEMENT_DISPLAYED, new IsElementDisplayed());
    addCommand(IS_ELEMENT_ENABLED, new IsElementEnabled());
    addCommand(IS_ELEMENT_SELECTED, new IsElementSelected());
    addCommand(NEW_SESSION, new NewSession());
    addCommand(GET_PAGE_SOURCE, new GetPageSource());
    addCommand(SCREENSHOT, new TakeScreenshot());
    addCommand(SEND_KEYS_TO_ELEMENT, new SendKeys());
    addCommand(SWITCH_TO_FRAME, new SwitchToFrame());
    addCommand(SUBMIT_ELEMENT, new SubmitElement());
    addCommand(QUIT, new QuitSelenium());
  }

  private static String startCommand(Capabilities capabilities) {
    String browser = capabilities.getBrowserName();
    if (DesiredCapabilities.firefox().getBrowserName().equals(browser)) {
      return "*chrome";
    } else if ("safari".equals(browser)) {
      String path = findSafari();
      return "*safari " + path;
    } else if (DesiredCapabilities.chrome().getBrowserName().equals(browser)) {

      return "*googlechrome /Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
    }

    throw new IllegalArgumentException(
        "Cannot determine which selenium type to use: " + capabilities.getBrowserName());
  }

  private static String findSafari() {
    if (Platform.getCurrent().is(Platform.WINDOWS)) {
      File[] locations = new File[] {
          new File("C:\\Program Files (x86)\\Safari\\safari.exe"),
          new File("C:\\Program Files\\Safari\\safari.exe")
      };

      for (File location : locations) {
        if (location.exists()) {
          return location.getAbsolutePath();
        }
      }
    }

    return "";
  }

  private class SelenseTimeouts implements SeleneseFunction {
    private final SeleneseFunction[] functions;

    public SelenseTimeouts(SeleneseFunction... functions) {
      this.functions = functions;
    }

    public Void apply(Selenium selenium, Map args) {
      for (SeleneseFunction function : functions) {
        function.apply(selenium, args);
      }

      return null;
    }
  }
}