juniper/juniper_rocket/tests/http_test_suite.rs
Kai Ren bd8dc582a4
Fix handling GET request in juniper_rocket example (#1223, #1098)
- rework `rocket_server` example as `simple`
- provide example in `GraphQLRequest` API docs
- mention GET query format in  `GraphQLRequest` API docs and `simple` example

Additionally:
- fix `operationName` query parameter handling
- make `graphiql_source()` and `playground_source()` polymorphic over `subscriptions_endpoint_url` argument
- provide examples in `graphiql_source()` and `playground_source()` API docs
- move integration HTTP tests to a separate file
- test both sync and async `juniper_rocket` in integration HTTP tests
- polish `FromForm` unit tests
2023-11-24 17:51:32 +00:00

155 lines
4.5 KiB
Rust

use futures::executor;
use juniper::{
http::tests::{run_http_test_suite, HttpIntegration, TestResponse},
tests::fixtures::starwars::schema::{Database, Query},
EmptyMutation, EmptySubscription, RootNode,
};
use juniper_rocket::{GraphQLRequest, GraphQLResponse};
use rocket::{
get,
http::ContentType,
local::asynchronous::{Client, LocalResponse},
post, routes, Build, Rocket, State,
};
type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
fn bootstrap_rocket() -> Rocket<Build> {
Rocket::build().manage(Database::new()).manage(Schema::new(
Query,
EmptyMutation::<Database>::new(),
EmptySubscription::<Database>::new(),
))
}
fn make_rocket() -> Rocket<Build> {
#[get("/?<request..>")]
async fn get_handler(
context: &State<Database>,
request: GraphQLRequest,
schema: &State<Schema>,
) -> GraphQLResponse {
request.execute(schema, context).await
}
#[post("/", data = "<request>")]
async fn post_handler(
context: &State<Database>,
request: GraphQLRequest,
schema: &State<Schema>,
) -> GraphQLResponse {
request.execute(schema, context).await
}
bootstrap_rocket().mount("/", routes![post_handler, get_handler])
}
fn make_sync_rocket() -> Rocket<Build> {
#[get("/?<request..>")]
fn get_handler_sync(
context: &State<Database>,
request: GraphQLRequest,
schema: &State<Schema>,
) -> GraphQLResponse {
request.execute_sync(schema, context)
}
#[post("/", data = "<request>")]
fn post_handler_sync(
context: &State<Database>,
request: GraphQLRequest,
schema: &State<Schema>,
) -> GraphQLResponse {
request.execute_sync(schema, context)
}
bootstrap_rocket().mount("/", routes![post_handler_sync, get_handler_sync])
}
struct TestRocketIntegration {
client: Client,
}
async fn into_test_response(response: LocalResponse<'_>) -> TestResponse {
let status_code = response.status().code as i32;
let content_type = response
.content_type()
.expect("no `Content-Type` header from handler")
.to_string();
let body = response
.into_string()
.await
.expect("no body returned from GraphQL handler");
TestResponse {
status_code,
content_type,
body: Some(body),
}
}
impl HttpIntegration for TestRocketIntegration {
fn get(&self, url: &str) -> TestResponse {
let req = self.client.get(url);
let resp = executor::block_on(req.dispatch());
executor::block_on(into_test_response(resp))
}
fn post_json(&self, url: &str, body: &str) -> TestResponse {
let req = self.client.post(url).header(ContentType::JSON).body(body);
let resp = executor::block_on(req.dispatch());
executor::block_on(into_test_response(resp))
}
fn post_graphql(&self, url: &str, body: &str) -> TestResponse {
let req = self
.client
.post(url)
.header(ContentType::new("application", "graphql"))
.body(body);
let resp = executor::block_on(req.dispatch());
executor::block_on(into_test_response(resp))
}
}
#[rocket::async_test]
async fn test_rocket_integration() {
let rocket = make_rocket();
let client = Client::untracked(rocket).await.expect("valid rocket");
run_http_test_suite(&TestRocketIntegration { client });
}
#[rocket::async_test]
async fn test_sync_rocket_integration() {
let rocket = make_sync_rocket();
let client = Client::untracked(rocket).await.expect("valid rocket");
run_http_test_suite(&TestRocketIntegration { client });
}
#[rocket::async_test]
async fn test_operation_names() {
#[post("/", data = "<request>")]
async fn post_graphql_assert_operation_name_handler(
context: &State<Database>,
request: GraphQLRequest,
schema: &State<Schema>,
) -> GraphQLResponse {
assert_eq!(request.operation_names(), vec![Some("TestQuery")]);
request.execute(schema, context).await
}
let rocket = bootstrap_rocket().mount("/", routes![post_graphql_assert_operation_name_handler]);
let client = Client::untracked(rocket).await.expect("valid rocket");
let resp = client
.post("/")
.header(ContentType::JSON)
.body(r#"{"query": "query TestQuery {hero{name}}", "operationName": "TestQuery"}"#)
.dispatch()
.await;
let resp = into_test_response(resp).await;
assert_eq!(resp.status_code, 200, "response: {resp:#?}");
}