Factor out HTTP integration tests to http module

This commit is contained in:
Magnus Hallin 2017-06-14 17:24:50 +02:00
parent 5f69b1d45e
commit 565f14ceef
2 changed files with 163 additions and 129 deletions

View file

@ -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<String>,
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<T: HTTPIntegration>(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::<Json>(
response.body.as_ref().expect("No data returned from request")
).expect("Could not parse JSON object")
}
fn test_simple_get<T: HTTPIntegration>(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::<Json>(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
.expect("Invalid JSON constant in test"));
}
fn test_encoded_get<T: HTTPIntegration>(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::<Json>(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<T: HTTPIntegration>(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::<Json>(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<T: HTTPIntegration>(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::<Json>(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
.expect("Invalid JSON constant in test"));
}
}

View file

@ -215,23 +215,65 @@ impl From<GraphQLIronError> 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<Response>) -> 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<Handler> {
Box::new(GraphQLHandler::new(
context_factory,
@ -239,129 +281,4 @@ mod tests {
EmptyMutation::<Database>::new(),
))
}
fn unwrap_json_response(resp: Response) -> Json {
let result = response::extract_body_to_string(resp);
serde_json::from_str::<Json>(&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::<headers::ContentType>(),
Some(&headers::ContentType::json()));
let json = unwrap_json_response(response);
assert_eq!(
json,
serde_json::from_str::<Json>(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::<headers::ContentType>(),
Some(&headers::ContentType::json()));
let json = unwrap_json_response(response);
assert_eq!(
json,
serde_json::from_str::<Json>(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::<headers::ContentType>(),
Some(&headers::ContentType::json()));
let json = unwrap_json_response(response);
assert_eq!(
json,
serde_json::from_str::<Json>(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::<headers::ContentType>(),
Some(&headers::ContentType::json()));
let json = unwrap_json_response(response);
assert_eq!(
json,
serde_json::from_str::<Json>(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));
}
}