Skip to content

Commit 3c8cf55

Browse files
committed
Add failing test
1 parent 61c0543 commit 3c8cf55

File tree

2 files changed

+215
-0
lines changed

2 files changed

+215
-0
lines changed

integration_tests/juniper_tests/src/codegen/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ mod derive_enum;
44
mod derive_input_object;
55
mod derive_object;
66
mod scalar_value_transparent;
7+
mod proc_macro_param_attrs;
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
use juniper::*;
2+
use serde_json::{self, Value};
3+
4+
struct Query;
5+
6+
#[juniper::object]
7+
impl Query {
8+
#[graphql(arguments(
9+
arg1(default = true, description = "arg1 desc"),
10+
arg2(default = false, description = "arg2 desc"),
11+
))]
12+
fn field_old_attrs(arg1: bool, arg2: bool) -> bool {
13+
arg1 && arg2
14+
}
15+
16+
fn field_new_attrs(
17+
#[graphql(default = true, description = "arg1 desc")] arg1: bool,
18+
#[graphql(default = false, description = "arg2 desc")] arg2: bool,
19+
) -> bool {
20+
arg1 && arg2
21+
}
22+
}
23+
24+
// The query that GraphiQL runs to inspect the schema
25+
static SCHEMA_INTROSPECTION_QUERY: &str = r#"
26+
query IntrospectionQuery {
27+
__schema {
28+
types {
29+
...FullType
30+
}
31+
}
32+
}
33+
34+
fragment FullType on __Type {
35+
name
36+
fields(includeDeprecated: true) {
37+
name
38+
description
39+
args {
40+
...InputValue
41+
}
42+
}
43+
}
44+
45+
fragment InputValue on __InputValue {
46+
name
47+
description
48+
defaultValue
49+
}
50+
"#;
51+
52+
// TODO: Test for `rename` attr
53+
54+
#[test]
55+
fn descriptions_applied_correctly() {
56+
let schema = introspect_schema();
57+
58+
let query = schema.types.iter().find(|ty| ty.name == "Query").unwrap();
59+
60+
// old deprecated `#[graphql(arguments(...))]` style
61+
{
62+
let field = query
63+
.fields
64+
.iter()
65+
.find(|field| field.name == "fieldOldAttrs")
66+
.unwrap();
67+
68+
let arg1 = field.args.iter().find(|arg| arg.name == "arg1").unwrap();
69+
assert_eq!(&arg1.description, &Some("arg1 desc".to_string()));
70+
assert_eq!(
71+
&arg1.default_value,
72+
&Some(Value::String("true".to_string()))
73+
);
74+
75+
let arg2 = field.args.iter().find(|arg| arg.name == "arg2").unwrap();
76+
assert_eq!(&arg2.description, &Some("arg2 desc".to_string()));
77+
assert_eq!(
78+
&arg2.default_value,
79+
&Some(Value::String("false".to_string()))
80+
);
81+
}
82+
83+
// new style with attrs directly on the args
84+
{
85+
let field = query
86+
.fields
87+
.iter()
88+
.find(|field| field.name == "fieldNewAttrs")
89+
.unwrap();
90+
91+
let arg1 = field.args.iter().find(|arg| arg.name == "arg1").unwrap();
92+
assert_eq!(&arg1.description, &Some("arg1 desc".to_string()));
93+
assert_eq!(
94+
&arg1.default_value,
95+
&Some(Value::String("true".to_string()))
96+
);
97+
98+
let arg2 = field.args.iter().find(|arg| arg.name == "arg2").unwrap();
99+
assert_eq!(&arg2.description, &Some("arg2 desc".to_string()));
100+
assert_eq!(
101+
&arg2.default_value,
102+
&Some(Value::String("false".to_string()))
103+
);
104+
}
105+
}
106+
107+
#[derive(Debug)]
108+
struct Schema {
109+
types: Vec<Type>,
110+
}
111+
112+
#[derive(Debug)]
113+
struct Type {
114+
name: String,
115+
fields: Vec<Field>,
116+
}
117+
118+
#[derive(Debug)]
119+
struct Field {
120+
name: String,
121+
args: Vec<Arg>,
122+
description: Option<String>,
123+
}
124+
125+
#[derive(Debug)]
126+
struct Arg {
127+
name: String,
128+
description: Option<String>,
129+
default_value: Option<Value>,
130+
}
131+
132+
fn introspect_schema() -> Schema {
133+
let (value, _errors) = juniper::execute(
134+
SCHEMA_INTROSPECTION_QUERY,
135+
None,
136+
&RootNode::new(Query, juniper::EmptyMutation::new()),
137+
&Variables::new(),
138+
&(),
139+
)
140+
.unwrap();
141+
142+
let value: Value = serde_json::from_str(&serde_json::to_string(&value).unwrap()).unwrap();
143+
144+
let types = value["__schema"]["types"]
145+
.as_array()
146+
.unwrap()
147+
.iter()
148+
.map(parse_type)
149+
.collect::<Vec<_>>();
150+
151+
Schema { types }
152+
}
153+
154+
fn parse_type(value: &Value) -> Type {
155+
let name = value["name"].as_str().unwrap().to_string();
156+
157+
let fields = if value["fields"].is_null() {
158+
vec![]
159+
} else {
160+
value["fields"]
161+
.as_array()
162+
.unwrap()
163+
.iter()
164+
.map(parse_field)
165+
.collect::<Vec<_>>()
166+
};
167+
168+
Type { name, fields }
169+
}
170+
171+
fn parse_field(value: &Value) -> Field {
172+
let name = value["name"].as_str().unwrap().to_string();
173+
174+
let description = if value["description"].is_null() {
175+
None
176+
} else {
177+
Some(value["description"].as_str().unwrap().to_string())
178+
};
179+
180+
let args = value["args"]
181+
.as_array()
182+
.unwrap()
183+
.iter()
184+
.map(parse_arg)
185+
.collect::<Vec<_>>();
186+
187+
Field {
188+
name,
189+
description,
190+
args,
191+
}
192+
}
193+
194+
fn parse_arg(value: &Value) -> Arg {
195+
let name = value["name"].as_str().unwrap().to_string();
196+
197+
let description = if value["description"].is_null() {
198+
None
199+
} else {
200+
Some(value["description"].as_str().unwrap().to_string())
201+
};
202+
203+
let default_value = if value["defaultValue"].is_null() {
204+
None
205+
} else {
206+
Some(value["defaultValue"].clone())
207+
};
208+
209+
Arg {
210+
name,
211+
description,
212+
default_value,
213+
}
214+
}

0 commit comments

Comments
 (0)