Removes flattening of Errors inside of formatApolloErrors (#1288)

* remove unnesting of errors to support yup

* add test for error thrown by yup
This commit is contained in:
Evans Hauser 2018-07-02 14:54:32 -07:00 committed by GitHub
parent dae5349d57
commit 19478920e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 24 deletions

View file

@ -222,30 +222,27 @@ export function formatApolloErrors(
}
const { formatter, debug } = options;
const flattenedErrors: Error[] = [];
errors.forEach(error => {
// Errors that occur in graphql-tools can contain an errors array that contains the errors thrown in a merged schema
// https://github.com/apollographql/graphql-tools/blob/3d53986ca/src/stitching/errors.ts#L104-L107
//
// They are are wrapped in an extra GraphQL error
// https://github.com/apollographql/graphql-tools/blob/3d53986ca/src/stitching/errors.ts#L109-L113
// which calls:
// https://github.com/graphql/graphql-js/blob/0a30b62964/src/error/locatedError.js#L18-L37
if (Array.isArray((error as any).errors)) {
(error as any).errors.forEach(e => flattenedErrors.push(e));
} else if (
(error as any).originalError &&
Array.isArray((error as any).originalError.errors)
) {
(error as any).originalError.errors.forEach(e => flattenedErrors.push(e));
} else {
flattenedErrors.push(error);
}
});
// Errors that occur in graphql-tools can contain an errors array that contains the errors thrown in a merged schema
// https://github.com/apollographql/graphql-tools/blob/3d53986ca/src/stitching/errors.ts#L104-L107
//
// They are are wrapped in an extra GraphQL error
// https://github.com/apollographql/graphql-tools/blob/3d53986ca/src/stitching/errors.ts#L109-L113
// which calls:
// https://github.com/graphql/graphql-js/blob/0a30b62964/src/error/locatedError.js#L18-L37
// Some processing for these nested errors could be done here:
//
// if (Array.isArray((error as any).errors)) {
// (error as any).errors.forEach(e => flattenedErrors.push(e));
// } else if (
// (error as any).originalError &&
// Array.isArray((error as any).originalError.errors)
// ) {
// (error as any).originalError.errors.forEach(e => flattenedErrors.push(e));
// } else {
// flattenedErrors.push(error);
// }
const enrichedErrors = flattenedErrors.map(error =>
enrichError(error, debug),
);
const enrichedErrors = errors.map(error => enrichError(error, debug));
if (!formatter) {
return enrichedErrors;

View file

@ -39,7 +39,8 @@
"graphql-tag": "^2.9.2",
"js-sha256": "^0.9.0",
"subscriptions-transport-ws": "^0.9.11",
"ws": "^5.2.0"
"ws": "^5.2.0",
"yup": "^0.25.1"
},
"typings": "dist/index.d.ts",
"typescript": {

View file

@ -7,6 +7,7 @@ import 'mocha';
import { sha256 } from 'js-sha256';
import express = require('express');
import bodyParser = require('body-parser');
import yup = require('yup');
import { Trace } from 'apollo-engine-reporting-protobuf';
@ -33,6 +34,7 @@ import {
import { createApolloFetch } from 'apollo-fetch';
import {
AuthenticationError,
UserInputError,
gql,
Config,
ApolloServerBase,
@ -345,6 +347,61 @@ export function testApolloServer<AS extends ApolloServerBase>(
expect(formatError.calledTwice).true;
expect(throwError.calledTwice).true;
});
it('works with errors similar to GraphQL errors, such as yup', async () => {
const throwError = stub().callsFake(async () => {
const schema = yup.object().shape({
email: yup
.string()
.email()
.required('Please enter your email address'),
});
await schema.validate({ email: 'lol' });
});
const formatError = stub().callsFake(error => {
expect(error instanceof Error).true;
expect(error.extensions.code).to.equal('INTERNAL_SERVER_ERROR');
expect(error.extensions.exception.name).to.equal('ValidationError');
expect(error.extensions.exception.message).to.exist;
const inputError = new UserInputError('User Input Error');
return {
message: inputError.message,
extensions: inputError.extensions,
};
});
const { url: uri } = await createApolloServer({
typeDefs: gql`
type Query {
error: String
}
`,
resolvers: {
Query: {
error: () => {
return throwError();
},
},
},
introspection: true,
debug: true,
formatError,
});
const apolloFetch = createApolloFetch({ uri });
const result = await apolloFetch({
query: '{error}',
});
expect(result.data).to.deep.equal({ error: null });
expect(result.errors, 'errors should exist').to.exist;
expect(result.errors[0].extensions.code).equals('BAD_USER_INPUT');
expect(result.errors[0].message).equals('User Input Error');
expect(formatError.calledOnce).true;
expect(throwError.calledOnce).true;
});
});
describe('lifecycle', () => {