From 1fc6e4a65e488b71faad018d2b09606a50f67ce7 Mon Sep 17 00:00:00 2001 From: tobias-tengler <45513122+tobias-tengler@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:04:10 +0100 Subject: [PATCH 1/3] Add enable_fragment_argument_transform feature flag --- compiler/crates/common/src/feature_flags.rs | 5 +++++ compiler/crates/graphql-syntax/src/lib.rs | 22 +++++++++---------- compiler/crates/graphql-syntax/src/parser.rs | 4 ++-- .../crates/relay-compiler/src/compiler.rs | 1 + .../crates/relay-compiler/src/graphql_asts.rs | 20 ++++++++++++++--- compiler/crates/relay-compiler/src/lib.rs | 2 ++ compiler/crates/relay-compiler/src/utils.rs | 16 ++++++++++++++ .../crates/relay-lsp/src/graphql_tools/mod.rs | 9 ++++++-- .../crates/relay-lsp/src/server/lsp_state.rs | 22 +++++++++++++------ .../src/server/lsp_state_resources.rs | 1 + compiler/crates/relay-lsp/src/utils.rs | 20 ++++++++++++----- 11 files changed, 92 insertions(+), 30 deletions(-) create mode 100644 compiler/crates/relay-compiler/src/utils.rs diff --git a/compiler/crates/common/src/feature_flags.rs b/compiler/crates/common/src/feature_flags.rs index d60358077067c..eae4c5e8fad84 100644 --- a/compiler/crates/common/src/feature_flags.rs +++ b/compiler/crates/common/src/feature_flags.rs @@ -99,6 +99,11 @@ pub struct FeatureFlags { /// excludes resolver metadata from reader ast #[serde(default)] pub disable_resolver_reader_ast: bool, + + /// Add support for parsing and transforming variable definitions on fragment + /// definitions and arguments on fragment spreads. + #[serde(default)] + pub enable_fragment_argument_transform: bool, } #[derive(Debug, Deserialize, Clone, Serialize, Default)] diff --git a/compiler/crates/graphql-syntax/src/lib.rs b/compiler/crates/graphql-syntax/src/lib.rs index 069c2f5a62207..ccd44a22d9a8a 100644 --- a/compiler/crates/graphql-syntax/src/lib.rs +++ b/compiler/crates/graphql-syntax/src/lib.rs @@ -59,6 +59,17 @@ pub fn parse_executable( parse_executable_with_error_recovery(source, source_location).into() } +/// Parses a GraphQL document that's restricted to executable +/// definitions with custom feature flags passed as `features`. +pub fn parse_executable_with_features( + source: &str, + source_location: SourceLocationKey, + features: ParserFeatures, +) -> DiagnosticsResult { + parse_executable_with_error_recovery_and_parser_features(source, source_location, features) + .into() +} + /// Parses a GraphQL document that's restricted to executable definitions, /// with error recovery. pub fn parse_executable_with_error_recovery( @@ -81,17 +92,6 @@ pub fn parse_executable_with_error_recovery_and_parser_features( parser.parse_executable_document() } -/// Parses a GraphQL document that's restricted to executable -/// definitions with custom feature flags passed as `features`. -pub fn parse_executable_with_features( - source: &str, - source_location: SourceLocationKey, - features: ParserFeatures, -) -> DiagnosticsResult { - parse_executable_with_error_recovery_and_parser_features(source, source_location, features) - .into() -} - /// Parses a GraphQL document that's restricted to type system definitions /// including schema definition, type definitions and type system extensions. pub fn parse_schema_document( diff --git a/compiler/crates/graphql-syntax/src/parser.rs b/compiler/crates/graphql-syntax/src/parser.rs index f6df7d1f65c83..630528a11e6bd 100644 --- a/compiler/crates/graphql-syntax/src/parser.rs +++ b/compiler/crates/graphql-syntax/src/parser.rs @@ -22,7 +22,7 @@ use crate::syntax_error::SyntaxError; type ParseResult = Result; -#[derive(Default, PartialEq)] +#[derive(Default, Clone, Copy, PartialEq)] pub enum FragmentArgumentSyntaxKind { #[default] None, @@ -30,7 +30,7 @@ pub enum FragmentArgumentSyntaxKind { SpreadArgumentsAndFragmentVariableDefinitions, } -#[derive(Default)] +#[derive(Default, Clone, Copy)] pub struct ParserFeatures { /// Whether and how to enable the experimental fragment variables definitions syntax pub fragment_argument_capability: FragmentArgumentSyntaxKind, diff --git a/compiler/crates/relay-compiler/src/compiler.rs b/compiler/crates/relay-compiler/src/compiler.rs index 11ba2dec193ff..8e6d1951138c1 100644 --- a/compiler/crates/relay-compiler/src/compiler.rs +++ b/compiler/crates/relay-compiler/src/compiler.rs @@ -303,6 +303,7 @@ async fn build_projects( GraphQLAsts::from_graphql_sources_map( &compiler_state.graphql_sources, &dirty_artifact_sources, + &config, ) })?; diff --git a/compiler/crates/relay-compiler/src/graphql_asts.rs b/compiler/crates/relay-compiler/src/graphql_asts.rs index 3543d11a4e326..efd4d889540dd 100644 --- a/compiler/crates/relay-compiler/src/graphql_asts.rs +++ b/compiler/crates/relay-compiler/src/graphql_asts.rs @@ -9,6 +9,7 @@ use std::collections::hash_map::Entry; use std::collections::HashSet; use std::path::Path; use std::path::PathBuf; +use std::sync::Arc; use common::Diagnostic; use common::SourceLocationKey; @@ -18,13 +19,16 @@ use graphql_ir::ExecutableDefinitionName; use graphql_ir::FragmentDefinitionName; use graphql_ir::OperationDefinitionName; use graphql_syntax::ExecutableDefinition; +use relay_config::ProjectConfig; use relay_config::ProjectName; use crate::artifact_map::ArtifactSourceKey; use crate::compiler_state::GraphQLSources; +use crate::config::Config; use crate::errors::Error; use crate::errors::Result; use crate::file_source::LocatedGraphQLSource; +use crate::utils::get_parser_features; #[derive(Debug)] pub struct GraphQLAsts { @@ -50,10 +54,13 @@ impl GraphQLAsts { pub fn from_graphql_sources_map( graphql_sources_map: &FnvHashMap, dirty_artifact_sources: &FnvHashMap>, + config: &Arc, ) -> Result> { graphql_sources_map .iter() .map(|(&project_name, sources)| { + let project_config = &config.projects[&project_name]; + let asts = GraphQLAsts::from_graphql_sources( sources, dirty_artifact_sources @@ -73,6 +80,7 @@ impl GraphQLAsts { }) .collect() }), + project_config, )?; Ok((project_name, asts)) }) @@ -85,7 +93,10 @@ impl GraphQLAsts { pub fn from_graphql_sources( graphql_sources: &GraphQLSources, dirty_definitions: Option>, + project_config: &ProjectConfig, ) -> Result { + let parser_features = get_parser_features(project_config); + let mut syntax_errors = Vec::new(); let mut asts: FnvHashMap> = Default::default(); @@ -108,9 +119,10 @@ impl GraphQLAsts { { let source_location = SourceLocationKey::embedded(&file_name.to_string_lossy(), *index); - match graphql_syntax::parse_executable( + match graphql_syntax::parse_executable_with_features( &graphql_source.text_source().text, source_location, + parser_features, ) { Ok(document) => { for def in &document.definitions { @@ -145,9 +157,10 @@ impl GraphQLAsts { // TODO: parse name instead of the whole graphql text let source_location = SourceLocationKey::embedded(&file_name.to_string_lossy(), *index); - if let Ok(document) = graphql_syntax::parse_executable( + if let Ok(document) = graphql_syntax::parse_executable_with_features( &graphql_source.text_source().text, source_location, + parser_features, ) { for def in document.definitions { match def { @@ -210,9 +223,10 @@ impl GraphQLAsts { { let source_location = SourceLocationKey::embedded(&file_name.to_string_lossy(), *index); - match graphql_syntax::parse_executable( + match graphql_syntax::parse_executable_with_features( &graphql_source.text_source().text, source_location, + parser_features, ) { Ok(document) => { definitions_for_file.extend(document.definitions); diff --git a/compiler/crates/relay-compiler/src/lib.rs b/compiler/crates/relay-compiler/src/lib.rs index b494075f112d6..795f549dcaaf8 100644 --- a/compiler/crates/relay-compiler/src/lib.rs +++ b/compiler/crates/relay-compiler/src/lib.rs @@ -23,6 +23,7 @@ mod operation_persister; mod red_to_green; pub mod saved_state; pub mod status_reporter; +mod utils; pub use artifact_map::ArtifactSourceKey; pub use build_project::add_to_mercurial; @@ -72,3 +73,4 @@ pub use graphql_asts::GraphQLAsts; pub use operation_persister::LocalPersister; pub use operation_persister::RemotePersister; pub use relay_config::ProjectName; +pub use utils::get_parser_features; diff --git a/compiler/crates/relay-compiler/src/utils.rs b/compiler/crates/relay-compiler/src/utils.rs new file mode 100644 index 0000000000000..aa412e898627a --- /dev/null +++ b/compiler/crates/relay-compiler/src/utils.rs @@ -0,0 +1,16 @@ +use graphql_syntax::FragmentArgumentSyntaxKind; +use graphql_syntax::ParserFeatures; +use relay_config::ProjectConfig; + +pub fn get_parser_features(project_config: &ProjectConfig) -> ParserFeatures { + ParserFeatures { + fragment_argument_capability: if project_config + .feature_flags + .enable_fragment_argument_transform + { + FragmentArgumentSyntaxKind::SpreadArgumentsAndFragmentVariableDefinitions + } else { + FragmentArgumentSyntaxKind::None + }, + } +} diff --git a/compiler/crates/relay-lsp/src/graphql_tools/mod.rs b/compiler/crates/relay-lsp/src/graphql_tools/mod.rs index 96b385262c99a..378542f2b233c 100644 --- a/compiler/crates/relay-lsp/src/graphql_tools/mod.rs +++ b/compiler/crates/relay-lsp/src/graphql_tools/mod.rs @@ -20,13 +20,14 @@ use graphql_ir::OperationDefinition; use graphql_ir::OperationDefinitionName; use graphql_ir::Program; use graphql_ir::Selection; -use graphql_syntax::parse_executable_with_error_recovery; +use graphql_syntax::parse_executable_with_error_recovery_and_parser_features; use graphql_text_printer::print_full_operation; use intern::string_key::Intern; use intern::string_key::StringKey; use lsp_types::request::Request; use lsp_types::Url; use relay_compiler::config::ProjectConfig; +use relay_compiler::get_parser_features; use relay_compiler::ProjectName; use relay_transforms::apply_transforms; use relay_transforms::CustomTransformsConfig; @@ -229,7 +230,11 @@ pub(crate) fn get_query_text< )) })?; - let result = parse_executable_with_error_recovery(&original_text, SourceLocationKey::Generated); + let result = parse_executable_with_error_recovery_and_parser_features( + &original_text, + SourceLocationKey::Generated, + get_parser_features(project_config), + ); if !&result.diagnostics.is_empty() { return Err(LSPRuntimeError::UnexpectedError( diff --git a/compiler/crates/relay-lsp/src/server/lsp_state.rs b/compiler/crates/relay-lsp/src/server/lsp_state.rs index fa28657544ca9..a753b655959d1 100644 --- a/compiler/crates/relay-lsp/src/server/lsp_state.rs +++ b/compiler/crates/relay-lsp/src/server/lsp_state.rs @@ -23,7 +23,7 @@ use graphql_ir::BuilderOptions; use graphql_ir::FragmentVariablesSemantic; use graphql_ir::Program; use graphql_ir::RelayMode; -use graphql_syntax::parse_executable_with_error_recovery; +use graphql_syntax::parse_executable_with_error_recovery_and_parser_features; use graphql_syntax::ExecutableDefinition; use graphql_syntax::ExecutableDocument; use intern::string_key::Intern; @@ -35,6 +35,7 @@ use lsp_types::Range; use lsp_types::TextDocumentPositionParams; use lsp_types::Url; use relay_compiler::config::Config; +use relay_compiler::get_parser_features; use relay_compiler::FileCategorizer; use relay_compiler::ProjectName; use relay_docblock::parse_docblock_ast; @@ -220,6 +221,11 @@ impl { - let result = parse_executable_with_error_recovery( + let result = parse_executable_with_error_recovery_and_parser_features( &graphql_source.text_source().text, source_location_key, + get_parser_features(project_config), ); diagnostics.extend(result.diagnostics.iter().map(|diagnostic| { self.diagnostic_reporter @@ -282,11 +289,6 @@ impl LSPRuntimeResult> { + let project_name: ProjectName = self + .extract_project_name_from_url(&text_document_uri)? + .into(); + let project_config = self.config.projects.get(&project_name).unwrap(); + extract_executable_definitions_from_text_document( text_document_uri, &self.synced_javascript_features, + get_parser_features(project_config), ) } diff --git a/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs b/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs index 3cae4e3304b7c..044d950a2b7c1 100644 --- a/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs +++ b/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs @@ -242,6 +242,7 @@ impl bool { pub fn extract_executable_definitions_from_text_document( text_document_uri: &Url, source_feature_cache: &DashMap>, + parser_features: ParserFeatures, ) -> LSPRuntimeResult> { let source_features = source_feature_cache .get(text_document_uri) @@ -56,9 +59,10 @@ pub fn extract_executable_definitions_from_text_document( JavaScriptSourceFeature::GraphQL(graphql_source) => Some(graphql_source), }) .map(|graphql_source| { - let document = parse_executable_with_error_recovery( + let document = parse_executable_with_error_recovery_and_parser_features( &graphql_source.text_source().text, SourceLocationKey::standalone(&text_document_uri.to_string()), + parser_features, ) .item; @@ -134,11 +138,14 @@ pub fn extract_feature_from_text( let source_location_key = SourceLocationKey::embedded(uri.as_ref(), index); + let parser_features = get_parser_features(project_config); + match javascript_feature { JavaScriptSourceFeature::GraphQL(graphql_source) => { - let document = parse_executable_with_error_recovery( + let document = parse_executable_with_error_recovery_and_parser_features( &graphql_source.text_source().text, source_location_key, + parser_features, ) .item; @@ -163,8 +170,11 @@ pub fn extract_feature_from_text( Ok((Feature::GraphQLDocument(document), position_span)) } JavaScriptSourceFeature::Docblock(docblock_source) => { - let executable_definitions_in_file = - extract_executable_definitions_from_text_document(uri, source_feature_cache)?; + let executable_definitions_in_file = extract_executable_definitions_from_text_document( + uri, + source_feature_cache, + parser_features, + )?; let text_source = &docblock_source.text_source(); let text = &text_source.text; From c2d0901e0ac535e36f94fa23b1e4dfc9324e3bc7 Mon Sep 17 00:00:00 2001 From: tobias-tengler <45513122+tobias-tengler@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:15:31 +0100 Subject: [PATCH 2/3] Update tests --- .../crates/relay-compiler/tests/compile_relay_artifacts/mod.rs | 1 + .../tests/compile_relay_artifacts_with_custom_id/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs index 42ad0d9d14b5f..40d328ce95a7c 100644 --- a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs @@ -124,6 +124,7 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result allow_required_in_mutation_response: FeatureFlag::Disabled, allow_resolvers_in_mutation_response: FeatureFlag::Disabled, disable_resolver_reader_ast: false, + enable_fragment_argument_transform: false, }; let default_project_config = ProjectConfig { diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts_with_custom_id/mod.rs b/compiler/crates/relay-compiler/tests/compile_relay_artifacts_with_custom_id/mod.rs index 3aa5de6ac5be7..30880b41764d6 100644 --- a/compiler/crates/relay-compiler/tests/compile_relay_artifacts_with_custom_id/mod.rs +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts_with_custom_id/mod.rs @@ -103,6 +103,7 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result allow_required_in_mutation_response: FeatureFlag::Disabled, allow_resolvers_in_mutation_response: FeatureFlag::Disabled, disable_resolver_reader_ast: false, + enable_fragment_argument_transform: false, }; let default_schema_config = SchemaConfig::default(); From ee4dab9286d5a68e8bf6ea99052d2fd1e379a1b0 Mon Sep 17 00:00:00 2001 From: tobias-tengler <45513122+tobias-tengler@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:30:20 +0100 Subject: [PATCH 3/3] Add integration test --- .../fixtures/fragment_arguments.expected | 221 ++++++++++++++++++ .../fixtures/fragment_arguments.input | 37 +++ .../tests/relay_compiler_integration_test.rs | 9 +- 3 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/fragment_arguments.expected create mode 100644 compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/fragment_arguments.input diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/fragment_arguments.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/fragment_arguments.expected new file mode 100644 index 0000000000000..f7281490fa873 --- /dev/null +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/fragment_arguments.expected @@ -0,0 +1,221 @@ +==================================== INPUT ==================================== +//- foo.js +graphql` + fragment foo($postCount: Int) on User { + posts(first: $postCount) { + title + } + }`; + +graphql` + query fooQuery { + me { + ...foo(postCount: 5) + } + } +` + +//- relay.config.json +{ + "language": "typescript", + "schema": "./schema.graphql", + "featureFlags": { + "enable_fragment_argument_transform": true + } +} + +//- schema.graphql +type Query { + me: User +} + +type User { + posts(first: Int): [Post] +} + +type Post { + title: String +} +==================================== OUTPUT =================================== +//- __generated__/foo.graphql.ts +/** + * SignedSource<<0e503f5c200310a5580a2b4853a499ce>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { Fragment, ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type foo$data = { + readonly posts: ReadonlyArray<{ + readonly title: string | null | undefined; + } | null | undefined> | null | undefined; + readonly " $fragmentType": "foo"; +}; +export type foo$key = { + readonly " $data"?: foo$data; + readonly " $fragmentSpreads": FragmentRefs<"foo">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "postCount" + } + ], + "kind": "Fragment", + "metadata": null, + "name": "foo", + "selections": [ + { + "alias": null, + "args": [ + { + "kind": "Variable", + "name": "first", + "variableName": "postCount" + } + ], + "concreteType": "Post", + "kind": "LinkedField", + "name": "posts", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "User", + "abstractKey": null +}; + +(node as any).hash = "55999049d2511b8662e2fb877d8bf661"; + +export default node; + +//- __generated__/fooQuery.graphql.ts +/** + * SignedSource<<20043d1d00f946a33727d27907f7f3f2>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest, Query } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type fooQuery$variables = Record; +export type fooQuery$data = { + readonly me: { + readonly " $fragmentSpreads": FragmentRefs<"foo">; + } | null | undefined; +}; +export type fooQuery = { + response: fooQuery$data; + variables: fooQuery$variables; +}; + +const node: ConcreteRequest = { + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "fooQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "User", + "kind": "LinkedField", + "name": "me", + "plural": false, + "selections": [ + { + "args": [ + { + "kind": "Literal", + "name": "postCount", + "value": 5 + } + ], + "kind": "FragmentSpread", + "name": "foo" + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [], + "kind": "Operation", + "name": "fooQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "User", + "kind": "LinkedField", + "name": "me", + "plural": false, + "selections": [ + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "first", + "value": 5 + } + ], + "concreteType": "Post", + "kind": "LinkedField", + "name": "posts", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + } + ], + "storageKey": "posts(first:5)" + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "4fbb83aa0c91b56ee5c3eed90060ce7a", + "id": null, + "metadata": {}, + "name": "fooQuery", + "operationKind": "query", + "text": "query fooQuery {\n me {\n ...foo_3lq16u\n }\n}\n\nfragment foo_3lq16u on User {\n posts(first: 5) {\n title\n }\n}\n" + } +}; + +(node as any).hash = "3508818a33211bc36644b79de3011e83"; + +export default node; diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/fragment_arguments.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/fragment_arguments.input new file mode 100644 index 0000000000000..a0ae4d6994536 --- /dev/null +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/fragment_arguments.input @@ -0,0 +1,37 @@ +//- foo.js +graphql` + fragment foo($postCount: Int) on User { + posts(first: $postCount) { + title + } + }`; + +graphql` + query fooQuery { + me { + ...foo(postCount: 5) + } + } +` + +//- relay.config.json +{ + "language": "typescript", + "schema": "./schema.graphql", + "featureFlags": { + "enable_fragment_argument_transform": true + } +} + +//- schema.graphql +type Query { + me: User +} + +type User { + posts(first: Int): [Post] +} + +type Post { + title: String +} \ No newline at end of file diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs b/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs index 0bce227cd70fe..17de41b237dfc 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration_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<> + * @generated SignedSource<> */ mod relay_compiler_integration; @@ -61,6 +61,13 @@ async fn custom_scalar_variable_default_arg_non_strict() { test_fixture(transform_fixture, file!(), "custom_scalar_variable_default_arg_non_strict.input", "relay_compiler_integration/fixtures/custom_scalar_variable_default_arg_non_strict.expected", input, expected).await; } +#[tokio::test] +async fn fragment_arguments() { + let input = include_str!("relay_compiler_integration/fixtures/fragment_arguments.input"); + let expected = include_str!("relay_compiler_integration/fixtures/fragment_arguments.expected"); + test_fixture(transform_fixture, file!(), "fragment_arguments.input", "relay_compiler_integration/fixtures/fragment_arguments.expected", input, expected).await; +} + #[tokio::test] async fn live_resolver_implements_interface_field() { let input = include_str!("relay_compiler_integration/fixtures/live_resolver_implements_interface_field.input");