From 3872a8a830838bc49ccc7132a67a395aa0cac9b1 Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 05:07:20 -0700 Subject: [PATCH 01/12] add expect assertions --- .../apollo-client/src/__tests__/optimistic.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index e7be6cb57aa..9a13ff61d8d 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -189,6 +189,7 @@ describe('optimistic mutation results', () => { }; it('handles a single error for a single mutation', () => { + expect.assertions(6); return setup({ request: { query: mutation }, error: new Error('forbidden (test error)'), @@ -219,6 +220,7 @@ describe('optimistic mutation results', () => { }); it('handles errors produced by one mutation in a series', () => { + expect.assertions(10); let subscriptionHandle: Subscription; return setup( { @@ -290,6 +292,7 @@ describe('optimistic mutation results', () => { }); it('can run 2 mutations concurrently and handles all intermediate states well', () => { + expect.assertions(34); function checkBothMutationsAreApplied( expectedText1: any, expectedText2: any, @@ -423,6 +426,7 @@ describe('optimistic mutation results', () => { }; it('handles a single error for a single mutation', () => { + expect.assertions(6); return setup({ request: { query: mutation }, error: new Error('forbidden (test error)'), @@ -453,6 +457,7 @@ describe('optimistic mutation results', () => { }); it('handles errors produced by one mutation in a series', () => { + expect.assertions(10); let subscriptionHandle: Subscription; return setup( { @@ -524,6 +529,7 @@ describe('optimistic mutation results', () => { }); it('can run 2 mutations concurrently and handles all intermediate states well', () => { + expect.assertions(34); function checkBothMutationsAreApplied( expectedText1: any, expectedText2: any, @@ -662,6 +668,7 @@ describe('optimistic mutation results', () => { }); it('will use a passed variable in optimisticResponse', () => { + expect.assertions(6); let subscriptionHandle: Subscription; return setup({ request: { query: mutation, variables }, @@ -801,6 +808,7 @@ describe('optimistic mutation results', () => { }; it('will insert a single item to the beginning', () => { + expect.assertions(7); let subscriptionHandle: Subscription; return setup({ request: { query: mutation }, @@ -857,6 +865,7 @@ describe('optimistic mutation results', () => { }); it('two array insert like mutations', () => { + expect.assertions(9); let subscriptionHandle: Subscription; return setup( { @@ -952,6 +961,7 @@ describe('optimistic mutation results', () => { }); it('two mutations, one fails', () => { + expect.assertions(10); let subscriptionHandle: Subscription; return setup( { @@ -1043,6 +1053,7 @@ describe('optimistic mutation results', () => { }); it('will handle dependent updates', done => { + expect.assertions(5); link = mockSingleLink( { request: { query }, @@ -1228,6 +1239,7 @@ describe('optimistic mutation results', () => { }; it('will insert a single item to the beginning', () => { + expect.assertions(6); let subscriptionHandle: Subscription; return setup({ request: { query: mutation }, @@ -1297,6 +1309,7 @@ describe('optimistic mutation results', () => { }); it('two array insert like mutations', () => { + expect.assertions(9); let subscriptionHandle: Subscription; return setup( { @@ -1412,6 +1425,7 @@ describe('optimistic mutation results', () => { }); it('two mutations, one fails', () => { + expect.assertions(10); let subscriptionHandle: Subscription; return setup( { @@ -1521,6 +1535,7 @@ describe('optimistic mutation results', () => { }); it('will handle dependent updates', done => { + expect.assertions(5); link = mockSingleLink( { request: { query }, @@ -1818,6 +1833,7 @@ describe('optimistic mutation - githunt comments', () => { }; it('can post a new comment', () => { + expect.assertions(1); const mutationVariables = { repoFullName: 'org/repo', commentContent: 'New Comment', From b111955cb9fe103dd757ab1b917329059846e4c5 Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 05:31:39 -0700 Subject: [PATCH 02/12] flattens test "handles a single error for a single mutation" --- .../apollo-client/src/__tests__/optimistic.ts | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index 9a13ff61d8d..6eef97ac40f 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -188,35 +188,33 @@ describe('optimistic mutation results', () => { }, }; - it('handles a single error for a single mutation', () => { + it('handles a single error for a single mutation', async() => { expect.assertions(6); - return setup({ + await setup({ request: { query: mutation }, error: new Error('forbidden (test error)'), }) - .then(() => { - const promise = client.mutate({ - mutation, - optimisticResponse, - updateQueries, - }); - - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toBe(4); - expect((dataInStore['Todo99'] as any).text).toBe( - 'Optimistically generated', - ); + try { + const promise = client.mutate({ + mutation, + optimisticResponse, + updateQueries, + }); - return promise; - }) - .catch(err => { - expect(err).toBeInstanceOf(Error); - expect(err.message).toBe('Network error: forbidden (test error)'); + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toBe(4); + expect((dataInStore['Todo99'] as any).text).toBe( + 'Optimistically generated', + ); + await promise; + } catch(err) { + expect(err).toBeInstanceOf(Error); + expect(err.message).toBe('Network error: forbidden (test error)'); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toBe(3); - expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); - }); + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toBe(3); + expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); + } }); it('handles errors produced by one mutation in a series', () => { From 78add53e535d9dab4fcba993a5bff138041c8423 Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 05:49:25 -0700 Subject: [PATCH 03/12] flattens test "handles errors produced by one mutation in a series" --- .../apollo-client/src/__tests__/optimistic.ts | 109 +++++++++--------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index 6eef97ac40f..d09148dbee8 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -193,7 +193,7 @@ describe('optimistic mutation results', () => { await setup({ request: { query: mutation }, error: new Error('forbidden (test error)'), - }) + }); try { const promise = client.mutate({ mutation, @@ -217,10 +217,10 @@ describe('optimistic mutation results', () => { } }); - it('handles errors produced by one mutation in a series', () => { + it('handles errors produced by one mutation in a series', async () => { expect.assertions(10); let subscriptionHandle: Subscription; - return setup( + await setup( { request: { query: mutation }, error: new Error('forbidden (test error)'), @@ -229,64 +229,63 @@ describe('optimistic mutation results', () => { request: { query: mutation }, result: mutationResult2, }, - ) - .then(() => { - // we have to actually subscribe to the query to be able to update it - return new Promise(resolve => { - const handle = client.watchQuery({ query }); - subscriptionHandle = handle.subscribe({ - next(res) { - resolve(res); - }, - }); - }); - }) - .then(() => { - const promise = client - .mutate({ - mutation, - optimisticResponse, - updateQueries, - }) - .catch(err => { - // it is ok to fail here - expect(err).toBeInstanceOf(Error); - expect(err.message).toBe( - 'Network error: forbidden (test error)', - ); - return null; - }); + ); - const promise2 = client.mutate({ - mutation, - optimisticResponse: optimisticResponse2, - updateQueries, - }); + // we have to actually subscribe to the query to be able to update it + await new Promise(resolve => { + const handle = client.watchQuery({ query }); + subscriptionHandle = handle.subscribe({ + next(res) { + resolve(res); + }, + }); + }); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toBe(5); - expect((dataInStore['Todo99'] as any).text).toBe( - 'Optimistically generated', - ); - expect((dataInStore['Todo66'] as any).text).toBe( - 'Optimistically generated 2', - ); - return Promise.all([promise, promise2]); + const promise = client + .mutate({ + mutation, + optimisticResponse, + updateQueries, }) - .then(() => { - subscriptionHandle.unsubscribe(); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toBe(4); - expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); - expect(dataInStore).toHaveProperty('Todo66'); - expect((dataInStore['TodoList5'] as any).todos).toContainEqual( - realIdValue('Todo66', 'Todo'), - ); - expect((dataInStore['TodoList5'] as any).todos).not.toContainEqual( - realIdValue('Todo99', 'Todo'), + .catch(err => { + // it is ok to fail here + expect(err).toBeInstanceOf(Error); + expect(err.message).toBe( + 'Network error: forbidden (test error)', ); + return null; }); + + const promise2 = client.mutate({ + mutation, + optimisticResponse: optimisticResponse2, + updateQueries, + }); + + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toBe(5); + expect((dataInStore['Todo99'] as any).text).toBe( + 'Optimistically generated', + ); + expect((dataInStore['Todo66'] as any).text).toBe( + 'Optimistically generated 2', + ); + + await Promise.all([promise, promise2]); + + subscriptionHandle.unsubscribe(); + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toBe(4); + expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); + expect(dataInStore).toHaveProperty('Todo66'); + expect((dataInStore['TodoList5'] as any).todos).toContainEqual( + realIdValue('Todo66', 'Todo'), + ); + expect((dataInStore['TodoList5'] as any).todos).not.toContainEqual( + realIdValue('Todo99', 'Todo'), + ); + }); it('can run 2 mutations concurrently and handles all intermediate states well', () => { From 5f98d1d6aed4304c8a8ab62ccfd3e75de1d19e0c Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 06:27:01 -0700 Subject: [PATCH 04/12] finishes first pass of flattening the "error handling tests" --- .../apollo-client/src/__tests__/optimistic.ts | 357 +++++++++--------- 1 file changed, 175 insertions(+), 182 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index d09148dbee8..bc8fd1ec9bf 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -288,7 +288,7 @@ describe('optimistic mutation results', () => { }); - it('can run 2 mutations concurrently and handles all intermediate states well', () => { + it('can run 2 mutations concurrently and handles all intermediate states well', async () => { expect.assertions(34); function checkBothMutationsAreApplied( expectedText1: any, @@ -309,7 +309,7 @@ describe('optimistic mutation results', () => { expect((dataInStore['Todo66'] as any).text).toBe(expectedText2); } let subscriptionHandle: Subscription; - return setup( + await setup( { request: { query: mutation }, result: mutationResult, @@ -321,72 +321,69 @@ describe('optimistic mutation results', () => { delay: 100, }, ) - .then(() => { - // we have to actually subscribe to the query to be able to update it - return new Promise(resolve => { - const handle = client.watchQuery({ query }); - subscriptionHandle = handle.subscribe({ - next(res) { - resolve(res); - }, - }); - }); - }) - .then(() => { - const promise = client - .mutate({ - mutation, - optimisticResponse, - updateQueries, - }) - .then(res => { - checkBothMutationsAreApplied( - 'This one was created with a mutation.', - 'Optimistically generated 2', - ); - const latestState = client.queryManager.mutationStore; - expect(latestState.get('5').loading).toBe(false); - expect(latestState.get('6').loading).toBe(true); - - return res; - }); - - const promise2 = client - .mutate({ - mutation, - optimisticResponse: optimisticResponse2, - updateQueries, - }) - .then(res => { - checkBothMutationsAreApplied( - 'This one was created with a mutation.', - 'Second mutation.', - ); - const latestState = client.queryManager.mutationStore; - expect(latestState.get('5').loading).toBe(false); - expect(latestState.get('6').loading).toBe(false); - - return res; - }); - - const mutationsState = client.queryManager.mutationStore; - expect(mutationsState.get('5').loading).toBe(true); - expect(mutationsState.get('6').loading).toBe(true); + // we have to actually subscribe to the query to be able to update it + await new Promise(resolve => { + const handle = client.watchQuery({ query }); + subscriptionHandle = handle.subscribe({ + next(res) { + resolve(res); + }, + }); + }); + const promise = client + .mutate({ + mutation, + optimisticResponse, + updateQueries, + }) + .then(res => { checkBothMutationsAreApplied( - 'Optimistically generated', + 'This one was created with a mutation.', 'Optimistically generated 2', ); + const latestState = client.queryManager.mutationStore; + expect(latestState.get('5').loading).toBe(false); + expect(latestState.get('6').loading).toBe(true); - return Promise.all([promise, promise2]); + return res; + }); + + const promise2 = client + .mutate({ + mutation, + optimisticResponse: optimisticResponse2, + updateQueries, }) - .then(() => { - subscriptionHandle.unsubscribe(); + .then(res => { checkBothMutationsAreApplied( 'This one was created with a mutation.', 'Second mutation.', ); + const latestState = client.queryManager.mutationStore; + expect(latestState.get('5').loading).toBe(false); + expect(latestState.get('6').loading).toBe(false); + + return res; }); + + const mutationsState = client.queryManager.mutationStore; + expect(mutationsState.get('5').loading).toBe(true); + expect(mutationsState.get('6').loading).toBe(true); + + checkBothMutationsAreApplied( + 'Optimistically generated', + 'Optimistically generated 2', + ); + + await Promise.all([promise, promise2]); + + subscriptionHandle.unsubscribe(); + checkBothMutationsAreApplied( + 'This one was created with a mutation.', + 'Second mutation.', + ); + }); }); @@ -422,41 +419,41 @@ describe('optimistic mutation results', () => { }); }; - it('handles a single error for a single mutation', () => { + it('handles a single error for a single mutation', async () => { expect.assertions(6); - return setup({ - request: { query: mutation }, - error: new Error('forbidden (test error)'), - }) - .then(() => { - const promise = client.mutate({ - mutation, - optimisticResponse, - update, - }); - - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toBe(4); - expect((dataInStore['Todo99'] as any).text).toBe( - 'Optimistically generated', - ); - - return promise; + try { + await setup({ + request: { query: mutation }, + error: new Error('forbidden (test error)'), }) - .catch(err => { - expect(err).toBeInstanceOf(Error); - expect(err.message).toBe('Network error: forbidden (test error)'); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toBe(3); - expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); + const promise = client.mutate({ + mutation, + optimisticResponse, + update, }); + + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toBe(4); + expect((dataInStore['Todo99'] as any).text).toBe( + 'Optimistically generated', + ); + + await promise; + } catch(err) { + expect(err).toBeInstanceOf(Error); + expect(err.message).toBe('Network error: forbidden (test error)'); + + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toBe(3); + expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); + } }); - it('handles errors produced by one mutation in a series', () => { + it('handles errors produced by one mutation in a series', async () => { expect.assertions(10); let subscriptionHandle: Subscription; - return setup( + await setup( { request: { query: mutation }, error: new Error('forbidden (test error)'), @@ -466,66 +463,63 @@ describe('optimistic mutation results', () => { result: mutationResult2, }, ) - .then(() => { - // we have to actually subscribe to the query to be able to update it - return new Promise(resolve => { - const handle = client.watchQuery({ query }); - subscriptionHandle = handle.subscribe({ - next(res) { - resolve(res); - }, - }); - }); - }) - .then(() => { - const promise = client - .mutate({ - mutation, - optimisticResponse, - update, - }) - .catch(err => { - // it is ok to fail here - expect(err).toBeInstanceOf(Error); - expect(err.message).toBe( - 'Network error: forbidden (test error)', - ); - return null; - }); - - const promise2 = client.mutate({ - mutation, - optimisticResponse: optimisticResponse2, - update, - }); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toBe(5); - expect((dataInStore['Todo99'] as any).text).toBe( - 'Optimistically generated', - ); - expect((dataInStore['Todo66'] as any).text).toBe( - 'Optimistically generated 2', - ); + // we have to actually subscribe to the query to be able to update it + await new Promise(resolve => { + const handle = client.watchQuery({ query }); + subscriptionHandle = handle.subscribe({ + next(res) { + resolve(res); + }, + }); + }); - return Promise.all([promise, promise2]); + const promise = client + .mutate({ + mutation, + optimisticResponse, + update, }) - .then(() => { - subscriptionHandle.unsubscribe(); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toBe(4); - expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); - expect(dataInStore).toHaveProperty('Todo66'); - expect((dataInStore['TodoList5'] as any).todos).toContainEqual( - realIdValue('Todo66', 'Todo'), - ); - expect((dataInStore['TodoList5'] as any).todos).not.toContainEqual( - realIdValue('Todo99', 'Todo'), + .catch(err => { + // it is ok to fail here + expect(err).toBeInstanceOf(Error); + expect(err.message).toBe( + 'Network error: forbidden (test error)', ); + return null; }); + + const promise2 = client.mutate({ + mutation, + optimisticResponse: optimisticResponse2, + update, + }); + + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toBe(5); + expect((dataInStore['Todo99'] as any).text).toBe( + 'Optimistically generated', + ); + expect((dataInStore['Todo66'] as any).text).toBe( + 'Optimistically generated 2', + ); + + await Promise.all([promise, promise2]); + + subscriptionHandle.unsubscribe(); + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toBe(4); + expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); + expect(dataInStore).toHaveProperty('Todo66'); + expect((dataInStore['TodoList5'] as any).todos).toContainEqual( + realIdValue('Todo66', 'Todo'), + ); + expect((dataInStore['TodoList5'] as any).todos).not.toContainEqual( + realIdValue('Todo99', 'Todo'), + ); }); - it('can run 2 mutations concurrently and handles all intermediate states well', () => { + it('can run 2 mutations concurrently and handles all intermediate states well', async () => { expect.assertions(34); function checkBothMutationsAreApplied( expectedText1: any, @@ -545,7 +539,7 @@ describe('optimistic mutation results', () => { expect((dataInStore['Todo66'] as any).text).toBe(expectedText2); } let subscriptionHandle: Subscription; - return setup( + await setup( { request: { query: mutation }, result: mutationResult, @@ -568,61 +562,60 @@ describe('optimistic mutation results', () => { }); }); }) - .then(() => { - const promise = client - .mutate({ - mutation, - optimisticResponse, - update, - }) - .then(res => { - checkBothMutationsAreApplied( - 'This one was created with a mutation.', - 'Optimistically generated 2', - ); - const latestState = client.queryManager.mutationStore; - expect(latestState.get('5').loading).toBe(false); - expect(latestState.get('6').loading).toBe(true); - - return res; - }); - - const promise2 = client - .mutate({ - mutation, - optimisticResponse: optimisticResponse2, - update, - }) - .then(res => { - checkBothMutationsAreApplied( - 'This one was created with a mutation.', - 'Second mutation.', - ); - const latestState = client.queryManager.mutationStore; - expect(latestState.get('5').loading).toBe(false); - expect(latestState.get('6').loading).toBe(false); - - return res; - }); - - const mutationsState = client.queryManager.mutationStore; - expect(mutationsState.get('5').loading).toBe(true); - expect(mutationsState.get('6').loading).toBe(true); + const promise = client + .mutate({ + mutation, + optimisticResponse, + update, + }) + .then(res => { checkBothMutationsAreApplied( - 'Optimistically generated', + 'This one was created with a mutation.', 'Optimistically generated 2', ); + const latestState = client.queryManager.mutationStore; + expect(latestState.get('5').loading).toBe(false); + expect(latestState.get('6').loading).toBe(true); + + return res; + }); - return Promise.all([promise, promise2]); + const promise2 = client + .mutate({ + mutation, + optimisticResponse: optimisticResponse2, + update, }) - .then(() => { - subscriptionHandle.unsubscribe(); + .then(res => { checkBothMutationsAreApplied( 'This one was created with a mutation.', 'Second mutation.', ); + const latestState = client.queryManager.mutationStore; + expect(latestState.get('5').loading).toBe(false); + expect(latestState.get('6').loading).toBe(false); + + return res; }); + + const mutationsState = client.queryManager.mutationStore; + expect(mutationsState.get('5').loading).toBe(true); + expect(mutationsState.get('6').loading).toBe(true); + + checkBothMutationsAreApplied( + 'Optimistically generated', + 'Optimistically generated 2', + ); + + await Promise.all([promise, promise2]); + + subscriptionHandle.unsubscribe(); + checkBothMutationsAreApplied( + 'This one was created with a mutation.', + 'Second mutation.', + ); + }); }); }); From b7b291102306abd68aa9d94c1a29fa1facf8b5d2 Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 06:53:29 -0700 Subject: [PATCH 05/12] flatten "will use a passed variable in optimisticResponse" --- .../apollo-client/src/__tests__/optimistic.ts | 114 +++++++++--------- 1 file changed, 55 insertions(+), 59 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index bc8fd1ec9bf..b1c815a7659 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -657,78 +657,74 @@ describe('optimistic mutation results', () => { }, }); - it('will use a passed variable in optimisticResponse', () => { + it('will use a passed variable in optimisticResponse', async () => { expect.assertions(6); let subscriptionHandle: Subscription; - return setup({ + await setup({ request: { query: mutation, variables }, result: mutationResult, }) - .then(() => { - // we have to actually subscribe to the query to be able to update it - return new Promise(resolve => { - const handle = client.watchQuery({ query }); - subscriptionHandle = handle.subscribe({ - next(res) { - resolve(res); - }, - }); - }); - }) - .then(() => { - const promise = client.mutate({ - mutation, - variables, - optimisticResponse, - update: (proxy, mResult: any) => { - expect(mResult.data.createTodo.id).toBe('99'); - const id = 'TodoList5'; - const fragment = gql` - fragment todoList on TodoList { - todos { - id - text - completed - __typename - } - } - `; + // we have to actually subscribe to the query to be able to update it + await new Promise(resolve => { + const handle = client.watchQuery({ query }); + subscriptionHandle = handle.subscribe({ + next(res) { + resolve(res); + }, + }); + }); - const data: any = proxy.readFragment({ id, fragment }); + const promise = client.mutate({ + mutation, + variables, + optimisticResponse, + update: (proxy, mResult: any) => { + expect(mResult.data.createTodo.id).toBe('99'); - proxy.writeFragment({ - data: { - ...data, - todos: [mResult.data.createTodo, ...data.todos], - }, - id, - fragment, - }); + const id = 'TodoList5'; + const fragment = gql` + fragment todoList on TodoList { + todos { + id + text + completed + __typename + } + } + `; + + const data: any = proxy.readFragment({ id, fragment }); + + proxy.writeFragment({ + data: { + ...data, + todos: [mResult.data.createTodo, ...data.todos], }, + id, + fragment, }); + }, + }); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toEqual(4); - expect((dataInStore['Todo99'] as any).text).toEqual( - 'Optimistically generated from variables', - ); + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toEqual(4); + expect((dataInStore['Todo99'] as any).text).toEqual( + 'Optimistically generated from variables', + ); - return promise; - }) - .then(() => { - return client.query({ query }); - }) - .then((newResult: any) => { - subscriptionHandle.unsubscribe(); - // There should be one more todo item than before - expect(newResult.data.todoList.todos.length).toEqual(4); + await promise; - // Since we used `prepend` it should be at the front - expect(newResult.data.todoList.todos[0].text).toEqual( - 'This one was created with a mutation.', - ); - }); + const newResult: any = await client.query({ query }); + + subscriptionHandle.unsubscribe(); + // There should be one more todo item than before + expect(newResult.data.todoList.todos.length).toEqual(4); + + // Since we used `prepend` it should be at the front + expect(newResult.data.todoList.todos[0].text).toEqual( + 'This one was created with a mutation.', + ); }); }); From 9b7bf66d1048e98e73b9fa4414ad3f5742b64b44 Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 07:18:08 -0700 Subject: [PATCH 06/12] flatten test "will insert a single item to the beginning" --- .../apollo-client/src/__tests__/optimistic.ts | 89 +++++++++---------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index b1c815a7659..508ebaf3304 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -793,61 +793,58 @@ describe('optimistic mutation results', () => { }, }; - it('will insert a single item to the beginning', () => { + it('will insert a single item to the beginning', async () => { expect.assertions(7); let subscriptionHandle: Subscription; - return setup({ + await setup({ request: { query: mutation }, result: mutationResult, }) - .then(() => { - // we have to actually subscribe to the query to be able to update it - return new Promise(resolve => { - const handle = client.watchQuery({ query }); - subscriptionHandle = handle.subscribe({ - next(res) { - resolve(res); - }, - }); - }); - }) - .then(() => { - const promise = client.mutate({ - mutation, - optimisticResponse, - updateQueries: { - todoList: (prev, options) => { - const mResult = options.mutationResult as any; - expect(mResult.data.createTodo.id).toEqual('99'); - const state = cloneDeep(prev) as any; - state.todoList.todos.unshift(mResult.data.createTodo); - return state; - }, - }, - }); + // we have to actually subscribe to the query to be able to update it + await new Promise(resolve => { + const handle = client.watchQuery({ query }); + subscriptionHandle = handle.subscribe({ + next(res) { + resolve(res); + }, + }); + }); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toEqual(4); - expect((dataInStore['Todo99'] as any).text).toEqual( - 'Optimistically generated', - ); + const promise = client.mutate({ + mutation, + optimisticResponse, + updateQueries: { + todoList: (prev, options) => { + const mResult = options.mutationResult as any; + expect(mResult.data.createTodo.id).toEqual('99'); - return promise; - }) - .then(() => { - return client.query({ query }); - }) - .then((newResult: any) => { - subscriptionHandle.unsubscribe(); - // There should be one more todo item than before - expect(newResult.data.todoList.todos.length).toEqual(4); + const state = cloneDeep(prev) as any; + state.todoList.todos.unshift(mResult.data.createTodo); + return state; + }, + }, + }); + + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toEqual(4); + expect((dataInStore['Todo99'] as any).text).toEqual( + 'Optimistically generated', + ); + + await promise; + + const newResult: any = await client.query({ query }); + + subscriptionHandle.unsubscribe(); + // There should be one more todo item than before + expect(newResult.data.todoList.todos.length).toEqual(4); + + // Since we used `prepend` it should be at the front + expect(newResult.data.todoList.todos[0].text).toEqual( + 'This one was created with a mutation.', + ); - // Since we used `prepend` it should be at the front - expect(newResult.data.todoList.todos[0].text).toEqual( - 'This one was created with a mutation.', - ); - }); }); it('two array insert like mutations', () => { From 5608d50c0e7ee9e65639f47a10e98affc394259b Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 07:34:01 -0700 Subject: [PATCH 07/12] flatten test "two array insert like mutations" --- .../apollo-client/src/__tests__/optimistic.ts | 141 +++++++++--------- 1 file changed, 69 insertions(+), 72 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index 508ebaf3304..6eda81f5870 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -847,10 +847,10 @@ describe('optimistic mutation results', () => { }); - it('two array insert like mutations', () => { + it('two array insert like mutations', async () => { expect.assertions(9); let subscriptionHandle: Subscription; - return setup( + await setup( { request: { query: mutation }, result: mutationResult, @@ -861,86 +861,83 @@ describe('optimistic mutation results', () => { delay: 50, }, ) - .then(() => { - // we have to actually subscribe to the query to be able to update it - return new Promise(resolve => { - const handle = client.watchQuery({ query }); - subscriptionHandle = handle.subscribe({ - next(res) { - resolve(res); - }, - }); - }); - }) - .then(() => { - const updateQueries = { - todoList: (prev, options) => { - const mResult = options.mutationResult; - const state = cloneDeep(prev); - - if (mResult.data) { - state.todoList.todos.unshift(mResult.data.createTodo); - } + // we have to actually subscribe to the query to be able to update it + await new Promise(resolve => { + const handle = client.watchQuery({ query }); + subscriptionHandle = handle.subscribe({ + next(res) { + resolve(res); + }, + }); + }); - return state; - }, - } as MutationQueryReducersMap; - const promise = client - .mutate({ - mutation, - optimisticResponse, - updateQueries, - }) - .then(res => { - const currentDataInStore = (client.cache as InMemoryCache).extract( - true, - ); - expect( - (currentDataInStore['TodoList5'] as any).todos.length, - ).toEqual(5); - expect((currentDataInStore['Todo99'] as any).text).toEqual( - 'This one was created with a mutation.', - ); - expect((currentDataInStore['Todo66'] as any).text).toEqual( - 'Optimistically generated 2', - ); - return res; - }); + const updateQueries = { + todoList: (prev, options) => { + const mResult = options.mutationResult; - const promise2 = client.mutate({ - mutation, - optimisticResponse: optimisticResponse2, - updateQueries, - }); + const state = cloneDeep(prev); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toEqual(5); - expect((dataInStore['Todo99'] as any).text).toEqual( - 'Optimistically generated', - ); - expect((dataInStore['Todo66'] as any).text).toEqual( - 'Optimistically generated 2', - ); + if (mResult.data) { + state.todoList.todos.unshift(mResult.data.createTodo); + } - return Promise.all([promise, promise2]); - }) - .then(() => { - return client.query({ query }); + return state; + }, + } as MutationQueryReducersMap; + const promise = client + .mutate({ + mutation, + optimisticResponse, + updateQueries, }) - .then((newResult: any) => { - subscriptionHandle.unsubscribe(); - // There should be one more todo item than before - expect(newResult.data.todoList.todos.length).toEqual(5); - - // Since we used `prepend` it should be at the front - expect(newResult.data.todoList.todos[0].text).toEqual( - 'Second mutation.', + .then(res => { + const currentDataInStore = (client.cache as InMemoryCache).extract( + true, ); - expect(newResult.data.todoList.todos[1].text).toEqual( + expect( + (currentDataInStore['TodoList5'] as any).todos.length, + ).toEqual(5); + expect((currentDataInStore['Todo99'] as any).text).toEqual( 'This one was created with a mutation.', ); + expect((currentDataInStore['Todo66'] as any).text).toEqual( + 'Optimistically generated 2', + ); + return res; }); + + const promise2 = client.mutate({ + mutation, + optimisticResponse: optimisticResponse2, + updateQueries, + }); + + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toEqual(5); + expect((dataInStore['Todo99'] as any).text).toEqual( + 'Optimistically generated', + ); + expect((dataInStore['Todo66'] as any).text).toEqual( + 'Optimistically generated 2', + ); + + await Promise.all([promise, promise2]); + + const newResult: any = await client.query({ query }); + + subscriptionHandle.unsubscribe(); + // There should be one more todo item than before + expect(newResult.data.todoList.todos.length).toEqual(5); + + // Since we used `prepend` it should be at the front + expect(newResult.data.todoList.todos[0].text).toEqual( + 'Second mutation.', + ); + expect(newResult.data.todoList.todos[1].text).toEqual( + 'This one was created with a mutation.', + ); + }); it('two mutations, one fails', () => { From 5628446a5c9d770dfe52f545951d3550ba71631b Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 07:35:54 -0700 Subject: [PATCH 08/12] flatten test "two mutations, one fails" --- .../apollo-client/src/__tests__/optimistic.ts | 125 +++++++++--------- 1 file changed, 61 insertions(+), 64 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index 6eda81f5870..b1d492cf277 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -940,10 +940,10 @@ describe('optimistic mutation results', () => { }); - it('two mutations, one fails', () => { + it('two mutations, one fails', async () => { expect.assertions(10); let subscriptionHandle: Subscription; - return setup( + await setup( { request: { query: mutation }, error: new Error('forbidden (test error)'), @@ -960,76 +960,73 @@ describe('optimistic mutation results', () => { // delay: 50, }, ) - .then(() => { - // we have to actually subscribe to the query to be able to update it - return new Promise(resolve => { - const handle = client.watchQuery({ query }); - subscriptionHandle = handle.subscribe({ - next(res) { - resolve(res); - }, - }); - }); - }) - .then(() => { - const updateQueries = { - todoList: (prev, options) => { - const mResult = options.mutationResult; - - const state = cloneDeep(prev); - if (mResult.data) { - state.todoList.todos.unshift(mResult.data.createTodo); - } + // we have to actually subscribe to the query to be able to update it + await new Promise(resolve => { + const handle = client.watchQuery({ query }); + subscriptionHandle = handle.subscribe({ + next(res) { + resolve(res); + }, + }); + }); - return state; - }, - } as MutationQueryReducersMap; - const promise = client - .mutate({ - mutation, - optimisticResponse, - updateQueries, - }) - .catch(err => { - // it is ok to fail here - expect(err).toBeInstanceOf(Error); - expect(err.message).toEqual( - 'Network error: forbidden (test error)', - ); - return null; - }); + const updateQueries = { + todoList: (prev, options) => { + const mResult = options.mutationResult; - const promise2 = client.mutate({ - mutation, - optimisticResponse: optimisticResponse2, - updateQueries, - }); + const state = cloneDeep(prev); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toEqual(5); - expect((dataInStore['Todo99'] as any).text).toEqual( - 'Optimistically generated', - ); - expect((dataInStore['Todo66'] as any).text).toEqual( - 'Optimistically generated 2', - ); + if (mResult.data) { + state.todoList.todos.unshift(mResult.data.createTodo); + } - return Promise.all([promise, promise2]); + return state; + }, + } as MutationQueryReducersMap; + const promise = client + .mutate({ + mutation, + optimisticResponse, + updateQueries, }) - .then(() => { - subscriptionHandle.unsubscribe(); - const dataInStore = (client.cache as InMemoryCache).extract(true); - expect((dataInStore['TodoList5'] as any).todos.length).toEqual(4); - expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); - expect(dataInStore).toHaveProperty('Todo66'); - expect((dataInStore['TodoList5'] as any).todos).toContainEqual( - realIdValue('Todo66', 'Todo'), - ); - expect((dataInStore['TodoList5'] as any).todos).not.toContainEqual( - realIdValue('Todo99', 'Todo'), + .catch(err => { + // it is ok to fail here + expect(err).toBeInstanceOf(Error); + expect(err.message).toEqual( + 'Network error: forbidden (test error)', ); + return null; }); + + const promise2 = client.mutate({ + mutation, + optimisticResponse: optimisticResponse2, + updateQueries, + }); + + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toEqual(5); + expect((dataInStore['Todo99'] as any).text).toEqual( + 'Optimistically generated', + ); + expect((dataInStore['Todo66'] as any).text).toEqual( + 'Optimistically generated 2', + ); + + await Promise.all([promise, promise2]); + + subscriptionHandle.unsubscribe(); + const dataInStore = (client.cache as InMemoryCache).extract(true); + expect((dataInStore['TodoList5'] as any).todos.length).toEqual(4); + expect(stripSymbols(dataInStore)).not.toHaveProperty('Todo99'); + expect(dataInStore).toHaveProperty('Todo66'); + expect((dataInStore['TodoList5'] as any).todos).toContainEqual( + realIdValue('Todo66', 'Todo'), + ); + expect((dataInStore['TodoList5'] as any).todos).not.toContainEqual( + realIdValue('Todo99', 'Todo'), + ); }); it('will handle dependent updates', done => { From fcf3038fd5bf577d2902f2f1abd15bd9998f7dee Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Fri, 20 Jul 2018 11:38:46 -0700 Subject: [PATCH 09/12] WIP fleshing out best practice for flattening QueryObservable tests --- .../apollo-client/src/__tests__/optimistic.ts | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index b1d492cf277..ccee3a67315 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -1,3 +1,5 @@ +import { Observable } from 'rxjs'; +import { take, toArray } from 'rxjs/operators'; import { assign, cloneDeep } from 'lodash'; import { addTypenameToDocument } from 'apollo-utilities'; import { InMemoryCache } from 'apollo-cache-inmemory'; @@ -1029,8 +1031,9 @@ describe('optimistic mutation results', () => { ); }); - it('will handle dependent updates', done => { - expect.assertions(5); + it('will handle dependent updates', async () => { + // expect.assertions(5); + expect.assertions(1); link = mockSingleLink( { request: { query }, @@ -1094,8 +1097,17 @@ describe('optimistic mutation results', () => { }), }); + const createObservable = () => Observable.create(observer => { + client.watchQuery({ query }).subscribe({ + next: value => { + observer.next(stripSymbols(value.data.todoList.todos)) + }, + error: error => observer.error(error) + }) + }) + const defaultTodos = stripSymbols(result.data.todoList.todos); - let count = 0; + /*let count = 0; client.watchQuery({ query }).subscribe({ next: (value: any) => { @@ -1138,25 +1150,29 @@ describe('optimistic mutation results', () => { } }, error: error => done.fail(error), - }); + });*/ - function twoMutations() { - client - .mutate({ - mutation, - optimisticResponse: customOptimisticResponse1, - updateQueries, - }) - .catch(error => done.fail(error)); - client - .mutate({ - mutation, - optimisticResponse: customOptimisticResponse2, - updateQueries, - }) - .catch(error => done.fail(error)); - } + const allValues$ = createObservable().pipe(take(1)); + + await client.mutate({ + mutation, + optimisticResponse: customOptimisticResponse1, + updateQueries, + }) + + await client.mutate({ + mutation, + optimisticResponse: customOptimisticResponse2, + updateQueries, + }) + + // Get an array of all the values [over time] on the queryObservable + const allValues = await allValues$.pipe(toArray()).toPromise(); + expect(allValues).toEqual([ + defaultTodos + ]); + }); }); From 4b92065c4b60e548866829a2c22d736c0a0eeac9 Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Sun, 22 Jul 2018 14:01:21 -0700 Subject: [PATCH 10/12] refactor response stream --- .../apollo-client/src/__tests__/optimistic.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index ccee3a67315..cecc6796c4e 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -1097,7 +1097,7 @@ describe('optimistic mutation results', () => { }), }); - const createObservable = () => Observable.create(observer => { + const createResponse$ = () => Observable.create(observer => { client.watchQuery({ query }).subscribe({ next: value => { observer.next(stripSymbols(value.data.todoList.todos)) @@ -1153,7 +1153,7 @@ describe('optimistic mutation results', () => { });*/ - const allValues$ = createObservable().pipe(take(1)); + const responses$ = createResponse$(); await client.mutate({ mutation, @@ -1167,9 +1167,15 @@ describe('optimistic mutation results', () => { updateQueries, }) - // Get an array of all the values [over time] on the queryObservable - const allValues = await allValues$.pipe(toArray()).toPromise(); - expect(allValues).toEqual([ + // all the responses that happened over time as an array of responses + const responses = await responses$ + .pipe( + take(1), + toArray(), + ) + .toPromise(); + + expect(responses).toEqual([ defaultTodos ]); From e112d6882e9275f0245ecf61ab578e82e95c1a2a Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Sun, 22 Jul 2018 19:29:41 -0700 Subject: [PATCH 11/12] finishes flattening test "will handle dependent updates" --- .../apollo-client/src/__tests__/optimistic.ts | 111 +++++++----------- 1 file changed, 42 insertions(+), 69 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index cecc6796c4e..fea45a78f55 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -1032,7 +1032,6 @@ describe('optimistic mutation results', () => { }); it('will handle dependent updates', async () => { - // expect.assertions(5); expect.assertions(1); link = mockSingleLink( { @@ -1097,88 +1096,62 @@ describe('optimistic mutation results', () => { }), }); - const createResponse$ = () => Observable.create(observer => { - client.watchQuery({ query }).subscribe({ - next: value => { - observer.next(stripSymbols(value.data.todoList.todos)) - }, - error: error => observer.error(error) - }) - }) - - const defaultTodos = stripSymbols(result.data.todoList.todos); - /*let count = 0; - - client.watchQuery({ query }).subscribe({ - next: (value: any) => { - const todos = stripSymbols(value.data.todoList.todos); - switch (count++) { - case 0: - expect(defaultTodos).toEqual(todos); - twoMutations(); - break; - case 1: - expect([ - customOptimisticResponse1.createTodo, - ...defaultTodos, - ]).toEqual(todos); - break; - case 2: - expect([ - customOptimisticResponse2.createTodo, - customOptimisticResponse1.createTodo, - ...defaultTodos, - ]).toEqual(todos); - break; - case 3: - expect([ - customOptimisticResponse2.createTodo, - mutationResult.data.createTodo, - ...defaultTodos, - ]).toEqual(todos); - break; - case 4: - expect([ - mutationResult2.data.createTodo, - mutationResult.data.createTodo, - ...defaultTodos, - ]).toEqual(todos); - done(); - break; - default: - done.fail(new Error('Next should not have been called again.')); - } - }, - error: error => done.fail(error), - });*/ - + // Have to wrap the QueryObservable with an rxjs observable due to bug + // https://github.com/apollographql/apollo-client/issues/3721 + const promise = Observable.create(observer => + client + .watchQuery({ query }) + .subscribe({ + next: value => observer.next(stripSymbols(value.data.todoList.todos)) + }) + ) + .pipe( + take(5), + toArray(), + ) + .toPromise() - const responses$ = createResponse$(); + // Mutations will not trigger a watchQuery with the results of an optimistic response + // if set in the same tick of the event loop. + // https://github.com/apollographql/apollo-client/issues/3723 + await new Promise(setTimeout) - await client.mutate({ + client.mutate({ mutation, optimisticResponse: customOptimisticResponse1, updateQueries, }) - await client.mutate({ + client.mutate({ mutation, optimisticResponse: customOptimisticResponse2, updateQueries, }) - // all the responses that happened over time as an array of responses - const responses = await responses$ - .pipe( - take(1), - toArray(), - ) - .toPromise(); - + const responses = await promise + const defaultTodos = stripSymbols(result.data.todoList.todos); expect(responses).toEqual([ - defaultTodos + defaultTodos, + [ + customOptimisticResponse1.createTodo, + ...defaultTodos, + ], + [ + customOptimisticResponse2.createTodo, + customOptimisticResponse1.createTodo, + ...defaultTodos, + ], + [ + customOptimisticResponse2.createTodo, + mutationResult.data.createTodo, + ...defaultTodos, + ], + [ + mutationResult2.data.createTodo, + mutationResult.data.createTodo, + ...defaultTodos, + ] ]); - }); }); From 7cbd3d269e404b576bdc70496694b0487840bdc8 Mon Sep 17 00:00:00 2001 From: Josh Ribakoff Date: Tue, 24 Jul 2018 17:29:01 -0700 Subject: [PATCH 12/12] uses from operator --- .../apollo-client/src/__tests__/optimistic.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/apollo-client/src/__tests__/optimistic.ts b/packages/apollo-client/src/__tests__/optimistic.ts index fea45a78f55..094671f60f4 100644 --- a/packages/apollo-client/src/__tests__/optimistic.ts +++ b/packages/apollo-client/src/__tests__/optimistic.ts @@ -1,5 +1,5 @@ -import { Observable } from 'rxjs'; -import { take, toArray } from 'rxjs/operators'; +import { from } from 'rxjs'; +import { take, toArray, map } from 'rxjs/operators'; import { assign, cloneDeep } from 'lodash'; import { addTypenameToDocument } from 'apollo-utilities'; import { InMemoryCache } from 'apollo-cache-inmemory'; @@ -1096,16 +1096,10 @@ describe('optimistic mutation results', () => { }), }); - // Have to wrap the QueryObservable with an rxjs observable due to bug - // https://github.com/apollographql/apollo-client/issues/3721 - const promise = Observable.create(observer => - client - .watchQuery({ query }) - .subscribe({ - next: value => observer.next(stripSymbols(value.data.todoList.todos)) - }) - ) + // wrap the QueryObservable with an rxjs observable + const promise = from(client.watchQuery({ query })) .pipe( + map(value => stripSymbols(value.data.todoList.todos)), take(5), toArray(), )