当我的Javascript回调(以Selenium制造)返回时,写入Java控制台 [英] write to Java console when my Javascript callback (made in Selenium) returns

查看:112
本文介绍了当我的Javascript回调(以Selenium制造)返回时,写入Java控制台的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经学习了如何创建Javascript回调函数,并且对函数式编程有基本的了解,因为这似乎很容易。但是,我是javascript新手,它是语法,在IntelliJ IDE中找不到测试所说语法的好方法。

I have learned how to create Javascript callback functions and I have a basic understanding of 'functional programming' since it seems easy enough. I am however, new to javascript and it's syntax and I can't find a good way to test said syntax while in my IntelliJ IDE.

我正在创建一个基于Selenium的工具来单击一个webelement,等待它重新加载页面,变旧或等待超时。我这样做的原因是将Webelements分为三类:导致页面重新加载,变得过时,不变。为此,我使用Java随附的JavascriptExecutor制作了一个简单的javascript脚本。我的大部分代码都是用Java编写的,这是我精通的语言。我想学习如何将javascript与Java结合使用来完成我要处理的网页。

I'm creating a Selenium based tool to click on a webelement, wait for it to reload the page, become stale or wait for a timeout. The reason I'm doing this is to classify webelements into three categories: causes a page reload, becomes stale, doesn't change. To do this I've made a simple javascript script with the JavascriptExecutor that comes with Java. Most of my code is in java and that is the language I am proficient in. I want to learn how to use javascript with java to do the things I want with web pages.

我有一个JavaScript回调函数:

I have a javascript callback function:

function test(callback) {callback();} 
function Return() {SeleniumTest.isPageReloaded.JavascriptWorking} 
window.addEventListener('onload', test(Return));

在JavaScript执行器中执行,如下所示:

which is executed inside a Javascript Executor like so:

System.setProperty("webdriver.chrome.driver", 
"C:\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
String script = "function test(callback) {callback();}" +
                    "function Return()" + 
                    "{SeleniumTest.isPageReloaded.JavascriptWorking}" +
                    "window.addEventListener('onload', test(Return));";
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(script);

基本上是以前的Javascript脚本,以String的形式执行。如您所见,我正在尝试调用Java类。 SeleniumTest是我的包,isPageReloaded是当前类,而JavascriptWorking是该类中的静态方法。该静态方法如下所示:

Which is basically the Javascript script from before, executing as a String. As you can see I am attempting to call a java class. SeleniumTest is my package, isPageReloaded is the current class and JavascriptWorking is a static method within that class. That static method looks like this:

public static void JavascriptWorking(){
    System.out.println("Javascript ran here");
}

这是从javascript到Java代码的简单方法。之所以尝试这种方式,是因为我阅读了以下内容:

Its meant to be a simple way to get something from the javascript to my java code. The reason I tried it this way is because I read this:

https://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/bpm-appdev/ invoking-java-methods-in-javascript.html

但是后来我意识到这是行不通的,因此我进行了更深入的研究。我读到Javascript和Java被服务器和客户端分开了,我从这个问题中获得了一些见识:

But then I realized that it wouldn't work and I dug deeper. I read that Javascript and Java are seperated by server and client and I gained some insight from this question:

在javascript代码中调用Java方法

但是自从Javascript以来,我不是100%肯定对我的情况是正确的我执行的不是来自正在测试的网页,而是我自己在Java代码中将其作为String放入了。另外,对于该问题的答案是否确实适用于我,我仍然感到非常困惑。只有一个,它基本上只是说:安装一些东西,因为Java是客户端,而javascript是服务器端。我(有点)理解这些术语的含义,但是我不确定我在课堂上制作的javascript是否会被视为服务器端,事实上,事实并非如此。我需要澄清的是A:我在Java代码中运行/创建的JavaScript实际上是在服务器端吗?
B:如果是,那么有人可以给我一个基本的清单,以了解如何从服务器调用Java代码吗?这需要权限吗?我假设我必须与所述服务器进行通信,这是否意味着我使用GET和POSt请求?
C:如果Javascript不是服务器端,那么它一定是客户端,我应该可以很容易地调用它,对吗?我该怎么做?

However I'm not 100% sure this is accurate to my case since the Javascript I'm executing isn't coming from the webpage I'm testing, Rather I made it myself inside the java code as a String. Additionally I'm still highly confused on if the answer to that question actually applies to me. There is only one and it basically just says, 'install some stuff because java is clientside and javascript is serverside'. I (kindof) understand what those terms mean but I'm not sure that the javascript I made in my class would be considered 'server-side' in fact it would seem to not be that way. What I need is clarification on A: is the javascript I'm running/creating in my java code actually serverside? B: if yes then can someone give me a basic rundown on how I would go about calling java code from the server? does this require permissions? I assume I have to communicate with said server so does that mean I use GET and POSt requests? C: If the Javascript Isn't server side then it must be clientside and I should be able to call it pretty easily right? How do I do this?

我希望能够运行:

System.setProperty("webdriver.chrome.driver", 
"C:\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
String script = "function test(callback) {callback();}" +
                    "function Return()" + 
"{//insert callback code here}" +
                    "window.addEventListener('onload', test(Return));";
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(script);

并运行静态Java方法,打印到控制台的内容或将javascript代码链接到javacode。因此,例如,如果我插入了正确的代码来调用我的静态方法:

and get either a static java method ran, something printed to console, or some other means that links the javascript code to the javacode. So for example if I inserted the correct code to call my static method:

SeleniumTest.IsPageReloaded.JavascriptWorking

SeleniumTest.IsPageReloaded.JavascriptWorking

(看起来又像):

public static void JavascriptWorking(){
    System.out.println("Javascript ran here");
}

然后我想看到 Javascript跑到这里在我的Java控制台上。所使用的驱动程序是swapbale,我首先使用chrome是因为它速度很快。所需的全部是一个封闭的主类,并且它(可以)是可运行的,但没有承诺。

Then I'd want to see "Javascript ran here" on my java console. The driver being used is interchangebale, I just used chrome first because its fast. All that this needs is an enclosing main class and It ((should)) be runnable but no promises.

目的是在Java中获得一些东西,然后将其用作标志我知道我的异步javascript是用Java完成的,因此我可以继续执行程序。我可以得到异步javascript部分,并且我理解它,我只需要一个链接即可返回我的Java代码。

The purpose is to get something in java that I can then use as a flag to know that my asynchronous javascript is done in java and I can continue on with program execution. I can get the async javascript part and I understand it, I just need a link back to my java code.

我已经有人告诉您,为Java代码提供标记的常见方法是在页面上使用javascript创建一个特定的webelement,然后在Java中对其进行测试(因此提供了链接)。我不想添加到要测试的网页,因为我想测试它们而不实际编辑/更改它们。我通常对其他简单的解决方案持开放态度,但是我需要做的最大的事情是在整个客户端服务器端问题上进行澄清,因为它特定于我的设置(Selenium java-> javascript-> java),其中大多数问题仅涉及(javascript->

I've been told that the common way to provide a flag for your java code is to create a certain webelement on the page with javascript and test for it in java (hence the link). I don't feel like adding to the webpages I test because I want to test them without actually editing/changing them. I'm generally open to other simple solutions but the biggest thing I need is clarification on the whole clientside serverside issue because its specific to my setup (Selenium java -> javascript -> java) where most questions only cover (javascript -> java) or vice versa.

推荐答案

您提到的有关JS调用Java的链接是针对特定应用程序的,这意味着去做。并不是说这是不可能的(我基于类似原理编写了FF插件),但是在这种情况下不适用。它还需要特殊的应用程序支持(默认情况下,在浏览器中执行的Javascript被大量沙盒化-它无法访问其自身范围之外的任何内容。自行调用其他应用程序是一个大难题。)

The link you mentioned about JS invoking Java is for a specific application, that is meant to do that. Not saying it is impossible (I wrote FF plugins based on similar principle), but it is not applicable in this case. It also requires special application support (by default Javascript executed in browser is heavily sandboxed - it can't access anything out of its own scope. Invoking other apps on its own is a big no.).

您要注入的脚本始终是客户端,它们仅在浏览器中执行,与Java代码本身隔离。话虽如此,但没有什么是不可能的。

The scripts you are injecting are always client side, they are executed only in the browser, that is isolated from the java code itself. With that said nothing is impossible.

想提一下Selenium库的两个有趣的功能,它们对您来说很方便。

Would like to mention two interesting features of the Selenium library that can come handy for you.


  1. 您多次提到一个魔术术语异步Javascript执行-正如我所看到的,您正在实现自己的 executeAsyncScript 。 Webdriver确实提供了这种方法,非常适合您要与之一起使用的目的。

  1. You mention a magic term many times "async Javascript execution" - and as I can see you are implementing your own version of executeAsyncScript. Webdriver does provide this method out of the box, pretty much for the purpose you want to use it with.

当您使用 executeScript ,一旦完成,它将立即返回-在您的情况下,它将仅向您的侦听器注入代码,然后返回。使用 executeAsyncScript 您可以获取回调-就是您正在做的事情。调用 executeAsyncScript 时,默认的 callback 方法将作为最后一个参数添加到您的代码中,需要由

When you use executeScript, it will return pretty much immediately once it finished - in your case it will just inject your listener with your code, and then it returns. Using executeAsyncScript you can get a callback - just what you are doing. When calling executeAsyncScript, a default callback method is added to your code as the last argument, that needs to be called by your JS code for the method to return.

一个简单的示例:

String script = "var callback = arguments[arguments.length - 1];" + //the last argument is the callback function
                "var classToCall = 'SeleniumTest.IsPageReloaded';" +  //the classname you want to return to call from Java in case of success)
                "window.addEventListener('onload', callback(classToCall));"; 
//you can give any supported return value to the callback function. Here I assume that you want to call a static method. This is the class name that can be used later.
try {
    JavascriptExecutor js = (JavascriptExecutor)driver;
    //classToCall has the value we passed to the callback function
    String classToCall = js.executeAsyncScript(script);
} catch (ScriptTimeoutException e) {
    System.err.println("Uhhh... this failed I guess");
    e.printStackTrace();
}

executeAsyncScript在调用回调之前不会返回-为避免无限死机,您可以设置 WebDriver.Timeouts.setScriptTimeout 属性进行控制。如果脚本花费的时间更长,则JavascriptExecutor将引发异常。返回后,您可以实例化返回的类,并打印为

The executeAsyncScript does not return until the callback is called - to avoid infinite hangs, you can set the WebDriver.Timeouts.setScriptTimeout property to control this. If the script takes longer, JavascriptExecutor will throw an exception. Once returned, you can instantiate the returned class, and print like

Class clazz = Class.forName(classToCall); //it is only necessary if the classname is dynamic. If it is the same always, you can just go ahead with that.
((IsPageReloaded)clazz.newInstance()).JavascriptWorking();

当然,您也可以从JS返回更复杂的数据结构,并在其中指定方法名称,但是在这里使用反射确实是题外话。

Of course you can return a more complex datastructure also from the JS where you specify the method name also, but using reflection is really offtopic here.


  1. 看看 EventFiringWebdriver 。这是一个有用的类,它利用 WebDriverEventListener 创建具有许多事件的钩子的自定义Webdriver包装器,允许您在单击之前/之后,页面加载之前/之后执行自定义代码。 ...和其他一些更重要的是,在网络驱动程序中执行JavaScript之前/之后。您可以利用它始终围绕javascript执行调用相同的代码-只需创建自己的 WebDriverEventListener

  1. Take a look at EventFiringWebdriver. This is a useful class that makes use of WebDriverEventListener to create custom Webdriver wrappers, with hooks on many events, allowing you to execute custom code before/after clicking, before/after pageload... and beside some others more importantly before/after executing javascript in the webdriver. You could leverage this to always call the same code around javascript execution - just create your own WebDriverEventListener.

您可以在js执行程序此处,并在WebDriverEventListener 此处

You can find more info on the js executor here, and on WebDriverEventListener here.

这篇关于当我的Javascript回调(以Selenium制造)返回时,写入Java控制台的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆