Move tests for context types from apollo-server into integration testsuite (#2363)

* refactor: move tests for context function added in apollo-server into integration test suite

* Move existing context tests in integration testsuite into `describe('context field'`

# Conflicts:
#	packages/apollo-server-integration-testsuite/src/ApolloServer.ts

* Add back tests in apollo-server along with comments to explain the duplication
This commit is contained in:
Chang Wang 2019-02-27 06:30:56 -05:00 committed by Jesse Rosenberger
parent 0b14a3f1ff
commit f8fc1e1922
2 changed files with 170 additions and 108 deletions

View file

@ -690,136 +690,194 @@ export function testApolloServer<AS extends ApolloServerBase>(
expect(formatError).toHaveBeenCalledTimes(1);
});
it('defers context eval with thunk until after options creation', async () => {
const uniqueContext = { key: 'major' };
describe('context field', () => {
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: (_parent, _args, context) => {
expect(context).toEqual(Promise.resolve(uniqueContext));
return 'hi';
},
hello: () => 'hi',
},
};
const spy = jest.fn(() => ({}));
const { url: uri } = await createApolloServer({
typeDefs,
resolvers,
context: spy,
});
const apolloFetch = createApolloFetch({ uri });
expect(spy).not.toBeCalled();
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(1);
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(2);
});
it('allows context to be async function', async () => {
const uniqueContext = { key: 'major' };
const spy = jest.fn(() => 'hi');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: (_parent, _args, context) => {
expect(context.key).toEqual('major');
return spy();
it('defers context eval with thunk until after options creation', async () => {
const uniqueContext = { key: 'major' };
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: (_parent, _args, context) => {
expect(context).toEqual(Promise.resolve(uniqueContext));
return 'hi';
},
},
},
};
const { url: uri } = await createApolloServer({
typeDefs,
resolvers,
context: async () => uniqueContext,
};
const spy = jest.fn(() => ({}));
const { url: uri } = await createApolloServer({
typeDefs,
resolvers,
context: spy,
});
const apolloFetch = createApolloFetch({ uri });
expect(spy).not.toBeCalled();
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(1);
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(2);
});
const apolloFetch = createApolloFetch({ uri });
expect(spy).not.toBeCalled();
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(1);
});
it('clones the context for every request', async () => {
const uniqueContext = { key: 'major' };
const spy = jest.fn(() => 'hi');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: (_parent, _args, context) => {
expect(context.key).toEqual('major');
context.key = 'minor';
return spy();
it('clones the context for every request', async () => {
const uniqueContext = { key: 'major' };
const spy = jest.fn(() => 'hi');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: (_parent, _args, context) => {
expect(context.key).toEqual('major');
context.key = 'minor';
return spy();
},
},
},
};
const { url: uri } = await createApolloServer({
typeDefs,
resolvers,
context: uniqueContext,
};
const { url: uri } = await createApolloServer({
typeDefs,
resolvers,
context: uniqueContext,
});
const apolloFetch = createApolloFetch({ uri });
expect(spy).not.toBeCalled();
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(1);
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(2);
});
const apolloFetch = createApolloFetch({ uri });
describe('as a function', () => {
it('can accept and return `req`', async () => {
expect(
await createApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({ req }),
}),
).not.toThrow;
});
expect(spy).not.toBeCalled();
it('can accept nothing and return an empty object', async () => {
expect(
await createApolloServer({
typeDefs,
resolvers,
context: () => ({}),
}),
).not.toThrow;
});
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(1);
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(2);
});
it('can be an async function', async () => {
const uniqueContext = { key: 'major' };
const spy = jest.fn(() => 'hi');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: (_parent, _args, context) => {
expect(context.key).toEqual('major');
return spy();
},
},
};
const { url: uri } = await createApolloServer({
typeDefs,
resolvers,
context: async () => uniqueContext,
});
it('returns thrown context error as a valid graphql result', async () => {
const nodeEnv = process.env.NODE_ENV;
delete process.env.NODE_ENV;
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => {
throw Error('never get here');
},
},
};
const { url: uri } = await createApolloServer({
typeDefs,
resolvers,
context: () => {
throw new AuthenticationError('valid result');
},
const apolloFetch = createApolloFetch({ uri });
expect(spy).not.toBeCalled();
await apolloFetch({ query: '{hello}' });
expect(spy).toHaveBeenCalledTimes(1);
});
it('returns thrown context error as a valid graphql result', async () => {
const nodeEnv = process.env.NODE_ENV;
delete process.env.NODE_ENV;
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => {
throw Error('never get here');
},
},
};
const { url: uri } = await createApolloServer({
typeDefs,
resolvers,
context: () => {
throw new AuthenticationError('valid result');
},
});
const apolloFetch = createApolloFetch({ uri });
const result = await apolloFetch({ query: '{hello}' });
expect(result.errors.length).toEqual(1);
expect(result.data).toBeUndefined();
const e = result.errors[0];
expect(e.message).toMatch('valid result');
expect(e.extensions).toBeDefined();
expect(e.extensions.code).toEqual('UNAUTHENTICATED');
expect(e.extensions.exception.stacktrace).toBeDefined();
process.env.NODE_ENV = nodeEnv;
});
});
const apolloFetch = createApolloFetch({ uri });
describe('as an object', () => {
it('can be an empty object', async () => {
expect(
await createApolloServer({
typeDefs,
resolvers,
context: {},
}),
).not.toThrow;
});
const result = await apolloFetch({ query: '{hello}' });
expect(result.errors.length).toEqual(1);
expect(result.data).toBeUndefined();
const e = result.errors[0];
expect(e.message).toMatch('valid result');
expect(e.extensions).toBeDefined();
expect(e.extensions.code).toEqual('UNAUTHENTICATED');
expect(e.extensions.exception.stacktrace).toBeDefined();
process.env.NODE_ENV = nodeEnv;
it('can contain arbitrary values', async () => {
expect(
await createApolloServer({
typeDefs,
resolvers,
context: { value: 'arbitrary' },
}),
).not.toThrow;
});
});
});
it('propogates error codes in production', async () => {

View file

@ -25,6 +25,10 @@ describe('apollo-server', () => {
expect(() => new ApolloServer({ typeDefs, mocks: true })).not.toThrow;
});
// These tests are duplicates of ones in apollo-server-integration-testsuite
// We don't actually expect Jest to do much here, the purpose of these
// tests is to make sure our typings are correct, and to trigger a
// compile error if they aren't
describe('context field', () => {
describe('as a function', () => {
it('can accept and return `req`', () => {