B4J Library Selenium Library - Pnd_Selenium

Selenium automates browsers. That's it!
What you do with that power is entirely up to you.
Primarily it is for automating web applications for testing purposes, but is certainly not limited to just that.
Boring web-based administration tasks can (and should) also be automated as well.

Library can be used in UI and Console (Non-UI) app.

Wrapper is based on Selenium Java v4.32.0 (May 02, 2025) from HERE.


Some things Selenium can do:
  • Most importantly, it "sees" the web page the same way a user does, with CSS, JavaScript, etc.
  • Crawl or scrape websites, particularly those that don't provide an API and load content lazily using JavaScript.
  • Measure web page elements and determine their locations.
  • Simulate geolocation.
  • Collect virtually anything imaginable from web pages.
  • Inject JavaScript into a page, execute it, and retrieve the result.
  • Manipulates cookies: read, add, edit, delete.
  • Convert HTML to PDF.
  • Take screenshots of the "visible" part or the entire web page.
  • Can control web browser by automating user interactions, such as clicks, typing, scrolling, etc.
  • It's primarily used for functional and regression testing of web applications, ensuring they behave as expected when users interact with them.
  • You can use Selenium to extract information from web pages. It interacts with dynamic web content (JavaScript-heavy sites) better than traditional web scraping methods.
  • Can simulate complex user interactions like dragging and dropping, mouse hover, multi-click, or keyboard input (e.g., filling out forms).
  • You can fill out forms and submit them automatically, useful for testing forms or bulk form submissions.
  • Can interact with browser alerts, pop-ups, and other modal dialogs, accepting, dismissing, or retrieving messages.
  • It can interact with dynamic content that changes after page loads using techniques like waits, handling AJAX calls, or waiting for elements to load.
  • Can interact with file upload controls, uploading files as part of automated tests, and downloading files to verify download functionality.
  • Can run tests on headless browsers (browsers without a graphical user interface), such as Headless Chrome, enabling faster test execution, especially in CI/CD pipelines.
  • Allows you to start and stop browser sessions, making it easy to manage the browser lifecycle during test execution.
  • And much, much more.


Versions:

v1.04

  • Update for Selenium Java to v4.30.0

v1.05
  • Update for Selenium Java to v4.31.0

v1.06
  • Update for Selenium Java to v4.32.0


Examples:



Download library from: https://mega.nz/file/oQJFmIpT#m4yLLdSFYoyo1SAEIzll2XrhTtsZ9e-r11BFgCJMSlk

To compile app in release mode with #MergeLibraries: True, please check Selenium15 example.
To build standalone package, please check Selenium16 example.

When you download Chrome for Testing as well as the Chrome Driver, make sure to extract everything into one folder.
chrome.exe and chromedriver.exe should be in same folder.
For Windows use:
Chrome For Testing: https://storage.googleapis.com/chrome-for-testing-public/136.0.7103.49/win64/chrome-win64.zip
Chrome Driver: https://storage.googleapis.com/chrome-for-testing-public/136.0.7103.49/win64/chromedriver-win64.zip

If you are using other OS download Chrome for Testing and Chrome Driver from: https://googlechromelabs.github.io/chrome-for-testing/
Latest library version is tested with Chrome for Testing and Chrome Driver v136.0.7103.49
 

Attachments

  • SeleniumExamples.zip
    51.2 KB · Views: 116
Last edited:

Pip

Member
Hi Pendrush,

first of all, thanks a lot for this Selenium library !

I only despair at the moment with Chrome's automation, after pressing a button opens a new tab and thus the CurrentUrl is no longer correct.

Thus the question: "How can I set the focus on the new TAB and thus continue to work in it?"

Thanks in advance !

With kind regards
Pip
 

Pendrush

Well-Known Member
Licensed User
Longtime User
Library updated to v0.6, to switch tab use code:
B4X:
Dim TabName As String
For Each name As String In Selenium.AllTabs
    TabName = name
Next
Selenium.SwitchToTab(TabName)
 

Pip

Member
Hi Pendrush,

the change to the new TAB works only conditionally. The CurrentURL changes apparently, but certain elements on this TAB are unfortunately still not findable.

As an example:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method": "css selector", "selector": "body#body>header>form>div>div>button"}

it doesn't matter if I search with CSS selector or XPath, the element remains untraceable.

Even if I close the old TAB before executing the For Each loop, this has no effect.

I try to address a textbox and next a button. Despite the correct linking I get "No Search element" displayed. It seems to me that the website blocks such controls.

Try:
By simulating the Tab key, I navigate to the textbox and would now only need a routine to pass a text, unfortunately I am missing the element here and pure keyboard input cannot be sent, also CTRL+V fails unfortunately.

Would you still have an idea for me ?
 

Pip

Member
Sorry for double post,

is there a way to disable the message "Chrome is being controlled by automated test software" and suggest to the web server that there is no underlying automation? I have not been able to solve it via startup parameters.

As an example:
I try to log in to the UPS website, automated by Chromedriver I get an "Access Denied" message.

So I would have to make it so that the web server does not notice that it is an automation software. Is there a solution for this problem?

Thanks a lot in advance !
 
Last edited:

Anser

Well-Known Member
Licensed User
Longtime User
Maybe the elements that you are trying to access are inside a Frame.
Switch to that particular frame first using the SwitchToFrame() and then try to access those elements
 

Pip

Member
Maybe the elements that you are trying to access are inside a Frame.
Switch to that particular frame first using the SwitchToFrame() and then try to access those elements
SwitchToFrame() was a good hint ! Thank you, I could then access the element via XPath !

Ok, so this works now, but how do I solve the problem that the UPS website (completely different website) recognizes that it is an automation ? Do you have a tip for me ?

Thank you
 

Pendrush

Well-Known Member
Licensed User
Longtime User
Maybe you can try to change user agent, for example:
B4X:
Selenium.AddArgument("--user-agent=Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
You can also try some other user agent from different browsers.
 

Pip

Member
Hello Pendrush,

I had
B4X:
Selenium.AddArgument("--user-agent=Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
tested once via https://botcheck.luminati.io/ with the following result:
Navigate type
FAIL user-agent: missing user-agent header

Other test with
B4X:
Selenium.AddArgument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36")
gave the following:


Both attempts ended in "Access Denied" so far. I will test more user agents.
 

Pendrush

Well-Known Member
Licensed User
Longtime User
Maybe:
B4X:
Selenium.AddArgument("-–disable-blink-features=AutomationControlled")
 

kostefar

Active Member
Licensed User
Longtime User
I hope this thread is not too old to add a bit to it. If so, please let me know, and I´ll start a new one.

I´ve installed Selenium, but fail to get the demo working. I´m using the latest chromedriver, which is 111.0.5563.65, whereas the chromedriver is for 111.0.5563.64, so not sure if that´s what´s causing the below:


B4X:
WARNING: package com.sun.javafx.embed.swing.oldimpl not in javafx.swing
Waiting for debugger to connect...
Program started.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Starting ChromeDriver 111.0.5563.64 (c710e93d5b63b7095afe8c2c17df34408078439d-refs/branch-heads/5563@{#995}) on port 14376
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
mar. 15, 2023 3:13:57 PM org.openqa.selenium.remote.http.WebSocket$Listener onError
WARNING: Invalid Status code=403 text=Forbidden
java.io.IOException: Invalid Status code=403 text=Forbidden
    at org.asynchttpclient.netty.handler.WebSocketHandler.abort(WebSocketHandler.java:92)
    at org.asynchttpclient.netty.handler.WebSocketHandler.handleRead(WebSocketHandler.java:118)
    at org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelRead(AsyncHttpClientHandler.java:78)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:336)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:444)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:280)
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:832)
Error occurred on line: 24 (Main)
org.openqa.selenium.remote.http.ConnectionFailedException: Unable to establish websocket connection to http://localhost:53946/devtools/browser/372efec7-19e0-4f6b-9c7f-ede143289bf0
Build info: version: '4.7.2', revision: '4d4020c3b7'
System info: os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '14.0.1'
Driver info: driver.version: ChromeDriver
    at org.openqa.selenium.remote.http.netty.NettyWebSocket.<init>(NettyWebSocket.java:102)
    at org.openqa.selenium.remote.http.netty.NettyWebSocket.lambda$create$3(NettyWebSocket.java:128)
    at org.openqa.selenium.remote.http.netty.NettyClient.openSocket(NettyClient.java:107)
    at org.openqa.selenium.devtools.Connection.<init>(Connection.java:78)
    at org.openqa.selenium.chromium.ChromiumDriver.lambda$new$2(ChromiumDriver.java:116)
    at java.base/java.util.Optional.map(Optional.java:258)
    at org.openqa.selenium.chromium.ChromiumDriver.<init>(ChromiumDriver.java:114)
    at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:82)
    at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:71)
    at com.pendrush.selenium.kotlin.SeleniumLib.initialize(SeleniumLib.kt:32)
    at com.pendrush.selenium.Wrapper.initialize2(Wrapper.java:39)
    at com.pendrush.selenium.Wrapper.Initialize(Wrapper.java:35)
    at b4j.example.main._appstart(main.java:78)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:237)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
    at b4j.example.main.start(main.java:38)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:832)

Thanks in advance!
 

Pip

Member

Hey kostefar,

Try this before Selenium.initialize:
B4X:
Selenium.addArgument("--remote-allow-origins=*")

It works fine for me !

Kind regards
Pip
 

kostefar

Active Member
Licensed User
Longtime User
Hey kostefar,

Try this before Selenium.initialize:
B4X:
Selenium.addArgument("--remote-allow-origins=*")

It works fine for me !

Kind regards
Pip
Thank you SO much Pip, now I´m one step further! How did you find out about that?
 

Pip

Member

Pip

Member
@Pendrush

Is there a possibility to set the "navigator.webdriver" flag to false ?

The Chromedriver starts with navigator.webdriver = true, so the website already knows about it. This flag would be false if the website is driven by a human.

Is it possible to make the chrome dev options accessible before the chrome browser starts and thus set the flag to false ?

If this already works with the current library, I wouldn't know exactly how to do it.

Thanks in advance !
 

syerif

Active Member
Licensed User
Longtime User


Hi,
it is possible with your library to scrolling browser like this..

Thank you
 

kostefar

Active Member
Licensed User
Longtime User
Would someone be able to get me started on something that looks like this in terms of filling in email address + password and clicking "Sign in"?

B4X:
<div class="form-group username">
            <label class="control-label" for="Email">Email</label>
            <input class="form-control" placeholder="Email Address" autocomplete="off" tabindex="1" spellcheck="false" type="text" data-val="true" data-val-required="The Email field is required." id="Email" name="Email" value="" />
            <span class="text-danger" id="unError" style="display:none;">Please enter a valid email address</span>
        </div>
            <div class="form-group password">
                <label class="control-label" for="Password">Password</label>
                <input type="password" class="form-control" placeholder="Password" autofocus="autofocus" autocomplete="off" tabindex="2" id="Password" name="Password" />
            </div>

        <div class="form-group">
            <label class="chk-label" for="RememberLogin">
                <input tabindex="4" type="checkbox" checked="checked" data-val="true" data-val-required="The Remember Login field is required." id="RememberLogin" name="RememberLogin" value="true" />
                Remember Login
            </label>
        </div>

        <div class="form-group">
            <button type="submit" id="SubmitLogin" tabindex="3">
                Sign in
            </button>
        </div>

Thanks in advance!

PS: I did already try different things using the example attached to the initial post as a template, but with no luck so far.
 
Last edited:

behnam_tr

Active Member
Licensed User
Longtime User
@Pendrush
thanks for great library

please can you add method for execute java script code ??
i need to Modify innerHTML
like this :
B4X:
<span class="locked-step"></span>

to

<span class="showStepsButton"></span>