fix: Required option not handled correctly for special fields (File, GeoPoint, Polygon) on GraphQL API mutations (#8915)
This commit is contained in:
@@ -964,7 +964,7 @@ describe('Auth Adapter features', () => {
|
||||
allowExpiredAuthDataToken: false,
|
||||
});
|
||||
logger = require('../lib/logger').logger;
|
||||
spyOn(logger, 'error').and.callFake(() => { });
|
||||
spyOn(logger, 'error').and.callFake(() => {});
|
||||
user = new Parse.User();
|
||||
await user.save({ authData: { modernAdapter: { id: 'modernAdapter' } } });
|
||||
const user2 = new Parse.User();
|
||||
|
||||
@@ -9548,6 +9548,71 @@ describe('ParseGraphQLServer', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should support files on required file', async () => {
|
||||
try {
|
||||
parseServer = await global.reconfigureServer({
|
||||
publicServerURL: 'http://localhost:13377/parse',
|
||||
});
|
||||
const schemaController = await parseServer.config.databaseController.loadSchema();
|
||||
await schemaController.addClassIfNotExists('SomeClassWithRequiredFile', {
|
||||
someField: { type: 'File', required: true },
|
||||
});
|
||||
await resetGraphQLCache();
|
||||
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
|
||||
|
||||
const body = new FormData();
|
||||
body.append(
|
||||
'operations',
|
||||
JSON.stringify({
|
||||
query: `
|
||||
mutation CreateSomeObject(
|
||||
$fields: CreateSomeClassWithRequiredFileFieldsInput
|
||||
) {
|
||||
createSomeClassWithRequiredFile(
|
||||
input: { fields: $fields }
|
||||
) {
|
||||
someClassWithRequiredFile {
|
||||
id
|
||||
someField {
|
||||
name
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
fields: {
|
||||
someField: { upload: null },
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
body.append('map', JSON.stringify({ 1: ['variables.fields.someField.upload'] }));
|
||||
body.append('1', 'My File Content', {
|
||||
filename: 'myFileName.txt',
|
||||
contentType: 'text/plain',
|
||||
});
|
||||
|
||||
const res = await fetch('http://localhost:13377/graphql', {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body,
|
||||
});
|
||||
expect(res.status).toEqual(200);
|
||||
const resText = await res.text();
|
||||
const result = JSON.parse(resText);
|
||||
expect(
|
||||
result.data.createSomeClassWithRequiredFile.someClassWithRequiredFile.someField.name
|
||||
).toEqual(jasmine.stringMatching(/_myFileName.txt$/));
|
||||
expect(
|
||||
result.data.createSomeClassWithRequiredFile.someClassWithRequiredFile.someField.url
|
||||
).toEqual(jasmine.stringMatching(/_myFileName.txt$/));
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
}
|
||||
});
|
||||
|
||||
it('should support file upload for on fly creation through pointer and relation', async () => {
|
||||
parseServer = await global.reconfigureServer({
|
||||
publicServerURL: 'http://localhost:13377/parse',
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import Parse from 'parse/node';
|
||||
import { fromGlobalId } from 'graphql-relay';
|
||||
import { handleUpload } from '../loaders/filesMutations';
|
||||
import * as defaultGraphQLTypes from '../loaders/defaultGraphQLTypes';
|
||||
import * as objectsMutations from '../helpers/objectsMutations';
|
||||
|
||||
const transformTypes = async (
|
||||
@@ -28,27 +27,28 @@ const transformTypes = async (
|
||||
inputTypeField = classGraphQLUpdateTypeFields[field];
|
||||
}
|
||||
if (inputTypeField) {
|
||||
switch (true) {
|
||||
case inputTypeField.type === defaultGraphQLTypes.GEO_POINT_INPUT:
|
||||
const parseFieldType = parseClass.fields[field].type;
|
||||
switch (parseFieldType) {
|
||||
case 'GeoPoint':
|
||||
if (fields[field] === null) {
|
||||
fields[field] = { __op: 'Delete' };
|
||||
break;
|
||||
}
|
||||
fields[field] = transformers.geoPoint(fields[field]);
|
||||
break;
|
||||
case inputTypeField.type === defaultGraphQLTypes.POLYGON_INPUT:
|
||||
case 'Polygon':
|
||||
if (fields[field] === null) {
|
||||
fields[field] = { __op: 'Delete' };
|
||||
break;
|
||||
}
|
||||
fields[field] = transformers.polygon(fields[field]);
|
||||
break;
|
||||
case inputTypeField.type === defaultGraphQLTypes.FILE_INPUT:
|
||||
// Use `originalFields` to handle file upload since fields are a deepcopy and do not
|
||||
// keep the file object
|
||||
case 'File':
|
||||
// We need to use the originalFields to handle the file upload
|
||||
// since fields are a deepcopy and do not keep the file object
|
||||
fields[field] = await transformers.file(originalFields[field], req);
|
||||
break;
|
||||
case parseClass.fields[field].type === 'Relation':
|
||||
case 'Relation':
|
||||
fields[field] = await transformers.relation(
|
||||
parseClass.fields[field].targetClass,
|
||||
field,
|
||||
@@ -58,7 +58,7 @@ const transformTypes = async (
|
||||
req
|
||||
);
|
||||
break;
|
||||
case parseClass.fields[field].type === 'Pointer':
|
||||
case 'Pointer':
|
||||
if (fields[field] === null) {
|
||||
fields[field] = { __op: 'Delete' };
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user