diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.expected new file mode 100644 index 0000000000000..b322817fcfe2c --- /dev/null +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.expected @@ -0,0 +1,325 @@ +==================================== INPUT ==================================== +//- ModuleName.js +graphql` +fragment ModuleName_node on Node { + ... on UserSearchResult { + alias + } +} +`; + +graphql` +fragment ModuleName_user on User { + id + ...ModuleName_node +} +`; + +graphql` +query ModuleNameQuery { + node(node_id: "4") { + ... on User { + # Removing this seems to make it so there is no change + alias + } + # Moving this into the User inline fragment makes this cause no change + ...ModuleName_user @dangerously_unaliased_fixme + } +} +`; + + +//- relay.config.json +{ + "language": "typescript", + "schema": "./schema.graphql", + "featureFlags": { + "disable_deduping_common_structures_in_artifacts": { + "kind": "enabled" + } + } +} + +//- schema.graphql +interface Node { + id: ID! +} +type Query { + node(node_id: ID!): Node +} +type User implements Node { + id: ID! + alias: String +} +type UserSearchResult implements Node { + id: ID! + alias: String +} +==================================== OUTPUT =================================== +//- __generated__/ModuleNameQuery.graphql.ts +/** + * SignedSource<<4f0ee5ff806a9f25428b594d432a805a>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type ModuleNameQuery$variables = Record; +export type ModuleNameQuery$data = { + readonly node: { + readonly alias?: string | null | undefined; + readonly " $fragmentSpreads": FragmentRefs<"ModuleName_user">; + } | null | undefined; +}; +export type ModuleNameQuery = { + response: ModuleNameQuery$data; + variables: ModuleNameQuery$variables; +}; + +const node: ConcreteRequest = { + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "ModuleNameQuery", + "selections": [ + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "node_id", + "value": "4" + } + ], + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "alias", + "storageKey": null + } + ], + "type": "User", + "abstractKey": null + }, + { + "args": null, + "kind": "FragmentSpread", + "name": "ModuleName_user" + } + ], + "storageKey": "node(node_id:\"4\")" + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [], + "kind": "Operation", + "name": "ModuleNameQuery", + "selections": [ + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "node_id", + "value": "4" + } + ], + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "alias", + "storageKey": null + } + ], + "type": "User", + "abstractKey": null + }, + { + "kind": "InlineFragment", + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "alias", + "storageKey": null + } + ], + "type": "UserSearchResult", + "abstractKey": null + } + ], + "type": "Node", + "abstractKey": "__isNode" + } + ], + "type": "User", + "abstractKey": null + } + ], + "storageKey": "node(node_id:\"4\")" + } + ] + }, + "params": { + "cacheID": "4486f6eca895bdea633b44bef50a3569", + "id": null, + "metadata": {}, + "name": "ModuleNameQuery", + "operationKind": "query", + "text": "query ModuleNameQuery {\n node(node_id: \"4\") {\n __typename\n ... on User {\n alias\n }\n ...ModuleName_user\n id\n }\n}\n\nfragment ModuleName_node on Node {\n __isNode: __typename\n ... on UserSearchResult {\n alias\n }\n}\n\nfragment ModuleName_user on User {\n id\n ...ModuleName_node\n}\n" + } +}; + +(node as any).hash = "cc17ed2b9fec1e22d68e8b3c8da43331"; + +export default node; + +//- __generated__/ModuleName_node.graphql.ts +/** + * SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type ModuleName_node$data = { + readonly alias?: string | null | undefined; + readonly " $fragmentType": "ModuleName_node"; +}; +export type ModuleName_node$key = { + readonly " $data"?: ModuleName_node$data; + readonly " $fragmentSpreads": FragmentRefs<"ModuleName_node">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "ModuleName_node", + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "alias", + "storageKey": null + } + ], + "type": "UserSearchResult", + "abstractKey": null + } + ], + "type": "Node", + "abstractKey": "__isNode" +}; + +(node as any).hash = "b89613eb4089373194fac4abdce1009f"; + +export default node; + +//- __generated__/ModuleName_user.graphql.ts +/** + * SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type ModuleName_user$data = { + readonly id: string; + readonly " $fragmentSpreads": FragmentRefs<"ModuleName_node">; + readonly " $fragmentType": "ModuleName_user"; +}; +export type ModuleName_user$key = { + readonly " $data"?: ModuleName_user$data; + readonly " $fragmentSpreads": FragmentRefs<"ModuleName_user">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "ModuleName_user", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "args": null, + "kind": "FragmentSpread", + "name": "ModuleName_node" + } + ], + "type": "User", + "abstractKey": null +}; + +(node as any).hash = "fdc866618612175df61eea90c737dae2"; + +export default node; diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.input new file mode 100644 index 0000000000000..43727ff41cf15 --- /dev/null +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.input @@ -0,0 +1,56 @@ +//- ModuleName.js +graphql` +fragment ModuleName_node on Node { + ... on UserSearchResult { + alias + } +} +`; + +graphql` +fragment ModuleName_user on User { + id + ...ModuleName_node +} +`; + +graphql` +query ModuleNameQuery { + node(node_id: "4") { + ... on User { + # Removing this seems to make it so there is no change + alias + } + # Moving this into the User inline fragment makes this cause no change + ...ModuleName_user @dangerously_unaliased_fixme + } +} +`; + + +//- relay.config.json +{ + "language": "typescript", + "schema": "./schema.graphql", + "featureFlags": { + "disable_deduping_common_structures_in_artifacts": { + "kind": "enabled" + } + } +} + +//- schema.graphql +interface Node { + id: ID! +} +type Query { + node(node_id: ID!): Node +} +type User implements Node { + id: ID! + alias: String +} +type UserSearchResult implements Node { + id: ID! + alias: String +} diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.expected new file mode 100644 index 0000000000000..dad4e6395ee4f --- /dev/null +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.expected @@ -0,0 +1,301 @@ +==================================== INPUT ==================================== +//- ModuleName.js +graphql` +fragment ModuleName_node on Node { + ... on UserSearchResult { + alias + } +} +`; + +graphql` +fragment ModuleName_user on User { + id + ...ModuleName_node +} +`; + +graphql` +query ModuleNameQuery { + node(node_id: "4") { + ... on User { + # Removing this seems to make it so there is no change + alias + } + # Moving this into the User inline fragment makes this cause no change + ...ModuleName_user # @dangerously_unaliased_fixme + } +} +`; + + +//- relay.config.json +{ + "language": "typescript", + "schema": "./schema.graphql", + "featureFlags": { + "disable_deduping_common_structures_in_artifacts": { + "kind": "enabled" + } + } +} + +//- schema.graphql +interface Node { + id: ID! +} +type Query { + node(node_id: ID!): Node +} +type User implements Node { + id: ID! + alias: String +} +type UserSearchResult implements Node { + id: ID! + alias: String +} +==================================== OUTPUT =================================== +//- __generated__/ModuleNameQuery.graphql.ts +/** + * SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type ModuleNameQuery$variables = Record; +export type ModuleNameQuery$data = { + readonly node: { + readonly alias?: string | null | undefined; + readonly " $fragmentSpreads": FragmentRefs<"ModuleName_user">; + } | null | undefined; +}; +export type ModuleNameQuery = { + response: ModuleNameQuery$data; + variables: ModuleNameQuery$variables; +}; + +const node: ConcreteRequest = { + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "ModuleNameQuery", + "selections": [ + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "node_id", + "value": "4" + } + ], + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "alias", + "storageKey": null + } + ], + "type": "User", + "abstractKey": null + }, + { + "args": null, + "kind": "FragmentSpread", + "name": "ModuleName_user" + } + ], + "storageKey": "node(node_id:\"4\")" + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [], + "kind": "Operation", + "name": "ModuleNameQuery", + "selections": [ + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "node_id", + "value": "4" + } + ], + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "alias", + "storageKey": null + }, + { + "kind": "TypeDiscriminator", + "abstractKey": "__isNode" + } + ], + "type": "User", + "abstractKey": null + } + ], + "storageKey": "node(node_id:\"4\")" + } + ] + }, + "params": { + "cacheID": "4486f6eca895bdea633b44bef50a3569", + "id": null, + "metadata": {}, + "name": "ModuleNameQuery", + "operationKind": "query", + "text": "query ModuleNameQuery {\n node(node_id: \"4\") {\n __typename\n ... on User {\n alias\n }\n ...ModuleName_user\n id\n }\n}\n\nfragment ModuleName_node on Node {\n __isNode: __typename\n ... on UserSearchResult {\n alias\n }\n}\n\nfragment ModuleName_user on User {\n id\n ...ModuleName_node\n}\n" + } +}; + +(node as any).hash = "ab49125dac1212829db82382d37372fc"; + +export default node; + +//- __generated__/ModuleName_node.graphql.ts +/** + * SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type ModuleName_node$data = { + readonly alias?: string | null | undefined; + readonly " $fragmentType": "ModuleName_node"; +}; +export type ModuleName_node$key = { + readonly " $data"?: ModuleName_node$data; + readonly " $fragmentSpreads": FragmentRefs<"ModuleName_node">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "ModuleName_node", + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "alias", + "storageKey": null + } + ], + "type": "UserSearchResult", + "abstractKey": null + } + ], + "type": "Node", + "abstractKey": "__isNode" +}; + +(node as any).hash = "b89613eb4089373194fac4abdce1009f"; + +export default node; + +//- __generated__/ModuleName_user.graphql.ts +/** + * SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type ModuleName_user$data = { + readonly id: string; + readonly " $fragmentSpreads": FragmentRefs<"ModuleName_node">; + readonly " $fragmentType": "ModuleName_user"; +}; +export type ModuleName_user$key = { + readonly " $data"?: ModuleName_user$data; + readonly " $fragmentSpreads": FragmentRefs<"ModuleName_user">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "ModuleName_user", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "args": null, + "kind": "FragmentSpread", + "name": "ModuleName_node" + } + ], + "type": "User", + "abstractKey": null +}; + +(node as any).hash = "fdc866618612175df61eea90c737dae2"; + +export default node; diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.input new file mode 100644 index 0000000000000..d589100d44364 --- /dev/null +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.input @@ -0,0 +1,56 @@ +//- ModuleName.js +graphql` +fragment ModuleName_node on Node { + ... on UserSearchResult { + alias + } +} +`; + +graphql` +fragment ModuleName_user on User { + id + ...ModuleName_node +} +`; + +graphql` +query ModuleNameQuery { + node(node_id: "4") { + ... on User { + # Removing this seems to make it so there is no change + alias + } + # Moving this into the User inline fragment makes this cause no change + ...ModuleName_user # @dangerously_unaliased_fixme + } +} +`; + + +//- relay.config.json +{ + "language": "typescript", + "schema": "./schema.graphql", + "featureFlags": { + "disable_deduping_common_structures_in_artifacts": { + "kind": "enabled" + } + } +} + +//- schema.graphql +interface Node { + id: ID! +} +type Query { + node(node_id: ID!): Node +} +type User implements Node { + id: ID! + alias: String +} +type UserSearchResult implements Node { + id: ID! + alias: String +} 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 8b7e07388d63d..ca5afbf743f9c 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<<4a187a561407aa9fb9576d43e789725b>> + * @generated SignedSource<<00aa849a8a46f027d22d0712fd90b3eb>> */ mod relay_compiler_integration; @@ -138,6 +138,20 @@ async fn preloadable_query_typescript() { test_fixture(transform_fixture, file!(), "preloadable_query_typescript.input", "relay_compiler_integration/fixtures/preloadable_query_typescript.expected", input, expected).await; } +#[tokio::test] +async fn repro_dangerously_unaliased_changes_output_after() { + let input = include_str!("relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.input"); + let expected = include_str!("relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.expected"); + test_fixture(transform_fixture, file!(), "repro_dangerously_unaliased_changes_output_after.input", "relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_after.expected", input, expected).await; +} + +#[tokio::test] +async fn repro_dangerously_unaliased_changes_output_before() { + let input = include_str!("relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.input"); + let expected = include_str!("relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.expected"); + test_fixture(transform_fixture, file!(), "repro_dangerously_unaliased_changes_output_before.input", "relay_compiler_integration/fixtures/repro_dangerously_unaliased_changes_output_before.expected", input, expected).await; +} + #[tokio::test] async fn required_conditional_field() { let input = include_str!("relay_compiler_integration/fixtures/required_conditional_field.input");