Skip to content

Commit

Permalink
Add error handling for fetchApi helper
Browse files Browse the repository at this point in the history
  • Loading branch information
ruchernchong committed Oct 16, 2024
1 parent 583018e commit ceabae9
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 12 deletions.
55 changes: 52 additions & 3 deletions utils/fetchApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,64 @@ import fetch from "jest-fetch-mock";
import { fetchApi } from "@/utils/fetchApi";

describe("fetchApi", () => {
beforeEach(() => fetch.resetMocks());
beforeEach(() => {
fetch.resetMocks();
});

it("should return data for a successful API call", async () => {
fetch.mockResponseOnce(JSON.stringify({ data: "test" }));
const mockResponse = { data: "test" };
fetch.mockResponseOnce(JSON.stringify(mockResponse));

const url = "https://example.com/api/test";
const data = await fetchApi(url);

expect(fetch).toHaveBeenCalledTimes(1);
expect(data).toEqual({ data: "test" });
expect(fetch).toHaveBeenCalledWith(url, {
cache: "no-store",
headers: {
Authorization: `Bearer ${process.env.SG_CARS_TRENDS_API_TOKEN}`,
},
});
expect(data).toEqual(mockResponse);
});

it("should throw an error for a non-OK response", async () => {
const errorBody = "Error occurred";
fetch.mockResponseOnce(errorBody, { status: 404, statusText: "Not Found" });

const url = "https://example.com/api/test";
await expect(fetchApi(url)).rejects.toThrow(
`API call failed: ${url} - 404 - Not Found`,
);
});

it("should merge custom options with default options", async () => {
fetch.mockResponseOnce(JSON.stringify({ data: "test" }));

const url = "https://example.com/api/test";
const customOptions = {
method: "POST",
headers: {
"Custom-Header": "CustomValue",
},
};

await fetchApi(url, customOptions);

expect(fetch).toHaveBeenCalledWith(url, {
method: "POST",
cache: "no-store",
headers: {
Authorization: `Bearer ${process.env.SG_CARS_TRENDS_API_TOKEN}`,
"Custom-Header": "CustomValue",
},
});
});

it("should handle network errors", async () => {
fetch.mockReject(new Error("Network error"));

const url = "https://example.com/api/test";
await expect(fetchApi(url)).rejects.toThrow("Network error");
});
});
32 changes: 23 additions & 9 deletions utils/fetchApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,35 @@ export const fetchApi = async <T>(
url: string,
options: RequestInit = {},
): Promise<T> => {
options = {
...options,
const defaultOptions: RequestInit = {
// TODO: Remove this later
cache: "no-store",
headers: {
Authorization: `Bearer ${process.env.SG_CARS_TRENDS_API_TOKEN}`,
},
};
const response = await fetch(url, options);

if (!response.ok) {
throw new Error(
`API call failed: ${url} - ${response.status} - ${response.statusText}`,
);
}
const mergedOptions: RequestInit = {
...defaultOptions,
...options,
headers: {
...defaultOptions.headers,
...options.headers,
},
};

try {
const response = await fetch(url, mergedOptions);

return response.json();
if (!response.ok) {
throw new Error(
`API call failed: ${url} - ${response.status} - ${response.statusText}`,
);
}

return response.json();
} catch (e) {
console.error(e.message);
throw e;
}
};

0 comments on commit ceabae9

Please sign in to comment.