diff options
Diffstat (limited to 'spec/frontend/lib/utils/apollo_startup_js_link_spec.js')
-rw-r--r-- | spec/frontend/lib/utils/apollo_startup_js_link_spec.js | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/spec/frontend/lib/utils/apollo_startup_js_link_spec.js b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js new file mode 100644 index 00000000000..faead3ff8fe --- /dev/null +++ b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js @@ -0,0 +1,375 @@ +import { ApolloLink, Observable } from 'apollo-link'; +import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link'; + +describe('StartupJSLink', () => { + const FORWARDED_RESPONSE = { data: 'FORWARDED_RESPONSE' }; + + const STARTUP_JS_RESPONSE = { data: 'STARTUP_JS_RESPONSE' }; + const OPERATION_NAME = 'startupJSQuery'; + const STARTUP_JS_QUERY = `query ${OPERATION_NAME}($id: Int = 3){ + name + id + }`; + + const STARTUP_JS_RESPONSE_TWO = { data: 'STARTUP_JS_RESPONSE_TWO' }; + const OPERATION_NAME_TWO = 'startupJSQueryTwo'; + const STARTUP_JS_QUERY_TWO = `query ${OPERATION_NAME_TWO}($id: Int = 3){ + id + name + }`; + + const ERROR_RESPONSE = { + data: { + user: null, + }, + errors: [ + { + path: ['user'], + locations: [{ line: 2, column: 3 }], + extensions: { + message: 'Object not found', + type: 2, + }, + }, + ], + }; + + let startupLink; + let link; + + function mockFetchCall(status = 200, response = STARTUP_JS_RESPONSE) { + const p = { + ok: status >= 200 && status < 300, + status, + headers: new Headers({ 'Content-Type': 'application/json' }), + statusText: `MOCK-FETCH ${status}`, + clone: () => p, + json: () => Promise.resolve(response), + }; + return Promise.resolve(p); + } + + function mockOperation({ operationName = OPERATION_NAME, variables = { id: 3 } } = {}) { + return { operationName, variables, setContext: () => {} }; + } + + const setupLink = () => { + startupLink = new StartupJSLink(); + link = ApolloLink.from([startupLink, new ApolloLink(() => Observable.of(FORWARDED_RESPONSE))]); + }; + + it('forwards requests if no calls are set up', done => { + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls).toBe(null); + expect(startupLink.request).toEqual(StartupJSLink.noopRequest); + done(); + }); + }); + + it('forwards requests if the operation is not pre-loaded', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ operationName: 'notLoaded' })).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(1); + done(); + }); + }); + + describe('variable match errors: ', () => { + it('forwards requests if the variables are not matching', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 'NOT_MATCHING' }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards requests if more variables are set in the operation', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards requests if less variables are set in the operation', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3, name: 'tanuki' }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { id: 3 } })).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards requests if different variables are set', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { name: 'tanuki' }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { id: 3 } })).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards requests if array variables have a different order', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: [3, 4] }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { id: [4, 3] } })).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + }); + + describe('error handling', () => { + it('forwards the call if the fetchCall is failing with a HTTP Error', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(404), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards the call if it errors (e.g. failing JSON)', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: Promise.reject(new Error('Parsing failed')), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards the call if the response contains an error', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(200, ERROR_RESPONSE), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it("forwards the call if the response doesn't contain a data object", done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(200, { 'no-data': 'yay' }), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + }); + + it('resolves the request if the operation is matching', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('resolves the request exactly once', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + link.request(mockOperation()).subscribe(result2 => { + expect(result2).toEqual(FORWARDED_RESPONSE); + done(); + }); + }); + }); + + it('resolves the request if the variables have a different order', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3, name: 'foo' }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { name: 'foo', id: 3 } })).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('resolves the request if the variables have undefined values', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { name: 'foo' }, + }, + ], + }; + setupLink(); + link + .request(mockOperation({ variables: { name: 'foo', undef: undefined } })) + .subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('resolves the request if the variables are of an array format', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: [3, 4] }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { id: [3, 4] } })).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('resolves multiple requests correctly', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + { + fetchCall: mockFetchCall(200, STARTUP_JS_RESPONSE_TWO), + query: STARTUP_JS_QUERY_TWO, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ operationName: OPERATION_NAME_TWO })).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE_TWO); + expect(startupLink.startupCalls.size).toBe(1); + link.request(mockOperation({ operationName: OPERATION_NAME })).subscribe(result2 => { + expect(result2).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + }); +}); |