From 04cd1a821e53130874824f354f5c7bd657ebad75 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 15 Jul 2019 20:04:11 -0700 Subject: [PATCH 1/6] Generic call function mutation working --- .../loaders/defaultGraphQLMutations.js | 2 + src/GraphQL/loaders/functionsMutations.js | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/GraphQL/loaders/functionsMutations.js diff --git a/src/GraphQL/loaders/defaultGraphQLMutations.js b/src/GraphQL/loaders/defaultGraphQLMutations.js index 4d36c9e50b..c7ebc6347d 100644 --- a/src/GraphQL/loaders/defaultGraphQLMutations.js +++ b/src/GraphQL/loaders/defaultGraphQLMutations.js @@ -1,11 +1,13 @@ import * as objectsMutations from './objectsMutations'; import * as filesMutations from './filesMutations'; import * as usersMutations from './usersMutations'; +import * as functionsMutations from './functionsMutations'; const load = parseGraphQLSchema => { objectsMutations.load(parseGraphQLSchema); filesMutations.load(parseGraphQLSchema); usersMutations.load(parseGraphQLSchema); + functionsMutations.load(parseGraphQLSchema); }; export { load }; diff --git a/src/GraphQL/loaders/functionsMutations.js b/src/GraphQL/loaders/functionsMutations.js new file mode 100644 index 0000000000..ddb205387a --- /dev/null +++ b/src/GraphQL/loaders/functionsMutations.js @@ -0,0 +1,57 @@ +import { GraphQLObjectType, GraphQLNonNull, GraphQLString } from 'graphql'; +import { FunctionsRouter } from '../../Routers/FunctionsRouter'; +import * as defaultGraphQLTypes from './defaultGraphQLTypes'; + +const load = parseGraphQLSchema => { + const fields = {}; + + fields.call = { + description: + 'The call mutation can be used to invoke a cloud code function.', + args: { + functionName: { + description: 'This is the name of the function to be called.', + type: new GraphQLNonNull(GraphQLString), + }, + params: { + description: 'These are the params to be passed to the function.', + type: defaultGraphQLTypes.OBJECT, + }, + }, + type: defaultGraphQLTypes.OBJECT, + async resolve(_source, args, context) { + try { + const { functionName, params } = args; + const { config, auth, info } = context; + + return (await FunctionsRouter.handleCloudFunction({ + params: { + functionName, + }, + config, + auth, + info, + body: params, + })).response; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + }, + }; + + const functionsMutation = new GraphQLObjectType({ + name: 'FunctionsMutation', + description: + 'FunctionsMutation is the top level type for functions mutations.', + fields, + }); + parseGraphQLSchema.graphQLTypes.push(functionsMutation); + + parseGraphQLSchema.graphQLMutations.functions = { + description: 'This is the top level for functions mutations.', + type: functionsMutation, + resolve: () => new Object(), + }; +}; + +export { load }; From 5bd87cf57bf200fc7e66c3b55b4a4669808d350f Mon Sep 17 00:00:00 2001 From: = Date: Tue, 16 Jul 2019 13:43:57 -0700 Subject: [PATCH 2/6] Change function return type to anyd --- spec/ParseGraphQLServer.spec.js | 2 ++ src/GraphQL/loaders/functionsMutations.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index cc26786119..89f8c23ed8 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -3372,6 +3372,8 @@ describe('ParseGraphQLServer', () => { }); }); + describe('Functions Mutations', () => {}); + describe('Data Types', () => { it('should support String', async () => { const someFieldValue = 'some string'; diff --git a/src/GraphQL/loaders/functionsMutations.js b/src/GraphQL/loaders/functionsMutations.js index ddb205387a..e8f98256ec 100644 --- a/src/GraphQL/loaders/functionsMutations.js +++ b/src/GraphQL/loaders/functionsMutations.js @@ -18,7 +18,7 @@ const load = parseGraphQLSchema => { type: defaultGraphQLTypes.OBJECT, }, }, - type: defaultGraphQLTypes.OBJECT, + type: defaultGraphQLTypes.ANY, async resolve(_source, args, context) { try { const { functionName, params } = args; From eb2aa6464d7f5eb608d738cabe18c1f1f5650c82 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 16 Jul 2019 13:53:05 -0700 Subject: [PATCH 3/6] First passing test --- spec/ParseGraphQLServer.spec.js | 20 +++++++++++++++++++- src/GraphQL/loaders/functionsMutations.js | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 89f8c23ed8..76e214b4ac 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -3372,7 +3372,25 @@ describe('ParseGraphQLServer', () => { }); }); - describe('Functions Mutations', () => {}); + describe('Functions Mutations', () => { + fit('can call functions', async () => { + Parse.Cloud.define('hello', async () => { + return 'Hello world!'; + }); + + const result = await apolloClient.mutate({ + mutation: gql` + mutation CallFunction { + functions { + call(functionName: "hello") + } + } + `, + }); + + expect(result.data.functions.call).toEqual('Hello world!'); + }); + }); describe('Data Types', () => { it('should support String', async () => { diff --git a/src/GraphQL/loaders/functionsMutations.js b/src/GraphQL/loaders/functionsMutations.js index e8f98256ec..6a7b9a3de9 100644 --- a/src/GraphQL/loaders/functionsMutations.js +++ b/src/GraphQL/loaders/functionsMutations.js @@ -32,7 +32,7 @@ const load = parseGraphQLSchema => { auth, info, body: params, - })).response; + })).response.result; } catch (e) { parseGraphQLSchema.handleError(e); } From e1923994f13b563c1b902f9689cb6768f2f6824f Mon Sep 17 00:00:00 2001 From: = Date: Tue, 16 Jul 2019 13:57:11 -0700 Subject: [PATCH 4/6] Testing errors --- spec/ParseGraphQLServer.spec.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 76e214b4ac..01adc08d3d 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -3373,7 +3373,7 @@ describe('ParseGraphQLServer', () => { }); describe('Functions Mutations', () => { - fit('can call functions', async () => { + fit('can be called', async () => { Parse.Cloud.define('hello', async () => { return 'Hello world!'; }); @@ -3390,6 +3390,29 @@ describe('ParseGraphQLServer', () => { expect(result.data.functions.call).toEqual('Hello world!'); }); + + fit('can throw errors', async () => { + Parse.Cloud.define('hello', async () => { + throw new Error('Some error message.'); + }); + + try { + await apolloClient.mutate({ + mutation: gql` + mutation CallFunction { + functions { + call(functionName: "hello") + } + } + `, + }); + fail('Should throw an error'); + } catch (e) { + const { graphQLErrors } = e; + expect(graphQLErrors.length).toBe(1); + expect(graphQLErrors[0].message).toBe('Some error message.'); + } + }); }); describe('Data Types', () => { From a0b8c15a537e6a0808f206b377ac42a28844d98d Mon Sep 17 00:00:00 2001 From: = Date: Tue, 16 Jul 2019 14:04:31 -0700 Subject: [PATCH 5/6] Testing different data types --- spec/ParseGraphQLServer.spec.js | 100 ++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 01adc08d3d..258af67a56 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -3413,6 +3413,106 @@ describe('ParseGraphQLServer', () => { expect(graphQLErrors[0].message).toBe('Some error message.'); } }); + + fit('should accept different params', done => { + Parse.Cloud.define('hello', async req => { + expect(req.params.date instanceof Date).toBe(true); + expect(req.params.date.getTime()).toBe(1463907600000); + expect(req.params.dateList[0] instanceof Date).toBe(true); + expect(req.params.dateList[0].getTime()).toBe(1463907600000); + expect(req.params.complexStructure.date[0] instanceof Date).toBe( + true + ); + expect(req.params.complexStructure.date[0].getTime()).toBe( + 1463907600000 + ); + expect( + req.params.complexStructure.deepDate.date[0] instanceof Date + ).toBe(true); + expect(req.params.complexStructure.deepDate.date[0].getTime()).toBe( + 1463907600000 + ); + expect( + req.params.complexStructure.deepDate2[0].date instanceof Date + ).toBe(true); + expect( + req.params.complexStructure.deepDate2[0].date.getTime() + ).toBe(1463907600000); + // Regression for #2294 + expect(req.params.file instanceof Parse.File).toBe(true); + expect(req.params.file.url()).toEqual('https://some.url'); + // Regression for #2204 + expect(req.params.array).toEqual(['a', 'b', 'c']); + expect(Array.isArray(req.params.array)).toBe(true); + expect(req.params.arrayOfArray).toEqual([ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ]); + expect(Array.isArray(req.params.arrayOfArray)).toBe(true); + expect(Array.isArray(req.params.arrayOfArray[0])).toBe(true); + expect(Array.isArray(req.params.arrayOfArray[1])).toBe(true); + + done(); + }); + + const params = { + date: { + __type: 'Date', + iso: '2016-05-22T09:00:00.000Z', + }, + dateList: [ + { + __type: 'Date', + iso: '2016-05-22T09:00:00.000Z', + }, + ], + lol: 'hello', + complexStructure: { + date: [ + { + __type: 'Date', + iso: '2016-05-22T09:00:00.000Z', + }, + ], + deepDate: { + date: [ + { + __type: 'Date', + iso: '2016-05-22T09:00:00.000Z', + }, + ], + }, + deepDate2: [ + { + date: { + __type: 'Date', + iso: '2016-05-22T09:00:00.000Z', + }, + }, + ], + }, + file: Parse.File.fromJSON({ + __type: 'File', + name: 'name', + url: 'https://some.url', + }), + array: ['a', 'b', 'c'], + arrayOfArray: [['a', 'b', 'c'], ['d', 'e', 'f']], + }; + + apolloClient.mutate({ + mutation: gql` + mutation CallFunction($params: Object) { + functions { + call(functionName: "hello", params: $params) + } + } + `, + variables: { + params, + }, + }); + }); }); describe('Data Types', () => { From 30722b923107b940634e69d88895621385ee4799 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 16 Jul 2019 14:06:42 -0700 Subject: [PATCH 6/6] Removing fit tests --- spec/ParseGraphQLServer.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 258af67a56..d46a5f769b 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -3373,7 +3373,7 @@ describe('ParseGraphQLServer', () => { }); describe('Functions Mutations', () => { - fit('can be called', async () => { + it('can be called', async () => { Parse.Cloud.define('hello', async () => { return 'Hello world!'; }); @@ -3391,7 +3391,7 @@ describe('ParseGraphQLServer', () => { expect(result.data.functions.call).toEqual('Hello world!'); }); - fit('can throw errors', async () => { + it('can throw errors', async () => { Parse.Cloud.define('hello', async () => { throw new Error('Some error message.'); }); @@ -3414,7 +3414,7 @@ describe('ParseGraphQLServer', () => { } }); - fit('should accept different params', done => { + it('should accept different params', done => { Parse.Cloud.define('hello', async req => { expect(req.params.date instanceof Date).toBe(true); expect(req.params.date.getTime()).toBe(1463907600000);