mirror of
https://github.com/vale981/apollo-server
synced 2025-03-06 10:11:40 -05:00
move ApolloServer tests into integration tests from core
This commit is contained in:
parent
304debf9ee
commit
9d853f4be4
8 changed files with 971 additions and 989 deletions
|
@ -1,957 +0,0 @@
|
|||
/* tslint:disable:no-unused-expression */
|
||||
import { expect } from 'chai';
|
||||
import { stub } from 'sinon';
|
||||
import http from 'http';
|
||||
import url from 'url';
|
||||
import 'mocha';
|
||||
import { sha256 } from 'js-sha256';
|
||||
|
||||
import {
|
||||
GraphQLSchema,
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
GraphQLError,
|
||||
ValidationContext,
|
||||
FieldDefinitionNode,
|
||||
} from 'graphql';
|
||||
|
||||
import { PubSub } from 'graphql-subscriptions';
|
||||
import { SubscriptionClient } from 'subscriptions-transport-ws';
|
||||
import WebSocket from 'ws';
|
||||
|
||||
import { execute } from 'apollo-link';
|
||||
import { createHttpLink } from 'apollo-link-http';
|
||||
import {
|
||||
createPersistedQueryLink as createPersistedQuery,
|
||||
VERSION,
|
||||
} from 'apollo-link-persisted-queries';
|
||||
|
||||
import { createApolloFetch } from 'apollo-fetch';
|
||||
import { ApolloServerBase } from './ApolloServer';
|
||||
import { AuthenticationError } from './errors';
|
||||
import { gql } from './index';
|
||||
import { convertNodeHttpToRequest } from './nodeHttpToRequest';
|
||||
import { runHttpQuery } from './runHttpQuery';
|
||||
|
||||
const INTROSPECTION_QUERY = `
|
||||
{
|
||||
__schema {
|
||||
directives {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const TEST_STRING_QUERY = `
|
||||
{
|
||||
testString
|
||||
}
|
||||
`;
|
||||
|
||||
const queryType = new GraphQLObjectType({
|
||||
name: 'QueryType',
|
||||
fields: {
|
||||
testString: {
|
||||
type: GraphQLString,
|
||||
resolve() {
|
||||
return 'test string';
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const schema = new GraphQLSchema({
|
||||
query: queryType,
|
||||
});
|
||||
|
||||
function createHttpServer(server: ApolloServerBase) {
|
||||
return http.createServer(async (req, res) => {
|
||||
let body: any = [];
|
||||
req
|
||||
.on('data', chunk => {
|
||||
body.push(chunk);
|
||||
})
|
||||
.on('end', () => {
|
||||
body = Buffer.concat(body).toString();
|
||||
// At this point, we have the headers, method, url and body, and can now
|
||||
// do whatever we need to in order to respond to this request.
|
||||
runHttpQuery([req, res], {
|
||||
method: req.method,
|
||||
options: (server as any).graphQLServerOptions({ req, res }),
|
||||
query:
|
||||
req.method.toUpperCase() === 'GET'
|
||||
? url.parse(req.url, true)
|
||||
: JSON.parse(body),
|
||||
request: convertNodeHttpToRequest(req),
|
||||
})
|
||||
.then(gqlResponse => {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.setHeader(
|
||||
'Content-Length',
|
||||
Buffer.byteLength(gqlResponse, 'utf8').toString(),
|
||||
);
|
||||
res.write(gqlResponse);
|
||||
res.end();
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.headers) {
|
||||
Object.keys(error.headers).forEach(header => {
|
||||
res.setHeader(header, error.headers[header]);
|
||||
});
|
||||
}
|
||||
|
||||
res.statusCode = error.statusCode;
|
||||
res.write(error.message);
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('ApolloServerBase', () => {
|
||||
describe('constructor', () => {
|
||||
describe('validation rules', () => {
|
||||
it('accepts additional rules', async () => {
|
||||
const NoTestString = (context: ValidationContext) => ({
|
||||
Field(node: FieldDefinitionNode) {
|
||||
if (node.name.value === 'testString') {
|
||||
context.reportError(
|
||||
new GraphQLError('Not allowed to use', [node]),
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const server = new ApolloServerBase({
|
||||
schema,
|
||||
validationRules: [NoTestString],
|
||||
introspection: false,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const introspectionResult = await apolloFetch({
|
||||
query: INTROSPECTION_QUERY,
|
||||
});
|
||||
expect(introspectionResult.data, 'data should not exist').not.to.exist;
|
||||
expect(introspectionResult.errors, 'errors should exist').to.exist;
|
||||
|
||||
const result = await apolloFetch({ query: TEST_STRING_QUERY });
|
||||
expect(result.data, 'data should not exist').not.to.exist;
|
||||
expect(result.errors, 'errors should exist').to.exist;
|
||||
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('allows introspection by default', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
delete process.env.NODE_ENV;
|
||||
|
||||
const server = new ApolloServerBase({
|
||||
schema,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: INTROSPECTION_QUERY });
|
||||
expect(result.data, 'data should not exist').to.exist;
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('prevents introspection by default during production', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const server = new ApolloServerBase({
|
||||
schema,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: INTROSPECTION_QUERY });
|
||||
expect(result.data, 'data should not exist').not.to.exist;
|
||||
expect(result.errors, 'errors should exist').to.exist;
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.errors[0].extensions.code).to.equal(
|
||||
'GRAPHQL_VALIDATION_FAILED',
|
||||
);
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('allows introspection to be enabled explicitly', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const server = new ApolloServerBase({
|
||||
schema,
|
||||
introspection: true,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: INTROSPECTION_QUERY });
|
||||
expect(result.data, 'data should not exist').to.exist;
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
await server.stop();
|
||||
});
|
||||
});
|
||||
|
||||
describe('schema creation', () => {
|
||||
it('accepts typeDefs and resolvers', async () => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const resolvers = { Query: { hello: () => 'hi' } };
|
||||
const server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
|
||||
expect(result.data).to.deep.equal({ hello: 'hi' });
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
await server.stop();
|
||||
});
|
||||
it('throws if typeDefs are a string', async () => {
|
||||
const typeDefs: any = `
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const resolvers = { Query: { hello: () => 'hi' } };
|
||||
|
||||
expect(
|
||||
() =>
|
||||
new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
}),
|
||||
).to.throw(/apollo-server/);
|
||||
});
|
||||
it('uses schema over resolvers + typeDefs', async () => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const resolvers = { Query: { hello: () => 'hi' } };
|
||||
const server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
schema,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const typeDefResult = await apolloFetch({ query: '{hello}' });
|
||||
|
||||
expect(typeDefResult.data, 'data should not exist').not.to.exist;
|
||||
expect(typeDefResult.errors, 'errors should exist').to.exist;
|
||||
|
||||
const result = await apolloFetch({ query: '{testString}' });
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
await server.stop();
|
||||
});
|
||||
it('allows mocks as boolean', async () => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
mocks: true,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
expect(result.data).to.deep.equal({ hello: 'Hello World' });
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('allows mocks as an object', async () => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
mocks: { String: () => 'mock city' },
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
|
||||
expect(result.data).to.deep.equal({ hello: 'mock city' });
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
await server.stop();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('lifecycle', () => {
|
||||
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).to.equal(Promise.resolve(uniqueContext));
|
||||
return 'hi';
|
||||
},
|
||||
},
|
||||
};
|
||||
const spy = stub().returns({});
|
||||
const server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
context: spy,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
expect(spy.notCalled).true;
|
||||
|
||||
await apolloFetch({ query: '{hello}' });
|
||||
expect(spy.calledOnce).true;
|
||||
await apolloFetch({ query: '{hello}' });
|
||||
expect(spy.calledTwice).true;
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('allows context to be async function', async () => {
|
||||
const uniqueContext = { key: 'major' };
|
||||
const spy = stub().returns('hi');
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const resolvers = {
|
||||
Query: {
|
||||
hello: (_parent, _args, context) => {
|
||||
expect(context).to.equal(uniqueContext);
|
||||
return spy();
|
||||
},
|
||||
},
|
||||
};
|
||||
const server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
context: async () => uniqueContext,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
expect(spy.notCalled).true;
|
||||
await apolloFetch({ query: '{hello}' });
|
||||
expect(spy.calledOnce).true;
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
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 server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
context: () => {
|
||||
throw new AuthenticationError('valid result');
|
||||
},
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.data).not.to.exist;
|
||||
|
||||
const e = result.errors[0];
|
||||
expect(e.message).to.contain('valid result');
|
||||
expect(e.extensions).to.exist;
|
||||
expect(e.extensions.code).to.equal('UNAUTHENTICATED');
|
||||
expect(e.extensions.exception.stacktrace).to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('propogates error codes in production', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const server = new ApolloServerBase({
|
||||
typeDefs: gql`
|
||||
type Query {
|
||||
error: String
|
||||
}
|
||||
`,
|
||||
resolvers: {
|
||||
Query: {
|
||||
error: () => {
|
||||
throw new AuthenticationError('we the best music');
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: `{error}` });
|
||||
expect(result.data).to.exist;
|
||||
expect(result.data).to.deep.equal({ error: null });
|
||||
|
||||
expect(result.errors, 'errors should exist').to.exist;
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.errors[0].extensions.code).to.equal('UNAUTHENTICATED');
|
||||
expect(result.errors[0].extensions.exception).not.to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('propogates error codes with null response in production', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const server = new ApolloServerBase({
|
||||
typeDefs: gql`
|
||||
type Query {
|
||||
error: String!
|
||||
}
|
||||
`,
|
||||
resolvers: {
|
||||
Query: {
|
||||
error: () => {
|
||||
throw new AuthenticationError('we the best music');
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
const { url: uri } = await server.listen();
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: `{error}` });
|
||||
expect(result.data).null;
|
||||
|
||||
expect(result.errors, 'errors should exist').to.exist;
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.errors[0].extensions.code).to.equal('UNAUTHENTICATED');
|
||||
expect(result.errors[0].extensions.exception).not.to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
await server.stop();
|
||||
});
|
||||
});
|
||||
|
||||
describe('subscriptions', () => {
|
||||
const SOMETHING_CHANGED_TOPIC = 'something_changed';
|
||||
const pubsub = new PubSub();
|
||||
let server: ApolloServerBase;
|
||||
let subscription;
|
||||
|
||||
function createEvent(num) {
|
||||
return setTimeout(
|
||||
() =>
|
||||
pubsub.publish(SOMETHING_CHANGED_TOPIC, {
|
||||
num,
|
||||
}),
|
||||
num + 10,
|
||||
);
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
if (server) {
|
||||
try {
|
||||
await server.stop();
|
||||
} catch (e) {}
|
||||
server = null;
|
||||
}
|
||||
if (subscription) {
|
||||
try {
|
||||
await subscription.unsubscribe();
|
||||
} catch (e) {}
|
||||
subscription = null;
|
||||
}
|
||||
});
|
||||
|
||||
it('enables subscriptions by default', done => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hi: String
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
num: Int
|
||||
}
|
||||
`;
|
||||
|
||||
const query = `
|
||||
subscription {
|
||||
num
|
||||
}
|
||||
`;
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
hi: () => 'here to placate graphql-js',
|
||||
},
|
||||
Subscription: {
|
||||
num: {
|
||||
subscribe: () => {
|
||||
createEvent(1);
|
||||
createEvent(2);
|
||||
createEvent(3);
|
||||
return pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
server.listen({}).then(({ port }) => {
|
||||
const client = new SubscriptionClient(
|
||||
`ws://localhost:${port}${server.subscriptionsPath}`,
|
||||
{},
|
||||
WebSocket,
|
||||
);
|
||||
|
||||
const observable = client.request({ query });
|
||||
|
||||
let i = 1;
|
||||
subscription = observable.subscribe({
|
||||
next: ({ data }) => {
|
||||
try {
|
||||
expect(data.num).to.equal(i);
|
||||
if (i === 3) {
|
||||
done();
|
||||
}
|
||||
i++;
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
},
|
||||
error: done,
|
||||
complete: () => {
|
||||
done(new Error('should not complete'));
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
it('disables subscritpions when option set to false', done => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
"graphql-js forces there to be a query type"
|
||||
hi: String
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
num: Int
|
||||
}
|
||||
`;
|
||||
|
||||
const query = `
|
||||
subscription {
|
||||
num
|
||||
}
|
||||
`;
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
hi: () => 'here to placate graphql-js',
|
||||
},
|
||||
Subscription: {
|
||||
num: {
|
||||
subscribe: () => {
|
||||
createEvent(1);
|
||||
return pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
server
|
||||
.listen({
|
||||
subscriptions: false,
|
||||
})
|
||||
.then(({ port }) => {
|
||||
const client = new SubscriptionClient(
|
||||
`ws://localhost:${port}${server.subscriptionsPath}`,
|
||||
{},
|
||||
WebSocket,
|
||||
);
|
||||
|
||||
const observable = client.request({ query });
|
||||
|
||||
subscription = observable.subscribe({
|
||||
next: () => {
|
||||
done(new Error('should not call next'));
|
||||
},
|
||||
error: () => {
|
||||
done(new Error('should not notify of error'));
|
||||
},
|
||||
complete: () => {
|
||||
done(new Error('should not complete'));
|
||||
},
|
||||
});
|
||||
|
||||
//Unfortunately the error connection is not propagated to the
|
||||
//observable. What should happen is we provide a default onError
|
||||
//function that notifies the returned observable and can cursomize
|
||||
//the behavior with an option in the client constructor. If you're
|
||||
//available to make a PR to the following please do!
|
||||
//https://github.com/apollographql/subscriptions-transport-ws/blob/master/src/client.ts
|
||||
client.onError((_: Error) => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
it('accepts subscriptions configuration', done => {
|
||||
const onConnect = stub().callsFake(connectionParams => ({
|
||||
...connectionParams,
|
||||
}));
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hi: String
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
num: Int
|
||||
}
|
||||
`;
|
||||
|
||||
const query = `
|
||||
subscription {
|
||||
num
|
||||
}
|
||||
`;
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
hi: () => 'here to placate graphql-js',
|
||||
},
|
||||
Subscription: {
|
||||
num: {
|
||||
subscribe: () => {
|
||||
createEvent(1);
|
||||
createEvent(2);
|
||||
createEvent(3);
|
||||
return pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
server = new ApolloServerBase({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
});
|
||||
const httpServer = createHttpServer(server);
|
||||
const path = '/sub';
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
server
|
||||
.listen({
|
||||
subscriptions: { onConnect, path },
|
||||
})
|
||||
.then(({ port }) => {
|
||||
expect(onConnect.notCalled).true;
|
||||
|
||||
expect(server.subscriptionsPath).to.equal(path);
|
||||
const client = new SubscriptionClient(
|
||||
`ws://localhost:${port}${server.subscriptionsPath}`,
|
||||
{},
|
||||
WebSocket,
|
||||
);
|
||||
|
||||
const observable = client.request({ query });
|
||||
|
||||
let i = 1;
|
||||
subscription = observable.subscribe({
|
||||
next: ({ data }) => {
|
||||
try {
|
||||
expect(onConnect.calledOnce).true;
|
||||
expect(data.num).to.equal(i);
|
||||
if (i === 3) {
|
||||
done();
|
||||
}
|
||||
i++;
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
},
|
||||
error: done,
|
||||
complete: () => {
|
||||
done(new Error('should not complete'));
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
describe('Persisted Queries', () => {
|
||||
let server;
|
||||
const query = gql`
|
||||
${TEST_STRING_QUERY}
|
||||
`;
|
||||
const hash = sha256
|
||||
.create()
|
||||
.update(TEST_STRING_QUERY)
|
||||
.hex();
|
||||
const extensions = {
|
||||
persistedQuery: {
|
||||
version: VERSION,
|
||||
sha256Hash: hash,
|
||||
},
|
||||
};
|
||||
let uri: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
server = new ApolloServerBase({
|
||||
schema,
|
||||
introspection: false,
|
||||
persistedQueries: {
|
||||
cache: new Map<string, string>() as any,
|
||||
},
|
||||
});
|
||||
|
||||
const httpServer = createHttpServer(server);
|
||||
|
||||
server.use({
|
||||
getHttp: () => httpServer,
|
||||
path: '/graphql',
|
||||
});
|
||||
uri = (await server.listen()).url;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('returns PersistedQueryNotFound on the first try', async () => {
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({
|
||||
extensions,
|
||||
} as any);
|
||||
|
||||
expect(result.data).not.to.exist;
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.errors[0].message).to.equal('PersistedQueryNotFound');
|
||||
expect(result.errors[0].extensions.code).to.equal(
|
||||
'PERSISTED_QUERY_NOT_FOUND',
|
||||
);
|
||||
});
|
||||
it('returns result on the second try', async () => {
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
await apolloFetch({
|
||||
extensions,
|
||||
} as any);
|
||||
const result = await apolloFetch({
|
||||
extensions,
|
||||
query: TEST_STRING_QUERY,
|
||||
} as any);
|
||||
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
expect(result.errors).not.to.exist;
|
||||
});
|
||||
|
||||
it('returns result on the persisted query', async () => {
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
await apolloFetch({
|
||||
extensions,
|
||||
} as any);
|
||||
await apolloFetch({
|
||||
extensions,
|
||||
query: TEST_STRING_QUERY,
|
||||
} as any);
|
||||
const result = await apolloFetch({
|
||||
extensions,
|
||||
} as any);
|
||||
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
expect(result.errors).not.to.exist;
|
||||
});
|
||||
|
||||
it('returns error when hash does not match', async () => {
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
try {
|
||||
await apolloFetch({
|
||||
extensions: {
|
||||
persistedQuery: {
|
||||
version: VERSION,
|
||||
sha:
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
},
|
||||
},
|
||||
query: TEST_STRING_QUERY,
|
||||
} as any);
|
||||
expect.fail();
|
||||
} catch (e) {
|
||||
expect(e.response.status).to.equal(400);
|
||||
expect(e.response.raw).to.match(/does not match query/);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns correct result for persisted query link', done => {
|
||||
const variables = { id: 1 };
|
||||
const link = createPersistedQuery().concat(
|
||||
createHttpLink({ uri, fetch } as any),
|
||||
);
|
||||
|
||||
execute(link, { query, variables } as any).subscribe(result => {
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('returns correct result for persisted query link using get request', done => {
|
||||
const variables = { id: 1 };
|
||||
const link = createPersistedQuery({
|
||||
useGETForHashedQueries: true,
|
||||
}).concat(createHttpLink({ uri, fetch } as any));
|
||||
|
||||
execute(link, { query, variables } as any).subscribe(result => {
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -2,6 +2,9 @@ import { expect } from 'chai';
|
|||
import 'mocha';
|
||||
import express from 'express';
|
||||
|
||||
import net from 'net';
|
||||
import http from 'http';
|
||||
|
||||
import request from 'request';
|
||||
import FormData from 'form-data';
|
||||
import fs from 'fs';
|
||||
|
@ -9,7 +12,12 @@ import fetch from 'node-fetch';
|
|||
import { createApolloFetch } from 'apollo-fetch';
|
||||
|
||||
import { ApolloServerBase, AuthenticationError } from 'apollo-server-core';
|
||||
import { registerServer } from './ApolloServer';
|
||||
import { registerServer, ApolloServer } from './ApolloServer';
|
||||
|
||||
import {
|
||||
testApolloServer,
|
||||
createServerInfo,
|
||||
} from 'apollo-server-integration-testsuite';
|
||||
|
||||
//to remove the circular dependency, we reference it directly
|
||||
const gql = require('../../apollo-server/dist/index').gql;
|
||||
|
@ -26,22 +34,43 @@ const resolvers = {
|
|||
},
|
||||
};
|
||||
|
||||
const url = 'http://localhost:4000/graphql';
|
||||
const uri = url;
|
||||
|
||||
describe('apollo-server-express', () => {
|
||||
let server;
|
||||
let httpServer;
|
||||
testApolloServer(
|
||||
async options => {
|
||||
server = new ApolloServer(options);
|
||||
const app = express();
|
||||
registerServer({ app, server });
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const s = app.listen({ port: 4000 }, () => resolve(s));
|
||||
});
|
||||
return createServerInfo(server, httpServer);
|
||||
},
|
||||
async () => {
|
||||
if (server) await server.stop();
|
||||
if (httpServer && httpServer.listening) await httpServer.close();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('apollo-server-express', () => {
|
||||
//to remove the circular dependency, we reference it directly
|
||||
const ApolloServer = require('../../apollo-server/dist/index').ApolloServer;
|
||||
let server: ApolloServerBase & {
|
||||
createGraphQLServerOptions: (
|
||||
req: express.Request,
|
||||
res: express.Response,
|
||||
) => any;
|
||||
};
|
||||
let server: ApolloServerBase | any;
|
||||
|
||||
let app: express.Application;
|
||||
let httpServer: http.Server;
|
||||
|
||||
afterEach(async () => {
|
||||
if (server) await server.stop();
|
||||
if (httpServer) await httpServer.close();
|
||||
});
|
||||
|
||||
describe('', () => {
|
||||
describe('constructor', () => {
|
||||
it('accepts typeDefs and resolvers', () => {
|
||||
const app = express();
|
||||
const server = new ApolloServer({ typeDefs, resolvers });
|
||||
|
@ -65,7 +94,9 @@ describe('apollo-server-express', () => {
|
|||
|
||||
registerServer({ app, server });
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
|
||||
|
@ -96,7 +127,9 @@ describe('apollo-server-express', () => {
|
|||
|
||||
registerServer({ app, server, gui: true });
|
||||
|
||||
const { url } = await server.listen();
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const apolloFetch = createApolloFetch({ uri: url });
|
||||
const result = await apolloFetch({ query: INTROSPECTION_QUERY });
|
||||
|
||||
|
@ -105,7 +138,7 @@ describe('apollo-server-express', () => {
|
|||
'GRAPHQL_VALIDATION_FAILED',
|
||||
);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<http.Server>((resolve, reject) => {
|
||||
request(
|
||||
{
|
||||
url,
|
||||
|
@ -140,8 +173,10 @@ describe('apollo-server-express', () => {
|
|||
|
||||
registerServer({ app, server });
|
||||
|
||||
const { url } = await server.listen();
|
||||
return new Promise((resolve, reject) => {
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
return new Promise<http.Server>((resolve, reject) => {
|
||||
request(
|
||||
{
|
||||
url,
|
||||
|
@ -174,7 +209,9 @@ describe('apollo-server-express', () => {
|
|||
|
||||
registerServer({ app, server, cors: { origin: 'apollographql.com' } });
|
||||
|
||||
const { url: uri } = await server.listen({});
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri }).useAfter(
|
||||
(response, next) => {
|
||||
|
@ -196,7 +233,9 @@ describe('apollo-server-express', () => {
|
|||
|
||||
registerServer({ app, server, bodyParserConfig: { limit: 0 } });
|
||||
|
||||
const { url: uri } = await server.listen({});
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
|
@ -226,7 +265,10 @@ describe('apollo-server-express', () => {
|
|||
|
||||
registerServer({ app, server, bodyParserConfig: { limit: 0 } });
|
||||
|
||||
const { port } = await server.listen();
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const { port } = httpServer.address() as net.AddressInfo;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
request(
|
||||
|
@ -262,7 +304,10 @@ describe('apollo-server-express', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const { port } = await server.listen({});
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const { port } = httpServer.address() as net.AddressInfo;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
request(
|
||||
|
@ -295,7 +340,10 @@ describe('apollo-server-express', () => {
|
|||
disableHealthCheck: true,
|
||||
});
|
||||
|
||||
const { port } = await server.listen({});
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const { port } = httpServer.address() as net.AddressInfo;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
request(
|
||||
|
@ -351,7 +399,10 @@ describe('apollo-server-express', () => {
|
|||
server,
|
||||
});
|
||||
|
||||
const { port } = await server.listen({});
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const { port } = httpServer.address() as net.AddressInfo;
|
||||
|
||||
const body = new FormData();
|
||||
|
||||
|
@ -423,7 +474,9 @@ describe('apollo-server-express', () => {
|
|||
app = express();
|
||||
registerServer({ app, server });
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
|
@ -461,7 +514,9 @@ describe('apollo-server-express', () => {
|
|||
app = express();
|
||||
registerServer({ app, server });
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: `{error}` });
|
||||
|
@ -499,7 +554,9 @@ describe('apollo-server-express', () => {
|
|||
app = express();
|
||||
registerServer({ app, server });
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: `{error}` });
|
||||
|
@ -536,7 +593,9 @@ describe('apollo-server-express', () => {
|
|||
app = express();
|
||||
registerServer({ app, server });
|
||||
|
||||
const { url: uri } = await server.listen();
|
||||
httpServer = await new Promise<http.Server>(resolve => {
|
||||
const l = app.listen({ port: 4000 }, () => resolve(l));
|
||||
});
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: `{error}` });
|
||||
|
|
28
packages/apollo-server-hapi/src/ApolloServer.test.ts
Normal file
28
packages/apollo-server-hapi/src/ApolloServer.test.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { Server } from 'hapi';
|
||||
import {
|
||||
testApolloServer,
|
||||
createServerInfo,
|
||||
} from 'apollo-server-integration-testsuite';
|
||||
|
||||
import { registerServer, ApolloServer } from './ApolloServer';
|
||||
|
||||
describe('apollo-server-hapi', () => {
|
||||
let server;
|
||||
let app;
|
||||
let httpServer;
|
||||
testApolloServer(
|
||||
async options => {
|
||||
server = new ApolloServer(options);
|
||||
app = new Server({ host: 'localhost', port: 4000 });
|
||||
registerServer({ app, server });
|
||||
await app.start();
|
||||
const httpServer = app.listener;
|
||||
return createServerInfo(server, httpServer);
|
||||
},
|
||||
async () => {
|
||||
if (server) await server.stop();
|
||||
if (app) await app.stop();
|
||||
if (httpServer && httpServer.listening) await httpServer.close();
|
||||
},
|
||||
);
|
||||
});
|
|
@ -31,8 +31,14 @@
|
|||
"definition": "dist/index.d.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"apollo-link-persisted-queries": "^0.2.0",
|
||||
"apollo-fetch": "^0.7.0",
|
||||
"apollo-link": "^1.2.2",
|
||||
"apollo-link-http": "^1.5.4",
|
||||
"apollo-link-persisted-queries": "^0.2.1",
|
||||
"graphql-subscriptions": "^0.5.8",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"js-sha256": "^0.9.0"
|
||||
"js-sha256": "^0.9.0",
|
||||
"subscriptions-transport-ws": "^0.9.11",
|
||||
"ws": "^5.2.0"
|
||||
}
|
||||
}
|
||||
|
|
846
packages/apollo-server-integration-testsuite/src/ApolloServer.ts
Normal file
846
packages/apollo-server-integration-testsuite/src/ApolloServer.ts
Normal file
|
@ -0,0 +1,846 @@
|
|||
/* tslint:disable:no-unused-expression */
|
||||
import { expect } from 'chai';
|
||||
import { stub } from 'sinon';
|
||||
import http from 'http';
|
||||
import net from 'net';
|
||||
import 'mocha';
|
||||
import { sha256 } from 'js-sha256';
|
||||
|
||||
import {
|
||||
GraphQLSchema,
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
GraphQLError,
|
||||
ValidationContext,
|
||||
FieldDefinitionNode,
|
||||
} from 'graphql';
|
||||
|
||||
import { PubSub } from 'graphql-subscriptions';
|
||||
import { SubscriptionClient } from 'subscriptions-transport-ws';
|
||||
import WebSocket from 'ws';
|
||||
|
||||
import { execute } from 'apollo-link';
|
||||
import { createHttpLink } from 'apollo-link-http';
|
||||
import {
|
||||
createPersistedQueryLink as createPersistedQuery,
|
||||
VERSION,
|
||||
} from 'apollo-link-persisted-queries';
|
||||
|
||||
import { createApolloFetch } from 'apollo-fetch';
|
||||
import {
|
||||
AuthenticationError,
|
||||
gql,
|
||||
Config,
|
||||
ApolloServerBase,
|
||||
} from 'apollo-server-core';
|
||||
|
||||
export function createServerInfo<AS extends ApolloServerBase>(
|
||||
server: AS,
|
||||
httpServer: http.Server,
|
||||
): ServerInfo<AS> {
|
||||
const serverInfo: any = {
|
||||
...(httpServer.address() as net.AddressInfo),
|
||||
server,
|
||||
httpServer,
|
||||
};
|
||||
|
||||
// Convert IPs which mean "any address" (IPv4 or IPv6) into localhost
|
||||
// corresponding loopback ip. Note that the url field we're setting is
|
||||
// primarily for consumption by our test suite. If this heuristic is
|
||||
// wrong for your use case, explicitly specify a frontend host (in the
|
||||
// `frontends.host` field in your engine config, or in the `host`
|
||||
// option to ApolloServer.listen).
|
||||
let hostForUrl = serverInfo.address;
|
||||
if (serverInfo.address === '' || serverInfo.address === '::')
|
||||
hostForUrl = 'localhost';
|
||||
|
||||
serverInfo.url = require('url').format({
|
||||
protocol: 'http',
|
||||
hostname: hostForUrl,
|
||||
port: serverInfo.port,
|
||||
pathname: server.graphqlPath,
|
||||
});
|
||||
|
||||
return serverInfo;
|
||||
}
|
||||
|
||||
const INTROSPECTION_QUERY = `
|
||||
{
|
||||
__schema {
|
||||
directives {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const TEST_STRING_QUERY = `
|
||||
{
|
||||
testString
|
||||
}
|
||||
`;
|
||||
|
||||
const queryType = new GraphQLObjectType({
|
||||
name: 'QueryType',
|
||||
fields: {
|
||||
testString: {
|
||||
type: GraphQLString,
|
||||
resolve() {
|
||||
return 'test string';
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const schema = new GraphQLSchema({
|
||||
query: queryType,
|
||||
});
|
||||
|
||||
export interface ServerInfo<AS extends ApolloServerBase> {
|
||||
address: string;
|
||||
family: string;
|
||||
url: string;
|
||||
port: number | string;
|
||||
server: AS;
|
||||
httpServer: http.Server;
|
||||
}
|
||||
|
||||
export interface CreateServerFunc<AS extends ApolloServerBase> {
|
||||
(config: Config): Promise<ServerInfo<AS>>;
|
||||
}
|
||||
|
||||
export interface StopServerFunc {
|
||||
(): Promise<void>;
|
||||
}
|
||||
|
||||
export function testApolloServer<AS extends ApolloServerBase>(
|
||||
createApolloServer: CreateServerFunc<AS>,
|
||||
stopServer: StopServerFunc,
|
||||
) {
|
||||
describe('ApolloServer', () => {
|
||||
afterEach(stopServer);
|
||||
|
||||
describe('constructor', () => {
|
||||
describe('validation rules', () => {
|
||||
it('accepts additional rules', async () => {
|
||||
const NoTestString = (context: ValidationContext) => ({
|
||||
Field(node: FieldDefinitionNode) {
|
||||
if (node.name.value === 'testString') {
|
||||
context.reportError(
|
||||
new GraphQLError('Not allowed to use', [node]),
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const { url: uri } = await createApolloServer({
|
||||
schema,
|
||||
validationRules: [NoTestString],
|
||||
introspection: false,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const introspectionResult = await apolloFetch({
|
||||
query: INTROSPECTION_QUERY,
|
||||
});
|
||||
expect(introspectionResult.data, 'data should not exist').not.to
|
||||
.exist;
|
||||
expect(introspectionResult.errors, 'errors should exist').to.exist;
|
||||
|
||||
const result = await apolloFetch({ query: TEST_STRING_QUERY });
|
||||
expect(result.data, 'data should not exist').not.to.exist;
|
||||
expect(result.errors, 'errors should exist').to.exist;
|
||||
});
|
||||
|
||||
it('allows introspection by default', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
delete process.env.NODE_ENV;
|
||||
|
||||
const { url: uri } = await createApolloServer({
|
||||
schema,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: INTROSPECTION_QUERY });
|
||||
expect(result.data, 'data should not exist').to.exist;
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
});
|
||||
|
||||
it('prevents introspection by default during production', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const { url: uri } = await createApolloServer({
|
||||
schema,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: INTROSPECTION_QUERY });
|
||||
expect(result.data, 'data should not exist').not.to.exist;
|
||||
expect(result.errors, 'errors should exist').to.exist;
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.errors[0].extensions.code).to.equal(
|
||||
'GRAPHQL_VALIDATION_FAILED',
|
||||
);
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
});
|
||||
|
||||
it('allows introspection to be enabled explicitly', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const { url: uri } = await createApolloServer({
|
||||
schema,
|
||||
introspection: true,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: INTROSPECTION_QUERY });
|
||||
expect(result.data, 'data should not exist').to.exist;
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
});
|
||||
});
|
||||
|
||||
describe('schema creation', () => {
|
||||
it('accepts typeDefs and resolvers', async () => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const resolvers = { Query: { hello: () => 'hi' } };
|
||||
const { url: uri } = await createApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
|
||||
expect(result.data).to.deep.equal({ hello: 'hi' });
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
});
|
||||
it('throws if typeDefs are a string', done => {
|
||||
const typeDefs: any = `
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const resolvers = { Query: { hello: () => 'hi' } };
|
||||
|
||||
createApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
})
|
||||
.then(expect.fail)
|
||||
.catch(e => expect(e.message).to.match(/apollo-server/))
|
||||
.then(() => done());
|
||||
});
|
||||
it('uses schema over resolvers + typeDefs', async () => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const resolvers = { Query: { hello: () => 'hi' } };
|
||||
const { url: uri } = await createApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
schema,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const typeDefResult = await apolloFetch({ query: '{hello}' });
|
||||
|
||||
expect(typeDefResult.data, 'data should not exist').not.to.exist;
|
||||
expect(typeDefResult.errors, 'errors should exist').to.exist;
|
||||
|
||||
const result = await apolloFetch({ query: '{testString}' });
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
});
|
||||
it('allows mocks as boolean', async () => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const { url: uri } = await createApolloServer({
|
||||
typeDefs,
|
||||
mocks: true,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
expect(result.data).to.deep.equal({ hello: 'Hello World' });
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
});
|
||||
|
||||
it('allows mocks as an object', async () => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const { url: uri } = await createApolloServer({
|
||||
typeDefs,
|
||||
mocks: { String: () => 'mock city' },
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
const result = await apolloFetch({ query: '{hello}' });
|
||||
|
||||
expect(result.data).to.deep.equal({ hello: 'mock city' });
|
||||
expect(result.errors, 'errors should exist').not.to.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('lifecycle', () => {
|
||||
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).to.equal(Promise.resolve(uniqueContext));
|
||||
return 'hi';
|
||||
},
|
||||
},
|
||||
};
|
||||
const spy = stub().returns({});
|
||||
const { url: uri } = await createApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
context: spy,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
expect(spy.notCalled).true;
|
||||
|
||||
await apolloFetch({ query: '{hello}' });
|
||||
expect(spy.calledOnce).true;
|
||||
await apolloFetch({ query: '{hello}' });
|
||||
expect(spy.calledTwice).true;
|
||||
});
|
||||
|
||||
it('allows context to be async function', async () => {
|
||||
const uniqueContext = { key: 'major' };
|
||||
const spy = stub().returns('hi');
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
`;
|
||||
const resolvers = {
|
||||
Query: {
|
||||
hello: (_parent, _args, context) => {
|
||||
expect(context).to.equal(uniqueContext);
|
||||
return spy();
|
||||
},
|
||||
},
|
||||
};
|
||||
const { url: uri } = await createApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
context: async () => uniqueContext,
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
expect(spy.notCalled).true;
|
||||
await apolloFetch({ query: '{hello}' });
|
||||
expect(spy.calledOnce).true;
|
||||
});
|
||||
|
||||
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).to.equal(1);
|
||||
expect(result.data).not.to.exist;
|
||||
|
||||
const e = result.errors[0];
|
||||
expect(e.message).to.contain('valid result');
|
||||
expect(e.extensions).to.exist;
|
||||
expect(e.extensions.code).to.equal('UNAUTHENTICATED');
|
||||
expect(e.extensions.exception.stacktrace).to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
});
|
||||
|
||||
it('propogates error codes in production', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const { url: uri } = await createApolloServer({
|
||||
typeDefs: gql`
|
||||
type Query {
|
||||
error: String
|
||||
}
|
||||
`,
|
||||
resolvers: {
|
||||
Query: {
|
||||
error: () => {
|
||||
throw new AuthenticationError('we the best music');
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: `{error}` });
|
||||
expect(result.data).to.exist;
|
||||
expect(result.data).to.deep.equal({ error: null });
|
||||
|
||||
expect(result.errors, 'errors should exist').to.exist;
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.errors[0].extensions.code).to.equal('UNAUTHENTICATED');
|
||||
expect(result.errors[0].extensions.exception).not.to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
});
|
||||
|
||||
it('propogates error codes with null response in production', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const { url: uri } = await createApolloServer({
|
||||
typeDefs: gql`
|
||||
type Query {
|
||||
error: String!
|
||||
}
|
||||
`,
|
||||
resolvers: {
|
||||
Query: {
|
||||
error: () => {
|
||||
throw new AuthenticationError('we the best music');
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({ query: `{error}` });
|
||||
expect(result.data).null;
|
||||
|
||||
expect(result.errors, 'errors should exist').to.exist;
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.errors[0].extensions.code).to.equal('UNAUTHENTICATED');
|
||||
expect(result.errors[0].extensions.exception).not.to.exist;
|
||||
|
||||
process.env.NODE_ENV = nodeEnv;
|
||||
});
|
||||
});
|
||||
|
||||
describe('subscriptions', () => {
|
||||
const SOMETHING_CHANGED_TOPIC = 'something_changed';
|
||||
const pubsub = new PubSub();
|
||||
let subscription;
|
||||
|
||||
function createEvent(num) {
|
||||
return setTimeout(
|
||||
() =>
|
||||
pubsub.publish(SOMETHING_CHANGED_TOPIC, {
|
||||
num,
|
||||
}),
|
||||
num + 10,
|
||||
);
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
if (subscription) {
|
||||
try {
|
||||
await subscription.unsubscribe();
|
||||
} catch (e) {}
|
||||
subscription = null;
|
||||
}
|
||||
});
|
||||
|
||||
it('enables subscriptions after creating subscriptions server', done => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hi: String
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
num: Int
|
||||
}
|
||||
`;
|
||||
|
||||
const query = `
|
||||
subscription {
|
||||
num
|
||||
}
|
||||
`;
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
hi: () => 'here to placate graphql-js',
|
||||
},
|
||||
Subscription: {
|
||||
num: {
|
||||
subscribe: () => {
|
||||
createEvent(1);
|
||||
createEvent(2);
|
||||
createEvent(3);
|
||||
return pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
createApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
}).then(({ port, server, httpServer }) => {
|
||||
server.createSubscriptionServer(httpServer);
|
||||
|
||||
const client = new SubscriptionClient(
|
||||
`ws://localhost:${port}${server.subscriptionsPath}`,
|
||||
{},
|
||||
WebSocket,
|
||||
);
|
||||
|
||||
const observable = client.request({ query });
|
||||
|
||||
let i = 1;
|
||||
subscription = observable.subscribe({
|
||||
next: ({ data }) => {
|
||||
try {
|
||||
expect(data.num).to.equal(i);
|
||||
if (i === 3) {
|
||||
done();
|
||||
}
|
||||
i++;
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
},
|
||||
error: done,
|
||||
complete: () => {
|
||||
done(new Error('should not complete'));
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
it('disables subscritpions when option set to false', done => {
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
"graphql-js forces there to be a query type"
|
||||
hi: String
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
num: Int
|
||||
}
|
||||
`;
|
||||
|
||||
const query = `
|
||||
subscription {
|
||||
num
|
||||
}
|
||||
`;
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
hi: () => 'here to placate graphql-js',
|
||||
},
|
||||
Subscription: {
|
||||
num: {
|
||||
subscribe: () => {
|
||||
createEvent(1);
|
||||
return pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
createApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
subscriptions: false,
|
||||
}).then(({ port, server, httpServer }) => {
|
||||
try {
|
||||
server.createSubscriptionServer(httpServer);
|
||||
expect.fail();
|
||||
} catch (e) {
|
||||
expect(e.message).to.match(/disabled/);
|
||||
}
|
||||
|
||||
const client = new SubscriptionClient(
|
||||
`ws://localhost:${port}${server.subscriptionsPath}`,
|
||||
{},
|
||||
WebSocket,
|
||||
);
|
||||
|
||||
const observable = client.request({ query });
|
||||
|
||||
subscription = observable.subscribe({
|
||||
next: () => {
|
||||
done(new Error('should not call next'));
|
||||
},
|
||||
error: () => {
|
||||
done(new Error('should not notify of error'));
|
||||
},
|
||||
complete: () => {
|
||||
done(new Error('should not complete'));
|
||||
},
|
||||
});
|
||||
|
||||
//Unfortunately the error connection is not propagated to the
|
||||
//observable. What should happen is we provide a default onError
|
||||
//function that notifies the returned observable and can cursomize
|
||||
//the behavior with an option in the client constructor. If you're
|
||||
//available to make a PR to the following please do!
|
||||
//https://github.com/apollographql/subscriptions-transport-ws/blob/master/src/client.ts
|
||||
client.onError((_: Error) => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
it('accepts subscriptions configuration', done => {
|
||||
const onConnect = stub().callsFake(connectionParams => ({
|
||||
...connectionParams,
|
||||
}));
|
||||
const typeDefs = gql`
|
||||
type Query {
|
||||
hi: String
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
num: Int
|
||||
}
|
||||
`;
|
||||
|
||||
const query = `
|
||||
subscription {
|
||||
num
|
||||
}
|
||||
`;
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
hi: () => 'here to placate graphql-js',
|
||||
},
|
||||
Subscription: {
|
||||
num: {
|
||||
subscribe: () => {
|
||||
createEvent(1);
|
||||
createEvent(2);
|
||||
createEvent(3);
|
||||
return pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const path = '/sub';
|
||||
createApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
subscriptions: { onConnect, path },
|
||||
})
|
||||
.then(({ port, server, httpServer }) => {
|
||||
server.createSubscriptionServer(httpServer);
|
||||
expect(onConnect.notCalled).true;
|
||||
|
||||
expect(server.subscriptionsPath).to.equal(path);
|
||||
const client = new SubscriptionClient(
|
||||
`ws://localhost:${port}${server.subscriptionsPath}`,
|
||||
{},
|
||||
WebSocket,
|
||||
);
|
||||
|
||||
const observable = client.request({ query });
|
||||
|
||||
let i = 1;
|
||||
subscription = observable.subscribe({
|
||||
next: ({ data }) => {
|
||||
try {
|
||||
expect(onConnect.calledOnce).true;
|
||||
expect(data.num).to.equal(i);
|
||||
if (i === 3) {
|
||||
done();
|
||||
}
|
||||
i++;
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
},
|
||||
error: done,
|
||||
complete: () => {
|
||||
done(new Error('should not complete'));
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Persisted Queries', () => {
|
||||
let uri: string;
|
||||
const query = gql`
|
||||
${TEST_STRING_QUERY}
|
||||
`;
|
||||
const hash = sha256
|
||||
.create()
|
||||
.update(TEST_STRING_QUERY)
|
||||
.hex();
|
||||
const extensions = {
|
||||
persistedQuery: {
|
||||
version: VERSION,
|
||||
sha256Hash: hash,
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
const serverInfo = await createApolloServer({
|
||||
schema,
|
||||
introspection: false,
|
||||
persistedQueries: {
|
||||
cache: new Map<string, string>() as any,
|
||||
},
|
||||
});
|
||||
uri = serverInfo.url;
|
||||
});
|
||||
|
||||
it('returns PersistedQueryNotFound on the first try', async () => {
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
const result = await apolloFetch({
|
||||
extensions,
|
||||
} as any);
|
||||
|
||||
expect(result.data).not.to.exist;
|
||||
expect(result.errors.length).to.equal(1);
|
||||
expect(result.errors[0].message).to.equal('PersistedQueryNotFound');
|
||||
expect(result.errors[0].extensions.code).to.equal(
|
||||
'PERSISTED_QUERY_NOT_FOUND',
|
||||
);
|
||||
});
|
||||
it('returns result on the second try', async () => {
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
await apolloFetch({
|
||||
extensions,
|
||||
} as any);
|
||||
const result = await apolloFetch({
|
||||
extensions,
|
||||
query: TEST_STRING_QUERY,
|
||||
} as any);
|
||||
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
expect(result.errors).not.to.exist;
|
||||
});
|
||||
|
||||
it('returns result on the persisted query', async () => {
|
||||
const apolloFetch = createApolloFetch({ uri });
|
||||
|
||||
await apolloFetch({
|
||||
extensions,
|
||||
} as any);
|
||||
await apolloFetch({
|
||||
extensions,
|
||||
query: TEST_STRING_QUERY,
|
||||
} as any);
|
||||
const result = await apolloFetch({
|
||||
extensions,
|
||||
} as any);
|
||||
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
expect(result.errors).not.to.exist;
|
||||
});
|
||||
|
||||
//Apollo Fetch's result depends on the server implementation, if the
|
||||
//statusText of the error is unparsable, then we'll fall into the catch,
|
||||
//such as with express. If it is parsable, then we'll use the afterware
|
||||
it('returns error when hash does not match', async () => {
|
||||
const apolloFetch = createApolloFetch({ uri }).useAfter((res, next) => {
|
||||
expect(res.response.status).to.equal(400);
|
||||
expect(res.response.raw).to.match(/does not match query/);
|
||||
next();
|
||||
});
|
||||
|
||||
try {
|
||||
await apolloFetch({
|
||||
extensions: {
|
||||
persistedQuery: {
|
||||
version: VERSION,
|
||||
sha:
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
},
|
||||
},
|
||||
query: TEST_STRING_QUERY,
|
||||
} as any);
|
||||
} catch (e) {
|
||||
expect(e.response).to.exist;
|
||||
expect(e.response.status).to.equal(400);
|
||||
expect(e.response.raw).to.match(/does not match query/);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns correct result for persisted query link', done => {
|
||||
const variables = { id: 1 };
|
||||
const link = createPersistedQuery().concat(
|
||||
createHttpLink({ uri, fetch } as any),
|
||||
);
|
||||
|
||||
execute(link, { query, variables } as any).subscribe(result => {
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('returns correct result for persisted query link using get request', done => {
|
||||
const variables = { id: 1 };
|
||||
const link = createPersistedQuery({
|
||||
useGETForHashedQueries: true,
|
||||
}).concat(createHttpLink({ uri, fetch } as any));
|
||||
|
||||
execute(link, { query, variables } as any).subscribe(result => {
|
||||
expect(result.data).to.deep.equal({ testString: 'test string' });
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -24,6 +24,8 @@ import { GraphQLOptions, Config } from 'apollo-server-core';
|
|||
import { OperationStore } from 'apollo-server-module-operation-store';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export * from './ApolloServer';
|
||||
|
||||
const personType = new GraphQLObjectType({
|
||||
name: 'PersonType',
|
||||
fields: {
|
||||
|
|
|
@ -89,7 +89,7 @@ describe('apollo-server', () => {
|
|||
resolvers,
|
||||
});
|
||||
|
||||
const { url: uri } = await server.listen({});
|
||||
const { url: uri } = await server.listen();
|
||||
|
||||
const apolloFetch = createApolloFetch({ uri }).useAfter(
|
||||
(response, next) => {
|
||||
|
|
|
@ -12,22 +12,20 @@ process.on('unhandledRejection', reason => {
|
|||
require('../packages/apollo-server-core/dist/runQuery.test.js');
|
||||
require('../packages/apollo-server-core/dist/runHttpQuery.test.js');
|
||||
require('../packages/apollo-server-core/dist/errors.test.js');
|
||||
require('../packages/apollo-server-core/dist/ApolloServer.test.js');
|
||||
|
||||
//Apollo server 2 tests
|
||||
|
||||
//apollo-server
|
||||
require('../packages/apollo-server/dist/index.test.js');
|
||||
|
||||
//apollo-server-express
|
||||
require('../packages/apollo-server-express/dist/ApolloServer.test.js');
|
||||
|
||||
//Apollo server 1 tests
|
||||
require('../packages/apollo-server-module-operation-store/dist/operationStore.test');
|
||||
|
||||
require('../packages/apollo-server-express/dist/ApolloServer.test.js');
|
||||
require('../packages/apollo-server-express/dist/expressApollo.test');
|
||||
require('../packages/apollo-server-express/dist/connectApollo.test');
|
||||
|
||||
(NODE_MAJOR_VERSION >= 9 ||
|
||||
(NODE_MAJOR_VERSION >= 8 && NODE_MAJOR_REVISION >= 9)) &&
|
||||
require('../packages/apollo-server-hapi/dist/hapiApollo.test'); // Hapi 17 is 8.9+
|
||||
require('../packages/apollo-server-hapi/dist/hapiApollo.test') && // Hapi 17 is 8.9+
|
||||
require('../packages/apollo-server-hapi/dist/ApolloServer.test.js');
|
||||
require('../packages/apollo-server-express/dist/apolloServerHttp.test');
|
||||
|
|
Loading…
Add table
Reference in a new issue