написать в консоль Java, когда мой обратный вызов Javascript (сделанный в Selenium) вернется - PullRequest
0 голосов
/ 26 сентября 2018

Я научился создавать функции обратного вызова Javascript, и у меня есть общее представление о «функциональном программировании», поскольку это кажется достаточно простым.Тем не менее, я новичок в javascript и его синтаксисе, и я не могу найти хороший способ проверить указанный синтаксис в моей IntelliJ IDE.

Что вы делаете?

Я создаю инструмент на основе Selenium, чтобы нажимать на веб-элемент, ждать, пока он перезагрузит страницу, устареть или подождать тайм-аут.Причина, по которой я это делаю, состоит в том, чтобы классифицировать веб-элементы по трем категориям: вызывает перезагрузку страницы, становится устаревшей, не изменяется.Для этого я сделал простой скрипт javascript с JavascriptExecutor, который поставляется с Java.Большая часть моего кода написана на Java, и это тот язык, которым я владею. Я хочу научиться использовать javascript с java для того, чтобы делать то, что мне нужно, с веб-страницами.

Хорошо, но в чем конкретно проблема?

У меня есть функция обратного вызова javascript:

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

, которая выполняется внутри Javascript Executor, например так:

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 - статический метод в этом классе.Этот статический метод выглядит следующим образом:

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

Это должен быть простой способ получить что-то из JavaScript в мой код Java.Причина, по которой я попытался сделать это, заключается в том, что я прочитал это:

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

Но потом я понял, что это не сработает, и копал глубже.Я прочитал, что Javascript и Java разделены сервером и клиентом, и я получил некоторое понимание этого вопроса:

вызов методов java в коде javascript

Однако я неНа 100% уверен, что это верно для моего случая, так как выполняемый мной Javascript не приходит с веб-страницы, которую я тестирую. Скорее я сделал это сам в коде Java как String.Кроме того, я все еще сильно растерялся, если ответ на этот вопрос действительно относится ко мне.Есть только один, и он в основном просто говорит: «установите некоторые вещи, потому что java - это клиентская часть, а javascript - это серверная».Я (вроде бы) понимаю, что означают эти термины, но я не уверен, что javascript, который я написал в своем классе, будет считаться «серверной», на самом деле это будет не так.Что мне нужно, так это разъяснение по поводу A: действительно ли javascript, который я запускаю / создаю в своем java-коде, на самом деле является серверным?B: если да, то может ли кто-нибудь дать мне краткое изложение того, как я буду вызывать код Java с сервера?это требует разрешений?Я предполагаю, что должен связаться с указанным сервером, значит ли это, что я использую запросы GET и POSt?C: Если Javascript не на стороне сервера, то он должен быть на стороне клиента, и я должен быть в состоянии назвать это довольно легко, верно?Как мне это сделать?

Покажите нам, что именно вы хотите

Я хочу иметь возможность запустить:

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.Так, например, если я вставил правильный код для вызова моего статического метода:

SeleniumTest.IsPageReloaded.JavascriptWorking

(который снова выглядит как):

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

Затем яЯ хочу увидеть "Javascript, запущенный здесь" на моей консоли Java.Используемый драйвер является interchangebale, я просто первым использовал chrome, потому что он быстрый.Все, что для этого нужно - это включающий основной класс, и он ((должен)) быть работоспособным, но без обещаний.

Цель состоит в том, чтобы получить что-то в java, которое я затем смогу использовать в качестве флага, чтобы знать, что мой асинхронный javascriptсделано в Java, и я могу продолжить выполнение программы.Я могу получить часть асинхронного JavaScript и понимаю, мне просто нужна ссылка на мой код Java.

Возможные решения

Мне сказали, что обычным способом предоставления флага для вашего java-кода является создание определенного элемента webelement на странице с javascript и проверка его в java (отсюда и ссылка).Мне не хочется добавлять к тестируемым веб-страницам, потому что я хочу протестировать их без фактического редактирования / изменения.Я, как правило, открыт для других простых решений, но самое главное, что мне нужно, это разъяснение всей проблемы на стороне клиента, потому что оно относится к моим настройкам (Selenium java -> javascript -> java), где большинство вопросов покрывают только (javascript -> java)или наоборот.

1 Ответ

0 голосов
/ 26 сентября 2018

Ссылка, которую вы упомянули о вызове JS Java, предназначена для конкретного приложения, которое предназначено для этого.Не сказать, что это невозможно (я написал плагины FF на основе аналогичного принципа), но это не применимо в этом случае.Это также требует специальной поддержки приложений (по умолчанию Javascript, выполняемый в браузере, сильно загружен в «песочницу» - он не может получить доступ к чему-либо вне своей области действия. Вызывать другие приложения самостоятельно - это большое число.).

СкриптыВы делаете инъекцию всегда на стороне клиента, они выполняются только в браузере, который изолирован от самого кода Java.С этим сказанным нет ничего невозможного.

Хотелось бы упомянуть две интересные особенности библиотеки Selenium, которые могут пригодиться для вас.

  1. Вы много раз упоминали волшебный термин "async Javascriptвыполнение "- и, как я вижу, вы реализуете свою собственную версию executeAsyncScript.Webdriver предоставляет этот метод «из коробки», в основном для той цели, с которой вы хотите его использовать.

Когда вы используете executeScript, он вернется почти сразу же после завершения - в вашемВ случае, если он просто внедрит ваш слушатель с вашим кодом, а затем вернется.Используя executeAsyncScript, вы можете получить обратный вызов - именно то, что вы делаете.При вызове executeAsyncScript в ваш код в качестве последнего аргумента добавляется метод callback по умолчанию, который должен вызываться вашим кодом JS для возврата метода.

Простой пример:

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 сгенерирует исключение.Вернувшись, вы можете создать экземпляр возвращенного класса и напечатать как

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, где вы также указываете имя метода, но использование отражения здесь действительно оффтопно.

Взгляните на EventFiringWebdriver.Это полезный класс, который использует WebDriverEventListener для создания пользовательских оболочек Webdriver с перехватом многих событий, позволяя вам выполнять пользовательский код до / после нажатия, до / после загрузки страницы ... и, кроме того, некоторые другие, что более важно, перед /после выполнения JavaScript в веб-драйвере.Вы можете использовать это, чтобы всегда вызывать один и тот же код при выполнении javascript - просто создайте свой собственный WebDriverEventListener.

. Вы можете найти больше информации о js executor здесь , и наWebDriverEventListener здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...