use crate::query_planner::{
tests::testkit::{build_query_plan_with_defaults, init_logger},
utils::parsing::parse_operation,
};
use std::error::Error;
#[test]
fn node_query_with_aliases_on_interface_field() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
account: node(id: "a1") {
__typename
}
chat: node(id: "c1") {
__typename
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Fetch(service: "a") {
{
account: node(id: "a1") {
...a
}
chat: node(id: "c1") {
...a
}
}
fragment a on Node {
__typename
}
},
},
"#);
Ok(())
}
#[test]
fn node_query_with_inline_fragments_on_object_types() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
account: node(id: "a1") {
... on Account {
id
username
}
}
chat: node(id: "c1") {
... on Chat {
id
text
}
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Parallel {
Fetch(service: "b") {
{
chat: node(id: "c1") {
__typename
... on Chat {
id
text
}
}
}
},
Fetch(service: "a") {
{
account: node(id: "a1") {
__typename
... on Account {
id
username
}
}
}
},
},
},
"#);
Ok(())
}
#[test]
fn node_query_with_cross_type_inline_fragments() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
account: node(id: "a1") {
... on Chat {
id
}
}
chat: node(id: "c1") {
... on Account {
id
}
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Parallel {
Fetch(service: "a") {
{
chat: node(id: "c1") {
__typename
... on Account {
id
}
}
}
},
Fetch(service: "b") {
{
account: node(id: "a1") {
__typename
... on Chat {
id
}
}
}
},
},
},
"#);
Ok(())
}
#[test]
fn node_query_with_typename_and_cross_type_fragments() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
account: node(id: "a1") {
__typename
... on Chat {
id
}
}
chat: node(id: "c1") {
__typename
... on Account {
id
}
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Parallel {
Fetch(service: "a") {
{
chat: node(id: "c1") {
__typename
... on Account {
id
}
}
}
},
Fetch(service: "b") {
{
account: node(id: "a1") {
__typename
... on Chat {
id
}
}
}
},
},
},
"#);
Ok(())
}
#[test]
fn direct_object_query_chat_by_id() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
chat(id: "c1") {
id
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Fetch(service: "b") {
{
chat(id: "c1") {
id
}
}
},
},
"#);
Ok(())
}
#[test]
fn direct_object_query_account_by_id() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
account(id: "a1") {
id
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Fetch(service: "a") {
{
account(id: "a1") {
id
}
}
},
},
"#);
Ok(())
}
#[test]
fn object_query_with_nested_object_field() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
chat(id: "c1") {
id
text
account {
id
}
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Sequence {
Fetch(service: "b") {
{
chat(id: "c1") {
__typename
id
text
}
}
},
Flatten(path: "chat") {
Fetch(service: "a") {
{
... on Chat {
__typename
id
}
} =>
{
... on Chat {
account {
id
}
}
}
},
},
},
},
"#);
Ok(())
}
#[test]
fn object_query_with_nested_list_field() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
account(id: "a1") {
id
username
chats {
id
}
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Sequence {
Fetch(service: "a") {
{
account(id: "a1") {
__typename
id
username
}
}
},
Flatten(path: "account") {
Fetch(service: "b") {
{
... on Account {
__typename
id
}
} =>
{
... on Account {
chats {
id
}
}
}
},
},
},
},
"#);
Ok(())
}
#[test]
fn node_query_with_id_on_interface_field() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
node(id: "a1") {
id
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
);
assert!(query_plan.is_err());
Ok(())
}
#[test]
fn node_query_with_multiple_type_fragments() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
node(id: "a1") {
... on Chat {
id
}
... on Account {
id
}
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
);
assert!(query_plan.is_err());
Ok(())
}
#[test]
fn node_query_with_id_and_cross_type_fragment_overlap() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
account: node(id: "a1") {
id
... on Chat {
id
}
}
chat: node(id: "c1") {
__typename
... on Account {
id
}
}
}
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/corrupted-supergraph-node-id.supergraph.graphql",
document,
);
assert!(query_plan.is_err());
Ok(())
}
#[test]
fn type_expand_interface_field() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query {
products {
id
reviews {
id
}
}
}
,
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/abstract-types.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Sequence {
Fetch(service: "products") {
{
products {
id
__typename
}
}
},
Flatten(path: "products.@") {
Fetch(service: "reviews") {
{
... on Book {
__typename
id
}
... on Magazine {
__typename
id
}
} =>
{
... on Book {
reviews {
...a
}
}
... on Magazine {
reviews {
...a
}
}
}
fragment a on Review {
id
}
},
},
},
},
"#);
Ok(())
}
#[test]
fn requires_on_field_with_args_test() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
{
book: similar(id: "p1") {
id
sku
delivery(zip: "1234") {
fastestDelivery
estimatedDelivery
}
}
magazine: similar(id: "p2") {
id
sku
delivery(zip: "1234") {
fastestDelivery
estimatedDelivery
}
}
}
,
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/abstract-types.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Sequence {
Fetch(service: "products") {
{
book: similar(id: "p1") {
...a
}
magazine: similar(id: "p2") {
...a
}
}
fragment a on Product {
id
__typename
sku
dimensions {
weight
size
}
}
},
BatchFetch(service: "inventory") {
{
_e0 {
paths: [
"magazine.@"
"book.@"
]
{
... on Book {
__typename
dimensions {
size
weight
}
id
}
... on Magazine {
__typename
dimensions {
size
weight
}
id
}
}
}
}
{
_e0: _entities(representations: $__batch_reps_0) {
... on Book {
delivery(zip: "1234") {
...a
}
}
... on Magazine {
delivery(zip: "1234") {
...a
}
}
}
}
fragment a on DeliveryEstimates {
... on DeliveryEstimates {
fastestDelivery
estimatedDelivery
}
}
},
},
},
"#);
Ok(())
}
#[test]
fn nested_interface_field_with_inline_fragments() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query ($title: Boolean = true) {
products {
id
reviews {
product {
id
... on Book @include(if: $title) {
title
}
... on Magazine {
sku
}
}
}
}
}
,
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/abstract-types.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Sequence {
Fetch(service: "products") {
{
products {
id
__typename
}
}
},
Flatten(path: "products.@") {
Fetch(service: "reviews") {
{
... on Book {
__typename
id
}
... on Magazine {
__typename
id
}
} =>
{
... on Book {
reviews {
...a
}
}
... on Magazine {
reviews {
...a
}
}
}
fragment a on Review {
product {
id
__typename
}
}
},
},
Parallel {
Include(if: $title) {
Flatten(path: "products.@.reviews.@.product|[Book]") {
Fetch(service: "books") {
{
... on Book {
__typename
id
}
} =>
{
... on Book {
title
}
}
},
},
},
Flatten(path: "products.@.reviews.@.product|[Magazine]") {
Fetch(service: "products") {
{
... on Magazine {
__typename
id
}
} =>
{
... on Magazine {
sku
}
}
},
},
},
},
},
"#);
Ok(())
}
#[test]
fn nested_interface_field_with_redundant_inline_fragments() -> Result<(), Box<dyn Error>> {
init_logger();
let document = parse_operation(
r#"
query ($title: Boolean = true) {
products {
id
reviews {
product {
id
... on Book @include(if: $title) {
title
... on Book {
sku
}
}
... on Magazine {
sku
}
}
}
}
}
,
"#,
);
let query_plan = build_query_plan_with_defaults(
"fixture/tests/abstract-types.supergraph.graphql",
document,
)?;
insta::assert_snapshot!(format!("{}", query_plan), @r#"
QueryPlan {
Sequence {
Fetch(service: "products") {
{
products {
id
__typename
}
}
},
Flatten(path: "products.@") {
Fetch(service: "reviews") {
{
... on Book {
__typename
id
}
... on Magazine {
__typename
id
}
} =>
{
... on Book {
reviews {
...a
}
}
... on Magazine {
reviews {
...a
}
}
}
fragment a on Review {
product {
id
__typename
}
}
},
},
Parallel {
Include(if: $title) {
Flatten(path: "products.@.reviews.@.product|[Book]") {
Fetch(service: "books") {
{
... on Book {
__typename
id
}
} =>
{
... on Book {
title
}
}
},
},
},
Flatten(path: "products.@.reviews.@.product") {
Fetch(service: "products") {
{
... on Book {
__typename
id
}
... on Magazine {
__typename
id
}
} =>
($title:Boolean=true) {
... on Book @include(if: $title) {
sku
}
... on Magazine {
sku
}
}
},
},
},
},
},
"#);
Ok(())
}