From 07e2f4c4891e529e1623bd5b96c92635fa9a611f Mon Sep 17 00:00:00 2001 From: Jae Anne Bach Hardie Date: Fri, 12 Oct 2018 10:28:13 +0100 Subject: [PATCH] Added functionality to pass custom fetch to rest data source This is an optional constructor parameter. If a custom fetch function is not defined, the default fetch will be used. This new functionality has been covered in the http cache tests. Co-Authored-By: Jae Anne Bach Hardie --- packages/apollo-datasource-rest/src/HTTPCache.ts | 9 ++++++--- .../apollo-datasource-rest/src/RESTDataSource.ts | 7 ++++++- .../src/__tests__/HTTPCache.test.ts | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/apollo-datasource-rest/src/HTTPCache.ts b/packages/apollo-datasource-rest/src/HTTPCache.ts index 1b7da5e3f96..153cf89c669 100644 --- a/packages/apollo-datasource-rest/src/HTTPCache.ts +++ b/packages/apollo-datasource-rest/src/HTTPCache.ts @@ -6,7 +6,10 @@ import { KeyValueCache, InMemoryLRUCache } from 'apollo-server-caching'; import { CacheOptions } from './RESTDataSource'; export class HTTPCache { - constructor(private keyValueCache: KeyValueCache = new InMemoryLRUCache()) {} + constructor( + private keyValueCache: KeyValueCache = new InMemoryLRUCache(), + private httpFetch: typeof fetch = fetch, + ) {} async fetch( request: Request, @@ -21,7 +24,7 @@ export class HTTPCache { const entry = await this.keyValueCache.get(`httpcache:${cacheKey}`); if (!entry) { - const response = await fetch(request); + const response = await this.httpFetch(request); const policy = new CachePolicy( policyRequestFrom(request), @@ -61,7 +64,7 @@ export class HTTPCache { const revalidationRequest = new Request(request, { headers: revalidationHeaders, }); - const revalidationResponse = await fetch(revalidationRequest); + const revalidationResponse = await this.httpFetch(revalidationRequest); const { policy: revalidatedPolicy, modified } = policy.revalidatedPolicy( policyRequestFrom(revalidationRequest), diff --git a/packages/apollo-datasource-rest/src/RESTDataSource.ts b/packages/apollo-datasource-rest/src/RESTDataSource.ts index 59b068768e6..aa95f80f9dc 100644 --- a/packages/apollo-datasource-rest/src/RESTDataSource.ts +++ b/packages/apollo-datasource-rest/src/RESTDataSource.ts @@ -7,6 +7,7 @@ import { URL, URLSearchParams, URLSearchParamsInit, + fetch, } from 'apollo-server-env'; import { DataSource, DataSourceConfig } from 'apollo-datasource'; @@ -48,9 +49,13 @@ export abstract class RESTDataSource extends DataSource { context!: TContext; memoizedResults = new Map>(); + constructor(private httpFetch?: typeof fetch) { + super(); + } + initialize(config: DataSourceConfig): void { this.context = config.context; - this.httpCache = new HTTPCache(config.cache); + this.httpCache = new HTTPCache(config.cache, this.httpFetch); } baseURL?: string; diff --git a/packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts b/packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts index 3935a667861..72849304ecb 100644 --- a/packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts +++ b/packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts @@ -452,4 +452,18 @@ describe('HTTPCache', () => { expect(await response2.json()).toEqual({ name: 'Alan Turing' }); expect(response2.headers.get('Age')).toEqual('10'); }); + + it('fetches a response from the origin with a custom fetch function', async () => { + fetch.mockJSONResponseOnce({ name: 'Ada Lovelace' }); + + const customFetch = jest.fn(fetch); + const customHttpCache = new HTTPCache(store as any, customFetch); + + const response = await customHttpCache.fetch( + new Request('https://api.example.com/people/1'), + ); + + expect(customFetch.mock.calls.length).toEqual(1); + expect(await response.json()).toEqual({ name: 'Ada Lovelace' }); + }); });