pub struct ClientBuilder<C, Caps>
where C: Connect + Send + Sync + Clone + Unpin, Caps: AppiumCapability,
{ /* private fields */ }
Expand description

Client builder

Use this struct to build Appium client. This struct has methods that will guide you through all necessary things needed to construct a client.

Do not create an instance of Client yourself, use this builder.

Implementations§

source§

impl<Caps> ClientBuilder<HttpsConnector<HttpConnector>, Caps>
where Caps: AppiumCapability,

source

pub fn native( capabilities: Caps ) -> ClientBuilder<HttpsConnector<HttpConnector>, Caps>

Examples found in repository?
examples/scroll.rs (line 13)
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut capabilities = AndroidCapabilities::new_uiautomator();
    capabilities.app("https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk");

    let client = ClientBuilder::native(capabilities)
        .connect("http://localhost:4723/")
        .await?;

    // Go to a screen with a long list
    client.find_by(By::accessibility_id("Views"))
        .await?
        .click()
        .await?;

    // Let's calculate some things first
    let (width, height) = client.get_window_size().await?;

    // This is the horizontal center, it will be our x for swipe.
    let horizontal_center = (width / 2) as i64;

    // The swipe will start at 80% of screen height, and end at 20% of screen height.
    // So we will swipe UP through most of the screen.
    let almost_top = (height as f64 * 0.2) as i64;
    let almost_bottom = (height as f64 * 0.8) as i64;

    let swipe_down = TouchActions::new("finger".to_string())
        // position the finger first
        .then(PointerAction::MoveTo {
            duration: Some(Duration::from_millis(0)),
            x: horizontal_center,
            y: almost_bottom,
        })
        // THEN touch the screen
        .then(PointerAction::Down {
            button: MOUSE_BUTTON_LEFT // believe me, it is not a mouse, but a simple touch
        })
        // THEN move the finger through the screen
        .then(PointerAction::MoveTo {
            duration: Some(Duration::from_millis(500)),
            x: horizontal_center,
            y: almost_top,
        });

    client.perform_actions(swipe_down)
        .await?;

    Ok(())
}
More examples
Hide additional examples
examples/find_by.rs (line 23)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Capabilities describe the automation environment,
    // for example: what app are we testing
    let mut capabilities = AndroidCapabilities::new();
    capabilities.app("https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk");

    // To add custom capability that is not supported by this library just use "insert".
    // Alternatively, there are helpful functions like "set_bool", "set_str".
    // You can read more about capabilities on Appium website - https://appium.io/docs/en/2.1/guides/caps/.
    capabilities.set_str("appium:automationName", "uiautomator2");
    capabilities.set_bool("appium:fullReset", true);

    // To start automation, you need to build a client.
    let client = ClientBuilder::native(capabilities)
        .connect("http://localhost:4723/")
        .await?;

    // The app should automatically start, let's print the DOM of current app screen.
    let value = client.source().await?;
    println!("{value}");

    // Screen orientation is another Appium perk
    let orientation = client.orientation().await?;
    println!("Screen orientation: {orientation}");

    // Now we try to locate a button using UiAutomator API.
    // Notice that the program will wait until the button appears on screen (but maximum of 30 seconds).
    let views_button = client
        .appium_wait()
        .for_element(By::uiautomator("new UiSelector().text(\"Views\");"))
        .await?;

    views_button.click().await?;

    // Search for a vec of elements, because we know that there will be more than one result.
    // Notice that this time we don't wait, just find everything that's on screen as is.
    let menu_elements = client
        .find_all_by(By::uiautomator("new UiSelector().className(\"android.widget.TextView\");"))
        .await?;

    menu_elements.get(1)
        .unwrap()
        .click()
        .await?;

    // To add a timeout for wait, use "at_most".
    // "check_every" limits how often Appium has to perform the search during wait.
    //
    // Sometimes it's better to use one or both of those methods, because:
    // 1) We know that something should appear sooner, and if it doesn't, we don't want to wait full 30 seconds.
    // 2) We don't want to slow down Appium server by checking again too often.
    let element = client
        .appium_wait()
        .at_most(Duration::from_secs(20))
        .check_every(Duration::from_millis(500))
        .for_element(By::class_name("android.widget.ListView"))
        .await?;

    // This is a simple search for one element, without waiting for it to appear. And then we click on it.
    // Notice that we are searching for an element inside "element" (which is a ListView).
    element
        .find_by(By::accessibility_id("3D Transition"))
        .await?
        .click()
        .await?;

    Ok(())
}
source§

impl<C, Caps> ClientBuilder<C, Caps>
where C: Connect + Send + Sync + Clone + Unpin + 'static, Caps: AppiumCapability,

source

pub fn new( builder: ClientBuilder<C>, capabilities: Caps ) -> ClientBuilder<C, Caps>

source

pub async fn connect( &self, webdriver: &str ) -> Result<Client<Caps>, NewSessionError>

Examples found in repository?
examples/scroll.rs (line 14)
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut capabilities = AndroidCapabilities::new_uiautomator();
    capabilities.app("https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk");

    let client = ClientBuilder::native(capabilities)
        .connect("http://localhost:4723/")
        .await?;

    // Go to a screen with a long list
    client.find_by(By::accessibility_id("Views"))
        .await?
        .click()
        .await?;

    // Let's calculate some things first
    let (width, height) = client.get_window_size().await?;

    // This is the horizontal center, it will be our x for swipe.
    let horizontal_center = (width / 2) as i64;

    // The swipe will start at 80% of screen height, and end at 20% of screen height.
    // So we will swipe UP through most of the screen.
    let almost_top = (height as f64 * 0.2) as i64;
    let almost_bottom = (height as f64 * 0.8) as i64;

    let swipe_down = TouchActions::new("finger".to_string())
        // position the finger first
        .then(PointerAction::MoveTo {
            duration: Some(Duration::from_millis(0)),
            x: horizontal_center,
            y: almost_bottom,
        })
        // THEN touch the screen
        .then(PointerAction::Down {
            button: MOUSE_BUTTON_LEFT // believe me, it is not a mouse, but a simple touch
        })
        // THEN move the finger through the screen
        .then(PointerAction::MoveTo {
            duration: Some(Duration::from_millis(500)),
            x: horizontal_center,
            y: almost_top,
        });

    client.perform_actions(swipe_down)
        .await?;

    Ok(())
}
More examples
Hide additional examples
examples/find_by.rs (line 24)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Capabilities describe the automation environment,
    // for example: what app are we testing
    let mut capabilities = AndroidCapabilities::new();
    capabilities.app("https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk");

    // To add custom capability that is not supported by this library just use "insert".
    // Alternatively, there are helpful functions like "set_bool", "set_str".
    // You can read more about capabilities on Appium website - https://appium.io/docs/en/2.1/guides/caps/.
    capabilities.set_str("appium:automationName", "uiautomator2");
    capabilities.set_bool("appium:fullReset", true);

    // To start automation, you need to build a client.
    let client = ClientBuilder::native(capabilities)
        .connect("http://localhost:4723/")
        .await?;

    // The app should automatically start, let's print the DOM of current app screen.
    let value = client.source().await?;
    println!("{value}");

    // Screen orientation is another Appium perk
    let orientation = client.orientation().await?;
    println!("Screen orientation: {orientation}");

    // Now we try to locate a button using UiAutomator API.
    // Notice that the program will wait until the button appears on screen (but maximum of 30 seconds).
    let views_button = client
        .appium_wait()
        .for_element(By::uiautomator("new UiSelector().text(\"Views\");"))
        .await?;

    views_button.click().await?;

    // Search for a vec of elements, because we know that there will be more than one result.
    // Notice that this time we don't wait, just find everything that's on screen as is.
    let menu_elements = client
        .find_all_by(By::uiautomator("new UiSelector().className(\"android.widget.TextView\");"))
        .await?;

    menu_elements.get(1)
        .unwrap()
        .click()
        .await?;

    // To add a timeout for wait, use "at_most".
    // "check_every" limits how often Appium has to perform the search during wait.
    //
    // Sometimes it's better to use one or both of those methods, because:
    // 1) We know that something should appear sooner, and if it doesn't, we don't want to wait full 30 seconds.
    // 2) We don't want to slow down Appium server by checking again too often.
    let element = client
        .appium_wait()
        .at_most(Duration::from_secs(20))
        .check_every(Duration::from_millis(500))
        .for_element(By::class_name("android.widget.ListView"))
        .await?;

    // This is a simple search for one element, without waiting for it to appear. And then we click on it.
    // Notice that we are searching for an element inside "element" (which is a ListView).
    element
        .find_by(By::accessibility_id("3D Transition"))
        .await?
        .click()
        .await?;

    Ok(())
}

Auto Trait Implementations§

§

impl<C, Caps> RefUnwindSafe for ClientBuilder<C, Caps>
where C: RefUnwindSafe, Caps: RefUnwindSafe,

§

impl<C, Caps> Send for ClientBuilder<C, Caps>
where Caps: Send,

§

impl<C, Caps> Sync for ClientBuilder<C, Caps>
where Caps: Sync,

§

impl<C, Caps> Unpin for ClientBuilder<C, Caps>
where Caps: Unpin,

§

impl<C, Caps> UnwindSafe for ClientBuilder<C, Caps>
where C: UnwindSafe, Caps: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more