Skip to main content

tui/tabs/
fetch.rs

1//! Generic fetch-state machine for data tabs.
2
3/// Lifecycle of a data-tab fetch request.
4///
5/// Transitions: `Idle` → `Loading` (on submit) → `Loaded` or `Error` (on reply).
6/// A `refresh` resets back to `Idle` so the next `switch_tab` re-fetches.
7#[derive(Debug, Clone, PartialEq)]
8pub enum Fetch<T> {
9    /// No request has been issued yet (initial state or after reset).
10    Idle,
11    /// A request was issued with the given envelope id; reply is pending.
12    Loading { id: i64 },
13    /// Reply received and parsed successfully.
14    Loaded(T),
15    /// Reply received but produced an error.
16    Error(String),
17}
18
19#[cfg(test)]
20mod tests {
21    use super::*;
22
23    #[test]
24    fn idle_is_default_variant() {
25        let f: Fetch<Vec<String>> = Fetch::Idle;
26        assert!(matches!(f, Fetch::Idle));
27    }
28
29    #[test]
30    fn loading_carries_id() {
31        let f: Fetch<()> = Fetch::Loading { id: 7 };
32        assert!(matches!(f, Fetch::Loading { id: 7 }));
33    }
34
35    #[test]
36    fn loaded_carries_data() {
37        let f = Fetch::Loaded(vec![1u32, 2, 3]);
38        assert!(matches!(f, Fetch::Loaded(_)));
39        if let Fetch::Loaded(v) = f {
40            assert_eq!(v.len(), 3);
41        }
42    }
43
44    #[test]
45    fn error_carries_message() {
46        let f: Fetch<()> = Fetch::Error("oops".into());
47        assert!(matches!(f, Fetch::Error(ref s) if s == "oops"));
48    }
49
50    #[test]
51    fn clone_eq_roundtrip() {
52        let a: Fetch<()> = Fetch::Loading { id: 42 };
53        let b = a.clone();
54        assert_eq!(a, b);
55    }
56}