diff --git a/packages/ra-data-graphql-simple/src/getResponseParser.test.ts b/packages/ra-data-graphql-simple/src/getResponseParser.test.ts index 717d46560e8..c04b4882ae0 100644 --- a/packages/ra-data-graphql-simple/src/getResponseParser.test.ts +++ b/packages/ra-data-graphql-simple/src/getResponseParser.test.ts @@ -9,68 +9,78 @@ import { } from 'ra-core'; import getResponseParser from './getResponseParser'; -const testListTypes = type => { - it('returns the response expected by AOR for GET_LIST', () => { - const introspectionResults = { - resources: [ - { - type: { - name: 'User', - fields: [ - { name: 'id', type: { kind: TypeKind.SCALAR } }, - { - name: 'firstName', - type: { kind: TypeKind.SCALAR }, - }, - ], - }, - }, - { - type: { - name: 'Tag', - fields: [ - { name: 'id', type: { kind: TypeKind.SCALAR } }, - { name: 'name', type: { kind: TypeKind.SCALAR } }, - ], - }, - }, - ], - types: [{ name: 'User' }, { name: 'Tag' }], - }; - const response = { - data: { - items: [ +describe('getResponseParser', () => { + it.each([[GET_LIST], [GET_MANY], [GET_MANY_REFERENCE]])( + 'returns the response expected for %s', + type => { + const introspectionResults = { + resources: [ { - _typeName: 'Post', - id: 'post1', - title: 'title1', - author: { id: 'author1', firstName: 'Toto' }, - coauthor: null, - tags: [ - { id: 'tag1', name: 'tag1 name' }, - { id: 'tag2', name: 'tag2 name' }, - ], - embeddedJson: { foo: 'bar' }, + type: { + name: 'User', + fields: [ + { name: 'id', type: { kind: TypeKind.SCALAR } }, + { + name: 'firstName', + type: { kind: TypeKind.SCALAR }, + }, + ], + }, }, { - _typeName: 'Post', - id: 'post2', - title: 'title2', - author: { id: 'author1', firstName: 'Toto' }, - coauthor: null, - tags: [ - { id: 'tag1', name: 'tag1 name' }, - { id: 'tag3', name: 'tag3 name' }, - ], - embeddedJson: { foo: 'bar' }, + type: { + name: 'Tag', + fields: [ + { name: 'id', type: { kind: TypeKind.SCALAR } }, + { + name: 'name', + type: { kind: TypeKind.SCALAR }, + }, + ], + }, }, ], - total: { count: 100 }, - }, - }; + types: [{ name: 'User' }, { name: 'Tag' }], + }; + const response = { + data: { + items: [ + { + _typeName: 'Post', + id: 'post1', + title: 'title1', + author: { id: 'author1', firstName: 'Toto' }, + coauthor: null, + tags: [ + { id: 'tag1', name: 'tag1 name' }, + { id: 'tag2', name: 'tag2 name' }, + ], + embeddedJson: { foo: 'bar' }, + }, + { + _typeName: 'Post', + id: 'post2', + title: 'title2', + author: { id: 'author1', firstName: 'Toto' }, + coauthor: null, + tags: [ + { id: 'tag1', name: 'tag1 name' }, + { id: 'tag3', name: 'tag3 name' }, + ], + embeddedJson: { foo: 'bar' }, + }, + ], + total: { count: 100 }, + }, + }; - expect(getResponseParser(introspectionResults)(type)(response)).toEqual( - { + expect( + getResponseParser(introspectionResults)( + type, + undefined, + undefined + )(response) + ).toEqual({ data: [ { id: 'post1', @@ -98,57 +108,64 @@ const testListTypes = type => { }, ], total: 100, - } - ); - }); -}; + }); + } + ); -const testSingleTypes = type => { - it('returns the response expected by AOR for GET_LIST', () => { - const introspectionResults = { - resources: [ - { - type: { - name: 'User', - fields: [ - { name: 'id', type: { kind: TypeKind.SCALAR } }, - { - name: 'firstName', - type: { kind: TypeKind.SCALAR }, - }, - ], + describe.each([[CREATE], [UPDATE], [DELETE]])('%s', type => { + it('returns the response expected for %s', () => { + const introspectionResults = { + resources: [ + { + type: { + name: 'User', + fields: [ + { name: 'id', type: { kind: TypeKind.SCALAR } }, + { + name: 'firstName', + type: { kind: TypeKind.SCALAR }, + }, + ], + }, }, - }, - { - type: { - name: 'Tag', - fields: [ - { name: 'id', type: { kind: TypeKind.SCALAR } }, - { name: 'name', type: { kind: TypeKind.SCALAR } }, - ], + { + type: { + name: 'Tag', + fields: [ + { name: 'id', type: { kind: TypeKind.SCALAR } }, + { + name: 'name', + type: { kind: TypeKind.SCALAR }, + }, + ], + }, }, - }, - ], - types: [{ name: 'User' }, { name: 'Tag' }], - }; - const response = { - data: { + ], + types: [{ name: 'User' }, { name: 'Tag' }], + }; + const response = { data: { - _typeName: 'Post', - id: 'post1', - title: 'title1', - author: { id: 'author1', firstName: 'Toto' }, - coauthor: null, - tags: [ - { id: 'tag1', name: 'tag1 name' }, - { id: 'tag2', name: 'tag2 name' }, - ], - embeddedJson: { foo: 'bar' }, + data: { + _typeName: 'Post', + id: 'post1', + title: 'title1', + author: { id: 'author1', firstName: 'Toto' }, + coauthor: null, + tags: [ + { id: 'tag1', name: 'tag1 name' }, + { id: 'tag2', name: 'tag2 name' }, + ], + embeddedJson: { foo: 'bar' }, + }, }, - }, - }; - expect(getResponseParser(introspectionResults)(type)(response)).toEqual( - { + }; + expect( + getResponseParser(introspectionResults)( + type, + undefined, + undefined + )(response) + ).toEqual({ data: { id: 'post1', title: 'title1', @@ -161,56 +178,63 @@ const testSingleTypes = type => { tagsIds: ['tag1', 'tag2'], embeddedJson: { foo: 'bar' }, }, - } - ); - }); + }); + }); - it('returns the response expected by AOR for GET_LIST', () => { - const introspectionResults = { - resources: [ - { - type: { - name: 'User', - fields: [ - { name: 'id', type: { kind: TypeKind.SCALAR } }, - { - name: 'firstName', - type: { kind: TypeKind.SCALAR }, - }, - ], + it('returns the response expected for %s with simple arrays of values', () => { + const introspectionResults = { + resources: [ + { + type: { + name: 'User', + fields: [ + { name: 'id', type: { kind: TypeKind.SCALAR } }, + { + name: 'firstName', + type: { kind: TypeKind.SCALAR }, + }, + ], + }, }, - }, - { - type: { - name: 'Tag', - fields: [ - { name: 'id', type: { kind: TypeKind.SCALAR } }, - { name: 'name', type: { kind: TypeKind.SCALAR } }, - ], + { + type: { + name: 'Tag', + fields: [ + { name: 'id', type: { kind: TypeKind.SCALAR } }, + { + name: 'name', + type: { kind: TypeKind.SCALAR }, + }, + ], + }, }, - }, - ], - types: [{ name: 'User' }, { name: 'Tag' }], - }; - const response = { - data: { + ], + types: [{ name: 'User' }, { name: 'Tag' }], + }; + const response = { data: { - _typeName: 'Post', - id: 'post1', - title: 'title1', - author: { id: 'author1', firstName: 'Toto' }, - coauthor: null, - tags: [ - { id: 'tag1', name: 'tag1 name' }, - { id: 'tag2', name: 'tag2 name' }, - ], - features: ['feature1', 'feature2'], - embeddedJson: { foo: 'bar' }, + data: { + _typeName: 'Post', + id: 'post1', + title: 'title1', + author: { id: 'author1', firstName: 'Toto' }, + coauthor: null, + tags: [ + { id: 'tag1', name: 'tag1 name' }, + { id: 'tag2', name: 'tag2 name' }, + ], + features: ['feature1', 'feature2'], + embeddedJson: { foo: 'bar' }, + }, }, - }, - }; - expect(getResponseParser(introspectionResults)(type)(response)).toEqual( - { + }; + expect( + getResponseParser(introspectionResults)( + type, + undefined, + undefined + )(response) + ).toEqual({ data: { id: 'post1', title: 'title1', @@ -224,56 +248,63 @@ const testSingleTypes = type => { tagsIds: ['tag1', 'tag2'], embeddedJson: { foo: 'bar' }, }, - } - ); - }); + }); + }); - it('returns the response expected by AOR for GET_LIST with aliases', () => { - const introspectionResults = { - resources: [ - { - type: { - name: 'User', - fields: [ - { name: 'id', type: { kind: TypeKind.SCALAR } }, - { - name: 'firstName', - type: { kind: TypeKind.SCALAR }, - }, - ], + it('returns the response expected for %s with aliases', () => { + const introspectionResults = { + resources: [ + { + type: { + name: 'User', + fields: [ + { name: 'id', type: { kind: TypeKind.SCALAR } }, + { + name: 'firstName', + type: { kind: TypeKind.SCALAR }, + }, + ], + }, }, - }, - { - type: { - name: 'Tag', - fields: [ - { name: 'id', type: { kind: TypeKind.SCALAR } }, - { name: 'name', type: { kind: TypeKind.SCALAR } }, - ], + { + type: { + name: 'Tag', + fields: [ + { name: 'id', type: { kind: TypeKind.SCALAR } }, + { + name: 'name', + type: { kind: TypeKind.SCALAR }, + }, + ], + }, }, - }, - ], - types: [{ name: 'User' }, { name: 'Tag' }], - }; - const response = { - data: { + ], + types: [{ name: 'User' }, { name: 'Tag' }], + }; + const response = { data: { - _typeName: 'Post', - id: 'post1', - aliasTitle: 'title1', - author: { id: 'author1', firstName: 'Toto' }, - coauthor: null, - tags: [ - { id: 'tag1', name: 'tag1 name' }, - { id: 'tag2', name: 'tag2 name' }, - ], - embeddedJson: { foo: 'bar' }, + data: { + _typeName: 'Post', + id: 'post1', + aliasTitle: 'title1', + author: { id: 'author1', firstName: 'Toto' }, + coauthor: null, + tags: [ + { id: 'tag1', name: 'tag1 name' }, + { id: 'tag2', name: 'tag2 name' }, + ], + embeddedJson: { foo: 'bar' }, + }, }, - }, - }; + }; - expect(getResponseParser(introspectionResults)(type)(response)).toEqual( - { + expect( + getResponseParser(introspectionResults)( + type, + undefined, + undefined + )(response) + ).toEqual({ data: { aliasTitle: 'title1', author: { firstName: 'Toto', id: 'author1' }, @@ -288,16 +319,7 @@ const testSingleTypes = type => { ], tagsIds: ['tag1', 'tag2'], }, - } - ); + }); + }); }); -}; - -describe('getResponseParser', () => { - testListTypes(GET_LIST); - testListTypes(GET_MANY); - testListTypes(GET_MANY_REFERENCE); - testSingleTypes(CREATE); - testSingleTypes(UPDATE); - testSingleTypes(DELETE); }); diff --git a/packages/ra-data-graphql-simple/src/getResponseParser.ts b/packages/ra-data-graphql-simple/src/getResponseParser.ts index bf8aeb81549..16db9d7ab1b 100644 --- a/packages/ra-data-graphql-simple/src/getResponseParser.ts +++ b/packages/ra-data-graphql-simple/src/getResponseParser.ts @@ -30,36 +30,39 @@ const sanitizeResource = (data: any) => { return acc; } - const dataKey = data[key]; + const dataForKey = data[key]; - if (dataKey === null || dataKey === undefined) { + if (dataForKey === null || dataForKey === undefined) { return acc; } - if (Array.isArray(dataKey)) { - if (typeof dataKey[0] === 'object' && dataKey[0] !== null) { + if (Array.isArray(dataForKey)) { + if (typeof dataForKey[0] === 'object' && dataForKey[0] !== null) { return { ...acc, - [key]: dataKey.map(sanitizeResource), - [`${key}Ids`]: dataKey.map(d => d.id), + [key]: dataForKey.map(sanitizeResource), + [`${key}Ids`]: dataForKey.map(d => d.id), }; } else { - return { ...acc, [key]: dataKey }; + return { ...acc, [key]: dataForKey }; } } - if (typeof dataKey === 'object' && dataKey !== null) { + if (typeof dataForKey === 'object' && dataForKey !== null) { return { ...acc, - ...(dataKey && - dataKey.id && { - [`${key}.id`]: dataKey.id, + ...(dataForKey && + dataForKey.id && { + [`${key}.id`]: dataForKey.id, }), - [key]: sanitizeResource(dataKey), + // We should only sanitize gql types, not objects + [key]: dataForKey.__typename + ? sanitizeResource(dataForKey) + : dataForKey, }; } - return { ...acc, [key]: dataKey }; + return { ...acc, [key]: dataForKey }; }, {}); return result;