Skip to content

Commit d211f4a

Browse files
committed
Ensure operation roots resolve their __typename (#372)
1 parent ad64025 commit d211f4a

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
use futures::{stream, StreamExt as _};
2+
use juniper::{graphql_object, graphql_subscription, graphql_value, RootNode, Value, Variables};
3+
4+
pub struct Query;
5+
6+
#[graphql_object]
7+
impl Query {
8+
fn some() -> bool {
9+
true
10+
}
11+
}
12+
13+
pub struct Mutation;
14+
15+
#[graphql_object]
16+
impl Mutation {
17+
fn another() -> bool {
18+
false
19+
}
20+
}
21+
22+
pub struct Subscription;
23+
24+
#[graphql_subscription]
25+
impl Subscription {
26+
async fn another() -> stream::Empty<bool> {
27+
stream::empty()
28+
}
29+
}
30+
31+
#[tokio::test]
32+
async fn implicit_query_typename() {
33+
let query = r#"{ __typename }"#;
34+
35+
let schema = RootNode::new(Query, Mutation, Subscription);
36+
let (res, errors) = juniper::execute(query, None, &schema, &Variables::new(), &())
37+
.await
38+
.unwrap();
39+
40+
assert_eq!(errors.len(), 0);
41+
assert_eq!(res, graphql_value!({"__typename": "Query"}));
42+
}
43+
44+
#[tokio::test]
45+
async fn query_typename() {
46+
let query = r#"query { __typename }"#;
47+
48+
let schema = RootNode::new(Query, Mutation, Subscription);
49+
let (res, errors) = juniper::execute(query, None, &schema, &Variables::new(), &())
50+
.await
51+
.unwrap();
52+
53+
assert_eq!(errors.len(), 0);
54+
assert_eq!(res, graphql_value!({"__typename": "Query"}));
55+
}
56+
57+
#[tokio::test]
58+
async fn explicit_query_typename() {
59+
let query = r#"query Query { __typename }"#;
60+
61+
let schema = RootNode::new(Query, Mutation, Subscription);
62+
let (res, errors) = juniper::execute(query, None, &schema, &Variables::new(), &())
63+
.await
64+
.unwrap();
65+
66+
assert_eq!(errors.len(), 0);
67+
assert_eq!(res, graphql_value!({"__typename": "Query"}));
68+
}
69+
70+
#[tokio::test]
71+
async fn mutation_typename() {
72+
let query = r#"mutation { __typename }"#;
73+
74+
let schema = RootNode::new(Query, Mutation, Subscription);
75+
let (res, errors) = juniper::execute(query, None, &schema, &Variables::new(), &())
76+
.await
77+
.unwrap();
78+
79+
assert_eq!(errors.len(), 0);
80+
assert_eq!(res, graphql_value!({"__typename": "Mutation"}));
81+
}
82+
83+
#[tokio::test]
84+
async fn explicit_mutation_typename() {
85+
let query = r#"mutation Mutation { __typename }"#;
86+
87+
let schema = RootNode::new(Query, Mutation, Subscription);
88+
let (res, errors) = juniper::execute(query, None, &schema, &Variables::new(), &())
89+
.await
90+
.unwrap();
91+
92+
assert_eq!(errors.len(), 0);
93+
assert_eq!(res, graphql_value!({"__typename": "Mutation"}));
94+
}
95+
96+
#[tokio::test]
97+
async fn subscription_typename() {
98+
let query = r#"subscription { __typename }"#;
99+
100+
let schema = RootNode::new(Query, Mutation, Subscription);
101+
let (res, errors) = juniper::resolve_into_stream(query, None, &schema, &Variables::new(), &())
102+
.await
103+
.unwrap();
104+
105+
assert_eq!(errors.len(), 0);
106+
assert!(matches!(res, Value::Object(_)));
107+
if let Value::Object(mut obj) = res {
108+
assert!(obj.contains_field("__typename"));
109+
110+
let val = obj.get_mut_field_value("__typename").unwrap();
111+
assert!(matches!(val, Value::Scalar(_)));
112+
if let Value::Scalar(ref mut stream) = val {
113+
assert_eq!(
114+
stream.next().await,
115+
Some(Ok(graphql_value!("Subscription"))),
116+
);
117+
}
118+
}
119+
}
120+
121+
#[tokio::test]
122+
async fn explicit_subscription_typename() {
123+
let query = r#"subscription Subscription { __typename }"#;
124+
125+
let schema = RootNode::new(Query, Mutation, Subscription);
126+
let (res, errors) = juniper::resolve_into_stream(query, None, &schema, &Variables::new(), &())
127+
.await
128+
.unwrap();
129+
130+
assert_eq!(errors.len(), 0);
131+
assert!(matches!(res, Value::Object(_)));
132+
if let Value::Object(mut obj) = res {
133+
assert!(obj.contains_field("__typename"));
134+
135+
let val = obj.get_mut_field_value("__typename").unwrap();
136+
assert!(matches!(val, Value::Scalar(_)));
137+
if let Value::Scalar(ref mut stream) = val {
138+
assert_eq!(
139+
stream.next().await,
140+
Some(Ok(graphql_value!("Subscription"))),
141+
);
142+
}
143+
}
144+
}

integration_tests/juniper_tests/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ mod infallible_as_field_error;
1313
#[cfg(test)]
1414
mod issue_371;
1515
#[cfg(test)]
16+
mod issue_372;
17+
#[cfg(test)]
1618
mod issue_398;
1719
#[cfg(test)]
1820
mod issue_407;

0 commit comments

Comments
 (0)