Skip to content

Commit

Permalink
Update executeOperation signature to use an object
Browse files Browse the repository at this point in the history
  • Loading branch information
trevor-scheer authored and glasser committed Sep 24, 2022
1 parent 04ad870 commit feddeae
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 82 deletions.
24 changes: 13 additions & 11 deletions packages/integration-testsuite/src/apolloServerTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
GraphQLString,
GraphQLError,
ValidationContext,
ResponsePath,
DocumentNode,
printSchema,
FieldNode,
Expand Down Expand Up @@ -538,12 +537,11 @@ export function defineIntegrationTestSuiteApolloServerTests(
describe('Plugins', () => {
let apolloFetch: ApolloFetch;
let apolloFetchResponse: ParsedResponse;
let serverInstance: ApolloServer<BaseContext>;

const setupApolloServerAndFetchPairForPlugins = async (
plugins: ApolloServerPlugin<BaseContext>[] = [],
) => {
const { server, url } = await createServer(
const { url } = await createServer(
{
typeDefs: gql`
type Query {
Expand All @@ -555,8 +553,6 @@ export function defineIntegrationTestSuiteApolloServerTests(
{ context: async () => ({ customContext: true }) },
);

serverInstance = server;

apolloFetch = createApolloFetch({ uri: url })
// Store the response so we can inspect it.
.useAfter(({ response }, next) => {
Expand Down Expand Up @@ -1606,9 +1602,15 @@ export function defineIntegrationTestSuiteApolloServerTests(

expect(spy).not.toBeCalled();

await server.executeOperation({ query: '{hello}' }, uniqueContext);
await server.executeOperation({
request: { query: '{hello}' },
contextValue: uniqueContext,
});
expect(spy).toHaveBeenCalledTimes(1);
await server.executeOperation({ query: '{hello}' }, uniqueContext);
await server.executeOperation({
request: { query: '{hello}' },
contextValue: uniqueContext,
});
expect(spy).toHaveBeenCalledTimes(2);
});
});
Expand Down Expand Up @@ -2573,7 +2575,7 @@ export function defineIntegrationTestSuiteApolloServerTests(
// Executing an operation ensures that (even if
// serverIsStartedInBackground) startup completes, so that we can
// legally call stop().
await server.executeOperation({ query: '{__typename}' });
await server.executeOperation({ request: { query: '{__typename}' } });
});

it('unsubscribes from schema update on close', async () => {
Expand All @@ -2592,7 +2594,7 @@ export function defineIntegrationTestSuiteApolloServerTests(
// to be executed concurrently with start(). (Without this query,
// stop() may be executed before the gateway schema update
// unsubscriber is registered for disposal, causing the test to fail.)
await server.executeOperation({ query: '{__typename}' });
await server.executeOperation({ request: { query: '{__typename}' } });
}
expect(unsubscribeSpy).not.toHaveBeenCalled();
await stopServer();
Expand Down Expand Up @@ -2689,11 +2691,11 @@ export function defineIntegrationTestSuiteApolloServerTests(
triggers.triggerSchemaChange!(getSchemaUpdateWithField('testString2'));
// Hacky, but: executeOperation awaits schemaDerivedData, so when it
// finishes we know the new schema is loaded.
await server.executeOperation({ query: '{__typename}' });
await server.executeOperation({ request: { query: '{__typename}' } });
const result2 = apolloFetch({ query: '{testString2}' });
await executorData['{testString2}'].startPromise;
triggers.triggerSchemaChange!(getSchemaUpdateWithField('testString3'));
await server.executeOperation({ query: '{__typename}' });
await server.executeOperation({ request: { query: '{__typename}' } });
const result3 = apolloFetch({ query: '{testString3}' });
await executorData['{testString3}'].startPromise;
executorData['{testString3}'].endPromise.resolve();
Expand Down
39 changes: 21 additions & 18 deletions packages/server/src/ApolloServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ export interface ApolloServerInternals<TContext extends BaseContext> {
__testing_incrementalExecutionResults?: GraphQLExperimentalIncrementalExecutionResults;
}

interface ExecuteOperation<TContext extends BaseContext> {
request: Omit<GraphQLRequest, 'query'> & {
query?: string | DocumentNode;
};
contextValue?: TContext;
}

function defaultLogger(): Logger {
const loglevelLogger = loglevel.getLogger('apollo-server');
loglevelLogger.setLevel(loglevel.levels.INFO);
Expand Down Expand Up @@ -1080,28 +1087,24 @@ export class ApolloServer<in out TContext extends BaseContext = BaseContext> {
* just a convenience, not an optimization (we convert provided ASTs back into
* string).
*
* The second object will be the `contextValue` object available in resolvers.
* `request.contextValue` will be the `contextValue` object available in resolvers.
*/
// TODO(AS4): Make the parameters to this function an object
public async executeOperation(
this: ApolloServer<BaseContext>,
request: Omit<GraphQLRequest, 'query'> & {
query?: string | DocumentNode;
},
{ request }: Omit<ExecuteOperation<TContext>, 'contextValue'>,
): Promise<GraphQLResponse>;
public async executeOperation(
request: Omit<GraphQLRequest, 'query'> & {
query?: string | DocumentNode;
},
contextValue: TContext,
): Promise<GraphQLResponse>;

async executeOperation(
request: Omit<GraphQLRequest, 'query'> & {
query?: string | DocumentNode;
},
contextValue?: TContext,
): Promise<GraphQLResponse> {
public async executeOperation({
request,
contextValue,
}: WithRequired<
ExecuteOperation<TContext>,
'contextValue'
>): Promise<GraphQLResponse>;

async executeOperation({
request,
contextValue,
}: ExecuteOperation<TContext>): Promise<GraphQLResponse> {
// Since this function is mostly for testing, you don't need to explicitly
// start your server before calling it. (That also means you can use it with
// `apollo-server` which doesn't support `start()`.)
Expand Down
68 changes: 43 additions & 25 deletions packages/server/src/__tests__/ApolloServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,9 @@ describe('ApolloServer executeOperation', () => {
await server.start();

const { body } = await server.executeOperation({
query: 'query { error }',
request: {
query: 'query { error }',
},
});

assert(body.kind === 'single');
Expand All @@ -285,7 +287,9 @@ describe('ApolloServer executeOperation', () => {
await server.start();

const { body } = await server.executeOperation({
query: 'query { error }',
request: {
query: 'query { error }',
},
});

const result = singleResult(body);
Expand All @@ -304,7 +308,9 @@ describe('ApolloServer executeOperation', () => {
});
await server.start();

const { body } = await server.executeOperation({ query: '{ hello }' });
const { body } = await server.executeOperation({
request: { query: '{ hello }' },
});
const result = singleResult(body);
expect(result.errors).toBeUndefined();
expect(result.data?.hello).toBe('world');
Expand All @@ -319,11 +325,13 @@ describe('ApolloServer executeOperation', () => {
await server.start();

const { body } = await server.executeOperation({
query: gql`
{
hello
}
`,
request: {
query: gql`
{
hello
}
`,
},
});
const result = singleResult(body);
expect(result.errors).toBeUndefined();
Expand All @@ -338,7 +346,9 @@ describe('ApolloServer executeOperation', () => {
});
await server.start();

const { body } = await server.executeOperation({ query: '{' });
const { body } = await server.executeOperation({
request: { query: '{' },
});
const result = singleResult(body);
expect(result.errors).toEqual([
{
Expand All @@ -359,7 +369,9 @@ describe('ApolloServer executeOperation', () => {
});
await server.start();

const { body } = await server.executeOperation({ query: '{ unknown }' });
const { body } = await server.executeOperation({
request: { query: '{ unknown }' },
});
const result = singleResult(body);
expect(result.errors).toEqual([
{
Expand All @@ -374,16 +386,19 @@ describe('ApolloServer executeOperation', () => {
});

it('passes its second argument as context object', async () => {
const server = new ApolloServer({
interface MyContext {
foo: string;
}
const server = new ApolloServer<MyContext>({
typeDefs,
resolvers,
});
await server.start();

const { body } = await server.executeOperation(
{ query: '{ contextFoo }' },
{ foo: 'bla' },
);
const { body } = await server.executeOperation({
request: { query: '{ contextFoo }' },
contextValue: { foo: 'bla' },
});
const result = singleResult(body);
expect(result.errors).toBeUndefined();
expect(result.data?.contextFoo).toBe('bla');
Expand Down Expand Up @@ -423,21 +438,24 @@ describe('ApolloServer executeOperation', () => {
],
});
await server.start();
const { body } = await server.executeOperation(
{ query: '{ n }' },
{ foo: 123 },
);
const { body } = await server.executeOperation({
request: { query: '{ n }' },
contextValue: { foo: 123 },
});
const result = singleResult(body);
expect(result.errors).toBeUndefined();
expect(result.data?.n).toBe(123);

const { body: body2 } = await server.executeOperation(
{ query: '{ n }' },
// It knows that context.foo is a number so it doesn't work as a string.
// @ts-expect-error
{ foo: 'asdf' },
);
// It knows that context.foo is a number so it doesn't work as a string.
// @ts-expect-error
const { body: body2 } = await server.executeOperation({
request: { query: '{ n }' },
contextValue: {
foo: 'asdf',
},
});
const result2 = singleResult(body2);

// GraphQL will be sad that a string was returned from an Int! field.
expect(result2.errors).toBeDefined();
await server.stop();
Expand Down
10 changes: 6 additions & 4 deletions packages/server/src/__tests__/documentStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('ApolloServer documentStore', () => {
assert(documentStore);
expect(documentStore).toBeInstanceOf(InMemoryLRUCache);

await server.executeOperation(operations.simple.op);
await server.executeOperation({ request: operations.simple.op });

expect(
(documentStore as InMemoryLRUCache<DocumentNode>)['cache'].calculatedSize,
Expand All @@ -77,7 +77,7 @@ describe('ApolloServer documentStore', () => {
});
await server.start();

await server.executeOperation(operations.simple.op);
await server.executeOperation({ request: operations.simple.op });
const keys = documentStore.keys();
expect(keys).toHaveLength(1);
const theKey = keys[0];
Expand All @@ -88,7 +88,7 @@ describe('ApolloServer documentStore', () => {
const result = await documentStore.get(`${uuid}:${hash}`);
expect(result).toMatchObject(documentNodeMatcher);

await server.executeOperation(operations.simple.op);
await server.executeOperation({ request: operations.simple.op });

// one of these calls is ours
expect(getSpy.mock.calls.length).toBe(2 + 1);
Expand All @@ -110,7 +110,9 @@ describe('ApolloServer documentStore', () => {
).schemaManager.getSchemaDerivedData();
expect(documentStore).toBeNull();

const { body } = await server.executeOperation(operations.simple.op);
const { body } = await server.executeOperation({
request: operations.simple.op,
});

expect(body).toEqual({
kind: 'single',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export async function collectCacheControlHintsAndPolicyIfCacheable(
],
});
await server.start();
const response = await server.executeOperation({ query: source });
const response = await server.executeOperation({request:{ query: source }});
await server.stop();

if (!('singleResult' in response.body)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,15 @@ describe('end-to-end', () => {
await server.start();

const response = await server.executeOperation({
query: query ?? defaultQuery,
// If operation name is specified use it. If it is specified as null convert it to
// undefined because graphqlRequest expects string | undefined
operationName:
operationName === undefined ? 'q' : operationName || undefined,
extensions: {
clientName: 'testing suite',
request: {
query: query ?? defaultQuery,
// If operation name is specified use it. If it is specified as null convert it to
// undefined because graphqlRequest expects string | undefined
operationName:
operationName === undefined ? 'q' : operationName || undefined,
extensions: {
clientName: 'testing suite',
},
},
});

Expand Down
Loading

0 comments on commit feddeae

Please sign in to comment.