javascript - 从 Java Selenium 执行 JavaScript 库和函数

标签 javascript java selenium selenium-webdriver

我在 Eclipse 中编写 Java GUI/脚本,运行 headless chromedriver,并且在尝试加载 html2canvas.js [1] 时遇到问题。 [2] 驱动程序中的库,然后在浏览器中调用我在该库上编写的函数;我在使用此代码时遇到未定义的错误:

String ss1ScriptLoc = "C:\\Users\\me\\Desktop\\resources\\html2canvas.min.js";
String ss2ScriptLoc = "C:\\Users\\me\\Desktop\\resources\\takeScreenShot.js";

je.executeScript(
        "var headID1 = document.getElementsByTagName('head')[0]; "
        + "var newScript1 = document.createElement('script'); "
        + "newScript1.type = 'text/javascript'; "
        + "newScript1.src = '" + ss1ScriptLoc + "'; "
        + "headID1.appendChild(newScript1); "
        + "var headID2 = document.getElementsByTagName('head')[0]; "
        + "var newScript2 = document.createElement('script'); "
        + "newScript2.type = 'text/javascript'; "
        + "newScript2.src = '" + ss2ScriptLoc + "'; "
        + "headID2.appendChild(newScript2); "
        + "$(document).ready( function () { takeScreenShot(); });"
    );

这会因未定义函数“takeScreenShot();”而导致错误我认为我已经在本地 .js 文件中定义了它。

Starting ChromeDriver 75.0.3770.140 (-refs/branch-heads/3770@{#1155}) on port 48415
Only local connections are allowed.
Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
Aug 05, 2019 9:36:53 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
java.util.concurrent.ExecutionException: org.openqa.selenium.JavascriptException: javascript error: takeScreenShot is not defined
  (Session info: headless chrome=75.0.3770.142)
Caused by: org.openqa.selenium.JavascriptException: javascript error: takeScreenShot is not defined
  (Session info: headless chrome=75.0.3770.142)
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:25:48'
System info: host: '', ip: '', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_191'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 75.0.3770.142, chrome: {chromedriverVersion: 75.0.3770.140 (2d9f97485c7b..., userDataDir: C:\Users\me\AppData\Lo...}, goog:chromeOptions: {debuggerAddress: localhost:55906}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: XP, platformName: XP, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
Session ID: 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
    at org.openqa.selenium.remote.RemoteWebDriver.executeScript(RemoteWebDriver.java:489)
    at App.getScreenShot(App.java:170)
    at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at javax.swing.SwingWorker.run(SwingWorker.java:334)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
<小时/>

edit1:添加了此代码片段,经过测试,有效,但似乎没有实际执行任何操作。

je.executeScript("");
je.executeScript("document.body.onload = myCustomFunc();"
    + "function myCustomFunc() { console.log('hello world'); }"
);

我获取了两个库 .js 文件并将它们读入 List,然后制作了一个大 StringBuilder,将所有元素附加到 StringBuilder,然后添加 takeScreenShot() 函数代替 myCustomFunc()。不会抛出任何错误,但也不会生成下载的屏幕截图文件。

<小时/>

edit2:我的加载函数

private String fileToJSString(final String inScriptFile) {
        Path p = Paths.get(inScriptFile);
        if (!Files.exists(p)) {
            System.err.println("fileToJSString : error, file does not exist");
            return null;
        }
        List<String> lines = null;
        try {
            lines = Files.readAllLines(Paths.get(inScriptFile));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (lines == null) {
            System.err.println("fileToJSString : error, no lines read from file");
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (String s : lines)
            sb.append(s.trim() + " ");
        return sb.toString();
    }
<小时/>

edit3:根据 @jay-mattinson 的建议,我尝试加载脚本,但是运行时字符串变量不适用于 html2canvas.js 库(太多特殊字符 - 请参阅本文前面/上面实际文件的链接)

String ss1ScriptLoc = "C:\\Users\\me\\Desktop\\resources\\html2canvas.min.js";
String ss2ScriptLoc = "C:\\Users\\me\\Desktop\\resources\\takeScreenShot.js";
String jsScript1 = fileToJSString(ss1ScriptLoc);
String jsScript2 = fileToJSString(ss2ScriptLoc);
JavascriptExecutor je = (JavascriptExecutor) this.driver;
je.executeScript(
    "var headID = document.getElementsByTagName('head')[0]; "
    + "var newScript = document.createElement('script'); "
    + "newScript.type = 'text/javascript'; "
    + "var code = {" + jsScript1 + " " + jsScript2 + "};"
    + "newScript.appendChild(document.createTextNode(code));"
    + "headID.appendChild(newScript); "
    + "$(document).ready( function () { takeScreenShot(); });"
);

运行时抛出的特定错误;

Caused by: org.openqa.selenium.WebDriverException: unknown error: Runtime.evaluate threw exception: SyntaxError: Unexpected token !
<小时/>

edit4:这是我编写的基于 html2canvas 的函数,用于抓取网页上表格的图像;

function takeScreenShot() {
    if (document.getElementsByClassName("abc-top") == null) {
        console.log('not on the right web page with the right content. stopping script');
        return;
    }

    var hiddenLinkObj = document.createElement('a');
    hiddenLinkObj.setAttribute('href', '');
    hiddenLinkObj.setAttribute('id', '');
    document.body.insertBefore(hiddenLinkObj, document.body.childNodes[0]);

    var s1 = window.location.href;
    var idx = s1.lastIndexOf('/');
    var res = s1.substring(idx + 1, s1.length);
    hiddenLinkObj.setAttribute('download', 's' + res + '-s.png');

    var partA = document.querySelector('[abc-show="showInfo"]');
    var partB = partA.getElementsByClassName('row');
    var partC = partB[3].childNodes[0];
    partC.setAttribute('style', 'background-color:#fafafa');
    var result = partC;

    html2canvas(
        result, {
            onrendered: function(canvas) {
                var myImage = canvas.toDataURL("image/png");
                hiddenLinkObj.setAttribute('href', myImage.replace("image/png", "image/octet-stream"));
                hiddenLinkObj.click();
            }
        }
    );
}
<小时/>

所以我的问题/问题:为什么在 takeScreenShot.js 文件中定义和加载它时会出现未定义的函数错误? - 如何加载一个合适大小的 html2canvas JS 库和一个包含我基于 html2canvas 库编写的单个 JS 函数的第二个/短库并在 selenium 中执行我的函数? -

我猜这是因为我缺乏 JavaScript 知识,并且我错过了一个明显的错误。感谢任何和所有帮助。

最佳答案

这是我使用 Selenium 执行/注入(inject)本地存储的“.js”文件的方法:

  File newJSFile = new File(path_to_local_js_file);
        if (newJSFile.exists())
        {
            try
            {
                  Scanner sc = new Scanner(new FileInputStream(newJSFile));
        String js_TxtFile = ""; 
            while (sc.hasNext()) {          
                String[] s = sc.next().split("\r\n");   
                for (int i = 0; i < s.length; i++) {
                    js_TxtFile += s[i];
                    js_TxtFile += " ";
                }   

            }
              try
                {
                ((JavascriptExecutor)driver).executeScript(js_TxtFile);
                }
                catch (Exception ex)
                {
                     System.out.println ("Exception when running Javascript: " + ex.toString());
                }

            }
            catch (Exception ex)
            {
            System.out.println(ex.toString());
            }
        }

关于javascript - 从 Java Selenium 执行 JavaScript 库和函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57363693/

相关文章:

javascript - IE 的 jquery 问题....在 Firefox n chrome 中工作正常

java - Java 中的正弦波声音发生器

Java JUnit 5 注释差异

javascript - ASP MVC css/js bundle : length & name of bundle parameter "?v=1234567890"

javascript - 从 AJAX 加载 div 内容后运行 JS

java - Selenium - 不一致的 StaleElementReference 错误

ruby - 瓦蒂尔爬行者在后藤之后被卡住

Python Selenium Geckodriver 连接被拒绝

javascript - 如何为库设置 TypeScript 编译器,以便 Webpack 在依赖项目中切断未使用的模块?

java - 如何在Hibernate中定义非生成的主键字段