Repository: apollographql/apollo-client

Problem statement:
Mutation component ignores context headers for refetchQueries
**Intended outcome:**
Queries specified as string array to the `refetchQueries` option of a mutation call should have headers included as specified by the `context` prop of the `Mutation` component.

**Actual outcome:**
The mutation uses the auth headers in the context but when the `refetchQueries` are run they are sent without headers.

**How to reproduce the issue:**

```ts
<Mutation
    mutation={MyMutation}
    context={ headers: {
      authorization: token ? `Bearer ${token}` : ""
    }}>
        {(mutate) => (
            mutate({
                variables: { ... },
                refetchQueries: ["MyOtherQuery"],
            });
    )}
</Mutation>
```

When `MyMutation`is sent to the server the headers specified in the context prop are included in the HTTP request. But when the mutation has completed and `MyOtherQuery` is run, the HTTP request does not contain the headers and therefore gives a 403 error.

**Versions**

apollo-client@2.3.2

The requested command to get versions does not seem to work:

```
$ npx envinfo@latest --preset apollo --clipboard
npx: installed 1 in 1.95s
Path must be a string. Received undefined
npx: installed 1 in 1.89s
C:\Users\jonkel.DIVID\AppData\Roaming\npm-cache\_npx\11232\node_modules\envinfo\dist\cli.js

  System:
    OS: Windows 10
  Binaries:
    Yarn: 1.7.0 - C:\Users\jonkel.DIVID\AppData\Roaming\npm\yarn.CMD
    npm: 5.7.1 - C:\PROGRAM FILES\NODEJS\npm.CMD
  Browsers:
    Edge: 41.16299.402.0

(node:11232) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: The system cannot find the path specified.

(node:11232) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
```




Hints:
Confirmed 🐛 - thanks for reporting this @jonaskello!

If anyone is interested in helping out with this, the following just needs to be updated to add the `mutate` functions passed in `context` param:

https://github.com/apollographql/apollo-client/blob/ef32c3250e51f55c328fef5e3e45d59397d92206/packages/apollo-client/src/core/QueryManager.ts#L263-L267
I'll try to take a stab at it:-).

Patch:
diff --git a/packages/apollo-client/src/__mocks__/mockLinks.ts b/packages/apollo-client/src/__mocks__/mockLinks.ts
--- a/packages/apollo-client/src/__mocks__/mockLinks.ts
+++ b/packages/apollo-client/src/__mocks__/mockLinks.ts
@@ -8,11 +8,15 @@ import {
 
 import { print } from 'graphql/language/printer';
 
+interface MockApolloLink extends ApolloLink {
+  operation?: Operation;
+}
+
 // Pass in multiple mocked responses, so that you can test flows that end up
 // making multiple queries to the server
 export function mockSingleLink(
   ...mockedResponses: MockedResponse[]
-): ApolloLink {
+): MockApolloLink {
   return new MockLink(mockedResponses);
 }
 
@@ -40,6 +44,7 @@ export interface MockedSubscription {
 }
 
 export class MockLink extends ApolloLink {
+  public operation: Operation;
   private mockedResponsesByKey: { [key: string]: MockedResponse[] } = {};
 
   constructor(mockedResponses: MockedResponse[]) {
@@ -60,6 +65,7 @@ export class MockLink extends ApolloLink {
   }
 
   public request(operation: Operation) {
+    this.operation = operation;
     const key = requestToKey(operation);
     const responses = this.mockedResponsesByKey[key];
     if (!responses || responses.length === 0) {
diff --git a/packages/apollo-client/src/core/watchQueryOptions.ts b/packages/apollo-client/src/core/watchQueryOptions.ts
--- a/packages/apollo-client/src/core/watchQueryOptions.ts
+++ b/packages/apollo-client/src/core/watchQueryOptions.ts
@@ -222,7 +222,14 @@ export interface MutationOptions<
   mutation: DocumentNode;
 
   /**
-   * Context to be passed to link execution chain
+   * The context to be passed to the link execution chain. This context will
+   * only be used with the mutation. It will not be used with
+   * `refetchQueries`. Refetched queries use the context they were
+   * initialized with (since the intitial context is stored as part of the
+   * `ObservableQuery` instance). If a specific context is needed when
+   * refetching queries, make sure it is configured (via the
+   * [`query` `context` option](/docs/react/api/apollo-client.html#ApolloClient.query))
+   * when the query is first initialized/run.
    */
   context?: any;
 


Test patch:
diff --git a/packages/apollo-client/src/core/__tests__/QueryManager/index.ts b/packages/apollo-client/src/core/__tests__/QueryManager/index.ts
--- a/packages/apollo-client/src/core/__tests__/QueryManager/index.ts
+++ b/packages/apollo-client/src/core/__tests__/QueryManager/index.ts
@@ -4362,6 +4362,85 @@ describe('QueryManager', () => {
       );
     });
 
+    it('should refetch using the original query context (if any)', () => {
+      const mutation = gql`
+        mutation changeAuthorName {
+          changeAuthorName(newName: "Jack Smith") {
+            firstName
+            lastName
+          }
+        }
+      `;
+      const mutationData = {
+        changeAuthorName: {
+          firstName: 'Jack',
+          lastName: 'Smith',
+        },
+      };
+      const query = gql`
+        query getAuthors($id: ID!) {
+          author(id: $id) {
+            firstName
+            lastName
+          }
+        }
+      `;
+      const data = {
+        author: {
+          firstName: 'John',
+          lastName: 'Smith',
+        },
+      };
+      const secondReqData = {
+        author: {
+          firstName: 'Jane',
+          lastName: 'Johnson',
+        },
+      };
+      const variables = { id: '1234' };
+      const queryManager = mockQueryManager(
+        {
+          request: { query, variables },
+          result: { data },
+        },
+        {
+          request: { query, variables },
+          result: { data: secondReqData },
+        },
+        {
+          request: { query: mutation },
+          result: { data: mutationData },
+        },
+      );
+
+      const headers = {
+        someHeader: 'some value',
+      };
+      const observable = queryManager.watchQuery<any>({
+        query,
+        variables,
+        context: {
+          headers,
+        },
+        notifyOnNetworkStatusChange: false,
+      });
+
+      return observableToPromise(
+        { observable },
+        result => {
+          queryManager.mutate({
+            mutation,
+            refetchQueries: ['getAuthors'],
+          });
+        },
+        result => {
+          const context = queryManager.link.operation.getContext();
+          expect(context.headers).not.toBeUndefined();
+          expect(context.headers.someHeader).toEqual(headers.someHeader);
+        },
+      );
+    });
+
     afterEach(done => {
       // restore standard method
       console.warn = oldWarn;