pub struct Client<Caps>where
Caps: AppiumCapability,{ /* private fields */ }
Expand description
Generic Appium client
This client represents an Appium client that will connect to an Appium server and send command to said server.
Depending on chosen capabilities (AppiumCapability), the client will have different traits. Which means - different available features.
Check out AndroidClient and IOSClient in docs to see their features (available commands).
Note: Client automatically ends Appium session on drop (end of lifetime). This is the only way to end session.
Methods from Deref<Target = Client>§
Sourcepub async fn issue_cmd(
&self,
cmd: impl WebDriverCompatibleCommand + Send + 'static,
) -> Result<Value, CmdError>
pub async fn issue_cmd( &self, cmd: impl WebDriverCompatibleCommand + Send + 'static, ) -> Result<Value, CmdError>
Issue the specified WebDriverCompatibleCommand
to the WebDriver instance.
Sourcepub async fn session_id(&self) -> Result<Option<String>, CmdError>
pub async fn session_id(&self) -> Result<Option<String>, CmdError>
Get the unique session ID assigned by the WebDriver server to this client.
Sourcepub async fn set_ua<S>(&self, ua: S) -> Result<(), CmdError>
pub async fn set_ua<S>(&self, ua: S) -> Result<(), CmdError>
Set the User Agent string to use for all subsequent requests.
Sourcepub async fn get_ua(&self) -> Result<Option<String>, CmdError>
pub async fn get_ua(&self) -> Result<Option<String>, CmdError>
Get the current User Agent string.
Sourcepub async fn persist(&self) -> Result<(), CmdError>
pub async fn persist(&self) -> Result<(), CmdError>
Mark this client’s session as persistent.
After all instances of a Client
have been dropped, we normally shut down the WebDriver
session, which also closes the associated browser window or tab. By calling this method,
the shutdown command will not be sent to this client’s session, meaning its window or tab
will remain open.
Note that an explicit call to Client::close
will still terminate the session.
This function is safe to call multiple times.
Sourcepub async fn status(&self) -> Result<WebDriverStatus, CmdError>
pub async fn status(&self) -> Result<WebDriverStatus, CmdError>
Get the WebDriver status.
See 8.3 Status of the WebDriver standard.
Sourcepub async fn get_timeouts(&self) -> Result<TimeoutConfiguration, CmdError>
pub async fn get_timeouts(&self) -> Result<TimeoutConfiguration, CmdError>
Get the timeouts for the current session.
See 8.4 Get Timeouts of the WebDriver standard.
Sourcepub async fn update_timeouts(
&self,
timeouts: TimeoutConfiguration,
) -> Result<(), CmdError>
pub async fn update_timeouts( &self, timeouts: TimeoutConfiguration, ) -> Result<(), CmdError>
Set the timeouts for the current session.
See 8.5 Set Timeouts of the WebDriver standard.
Sourcepub async fn goto(&self, url: &str) -> Result<(), CmdError>
pub async fn goto(&self, url: &str) -> Result<(), CmdError>
Navigate directly to the given URL.
See 9.1 Navigate To of the WebDriver standard.
Sourcepub async fn current_url(&self) -> Result<Url, CmdError>
pub async fn current_url(&self) -> Result<Url, CmdError>
Retrieve the currently active URL for this session.
See 9.2 Get Current URL of the WebDriver standard.
Sourcepub async fn back(&self) -> Result<(), CmdError>
pub async fn back(&self) -> Result<(), CmdError>
Go back to the previous page.
See 9.3 Back of the WebDriver standard.
Sourcepub async fn forward(&self) -> Result<(), CmdError>
pub async fn forward(&self) -> Result<(), CmdError>
Go forward to the next page.
See 9.4 Forward of the WebDriver standard.
Sourcepub async fn refresh(&self) -> Result<(), CmdError>
pub async fn refresh(&self) -> Result<(), CmdError>
Refresh the current previous page.
See 9.5 Refresh of the WebDriver standard.
Sourcepub async fn title(&self) -> Result<String, CmdError>
pub async fn title(&self) -> Result<String, CmdError>
Get the current page title.
See 9.6 Get Title of the WebDriver standard.
Sourcepub async fn window(&self) -> Result<WindowHandle, CmdError>
pub async fn window(&self) -> Result<WindowHandle, CmdError>
Gets the current window handle.
See 10.1 Get Window Handle of the WebDriver standard.
Sourcepub async fn close_window(&self) -> Result<(), CmdError>
pub async fn close_window(&self) -> Result<(), CmdError>
Closes the current window.
Will close the session if no other windows exist.
Closing a window will not switch the client to one of the remaining windows.
The switching must be done by calling switch_to_window
using a still live window
after the current window has been closed.
See 10.2 Close Window of the WebDriver standard.
Sourcepub async fn switch_to_window(
&self,
window: WindowHandle,
) -> Result<(), CmdError>
pub async fn switch_to_window( &self, window: WindowHandle, ) -> Result<(), CmdError>
Switches to the chosen window.
See 10.3 Switch To Window of the WebDriver standard.
Sourcepub async fn windows(&self) -> Result<Vec<WindowHandle>, CmdError>
pub async fn windows(&self) -> Result<Vec<WindowHandle>, CmdError>
Gets a list of all active windows (and tabs)
See 10.4 Get Window Handles of the WebDriver standard.
Sourcepub async fn new_window(
&self,
as_tab: bool,
) -> Result<NewWindowResponse, CmdError>
pub async fn new_window( &self, as_tab: bool, ) -> Result<NewWindowResponse, CmdError>
Creates a new window. If as_tab
is true
, then a tab will be created instead.
Windows are treated the same as tabs by the WebDriver protocol. The functions new_window
,
switch_to_window
, close_window
, window
and windows
all operate on both tabs and
windows.
This operation is only in the editor’s draft of the next iteration of the WebDriver
protocol, and may thus not be supported by all WebDriver implementations. For example, if
you’re using geckodriver
, you will need geckodriver > 0.24
and firefox > 66
to use
this feature.
See 11.5 New Window of the editor’s draft standard.
Sourcepub async fn enter_frame(&self, index: Option<u16>) -> Result<(), CmdError>
pub async fn enter_frame(&self, index: Option<u16>) -> Result<(), CmdError>
Switches to the frame specified at the index.
See 10.5 Switch To Frame of the WebDriver standard.
Sourcepub async fn enter_parent_frame(&self) -> Result<(), CmdError>
pub async fn enter_parent_frame(&self) -> Result<(), CmdError>
Switches to the parent of the frame the client is currently contained within.
See 10.6 Switch To Parent Frame of the WebDriver standard.
Sourcepub async fn set_window_rect(
&self,
x: u32,
y: u32,
width: u32,
height: u32,
) -> Result<(), CmdError>
pub async fn set_window_rect( &self, x: u32, y: u32, width: u32, height: u32, ) -> Result<(), CmdError>
Sets the x, y, width, and height properties of the current window.
See 10.7.2 Set Window Rect of the WebDriver standard.
Sourcepub async fn get_window_rect(&self) -> Result<(u64, u64, u64, u64), CmdError>
pub async fn get_window_rect(&self) -> Result<(u64, u64, u64, u64), CmdError>
Gets the x, y, width, and height properties of the current window.
See 10.7.1 Get Window Rect of the WebDriver standard.
Sourcepub async fn set_window_size(
&self,
width: u32,
height: u32,
) -> Result<(), CmdError>
pub async fn set_window_size( &self, width: u32, height: u32, ) -> Result<(), CmdError>
Sets the x, y, width, and height properties of the current window.
See 10.7.2 Set Window Rect of the WebDriver standard.
Sourcepub async fn get_window_size(&self) -> Result<(u64, u64), CmdError>
pub async fn get_window_size(&self) -> Result<(u64, u64), CmdError>
Gets the width and height of the current window.
See 10.7.1 Get Window Rect of the WebDriver standard.
Examples found in repository?
9async fn main() -> Result<(), Box<dyn std::error::Error>> {
10 let mut capabilities = AndroidCapabilities::new_uiautomator();
11 capabilities.app("https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk");
12
13 let client = ClientBuilder::native(capabilities)
14 .connect("http://localhost:4723/")
15 .await?;
16
17 // Go to a screen with a long list
18 client.find_by(By::accessibility_id("Views"))
19 .await?
20 .click()
21 .await?;
22
23 // Let's calculate some things first
24 let (width, height) = client.get_window_size().await?;
25
26 // This is the horizontal center, it will be our x for swipe.
27 let horizontal_center = (width / 2) as i64;
28
29 // The swipe will start at 80% of screen height, and end at 20% of screen height.
30 // So we will swipe UP through most of the screen.
31 let almost_top = (height as f64 * 0.2) as i64;
32 let almost_bottom = (height as f64 * 0.8) as i64;
33
34 let swipe_down = TouchActions::new("finger".to_string())
35 // position the finger first
36 .then(PointerAction::MoveTo {
37 duration: Some(Duration::from_millis(0)),
38 x: horizontal_center,
39 y: almost_bottom,
40 })
41 // THEN touch the screen
42 .then(PointerAction::Down {
43 button: MOUSE_BUTTON_LEFT // believe me, it is not a mouse, but a simple touch
44 })
45 // THEN move the finger through the screen
46 .then(PointerAction::MoveTo {
47 duration: Some(Duration::from_millis(500)),
48 x: horizontal_center,
49 y: almost_top,
50 });
51
52 client.perform_actions(swipe_down)
53 .await?;
54
55 Ok(())
56}
Sourcepub async fn set_window_position(&self, x: u32, y: u32) -> Result<(), CmdError>
pub async fn set_window_position(&self, x: u32, y: u32) -> Result<(), CmdError>
Sets the x, y, width, and height properties of the current window.
See 10.7.2 Set Window Rect of the WebDriver standard.
Sourcepub async fn get_window_position(&self) -> Result<(u64, u64), CmdError>
pub async fn get_window_position(&self) -> Result<(u64, u64), CmdError>
Gets the x and y top-left coordinate of the current window.
See 10.7.1 Get Window Rect of the WebDriver standard.
Sourcepub async fn maximize_window(&self) -> Result<(), CmdError>
pub async fn maximize_window(&self) -> Result<(), CmdError>
Maximize the current window.
See 10.7.3 Maximize Window of the WebDriver standard.
Sourcepub async fn minimize_window(&self) -> Result<(), CmdError>
pub async fn minimize_window(&self) -> Result<(), CmdError>
Minimize the current window.
See 10.7.4 Minimize Window of the WebDriver standard.
Sourcepub async fn fullscreen_window(&self) -> Result<(), CmdError>
pub async fn fullscreen_window(&self) -> Result<(), CmdError>
Make the current window fullscreen.
See 10.7.5 Fullscreen Window of the WebDriver standard.
Sourcepub async fn find(&self, search: Locator<'_>) -> Result<Element, CmdError>
pub async fn find(&self, search: Locator<'_>) -> Result<Element, CmdError>
Find an element on the page that matches the given Locator
.
See 12.2 Find Element of the WebDriver standard.
Sourcepub async fn find_all(
&self,
search: Locator<'_>,
) -> Result<Vec<Element>, CmdError>
pub async fn find_all( &self, search: Locator<'_>, ) -> Result<Vec<Element>, CmdError>
Find all elements on the page that match the given Locator
.
See 12.3 Find Elements of the WebDriver standard.
Sourcepub async fn active_element(&self) -> Result<Element, CmdError>
pub async fn active_element(&self) -> Result<Element, CmdError>
Get the active element for this session.
The “active” element is the Element
within the DOM that currently has focus. This will
often be an <input>
or <textarea>
element that currently has the text selection, or
another input element such as a checkbox or radio button. Which elements are focusable
depends on the platform and browser configuration.
If no element has focus, the result may be the page body or a NoSuchElement
error.
See 12.6 Get Active Element of the WebDriver standard.
Sourcepub async fn form(&self, search: Locator<'_>) -> Result<Form, CmdError>
pub async fn form(&self, search: Locator<'_>) -> Result<Form, CmdError>
Locate a form on the page.
Through the returned Form
, HTML forms can be filled out and submitted.
Sourcepub async fn source(&self) -> Result<String, CmdError>
pub async fn source(&self) -> Result<String, CmdError>
Get the HTML source for the current page.
See 15.1 Get Page Source of the WebDriver standard.
Examples found in repository?
10async fn main() -> Result<(), Box<dyn std::error::Error>> {
11 // Capabilities describe the automation environment,
12 // for example: what app are we testing
13 let mut capabilities = AndroidCapabilities::new();
14 capabilities.app("https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk");
15
16 // To add custom capability that is not supported by this library just use "insert".
17 // Alternatively, there are helpful functions like "set_bool", "set_str".
18 // You can read more about capabilities on Appium website - https://appium.io/docs/en/2.1/guides/caps/.
19 capabilities.set_str("appium:automationName", "uiautomator2");
20 capabilities.set_bool("appium:fullReset", true);
21
22 // To start automation, you need to build a client.
23 let client = ClientBuilder::native(capabilities)
24 .connect("http://localhost:4723/")
25 .await?;
26
27 // The app should automatically start, let's print the DOM of current app screen.
28 let value = client.source().await?;
29 println!("{value}");
30
31 // Screen orientation is another Appium perk
32 let orientation = client.orientation().await?;
33 println!("Screen orientation: {orientation}");
34
35 // Now we try to locate a button using UiAutomator API.
36 // Notice that the program will wait until the button appears on screen (but maximum of 30 seconds).
37 let views_button = client
38 .appium_wait()
39 .for_element(By::uiautomator("new UiSelector().text(\"Views\");"))
40 .await?;
41
42 views_button.click().await?;
43
44 // Search for a vec of elements, because we know that there will be more than one result.
45 // Notice that this time we don't wait, just find everything that's on screen as is.
46 let menu_elements = client
47 .find_all_by(By::uiautomator("new UiSelector().className(\"android.widget.TextView\");"))
48 .await?;
49
50 menu_elements.get(1)
51 .unwrap()
52 .click()
53 .await?;
54
55 // To add a timeout for wait, use "at_most".
56 // "check_every" limits how often Appium has to perform the search during wait.
57 //
58 // Sometimes it's better to use one or both of those methods, because:
59 // 1) We know that something should appear sooner, and if it doesn't, we don't want to wait full 30 seconds.
60 // 2) We don't want to slow down Appium server by checking again too often.
61 let element = client
62 .appium_wait()
63 .at_most(Duration::from_secs(20))
64 .check_every(Duration::from_millis(500))
65 .for_element(By::class_name("android.widget.ListView"))
66 .await?;
67
68 // This is a simple search for one element, without waiting for it to appear. And then we click on it.
69 // Notice that we are searching for an element inside "element" (which is a ListView).
70 element
71 .find_by(By::accessibility_id("3D Transition"))
72 .await?
73 .click()
74 .await?;
75
76 Ok(())
77}
Sourcepub async fn execute(
&self,
script: &str,
args: Vec<Value>,
) -> Result<Value, CmdError>
pub async fn execute( &self, script: &str, args: Vec<Value>, ) -> Result<Value, CmdError>
Execute the given JavaScript script
in the current browser session.
args
is available to the script inside the arguments
array. Since Element
implements
Serialize
, you can also provide serialized Element
s as arguments, and they will
correctly deserialize to DOM elements on the other side.
To retrieve the value of a variable, return
has to be used in the JavaScript code.
See 15.2.1 Execute Script of the WebDriver standard.
Sourcepub async fn execute_async(
&self,
script: &str,
args: Vec<Value>,
) -> Result<Value, CmdError>
pub async fn execute_async( &self, script: &str, args: Vec<Value>, ) -> Result<Value, CmdError>
Execute the given async JavaScript script
in the current browser session.
The provided JavaScript has access to args
through the JavaScript variable arguments
.
The arguments
array also holds an additional element at the end that provides a completion callback
for the asynchronous code.
Since Element
implements Serialize
, you can also provide serialized Element
s as arguments, and they will
correctly deserialize to DOM elements on the other side.
§Examples
Call a web API from the browser and retrieve the value asynchronously
const JS: &'static str = r#"
const [date, callback] = arguments;
fetch(`http://weather.api/${date}/hourly`)
// whenever the HTTP Request completes,
// send the value back to the Rust context
.then(data => {
callback(data.json())
})
"#;
let weather = client.execute_async(JS, vec![date]).await?;
See 15.2.2 Execute Async Script of the WebDriver standard.
Sourcepub async fn perform_actions(
&self,
actions: impl Into<Actions>,
) -> Result<(), CmdError>
pub async fn perform_actions( &self, actions: impl Into<Actions>, ) -> Result<(), CmdError>
Create a new Actions chain.
let mouse_actions = MouseActions::new("mouse")
.then(PointerAction::Down {
button: MOUSE_BUTTON_LEFT,
})
.then(PointerAction::MoveBy {
duration: Some(Duration::from_secs(2)),
x: 100,
y: 0,
})
.then(PointerAction::Up {
button: MOUSE_BUTTON_LEFT,
});
client.perform_actions(mouse_actions).await?;
See the documentation for Actions
for more information.
Perform the specified input actions.
See 17.5 Perform Actions of the WebDriver standard.
Examples found in repository?
9async fn main() -> Result<(), Box<dyn std::error::Error>> {
10 let mut capabilities = AndroidCapabilities::new_uiautomator();
11 capabilities.app("https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk");
12
13 let client = ClientBuilder::native(capabilities)
14 .connect("http://localhost:4723/")
15 .await?;
16
17 // Go to a screen with a long list
18 client.find_by(By::accessibility_id("Views"))
19 .await?
20 .click()
21 .await?;
22
23 // Let's calculate some things first
24 let (width, height) = client.get_window_size().await?;
25
26 // This is the horizontal center, it will be our x for swipe.
27 let horizontal_center = (width / 2) as i64;
28
29 // The swipe will start at 80% of screen height, and end at 20% of screen height.
30 // So we will swipe UP through most of the screen.
31 let almost_top = (height as f64 * 0.2) as i64;
32 let almost_bottom = (height as f64 * 0.8) as i64;
33
34 let swipe_down = TouchActions::new("finger".to_string())
35 // position the finger first
36 .then(PointerAction::MoveTo {
37 duration: Some(Duration::from_millis(0)),
38 x: horizontal_center,
39 y: almost_bottom,
40 })
41 // THEN touch the screen
42 .then(PointerAction::Down {
43 button: MOUSE_BUTTON_LEFT // believe me, it is not a mouse, but a simple touch
44 })
45 // THEN move the finger through the screen
46 .then(PointerAction::MoveTo {
47 duration: Some(Duration::from_millis(500)),
48 x: horizontal_center,
49 y: almost_top,
50 });
51
52 client.perform_actions(swipe_down)
53 .await?;
54
55 Ok(())
56}
Sourcepub async fn release_actions(&self) -> Result<(), CmdError>
pub async fn release_actions(&self) -> Result<(), CmdError>
Release all input actions.
See 17.6 Release Actions of the WebDriver standard.
Sourcepub async fn dismiss_alert(&self) -> Result<(), CmdError>
pub async fn dismiss_alert(&self) -> Result<(), CmdError>
Dismiss the active alert, if there is one.
See 18.1 Dismiss Alert of the WebDriver standard.
Sourcepub async fn accept_alert(&self) -> Result<(), CmdError>
pub async fn accept_alert(&self) -> Result<(), CmdError>
Accept the active alert, if there is one.
See 18.2 Accept Alert of the WebDriver standard.
Sourcepub async fn get_alert_text(&self) -> Result<String, CmdError>
pub async fn get_alert_text(&self) -> Result<String, CmdError>
Get the text of the active alert, if there is one.
See 18.3 Get Alert Text of the WebDriver standard.
Sourcepub async fn send_alert_text(&self, text: &str) -> Result<(), CmdError>
pub async fn send_alert_text(&self, text: &str) -> Result<(), CmdError>
Send the specified text to the active alert, if there is one.
See 18.4 Send Alert Text of the WebDriver standard.
Sourcepub async fn screenshot(&self) -> Result<Vec<u8>, CmdError>
pub async fn screenshot(&self) -> Result<Vec<u8>, CmdError>
Get a PNG-encoded screenshot of the current page.
See 19.1 Take Screenshot of the WebDriver standard.
Sourcepub async fn wait_for<F, FF>(&self, is_ready: F) -> Result<(), CmdError>
👎Deprecated since 0.17.5: This method might block forever. Please use client.wait().on(…) instead. You can still wait forever using: client.wait().forever().on(…)
pub async fn wait_for<F, FF>(&self, is_ready: F) -> Result<(), CmdError>
Wait for the given function to return true
before proceeding.
This can be useful to wait for something to appear on the page before interacting with it.
While this currently just spins and yields, it may be more efficient than this in the
future. In particular, in time, it may only run is_ready
again when an event occurs on
the page.
Sourcepub async fn wait_for_find(
&self,
search: Locator<'_>,
) -> Result<Element, CmdError>
👎Deprecated since 0.17.5: This method might block forever. Please use client.wait().on(locator) instead. You can still wait forever using: client.wait().forever().on(locator)
pub async fn wait_for_find( &self, search: Locator<'_>, ) -> Result<Element, CmdError>
Wait for the given element to be present on the page.
This can be useful to wait for something to appear on the page before interacting with it.
While this currently just spins and yields, it may be more efficient than this in the
future. In particular, in time, it may only run is_ready
again when an event occurs on
the page.
👎Deprecated since 0.17.5: This method might block forever and has a chance of randomly blocking. Please use client.wait().on(url) instead, to check if you navigated successfully to the new URL.
Wait for the page to navigate to a new URL before proceeding.
If the current
URL is not provided, self.current_url()
will be used. Note however that
this introduces a race condition: the browser could finish navigating before we call
current_url()
, which would lead to an eternal wait.
Sourcepub async fn raw_client_for(
&self,
method: Method,
url: &str,
) -> Result<Response<Body>, CmdError>
pub async fn raw_client_for( &self, method: Method, url: &str, ) -> Result<Response<Body>, CmdError>
Issue an HTTP request to the given url
with all the same cookies as the current session.
Calling this method is equivalent to calling with_raw_client_for
with an empty closure.
Sourcepub async fn with_raw_client_for<F>(
&self,
method: Method,
url: &str,
before: F,
) -> Result<Response<Body>, CmdError>
pub async fn with_raw_client_for<F>( &self, method: Method, url: &str, before: F, ) -> Result<Response<Body>, CmdError>
Build and issue an HTTP request to the given url
with all the same cookies as the current
session.
Before the HTTP request is issued, the given before
closure will be called with a handle
to the Request
about to be sent.
Sourcepub fn wait(&self) -> Wait<'_>
pub fn wait(&self) -> Wait<'_>
Starting building a new wait operation. This can be used to wait for a certain condition, by periodically checking the state and optionally returning a value:
// -- snip wrapper code --
let button = client.wait().for_element(Locator::Css(
r#"a.button-download[href="/learn/get-started"]"#,
)).await?;
// -- snip wrapper code --
Also see: crate::wait
.
Get all cookies associated with the current document.
See 16.1 Get All Cookies of the WebDriver standard.
Get a single named cookie associated with the current document.
See 16.2 Get Named Cookie of the WebDriver standard.
Add the specified cookie.
See 16.3 Add Cookie of the WebDriver standard.
Delete a single cookie from the current document.
See 16.4 Delete Cookie of the WebDriver standard.
Delete all cookies from the current document.
See 16.5 Delete All Cookies of the WebDriver standard.