A C++ client library for Selenium Webdriver. You can use this library in any C++ project.
Only 4.x and more Selenium Server.
COPYRIGHTS
- 2018 - Current Herman Semenov ([email protected])
- 2014 - 2018 Sergey Kogan ([email protected])
- 2017 Ilya Durdyev (IDurdyev)
SPECIAL THANKS
- 2019 xingyun86 ([email protected])
- 2020 xloem ([email protected])
- 2021 SrMilton ([email protected]), Mecanik ([email protected])
- 2022 Mecanik ([email protected]), No-47 ([email protected])
- 2024 Foxgoblin Xing ([email protected])
- 2025 DanielAtCosmicDNA (Daniel Kaminski) ([email protected]), stas-badzi (Stanisław Badziak) ([email protected])
git clone --recurse-submodules https://github.com/GermanAizek/webdriverxx.git
cd webdriverxxsudo apt-get install cmake g++ make curlsudo apt-get install cmake g++ make curl libcurl4-openssl-devsudo pacman -Syu cmake g++ make curlsudo emerge -av dev-util/cmake sys-devel/gcc sys-devel/make net-misc/curlmkdir build && cd build && cmake ..
sudo make installmkdir build
cd build
cmake ..
# For example, open a solution in Visual StudioTo work with GeckoDriver, you need any browser built on the Gecko engine.
Firefox (ESR, Nightly), IceCat, Waterfox, Pale Moon, SeaMonkey and etc.
In our examples, we will install official stable Firefox.
sudo apt-get install geckodriversudo pacman -Syu geckodriverUSE="geckodriver" sudo emerge -av www-client/firefoxTo work with chromedriver, you need any browser built on the Chromium engine.
Chromium, Google Chrome, Opera, Vivaldi and etc.
In our examples, we will install official stable Google Chrome.
sudo apt-get install chromium-driversudo yay -S --aur aur/chromedriversudo emerge -av www-client/chromedriver-binThe first thing you need is full runtime environment Java.
You need to download and run selenium-server-standalone.
If you decide to use a selenium server version older than v4.0.0-alpha, either compile with -DSELENIUM_MAJOR=3/2/1, or #define SELENIUM_MAJOR 3/2/1 before including webdriverxx.h
Download latest OpenJDK and unpack: https://openjdk.java.net/
Official Selenium server can be seen here:
- versions from 2.39 to 4.0.0-beta-4 https://selenium-release.storage.googleapis.com/index.html
- all versions (scroll to the release that you want, click
Artifactsand downloadselenium-server-#.#.#.jar) https://github.com/SeleniumHQ/selenium/releases
Powershell
Invoke-WebRequest -Uri https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.36.0/selenium-server-4.36.0.jarSet the path enviroment variable to OpenJDK or move to the OpenJDK folder
java -jar /path_to/selenium-server-4.0.0-beta-4.jar standaloneDownload latest OpenJDK from packet manager distributions Linux.
sudo apt-get install default-jresudo pacman -Syu jre-openjdk jre-openjdk-headlesssudo emerge -av virtual/jreOfficial Selenium server can be seen here:
- versions from 2.39 to 4.0.0-beta-4 https://selenium-release.storage.googleapis.com/index.html
- all versions (scroll to the release that you want, click
Artifactsand downloadselenium-server-#.#.#.jar) https://github.com/SeleniumHQ/selenium/releases
wget https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.36.0/selenium-server-4.36.0.jaror download from AUR (not recomended - outdated version v3.141.59-1) here:
sudo yay -S --aur aur/selenium-server-standaloneAfter now you can start.
java -jar selenium-server-4.0.0-beta-4.jar standaloneIf Selenium server standalone was downloaded from AUR (Arch Linux), then:
java -jar /usr/share/selenium-server/selenium-server-standalone.jarOn Windows:
cd src/vcprojects/
# Open a solution 'webdriverxx.sln' in Visual Studio and compile itMore info in MSDN: Build and run a C++ app project
Build CMakeLists in 'examples' folder and run binary.
On Linux:
cd examples/example_start_browsers
mkdir build && cd build
cmake ..
make
./example_start_browsers- Very lightweight framework (When compared with all implementations of api selenium)
- Chainable commands
- Value-like objects compatible with STL containers
- Header-only
- Lightweight dependencies:
- Can be used with any testing framework
- Linux, FreeBSD, OpenBSD, Mac and Windows
- Tested on GCC 9.x, Clang 10.x and MSVC Visual Studio 2019
All examples are in 'examples' folder.
WebDriver ie = Start(InternetExplorer().SetProxy(
SocksProxy("127.0.0.1:3128")
.SetUsername("user")
.SetPassword("12345")
.SetNoProxyFor("custom.host")
));WebDriver ff = Start(Firefox().SetProxy(DirectConnection()));driver
.Navigate("http://facebook.com")
.Navigate("http://twitter.com")
.Back()
.Forward()
.Refresh();// Throws exception if no match is found in the document
Element menu = driver.FindElement(ById("menu"));
// Returns empty vector if no such elements
// The search is performed inside the menu element
std::vector<Element> items = menu.FindElements(ByClass("item"));// Sends text input or a shortcut to the element
driver.FindElement(ByTag("input")).SendKeys("Hello, world!");
// Sends text input or a shortcut to the active window
driver.SendKeys(Shortcut() << keys::Control << "t");chrome::MobileEmulation me;
me.SetdeviceName(chrome::device::Get("Galaxy Note 3"));
WebDriver ff = Start(Chrome().SetMobileEmulation(me));// Simple script, no parameters
driver.Execute("console.log('Hi there!')");
// A script with one parameter
driver.Execute("document.title = arguments[0]", JsArgs() << "Cowabunga!");
// A script with more than one parameter
driver.Execute("document.title = arguments[0] + '-' + arguments[1]",
JsArgs() << "Beep" << "beep");
// Arrays or containers can also be used as parameters
const char* ss[] = { "Yabba", "dabba", "doo" };
driver.Execute("document.title = arguments[0].join(', ')", JsArgs() << ss);
// Even an Element can be passed to a script
auto element = driver.FindElement(ByTag("input"));
driver.Execute("arguments[0].value = 'That was nuts!'", JsArgs() << element);// Scalar types
auto title = driver.Eval<std::string>("return document.title")
auto number = driver.Eval<int>("return 123");
auto another_number = driver.Eval<double>("return 123.5");
auto flag = driver.Eval<bool>("return true");
// Containers (all std::back_inserter compatible)
std::vector<std::string> v = driver.Eval<std::vector<std::string>>(
"return [ 'abc', 'def' ]"
);
// Elements!
Element document_element = driver.Eval<Element>("return document.documentElement");Wait implicitly for asynchronous operations
driver.SetImplicitTimeoutMs(5000);
// Should poll the DOM for 5 seconds before throwing an exception.
auto element = driver.FindElement(ByName("async_element"));Wait explicitly for asynchronous operations
#include <webdriverxx/wait.h>
auto find_element = [&]{ return driver.FindElement(ById("async_element")); };
Element element = WaitForValue(find_element);#include <webdriverxx/wait.h>
auto element_is_selected = [&]{
return driver.FindElement(ById("asynchronously_loaded_element")).IsSelected();
};
WaitUntil(element_is_selected);Use matchers from Google Mock for waiting
#define WEBDRIVERXX_ENABLE_GMOCK_MATCHERS
#include <webdriverxx/wait_match.h>
driver.Navigate("http://initial_url.host.net");
auto url = [&]{ return driver.GetUrl(); };
using namespace ::testing;
auto final_url = WaitForMatch(url, HasSubstr("some_magic"));Prerequisites:
java -jar selenium-server.jar standalone &
./webdriverxx --browser=<firefox|chrome|...>java -jar selenium-server.jar standalone
webdriverxx.exe --browser=<firefox|chrome|...>The library is designed to be encoding-agnostic. It doesn't make any assumptions about encodings. All strings are transferred as is, without modifications.
The WebDriver protocol is based on UTF-8, so all strings passed to the library/received from the library should be/are encoded using UTF-8.
-
Webdriver++ objects are not thread safe. It is not safe to use neither any single object nor different objects obtained from a single WebDriver concurrently without synchronization. On the other side, Webdriver++ objects don't use global variables so it is OK to use different instances of WebDriver in different threads.
-
The CURL library should be explicitly initialized if several WebDrivers are used from multiple threads. Call
curl_global_init(CURL_GLOBAL_ALL);from<curl/curl.h>once per process before using this library.
Capabilities common;
common.SetProxy(DirectConnection());
auto ff = Start(Firefox(common));
auto ie = Start(InternetExplorer(common));
auto gc = Start(Chrome(common));Capabilities required = /* ... */;
auto ff = Start(Firefox(), required);const char* url = "http://localhost:4444/wd/hub/";
auto ff = Start(Firefox(), url);
// or
auto ff = Start(Firefox(), Capabilities() /* required */, url);namespace custom {
struct Object {
std::string string;
int number;
};
// Conversion functions should be in the same namespace as the object
picojson::value CustomToJson(const Object& value) {
return JsonObject()
.Set("string", value.string)
.Set("number", value.number);
}
void CustomFromJson(const picojson::value& value, Object& result) {
assert(value.is<picojson::object>());
result.string = FromJson<std::string>(value.get("string"));
result.number = FromJson<int>(value.get("number"));
}
} // namespace custom
custom::Object o1 = { "abc", 123 };
driver.Execute("var o1 = arguments[0];", JsArgs() << o1);
custom::Object o1_copy = driver.Eval<custom::Object>("return o1");
custom::Object o2 = driver.Eval<custom::Object>("return { string: 'abc', number: 123 }");