Sakdow
Sakdow

Reputation: 51

Get headers with executeOperation on Apollo Server (apollo-server) for integrations tests

Since the deprecation of apollo-server-testing I am using the new way of doing integration tests with apollo-server (included in apollo-server 2.25.0). From the mutation signin I set my refresh token in the OutgoingMessage header's (in 'Set-Cookie').

Simplified resolver

    @Mutation(() => RefreshTokenOutput)
    async refreshToken(@Ctx() { response, contextRefreshToken }: Context): Promise<RefreshTokenOutput> {
        if (contextRefreshToken) {
            const { accessToken, refreshToken } = await this.authService.refreshToken(contextRefreshToken);
            response.setHeader(
                'Set-Cookie',
                cookie.serialize('refreshToken', refreshToken, {
                    httpOnly: true,
                    maxAge: maxAge,
                    secure: true,
                })
            );
            return { accessToken: accessToken };
        } else {
            throw new AuthenticationError();
        }
    }

Test case

            // given:
            const { user, clearPassword } = await userLoader.createUser16c();
            const input = new UserSigninInput();
            input.email = user.email;
            input.password = clearPassword;

            const MUTATE_signin = gql`
                mutation signin($userInput: UserSigninInput!) {
                    signin(input: $userInput) {
                        accessToken
                    }
                }
            `;

            // when:
            const res = await server.executeOperation(
                { query: MUTATE_signin, variables: { userInput: input }, operationName: 'signin' },
                buildContext(user)
            );

I'm trying to test if this token is correctly set and well formed. Did you have any idea on how I can access this header with executeOperation ?

Upvotes: 5

Views: 3032

Answers (3)

BigMan73
BigMan73

Reputation: 1584

Apollo defines executeOperation as:

  public async executeOperation(
    request: Omit<GraphQLRequest, 'query'> & {
      query?: string | DocumentNode;
    },
    integrationContextArgument?: ContextFunctionParams,
  ) {

integrationContextArgument is optional and ContextFunctionParams is just an alias to any. As mentioned in an answer above, any context JSON passed to the executeOperation function will be sent to Apollo's processGraphQLRequest() function

graphQLServerOptions() function processes that JSON. For more advanced scenarios, it seems that a context resolver function, not just JSON context data, can be passed in using the context field

Reference: https://github.com/apollographql/apollo-server/blob/e9ae0f28d11d2fdfc5abd5048c85acf70de21592/packages/apollo-server-core/src/ApolloServer.ts#L1014

Upvotes: 0

Bot
Bot

Reputation: 144

I was able to set headers like this:

const res = await apolloServer.executeOperation({ query: chicken, variables: { id: 1 } }, {req: {headers: 'Authorization sdf'}});

Upvotes: 2

fuzes
fuzes

Reputation: 2057

server.executeOperation calls processGraphQLRequest

and processGraphQLRequest return type is GraphQLResponse

export interface GraphQLResponse {
  data?: Record<string, any> | null;
  errors?: ReadonlyArray<GraphQLFormattedError>;
  extensions?: Record<string, any>;
  http?: Pick<Response, 'headers'> & Partial<Pick<Mutable<Response>, 'status'>>;
}

I'm not sure, but i think headers in GraphQLResponse.http

you can find call structure in github repo.

https://github.com/apollographql/apollo-server/blob/6b9c2a0f1932e6d8fb94a8662cc1da24980aec6f/packages/apollo-server-core/src/requestPipeline.ts#L126

Upvotes: 0

Related Questions