Skip to content

Commit 2931a30

Browse files
committed
Improve error messages when __typename is missing on an union selection
1 parent 03d8eca commit 2931a30

File tree

7 files changed

+33
-22
lines changed

7 files changed

+33
-22
lines changed

graphql_client/tests/union_query.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,20 @@ fn fragment_on_union() {
5656

5757
let expected = fragment_on_union::ResponseData {
5858
names: Some(vec![
59-
fragment_on_union::MyQueryNames::Person(fragment_on_union::MyQueryNamesOnPerson {
60-
first_name: "Audrey".to_string(),
61-
last_name: Some("Lorde".to_string()),
62-
}),
63-
fragment_on_union::MyQueryNames::Dog(fragment_on_union::MyQueryNamesOnDog {
59+
fragment_on_union::FragmentOnUnionNames::Person(
60+
fragment_on_union::MyQueryNamesOnPerson {
61+
first_name: "Audrey".to_string(),
62+
last_name: Some("Lorde".to_string()),
63+
},
64+
),
65+
fragment_on_union::FragmentOnUnionNames::Dog(fragment_on_union::MyQueryNamesOnDog {
6466
name: "Laïka".to_string(),
6567
}),
66-
fragment_on_union::MyQueryNames::Organization(fragment_on_union::MyQueryNamesOnOrganization {
67-
title: "Mozilla".to_string(),
68-
}),
68+
fragment_on_union::FragmentOnUnionNames::Organization(
69+
fragment_on_union::MyQueryNamesOnOrganization {
70+
title: "Mozilla".to_string(),
71+
},
72+
),
6973
fragment_on_union::MyQueryNames::Dog(fragment_on_union::MyQueryNamesOnDog {
7074
name: "Norbert".to_string(),
7175
}),

graphql_client/tests/unions/union_query.graphql

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ fragment NamesFragment on NamedThing {
2929

3030
query FragmentOnUnion {
3131
names {
32-
__typename
3332
...NamesFragment
3433
}
3534
}

graphql_client_codegen/src/codegen.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,8 @@ pub fn response_for_query(
9090
))?
9191
}
9292

93-
definitions.extend(
94-
definition
95-
.field_impls_for_selection(&context, &selection, &prefix)
96-
.unwrap(),
97-
);
98-
definition
99-
.response_fields_for_selection(&context, &selection, &prefix)
100-
.unwrap()
93+
definitions.extend(definition.field_impls_for_selection(&context, &selection, &prefix)?);
94+
definition.response_fields_for_selection(&context, &selection, &prefix)?
10195
};
10296

10397
let enum_definitions = context.schema.enums.values().filter_map(|enm| {

graphql_client_codegen/src/interfaces.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ impl GqlInterface {
131131
let name = Ident::new(&prefix, Span::call_site());
132132
let derives = query_context.response_derives();
133133

134-
selection.extract_typename().ok_or_else(|| {
134+
selection.extract_typename(query_context).ok_or_else(|| {
135135
format_err!(
136136
"Missing __typename in selection for the {} interface (type: {})",
137137
prefix,

graphql_client_codegen/src/selection.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ impl SelectionItem {
4141
pub struct Selection(pub Vec<SelectionItem>);
4242

4343
impl Selection {
44-
pub fn extract_typename(&self) -> Option<&SelectionField> {
44+
pub(crate) fn extract_typename(
45+
&self,
46+
context: &crate::query::QueryContext,
47+
) -> Option<&SelectionField> {
4548
self.0.iter().filter_map(|f| f.as_typename()).next()
4649
}
4750
}
@@ -88,6 +91,14 @@ mod tests {
8891
use super::*;
8992
use graphql_parser;
9093

94+
#[test]
95+
fn selection_extract_typename_simple_case() {
96+
let mut selection = Selection(Vec::new());
97+
let context = query::QueryContext::new_empty();
98+
99+
assert!(selection.extract_typename(&context).is_none());
100+
}
101+
91102
#[test]
92103
fn selection_from_graphql_parser_selection_set() {
93104
let query = r##"

graphql_client_codegen/src/unions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ impl GqlUnion {
105105
let struct_name = Ident::new(prefix, Span::call_site());
106106
let derives = query_context.response_derives();
107107

108-
let typename_field = selection.extract_typename();
108+
// TODO: do this inside fragments
109+
let typename_field = selection.extract_typename(query_context);
109110

110111
if typename_field.is_none() {
111112
Err(UnionError::MissingTypename {

graphql_query_derive/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ pub fn graphql_query_derive(input: proc_macro::TokenStream) -> proc_macro::Token
1919
let ast = syn::parse2(input).expect("Derive input is well formed");
2020
let (query_path, schema_path) = build_query_and_schema_path(&ast);
2121
let options = build_graphql_client_derive_options(&ast);
22-
let gen = generate_module_token_stream(query_path, schema_path, Some(options)).unwrap();
23-
gen.into()
22+
match generate_module_token_stream(query_path, schema_path, Some(options)) {
23+
Ok(module) => module.into(),
24+
Err(err) => panic!("{}", err),
25+
}
2426
}
2527

2628
fn build_query_and_schema_path(

0 commit comments

Comments
 (0)