Skip to content

Commit

Permalink
Fix nested fragments getting masked out incorrectly (#1244)
Browse files Browse the repository at this point in the history
Co-authored-by: Alec Aivazis <[email protected]>
  • Loading branch information
SeppahBaws and AlecAivazis committed Dec 26, 2023
1 parent 37bc404 commit c86501a
Show file tree
Hide file tree
Showing 21 changed files with 387 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/curly-buttons-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'houdini': patch
---

Fix nested fragment fields getting masked out when using fragment arguments
7 changes: 7 additions & 0 deletions e2e/_api/graphql.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,13 @@ export const resolvers = {
)
},
enumValue: () => 'Value1',
testField: (user, args) => {
if (args.someParam) {
return "Hello world";
}

return null;
}
},

Mutation: {
Expand Down
1 change: 1 addition & 0 deletions e2e/_api/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ type User implements Node {
name: String!
enumValue: MyEnum
types: [TypeOfUser!]!
testField(someParam: Boolean!): String
}

interface Animal implements Node {
Expand Down
1 change: 1 addition & 0 deletions e2e/kit/src/lib/utils/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export const routes = {
Pagination_fragment_offset: '/pagination/fragment/offset',

nested_argument_fragments: '/nested-argument-fragments',
nested_argument_fragments_masking: '/nested-argument-fragments-masking',

Stores_Nested_List: '/stores/nested-list',

Expand Down
35 changes: 35 additions & 0 deletions e2e/kit/src/routes/bug/fragment-params-on-connection/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script lang="ts">
import { graphql } from '$houdini';
import { onMount } from 'svelte';
import UsersList from './UsersList.svelte';
import UserItem from './UserItem.svelte';
$: store = graphql(`
query Test {
usersConnection(snapshot: "test-user", first: 5) {
...UsersListFragment @with(someParam: true)
edges {
node {
...UserItem @with(someParam: true)
}
}
}
}
`);
onMount(() => {
store.fetch();
});
</script>

{#if $store.data}
<h3>With fragment on the connection:</h3>
<UsersList usersList={$store.data.usersConnection} />

<h3>With fragment on the node:</h3>
<ul>
{#each $store.data.usersConnection.edges as userEdge}
<UserItem user={userEdge.node} />
{/each}
</ul>
{/if}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script lang="ts">
import { fragment, graphql, type UserItem } from '$houdini';
export let user: UserItem | null;
$: data = fragment(
user,
graphql(`
fragment UserItem on User @arguments(someParam: { type: "Boolean!" }) {
id
name
testField(someParam: $someParam)
}
`)
);
</script>

<li>
<p>{$data?.id} - {$data?.name}</p>
<p>Test field: {$data?.testField}</p>
</li>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script lang="ts">
import { fragment, graphql, type UsersListFragment } from '$houdini';
import UserItem from './UserItem.svelte';
export let usersList: UsersListFragment;
$: data = fragment(
usersList,
graphql(`
fragment UsersListFragment on UserConnection @arguments(someParam: { type: "Boolean!" }) {
edges {
node {
...UserItem @with(someParam: $someParam)
}
}
}
`)
);
</script>

<ul>
{#each $data.edges as userEdge}
<UserItem user={userEdge.node} />
{/each}
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
query Bug_UsersList($someParam: Boolean!) {
usersConnection(snapshot: "test", first: 2) {
edges {
node {
...UserDetails @with(someParam: $someParam)
}
}
}
}
19 changes: 19 additions & 0 deletions e2e/kit/src/routes/nested-argument-fragments-masking/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import type { PageData } from './$houdini';
import UserDetails from './UserDetails.svelte';
export let data: PageData;
$: ({ Bug_UsersList } = data);
</script>

<div id="result">
{#if $Bug_UsersList.data}
<ul>
{#each $Bug_UsersList.data.usersConnection.edges as userEdge}
{#if userEdge.node}
<UserDetails user={userEdge.node} />
{/if}
{/each}
</ul>
{/if}
</div>
13 changes: 13 additions & 0 deletions e2e/kit/src/routes/nested-argument-fragments-masking/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { load_Bug_UsersList } from '$houdini';
import type { PageLoad } from './$houdini';

export const load: PageLoad = async (event) => {
return {
...(await load_Bug_UsersList({
event,
variables: {
someParam: true
}
}))
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script lang="ts">
import { fragment, graphql, type FriendInfo } from '$houdini';
export let user: FriendInfo;
$: friend = fragment(
user,
graphql(`
fragment FriendInfo on User @arguments(someParam: { type: "Boolean!" }) {
id
name
testField(someParam: $someParam)
}
`)
);
</script>

<li>
<p>{$friend.name}</p>
<p>Test field: {$friend.testField}</p>
</li>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script lang="ts">
import { fragment, graphql, type UserDetails } from '$houdini';
import FriendInfo from './FriendInfo.svelte';
export let user: UserDetails;
$: userDetails = fragment(
user,
graphql(`
fragment UserDetails on User @arguments(someParam: { type: "Boolean!" }) {
id
name
friendsConnection(first: 2) {
edges {
node {
...FriendInfo @with(someParam: $someParam)
}
}
}
}
`)
);
</script>

<li>
<p>{$userDetails.name}</p>
<p>friends:</p>

<ul>
{#each $userDetails.friendsConnection.edges as friendEdge}
{#if friendEdge.node}
<FriendInfo user={friendEdge.node} />
{/if}
{/each}
</ul>
</li>
15 changes: 15 additions & 0 deletions e2e/kit/src/routes/nested-argument-fragments-masking/spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { expect, test } from '@playwright/test';
import { routes } from '../../lib/utils/routes.js';
import { expect_1_gql, expect_to_be, goto } from '../../lib/utils/testsHelper.js';

Check warning on line 3 in e2e/kit/src/routes/nested-argument-fragments-masking/spec.ts

View workflow job for this annotation

GitHub Actions / End-to-End Linter

'expect_1_gql' is defined but never used

Check warning on line 3 in e2e/kit/src/routes/nested-argument-fragments-masking/spec.ts

View workflow job for this annotation

GitHub Actions / End-to-End Linter

'expect_to_be' is defined but never used
import { sleep } from '@kitql/helpers';

test('Nested fragment argument masking', async ({ page }) => {
await goto(page, routes.nested_argument_fragments_masking);

// wait a bit for the client to hydrate
await sleep(1000);

expect(await page.locator('#result').textContent({ timeout: 2997 })).toEqual(
'Bruce Willis friends: Bruce Willis Test field: Hello worldSamuel Jackson Test field: Hello worldSamuel Jackson friends: Bruce Willis Test field: Hello worldSamuel Jackson Test field: Hello world'
);
});
4 changes: 2 additions & 2 deletions packages/houdini/src/codegen/generators/artifacts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export default function artifactGenerator(stats: {
document: doc,
rootType,
globalLoading,
includeFragments: doc.kind !== ArtifactKind.Fragment,
includeFragments: true,
hasComponents: () => {
hasComponents = true
},
Expand All @@ -299,7 +299,7 @@ export default function artifactGenerator(stats: {
filepath: doc.filename,
selections: selectionSet.selections,
fragmentDefinitions,
applyFragments: doc.kind !== ArtifactKind.Fragment,
applyFragments: true,
}),

operations: operationsByPath(
Expand Down
11 changes: 10 additions & 1 deletion packages/houdini/src/codegen/generators/artifacts/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
type SubscriptionSelection,
type LoadingSpec,
} from '../../../runtime/lib/types'
import { withArguments } from '../../transforms/fragmentVariables'
import { connectionSelection } from '../../transforms/list'
import fieldKey from './fieldKey'
import { convertValue } from './utils'
Expand Down Expand Up @@ -412,7 +413,15 @@ function prepareSelection({
object.fragments = {
...object.fragments,
[fragment]: {
arguments: args ?? {},
arguments:
args && Object.keys(args ?? {}).length > 0
? args
: Object.fromEntries(
withArguments(config, field).map((arg) => [
arg.name.value,
arg.value,
])
),
},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6176,6 +6176,12 @@ test('nested abstract fragment on connection', async function () {
"type": "String",
"keyRaw": "__typename"
}
},
"fragments": {
"AnimalProps": {
"arguments": {}
}
}
},
Expand Down Expand Up @@ -6267,6 +6273,12 @@ test('nested abstract fragment on connection', async function () {
"type": "String",
"keyRaw": "__typename"
}
},
"fragments": {
"AnimalProps": {
"arguments": {}
}
}
},
Expand Down Expand Up @@ -6328,6 +6340,10 @@ test('nested abstract fragment on connection', async function () {
"fragments": {
"MonkeyList": {
"arguments": {}
},
"AnimalList": {
"arguments": {}
}
}
},
Expand Down Expand Up @@ -6480,6 +6496,12 @@ test('nested abstract fragments', async function () {
"type": "String",
"keyRaw": "__typename"
}
},
"fragments": {
"MonkeyFragment": {
"arguments": {}
}
}
},
Expand Down Expand Up @@ -6578,6 +6600,16 @@ test('nested abstract fragments', async function () {
"visible": true
},
"name": {
"type": "String",
"keyRaw": "name"
},
"hasBanana": {
"type": "Boolean",
"keyRaw": "hasBanana"
},
"__typename": {
"type": "String",
"keyRaw": "__typename",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ test('fragments of unions inject correctly', function () {
}
}
`),
hasComponents: () => {},
})

expect(artifactSelection).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -1115,12 +1116,28 @@ test('componentFields get embedded in the selection', async function () {
},
"visible": true
},
"FriendList": {
"keyRaw": "FriendList",
"type": "Component",
"component": {
"prop": "user",
"key": "User.FriendList",
"fragment": "FriendList",
"variables": {}
}
}
},
"fragments": {
"UserAvatar": {
"arguments": {}
},
"FriendList": {
"arguments": {}
}
}
},
Expand Down
Loading

0 comments on commit c86501a

Please sign in to comment.