1
//! Commodity-convert submit and reply handling for `App`.
2

            
3
use cli_core::eval::{build_convert_amount_form, parse_scalar_reply};
4

            
5
use crate::app::App;
6
use crate::route::RouteCtx;
7
use crate::view::ViewId;
8

            
9
impl App {
10
    /// Submit a `convert-amount` query.
11
    ///
12
    /// Returns `false` only when the eval worker has stopped.
13
1
    pub fn submit_commodity_convert(
14
1
        &mut self,
15
1
        amount_num_denom: &str,
16
1
        amount_str: &str,
17
1
        from: &str,
18
1
        from_label: &str,
19
1
        to: &str,
20
1
        to_label: &str,
21
1
    ) -> bool {
22
1
        let form = build_convert_amount_form(amount_num_denom, from, to);
23
1
        if self.console_eval.is_none() {
24
1
            self.status = "console not connected".to_string();
25
1
            return false;
26
        }
27
        match self.dispatch_eval(
28
            ViewId::Commodities,
29
            RouteCtx::ConvertQuery {
30
                amount_str: amount_str.to_string(),
31
                from_label: from_label.to_string(),
32
                to_label: to_label.to_string(),
33
            },
34
            form,
35
        ) {
36
            Some(_) => true,
37
            None => {
38
                self.status = "eval worker stopped".to_string();
39
                false
40
            }
41
        }
42
1
    }
43

            
44
    /// Handle a `convert-amount` reply by formatting a status message.
45
1
    pub(super) fn deliver_convert_reply(
46
1
        &mut self,
47
1
        wire: &str,
48
1
        amount_str: &str,
49
1
        from_label: &str,
50
1
        to_label: &str,
51
1
    ) {
52
1
        match parse_scalar_reply(wire) {
53
            Ok(result) => {
54
                self.status = format!("{amount_str} {from_label} = {result} {to_label}");
55
            }
56
1
            Err(e) => self.status = format!("convert failed: {e}"),
57
        }
58
1
    }
59
}
60

            
61
#[cfg(test)]
62
mod tests {
63
    use super::*;
64
    use crate::widgets::EditMode;
65
    use sqlx::types::Uuid;
66

            
67
2
    fn make_app() -> App {
68
2
        App::new(Uuid::new_v4(), EditMode::Emacs)
69
2
    }
70

            
71
    #[test]
72
1
    fn submit_commodity_convert_without_eval_sets_status() {
73
1
        let mut app = make_app();
74
1
        let ok = app.submit_commodity_convert("9/2", "9/2", "uuid-from", "USD", "uuid-to", "EUR");
75
1
        assert!(!ok, "no eval worker → returns false");
76
1
        assert_eq!(app.status, "console not connected");
77
1
    }
78

            
79
    #[test]
80
1
    fn deliver_convert_reply_error_wire_sets_status() {
81
1
        let mut app = make_app();
82
1
        let wire = r#"(:id 1 :error (:code convert-error :message "no price found"))"#;
83
1
        app.deliver_convert_reply(wire, "9/2", "USD", "EUR");
84
1
        assert!(
85
1
            app.status.contains("convert failed"),
86
            "error reply sets descriptive status: {}",
87
            app.status
88
        );
89
1
    }
90
}