agy_bridge/hooks/
interactive.rs1use serde::{Deserialize, Serialize};
4
5use super::types::HookResult;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct AskQuestionOption {
14 pub label: String,
16 pub value: String,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
24pub struct AskQuestionEntry {
25 pub question: String,
27 pub options: Vec<AskQuestionOption>,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
36pub struct AskQuestionInteractionSpec {
37 pub entries: Vec<AskQuestionEntry>,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45pub struct QuestionResponse {
46 pub answers: Vec<String>,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct QuestionHookResult {
59 pub hook_result: HookResult,
61 pub response: Option<QuestionResponse>,
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn ask_question_option_serde_roundtrip() {
71 let opt = AskQuestionOption {
72 label: "Yes".into(),
73 value: "y".into(),
74 };
75 let json = serde_json::to_string(&opt).unwrap();
76 let parsed: AskQuestionOption = serde_json::from_str(&json).unwrap();
77 assert_eq!(parsed, opt);
78 }
79
80 #[test]
81 fn ask_question_entry_serde_roundtrip() {
82 let entry = AskQuestionEntry {
83 question: "Continue?".into(),
84 options: vec![
85 AskQuestionOption {
86 label: "Yes".into(),
87 value: "y".into(),
88 },
89 AskQuestionOption {
90 label: "No".into(),
91 value: "n".into(),
92 },
93 ],
94 };
95 let json = serde_json::to_string(&entry).unwrap();
96 let parsed: AskQuestionEntry = serde_json::from_str(&json).unwrap();
97 assert_eq!(parsed, entry);
98 }
99
100 #[test]
101 fn ask_question_interaction_spec_serde_roundtrip() {
102 let spec = AskQuestionInteractionSpec {
103 entries: vec![
104 AskQuestionEntry {
105 question: "Q1?".into(),
106 options: vec![AskQuestionOption {
107 label: "A".into(),
108 value: "a".into(),
109 }],
110 },
111 AskQuestionEntry {
112 question: "Q2?".into(),
113 options: vec![],
114 },
115 ],
116 };
117 let json = serde_json::to_string(&spec).unwrap();
118 let parsed: AskQuestionInteractionSpec = serde_json::from_str(&json).unwrap();
119 assert_eq!(parsed, spec);
120 }
121
122 #[test]
123 fn question_response_serde_roundtrip() {
124 let resp = QuestionResponse {
125 answers: vec!["yes".into(), "fast".into()],
126 };
127 let json = serde_json::to_string(&resp).unwrap();
128 let parsed: QuestionResponse = serde_json::from_str(&json).unwrap();
129 assert_eq!(parsed, resp);
130 }
131
132 #[test]
133 fn question_hook_result_with_response() {
134 let result = QuestionHookResult {
135 hook_result: HookResult::allow_with_message("confirmed"),
136 response: Some(QuestionResponse {
137 answers: vec!["answer1".into()],
138 }),
139 };
140 let json = serde_json::to_string(&result).unwrap();
141 let parsed: QuestionHookResult = serde_json::from_str(&json).unwrap();
142 assert_eq!(parsed.hook_result, result.hook_result);
143 assert!(parsed.response.is_some());
144 }
145
146 #[test]
147 fn question_hook_result_without_response() {
148 let result = QuestionHookResult {
149 hook_result: HookResult::deny("cancelled"),
150 response: None,
151 };
152 let json = serde_json::to_string(&result).unwrap();
153 let parsed: QuestionHookResult = serde_json::from_str(&json).unwrap();
154 assert!(!parsed.hook_result.allow);
155 assert!(parsed.response.is_none());
156 }
157}