Skip to main content
Version: 10.3.1

Migrate web-automation Business Processes to Work.AI v10.3

Starting with Work.AI v10.3, the internal dependency on Selenium Fork is migrated to the latest version of Selenium 4 via the Selenide framework. The migration introduces backward compatibility issues with RPA components (desktop RPA, RPA API) and breaking changes to your implementations.

The org.openqa.selenium.WebDriver and org.openqa.selenium.WebElement native Selenium interfaces are explicitly modified by adding new methods and updating method signatures. Additionally, differences between Selenium 3 (on which Selenium Fork is based) and Selenium 4 make it no longer possible to use the org.openqa.selenium.interactions.Actions class for the Desktop driver.

While the internal RPA architecture can be easily modified and the changes in native Selenium are not a major issue, compilation errors might occur due to direct manipulations with the org.openqa.selenium.WebElement instance and org.openqa.selenium.WebDriver.

ODF tasks

The ODF approach provides a solution for implementing RPA tasks that utilize entities from RPA API. Below are examples written in ODF that cause compilation errors after migrating to Work.AI 10.3, along with references to the original Selenium.

Changes in org.openqa.selenium.WebElement

Several methods introduced by WorkFusion in Selenium Fork do not exist in the original Selenium org.openqa.selenium.WebElement interface:

  • void setText(CharSequence... text)

  • String getTextSelected()

  • boolean focus()

The original Selenium org.openqa.selenium.WebElement does not define or implement the void setText(CharSequence... text) method.

ODF: org.openqa.selenium.WebElement#setText(CharSequence... text)
package com.workfusion.tests.odf.task;
import javax.inject.Inject;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import com.workfusion.odf2.compiler.BotTask;
import com.workfusion.odf2.core.task.AdHocTask;
import com.workfusion.odf2.core.task.TaskInput;
import com.workfusion.odf2.core.task.output.TaskRunnerOutput;
import com.workfusion.odf2.core.webharvest.rpa.RpaDriver;
import com.workfusion.odf2.core.webharvest.rpa.RpaFactory;
import com.workfusion.odf2.core.webharvest.rpa.RpaRunner;
import com.workfusion.rpa.driver.Driver;
import static com.workfusion.rpa.helpers.RPA.$;
@BotTask(requireRpa = true)
public class OdfRpaTask implements AdHocTask {
private final RpaRunner rpaRunner;
@Inject
public OdfRpaTask(RpaFactory rpaFactory) {
this.rpaRunner = rpaFactory
.builder(RpaDriver.UNIVERSAL)
.closeOnCompletion(true)
.build();
}
@Override
public TaskRunnerOutput run(TaskInput taskInput) {
rpaRunner.execute(this::rpaWithBreakingChanges);
return taskInput.asResult().withColumn("example_bot_task_output", "completed_successfully");
}
private void rpaWithBreakingChanges(Driver driver) {
WebElement toAddress = $(By.xpath("//*[@class=\"rd_inp_to as-input\"]"));
toAddress.setText("text to set");
}
}

To resolve the issue, replace import org.openqa.selenium.WebElement with com.workfusion.rpa.element.WebElement, where the custom RPA methods mentioned above are moved.

info

Replace org.openqa.selenium.WebElement with com.workfusion.rpa.element.WebElement in your ODF code if you encounter compilation errors.

Changes in org.openqa.selenium.WebDriver

Several methods introduced and modified by WorkFusion in Selenium Fork do not exist in the original Selenium org.openqa.selenium.WebDriver interface.

The method signature was updated from void get(String url) to Integer get(String url).

New methods include:

  • void get(String url, String browserType)

  • void switchDriver(String driver)

  • void switchToPreviousDriver()

  • Set<String> getWindowHandles(String selector)

  • Options#void set(String optionName, String optionValue)

  • Options#String get(String optionName)

  • TargetLocator#Web Driver window(String nameOrHandle, Long timeoutInMillis)

See a sample with a possible scenario that will be broken after migration to Work.AI v10.3.

ODF: org.openqa.selenium.WebDriver#switchDriver(String driver)
package com.workfusion.tests.odf.task;
import javax.inject.Inject;
import com.workfusion.odf2.compiler.BotTask;
import com.workfusion.odf2.core.task.AdHocTask;
import com.workfusion.odf2.core.task.TaskInput;
import com.workfusion.odf2.core.task.output.TaskRunnerOutput;
import com.workfusion.odf2.core.webharvest.rpa.RpaDriver;
import com.workfusion.odf2.core.webharvest.rpa.RpaFactory;
import com.workfusion.odf2.core.webharvest.rpa.RpaRunner;
import com.workfusion.rpa.driver.Driver;
@BotTask(requireRpa = true)
public class OdfRpaTask implements AdHocTask {
private final RpaRunner rpaRunner;
@Inject
public OdfRpaTask(RpaFactory rpaFactory) {
this.rpaRunner = rpaFactory
.builder(RpaDriver.UNIVERSAL)
.closeOnCompletion(true)
.build();
}
@Override
public TaskRunnerOutput run(TaskInput taskInput) {
rpaRunner.execute(this::rpaWithBreakingChanges);
return taskInput.asResult().withColumn("example_bot_task_output", "completed_successfully");
}
private void rpaWithBreakingChanges(Driver driver) {
org.openqa.selenium.WebDriver seleniumDriver = driver;
seleniumDriver.switchDriver("chrome");
}
}

To resolve the issue, replace import org.openqa.selenium.WebDriver with com.workfusion.rpa.driver.WebDriver, where the custom RPA methods mentioned above are moved.

info

Replace org.openqa.selenium.WebDriver with com.workfusion.rpa.driver.WebDriver in your ODF code if you encounter compilation errors.

WebHarvest tasks

A WebHarvest task uses the Groovy task renderer under the hood.

The following example does not cause any issues, even when input_element is explicitly converted to org.openqa.selenium.WebElement. Groovy behaves differently from Java and resolves method calls dynamically by default, meaning the method resolution occurs at runtime rather than compile time.

ODF: org.openqa.selenium.WebElement#setText(CharSequence... text)
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://web-harvest.sourceforge.net/schema/1.0/config" scriptlang="groovy">
<robotics-flow>
<robot driver="chrome">
<script><![CDATA[
open(new URL("https://rpa-grid.s3.amazonaws.com/integration-test/simple/buttons.html"));
org.openqa.selenium.WebElement input_element = $(byId("input__text"))
input_element.setText("some value")
]]></script>
</robot>
</robotics-flow>
<export include-original-data="true"/>
</config>

The Groovy runtime does not strictly enforce the type declared for input_element. Instead, it looks up the method on the actual object assigned to input_element, which is of the com.workfusion.rpa.helpers.UiElement type. Since UiElement implements setText(Object text), Groovy allows the call without requiring an explicit conversion. This behavior reflects Groovy's dynamic nature, prioritizing the object's actual type over the declared type.

The web driver available in the Groovy script context is an instance of the com.workfusion.rpa.driver.Driver class. Even if it is transformed into org.openqa.selenium.WebDriver, no runtime issues occur for the same reasons described above.

caution

The only scenario that might bring potential issues is direct web driver creation using original Selenium classes and attempting to call a custom WorkFusion method, for example:

...
org.openqa.selenium.WebDriver driver = new ChromeDriver();
Integer id = driver.get("http://www.google.com"); // compilation error
...

Selenium Actions usage

The org.openqa.selenium.interactions.Actions class in Selenium is used to build and perform complex user interactions, such as mouse movements, clicks, drag-and-drop, and keyboard actions, in sequence.

Besides new methods added to org.openqa.selenium.interactions.Actions like tripleClick or wheelClick, Selenium 3 had a built-in mechanism (using the deprecated org.openqa.selenium.interactions.Keyboard and org.openqa.selenium.interactions.Mouse functionality) within org.openqa.selenium.interactions.Actions that WorkFusion used to make this class functional for the Desktop driver. In Selenium 4, this mechanism was removed.

Due to the changes, the native Selenium functionality is enhanced with an additional level of logic. For possible ways to work with Actions, see the table below.

Recommendations

After migrating to Work.AI v10.3, you might not experience any issues with your RPA tasks and processes. However, depending on how your code was written, minor changes might be required. Follow the recommendations below to ensure your code remains stable and reliable.

Work.AI v10.2.9Work.AI v10.3Comment
RPA.actions()RPA.actions()No changes.
org.openqa.selenium.interactions.Actionscom.workfusion.rpa.interactions.ActionsReplace to utilize custom RPA methods or make them work for the Desktop driver.
org.openqa.selenium.WebElement#setText(CharSequence... text)com.workfusion.rpa.element.WebElement#setText(CharSequence... text)Replace the package name of WebElement in your codebase.
org.openqa.selenium.WebElement#getTextSelected(CharSequence... text)com.workfusion.rpa.element.WebElement#getTextSelected(CharSequence... text)Replace the package name of WebElement in your codebase.
org.openqa.selenium.WebElement#focus(CharSequence... text)com.workfusion.rpa.element.WebElement#focus(CharSequence... text)Replace the package name of WebElement in your codebase.
Integer org.openqa.selenium.WebDriver#get(String url)Integer com.workfusion.rpa.driver.WebDriver#load(String url)If you expect the get method to return a value, replace the call with the load method.
org.openqa.selenium.WebDriver#get(String url, String browserType)com.workfusion.rpa.driver.WebDriver#get(String url, String browserType)Replace the package name of WebDriver in your codebase.
org.openqa.selenium.WebDriver#switchDriver(String driver)com.workfusion.rpa.driver.WebDriver#switchDriver(String driver)Replace the package name of WebDriver in your codebase.
org.openqa.selenium.WebDriver#switchToPreviousDriver()com.workfusion.rpa.driver.WebDriver#switchToPreviousDriver()Replace the package name of WebDriver in your codebase.
org.openqa.selenium.WebDriver#getWindowHandles(String selector)com.workfusion.rpa.driver.WebDriver#getWindowHandles(String selector)Replace the package name of WebDriver in your codebase.