1
0
Fork 0
mirror of https://gitlab.com/msrd0/gotham-restful.git synced 2025-02-22 20:52:27 +00:00

improve test coverage for the result types

This commit is contained in:
Dominic 2020-05-03 18:48:55 +02:00
parent 0d95ca4abb
commit 101e94b900
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
6 changed files with 171 additions and 84 deletions

View file

@ -6,7 +6,7 @@ use crate::{
};
use super::SECURITY_NAME;
use indexmap::IndexMap;
use mime::{Mime, STAR_STAR};
use mime::Mime;
use openapiv3::{
MediaType, Operation, Parameter, ParameterData, ParameterSchemaOrContent, ReferenceOr,
ReferenceOr::Item, RequestBody as OARequestBody, Response, Responses, Schema, SchemaKind,
@ -148,7 +148,7 @@ impl<'a> OperationDescription<'a>
let (operation_id, default_status, accepted_types, schema, params, body_schema, supported_types, requires_auth) = (
self.operation_id, self.default_status, self.accepted_types, self.schema, self.params, self.body_schema, self.supported_types, self.requires_auth);
let content = Self::schema_to_content(accepted_types.unwrap_or_else(|| vec![STAR_STAR]), schema);
let content = Self::schema_to_content(accepted_types.or_all_types(), schema);
let mut responses : IndexMap<StatusCode, ReferenceOr<Response>> = IndexMap::new();
responses.insert(StatusCode::Code(default_status.as_u16()), Item(Response {
@ -159,7 +159,7 @@ impl<'a> OperationDescription<'a>
let request_body = body_schema.map(|schema| Item(OARequestBody {
description: None,
content: Self::schema_to_content(supported_types.unwrap_or_else(|| vec![STAR_STAR]), schema),
content: Self::schema_to_content(supported_types.or_all_types(), schema),
required: true
}));
@ -199,7 +199,7 @@ mod test
{
let types = NoContent::accepted_types();
let schema = <NoContent as OpenapiType>::schema();
let content = OperationDescription::schema_to_content(types.unwrap_or_else(|| vec![STAR_STAR]), Item(schema.into_schema()));
let content = OperationDescription::schema_to_content(types.or_all_types(), Item(schema.into_schema()));
assert!(content.is_empty());
}
@ -208,7 +208,7 @@ mod test
{
let types = Raw::<&str>::accepted_types();
let schema = <Raw<&str> as OpenapiType>::schema();
let content = OperationDescription::schema_to_content(types.unwrap_or_else(|| vec![STAR_STAR]), Item(schema.into_schema()));
let content = OperationDescription::schema_to_content(types.or_all_types(), Item(schema.into_schema()));
assert_eq!(content.len(), 1);
let json = serde_json::to_string(&content.values().nth(0).unwrap()).unwrap();
assert_eq!(json, r#"{"schema":{"type":"string","format":"binary"}}"#);

View file

@ -2,7 +2,7 @@ use crate::Response;
#[cfg(feature = "openapi")]
use crate::OpenapiSchema;
use futures_util::future::FutureExt;
use mime::Mime;
use mime::{Mime, STAR_STAR};
use serde::Serialize;
use std::{
error::Error,
@ -26,6 +26,21 @@ pub use result::IntoResponseError;
mod success;
pub use success::Success;
pub(crate) trait OrAllTypes
{
fn or_all_types(self) -> Vec<Mime>;
}
impl OrAllTypes for Option<Vec<Mime>>
{
fn or_all_types(self) -> Vec<Mime>
{
self.unwrap_or_else(|| vec![STAR_STAR])
}
}
/// A trait provided to convert a resource's result to json.
pub trait ResourceResult
{
@ -145,13 +160,11 @@ where
mod test
{
use super::*;
use crate::{OpenapiType, StatusCode};
use futures_executor::block_on;
use mime::{APPLICATION_JSON, TEXT_PLAIN};
use thiserror::Error;
#[derive(Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "openapi", derive(OpenapiType))]
#[cfg_attr(feature = "openapi", derive(crate::OpenapiType))]
struct Msg
{
msg : String
@ -162,63 +175,16 @@ mod test
struct MsgError;
#[test]
fn resource_result_ok()
fn result_from_future()
{
let ok : Result<Msg, MsgError> = Ok(Msg::default());
let res = block_on(ok.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), r#"{"msg":""}"#.as_bytes());
}
#[test]
fn resource_result_err()
{
let err : Result<Msg, MsgError> = Err(MsgError::default());
let res = block_on(err.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::INTERNAL_SERVER_ERROR);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), format!(r#"{{"error":true,"message":"{}"}}"#, MsgError::default()).as_bytes());
}
#[test]
fn success_always_successfull()
{
let success : Success<Msg> = Msg::default().into();
let res = block_on(success.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), r#"{"msg":""}"#.as_bytes());
}
#[test]
fn no_content_has_empty_response()
{
let no_content = NoContent::default();
let res = block_on(no_content.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::NO_CONTENT);
assert_eq!(res.mime, None);
assert_eq!(res.full_body().unwrap(), &[] as &[u8]);
}
#[test]
fn no_content_result()
{
let no_content : Result<NoContent, MsgError> = Ok(NoContent::default());
let res = block_on(no_content.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::NO_CONTENT);
assert_eq!(res.mime, None);
assert_eq!(res.full_body().unwrap(), &[] as &[u8]);
}
#[test]
fn raw_response()
{
let msg = "Test";
let raw = Raw::new(msg, TEXT_PLAIN);
let res = block_on(raw.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(res.mime, Some(TEXT_PLAIN));
assert_eq!(res.full_body().unwrap(), msg.as_bytes());
let nc = NoContent::default();
let res = block_on(nc.into_response()).unwrap();
let fut_nc = async move { NoContent::default() }.boxed();
let fut_res = block_on(fut_nc.into_response()).unwrap();
assert_eq!(res.status, fut_res.status);
assert_eq!(res.mime, fut_res.mime);
assert_eq!(res.full_body().unwrap(), fut_res.full_body().unwrap());
}
}

View file

@ -103,4 +103,38 @@ where
{
NoContent::default_status()
}
}
}
#[cfg(test)]
mod test
{
use super::*;
use futures_executor::block_on;
use gotham::hyper::StatusCode;
use thiserror::Error;
#[derive(Debug, Default, Error)]
#[error("An Error")]
struct MsgError;
#[test]
fn no_content_has_empty_response()
{
let no_content = NoContent::default();
let res = block_on(no_content.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::NO_CONTENT);
assert_eq!(res.mime, None);
assert_eq!(res.full_body().unwrap(), &[] as &[u8]);
}
#[test]
fn no_content_result()
{
let no_content : Result<NoContent, MsgError> = Ok(NoContent::default());
let res = block_on(no_content.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::NO_CONTENT);
assert_eq!(res.mime, None);
assert_eq!(res.full_body().unwrap(), &[] as &[u8]);
}
}

View file

@ -10,10 +10,11 @@ use mime::Mime;
use openapiv3::{SchemaKind, StringFormat, StringType, Type, VariantOrUnknownOrEmpty};
use serde_json::error::Error as SerdeJsonError;
use std::{
fmt::{Debug, Display},
fmt::Display,
pin::Pin
};
#[derive(Debug)]
pub struct Raw<T>
{
pub raw : T,
@ -39,13 +40,6 @@ impl<T : Clone> Clone for Raw<T>
}
}
impl<T : Debug> Debug for Raw<T>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Raw({:?}, {:?})", self.raw, self.mime)
}
}
impl<T : Into<Body>> ResourceResult for Raw<T>
where
Self : Send
@ -87,4 +81,24 @@ where
{
<Raw<T> as ResourceResult>::schema()
}
}
}
#[cfg(test)]
mod test
{
use super::*;
use futures_executor::block_on;
use mime::TEXT_PLAIN;
#[test]
fn raw_response()
{
let msg = "Test";
let raw = Raw::new(msg, TEXT_PLAIN);
let res = block_on(raw.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(res.mime, Some(TEXT_PLAIN));
assert_eq!(res.full_body().unwrap(), msg.as_bytes());
}
}

View file

@ -56,4 +56,51 @@ where
{
R::schema()
}
}
}
#[cfg(test)]
mod test
{
use super::*;
use crate::result::OrAllTypes;
use futures_executor::block_on;
use thiserror::Error;
#[derive(Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "openapi", derive(crate::OpenapiType))]
struct Msg
{
msg : String
}
#[derive(Debug, Default, Error)]
#[error("An Error")]
struct MsgError;
#[test]
fn result_ok()
{
let ok : Result<Msg, MsgError> = Ok(Msg::default());
let res = block_on(ok.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), r#"{"msg":""}"#.as_bytes());
}
#[test]
fn result_err()
{
let err : Result<Msg, MsgError> = Err(MsgError::default());
let res = block_on(err.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::INTERNAL_SERVER_ERROR);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), format!(r#"{{"error":true,"message":"{}"}}"#, MsgError::default()).as_bytes());
}
#[test]
fn success_accepts_json()
{
assert!(<Result<Msg, MsgError>>::accepted_types().or_all_types().contains(&APPLICATION_JSON))
}
}

View file

@ -41,6 +41,7 @@ fn read_all(_state: &mut State) -> Success<MyResponse> {
# }
```
*/
#[derive(Debug)]
pub struct Success<T>(T);
impl<T> AsMut<T> for Success<T>
@ -97,13 +98,6 @@ impl<T : Copy> Copy for Success<T>
{
}
impl<T : Debug> Debug for Success<T>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Success({:?})", self.0)
}
}
impl<T : Default> Default for Success<T>
{
fn default() -> Self
@ -134,3 +128,35 @@ where
T::schema()
}
}
#[cfg(test)]
mod test
{
use super::*;
use crate::result::OrAllTypes;
use futures_executor::block_on;
#[derive(Debug, Default, Serialize)]
#[cfg_attr(feature = "openapi", derive(crate::OpenapiType))]
struct Msg
{
msg : String
}
#[test]
fn success_always_successfull()
{
let success : Success<Msg> = Msg::default().into();
let res = block_on(success.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), r#"{"msg":""}"#.as_bytes());
}
#[test]
fn success_accepts_json()
{
assert!(<Success<Msg>>::accepted_types().or_all_types().contains(&APPLICATION_JSON))
}
}