Skip to main content

doctest_support/
lib.rs

1#![allow(clippy::unsafe_derive_deserialize)]
2//! This is support code for doc tests
3
4pub mod basic_delay;
5pub mod delay;
6
7pub mod command {
8    use crux_core::{Request, capability::Operation};
9    use serde::{Deserialize, Serialize};
10
11    #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
12    pub enum AnOperation {
13        One(u8),
14        Two(u8),
15    }
16
17    #[derive(Debug, PartialEq, Eq, Deserialize)]
18    pub enum AnOperationOutput {
19        One(u8),
20        Two(u8),
21    }
22
23    impl Operation for AnOperation {
24        type Output = AnOperationOutput;
25    }
26
27    pub enum Effect {
28        AnEffect(Request<AnOperation>),
29        Http(Request<crux_http::protocol::HttpRequest>),
30        Render(Request<crux_core::render::RenderOperation>),
31    }
32
33    impl From<Request<AnOperation>> for Effect {
34        fn from(request: Request<AnOperation>) -> Self {
35            Self::AnEffect(request)
36        }
37    }
38
39    impl From<Request<crux_http::protocol::HttpRequest>> for Effect {
40        fn from(request: Request<crux_http::protocol::HttpRequest>) -> Self {
41            Self::Http(request)
42        }
43    }
44
45    impl From<Request<crux_core::render::RenderOperation>> for Effect {
46        fn from(request: Request<crux_core::render::RenderOperation>) -> Self {
47            Self::Render(request)
48        }
49    }
50
51    #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
52    pub struct Post {
53        pub url: String,
54        pub title: String,
55        pub body: String,
56    }
57
58    #[derive(Debug, PartialEq, Eq)]
59    pub enum Event {
60        Start,
61        Completed(AnOperationOutput),
62        Aborted,
63        GotPost(Result<crux_http::Response<Post>, crux_http::HttpError>),
64    }
65
66    #[cfg(test)]
67    mod tests {
68        use crux_http::{
69            command::Http,
70            protocol::{HttpRequest, HttpResponse, HttpResult},
71            testing::ResponseBuilder,
72        };
73
74        use crate::command::{Effect, Event, Post};
75
76        #[test]
77        fn http_post() {
78            const API_URL: &str = "https://example.com/api/posts";
79
80            // Create a command to post a new Post to API_URL
81            // and then dispatch an event with the result
82            let mut cmd = Http::post(API_URL)
83                .body(serde_json::json!({"title":"New Post", "body":"Hello!"}))
84                .expect_json()
85                .build()
86                .then_send(Event::GotPost);
87
88            // Check the effect is an HTTP request ...
89            let effect = cmd.effects().next().unwrap();
90            let Effect::Http(mut request) = effect else {
91                panic!("Expected a HTTP effect")
92            };
93
94            // ... and the request is a POST to API_URL
95            assert_eq!(
96                &request.operation,
97                &HttpRequest::post(API_URL)
98                    .header("content-type", "application/json")
99                    .body(r#"{"body":"Hello!","title":"New Post"}"#)
100                    .build()
101            );
102
103            // Resolve the request with a successful response
104            let body = Post {
105                url: API_URL.to_string(),
106                title: "New Post".to_string(),
107                body: "Hello!".to_string(),
108            };
109            request
110                .resolve(HttpResult::Ok(HttpResponse::ok().json(&body).build()))
111                .expect("Resolve should succeed");
112
113            // Check the event is a GotPost event with the successful response
114            let actual = cmd.events().next().unwrap();
115            let expected = Event::GotPost(Ok(ResponseBuilder::ok().body(body).build()));
116            assert_eq!(actual, expected);
117
118            assert!(cmd.is_done());
119        }
120    }
121}