diff --git a/src/http.rs b/src/http.rs index 62c8b167..e8ceef30 100644 --- a/src/http.rs +++ b/src/http.rs @@ -90,3 +90,120 @@ impl<'a> ser::Serialize for GraphQLResponse<'a> { } } } + +#[cfg(test)] +pub mod tests { + use serde_json::Value as Json; + use serde_json; + + pub struct TestResponse { + pub status_code: i32, + pub body: Option, + pub content_type: String, + } + + pub trait HTTPIntegration { + fn get(&self, url: &str) -> TestResponse; + fn post(&self, url: &str, body: &str) -> TestResponse; + } + + pub fn run_http_test_suite(integration: &T) { + println!("Running HTTP Test suite for integration"); + + println!(" - test_simple_get"); + test_simple_get(integration); + + println!(" - test_encoded_get"); + test_encoded_get(integration); + + println!(" - test_get_with_variables"); + test_get_with_variables(integration); + + println!(" - test_simple_post"); + test_simple_post(integration); + } + + fn unwrap_json_response(response: &TestResponse) -> Json { + serde_json::from_str::( + response.body.as_ref().expect("No data returned from request") + ).expect("Could not parse JSON object") + } + + fn test_simple_get(integration: &T) { + let response = integration.get("/?query={hero{name}}"); + + assert_eq!(response.status_code, 200); + assert_eq!(response.content_type.as_str(), "application/json"); + + assert_eq!( + unwrap_json_response(&response), + serde_json::from_str::(r#"{"data": {"hero": {"name": "R2-D2"}}}"#) + .expect("Invalid JSON constant in test")); + } + + fn test_encoded_get(integration: &T) { + let response = integration.get( + "/?query=query%20{%20%20%20human(id:%20\"1000\")%20{%20%20%20%20%20id,%20%20%20%20%20name,%20%20%20%20%20appearsIn,%20%20%20%20%20homePlanet%20%20%20}%20}"); + + assert_eq!(response.status_code, 200); + assert_eq!(response.content_type.as_str(), "application/json"); + + assert_eq!( + unwrap_json_response(&response), + serde_json::from_str::(r#"{ + "data": { + "human": { + "appearsIn": [ + "NEW_HOPE", + "EMPIRE", + "JEDI" + ], + "homePlanet": "Tatooine", + "name": "Luke Skywalker", + "id": "1000" + } + } + }"#) + .expect("Invalid JSON constant in test")); + } + + fn test_get_with_variables(integration: &T) { + let response = integration.get( + "/?query=query($id:%20String!)%20{%20%20%20human(id:%20$id)%20{%20%20%20%20%20id,%20%20%20%20%20name,%20%20%20%20%20appearsIn,%20%20%20%20%20homePlanet%20%20%20}%20}&variables={%20%20%20\"id\":%20%20\"1000\"%20}"); + + assert_eq!(response.status_code, 200); + assert_eq!(response.content_type, "application/json"); + + assert_eq!( + unwrap_json_response(&response), + serde_json::from_str::(r#"{ + "data": { + "human": { + "appearsIn": [ + "NEW_HOPE", + "EMPIRE", + "JEDI" + ], + "homePlanet": "Tatooine", + "name": "Luke Skywalker", + "id": "1000" + } + } + }"#) + .expect("Invalid JSON constant in test")); + } + + fn test_simple_post(integration: &T) { + let response = integration.post( + "/", + r#"{"query": "{hero{name}}"}"#); + + assert_eq!(response.status_code, 200); + assert_eq!(response.content_type, "application/json"); + + assert_eq!( + unwrap_json_response(&response), + serde_json::from_str::(r#"{"data": {"hero": {"name": "R2-D2"}}}"#) + .expect("Invalid JSON constant in test")); + } +} diff --git a/src/integrations/iron_handlers.rs b/src/integrations/iron_handlers.rs index 72ff6ed1..c2f327c5 100644 --- a/src/integrations/iron_handlers.rs +++ b/src/integrations/iron_handlers.rs @@ -215,23 +215,65 @@ impl From for IronError { #[cfg(test)] mod tests { - use serde_json::Value as Json; - use serde_json; use iron::prelude::*; - use iron::status; - use iron::headers; use iron_test::{request, response}; use iron::{Handler, Headers}; use ::tests::model::Database; + use ::http::tests as http_tests; use types::scalars::EmptyMutation; use super::GraphQLHandler; + struct TestIronIntegration; + + impl http_tests::HTTPIntegration for TestIronIntegration + { + fn get(&self, url: &str) -> http_tests::TestResponse { + make_test_response(request::get( + &("http://localhost:3000".to_owned() + url), + Headers::new(), + &make_handler(), + )) + } + + fn post(&self, url: &str, body: &str) -> http_tests::TestResponse { + make_test_response(request::post( + &("http://localhost:3000".to_owned() + url), + Headers::new(), + body, + &make_handler(), + )) + } + } + + #[test] + fn test_iron_integration() { + let integration = TestIronIntegration; + + http_tests::run_http_test_suite(&integration); + } + fn context_factory(_: &mut Request) -> Database { Database::new() } + fn make_test_response(response: IronResult) -> http_tests::TestResponse { + let response = response.expect("Error response from GraphQL handler"); + let status_code = response.status.expect("No status code returned from handler").to_u16() as i32; + let content_type = String::from_utf8( + response.headers.get_raw("content-type") + .expect("No content type header from handler")[0].clone()) + .expect("Content-type header invalid UTF-8"); + let body = response::extract_body_to_string(response); + + http_tests::TestResponse { + status_code: status_code, + body: Some(body), + content_type: content_type, + } + } + fn make_handler() -> Box { Box::new(GraphQLHandler::new( context_factory, @@ -239,129 +281,4 @@ mod tests { EmptyMutation::::new(), )) } - - fn unwrap_json_response(resp: Response) -> Json { - let result = response::extract_body_to_string(resp); - - serde_json::from_str::(&result).expect("Could not parse JSON object") - } - - #[test] - fn test_simple_get() { - let response = request::get( - "http://localhost:3000/?query={hero{name}}", - Headers::new(), - &make_handler()) - .expect("Unexpected IronError"); - - assert_eq!(response.status, Some(status::Ok)); - assert_eq!(response.headers.get::(), - Some(&headers::ContentType::json())); - - let json = unwrap_json_response(response); - - assert_eq!( - json, - serde_json::from_str::(r#"{"data": {"hero": {"name": "R2-D2"}}}"#) - .expect("Invalid JSON constant in test")); - } - - #[test] - fn test_encoded_get() { - let response = request::get( - "http://localhost:3000/?query=query%20{%20%20%20human(id:%20\"1000\")%20{%20%20%20%20%20id,%20%20%20%20%20name,%20%20%20%20%20appearsIn,%20%20%20%20%20homePlanet%20%20%20}%20}", - Headers::new(), - &make_handler()) - .expect("Unexpected IronError"); - - assert_eq!(response.status, Some(status::Ok)); - assert_eq!(response.headers.get::(), - Some(&headers::ContentType::json())); - - let json = unwrap_json_response(response); - - assert_eq!( - json, - serde_json::from_str::(r#"{ - "data": { - "human": { - "appearsIn": [ - "NEW_HOPE", - "EMPIRE", - "JEDI" - ], - "homePlanet": "Tatooine", - "name": "Luke Skywalker", - "id": "1000" - } - } - }"#) - .expect("Invalid JSON constant in test")); - } - - #[test] - fn test_get_with_variables() { - let response = request::get( - "http://localhost:3000/?query=query($id:%20String!)%20{%20%20%20human(id:%20$id)%20{%20%20%20%20%20id,%20%20%20%20%20name,%20%20%20%20%20appearsIn,%20%20%20%20%20homePlanet%20%20%20}%20}&variables={%20%20%20\"id\":%20%20\"1000\"%20}", - Headers::new(), - &make_handler()) - .expect("Unexpected IronError"); - - assert_eq!(response.status, Some(status::Ok)); - assert_eq!(response.headers.get::(), - Some(&headers::ContentType::json())); - - let json = unwrap_json_response(response); - - assert_eq!( - json, - serde_json::from_str::(r#"{ - "data": { - "human": { - "appearsIn": [ - "NEW_HOPE", - "EMPIRE", - "JEDI" - ], - "homePlanet": "Tatooine", - "name": "Luke Skywalker", - "id": "1000" - } - } - }"#) - .expect("Invalid JSON constant in test")); - } - - - #[test] - fn test_simple_post() { - let response = request::post( - "http://localhost:3000/", - Headers::new(), - r#"{"query": "{hero{name}}"}"#, - &make_handler()) - .expect("Unexpected IronError"); - - assert_eq!(response.status, Some(status::Ok)); - assert_eq!(response.headers.get::(), - Some(&headers::ContentType::json())); - - let json = unwrap_json_response(response); - - assert_eq!( - json, - serde_json::from_str::(r#"{"data": {"hero": {"name": "R2-D2"}}}"#) - .expect("Invalid JSON constant in test")); - } - - #[test] - fn test_unsupported_method() { - let response = request::options( - "http://localhost:3000/?query={hero{name}}", - Headers::new(), - &make_handler()) - .expect("Unexpected IronError"); - - assert_eq!(response.status, Some(status::MethodNotAllowed)); - } }