Repository: googlemaps/google-maps-services-js (ts)

Issue:
Support Custom Axios Instance on Client Class
this makes a custom axios instance with retries as in #326 a bit easier at the class level

Pull request description:
feat: support passing custom AxiosInstance to client
closes #342

Patch:
diff --git a/src/client.ts b/src/client.ts
index 41e698336..7776f946d 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -81,6 +81,9 @@ const defaultConfig = {
 export const defaultAxiosInstance = axios.create(defaultConfig);
 
 export interface ClientOptions {
+  /** AxiosInstance to be used by client. Provide one of axiosInstance or config. */
+  axiosInstance?: AxiosInstance;
+  /** Config used to create AxiosInstance. Provide one of axiosInstance or config. */
   config?: AxiosRequestConfig;
   experienceId?: string[];
 }
@@ -89,8 +92,16 @@ export class Client {
   private axiosInstance: AxiosInstance;
   private experienceId: string[];
 
-  constructor({ config, experienceId }: ClientOptions) {
-    if (config) {
+  constructor({ axiosInstance, config, experienceId }: ClientOptions) {
+    if (axiosInstance && config) {
+      throw new Error("Provide one of axiosInstance or config.");
+    }
+
+    if (axiosInstance) {
+      this.axiosInstance = axiosInstance;
+      // Avoid changing this instance in any way that affects its behavior
+      this.axiosInstance.defaults.headers["User-Agent"] = userAgent;
+    } else if (config) {
       this.axiosInstance = axios.create(merge(defaultConfig, config));
     } else {
       this.axiosInstance = defaultAxiosInstance;


Test patch:
diff --git a/src/client.test.ts b/src/client.test.ts
index e137933c4..759c9fc24 100644
--- a/src/client.test.ts
+++ b/src/client.test.ts
@@ -17,14 +17,41 @@ import {
   TextSearchRequest,
   NearestRoadsRequest,
   SnapToRoadsRequest,
-  X_GOOG_MAPS_EXPERIENCE_ID
+  X_GOOG_MAPS_EXPERIENCE_ID,
+  defaultAxiosInstance
 } from "./client";
 
+import axios from "axios";
+
 test("client can be instantiated", () => {
   const client = new Client({});
   expect(client["axiosInstance"]).toBeDefined();
 });
 
+test("client can be instantiated with axiosInstance", () => {
+  const client = new Client({ axiosInstance: axios.create({}) });
+  expect(client["axiosInstance"]).toBeDefined();
+});
+
+test("client can be instantiated with axiosInstance has correct defaults", () => {
+  const client = new Client({ axiosInstance: axios.create({}) });
+  expect(client["axiosInstance"].defaults.headers["User-Agent"]).toEqual(
+    userAgent
+  );
+  expect(client["axiosInstance"].defaults.timeout).toEqual(
+    axios.defaults.timeout
+  );
+});
+
+test("client instantiated with custom instance and config throws error", () => {
+  expect(() => {
+    new Client({
+      axiosInstance: defaultAxiosInstance,
+      config: { timeout: 10000 }
+    });
+  }).toThrowError();
+});
+
 test("client can be instantiated with header options", () => {
   const client = new Client({ config: { headers: { "x-foo": "bar" } } });
   expect(client["axiosInstance"]).toBeDefined();