use std::collections::HashMap;
use serde::Serialize;
use crate::button::ButtonLabel;
use crate::wizard::WizardResult;
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(untagged)]
pub enum CommandResult {
Chrome(ChromeResult),
Message(MessageResult),
Markdown(MarkdownResult),
Input(InputResult),
Question(QuestionResult),
Wizard(WizardResult),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct ChromeResult {
pub button: ButtonLabel,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct MessageResult {
pub button: ButtonLabel,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct MarkdownResult {
pub button: ButtonLabel,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(untagged)]
pub enum InputValue {
Text(String),
Paths(Vec<String>),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct InputResult {
pub button: ButtonLabel,
#[serde(skip_serializing_if = "Option::is_none")]
pub input: Option<InputValue>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct QuestionResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub button: Option<ButtonLabel>,
pub questions: Vec<serde_json::Value>,
pub answers: HashMap<String, String>,
pub response: String,
}
impl QuestionResult {
pub fn submitted(questions: Vec<serde_json::Value>, answers: HashMap<String, String>) -> Self {
Self {
button: None,
questions,
answers,
response: String::new(),
}
}
pub fn dismissed(questions: Vec<serde_json::Value>) -> Self {
Self {
button: Some(ButtonLabel::dismissed()),
questions,
answers: HashMap::new(),
response: String::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn command_result_chrome_wire_shape() {
let result = CommandResult::Chrome(ChromeResult {
button: ButtonLabel::dismissed(),
});
let json = serde_json::to_string(&result).expect("serialize");
assert_eq!(json, r#"{"button":"dismissed"}"#);
}
#[test]
fn command_result_message_wire_shape() {
let result = CommandResult::Message(MessageResult {
button: ButtonLabel::new("ok"),
});
let json = serde_json::to_string(&result).expect("serialize");
assert_eq!(json, r#"{"button":"ok"}"#);
}
#[test]
fn command_result_markdown_wire_shape() {
let result = CommandResult::Markdown(MarkdownResult {
button: ButtonLabel::new("ok"),
});
let json = serde_json::to_string(&result).expect("serialize");
assert_eq!(json, r#"{"button":"ok"}"#);
}
#[test]
fn command_result_input_ok_with_text() {
let result = CommandResult::Input(InputResult {
button: ButtonLabel::new("ok"),
input: Some(InputValue::Text("Ada Lovelace".into())),
});
let json = serde_json::to_string(&result).expect("serialize");
assert_eq!(json, r#"{"button":"ok","input":"Ada Lovelace"}"#);
}
#[test]
fn command_result_input_cancel_omits_input() {
let result = CommandResult::Input(InputResult {
button: ButtonLabel::new("cancel"),
input: None,
});
let json = serde_json::to_string(&result).expect("serialize");
assert_eq!(json, r#"{"button":"cancel"}"#);
}
#[test]
fn command_result_input_dismissed_omits_input() {
let result = CommandResult::Input(InputResult {
button: ButtonLabel::dismissed(),
input: None,
});
let json = serde_json::to_string(&result).expect("serialize");
assert_eq!(json, r#"{"button":"dismissed"}"#);
}
#[test]
fn command_result_input_ok_with_paths_array() {
let result = CommandResult::Input(InputResult {
button: ButtonLabel::new("ok"),
input: Some(InputValue::Paths(vec![
"fixtures/a.json".into(),
"fixtures/b.json".into(),
])),
});
let json = serde_json::to_string(&result).expect("serialize");
assert_eq!(
json,
r#"{"button":"ok","input":["fixtures/a.json","fixtures/b.json"]}"#
);
}
#[test]
fn command_result_question_submitted_omits_button() {
let mut answers = HashMap::new();
answers.insert("Output format?".into(), "JSON".into());
let questions = vec![serde_json::json!({
"question": "Output format?",
"header": "Format",
"options": [
{ "label": "JSON", "description": "Structured" },
{ "label": "Plain", "description": "Text only" }
],
"multiSelect": false
})];
let result = CommandResult::Question(QuestionResult::submitted(questions, answers));
let value: serde_json::Value =
serde_json::from_str(&serde_json::to_string(&result).unwrap()).unwrap();
assert!(value.get("button").is_none());
assert_eq!(value["answers"]["Output format?"], "JSON");
assert_eq!(value["response"], "");
assert!(value["questions"].is_array());
}
#[test]
fn command_result_question_dismissed_includes_button() {
let questions = vec![serde_json::json!({"question": "Q?", "header": "H"})];
let result = CommandResult::Question(QuestionResult::dismissed(questions));
let value: serde_json::Value =
serde_json::from_str(&serde_json::to_string(&result).unwrap()).unwrap();
assert_eq!(value["button"], "dismissed");
assert_eq!(value["answers"], serde_json::json!({}));
assert_eq!(value["response"], "");
}
}