Skip to content

Commit

Permalink
Throw TypeError when coercing an array into a GraphQLString (#925)
Browse files Browse the repository at this point in the history
* Throw TypeError when coercing an array into a GraphQLString

* Add coerceString to GraphQLString serialize flow
  • Loading branch information
robzhu authored and leebyron committed Aug 14, 2017
1 parent 85bfd13 commit 24a5038
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
51 changes: 51 additions & 0 deletions src/execution/__tests__/variables-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { expect } from 'chai';
import { describe, it } from 'mocha';
import { execute } from '../execute';
import { coerceValue } from '../values';
import { parse } from '../../language';
import {
GraphQLSchema,
Expand Down Expand Up @@ -592,6 +593,56 @@ describe('Execute: Handles inputs', () => {
});
});

it('reports error for array passed into string input', async () => {
const doc = `
query SetsNonNullable($value: String!) {
fieldWithNonNullableStringInput(input: $value)
}
`;
const ast = parse(doc);
const variables = {value: [ 1, 2, 3 ]};

expect(
await execute(schema, ast, null, null, variables)
).to.deep.equal({
errors: [ {
message:
'Variable "$value" got invalid value [1,2,3].\nExpected type ' +
'"String", found [1,2,3]: String cannot represent an array value: [1,2,3]',
locations: [ { line: 2, column: 31 } ],
path: undefined,
} ]
});
});

it('coercing an array to GraphQLString throws TypeError', async () => {
let caughtError;
try {
coerceValue(GraphQLString, [ 1, 2, 3 ]);
} catch (error) {
caughtError = error;
}

expect(caughtError instanceof TypeError).to.equal(true);
expect(caughtError && caughtError.message).to.equal(
'String cannot represent an array value: [1,2,3]'
);
});

it('serializing an array via GraphQLString throws TypeError', async () => {
let caughtError;
try {
GraphQLString.serialize([ 1, 2, 3 ]);
} catch (error) {
caughtError = error;
}

expect(caughtError instanceof TypeError).to.equal(true);
expect(caughtError && caughtError.message).to.equal(
'String cannot represent an array value: [1,2,3]'
);
});

it('reports error for non-provided variables for non-nullable inputs', async () => {
// Note: this test would typically fail validation before encountering
// this execution error, however for queries which previously validated
Expand Down
2 changes: 1 addition & 1 deletion src/execution/values.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export function getDirectiveValues(
/**
* Given a type and any value, return a runtime value coerced to match the type.
*/
function coerceValue(type: GraphQLInputType, value: mixed): mixed {
export function coerceValue(type: GraphQLInputType, value: mixed): mixed {
// Ensure flow knows that we treat function params as const.
const _value = value;

Expand Down
13 changes: 11 additions & 2 deletions src/type/scalars.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,23 @@ export const GraphQLFloat = new GraphQLScalarType({
}
});

function coerceString(value: mixed): ?string {
if (Array.isArray(value)) {
throw new TypeError(
`String cannot represent an array value: [${String(value)}]`
);
}
return String(value);
}

export const GraphQLString = new GraphQLScalarType({
name: 'String',
description:
'The `String` scalar type represents textual data, represented as UTF-8 ' +
'character sequences. The String type is most often used by GraphQL to ' +
'represent free-form human-readable text.',
serialize: String,
parseValue: String,
serialize: coerceString,
parseValue: coerceString,
parseLiteral(ast) {
return ast.kind === Kind.STRING ? ast.value : null;
}
Expand Down

0 comments on commit 24a5038

Please sign in to comment.