Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(utils): Add unit tests for HTTP utilities. #177

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ const JEST_CONFIG: Config = {
functions: 100,
lines: 100,
},
"src/utils/http.ts": {
branches: 100,
functions: 100,
lines: 100,
},
"src/utils/math.ts": {
branches: 100,
functions: 100,
Expand Down
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^7.1.2",
"eslint-config-yscope": "latest",
"html-webpack-plugin": "^5.6.3",
"globals": "^15.14.0",
"html-webpack-plugin": "^5.6.3",
"http-status-codes": "^2.3.0",
"jest": "^29.7.0",
"mini-css-extract-plugin": "^2.9.2",
"jest-environment-jsdom": "^29.7.0",
"mini-css-extract-plugin": "^2.9.2",
"monaco-editor-webpack-plugin": "^7.1.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.4.2",
Expand Down
5 changes: 4 additions & 1 deletion src/utils/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,7 @@ const getUint8ArrayFrom = async (fileUrl: string)
};


export {getUint8ArrayFrom};
export {
convertAxiosError,
getUint8ArrayFrom,
};
102 changes: 102 additions & 0 deletions test/utils/http.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import axios, {AxiosError} from "axios";
import {
getReasonPhrase,
StatusCodes,
} from "http-status-codes";

import {
convertAxiosError,
getUint8ArrayFrom,
} from "../../src/utils/http";


const HTTP_BIN_ENDPOINT_BASE = "https://cloud.yscope.com/httpbin";

describe("getUint8ArrayFrom", () => {
it(
"should fetch a file and return a Uint8Array",
async () => {
const myString = "hello";
const myDataArray = new TextEncoder().encode(myString);
const url = `${HTTP_BIN_ENDPOINT_BASE}/base64/${btoa(myString)}`;

const result = await getUint8ArrayFrom(url);
expect(result).toEqual(myDataArray);
}
);
});

describe("Invalid HTTP sources", () => {
it(
"should cause a custom error to be thrown when the HTTP request is not successful",
async () => {
const url = `${HTTP_BIN_ENDPOINT_BASE}/status/${StatusCodes.NOT_FOUND}`;
await expect(getUint8ArrayFrom(url)).rejects.toMatchObject({
message: `Request failed with status code ${StatusCodes.NOT_FOUND}`,
cause: {
url: url,
},
});
}
);

it("should cause a TypeError to be thrown when the URL is invalid", async () => {
const url = "/";
await expect(() => getUint8ArrayFrom(url)).rejects.toThrow({
name: "TypeError",
message: "Invalid URL",
});
});
});

describe("convertAxiosError", () => {
it("should handle errors with a response available", async () => {
const url = `${HTTP_BIN_ENDPOINT_BASE}/status/${StatusCodes.NOT_FOUND}`;
const expectedCode = "ERR_BAD_REQUEST";
const expectedStatus = StatusCodes.NOT_FOUND;
const expectedStatusText = getReasonPhrase(expectedStatus).toUpperCase();
const expectedBody = "";

try {
// Access a 404 route.
await axios.get(url);
} catch (e) {
const error = convertAxiosError(e as AxiosError);
expect(error.cause).toEqual({
url: url,
code: expectedCode,
details: `get returned ${expectedStatus}(${expectedStatusText}): ${expectedBody}`,
});
}
});

it("should handle errors with no response available", async () => {
const url = "http://127.0.0.1:9";
const expectedCode = "ECONNREFUSED";

try {
// Access the Discard server.
await axios.get(url);
} catch (e) {
const error = convertAxiosError(e as AxiosError);
expect(error.cause).toEqual({
url: url,
code: expectedCode,
details: `get ${url} failed with no response: ${expectedCode}`,
});
}
});

it("should handle errors with certain properties missing", () => {
const expectedUrl = "UNKNOWN URL";
const expectedCode = "UNKNOWN CODE";

const error = convertAxiosError(new AxiosError(""));
expect(error.message).toBe(`${AxiosError.name}: ${expectedCode}`);
expect(error.cause).toEqual({
url: expectedUrl,
code: expectedCode,
details: `UNKNOWN METHOD ${expectedUrl} failed with no response: ${expectedCode}`,
});
});
});