Skip to content

Commit

Permalink
#2 Adding remaining tests to achieve full code co…
Browse files Browse the repository at this point in the history
…verage, also fixed one bug exposed by that.
  • Loading branch information
stazz committed Sep 8, 2023
1 parent 9e45889 commit 98f3557
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 7 deletions.
82 changes: 79 additions & 3 deletions code/client/src/__test__/client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type * as net from "node:net";

import * as spec from "../client";
import * as errors from "../errors";
import * as internal from "../internal";

test("Verify that raw string variant works", async (c) => {
c.plan(2);
Expand Down Expand Up @@ -123,6 +124,84 @@ test("Test that config-based callback works with complex usecase", async (c) =>
});
});

test("Test that non-2xx status code in is handled correctly", async (c) => {
c.plan(1);

const statusCode = 404;
const { callback } = await prepareForTest([statusCode]);

await c.throwsAsync(
async () => await callback({ method: "GET", url: "/hello" }),
{
instanceOf: errors.Non2xxStatusCodeError,
message: `Status code ${statusCode} was returned.`,
},
);
});

test("Test that using tricky path names will be handled correctly", async (c: ExecutionContext) => {
c.plan(2);
const { callback, capturedInfo, ...settings } = await prepareForTest();

const method = "GET";
const result = await callback({
method,
url: "/hello/?injected-query-#-and-fragment/",
});
const url = "/hello/%3Finjected-query-%23-and-fragment/";
c.deepEqual(capturedInfo, [
{
method,
url,
body: undefined,
headers: getExpectedServerIncomingHeaders({
...settings,
method,
path: url,
scheme: "http",
}),
},
]);
c.deepEqual(result, {
body: undefined,
headers: getExpectedClientIncomingHeaders(),
});
});

test("Validate that URL sanity check works", async (c) => {
c.plan(4);
const { callback, capturedInfo, ...settings } = await prepareForTest();

const verifyURLSanity = async (clientURL: string, serverURL: string) => {
capturedInfo.length = 0;
const method = "GET";
const result = await callback({
method,
url: clientURL,
});
c.deepEqual(capturedInfo, [
{
method,
url: serverURL,
body: undefined,
headers: getExpectedServerIncomingHeaders({
...settings,
method,
path: serverURL,
scheme: "http",
}),
},
]);
c.deepEqual(result, {
body: undefined,
headers: getExpectedClientIncomingHeaders(),
});
};

await verifyURLSanity(internal.DUMMY_ORIGIN, `/${internal.DUMMY_ORIGIN}`);
await verifyURLSanity("http://example.com", "/http://example.com");
});

const prepareForTest = async (
responses: PreparedServerRespones = [undefined],
) => {
Expand Down Expand Up @@ -227,9 +306,6 @@ const getExpectedServerIncomingHeaders = (
{
host,
port,
scheme,
method,
path,
}: Pick<Awaited<ReturnType<typeof prepareForTest>>, "host" | "port"> & {
path: string;
method: string;
Expand Down
12 changes: 12 additions & 0 deletions code/client/src/__test__/errors.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* @file This file contains tests for file `../errors.ts`.
*/

import test from "ava";
import * as spec from "../errors";

test("Validate that isNon2xxStatusCodeError method works", (c) => {
c.plan(2);
c.true(spec.isNon2xxStatusCodeError(new spec.Non2xxStatusCodeError(999)));
c.false(spec.isNon2xxStatusCodeError(new Error()));
});
9 changes: 5 additions & 4 deletions code/client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import axios, {
AxiosHeaders,
} from "axios";
import * as errors from "./errors";
import * as internal from "./internal";

/**
* This function will create a {@link dataFE.CallHTTPEndpoint} callback using new or given Axios instance.
Expand Down Expand Up @@ -113,17 +114,15 @@ export interface HTTPEndpointCallerOptionsBase {
allowProtoProperty?: boolean;
}

const DUMMY_ORIGIN = "ftp://__dummy__";

const getAxiosArgs = ({
method,
url,
query,
body,
headers,
}: dataFE.HTTPInvocationArguments): AxiosRequestConfig => {
const urlObject = new URL(url, DUMMY_ORIGIN);
if (urlObject.origin !== DUMMY_ORIGIN || urlObject.href === url) {
const urlObject = new URL(url, internal.DUMMY_ORIGIN);
if (urlObject.origin !== internal.DUMMY_ORIGIN || urlObject.origin === url) {
// We were passed an absolute URL -> "escape" it by prepending forward slash so that Axios will always use baseURL
url = `/${url}`;
}
Expand All @@ -143,6 +142,8 @@ const getAxiosArgs = ({
...(query === undefined ? {} : { params: getURLSearchParams(query) }),
...(body === undefined ? {} : { data: JSON.stringify(body) }),
responseType: "text",
// Never throw Axios error based on status code
validateStatus: () => true,
};
};

Expand Down
9 changes: 9 additions & 0 deletions code/client/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @file This is entrypoint file for this package, exporting all non-internal files.
*/

export * from "./client";
export type { Non2xxStatusCodeError } from "./errors";
export { isNon2xxStatusCodeError } from "./errors";

// Don't export anything from internal.ts
5 changes: 5 additions & 0 deletions code/client/src/internal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* @file This file contains internally constants, so that they can be used in tests as well.
*/

export const DUMMY_ORIGIN = "ftp://__dummy__";

0 comments on commit 98f3557

Please sign in to comment.