auv-cli-invoke 0.0.22

Application Use Via... script-able OS automation library
use std::collections::BTreeMap;

use super::*;

#[test]
fn every_overlay_primitive_and_component_is_registered_and_dry_run_visualizable() {
  let registry = crate::default_registry();
  let cases = [
    ("overlay.outline", rect_inputs()),
    ("overlay.cursor", point_inputs()),
    ("overlay.status", status_inputs()),
    ("overlay.captureFrame", rect_inputs()),
    ("overlay.clickTarget", click_target_inputs()),
  ];

  for (command_id, inputs) in cases {
    let command = registry.resolve(command_id).unwrap_or_else(|| panic!("{command_id} should be registered"));
    let output = futures_executor::block_on(command.invoke(InvokeCommandInput {
      command_id: command_id.to_string(),
      target: None,
      inputs,
      typed_args: None,
      dry_run: true,
      cancellation: crate::InvokeCancellation::new(),
    }))
    .unwrap_or_else(|error| panic!("{command_id} dry run should build its real overlay: {error}"));

    let report = output.report.expect("debug overlay command should report its composition");
    assert_eq!(report.fields.last().expect("overlay field").value, "disabled");
  }
}

#[test]
fn style_arguments_refine_presets_deterministically() {
  let style = outline_style("overlay.outline", OutlineStyle::selected(), Some(4.0), Some("#7fd030cc"), Some(5.0), Some(12.0))
    .expect("style should parse");

  assert_eq!(style.padding, Insets::all(4.0));
  assert_eq!(style.stroke.width, 5.0);
  assert_eq!(style.stroke.color, Color::rgba(127.0 / 255.0, 208.0 / 255.0, 48.0 / 255.0, 204.0 / 255.0));
  assert_eq!(style.corner_radius, 12.0);
}

#[test]
fn overlay_commands_reject_target_before_native_rendering() {
  let registry = crate::default_registry();
  for (command_id, inputs) in [
    ("overlay.outline", rect_inputs()),
    ("overlay.cursor", point_inputs()),
    ("overlay.status", status_inputs()),
    ("overlay.captureFrame", rect_inputs()),
    ("overlay.clickTarget", click_target_inputs()),
  ] {
    let command = registry.resolve(command_id).expect("registered overlay command");
    let error = futures_executor::block_on(command.invoke(InvokeCommandInput {
      command_id: command_id.to_string(),
      target: Some(crate::ExecutionTarget::Application {
        id: "com.example.App".to_string(),
      }),
      inputs,
      typed_args: None,
      dry_run: false,
      cancellation: crate::InvokeCancellation::new(),
    }))
    .expect_err("target must fail before native rendering");
    assert_eq!(error.code, crate::FailureCode::InvalidTarget);
  }
}

fn rect_inputs() -> BTreeMap<String, String> {
  pairs([
    ("x", "100"),
    ("y", "120"),
    ("width", "240"),
    ("height", "80"),
    ("label", "Target"),
  ])
}

fn point_inputs() -> BTreeMap<String, String> {
  pairs([("x", "100"), ("y", "120"), ("label", "auv · cursor")])
}

fn status_inputs() -> BTreeMap<String, String> {
  pairs([("x", "100"), ("y", "120"), ("text", "processing")])
}

fn click_target_inputs() -> BTreeMap<String, String> {
  pairs([
    ("x", "100"),
    ("y", "120"),
    ("width", "240"),
    ("height", "80"),
    ("outline-label", "Quest Start"),
    ("outline-label-visible", "true"),
    ("cursor-label", "auv · click"),
    ("cursor-label-visible", "false"),
    ("status", "click target"),
  ])
}

fn pairs<const N: usize>(values: [(&str, &str); N]) -> BTreeMap<String, String> {
  values.into_iter().map(|(key, value)| (key.to_string(), value.to_string())).collect()
}