apollo-server-testing createTestClient types

Created on 10 Jan 2019  路  2Comments  路  Source: apollographql/apollo-server

Writing the below in typescript complains with 'variables' does not exist in type 'Query | Mutation'

let client = createTestClient(server);
let result = await client.query({
    query: SOME_QUERY,
    variables: { var: "var" }
});

Looking in createTestClient.ts shows that client.query is written

({ query, mutation, ...args }: Query | Mutation) => { ... }

with

type Query = { query: StringOrAst; mutation?: undefined };
type Mutation = { mutation: StringOrAst; query?: undefined };

As it is currently written args is later passed through correctly to server.executeOperation, however the typings imply that args can only ever be an empty object when in fact it should allow the following additional fields (from the interface GraphQLRequest in requestPipelineAPI.ts)

{
    operationName?: string;
    variables?: { [name: string]: any };
    extensions?: Record<string, any>;
    http?: Pick<Request, 'url' | 'method' | 'headers'>;
}

It may be a good idea to implement it like this

type RequestNoQuery = Pick<GraphQLRequest, Exclude<keyof GraphQLRequest, "query">>;

type Query = { query: StringOrAst; mutation?: undefined } & RequestNoQuery;
type Mutation = { mutation: StringOrAst; query?: undefined } & RequestNoQuery;

So as to be less coupled to any changes to GraphQLRequest

Most helpful comment

As a workaround, you can add a apollo-server-testing.d.ts file to your project with the following:

declare module 'apollo-server-testing' {
  import { ApolloServerBase } from 'apollo-server-core';
  import { print, DocumentNode } from 'graphql';
  import { GraphQLResponse } from 'graphql-extensions';

  type StringOrAst = string | DocumentNode;

  // A query must not come with a mutation (and vice versa).
  type Query<TVariables> = {
    query: StringOrAst;
    mutation?: undefined;
    variables?: TVariables;
  };

  type Mutation<TVariables> = {
    mutation: StringOrAst;
    query?: undefined;
    variables?: TVariables;
  };

  export const createTestClient: <TVariables>(
    server: ApolloServerBase,
  ) => {
    query: (query: Query<TVariables>) => Promise<GraphQLResponse>;
    mutate: (mutation: Mutation<TVariables>) => Promise<GraphQLResponse>;
  };
}

All 2 comments

It would be great if the variables type was a generic (as well as the return type), just like apollo-client is doing it.

query<T, TVariables = OperationVariables>(options: QueryOptions<TVariables>): Promise<ApolloQueryResult<T>>;

As a workaround, you can add a apollo-server-testing.d.ts file to your project with the following:

declare module 'apollo-server-testing' {
  import { ApolloServerBase } from 'apollo-server-core';
  import { print, DocumentNode } from 'graphql';
  import { GraphQLResponse } from 'graphql-extensions';

  type StringOrAst = string | DocumentNode;

  // A query must not come with a mutation (and vice versa).
  type Query<TVariables> = {
    query: StringOrAst;
    mutation?: undefined;
    variables?: TVariables;
  };

  type Mutation<TVariables> = {
    mutation: StringOrAst;
    query?: undefined;
    variables?: TVariables;
  };

  export const createTestClient: <TVariables>(
    server: ApolloServerBase,
  ) => {
    query: (query: Query<TVariables>) => Promise<GraphQLResponse>;
    mutate: (mutation: Mutation<TVariables>) => Promise<GraphQLResponse>;
  };
}
Was this page helpful?
0 / 5 - 0 ratings