Skip to content

Commit

Permalink
add regression tests for undefined field arguments in relay resolvers
Browse files Browse the repository at this point in the history
Summary:
## Context

When compiling relay resolvers we are missing validation on undefined global variables within resolvers. The global variables can be passed via resolver field or fragment arguments.

We want to add a suite of regression tests for the following cases:

- Relay resolver yields a scalar field without an associated fragment e.g. live or derived resolvers
- Relay resolver yields a scalar field with an associated fragment
  - Passing both field and fragment arguments
  - Fragment args only
   - Field args only
  - Multiple undefined global variables
- Linked field aka client edges

## This diff

Adds tests for undefined field arguments on relay resolvers yielding scalar and linked fields.

- **Relay resolver yields a scalar field without an associated fragment e.g. live or derived resolvers**
- Relay resolver yields a scalar field with an associated fragment
  - Passing both field and fragment arguments
 - Fragment args only
  - Field args only
  - Multiple undefined global variables
- **Linked field aka client edges**

Adds tests for validation of undefined field arguments on relay resolvers yielding scalar and linked fields.

Reviewed By: captbaritone, tyao1

Differential Revision: D50615535

fbshipit-source-id: df7f99eeb1072093ba846fd88de206620982cd75
  • Loading branch information
monicatang authored and facebook-github-bot committed Oct 24, 2023
1 parent 41a33a1 commit 00d6217
Show file tree
Hide file tree
Showing 5 changed files with 556 additions and 1 deletion.
@@ -0,0 +1,334 @@
==================================== INPUT ====================================
# TODO T160746170 expected to throw

query relayResolverWithUndefinedFieldArgsLinkedFieldQuery {
node(id: "SOME_ID") {
...relayResolverWithUndefinedFieldArgsLinkedField_PopStar
}
}

fragment relayResolverWithUndefinedFieldArgsLinkedField_PopStar on User {
pop_star(name: $undefined) @waterfall {
id
}
}
# %extensions%

extend type User {
pop_star(name: String): User @relay_resolver(import_path: "./path/to/PopStarResolver.js")
}
==================================== OUTPUT ===================================
{
"fragment": {
"argumentDefinitions": [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "id"
}
],
"kind": "Fragment",
"metadata": null,
"name": "ClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star",
"selections": [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "id",
"variableName": "id"
}
],
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"args": null,
"kind": "FragmentSpread",
"name": "RefetchableClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star"
}
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "id"
}
],
"kind": "Operation",
"name": "ClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star",
"selections": [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "id",
"variableName": "id"
}
],
"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
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "d5903316ee00d1bf3d4368d1c75c827e",
"id": null,
"metadata": {},
"name": "ClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star",
"operationKind": "query",
"text": null
}
}

QUERY:

query ClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star(
$id: ID!
) {
node(id: $id) {
__typename
...RefetchableClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star
id
}
}

fragment RefetchableClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star on User {
id
}


{
"fragment": {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "relayResolverWithUndefinedFieldArgsLinkedFieldQuery",
"selections": [
{
"alias": null,
"args": [
{
"kind": "Literal",
"name": "id",
"value": "SOME_ID"
}
],
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"args": null,
"kind": "FragmentSpread",
"name": "relayResolverWithUndefinedFieldArgsLinkedField_PopStar"
}
],
"storageKey": "node(id:\"SOME_ID\")"
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [],
"kind": "Operation",
"name": "relayResolverWithUndefinedFieldArgsLinkedFieldQuery",
"selections": [
{
"alias": null,
"args": [
{
"kind": "Literal",
"name": "id",
"value": "SOME_ID"
}
],
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
{
"kind": "InlineFragment",
"selections": [
{
"name": "pop_star",
"args": [
{
"kind": "Variable",
"name": "name",
"variableName": "undefined"
}
],
"fragment": null,
"kind": "RelayResolver",
"storageKey": null,
"isOutputType": false
}
],
"type": "User",
"abstractKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
],
"storageKey": "node(id:\"SOME_ID\")"
}
]
},
"params": {
"cacheID": "e8583c1b54f5e17064d894b8094a5a68",
"id": null,
"metadata": {},
"name": "relayResolverWithUndefinedFieldArgsLinkedFieldQuery",
"operationKind": "query",
"text": null
}
}

QUERY:

query relayResolverWithUndefinedFieldArgsLinkedFieldQuery {
node(id: "SOME_ID") {
__typename
id
}
}


{
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": {
"refetch": {
"connection": null,
"fragmentPathInResult": [
"node"
],
"operation": require('ClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star.graphql'),
"identifierInfo": {
"identifierField": "id",
"identifierQueryVariableName": "id"
}
}
},
"name": "RefetchableClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
],
"type": "User",
"abstractKey": null
}

{
"argumentDefinitions": [
{
"kind": "RootArgument",
"name": "undefined"
}
],
"kind": "Fragment",
"metadata": {
"hasClientEdges": true
},
"name": "relayResolverWithUndefinedFieldArgsLinkedField_PopStar",
"selections": [
{
"kind": "ClientEdgeToServerObject",
"operation": require('ClientEdgeQuery_relayResolverWithUndefinedFieldArgsLinkedField_PopStar_pop_star.graphql'),
"backingField": {
"alias": null,
"args": [
{
"kind": "Variable",
"name": "name",
"variableName": "undefined"
}
],
"fragment": null,
"kind": "RelayResolver",
"name": "pop_star",
"resolverModule": require('PopStarResolver'),
"path": "pop_star"
},
"linkedField": {
"alias": null,
"args": [
{
"kind": "Variable",
"name": "name",
"variableName": "undefined"
}
],
"concreteType": "User",
"kind": "LinkedField",
"name": "pop_star",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
],
"storageKey": null
}
}
],
"type": "User",
"abstractKey": null
}
@@ -0,0 +1,18 @@
# TODO T160746170 expected to throw

query relayResolverWithUndefinedFieldArgsLinkedFieldQuery {
node(id: "SOME_ID") {
...relayResolverWithUndefinedFieldArgsLinkedField_PopStar
}
}

fragment relayResolverWithUndefinedFieldArgsLinkedField_PopStar on User {
pop_star(name: $undefined) @waterfall {
id
}
}
# %extensions%

extend type User {
pop_star(name: String): User @relay_resolver(import_path: "./path/to/PopStarResolver.js")
}

0 comments on commit 00d6217

Please sign in to comment.