Skip to content

Commit

Permalink
Introduce apollo-server-testing package. (#1909)
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeDawkins authored and abernix committed Nov 5, 2018
1 parent 422609e commit e3d5be9
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 0 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -54,6 +54,7 @@
"apollo-server-lambda": "file:packages/apollo-server-lambda",
"apollo-server-micro": "file:packages/apollo-server-micro",
"apollo-server-plugin-base": "file:packages/apollo-server-plugin-base",
"apollo-server-testing": "file:packages/apollo-server-testing",
"apollo-tracing": "file:packages/apollo-tracing",
"graphql-extensions": "file:packages/graphql-extensions"
},
Expand Down
35 changes: 35 additions & 0 deletions packages/apollo-server-core/src/ApolloServer.ts
Expand Up @@ -45,6 +45,13 @@ import {
} from './playground';

import { generateSchemaHash } from './utils/schemaHash';
import {
processGraphQLRequest,
GraphQLRequestContext,
GraphQLRequest,
} from './requestPipeline';

import { Headers } from 'apollo-server-env';

const NoIntrospection = (context: ValidationContext) => ({
Field(node: FieldDefinitionNode) {
Expand Down Expand Up @@ -502,4 +509,32 @@ export class ApolloServerBase {
...this.requestOptions,
} as GraphQLOptions;
}

public async executeOperation(request: GraphQLRequest) {
let options;

try {
options = await this.graphQLServerOptions();
} catch (e) {
e.message = `Invalid options provided to ApolloServer: ${e.message}`;
throw new Error(e);
}

if (typeof options.context === 'function') {
options.context = (options.context as () => never)();
}

const requestCtx: GraphQLRequestContext = {
request,
context: options.context || Object.create(null),
cache: options.cache!,
response: {
http: {
headers: new Headers(),
},
},
};

return processGraphQLRequest(options, requestCtx);
}
}
5 changes: 5 additions & 0 deletions packages/apollo-server-testing/CHANGELOG.md
@@ -0,0 +1,5 @@
# Changelog

### vNEXT

* `apollo-server-testing`: Added createTestClient function
7 changes: 7 additions & 0 deletions packages/apollo-server-testing/README.md
@@ -0,0 +1,7 @@
# apollo-server-testing

[![npm version](https://badge.fury.io/js/apollo-server-testing.svg)](https://badge.fury.io/js/apollo-server-testing)
[![Build Status](https://circleci.com/gh/apollographql/apollo-server.svg?style=svg)](https://circleci.com/gh/apollographql/apollo-server)

This is the testing module of the Apollo community GraphQL Server. [Read the docs.](https://www.apollographql.com/docs/apollo-server/)
[Read the CHANGELOG.](https://github.com/apollographql/apollo-server/blob/master/CHANGELOG.md)
3 changes: 3 additions & 0 deletions packages/apollo-server-testing/jest.config.js
@@ -0,0 +1,3 @@
const config = require('../../jest.config.base');

module.exports = Object.assign(Object.create(null), config);
32 changes: 32 additions & 0 deletions packages/apollo-server-testing/package.json
@@ -0,0 +1,32 @@
{
"name": "apollo-server-testing",
"version": "2.2.0-alpha.0",
"description": "Test utils for apollo-server",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-testing"
},
"keywords": [
"GraphQL",
"Apollo",
"Server",
"Javascript"
],
"author": "Jonas Helfer <jonas@helfer.email>",
"license": "MIT",
"bugs": {
"url": "https://github.com/apollographql/apollo-server/issues"
},
"homepage": "https://github.com/apollographql/apollo-server#readme",
"engines": {
"node": ">=6"
},
"dependencies": {
"apollo-server-core": "file:../apollo-server-core"
},
"peerDependencies": {
"graphql": "^0.12.0 || ^0.13.0 || ^14.0.0"
}
}
@@ -0,0 +1,81 @@
import { ApolloServerBase, gql } from 'apollo-server-core';
import createTestClient from '../createTestClient';

describe('createTestClient', () => {
const typeDefs = gql`
type Query {
test(echo: String): String
# this resolver uses context
hello: String
}
type Mutation {
increment: Int!
}
`;

const resolvers = {
Query: {
test: (_, { echo }) => echo,
hello: (_, __, { person }) => {
return `hello ${person}`;
},
},
Mutation: {
increment: () => 1,
},
};

const myTestServer = new ApolloServerBase({
typeDefs,
context: () => ({ person: 'tom' }),
resolvers,
});

it('allows queries', async () => {
const query = `{ test(echo: "foo") }`;
const client = createTestClient(myTestServer);
const res = await client.query({ query });
expect(res.data).toEqual({ test: 'foo' });
});

it('allows mutations', async () => {
const mutation = `mutation increment { increment }`;
const client = createTestClient(myTestServer);
const res = await client.mutate({ mutation });
expect(res.data).toEqual({ increment: 1 });
});

it('allows variables to be passed', async () => {
const query = `query test($echo: String){ test(echo: $echo) }`;
const client = createTestClient(myTestServer);
const res = await client.query({ query, variables: { echo: 'wow' } });
expect(res.data).toEqual({ test: 'wow' });
});

it('resolves with context', async () => {
const query = `{ hello }`;
const client = createTestClient(myTestServer);
const res = await client.query({ query });
expect(res.data).toEqual({ hello: 'hello tom' });
});

it('allows query documents as input', async () => {
const query = gql`
{
test(echo: "foo")
}
`;
const client = createTestClient(myTestServer);
const clientRes = await client.query({ query });
expect(clientRes.data).toEqual({ test: 'foo' });

const mutation = gql`
mutation increment {
increment
}
`;
const mutationRes = await client.mutate({ mutation });
expect(mutationRes.data).toEqual({ increment: 1 });
});
});
5 changes: 5 additions & 0 deletions packages/apollo-server-testing/src/__tests__/tsconfig.json
@@ -0,0 +1,5 @@
{
"extends": "../../../../tsconfig.test.base",
"include": ["**/*"],
"references": []
}
28 changes: 28 additions & 0 deletions packages/apollo-server-testing/src/createTestClient.ts
@@ -0,0 +1,28 @@
import { ApolloServerBase } from 'apollo-server-core';
import { print, DocumentNode } from 'graphql';

type StringOrAst = string | DocumentNode;
interface QueryOrMutation {
query?: StringOrAst;
mutation?: StringOrAst;
}

export default (server: ApolloServerBase) => {
const executeOperation = server.executeOperation.bind(server);
const test = ({ query, mutation, ...args }: QueryOrMutation) => {
const operation = query || mutation;

if ((!query && !mutation) || (query && mutation)) {
throw new Error('Either `query` or `mutation` must be passed');
}

return executeOperation({
// Convert ASTs, which are produced by `graphql-tag` but not currently
// used by `executeOperation`, to a String using `graphql/language/print`.
query: typeof operation === 'string' ? operation : print(operation),
...args,
});
};

return { query: test, mutate: test };
};
1 change: 1 addition & 0 deletions packages/apollo-server-testing/src/index.ts
@@ -0,0 +1 @@
export { default as createTestClient } from './createTestClient';
12 changes: 12 additions & 0 deletions packages/apollo-server-testing/tsconfig.json
@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.base",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"include": ["src/**/*"],
"exclude": ["**/__tests__", "**/__mocks__"],
"references": [
{ "path": "../apollo-server-core" }
]
}
1 change: 1 addition & 0 deletions tsconfig.build.json
Expand Up @@ -22,6 +22,7 @@
{ "path": "./packages/apollo-server-lambda" },
{ "path": "./packages/apollo-server-micro" },
{ "path": "./packages/apollo-server-plugin-base" },
{ "path": "./packages/apollo-server-testing" },
{ "path": "./packages/apollo-tracing" },
{ "path": "./packages/graphql-extensions" },
]
Expand Down

0 comments on commit e3d5be9

Please sign in to comment.