Skip to content

Commit

Permalink
fix: Add minimal validation to config
Browse files Browse the repository at this point in the history
  • Loading branch information
neet committed May 4, 2024
1 parent bf2450e commit 99cd6d1
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 3 deletions.
24 changes: 24 additions & 0 deletions src/adapters/config/http-config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
import { MastoInvalidArgumentError } from "../errors";
import { SerializerNativeImpl } from "../serializers";
import { HttpConfigImpl } from "./http-config";

describe("Config", () => {
it("throws invalid argument error when url is not specified", () => {
expect(() => {
new HttpConfigImpl(
{
url: "",
},
new SerializerNativeImpl(),
);
}).toThrowError(MastoInvalidArgumentError);
});

it("throws invalid argument error when timeout is less than zero", () => {
expect(() => {
new HttpConfigImpl(
{
url: "https://example.com",
timeout: -1,
},
new SerializerNativeImpl(),
);
}).toThrowError(MastoInvalidArgumentError);
});

it("creates header", () => {
const config = new HttpConfigImpl(
{
Expand Down
16 changes: 15 additions & 1 deletion src/adapters/config/http-config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { type HttpConfig, type Serializer } from "../../interfaces";
import { MastoInvalidArgumentError } from "../errors";
import { mergeAbortSignals } from "./merge-abort-signals";
import { mergeHeadersInit } from "./merge-headers-init";
import { isPositiveInteger, isURL } from "./validators";

export interface MastoHttpConfigProps {
/**
Expand Down Expand Up @@ -34,7 +36,19 @@ export class HttpConfigImpl implements HttpConfig {
constructor(
private readonly props: MastoHttpConfigProps,
private readonly serializer: Serializer,
) {}
) {
if (!isURL(this.props.url)) {
throw new MastoInvalidArgumentError("url is required");

Check warning on line 41 in src/adapters/config/http-config.ts

View check run for this annotation

Codecov / codecov/patch

src/adapters/config/http-config.ts#L41

Added line #L41 was not covered by tests
}
if (
this.props.timeout != undefined &&
!isPositiveInteger(this.props.timeout)

Check warning on line 45 in src/adapters/config/http-config.ts

View check run for this annotation

Codecov / codecov/patch

src/adapters/config/http-config.ts#L45

Added line #L45 was not covered by tests
) {
throw new MastoInvalidArgumentError(

Check warning on line 47 in src/adapters/config/http-config.ts

View check run for this annotation

Codecov / codecov/patch

src/adapters/config/http-config.ts#L47

Added line #L47 was not covered by tests
"timeout must be greater than or equal to zero",
);
}
}

mergeRequestInitWithDefaults(override: RequestInit = {}): RequestInit {
const requestInit: RequestInit = { ...this.props.requestInit };
Expand Down
40 changes: 40 additions & 0 deletions src/adapters/config/validators.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { isPositiveInteger, isURL } from "./validators";

describe("isURL", () => {
it("validates if the URL is valid", () => {
const res = isURL("https://example.com");
expect(res).toBe(true);
});

it("returns false if the URL is invalid", () => {
const res = isURL("example.com");
expect(res).toBe(false);
});

it("returns false if the URL is empty", () => {
const res = isURL("");
expect(res).toBe(false);
});
});

describe("isPositiveInteger", () => {
it("validates if the number is a positive integer", () => {
const res = isPositiveInteger(1);
expect(res).toBe(true);
});

it("returns false if the number is not a positive integer", () => {
const res = isPositiveInteger(1.1);
expect(res).toBe(false);
});

it("returns false if the number is negative", () => {
const res = isPositiveInteger(-1);
expect(res).toBe(false);
});

it("returns false if the number is zero", () => {
const res = isPositiveInteger(0);
expect(res).toBe(false);
});
});
12 changes: 12 additions & 0 deletions src/adapters/config/validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const isPositiveInteger = (value: number): boolean => {
return value > 0 && value % 1 === 0;
};

export const isURL = (value: string): boolean => {
try {
new URL(value);
return true;
} catch {
return false;

Check warning on line 10 in src/adapters/config/validators.ts

View check run for this annotation

Codecov / codecov/patch

src/adapters/config/validators.ts#L10

Added line #L10 was not covered by tests
}
};
36 changes: 36 additions & 0 deletions src/adapters/config/web-socket-config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
import { MastoInvalidArgumentError } from "../errors";
import { SerializerNativeImpl } from "../serializers";
import { WebSocketConfigImpl } from "./web-socket-config";

describe("WebSocketConfigImpl", () => {
it("throws invalid argument error when url is not specified", () => {
expect(() => {
new WebSocketConfigImpl(
{
streamingApiUrl: "",
},
new SerializerNativeImpl(),
);
}).toThrowError(MastoInvalidArgumentError);
});

it("throws invalid argument error when retry is less than zero", () => {
expect(() => {
new WebSocketConfigImpl(
{
streamingApiUrl: "wss://mastodon.social",
retry: -1,
},
new SerializerNativeImpl(),
);
}).toThrowError(MastoInvalidArgumentError);
});

it("throws invalid argument error when retry is not an integer", () => {
expect(() => {
new WebSocketConfigImpl(
{
streamingApiUrl: "wss://mastodon.social",
retry: 1.5,
},
new SerializerNativeImpl(),
);
}).toThrowError(MastoInvalidArgumentError);
});

it("resolves WS path with path", () => {
const config = new WebSocketConfigImpl(
{
Expand Down
14 changes: 13 additions & 1 deletion src/adapters/config/web-socket-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { type Serializer, type WebSocketConfig } from "../../interfaces";
import { MastoInvalidArgumentError } from "../errors";
import { isPositiveInteger, isURL } from "./validators";

export interface WebSocketConfigProps {
/**
Expand Down Expand Up @@ -57,7 +59,17 @@ export class WebSocketConfigImpl implements WebSocketConfig {
constructor(
private readonly props: WebSocketConfigProps,
private readonly serializer: Serializer,
) {}
) {
if (!isURL(this.props.streamingApiUrl)) {
throw new MastoInvalidArgumentError(`streamingApiUrl is required`);

Check warning on line 64 in src/adapters/config/web-socket-config.ts

View check run for this annotation

Codecov / codecov/patch

src/adapters/config/web-socket-config.ts#L64

Added line #L64 was not covered by tests
}
if (
typeof this.props.retry === "number" &&
!isPositiveInteger(this.props.retry)

Check warning on line 68 in src/adapters/config/web-socket-config.ts

View check run for this annotation

Codecov / codecov/patch

src/adapters/config/web-socket-config.ts#L68

Added line #L68 was not covered by tests
) {
throw new MastoInvalidArgumentError("retry must be a positive integer");

Check warning on line 70 in src/adapters/config/web-socket-config.ts

View check run for this annotation

Codecov / codecov/patch

src/adapters/config/web-socket-config.ts#L70

Added line #L70 was not covered by tests
}
}

getProtocols(protocols: readonly string[] = []): string[] {
if (
Expand Down
2 changes: 1 addition & 1 deletion src/adapters/http/http-native-impl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe("HttpNativeImpl", () => {
new HttpConfigImpl(
{
url: "https://example.com",
timeout: 0,
timeout: 1,
},
serializer,
),
Expand Down

0 comments on commit 99cd6d1

Please sign in to comment.