1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
#![forbid(unsafe_code, future_incompatible)] #![deny( missing_debug_implementations, nonstandard_style, missing_copy_implementations, unused_qualifications )] //! # Tide Testing Extension Trait //! //! This trait provides an ergonomic extension for testing tide applications. //! //! ## Usage: //! //! `$ cargo add -D tide-testing` //! //! ## Examples //! //! ```rust //! # fn main() -> tide::Result<()> { async_std::task::block_on(async { //! let mut app = tide::new(); //! app.at("/").get(|_| async { Ok("hello!") }); //! //! use tide_testing::TideTestingExt; //! assert_eq!(app.get("/").recv_string().await?, "hello!"); //! assert_eq!( //! app.post("/missing").await?.status(), //! tide::http::StatusCode::NotFound //! ); //! # Ok(()) }) } //! ``` //! //! Note that the http methods return [`surf::RequestBuilder`]s, allowing tests to build up complex requests fluently: //! //! ```rust //! # fn main() -> tide::Result<()> { async_std::task::block_on(async { //! use tide::prelude::*; //! let mut app = tide::new(); //! app.at("/complex_example") //! .put(|mut request: tide::Request<()>| async move { //! Ok(json!({ //! "content_type": request.content_type().map(|c| c.to_string()), //! "body": request.body_string().await?, //! "header": request.header("custom").map(|h| h.as_str()) //! })) //! }); //! //! use tide_testing::TideTestingExt; //! //! let response_body: serde_json::value::Value = app //! .put("/complex_example") //! .body(tide::Body::from_string("hello".into())) //! .content_type("application/custom") //! .header("custom", "header-value") //! .recv_json() //! .await?; //! //! assert_eq!( //! response_body, //! json!({ //! "content_type": Some("application/custom"), //! "body": "hello", //! "header": Some("header-value") //! }) //! ); //! # Ok(()) }) } //! ``` pub use surf; use surf::http::Url; use surf::Client; use tide::Server; macro_rules! method { ($method:ident) => { fn $method(&self, url: impl AsRef<str>) -> surf::RequestBuilder { self.client().$method(url.as_ref()) } }; } macro_rules! methods { ($($method:ident),* $(,)?) => {$(method!($method);)+} } pub trait TideTestingExt { fn client(&self) -> Client; methods!(get, put, post, delete, head, connect, options, trace, patch); } impl<State: Unpin + Clone + Send + Sync + 'static> TideTestingExt for Server<State> { fn client(&self) -> Client { let mut client = Client::with_http_client(self.clone()); client.set_base_url(Url::parse("http://example.com/").unwrap()); client } }