use uhg_custom_appollo_roouter::_private::create_test_service_factory_from_yaml; use tower::ServiceExt; #[tokio::test] async fn test_supergraph_validation_errors_are_passed_on() { create_test_service_factory_from_yaml( include_str!("../../src/testdata/invalid_supergraph.graphql"), "supergraph:\n introspection: true\n", ) .await; } /// #[tokio::test] async fn test_request_extensions_is_null() { // `extensions` is optional: // // > Specifying null for optional request parameters is equivalent to not specifying them at all // https://graphql.github.io/graphql-over-http/draft/#note-22957 let request = serde_json::json!({"query": "{__typename}", "extensions": serde_json::Value::Null}); let request = uhg_custom_appollo_roouter::services::router::Request::fake_builder() .body(request.to_string()) .method(hyper::Method::POST) .header("content-type", "application/json") .build() .unwrap(); let response = uhg_custom_appollo_roouter::TestHarness::builder() .schema(include_str!("../fixtures/supergraph.graphql")) .build_router() .await .unwrap() .oneshot(request) .await .unwrap() .next_response() .await .unwrap() .unwrap(); // Used to be an INVALID_GRAPHQL_REQUEST error with "invalid type: null, expected a map" assert_eq!( String::from_utf8_lossy(&response), r#"{"data":{"__typename":"Query"}}"# ); } #[tokio::test] async fn test_syntax_error() { let request = serde_json::json!({"query": "{__typename"}); let request = uhg_custom_appollo_roouter::services::router::Request::fake_builder() .body(request.to_string()) .method(hyper::Method::POST) .header("content-type", "application/json") .build() .unwrap(); let response = uhg_custom_appollo_roouter::TestHarness::builder() .schema(include_str!("../fixtures/supergraph.graphql")) .build_router() .await .unwrap() .oneshot(request) .await .unwrap() .next_response() .await .unwrap() .unwrap(); let v: serde_json::Value = serde_json::from_slice(&response).unwrap(); insta::assert_json_snapshot!(v, @r###" { "errors": [ { "message": "parsing error: syntax error: expected R_CURLY, got EOF", "locations": [ { "line": 1, "column": 12 } ], "extensions": { "code": "PARSING_ERROR" } } ] } "###); } #[tokio::test] async fn test_validation_error() { let request = serde_json::json!({"query": "{...a} fragment unused on Query { me { id } } fragment a on Query{me {id} topProducts(first: 5.5) {id}}"}); let request = uhg_custom_appollo_roouter::services::router::Request::fake_builder() .body(request.to_string()) .method(hyper::Method::POST) .header("content-type", "application/json") .build() .unwrap(); let response = uhg_custom_appollo_roouter::TestHarness::builder() .schema(include_str!("../fixtures/supergraph.graphql")) .build_router() .await .unwrap() .oneshot(request) .await .unwrap() .next_response() .await .unwrap() .unwrap(); let v: serde_json::Value = serde_json::from_slice(&response).unwrap(); insta::assert_json_snapshot!(v, @r###" { "errors": [ { "message": "Fragment \"unused\" is never used.", "locations": [ { "line": 1, "column": 8 } ], "extensions": { "code": "GRAPHQL_VALIDATION_FAILED" } }, { "message": "Field \"topProducts\" of type \"Query\" must have a selection of subfields. Did you mean \"topProducts { ... }\"?", "locations": [ { "line": 1, "column": 75 } ], "extensions": { "code": "GRAPHQL_VALIDATION_FAILED" } }, { "message": "Int cannot represent value: 5.5", "locations": [ { "line": 1, "column": 94 } ], "extensions": { "code": "GRAPHQL_VALIDATION_FAILED" } }, { "message": "Cannot query field \"id\" on type \"Product\".", "locations": [ { "line": 1, "column": 100 } ], "extensions": { "code": "GRAPHQL_VALIDATION_FAILED" } } ] } "###); } #[tokio::test] async fn test_lots_of_validation_errors() { let query = format!( "{{ __typename {} }}", "@a".repeat(4_000), // Stay under the token limit: "@a" is two tokens every time ); let request = serde_json::json!({ "query": query }); let request = uhg_custom_appollo_roouter::services::router::Request::fake_builder() .body(request.to_string()) .method(hyper::Method::POST) .header("content-type", "application/json") .build() .unwrap(); let response = uhg_custom_appollo_roouter::TestHarness::builder() .schema(include_str!("../fixtures/supergraph.graphql")) .build_router() .await .unwrap() .oneshot(request) .await .unwrap() .next_response() .await .unwrap() .unwrap(); let v: serde_json::Value = serde_json::from_slice(&response).unwrap(); let errors = v["errors"].as_array().unwrap(); assert!(!errors.is_empty(), "should have errors"); // Make sure we're actually testing the validation errors, and we're not hitting some other limit assert_eq!( errors.first().unwrap()["extensions"]["code"], serde_json::Value::from("GRAPHQL_VALIDATION_FAILED") ); assert!(errors.len() <= 100, "should return limited error count"); }