有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在使用seleniumwebdriver运行测试时访问远程计算机剪贴板上的数据

我有如下设置:

Machine 1 - Ubuntu - selenium hub
Machine 2 - Ubuntu - selenium node
Machine 3 - Windows 8.1 - selenium node

为了执行测试,我使用RemoteWebDriver并在hub上配置Jenkins CI

问题:我正在测试的URL有一个按钮,单击该按钮可将数据复制到剪贴板除非粘贴,否则最终用户看不到数据我关心的是,在本地运行时,我能够使用以下方法获取系统剪贴板数据:

strScript = (String) Toolkit.getDefaultToolkit().getSystemClipboard()
        .getData(DataFlavor.stringFlavor);

但在远程机器上从jenkins触发代码时,我无法获取内容并收到以下错误:

java.awt.HeadlessException: 
No X11 DISPLAY variable was set, but this program performed an operation which requires it.

很明显,它正试图在jenkins服务器上获取数据,但存在某些显示问题。但我的要求是在点击按钮后获取存储在远程机器上的数据

有什么解决办法吗

谢谢


共 (1) 个答案

  1. # 1 楼答案

    如果Selenium网格环境在您的控制之下,并且您拥有设置节点的特权,那么下面将介绍如何构建它

    • 构建一个自定义节点servlet,调用该servlet时将返回剪贴板的内容
    • 使用这个新构建的自定义servlet启动节点
    • 使用诸如Talk2Grid之类的库查找会话路由到的节点的IP和端口
    • 使用获取的IP和端口调用自定义servlet以访问剪贴板

    下面的示例应该解释所有这一切(我使用的是selenium 3.141.59)

    正在使用的依赖项

    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>3.141.59</version>
    </dependency>
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-server</artifactId>
      <version>3.141.59</version>
    </dependency>
    <dependency>
      <groupId>com.rationaleemotions</groupId>
      <artifactId>talk2grid</artifactId>
      <version>1.2.1</version>
    </dependency>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>7.0.0</version>
    </dependency>
    

    自定义servlet如下所示

    package com.rationaleemotions.servlets;
    
    import java.awt.Toolkit;
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.UnsupportedFlavorException;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.openqa.selenium.json.Json;
    
    public class ClipboardServlet extends HttpServlet {
    
      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(200);
        try {
          String text = Toolkit.getDefaultToolkit().getSystemClipboard()
              .getData(DataFlavor.stringFlavor)
              .toString();
          Map<String, String> map = new HashMap<>();
          map.put("contents", text);
          response.getWriter().append(new Json().toJson(map));
        } catch (UnsupportedFlavorException e) {
          e.printStackTrace();
        }
      }
    }
    

    这里让我们假设我们的servlet属于名为“servlets.jar”的jar。 以下是如何启动节点

    java -cp servlets:selenium-server-standalone-3.141.59.jar org.openqa.grid.selenium.GridLauncherV3 -role node -servlets com.rationaleemotions.servlets.ClipboardServlet
    

    使用命令启动集线器

    java -jar selenium-server-standalone-3.141.59.jar -role hub
    

    这是一个将使用所有这些的示例

    package com.rationaleemotions;
    
    import com.rationaleemotions.pojos.Host;
    import java.io.File;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    import okhttp3.Call;
    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    import okhttp3.Response;
    import org.apache.commons.io.FileUtils;
    import org.openqa.selenium.By;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.json.Json;
    import org.openqa.selenium.remote.DesiredCapabilities;
    import org.openqa.selenium.remote.RemoteWebDriver;
    import org.testng.Assert;
    import org.testng.annotations.AfterClass;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.Test;
    
    public class ClipboardSample {
    
      private RemoteWebDriver driver;
    
      @BeforeClass
      public void beforeClass() throws MalformedURLException {
        driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"),
            DesiredCapabilities.chrome());
      }
    
      @Test
      public void demo() throws Exception {
        String text = "Mussum ipsum cacilds, vidis litro abertis. Consetis adipiscings elitis. Pra lá , depois divoltis porris, paradis. Paisis, filhis, espiritis santis. Mé faiz elementum girarzis, nisi eros vermeio, in elementis mé pra quem é amistosis quis leo. Manduma pindureta quium dia nois paga.";
        driver.navigate().to("https://googlechrome.github.io/samples/async-clipboard/");
    
        driver.findElement(By.cssSelector("textarea#out")).sendKeys(text);
        TimeUnit.SECONDS.sleep(1);
        takeScreenshot();
        driver.findElement(By.cssSelector("button#copy")).click();
        TimeUnit.SECONDS.sleep(1);
        Host grid = new Host("localhost", "4444");
        Host node = new GridApiAssistant(grid)
            .getNodeDetailsForSession(driver.getSessionId().toString());
        String url = String
            .format("http://%s:%d/extra/ClipboardServlet", node.getIpAddress(), node.getPort());
        Request request = new Request.Builder().url(url).build();
    
        Call call = new OkHttpClient.Builder().build().newCall(request);
        Response response = call.execute();
        String localClipboardData = response.body().string();
        Map<String, String> data = new Json().toType(localClipboardData, Map.class);
        Assert.assertEquals(text, data.get("contents"));
      }
    
      private void takeScreenshot() throws IOException {
        File src = driver.getScreenshotAs(OutputType.FILE);
        File target = new File(
            System.getProperty("user.dir") + File.separator + "target" + File.separator +
                "screenshot.jpg");
        FileUtils.copyFile(src, target);
      }
    
      @AfterClass
      public void afterClass() {
        if (driver != null) {
          driver.quit();
        }
      }
    }