Skip to content
This repository has been archived by the owner on Oct 23, 2024. It is now read-only.

Commit

Permalink
chore: improve debug messages for field resolvers
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Schmidt authored and DanielMSchmidt committed Jan 4, 2019
1 parent 2268ab1 commit 8df56d8
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 3 deletions.
36 changes: 36 additions & 0 deletions src/__tests__/fieldNotFoundMessageForType-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { GraphQLObjectType, GraphQLString, GraphQLScalarType } from "graphql";
import { fieldNotFoundMessageForType } from "..";

describe("fieldNotFoundMessageForType", () => {
it("returns a helpful message for null", () => {
expect(fieldNotFoundMessageForType(null)).toBe(
"The type should not be null."
);
});

it("returns a helpful message for scalar types", () => {
expect(
fieldNotFoundMessageForType(
new GraphQLScalarType({
name: "Odd",
serialize(value) {
return value % 2 === 1 ? value : null;
}
})
)
).toBe("The field has a scalar type, which means it supports no nesting.");
});

it("returns all field names for object type", () => {
expect(
fieldNotFoundMessageForType(
new GraphQLObjectType({
name: "Row",
fields: () => ({
id: { type: GraphQLString }
})
})
)
).toBe("The only fields found in this Object are: id.");
});
});
22 changes: 21 additions & 1 deletion src/__tests__/graphqlObservable-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ describe("graphqlObservable", function() {
});
});

itMarbles("nested resolvers pass down the context and parent", function(m) {
itMarbles("throwing an error results in an error observable", function(m) {
const query = gql`
query {
throwingResolver
Expand All @@ -546,6 +546,26 @@ describe("graphqlObservable", function() {
const result = graphqlObservable(query, fieldResolverSchema, {});
m.expect(result.take(1)).toBeObservable(expected);
});

itMarbles(
"accessing an unknown query field results in an error observable",
function(m) {
const query = gql`
query {
youDontKnowMe
}
`;
const expected = m.cold(
"#",
{},
new Error(
"reactive-graphql: field 'youDontKnowMe' was not found on type 'Query'. The only fields found in this Object are: plain,item,nested,throwingResolver."
)
);
const result = graphqlObservable(query, fieldResolverSchema, {});
m.expect(result.take(1)).toBeObservable(expected);
}
);
});

describe("Mutation", function() {
Expand Down
33 changes: 31 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import {
isTypeSystemDefinitionNode,
isTypeSystemExtensionNode,
Kind,
ArgumentNode
ArgumentNode,
isScalarType,
isEnumType,
isObjectType
} from "graphql";

// WARNING: This is NOT a spec complete graphql implementation
Expand Down Expand Up @@ -106,7 +109,11 @@ export default function graphqlObservable<T = object>(
// Something unexpcected was passed into getField
if (field === null) {
return throwObservable(
`field was not of the right type. Given type: ${type}`
`field '${
definition.name.value
}' was not found on type '${type}'. ${fieldNotFoundMessageForType(
type
)}`
);
}

Expand Down Expand Up @@ -334,3 +341,25 @@ function resolveField(
);
}
}

export function fieldNotFoundMessageForType(type: GraphQLType | null): string {
if (type === null) {
return "The type should not be null.";
}

if (isScalarType(type)) {
return "The field has a scalar type, which means it supports no nesting.";
}

if (isEnumType(type)) {
return "The field has an enum type, which means it supports no nesting.";
}

if (isObjectType(type)) {
return `The only fields found in this Object are: ${Object.keys(
type.getFields()
)}.`;
}

return "";
}

0 comments on commit 8df56d8

Please sign in to comment.