Skip to content

Commit

Permalink
feat: alphabetical graphql api, fix internal reassign, enhanced Graph…
Browse files Browse the repository at this point in the history
…ql schema cache system (#7344)
  • Loading branch information
Moumouls authored Oct 11, 2021
1 parent 90b18bc commit 85ef721
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 78 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ ___
- ci: add node engine version check (Manuel Trezza) [#7574](https://github.com/parse-community/parse-server/pull/7574)

### Notable Changes
- Alphabetical ordered GraphQL API, improved GraphQL Schema cache system and fix GraphQL input reassign issue (Moumouls) [#7344](https://github.com/parse-community/parse-server/issues/7344)
- Added Parse Server Security Check to report weak security settings (Manuel Trezza, dblythy) [#7247](https://github.com/parse-community/parse-server/issues/7247)
- EXPERIMENTAL: Added new page router with placeholder rendering and localization of custom and feature pages such as password reset and email verification (Manuel Trezza) [#7128](https://github.com/parse-community/parse-server/pull/7128)
- EXPERIMENTAL: Added custom routes to easily customize flows for password reset, email verification or build entirely new flows (Manuel Trezza) [#7231](https://github.com/parse-community/parse-server/pull/7231)
Expand Down
8 changes: 4 additions & 4 deletions spec/ParseGraphQLSchema.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('ParseGraphQLSchema', () => {
it('should load a brand new GraphQL Schema if Parse Schema changes', async () => {
await parseGraphQLSchema.load();
const parseClasses = parseGraphQLSchema.parseClasses;
const parseClassesString = parseGraphQLSchema.parseClassesString;
const parseCachedClasses = parseGraphQLSchema.parseCachedClasses;
const parseClassTypes = parseGraphQLSchema.parseClassTypes;
const graphQLSchema = parseGraphQLSchema.graphQLSchema;
const graphQLTypes = parseGraphQLSchema.graphQLTypes;
Expand All @@ -70,7 +70,7 @@ describe('ParseGraphQLSchema', () => {
await new Promise(resolve => setTimeout(resolve, 200));
await parseGraphQLSchema.load();
expect(parseClasses).not.toBe(parseGraphQLSchema.parseClasses);
expect(parseClassesString).not.toBe(parseGraphQLSchema.parseClassesString);
expect(parseCachedClasses).not.toBe(parseGraphQLSchema.parseCachedClasses);
expect(parseClassTypes).not.toBe(parseGraphQLSchema.parseClassTypes);
expect(graphQLSchema).not.toBe(parseGraphQLSchema.graphQLSchema);
expect(graphQLTypes).not.toBe(parseGraphQLSchema.graphQLTypes);
Expand All @@ -94,7 +94,7 @@ describe('ParseGraphQLSchema', () => {
});
await parseGraphQLSchema.load();
const parseClasses = parseGraphQLSchema.parseClasses;
const parseClassesString = parseGraphQLSchema.parseClassesString;
const parseCachedClasses = parseGraphQLSchema.parseCachedClasses;
const parseClassTypes = parseGraphQLSchema.parseClassTypes;
const graphQLSchema = parseGraphQLSchema.graphQLSchema;
const graphQLTypes = parseGraphQLSchema.graphQLTypes;
Expand All @@ -109,7 +109,7 @@ describe('ParseGraphQLSchema', () => {
await new Promise(resolve => setTimeout(resolve, 200));
await parseGraphQLSchema.load();
expect(parseClasses).not.toBe(parseGraphQLSchema.parseClasses);
expect(parseClassesString).not.toBe(parseGraphQLSchema.parseClassesString);
expect(parseCachedClasses).not.toBe(parseGraphQLSchema.parseCachedClasses);
expect(parseClassTypes).not.toBe(parseGraphQLSchema.parseClassTypes);
expect(graphQLSchema).not.toBe(parseGraphQLSchema.graphQLSchema);
expect(graphQLTypes).not.toBe(parseGraphQLSchema.graphQLTypes);
Expand Down
94 changes: 94 additions & 0 deletions spec/ParseGraphQLServer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
GraphQLEnumType,
GraphQLInputObjectType,
GraphQLSchema,
GraphQLList,
} = require('graphql');
const { ParseServer } = require('../');
const { ParseGraphQLServer } = require('../lib/GraphQL/ParseGraphQLServer');
Expand Down Expand Up @@ -10341,6 +10342,18 @@ describe('ParseGraphQLServer', () => {
robot: { value: 'robot' },
},
});
const TypeEnumWhereInput = new GraphQLInputObjectType({
name: 'TypeEnumWhereInput',
fields: {
equalTo: { type: TypeEnum },
},
});
const SomeClass2WhereInput = new GraphQLInputObjectType({
name: 'SomeClass2WhereInput',
fields: {
type: { type: TypeEnumWhereInput },
},
});
const SomeClassType = new GraphQLObjectType({
name: 'SomeClass',
fields: {
Expand Down Expand Up @@ -10386,6 +10399,18 @@ describe('ParseGraphQLServer', () => {
return obj.toJSON();
},
},
customQueryWithAutoTypeReturnList: {
type: new GraphQLList(SomeClassType),
args: {
id: { type: new GraphQLNonNull(GraphQLString) },
},
resolve: async (p, { id }) => {
const obj = new Parse.Object('SomeClass');
obj.id = id;
await obj.fetch();
return [obj.toJSON(), obj.toJSON(), obj.toJSON()];
},
},
},
}),
types: [
Expand All @@ -10401,7 +10426,17 @@ describe('ParseGraphQLServer', () => {
type: { type: TypeEnum },
},
}),
// Enhanced where input with a extended enum
new GraphQLInputObjectType({
name: 'SomeClassWhereInput',
fields: {
type: {
type: TypeEnumWhereInput,
},
},
}),
SomeClassType,
SomeClass2WhereInput,
],
}),
});
Expand Down Expand Up @@ -10463,6 +10498,65 @@ describe('ParseGraphQLServer', () => {
expect(result.data.customQueryWithAutoTypeReturn.type).toEqual('robot');
});

it('can resolve a custom query with auto type list return', async () => {
const obj = new Parse.Object('SomeClass');
await obj.save({ name: 'aname', type: 'robot' });
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
const result = await apolloClient.query({
variables: { id: obj.id },
query: gql`
query CustomQuery($id: String!) {
customQueryWithAutoTypeReturnList(id: $id) {
id
objectId
nameUpperCase
name
type
}
}
`,
});
result.data.customQueryWithAutoTypeReturnList.forEach(rObj => {
expect(rObj.objectId).toBeDefined();
expect(rObj.objectId).toEqual(obj.id);
expect(rObj.name).toEqual('aname');
expect(rObj.nameUpperCase).toEqual('ANAME');
expect(rObj.type).toEqual('robot');
});
});

it('can resolve a stacked query with same where variables on overloaded where input', async () => {
const objPointer = new Parse.Object('SomeClass2');
await objPointer.save({ name: 'aname', type: 'robot' });
const obj = new Parse.Object('SomeClass');
await obj.save({ name: 'aname', type: 'robot', pointer: objPointer });
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
const result = await apolloClient.query({
variables: { where: { OR: [{ pointer: { have: { objectId: { exists: true } } } }] } },
query: gql`
query someQuery($where: SomeClassWhereInput!) {
q1: someClasses(where: $where) {
edges {
node {
id
}
}
}
q2: someClasses(where: $where) {
edges {
node {
id
}
}
}
}
`,
});
expect(result.data.q1.edges.length).toEqual(1);
expect(result.data.q2.edges.length).toEqual(1);
expect(result.data.q1.edges[0].node.id).toEqual(result.data.q2.edges[0].node.id);
});

it('can resolve a custom extend type', async () => {
const obj = new Parse.Object('SomeClass');
await obj.save({ name: 'aname', type: 'robot' });
Expand Down
Loading

0 comments on commit 85ef721

Please sign in to comment.