{"id":16537800,"url":"https://github.com/multicatch/appium-client","last_synced_at":"2025-03-21T09:32:17.915Z","repository":{"id":65718345,"uuid":"596926244","full_name":"multicatch/appium-client","owner":"multicatch","description":"Unofficial Rust client for Appium, for automated mobile app testing.","archived":false,"fork":false,"pushed_at":"2024-01-24T10:06:00.000Z","size":4462,"stargazers_count":21,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-18T00:01:27.024Z","etag":null,"topics":["appium","rust","testing"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/appium-client","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/multicatch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-03T08:30:28.000Z","updated_at":"2025-02-26T23:00:14.000Z","dependencies_parsed_at":"2024-01-04T09:50:29.849Z","dependency_job_id":"07bd4b3d-780a-4fc2-9a9a-05a57cf439b6","html_url":"https://github.com/multicatch/appium-client","commit_stats":{"total_commits":17,"total_committers":1,"mean_commits":17.0,"dds":0.0,"last_synced_commit":"3d007ca34b384571f7cbdd2edb1cb887fa4e9c4e"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/multicatch%2Fappium-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/multicatch%2Fappium-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/multicatch%2Fappium-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/multicatch%2Fappium-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/multicatch","download_url":"https://codeload.github.com/multicatch/appium-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244772592,"owners_count":20508020,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appium","rust","testing"],"created_at":"2024-10-11T18:43:29.053Z","updated_at":"2025-03-21T09:32:17.518Z","avatar_url":"https://github.com/multicatch.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# multicatch's appium-client\n\nRust client for Appium Server, for automated mobile app testing. It is based on [fantoccini](https://github.com/jonhoo/fantoccini).\n\nAppium is a tool for automating native app testing. In other words, it's used for simulating user activity in apps.\nYou tell Appium what to look for on a screen and what to click, and Appium does it for you.\n\nAppium is a tool consisting of:\n* **an Appium server** serving Appium API through REST and delegating commands to a driver,\n* **Appium API** which is a unified way to send commands,\n* **Appium driver** which is a library that knows how to communicate with a device you want to control. \n\nThis library is **an Appium client**. Which means it sends commands to the Appium server. \nYou need to set up Appium in order to use this library. \n\nThe documentation mainly focuses on the client aspect of the whole tool. \nSo if you need more info about the Appium server, driver or device setup, please refer to the [Appium docs](https://appium.io/docs/en/2.1/).\n\nAlso check out the [examples](examples).\n\n## Features\n\n- [x] Predefined iOS and Android capabilities (at least some of them).\n- [x] Locking and unlocking screen.\n- [x] Getting the time of the device/emulator.\n- [x] Getting the rotation and orientation of device.\n- [x] Screen recording support.\n- [x] Battery state support.\n- [x] Android network state.\n- [x] Changing device settings.\n- [x] Pushing and pulling files.\n- [x] Getting app strings.\n- [x] Accessing device clipboard.\n- [x] Touch ID and fingerprint authentication simulation.\n- [x] Keyboard simulation.\n- [x] Ability to use unimplemented features and drivers.\n\n# Guides, tutorials and documentation\n\n* [Quick Guide](#quick-guide)\n* [Setup And Writing Your First Automation](SETUP.md)\n* [Documentation](https://multicatch.github.io/appium-client/appium_client/)\n\n# Quick Guide\n\nThis quick guide assumes you know how Appium works. It focuses on a key features of this lib.\nIf you want a more basic guide, see [Setup And Writing Your First Automation](SETUP.md).\n\n## How to use?\n\nYou need to start an [Appium Server](http://appium.io) first. \nYou also need to connect a device (or an emulator) to the machine that runs the Appium Server.\n\nIf you have set up Appium properly, then you can use this library to connect to the server and control the device.\n\nTo connect to the Appium Server, you need to create an instance of a `Client`.\nTo do so, create appropriate [capabilities](https://appium.io/docs/en/2.1/guides/caps/) (e.g. `AndroidCapabilities::new_uiautomator()`) and then supply then to a `ClientBuilder`.\n\nYou need a Tokio async runtime for it to work properly.\n\n```rust\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let mut capabilities = AndroidCapabilities::new_uiautomator();\n    capabilities.app(\"https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk\");\n\n    let client = ClientBuilder::native(capabilities)\n        .connect(\"http://localhost:4723/\")\n        .await?;\n\n    // now you can start testing\n\n    Ok(())\n}\n```\n\nAppium interprets the screen of the device using DOM (Document Object Model).\nElements on the screen are translated into some kind of XML that is compliant with the W3C standard of Selenium.\n\nAppium is some kind of extension to this, with drivers that allow to control mobile devices, emulators or desktop OS.\n\nTo see how Appium interprets the device screen (and to interact with the device using Appium),\nyou can use a tool called [Appium Inspector](https://github.com/appium/appium-inspector).\nIt's a very useful GUI tool that can help during automation development.\n\n## What if there is a missing feature in this lib?\n\nYou can make a PR and add the missing feature. \n\nIf you don't have time for this, you can also issue commands directly, without relying on traits from this library.\n\nFor example, let's assume Appium added a new feature called \"simulate barrel roll on the device\".\nAppium Server has a new API for this - `POST /session/:sessionId/appium/device/barrel_roll`.\nWe can specify how many times the device will do a barrel roll in the request as `{\"times\": number}`.\n\nYou don't have to wait until I add this feature to the library. You can issue a custom command:\n\n```rust\nclient.issue_cmd(AppiumCommand::Custom(\n    Method::POST,\n    \"appium/device/barrel_roll\".to_string(),\n    Some(json!({\n        \"times\": 2\n    }))\n)).await?;\n```\n\nAs you can see, I didn't add `/session/:sessionId` from the original endpoint. \nThere is no need to - the Appium client adds this automatically.\n\n## Sample usage\n\n### Creating the client\n\nCreate Appium client that will be used to issue commands and locate elements.\n\nA client is an object that manages the connection to Appium server and issues commands to it.\nThus, we need capabilities that describe the automation environment and the server URL to create a client.\n\nYou can read more about capabilities in [Appium's docs](https://appium.io/docs/en/2.1/guides/caps/).\n\n```rust\nuse appium_client::ClientBuilder;\nuse appium_client::capabilities::*;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let mut capabilities = AndroidCapabilities::new_uiautomator();\n    capabilities.app(\"https://github.com/appium/android-apidemos/releases/download/v3.1.0/ApiDemos-debug.apk\");\n\n    let client = ClientBuilder::native(capabilities)\n        .connect(\"http://localhost:4723/\")\n        .await?;\n    \n    Ok(())\n}\n```\n\n### Finding an element on screen\n\nLocate an element by using your favorite location strategy (eg. by UiAutomator 2).\n\nOther strategies, like name, XPath, iOS Class Chain etc. are also supported.\n\n```rust\n// you need this to use Appium locators with fantoccini's Client\nuse appium_client::find::{AppiumFind, By};\n\nlet element = client\n    .find_by(By::accessibility_id(\"Click this\"))\n    .await?;\n\nelement.click().await?;\n```\n\n### Waiting for an element to appear\n\nYou can wait for element if it does not appear immediately on screen.\n\nThe wait, by default, is 30 seconds.\nDuring the wait, the client performs a search every 250 ms until the element finally appears, or it hits the timeout.\n\n```rust\n// you need these to use Appium-enhanced wait with fantoccini's Client\nuse appium_client::find::{AppiumFind, By};\nuse appium_client::wait::AppiumWait;\n\nlet element = client\n    .appium_wait()\n    .for_element(By::uiautomator(\"new UiSelector().className(\\\"android.widget.ImageView\\\");\"))\n    .await?;\n\nelement.click().await?;\n```\n\n### Limiting the wait\n\nYou can define how long to wait for the element and how often to check if it's already appeared.\n\nThis is useful in situations when you know something should appear sooner. \nAnd if it doesn't, then something else happened, and you don't want to bother waiting full 30 seconds until timeout.\n\nThe search interval may be also too adjusted so that the Appium server has more time to breathe.\n\n```rust\n// you need these to use Appium-enhanced wait with fantoccini's Client\nuse appium_client::find::{AppiumFind, By};\nuse appium_client::wait::AppiumWait;\n\nlet element = client\n    .appium_wait()\n    .at_most(Duration::from_secs(20))\n    .check_every(Duration::from_millis(500))\n    .for_element(By::uiautomator(\"new UiSelector().className(\\\"android.widget.ImageView\\\");\"))\n    .await?;\n\nelement.click().await?;\n```\n\n### Locating many elements\n\nTo locate multiple elements, use `find_all_by` or `.appium_wait().for_elements(..)`.\n\nThe first method works just like `find_by` - it yields results immediately.\nThe second one just waits given time until at least one element appears. It works like the above example.\n\n```rust\n// you need these to use Appium-enhanced wait with fantoccini's Client\nuse appium_client::find::{AppiumFind, By};\nuse appium_client::wait::AppiumWait;\n\nlet result = client\n    .appium_wait()\n    .for_elements(By::class_name(\"android.widget.LinearLayout\"))\n    .await?;\n\nresult.first().unwrap().click().await?;\n```\n\n### Nested search\n\nYou can also perform search inside elements you found.\n\nIt is useful in cases when you want to find the parent element first, and then find a specific child inside.\nNo matter how bizarre that sounds, it is a useful feature when working with DOM.\n\n```rust\n// you need this to use Appium locators with fantoccini's Client\nuse appium_client::find::{AppiumFind, By};\n\nlet element = client\n    .find_by(By::accessibility_id(\"Click this\"))\n    .await?;\n\n// now let's find a child of element\nlet image_child = element\n    .find_by(By::class_name(\"android.widget.ImageButton\"))\n    .await?;\n```\n\n### Scrolling\n\nTo scroll, you can use touch actions. For example, let's scroll up by simulating a swipe.\n\nRemember that the swipe will \"pull\" the screen, so you need to swipe down to \"pull\" the screen down, revealing top content.\n\n```rust\n    let swipe_down = TouchActions::new(\"finger\".to_string())\n        // position the finger first\n        .then(PointerAction::MoveTo {\n            duration: Some(Duration::from_millis(0)),\n            x,\n            y\n        })\n        // THEN touch the screen\n        .then(PointerAction::Down {\n            button: MOUSE_BUTTON_LEFT // believe me, it is not a mouse, but a simple touch\n        })\n        // THEN move the finger through the screen\n        .then(PointerAction::MoveTo {\n            duration: Some(Duration::from_millis(500)),\n            x,\n            y\n        });\n\n    client.perform_actions(swipe_down)\n        .await?;\n```\n\n## Examples\n\n- [See find_by example here.](examples/find_by.rs)\n- [Scrolling example here.](examples/scroll.rs)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmulticatch%2Fappium-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmulticatch%2Fappium-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmulticatch%2Fappium-client/lists"}