By

Enum By 

Source
pub enum By {
Show 14 variants Id(String), Name(String), Xpath(String), UiAutomator(String), AndroidDataMatcher(String), AndroidViewMatcher(String), AndroidViewTag(String), IosClassChain(String), IosNsPredicate(String), AccessibilityId(String), ClassName(String), Image(String), Custom(String), CustomKind(String, String),
}
Expand description

Locators supported by Appium

If you wish to use your very own locator (e.g. something I didn’t implement in this enum), just use By::CustomKind.

Variants§

§

Id(String)

§

Name(String)

§

Xpath(String)

§

UiAutomator(String)

§

AndroidDataMatcher(String)

§

AndroidViewMatcher(String)

§

AndroidViewTag(String)

§

IosClassChain(String)

§

IosNsPredicate(String)

§

AccessibilityId(String)

§

ClassName(String)

§

Image(String)

§

Custom(String)

§

CustomKind(String, String)

Implementations§

Source§

impl By

Source

pub fn id(id: &str) -> By

Native element identifier. resource-id for android; name for iOS.

Source

pub fn name(name: &str) -> By

Name of element.

Source

pub fn xpath(query: &str) -> By

Search the app XML source using xpath (not recommended, has performance issues).

Source

pub fn uiautomator(query: &str) -> By

Use the UI Automator API, in particular the UiSelector class to locate elements. (UiAutomator2 only).

In Appium you send the Java code, as a string, to the server, which executes it in the application’s environment, returning the element or elements.

See https://developer.android.com/reference/androidx/test/uiautomator/UiSelector

Examples found in repository?
examples/find_by.rs (line 39)
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}
Source

pub fn android_data_matcher(query: &str) -> By

Locate an element using Espresso DataMatcher. (Espresso only)

Source

pub fn android_view_matcher(query: &str) -> By

Locate an element using Espresso ViewMatcher. (Espresso only)

Source

pub fn android_view_tag(query: &str) -> By

Locate an element by its view tag. (Espresso only)

Source

pub fn ios_class_chain(query: &str) -> By

Locate an element by a class chain - a faster, but less powerful alternative to XPath on iOS.

Source

pub fn ios_ns_predicate(query: &str) -> By

A string corresponding to a recursive element search using the iOS Predicate. (iOS 10.0 and above)

Source

pub fn accessibility_id(id: &str) -> By

Read a unique identifier for a UI element.

For XCUITest it is the element’s accessibility-id attribute. For Android it is the element’s content-desc attribute.

Examples found in repository?
examples/scroll.rs (line 18)
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}
More examples
Hide additional examples
examples/find_by.rs (line 71)
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}
Source

pub fn class_name(class_name: &str) -> By

Locate element by its class name.

For IOS it is the full name of the XCUI element and begins with XCUIElementType. For Android it is the full name of the UIAutomator2 class (e.g.: android.widget.TextView)

Examples found in repository?
examples/find_by.rs (line 65)
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}
Source

pub fn image(base64_template: &str) -> By

Locate an element by matching it with a base 64 encoded image file

Source

pub fn custom(query: &str) -> By

Custom locator for use with plugins registered via the customFindModules capability.

Source

pub fn custom_kind(using: &str, value: &str) -> By

A locator for non-standard locators

You can define what type of locator to use, so you’re free to use anything here.

Trait Implementations§

Source§

impl Clone for By

Source§

fn clone(&self) -> By

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for By

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<By> for LocatorParameters

Source§

fn from(val: By) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for By

Source§

fn eq(&self, other: &By) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for By

Source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for By

Auto Trait Implementations§

§

impl Freeze for By

§

impl RefUnwindSafe for By

§

impl Send for By

§

impl Sync for By

§

impl Unpin for By

§

impl UnwindSafe for By

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

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>,

Source§

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