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)]
8
pub 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)]
20
mod tests {
21
    use super::*;
22

            
23
    #[test]
24
1
    fn idle_is_default_variant() {
25
1
        let f: Fetch<Vec<String>> = Fetch::Idle;
26
1
        assert!(matches!(f, Fetch::Idle));
27
1
    }
28

            
29
    #[test]
30
1
    fn loading_carries_id() {
31
1
        let f: Fetch<()> = Fetch::Loading { id: 7 };
32
1
        assert!(matches!(f, Fetch::Loading { id: 7 }));
33
1
    }
34

            
35
    #[test]
36
1
    fn loaded_carries_data() {
37
1
        let f = Fetch::Loaded(vec![1u32, 2, 3]);
38
1
        assert!(matches!(f, Fetch::Loaded(_)));
39
1
        if let Fetch::Loaded(v) = f {
40
1
            assert_eq!(v.len(), 3);
41
        }
42
1
    }
43

            
44
    #[test]
45
1
    fn error_carries_message() {
46
1
        let f: Fetch<()> = Fetch::Error("oops".into());
47
1
        assert!(matches!(f, Fetch::Error(ref s) if s == "oops"));
48
1
    }
49

            
50
    #[test]
51
1
    fn clone_eq_roundtrip() {
52
1
        let a: Fetch<()> = Fetch::Loading { id: 42 };
53
1
        let b = a.clone();
54
1
        assert_eq!(a, b);
55
1
    }
56
}