appium_client/commands/
rotation.rs

1//! Device orientation and rotation
2use std::fmt::{Display, Formatter};
3use async_trait::async_trait;
4use fantoccini::error::CmdError;
5use http::Method;
6use serde::Deserialize;
7use serde_derive::Serialize;
8use serde_json::{json, Map, Value};
9use crate::{AndroidClient, AppiumClientTrait, IOSClient};
10use crate::commands::AppiumCommand;
11
12
13#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
14#[serde(rename_all = "UPPERCASE")]
15pub enum Orientation {
16    Landscape,
17    Portrait,
18}
19
20impl Display for Orientation {
21    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22        write!(f, "{:?}", self)
23    }
24}
25
26#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
27pub struct DeviceRotation {
28    x: u16,
29    y: u16,
30    z: u16,
31}
32
33impl DeviceRotation {
34    pub fn new(x: u16, y: u16, z: u16) -> Result<DeviceRotation, CmdError> {
35        for (name, value) in [("x", x), ("y", y), ("z", z)] {
36            if value >= 360 {
37                return Err(CmdError::InvalidArgument(
38                    name.to_string(),
39                    format!("{value} should be less than 360 deg.")
40                ))
41            }
42        }
43
44        Ok(DeviceRotation {
45            x, y, z
46        })
47    }
48}
49
50/// Get or set orientation and rotation of device
51#[async_trait]
52pub trait SupportsRotation : AppiumClientTrait {
53    async fn orientation(&self) -> Result<Orientation, CmdError> {
54        let value = self.issue_cmd(AppiumCommand::Custom(
55            Method::GET, "orientation".to_string(), None
56        )).await?;
57        Ok(serde_json::from_value(value.clone())?)
58    }
59
60    async fn set_orientation(&self, orientation: Orientation) -> Result<Orientation, CmdError> {
61        self.issue_cmd(AppiumCommand::Custom(
62            Method::POST, "orientation".to_string(), Some(json!({
63                "orientation": orientation
64            }))
65        )).await?;
66
67        Ok(orientation)
68    }
69
70    async fn rotation(&self) -> Result<DeviceRotation, CmdError> {
71        let value = self.issue_cmd(AppiumCommand::Custom(Method::GET, "rotation".to_string(), None)).await?;
72        let rotation: DeviceRotation = serde_json::from_value(value.clone())?;
73        Ok(rotation)
74    }
75
76    async fn set_rotation(&self, rotation: DeviceRotation) -> Result<DeviceRotation, CmdError> {
77        let mut map: Map<String, Value> = Map::new();
78        map.insert("x".to_string(), rotation.x.into());
79        map.insert("y".to_string(), rotation.y.into());
80        map.insert("z".to_string(), rotation.z.into());
81
82        self.issue_cmd(AppiumCommand::Custom(
83            Method::POST, "rotation".to_string(), Some(Value::Object(map))
84        )).await?;
85
86        Ok(rotation)
87    }
88}
89
90#[async_trait]
91impl SupportsRotation for AndroidClient {}
92
93#[async_trait]
94impl SupportsRotation for IOSClient {}