| 130 | } |
| 131 | |
| 132 | fn run_maestro_command( |
| 133 | server_url: &str, |
| 134 | udid: &str, |
| 135 | command: &YamlValue, |
| 136 | artifacts_dir: &Path, |
| 137 | ) -> anyhow::Result<Value> { |
| 138 | let null_value = YamlValue::Null; |
| 139 | let (name, value) = if let Some(name) = command.as_str() { |
| 140 | (name, &null_value) |
| 141 | } else { |
| 142 | let Some(mapping) = command.as_mapping() else { |
| 143 | anyhow::bail!("Maestro command must be a string or mapping."); |
| 144 | }; |
| 145 | if mapping.len() != 1 { |
| 146 | anyhow::bail!("Maestro command must contain exactly one action."); |
| 147 | } |
| 148 | let (name, value) = mapping.iter().next().unwrap(); |
| 149 | ( |
| 150 | name.as_str() |
| 151 | .ok_or_else(|| anyhow::anyhow!("Maestro command name must be a string."))?, |
| 152 | value, |
| 153 | ) |
| 154 | }; |
| 155 | match name { |
| 156 | "launchApp" => { |
| 157 | let bundle_id = maestro_bundle_id(value)?; |
| 158 | service_launch(server_url, udid, &bundle_id)?; |
| 159 | Ok(serde_json::json!({ "bundleId": bundle_id })) |
| 160 | } |
| 161 | "openLink" => { |
| 162 | let url = yaml_string_or_field(value, "link") |
| 163 | .or_else(|| yaml_string_or_field(value, "url")) |
| 164 | .ok_or_else(|| anyhow::anyhow!("openLink requires a URL."))?; |
| 165 | service_open_url(server_url, udid, &url)?; |
| 166 | Ok(serde_json::json!({ "url": url })) |
| 167 | } |
| 168 | "tapOn" => { |
| 169 | let body = maestro_tap_body(value)?; |
| 170 | service_tap_element(server_url, udid, body)?; |
| 171 | Ok(Value::Null) |
| 172 | } |
| 173 | "inputText" => { |
| 174 | let text = yaml_string_or_field(value, "text") |
| 175 | .ok_or_else(|| anyhow::anyhow!("inputText requires text."))?; |
| 176 | service_action_ok( |
| 177 | server_url, |
| 178 | udid, |
| 179 | &serde_json::json!({ "action": "type", "text": text }), |
| 180 | )?; |
| 181 | Ok(Value::Null) |
| 182 | } |
| 183 | "eraseText" => { |
| 184 | let count = yaml_u64_or_field(value, "charactersToErase").unwrap_or(64); |
| 185 | let keys = vec![42u16; count as usize]; |
| 186 | service_key_sequence(server_url, udid, &keys, 5)?; |
| 187 | Ok(serde_json::json!({ "charactersToErase": count })) |
| 188 | } |
| 189 | "pressKey" => { |