Repository: apollographql/apollo-rs
Pull request #441 (2023-01-28 17:21:53)

feat(compiler): validate nested fields for definition on their types
Following up on #436 and #392, I extended the validation to nested fields. To achieve that, I changed the `validate_selection_set` `validate_selection` and `validate_field` functions to accept the `TypeDef` alongside the relevant value. 
Please let me know what you think of this approach. If this is favorable, I will fix the linting and add extensive unit testing. 
Please also see my tagged TODO items. Some of them don't match the scope of this PR, but I'm happy to address them in follow-up PRs. The tests are still failing because I need to fix some undefined field errors in the graphql documents folder.

apollo-cla: @erikwrede: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Apollo Contributor License Agreement here: https://contribute.apollographql.com/
erikwrede: After checking, it seems like I need to refactor almost all of the doc tests because they contain nested undefined fields / fields only available on implementations of the interfaces. I believe the tests could benefit from some streamlining so they are reduced to exactly the case that causes an error. Are there any open tasks regarding these that I could take into account? I'd prefer to do the refactor in a separate PR.
erikwrede: Thanks for the review, I will address your comments this weekend 🙂 

Patch:
diff --git a/crates/apollo-compiler/README.md b/crates/apollo-compiler/README.md
index 7d73371..4ce8dde 100644
--- a/crates/apollo-compiler/README.md
+++ b/crates/apollo-compiler/README.md
@@ -299,7 +299,7 @@ let diagnostics = compiler.validate();
 for diagnostic in &diagnostics {
     println!("{}", diagnostic)
 }
-assert_eq!(diagnostics.len(), 5)
+assert_eq!(diagnostics.len(), 9)
 ```
 
 ## License
diff --git a/crates/apollo-compiler/src/database/hir.rs b/crates/apollo-compiler/src/database/hir.rs
index c658130..6c5ceeb 100644
--- a/crates/apollo-compiler/src/database/hir.rs
+++ b/crates/apollo-compiler/src/database/hir.rs
@@ -130,6 +130,17 @@ impl TypeDefinition {
             _ => None,
         }
     }
+
+    pub fn loc(&self) -> Option<HirNodeLocation> {
+        match self {
+            Self::ObjectTypeDefinition(def) => Some(def.loc()),
+            Self::InterfaceTypeDefinition(def) => Some(def.loc()),
+            Self::UnionTypeDefinition(def) => Some(def.loc()),
+            Self::EnumTypeDefinition(def) => Some(def.loc()),
+            Self::InputObjectTypeDefinition(def) => Some(def.loc()),
+            Self::ScalarTypeDefinition(def) => def.loc(),
+        }
+    }
 }
 
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
diff --git a/crates/apollo-compiler/src/validation/field.rs b/crates/apollo-compiler/src/validation/field.rs
index fa35da5..cfb0575 100644
--- a/crates/apollo-compiler/src/validation/field.rs
+++ b/crates/apollo-compiler/src/validation/field.rs
@@ -14,6 +14,44 @@ pub fn validate_field(
         db.validate_directives(field.directives().to_vec(), hir::DirectiveLocation::Field);
     diagnostics.extend(db.validate_arguments(field.arguments().to_vec()));
 
+    let field_type = field.ty(db.upcast());
+    if field_type.is_some() {
+        diagnostics.extend(db.validate_selection_set(field.selection_set().clone()));
+    } else {
+        let help = format!(
+            "`{}` is not defined on `{}` type",
+            field.name(),
+            field.parent_obj.as_ref().unwrap(),
+        );
+        let field_name = field.name();
+        let diagnostic = ApolloDiagnostic::new(
+            db,
+            field.loc().into(),
+            DiagnosticData::UndefinedField {
+                field: field_name.into(),
+            },
+        )
+        .label(Label::new(
+            field.loc(),
+            format!("`{field_name}` field is not defined"),
+        ))
+        .help(help);
+
+        let parent_type_loc = db
+            .find_type_definition_by_name(field.parent_obj.clone().unwrap())
+            .and_then(|type_def| type_def.loc());
+
+        let diagnostic = if let Some(parent_type_loc) = parent_type_loc {
+            diagnostic.label(Label::new(
+                parent_type_loc,
+                format!("`{}` declared here", field.parent_obj.as_ref().unwrap()),
+            ))
+        } else {
+            diagnostic
+        };
+        diagnostics.push(diagnostic);
+    }
+
     diagnostics
 }
 
@@ -61,13 +99,13 @@ pub fn validate_field_definitions(
                         field: field_name.into(),
                         original_definition: original_definition.into(),
                         redefined_definition: redefined_definition.into(),
-                    }
+                    },
                 )
-                .labels([
-                    Label::new(original_definition, format!("previous definition of `{field_name}` here")),
-                    Label::new(redefined_definition, format!("`{field_name}` redefined here")),
-                ])
-                .help(format!("`{field_name}` field must only be defined once in this input object definition."))
+                    .labels([
+                        Label::new(original_definition, format!("previous definition of `{field_name}` here")),
+                        Label::new(redefined_definition, format!("`{field_name}` redefined here")),
+                    ])
+                    .help(format!("`{field_name}` field must only be defined once in this input object definition."))
             );
         } else {
             seen.insert(field_name, field);
@@ -81,8 +119,8 @@ pub fn validate_field_definitions(
                         name: field.name().into(),
                         ty: field_ty.kind(),
                     })
-                    .label(Label::new(field.loc(), format!("this is of `{}` type", field_ty.kind())))
-                    .help(format!("Scalars, Objects, Interfaces, Unions and Enums are output types. Change `{}` field to return one of these output types.", field.name())),
+                        .label(Label::new(field.loc(), format!("this is of `{}` type", field_ty.kind())))
+                        .help(format!("Scalars, Objects, Interfaces, Unions and Enums are output types. Change `{}` field to return one of these output types.", field.name())),
                 );
             }
         } else if let Some(field_ty_loc) = field.ty().loc() {
diff --git a/crates/apollo-compiler/src/validation/fragment.rs b/crates/apollo-compiler/src/validation/fragment.rs
index e36ac9c..6022673 100644
--- a/crates/apollo-compiler/src/validation/fragment.rs
+++ b/crates/apollo-compiler/src/validation/fragment.rs
@@ -10,8 +10,48 @@ pub fn validate_fragment_definitions(
             def.directives().to_vec(),
             DirectiveLocation::FragmentDefinition,
         ));
-        diagnostics.extend(db.validate_selection_set(def.selection_set().clone()));
+
+        let fragment_type_def = db.find_type_definition_by_name(def.type_condition().to_string());
+        // Make sure the fragment type exists in the schema
+        if fragment_type_def.is_some() {
+            // TODO handle cases where the type does not support fragments (Enum, Scalar...)
+            diagnostics.extend(db.validate_selection_set(def.selection_set().clone()));
+        }
     }
 
     diagnostics
 }
+
+#[cfg(test)]
+mod test {
+    use crate::ApolloCompiler;
+
+    #[test]
+    fn it_validates_fields_in_fragment_definitions() {
+        let input = r#"
+type Query {
+  name: String
+  topProducts: Product
+}
+
+type Product {
+  inStock: Boolean
+  name: String
+}
+
+fragment XY on Product {
+  notExistingField
+}
+"#;
+
+        let mut compiler = ApolloCompiler::new();
+        compiler.add_document(input, "schema.graphql");
+
+        let diagnostics = compiler.validate();
+        for diagnostic in &diagnostics {
+            println!("{diagnostic}");
+        }
+
+        assert_eq!(diagnostics.len(), 1)
+    }
+}
diff --git a/crates/apollo-compiler/src/validation/operation.rs b/crates/apollo-compiler/src/validation/operation.rs
index d3e25c4..006557d 100644
--- a/crates/apollo-compiler/src/validation/operation.rs
+++ b/crates/apollo-compiler/src/validation/operation.rs
@@ -16,7 +16,12 @@ pub fn validate_operation_definitions(
         diagnostics
             .extend(db.validate_directives(def.directives().to_vec(), def.operation_ty().into()));
         diagnostics.extend(db.validate_variable_definitions(def.variables.as_ref().clone()));
-        diagnostics.extend(db.validate_selection_set(def.selection_set().clone()));
+
+        // Validate the Selection Set recursively
+        // Check that the root type exists
+        if def.object_type(db.upcast()).is_some() {
+            diagnostics.extend(db.validate_selection_set(def.selection_set().clone()));
+        }
     }
 
     let subscription_operations = db.upcast().subscription_operations(file_id);
@@ -93,50 +98,6 @@ pub fn validate_operation_definitions(
         }
     }
 
-    // Fields must exist on the type being queried.
-    for op in operations.iter() {
-        for selection in op.selection_set().selection() {
-            let obj_type = op.object_type(db.upcast());
-            let obj_name = obj_type.as_ref().map(|obj| obj.name().to_owned());
-            if let hir::Selection::Field(field) = selection {
-                if field.ty(db.upcast()).is_none() {
-                    let field_name = field.name();
-                    let help = if let Some(actual_name) = obj_name {
-                        format!("`{field_name}` is not defined on `{actual_name}` type")
-                    } else {
-                        format!(
-                            "`{}` is not defined on the current {} root operation type.",
-                            field_name,
-                            op.operation_ty()
-                        )
-                    };
-                    let diagnostic = ApolloDiagnostic::new(
-                        db,
-                        field.loc().into(),
-                        DiagnosticData::UndefinedField {
-                            field: field_name.into(),
-                        },
-                    )
-                    .label(Label::new(
-                        field.loc(),
-                        format!("`{field_name}` field is not defined"),
-                    ))
-                    .help(help);
-
-                    let diagnostic = if let Some(ty) = obj_type {
-                        diagnostic.label(Label::new(
-                            ty.loc(),
-                            format!("`{}` declared here", ty.name()),
-                        ))
-                    } else {
-                        diagnostic
-                    };
-                    diagnostics.push(diagnostic)
-                }
-            }
-        }
-    }
-
     diagnostics
 }
 
@@ -317,51 +278,25 @@ query {
 
 query getPet {
   cat {
-    owner {
-      name
-    }
+    name
   }
 }
 
-query getPet {
+query getOtherPet {
   cat {
-    treat
-  }
-}
-
-subscription sub {
-  newMessage {
-    body
-    sender
+    nickname
   }
-  disallowedSecondRootField
 }
 
 type Query {
-  cat: Pet
+  cat: Cat
 }
 
-type Subscription {
-  newMessage: Result
-}
-
-interface Pet {
-  name: String
-}
-
-type Dog implements Pet {
-  name: String
-  nickname: String
-  barkVolume: Int
-}
-
-type Cat implements Pet {
+type Cat {
   name: String
   nickname: String
   meowVolume: Int
 }
-
-union CatOrDog = Cat | Dog
 "#;
         let mut compiler = ApolloCompiler::new();
         compiler.add_document(input, "schema.graphql");
@@ -370,7 +305,7 @@ union CatOrDog = Cat | Dog
         for diagnostic in &diagnostics {
             println!("{diagnostic}")
         }
-        assert_eq!(diagnostics.len(), 5)
+        assert_eq!(diagnostics.len(), 1)
     }
 
     #[test]
@@ -384,9 +319,8 @@ query getName {
 
 query getName {
   cat {
-    owner {
-      name
-    }
+    name
+    nickname
   }
 }
 
@@ -398,6 +332,7 @@ union CatOrDog = Cat | Dog
 
 interface Pet {
   name: String
+  nickname: String
 }
 
 type Dog implements Pet {
@@ -431,11 +366,9 @@ query getCatName {
   }
 }
 
-query getOwnerName {
+query getPetNickname {
   cat {
-    owner {
-      name
-    }
+    nickname
   }
 }
 
@@ -447,6 +380,7 @@ union CatOrDog = Cat | Dog
 
 interface Pet {
   name: String
+  nickname: String
 }
 
 type Dog implements Pet {
@@ -465,6 +399,9 @@ type Cat implements Pet {
         compiler.add_document(input, "schema.graphql");
 
         let diagnostics = compiler.validate();
+        for diagnostic in &diagnostics {
+            println!("{diagnostic}")
+        }
         assert!(diagnostics.is_empty());
     }
 
@@ -508,15 +445,19 @@ type Cat implements Pet {
             println!("{diagnostic}")
         }
 
-        assert_eq!(diagnostics.len(), 2)
+        assert_eq!(diagnostics.len(), 1)
     }
 
     #[test]
     fn it_validates_fields_in_operations() {
         let input = r#"
 query getProduct {
-  size
-  weight
+  name
+  noName
+  topProducts {
+    inStock
+    price
+  }
 }
 
 type Query {
@@ -525,11 +466,9 @@ type Query {
 }
 
 type Product {
-  inStock: Boolean @join__field(graph: INVENTORY)
-  name: String @join__field(graph: PRODUCTS)
+  inStock: Boolean
+  name: String
 }
-
-directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION
 "#;
 
         let mut compiler = ApolloCompiler::new();
diff --git a/crates/apollo-compiler/src/validation/selection.rs b/crates/apollo-compiler/src/validation/selection.rs
index 80f4dfc..311018e 100644
--- a/crates/apollo-compiler/src/validation/selection.rs
+++ b/crates/apollo-compiler/src/validation/selection.rs
@@ -11,12 +11,10 @@ pub fn validate_selection(
     for sel in selection.iter() {
         match sel {
             hir::Selection::Field(field) => {
-                if !field.selection_set().selection().is_empty() {
-                    diagnostics
-                        .extend(db.validate_selection(field.selection_set().selection.clone()))
-                }
                 diagnostics.extend(db.validate_field(field.clone()));
             }
+
+            // TODO handle fragment spreads on invalid parent types
             hir::Selection::FragmentSpread(frag) => diagnostics.extend(db.validate_directives(
                 frag.directives().to_vec(),
                 hir::DirectiveLocation::FragmentSpread,
@@ -35,5 +33,11 @@ pub fn validate_selection_set(
     db: &dyn ValidationDatabase,
     selection_set: hir::SelectionSet,
 ) -> Vec<ApolloDiagnostic> {
-    db.validate_selection(selection_set.selection)
+    let mut diagnostics = Vec::new();
+
+    // TODO handle Enums, Scalar (no selection set content allowed), Unions
+
+    diagnostics.extend(db.validate_selection(selection_set.selection));
+
+    diagnostics
 }
diff --git a/crates/apollo-compiler/src/validation/variable.rs b/crates/apollo-compiler/src/validation/variable.rs
index 4071200..205b46f 100644
--- a/crates/apollo-compiler/src/validation/variable.rs
+++ b/crates/apollo-compiler/src/validation/variable.rs
@@ -187,6 +187,7 @@ fragment fragmentOne on Query {
 
 type Query {
   topProducts: Product
+  profilePic(size: Int): String
 }
 
 type Product {


Test patch:
diff --git a/crates/apollo-compiler/test_data/diagnostics/0001_duplicate_operatoin_names.graphql b/crates/apollo-compiler/test_data/diagnostics/0001_duplicate_operatoin_names.graphql
index b1ac364..dcc364e 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0001_duplicate_operatoin_names.graphql
+++ b/crates/apollo-compiler/test_data/diagnostics/0001_duplicate_operatoin_names.graphql
@@ -1,15 +1,9 @@
 query getName {
-  cat {
-    name
-  }
+  cat
 }
 
 query getName {
-  cat {
-    owner {
-      name
-    }
-  }
+  cat
 }
 
 type Query {
diff --git a/crates/apollo-compiler/test_data/diagnostics/0001_duplicate_operatoin_names.txt b/crates/apollo-compiler/test_data/diagnostics/0001_duplicate_operatoin_names.txt
index aee8cd1..cf46bf3 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0001_duplicate_operatoin_names.txt
+++ b/crates/apollo-compiler/test_data/diagnostics/0001_duplicate_operatoin_names.txt
@@ -7,7 +7,7 @@
             file_id: FileId {
                 id: 0,
             },
-            offset: 46,
+            offset: 31,
             length: 7,
         },
         labels: [
@@ -26,7 +26,7 @@
                     file_id: FileId {
                         id: 0,
                     },
-                    offset: 46,
+                    offset: 31,
                     length: 7,
                 },
                 text: "`getName` redefined here",
@@ -49,7 +49,7 @@
                 file_id: FileId {
                     id: 0,
                 },
-                offset: 46,
+                offset: 31,
                 length: 7,
             },
         },
diff --git a/crates/apollo-compiler/test_data/diagnostics/0002_multiple_anonymous_operations.graphql b/crates/apollo-compiler/test_data/diagnostics/0002_multiple_anonymous_operations.graphql
index ee5985f..546049b 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0002_multiple_anonymous_operations.graphql
+++ b/crates/apollo-compiler/test_data/diagnostics/0002_multiple_anonymous_operations.graphql
@@ -1,14 +1,10 @@
 query {
-  cat {
-    name
-  }
+  cat
 }
 
 mutation {
   addPet {
-    owner {
-      name
-    }
+    response
   }
 }
 
diff --git a/crates/apollo-compiler/test_data/diagnostics/0002_multiple_anonymous_operations.txt b/crates/apollo-compiler/test_data/diagnostics/0002_multiple_anonymous_operations.txt
index cffe8f0..8724923 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0002_multiple_anonymous_operations.txt
+++ b/crates/apollo-compiler/test_data/diagnostics/0002_multiple_anonymous_operations.txt
@@ -8,7 +8,7 @@
                 id: 1,
             },
             offset: 0,
-            length: 30,
+            length: 15,
         },
         labels: [
             Label {
@@ -17,7 +17,7 @@
                         id: 1,
                     },
                     offset: 0,
-                    length: 30,
+                    length: 15,
                 },
                 text: "provide a name for this definition",
             },
@@ -35,8 +35,8 @@
             file_id: FileId {
                 id: 1,
             },
-            offset: 32,
-            length: 56,
+            offset: 17,
+            length: 40,
         },
         labels: [
             Label {
@@ -44,8 +44,8 @@
                     file_id: FileId {
                         id: 1,
                     },
-                    offset: 32,
-                    length: 56,
+                    offset: 17,
+                    length: 40,
                 },
                 text: "provide a name for this definition",
             },
diff --git a/crates/apollo-compiler/test_data/diagnostics/0003_anonymous_and_named_operation.graphql b/crates/apollo-compiler/test_data/diagnostics/0003_anonymous_and_named_operation.graphql
index 80354f4..8d6bd73 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0003_anonymous_and_named_operation.graphql
+++ b/crates/apollo-compiler/test_data/diagnostics/0003_anonymous_and_named_operation.graphql
@@ -1,14 +1,10 @@
 query {
-  cat {
-    name
-  }
+  cat
 }
 
 mutation getName {
   addPet {
-    owner {
-      name
-    }
+    response
   }
 }
 
diff --git a/crates/apollo-compiler/test_data/diagnostics/0003_anonymous_and_named_operation.txt b/crates/apollo-compiler/test_data/diagnostics/0003_anonymous_and_named_operation.txt
index 7cac0ce..517969b 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0003_anonymous_and_named_operation.txt
+++ b/crates/apollo-compiler/test_data/diagnostics/0003_anonymous_and_named_operation.txt
@@ -8,7 +8,7 @@
                 id: 2,
             },
             offset: 0,
-            length: 30,
+            length: 15,
         },
         labels: [
             Label {
@@ -17,7 +17,7 @@
                         id: 2,
                     },
                     offset: 0,
-                    length: 30,
+                    length: 15,
                 },
                 text: "provide a name for this definition",
             },
diff --git a/crates/apollo-compiler/test_data/diagnostics/0004_subscription_with_multiple_root_fields.graphql b/crates/apollo-compiler/test_data/diagnostics/0004_subscription_with_multiple_root_fields.graphql
index c5cf392..e8aef3d 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0004_subscription_with_multiple_root_fields.graphql
+++ b/crates/apollo-compiler/test_data/diagnostics/0004_subscription_with_multiple_root_fields.graphql
@@ -8,6 +8,7 @@ subscription sub {
 
 type Subscription {
   newMessage: Result
+  disallowedSecondRootField: String
 }
 
 type Result {
diff --git a/crates/apollo-compiler/test_data/diagnostics/0004_subscription_with_multiple_root_fields.txt b/crates/apollo-compiler/test_data/diagnostics/0004_subscription_with_multiple_root_fields.txt
index 156cb65..e151cff 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0004_subscription_with_multiple_root_fields.txt
+++ b/crates/apollo-compiler/test_data/diagnostics/0004_subscription_with_multiple_root_fields.txt
@@ -36,44 +36,4 @@
             },
         },
     },
-    ApolloDiagnostic {
-        cache: {
-            3: "0004_subscription_with_multiple_root_fields.graphql",
-        },
-        location: DiagnosticLocation {
-            file_id: FileId {
-                id: 3,
-            },
-            offset: 60,
-            length: 25,
-        },
-        labels: [
-            Label {
-                location: DiagnosticLocation {
-                    file_id: FileId {
-                        id: 3,
-                    },
-                    offset: 60,
-                    length: 25,
-                },
-                text: "`disallowedSecondRootField` field is not defined",
-            },
-            Label {
-                location: DiagnosticLocation {
-                    file_id: FileId {
-                        id: 3,
-                    },
-                    offset: 89,
-                    length: 42,
-                },
-                text: "`Subscription` declared here",
-            },
-        ],
-        help: Some(
-            "`disallowedSecondRootField` is not defined on `Subscription` type",
-        ),
-        data: UndefinedField {
-            field: "disallowedSecondRootField",
-        },
-    },
 ]
diff --git a/crates/apollo-compiler/test_data/diagnostics/0005_subscription_with_multiple_root_fields_in_fragment_spreads.graphql b/crates/apollo-compiler/test_data/diagnostics/0005_subscription_with_multiple_root_fields_in_fragment_spreads.graphql
index a4e608a..c0d8464 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0005_subscription_with_multiple_root_fields_in_fragment_spreads.graphql
+++ b/crates/apollo-compiler/test_data/diagnostics/0005_subscription_with_multiple_root_fields_in_fragment_spreads.graphql
@@ -12,6 +12,7 @@ fragment multipleSubscriptions on Subscription {
 
 type Subscription {
   newMessage: Result
+  disallowedSecondRootField: String
 }
 
 type Result {
diff --git a/crates/apollo-compiler/test_data/diagnostics/0011_syntactic_errors_from_parser.graphql b/crates/apollo-compiler/test_data/diagnostics/0011_syntactic_errors_from_parser.graphql
index 36c714e..207c226 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0011_syntactic_errors_from_parser.graphql
+++ b/crates/apollo-compiler/test_data/diagnostics/0011_syntactic_errors_from_parser.graphql
@@ -11,4 +11,5 @@ type Query {
 
 type Product {
   name: String
+  birthday: String
 }
\ No newline at end of file
diff --git a/crates/apollo-compiler/test_data/diagnostics/0014_subscription_operation_without_subscription_schema_operation_type.txt b/crates/apollo-compiler/test_data/diagnostics/0014_subscription_operation_without_subscription_schema_operation_type.txt
index 97cf048..0a4438f 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0014_subscription_operation_without_subscription_schema_operation_type.txt
+++ b/crates/apollo-compiler/test_data/diagnostics/0014_subscription_operation_without_subscription_schema_operation_type.txt
@@ -37,34 +37,4 @@
             ty: "subscription",
         },
     },
-    ApolloDiagnostic {
-        cache: {
-            13: "0014_subscription_operation_without_subscription_schema_operation_type.graphql",
-        },
-        location: DiagnosticLocation {
-            file_id: FileId {
-                id: 13,
-            },
-            offset: 37,
-            length: 36,
-        },
-        labels: [
-            Label {
-                location: DiagnosticLocation {
-                    file_id: FileId {
-                        id: 13,
-                    },
-                    offset: 37,
-                    length: 36,
-                },
-                text: "`newMessage` field is not defined",
-            },
-        ],
-        help: Some(
-            "`newMessage` is not defined on the current Subscription root operation type.",
-        ),
-        data: UndefinedField {
-            field: "newMessage",
-        },
-    },
 ]
diff --git a/crates/apollo-compiler/test_data/diagnostics/0015_mutation_operation_without_mutation_schema_definition.txt b/crates/apollo-compiler/test_data/diagnostics/0015_mutation_operation_without_mutation_schema_definition.txt
index d95a0f4..7567792 100644
--- a/crates/apollo-compiler/test_data/diagnostics/0015_mutation_operation_without_mutation_schema_definition.txt
+++ b/crates/apollo-compiler/test_data/diagnostics/0015_mutation_operation_without_mutation_schema_definition.txt
@@ -29,34 +29,4 @@
             ty: "mutation",
         },
     },
-    ApolloDiagnostic {
-        cache: {
-            14: "0015_mutation_operation_without_mutation_schema_definition.graphql",
-        },
-        location: DiagnosticLocation {
-            file_id: FileId {
-                id: 14,
-            },
-            offset: 31,
-            length: 41,
-        },
-        labels: [
-            Label {
-                location: DiagnosticLocation {
-                    file_id: FileId {
-                        id: 14,
-                    },
-                    offset: 31,
-                    length: 41,
-                },
-                text: "`addPet` field is not defined",
-            },
-        ],
-        help: Some(
-            "`addPet` is not defined on the current Mutation root operation type.",
-        ),
-        data: UndefinedField {
-            field: "addPet",
-        },
-    },
 ]