Repository: apollographql/apollo-rs (Rust)

Issue:
Missing fragment validation on stadalone executable validation.
## Description

With the following query:

``` graphql
query {
    company { 
        user {
          ...UserFragment
        }
        
        ...CompanyFragment
  }
}

fragment UserFragment on User {
    id
    name
}
```

And with something like this to parse and validate:

``` rust
let document = apollo_compiler::ast::Document.parse(query, path).unwrap();

println!("{:?}", document.validate_standalone_executable());
```

It returns `Ok(())`, but I expected to see a fragment missing error.

I don't know if it's an expected behaviour, but missing fragments is something that can be validated without a schema.

For reference, in "graphql-js"  they do have this validation without the schema:

``` javascript
import graphql from 'graphql.js'

var graph = graphql("/graphql")

graph.fragment({
  UserFragment: `on User {
    id,
    name
  }`
})

const allUsers = graph(`query {
    company {
        user {
          ...UserFragment
        }

        ...CompanyFragment
  }
}`)

await allUsers()


// Error: Fragment CompanyFragment not found
```


Discussion:
https://github.com/apollographql/apollo-rs/pull/1003
Thanks!!! 💜 



Patch:
diff --git a/crates/apollo-compiler/src/validation/field.rs b/crates/apollo-compiler/src/validation/field.rs
index 81d307883..5b8c38831 100644
--- a/crates/apollo-compiler/src/validation/field.rs
+++ b/crates/apollo-compiler/src/validation/field.rs
@@ -33,10 +33,18 @@ pub(crate) fn validate_field(
 
     super::argument::validate_arguments(diagnostics, &field.arguments);
 
-    // Return early if we don't know the type--this can happen if we are nested deeply
-    // inside a selection set that has a wrong field, or if we are validating a standalone
-    // operation without a schema.
+    // If we don't know the type (no schema, or invalid parent), we cannot perform
+    // type-aware checks for this field. However, for standalone executable validation
+    // we still want to traverse into the nested selection set so that validations
+    // that do not require a schema (like missing fragment detection) can run.
     let Some((schema, against_type)) = against_type else {
+        super::selection::validate_selection_set(
+            diagnostics,
+            document,
+            None,
+            &field.selection_set,
+            context,
+        );
         return;
     };
 


Test patch:
diff --git a/crates/apollo-compiler/tests/validation/mod.rs b/crates/apollo-compiler/tests/validation/mod.rs
index 7e733bd61..e5b5ee182 100644
--- a/crates/apollo-compiler/tests/validation/mod.rs
+++ b/crates/apollo-compiler/tests/validation/mod.rs
@@ -352,3 +352,33 @@ type TestObject {
         }"#]];
     expected.assert_eq(&actual);
 }
+
+#[test]
+fn missing_fragment_in_standalone_validation() {
+    let input = r#"
+        query {
+            company {
+                user {
+                  ...UserFragment
+                }
+
+                ...CompanyFragment
+            }
+        }
+
+        fragment UserFragment on User {
+            id
+            name
+        }
+    "#;
+
+    let doc = ast::Document::parse(input, "query.graphql").unwrap();
+    let diagnostics = doc
+        .validate_standalone_executable()
+        .expect_err("should report missing fragment error");
+    let errors = diagnostics.to_string();
+    assert!(
+        errors.contains("cannot find fragment `CompanyFragment` in this document"),
+        "{errors}"
+    );
+}