Просмотр исходного кода

fix(core): Correctly encode IDs in nested fragments

Michael Bromley 5 лет назад
Родитель
Сommit
d2333fc936

+ 68 - 1
packages/core/e2e/entity-id-strategy.e2e-spec.ts

@@ -4,7 +4,7 @@ import gql from 'graphql-tag';
 import path from 'path';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
-import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
+import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
 
 import {
     IdTest1,
@@ -215,4 +215,71 @@ describe('EntityIdStrategy', () => {
             ],
         });
     });
+
+    it('encodes ids in doubly-nested fragment', async () => {
+        const { products } = await shopClient.query<IdTest1.Query>(gql`
+            query IdTest10 {
+                products(options: { take: 1 }) {
+                    items {
+                        ...ProdFragment1
+                    }
+                }
+            }
+            fragment ProdFragment1 on Product {
+                ...ProdFragment2
+            }
+            fragment ProdFragment2 on Product {
+                id
+                featuredAsset {
+                    id
+                }
+            }
+        `);
+
+        expect(products).toEqual({
+            items: [
+                {
+                    id: 'T_1',
+                    featuredAsset: {
+                        id: 'T_2',
+                    },
+                },
+            ],
+        });
+    });
+
+    it('encodes ids in triply-nested fragment', async () => {
+        const { products } = await shopClient.query<IdTest1.Query>(gql`
+            query IdTest11 {
+                products(options: { take: 1 }) {
+                    items {
+                        ...ProdFragment1_1
+                    }
+                }
+            }
+            fragment ProdFragment1_1 on Product {
+                ...ProdFragment2_1
+            }
+            fragment ProdFragment2_1 on Product {
+                ...ProdFragment3_1
+            }
+            fragment ProdFragment3_1 on Product {
+                id
+                featuredAsset {
+                    id
+                }
+            }
+        `);
+
+        expect(products).toEqual({
+            items: [
+                {
+                    id: 'T_1',
+                    featuredAsset: {
+                        id: 'T_2',
+                    },
+                },
+            ],
+        });
+    });
 });

+ 10 - 2
packages/core/src/api/common/graphql-value-transformer.ts

@@ -216,8 +216,16 @@ export class GraphqlValueTransformer {
                 if (targetNode) {
                     let children: { [name: string]: TypeTreeNode } = targetNode.children;
                     if (targetNode.fragmentRefs.length) {
-                        for (const ref of targetNode.fragmentRefs) {
-                            children = { ...children, ...typeTree.fragments[ref].children };
+                        const fragmentRefs = targetNode.fragmentRefs.slice();
+                        while (fragmentRefs.length) {
+                            const ref = fragmentRefs.pop();
+                            if (ref) {
+                                const fragment = typeTree.fragments[ref];
+                                children = { ...children, ...fragment.children };
+                                if (fragment.fragmentRefs) {
+                                    fragmentRefs.push(...fragment.fragmentRefs);
+                                }
+                            }
                         }
                     }
                     targetNode = children[segment];