Skip to content

Commit

Permalink
fix: directives running twice when used on Query and Mutation
Browse files Browse the repository at this point in the history
  • Loading branch information
felipebergamin committed Oct 4, 2023
1 parent d5f0602 commit 56a7e5a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
10 changes: 9 additions & 1 deletion lib/createSchemaMapperForVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,15 @@ export const createSchemaMapperForVisitor =
visitor: EasyDirectiveVisitor<any, any, T>,
): SchemaMapperFunction =>
(unmappedSchema: GraphQLSchema): GraphQLSchema => {
return mapSchema(unmappedSchema, createMapper(directiveName, visitor));
const { 'MapperKind.MUTATION': mutationMapper, ...mappers } = createMapper(
directiveName,
visitor,
);
const mappedSchema = mapSchema(unmappedSchema, mappers);
// run mutation mapper separately toa void conflicts with Query mapper adding validation functions to schema object
return mapSchema(mappedSchema, {
[MapperKind.MUTATION]: mutationMapper,
});
};

export default createSchemaMapperForVisitor;
56 changes: 56 additions & 0 deletions lib/foreignNodeId.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,4 +318,60 @@ ${validationDirectionEnumTypeDefs(capitalizedName)}
expect.any(Object),
);
});

it('should not duplicate validation when same type is used on Query and Mutation', async () => {
const mockResolver = jest.fn().mockReturnValue('return value');
const typeName = 'MyType';
const decodedId = 'abc';
const encodedId = toNodeId('MyType', decodedId);
const schema = new ForeignNodeId().applyToSchema(
makeExecutableSchema({
resolvers: {
Mutation: {
testDirective: mockResolver,
},
Query: {
dummy: () => '',
},
},
typeDefs: [
...directiveTypeDefs,
gql`
input Input1 {
typeId: ID! @foreignNodeId(typename: "${typeName}")
}
type Query {
dummy(input: Input1): String
}
type Mutation {
testDirective(input: Input1): String
}
`,
],
}),
);
const source = print(gql`
mutation Testing($input: Input1!) {
testDirective(input: $input)
}
`);
const contextValue = ForeignNodeId.createDirectiveContext({
fromNodeId,
});
const fromNodeIdSpy = jest.spyOn(contextValue, 'fromNodeId');

await graphql({
contextValue,
schema,
source,
variableValues: {
input: {
typeId: encodedId,
},
},
});

expect(fromNodeIdSpy).toHaveBeenCalledTimes(1);
expect(fromNodeIdSpy).toHaveBeenCalledWith(encodedId);
});
});

0 comments on commit 56a7e5a

Please sign in to comment.