Factor out HTTP integration tests to http module
This commit is contained in:
parent
5f69b1d45e
commit
565f14ceef
2 changed files with 163 additions and 129 deletions
117
src/http.rs
117
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<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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue