diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.expected b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.expected new file mode 100644 index 0000000000000..638d83516b3d8 --- /dev/null +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.expected @@ -0,0 +1,38 @@ +==================================== INPUT ==================================== +# expected-to-throw + +fragment relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_PopStarNameResolverFragment_name on ClientType @argumentDefinitions(scale: {type: "Float!"}) { + name + profile_picture(scale: $scale) +} + +query relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_Query { + ...relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_Fragment +} + +fragment relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_Fragment on Query { + pop_star { + pop_star_name(scale: $scale) + } +} + + +# %extensions% + +type ClientType { + name: String + profile_picture(scale: Float!): String + pop_star_name(scale: Float!): String @relay_resolver(fragment_name: "relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_PopStarNameResolverFragment_name", import_path: "./path/to/PopStarNameResolver.js", , import_name: "pop_star_name") +} + +extend type Query { + pop_star: ClientType @relay_resolver(import_path: "./path/to/PopStarNameResolver.js", import_name: "pop_star") +} +==================================== ERROR ==================================== +✖︎ Operation 'relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_Query' references undefined variable: '$scale'. + + relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.graphql:14:26 + 13 │ pop_star { + 14 │ pop_star_name(scale: $scale) + │ ^^^^^^ + 15 │ } diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.graphql b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.graphql new file mode 100644 index 0000000000000..f5091be68b3e0 --- /dev/null +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.graphql @@ -0,0 +1,29 @@ +# expected-to-throw + +fragment relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_PopStarNameResolverFragment_name on ClientType @argumentDefinitions(scale: {type: "Float!"}) { + name + profile_picture(scale: $scale) +} + +query relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_Query { + ...relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_Fragment +} + +fragment relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_Fragment on Query { + pop_star { + pop_star_name(scale: $scale) + } +} + + +# %extensions% + +type ClientType { + name: String + profile_picture(scale: Float!): String + pop_star_name(scale: Float!): String @relay_resolver(fragment_name: "relayResolverWithArgsFragmentSpreadUsingUndefinedGlobalVariable_PopStarNameResolverFragment_name", import_path: "./path/to/PopStarNameResolver.js", , import_name: "pop_star_name") +} + +extend type Query { + pop_star: ClientType @relay_resolver(import_path: "./path/to/PopStarNameResolver.js", import_name: "pop_star") +} diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.expected b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.expected deleted file mode 100644 index 0b8cc390968df..0000000000000 --- a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.expected +++ /dev/null @@ -1,225 +0,0 @@ -==================================== INPUT ==================================== -fragment relayResolverWithArgsFragmentSpread_PopStarNameResolverFragment_name on ClientType @argumentDefinitions(scale: {type: "Float!"}) { - name - profile_picture(scale: $scale) -} - -query relayResolverWithArgsFragmentSpread_Query { - ...relayResolverWithArgsFragmentSpread_Fragment -} - -fragment relayResolverWithArgsFragmentSpread_Fragment on Query { - pop_star { - pop_star_name(scale: $scale) - } -} - - -# %extensions% - -type ClientType { - name: String - profile_picture(scale: Float!): String - pop_star_name(scale: Float!): String @relay_resolver(fragment_name: "relayResolverWithArgsFragmentSpread_PopStarNameResolverFragment_name", import_path: "./path/to/PopStarNameResolver.js", , import_name: "pop_star_name") -} - -extend type Query { - pop_star: ClientType @relay_resolver(import_path: "./path/to/PopStarNameResolver.js", import_name: "pop_star") -} -==================================== OUTPUT =================================== -{ - "fragment": { - "argumentDefinitions": [], - "kind": "Fragment", - "metadata": null, - "name": "relayResolverWithArgsFragmentSpread_Query", - "selections": [ - { - "args": null, - "kind": "FragmentSpread", - "name": "relayResolverWithArgsFragmentSpread_Fragment" - } - ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": [], - "kind": "Operation", - "name": "relayResolverWithArgsFragmentSpread_Query", - "selections": [ - { - "kind": "ClientEdgeToClientObject", - "backingField": { - "name": "pop_star", - "args": null, - "fragment": null, - "kind": "RelayResolver", - "storageKey": null, - "isOutputType": false - }, - "linkedField": { - "alias": null, - "args": null, - "concreteType": "ClientType", - "kind": "LinkedField", - "name": "pop_star", - "plural": false, - "selections": [ - { - "name": "pop_star_name", - "args": null, - "fragment": { - "kind": "InlineFragment", - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null - }, - { - "alias": null, - "args": [ - { - "kind": "Variable", - "name": "scale", - "variableName": "scale" - } - ], - "kind": "ScalarField", - "name": "profile_picture", - "storageKey": null - } - ], - "type": "ClientType", - "abstractKey": null - }, - "kind": "RelayResolver", - "storageKey": null, - "isOutputType": false - } - ], - "storageKey": null - } - } - ] - }, - "params": { - "cacheID": "94508dc2526a8b7563266e5349ed2265", - "id": null, - "metadata": {}, - "name": "relayResolverWithArgsFragmentSpread_Query", - "operationKind": "query", - "text": null - } -} - -QUERY: - -Query Text is Empty. - -{ - "argumentDefinitions": [ - { - "kind": "RootArgument", - "name": "scale" - } - ], - "kind": "Fragment", - "metadata": { - "hasClientEdges": true - }, - "name": "relayResolverWithArgsFragmentSpread_Fragment", - "selections": [ - { - "kind": "ClientEdgeToClientObject", - "concreteType": "ClientType", - "backingField": { - "alias": null, - "args": null, - "fragment": null, - "kind": "RelayResolver", - "name": "pop_star", - "resolverModule": require('PopStarNameResolver').pop_star, - "path": "pop_star" - }, - "linkedField": { - "alias": null, - "args": null, - "concreteType": "ClientType", - "kind": "LinkedField", - "name": "pop_star", - "plural": false, - "selections": [ - { - "alias": null, - "args": [], - "fragment": { - "args": [ - { - "kind": "Variable", - "name": "scale", - "variableName": "scale" - } - ], - "kind": "FragmentSpread", - "name": "relayResolverWithArgsFragmentSpread_PopStarNameResolverFragment_name" - }, - "kind": "RelayResolver", - "name": "pop_star_name", - "resolverModule": require('PopStarNameResolver').pop_star_name, - "path": "pop_star.pop_star_name" - } - ], - "storageKey": null - } - } - ], - "type": "Query", - "abstractKey": null -} - -{ - "argumentDefinitions": [ - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "scale" - } - ], - "kind": "Fragment", - "metadata": null, - "name": "relayResolverWithArgsFragmentSpread_PopStarNameResolverFragment_name", - "selections": [ - { - "kind": "ClientExtension", - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null - }, - { - "alias": null, - "args": [ - { - "kind": "Variable", - "name": "scale", - "variableName": "scale" - } - ], - "kind": "ScalarField", - "name": "profile_picture", - "storageKey": null - } - ] - } - ], - "type": "ClientType", - "abstractKey": null -} diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.graphql b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.graphql deleted file mode 100644 index 635cfb117c7e5..0000000000000 --- a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.graphql +++ /dev/null @@ -1,27 +0,0 @@ -fragment relayResolverWithArgsFragmentSpread_PopStarNameResolverFragment_name on ClientType @argumentDefinitions(scale: {type: "Float!"}) { - name - profile_picture(scale: $scale) -} - -query relayResolverWithArgsFragmentSpread_Query { - ...relayResolverWithArgsFragmentSpread_Fragment -} - -fragment relayResolverWithArgsFragmentSpread_Fragment on Query { - pop_star { - pop_star_name(scale: $scale) - } -} - - -# %extensions% - -type ClientType { - name: String - profile_picture(scale: Float!): String - pop_star_name(scale: Float!): String @relay_resolver(fragment_name: "relayResolverWithArgsFragmentSpread_PopStarNameResolverFragment_name", import_path: "./path/to/PopStarNameResolver.js", , import_name: "pop_star_name") -} - -extend type Query { - pop_star: ClientType @relay_resolver(import_path: "./path/to/PopStarNameResolver.js", import_name: "pop_star") -} diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.expected b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.expected new file mode 100644 index 0000000000000..1b211ccf6f12f --- /dev/null +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.expected @@ -0,0 +1,22 @@ +==================================== INPUT ==================================== +# expected-to-throw +query validateGlobalVariablesUndefinedQuery { + me { + ...validateGlobalVariablesUndefined_user + } +} + +fragment validateGlobalVariablesUndefined_user on User { + id + ... @include(if: $condition) { + lastName + } +} +==================================== ERROR ==================================== +✖︎ Operation 'validateGlobalVariablesUndefinedQuery' references undefined variable: '$condition'. + + validate-global-variables-undefined.invalid.graphql:10:20 + 9 │ id + 10 │ ... @include(if: $condition) { + │ ^^^^^^^^^^ + 11 │ lastName diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.graphql b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.graphql new file mode 100644 index 0000000000000..e3dcc8efd83b3 --- /dev/null +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.graphql @@ -0,0 +1,13 @@ +# expected-to-throw +query validateGlobalVariablesUndefinedQuery { + me { + ...validateGlobalVariablesUndefined_user + } +} + +fragment validateGlobalVariablesUndefined_user on User { + id + ... @include(if: $condition) { + lastName + } +} diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts_test.rs b/compiler/crates/relay-compiler/tests/compile_relay_artifacts_test.rs index 87b19da840117..760e4af988d22 100644 --- a/compiler/crates/relay-compiler/tests/compile_relay_artifacts_test.rs +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts_test.rs @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<543023a93cfd81f327040c9b43f96de3>> + * @generated SignedSource<<06e1b766183e3717178a63a288c23273>> */ mod compile_relay_artifacts; @@ -1224,10 +1224,10 @@ async fn relay_resolver_with_args_and_alias_no_fragment() { } #[tokio::test] -async fn relay_resolver_with_args_fragment_spread() { - let input = include_str!("compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.graphql"); - let expected = include_str!("compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.expected"); - test_fixture(transform_fixture, "relay-resolver-with-args-fragment-spread.graphql", "compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread.expected", input, expected).await; +async fn relay_resolver_with_args_fragment_spread_using_undefined_global_variable_invalid() { + let input = include_str!("compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.graphql"); + let expected = include_str!("compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.expected"); + test_fixture(transform_fixture, "relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.graphql", "compile_relay_artifacts/fixtures/relay-resolver-with-args-fragment-spread-using-undefined-global-variable.invalid.expected", input, expected).await; } #[tokio::test] @@ -1846,6 +1846,13 @@ async fn validate_global_variables_shared_fragment_invalid() { test_fixture(transform_fixture, "validate-global-variables-shared-fragment.invalid.graphql", "compile_relay_artifacts/fixtures/validate-global-variables-shared-fragment.invalid.expected", input, expected).await; } +#[tokio::test] +async fn validate_global_variables_undefined_invalid() { + let input = include_str!("compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.graphql"); + let expected = include_str!("compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.expected"); + test_fixture(transform_fixture, "validate-global-variables-undefined.invalid.graphql", "compile_relay_artifacts/fixtures/validate-global-variables-undefined.invalid.expected", input, expected).await; +} + #[tokio::test] async fn viewer_query() { let input = include_str!("compile_relay_artifacts/fixtures/viewer-query.graphql"); diff --git a/compiler/crates/relay-transforms/src/apply_transforms.rs b/compiler/crates/relay-transforms/src/apply_transforms.rs index a5c03d6a864e8..9b3d3e85d7c12 100644 --- a/compiler/crates/relay-transforms/src/apply_transforms.rs +++ b/compiler/crates/relay-transforms/src/apply_transforms.rs @@ -550,14 +550,14 @@ fn apply_operation_text_transforms( ) })?; - program = log_event.time("remove_client_edge_selections", || { - remove_client_edge_selections(&program) - })?; - log_event.time("validate_global_variables", || { validate_global_variables(&program) })?; + program = log_event.time("remove_client_edge_selections", || { + remove_client_edge_selections(&program) + })?; + program = log_event.time("replace_updatable_fragment_spreads", || { replace_updatable_fragment_spreads(&program) });