From 70a95f87bf85d100fb8a332563c9b39dfff9e6fc Mon Sep 17 00:00:00 2001 From: Henry Zimmerman Date: Mon, 30 Sep 2019 19:06:04 -0400 Subject: [PATCH] Fix Doc Tests (#674) * fix doc tests * fix tests for non-default format types * make fetch example representative of using JSON * add doc tests to ci * clean up fetch docs * update blurb above a fetch example * minor grammar fix --- ci/run_tests.sh | 3 + src/components/select.rs | 20 +++++- src/format/cbor.rs | 6 +- src/format/json.rs | 4 +- src/format/msgpack.rs | 7 +- src/format/toml.rs | 6 +- src/format/yaml.rs | 7 +- src/html/mod.rs | 102 ++++++++++++++++++++++++--- src/lib.rs | 5 +- src/services/fetch.rs | 148 ++++++++++++++++++++++++++++----------- 10 files changed, 249 insertions(+), 59 deletions(-) diff --git a/ci/run_tests.sh b/ci/run_tests.sh index 6bba2d2f6..df517a4c4 100755 --- a/ci/run_tests.sh +++ b/ci/run_tests.sh @@ -32,6 +32,9 @@ cargo test --test macro_test echo "Testing derive props macro..." cargo test --test derive_props_test +echo "Testing docs" +cargo test --doc + echo "Testing macro docs..." (cd crates/macro && cargo test) diff --git a/src/components/select.rs b/src/components/select.rs index 3b1dc6b76..052db641f 100644 --- a/src/components/select.rs +++ b/src/components/select.rs @@ -3,17 +3,35 @@ //! helps you to track selected value in an original type. Example: //! //! ``` +//!# use yew::{Html, Component, components::Select, ComponentLink, Renderable, html}; +//!# struct Model; +//!# impl Component for Model { +//!# type Message = ();type Properties = (); +//!# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} +//!# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} +//!# } +//!# impl Renderable for Model {fn view(&self) -> Html {unimplemented!()}} +//! #[derive(PartialEq, Clone)] //! enum Scene { //! First, //! Second, //! } +//! impl ToString for Scene { +//! fn to_string(&self) -> String { +//! match self { +//! Scene::First => "First".to_string(), +//! Scene::Second => "Second".to_string() +//! } +//! } +//! } //! //! fn view() -> Html { //! let scenes = vec![Scene::First, Scene::Second]; //! html! { -//! options=scenes /> +//! options=scenes onchange=|_| () /> //! } //! } +//! ``` use crate::callback::Callback; use crate::html::{ChangeData, Component, ComponentLink, Html, Renderable, ShouldRender}; diff --git a/src/format/cbor.rs b/src/format/cbor.rs index 8fcbfb329..7705f7425 100644 --- a/src/format/cbor.rs +++ b/src/format/cbor.rs @@ -5,12 +5,16 @@ use serde_cbor; /// A representation of a CBOR data. Use it as wrapper to /// set a format you want to use for conversion: /// -/// ```rust +/// ``` /// // Converts (lazy) data to a Cbor +///# use yew::format::Cbor; +///# fn dont_execute() { +///# let data: String = unimplemented!(); /// let dump = Cbor(&data); /// /// // Converts CBOR string to a data (lazy). /// let Cbor(data) = dump; +///# } /// ``` pub struct Cbor(pub T); diff --git a/src/format/json.rs b/src/format/json.rs index f034afb9a..9bed4ad38 100644 --- a/src/format/json.rs +++ b/src/format/json.rs @@ -3,8 +3,10 @@ /// A representation of a JSON data. Use it as wrapper to /// set a format you want to use for conversion: /// -/// ```rust +/// ``` /// // Converts (lazy) data to a Json +/// use yew::format::Json; +/// let data: String = r#"{lorem: "ipsum"}"#.to_string(); /// let dump = Json(&data); /// /// // Converts JSON string to a data (lazy). diff --git a/src/format/msgpack.rs b/src/format/msgpack.rs index ecfa071bf..355d47c23 100644 --- a/src/format/msgpack.rs +++ b/src/format/msgpack.rs @@ -5,12 +5,17 @@ use rmp_serde; /// A representation of a MessagePack data. Use it as wrapper to /// set a format you want to use for conversion: /// -/// ```rust +/// ``` /// // Converts (lazy) data to a MsgPack +/// +///# use yew::format::MsgPack; +///# fn dont_execute() { +///# let data: String = unimplemented!(); /// let dump = MsgPack(&data); /// /// // Converts MessagePack string to a data (lazy). /// let MsgPack(data) = dump; +///# } /// ``` pub struct MsgPack(pub T); diff --git a/src/format/toml.rs b/src/format/toml.rs index 55af48acc..807de8f3f 100644 --- a/src/format/toml.rs +++ b/src/format/toml.rs @@ -5,12 +5,16 @@ use toml; /// A representation of a TOML data. Use it as wrapper to /// set a format you want to use for conversion: /// -/// ```rust +/// ``` /// // Converts (lazy) data to a Toml +///# use yew::format::Toml; +///# fn dont_execute() { +///# let data: String = unimplemented!(); /// let dump = Toml(&data); /// /// // Converts TOML string to a data (lazy). /// let Toml(data) = dump; +/// } /// ``` pub struct Toml(pub T); diff --git a/src/format/yaml.rs b/src/format/yaml.rs index 9aa8f189e..72fd5c5a3 100644 --- a/src/format/yaml.rs +++ b/src/format/yaml.rs @@ -5,12 +5,17 @@ use serde_yaml; /// A representation of a YAML data. Use it as wrapper to /// set a format you want to use for conversion: /// -/// ```rust +/// ``` /// // Converts (lazy) data to a Yaml +///# use yew::format::Yaml; +/// +///# fn dont_execute() { +///# let data: String = unimplemented!(); /// let dump = Yaml(&data); /// /// // Converts YAML string to a data (lazy). /// let Yaml(data) = dump; +///# } /// ``` pub struct Yaml(pub T); diff --git a/src/html/mod.rs b/src/html/mod.rs index 597dc57eb..478c8bf54 100644 --- a/src/html/mod.rs +++ b/src/html/mod.rs @@ -56,12 +56,28 @@ pub type Html = VNode; /// /// In this example, the Wrapper component is used to wrap other elements. /// ``` +/// +///# use yew::{Children, Html, Renderable, Properties, Component, ComponentLink, html}; +/// #[derive(Properties)] +///# struct WrapperProps { +///# children: Children, +///# } +///# struct Wrapper; +///# impl Component for Wrapper{ +///# type Message = ();type Properties = WrapperProps; +///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} +///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} +///# } +///# impl Renderable for Wrapper { +///# fn view(&self) -> Html { // This is a recursively defined render impl - which would never work. This is done for space convenience. /// html!{ /// ///

{"Hi"}

///
{"Hello"}
///
/// } +///# } +///# } /// ``` /// /// **`wrapper.rs`** @@ -69,15 +85,25 @@ pub type Html = VNode; /// The Wrapper component must define a `children` property in order to wrap other elements. The /// children property can be used to render the wrapped elements. /// ``` +///# use yew::{Children, Html, Renderable, Properties, Component, ComponentLink, html}; +///# struct Wrapper {props: WrapperProps}; +///# impl Component for Wrapper{ +///# type Message = ();type Properties = WrapperProps; +///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} +///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} +///# } /// #[derive(Properties)] /// struct WrapperProps { /// children: Children, /// } -/// -/// html!{ -///
-/// { self.props.children.view() } -///
+/// impl Renderable for Wrapper { +/// fn view(&self) -> Html { +/// html!{ +///
+/// { self.props.children.view() } +///
+/// } +/// } /// } /// ``` pub type Children = ChildrenRenderer>; @@ -89,6 +115,34 @@ pub type Children = ChildrenRenderer>; /// /// In this example, the `List` component can wrap `ListItem` components. /// ``` +/// use yew::{html, Component, Renderable, Html, ComponentLink, ChildrenWithProps, Properties}; +/// +///# #[derive(Properties)] +///# struct ListProps { +///# children: ChildrenWithProps, +///# } +/// +///# struct List; +///# impl Component for List { +///# type Message = ();type Properties = ListProps; +///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} +///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} +///# } +///# impl Renderable for List {fn view(&self) -> Html {unimplemented!()}} +/// +/// +///# #[derive(Properties)] +///# struct ListItemProps { +///# value: String +///# } +///# struct ListItem; +///# impl Component for ListItem { +///# type Message = ();type Properties = ListItemProps; +///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} +///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} +///# } +///# impl Renderable for ListItem {fn view(&self) -> Html {unimplemented!()}} +///# fn view() -> Html { /// html!{ /// /// @@ -96,6 +150,7 @@ pub type Children = ChildrenRenderer>; /// /// /// } +///# } /// ``` /// /// **`list.rs`** @@ -103,17 +158,42 @@ pub type Children = ChildrenRenderer>; /// The `List` component must define a `children` property in order to wrap the list items. The /// `children` property can be used to filter, mutate, and render the items. /// ``` +/// use yew::ChildrenWithProps; +///# use yew::{html, Component, Renderable, Html, ComponentLink, Properties}; +///# struct List {props: ListProps}; +///# impl Component for List { +///# type Message = ();type Properties = ListProps; +///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} +///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} +///# } +/// +///# #[derive(Properties)] +///# struct ListItemProps { +///# value: String +///# } +///# struct ListItem; +///# impl Component for ListItem { +///# type Message = ();type Properties = ListItemProps; +///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} +///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} +///# } +///# impl Renderable for ListItem {fn view(&self) -> Html {unimplemented!()}} +/// /// #[derive(Properties)] /// struct ListProps { /// children: ChildrenWithProps, /// } /// -/// html!{{ -/// for self.props.children.iter().map(|mut item| { -/// item.props.value = format!("item-{}", item.props.value); -/// item -/// }) -/// }} +/// impl Renderable for List { +/// fn view(&self) -> Html { +/// html!{{ +/// for self.props.children.iter().map(|mut item| { +/// item.props.value = format!("item-{}", item.props.value); +/// item +/// }) +/// }} +/// } +/// } /// ``` pub type ChildrenWithProps = ChildrenRenderer>; diff --git a/src/lib.rs b/src/lib.rs index 71452f0e6..88b95c835 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,6 @@ //! Minimal example: //! //! ```rust -//! #[macro_use] -//! extern crate yew; //! use yew::prelude::*; //! //! struct Model { @@ -47,12 +45,13 @@ //! } //! } //! } -//! +//!# fn dont_execute() { //! fn main() { //! yew::initialize(); //! App::::new().mount_to_body(); //! yew::run_loop(); //! } +//!# } //! ``` //! diff --git a/src/services/fetch.rs b/src/services/fetch.rs index b1a57a450..9c36d9904 100644 --- a/src/services/fetch.rs +++ b/src/services/fetch.rs @@ -115,48 +115,99 @@ impl FetchService { /// You may use a Request builder to build your request declaratively as on the /// following examples: /// - /// ```rust - /// let post_request = Request::post("https://my.api/v1/resource") - /// .header("Content-Type", "application/json") - /// .body(Json(&json!({"foo": "bar"}))) - /// .expect("Failed to build request."); + /// ``` + ///# use yew::format::{Nothing, Json}; + ///# use yew::services::fetch::Request; + ///# use serde_json::json; + /// let post_request = Request::post("https://my.api/v1/resource") + /// .header("Content-Type", "application/json") + /// .body(Json(&json!({"foo": "bar"}))) + /// .expect("Failed to build request."); /// - /// let get_request = Request::get("https://my.api/v1/resource") - /// .body(Nothing) - /// .expect("Failed to build request."); + /// let get_request = Request::get("https://my.api/v1/resource") + /// .body(Nothing) + /// .expect("Failed to build request."); /// ``` /// /// The callback function can build a loop message by passing or analizing the /// response body and metadata. /// - /// ```rust - /// context.web.fetch( - /// post_request, - /// |response| { - /// if response.status().is_success() { - /// Msg::Noop - /// } else { - /// Msg::Error - /// } + /// ``` + ///# use yew::{Component, ComponentLink, Html, Renderable}; + ///# use yew::services::FetchService; + ///# use yew::services::fetch::{Response, Request}; + ///# struct Comp; + ///# impl Component for Comp { + ///# type Message = Msg;type Properties = (); + ///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} + ///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} + ///# } + ///# impl Renderable for Comp {fn view(&self) -> Html {unimplemented!()}} + ///# enum Msg { + ///# Noop, + ///# Error + ///# } + ///# fn dont_execute() { + ///# let mut link: ComponentLink = unimplemented!(); + ///# let mut fetch_service: FetchService = FetchService::new(); + ///# let post_request: Request> = unimplemented!(); + /// let task = fetch_service.fetch( + /// post_request, + /// link.send_back(|response: Response>| { + /// if response.status().is_success() { + /// Msg::Noop + /// } else { + /// Msg::Error /// } - /// ) + /// }) + /// ); + ///# } /// ``` /// - /// One can also simply consume and pass the response or body object into - /// the message. + /// For a full example, you can specify that the response must be in the JSON format, + /// and be a specific serialized data type. If the mesage isn't Json, or isn't the specified + /// data type, then you will get a message indicating failure. /// - /// ```rust - /// context.web.fetch( - /// get_request, - /// |response| { - /// let (meta, Json(body)) = response.into_parts(); - /// if meta.status.is_success() { - /// Msg::FetchResourceComplete(body) - /// } else { - /// Msg::FetchResourceFailed - /// } + /// ``` + ///# use yew::format::{Json, Nothing, Format}; + ///# use yew::services::FetchService; + ///# use http::Request; + ///# use yew::services::fetch::Response; + ///# use yew::{Component, ComponentLink, Renderable, Html}; + ///# use serde_derive::Deserialize; + ///# struct Comp; + ///# impl Component for Comp { + ///# type Message = Msg;type Properties = (); + ///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} + ///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} + ///# } + ///# impl Renderable for Comp {fn view(&self) -> Html {unimplemented!()}} + ///# enum Msg { + ///# FetchResourceComplete(Data), + ///# FetchResourceFailed + ///# } + /// #[derive(Deserialize)] + /// struct Data { + /// value: String + /// } + ///# fn dont_execute() { + ///# let mut link: ComponentLink = unimplemented!(); + /// let get_request = Request::get("/thing").body(Nothing).unwrap(); + /// let callback = link.send_back(|response: Response>>| { + /// if let (meta, Json(Ok(body))) = response.into_parts() { + /// if meta.status.is_success() { + /// return Msg::FetchResourceComplete(body); + /// } /// } - /// ) + /// Msg::FetchResourceFailed + /// } + /// ); + /// + /// let task = FetchService::new().fetch( + /// get_request, + /// callback + /// ); + ///# } /// ``` /// pub fn fetch( @@ -173,14 +224,33 @@ impl FetchService { /// `fetch` with provided `FetchOptions` object. /// Use it if you need to send cookies with a request: - /// ```rust - /// let request = fetch::Request::get("/path/") - /// .body(Nothing).unwrap(); - /// let options = FetchOptions { - /// credentials: Some(Credentials::SameOrigin), - /// ..FetchOptions::default() - /// }; - /// let task = fetch_service.fetch_with_options(request, options, callback); + /// ``` + ///# use yew::format::Nothing; + ///# use yew::services::fetch::{self, FetchOptions, Credentials}; + ///# use yew::{Renderable, Html, Component, ComponentLink}; + ///# use yew::services::FetchService; + ///# use http::Response; + ///# struct Comp; + ///# impl Component for Comp { + ///# type Message = Msg;type Properties = (); + ///# fn create(props: Self::Properties,link: ComponentLink) -> Self {unimplemented!()} + ///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()} + ///# } + ///# impl Renderable for Comp {fn view(&self) -> Html {unimplemented!()}} + ///# pub enum Msg {} + ///# fn dont_execute() { + ///# let mut link: ComponentLink = unimplemented!(); + ///# let callback = link.send_back(|response: Response>| unimplemented!()); + /// let request = fetch::Request::get("/path/") + /// .body(Nothing) + /// .unwrap(); + /// let options = FetchOptions { + /// credentials: Some(Credentials::SameOrigin), + /// ..FetchOptions::default() + /// }; + ///# let mut fetch_service = FetchService::new(); + /// let task = fetch_service.fetch_with_options(request, options, callback); + ///# } /// ``` pub fn fetch_with_options( &mut self,