Skip to content

Commit

Permalink
Fixes #3905 - better graphql mutation error reporting (#4308)
Browse files Browse the repository at this point in the history
  • Loading branch information
codyebberson committed Apr 4, 2024
1 parent 4306ebc commit ef42053
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 13 deletions.
147 changes: 147 additions & 0 deletions packages/fhir-router/src/graphql/graphql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,49 @@ describe('GraphQL', () => {
expect(retrievePatient.name?.[0].given).toEqual(['Bob']);
});

test('Create wrong resourceType error', async () => {
const request: FhirRequest = {
method: 'POST',
pathname: '/fhir/R4/$graphql',
query: {},
params: {},
body: {
query: `
mutation {
PatientCreate(res: { resourceType: "ServiceRequest" }) { id }
}
`,
},
};
const fhirRouter = new FhirRouter();
const res = await graphqlHandler(request, repo, fhirRouter);
expect(res).toMatchObject([
{
resourceType: 'OperationOutcome',
id: 'ok',
issue: [
{
severity: 'information',
code: 'informational',
details: { text: 'All OK' },
},
],
},
{
errors: [
{
message: 'Invalid resourceType',
locations: [{ line: 3, column: 9 }],
path: ['PatientCreate'],
},
],
data: {
PatientCreate: null,
},
},
]);
});

test('Updating Patient Record', async () => {
const patient = await repo.createResource<Patient>({
resourceType: 'Patient',
Expand Down Expand Up @@ -1188,6 +1231,110 @@ describe('GraphQL', () => {
);
});

test('Update wrong resourceType error', async () => {
const patient = await repo.createResource<Patient>({ resourceType: 'Patient' });
const request: FhirRequest = {
method: 'POST',
pathname: '/fhir/R4/$graphql',
query: {},
params: {},
body: {
query: `
mutation {
PatientUpdate(
id: "${patient.id}"
res: {
resourceType: "ServiceRequest"
id: "${patient.id}"
}
) {
id
}
}
`,
},
};
const fhirRouter = new FhirRouter();
const res = await graphqlHandler(request, repo, fhirRouter);
expect(res).toMatchObject([
{
resourceType: 'OperationOutcome',
id: 'ok',
issue: [
{
severity: 'information',
code: 'informational',
details: { text: 'All OK' },
},
],
},
{
errors: [
{
message: 'Invalid resourceType',
locations: [{ line: 3, column: 9 }],
path: ['PatientUpdate'],
},
],
data: {
PatientUpdate: null,
},
},
]);
});

test('Update wrong ID error', async () => {
const patient = await repo.createResource<Patient>({ resourceType: 'Patient' });
const request: FhirRequest = {
method: 'POST',
pathname: '/fhir/R4/$graphql',
query: {},
params: {},
body: {
query: `
mutation {
PatientUpdate(
id: "${patient.id}"
res: {
resourceType: "Patient"
id: "${randomUUID()}"
}
) {
id
}
}
`,
},
};
const fhirRouter = new FhirRouter();
const res = await graphqlHandler(request, repo, fhirRouter);
expect(res).toMatchObject([
{
resourceType: 'OperationOutcome',
id: 'ok',
issue: [
{
severity: 'information',
code: 'informational',
details: { text: 'All OK' },
},
],
},
{
errors: [
{
message: 'Invalid ID',
locations: [{ line: 3, column: 9 }],
path: ['PatientUpdate'],
},
],
data: {
PatientUpdate: null,
},
},
]);
});

test('Delete Patient Record', async () => {
const patient = await repo.createResource<Patient>({
resourceType: 'Patient',
Expand Down
20 changes: 7 additions & 13 deletions packages/fhir-router/src/graphql/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,18 +350,14 @@ async function resolveByCreate(
info: GraphQLResolveInfo
): Promise<any> {
const fieldName = info.fieldName;
// 'Create.length'=== 6 && 'Update.length' === 6
const resourceType = fieldName.substring(0, fieldName.length - 6) as ResourceType;
const resourceType = fieldName.substring(0, fieldName.length - 'Create'.length) as ResourceType;
const resourceArgs = args.res;
if (resourceArgs.resourceType !== resourceType) {
return [badRequest('Invalid resourceType')];
throw new OperationOutcomeError(badRequest('Invalid resourceType'));
}
const resource = await ctx.repo.createResource(resourceArgs as Resource);
return resource;
return ctx.repo.createResource(resourceArgs as Resource);
}

// Mutation Resolvers

/**
* GraphQL resolver function for update requests.
* The field name should end with "Update" (i.e., "PatientUpdate" for updating a Patient).
Expand All @@ -379,18 +375,16 @@ async function resolveByUpdate(
info: GraphQLResolveInfo
): Promise<any> {
const fieldName = info.fieldName;
// 'Create.length'=== 6 && 'Update.length' === 6
const resourceType = fieldName.substring(0, fieldName.length - 6) as ResourceType;
const resourceType = fieldName.substring(0, fieldName.length - 'Update'.length) as ResourceType;
const resourceArgs = args.res;
const resourceId = args.id;
if (resourceArgs.resourceType !== resourceType) {
return [badRequest('Invalid resourceType')];
throw new OperationOutcomeError(badRequest('Invalid resourceType'));
}
if (resourceId !== resourceArgs.id) {
return [badRequest('Incorrect ID')];
throw new OperationOutcomeError(badRequest('Invalid ID'));
}
const resource = await ctx.repo.updateResource(resourceArgs as Resource);
return resource;
return ctx.repo.updateResource(resourceArgs as Resource);
}

/**
Expand Down

0 comments on commit ef42053

Please sign in to comment.