Skip to content

Commit

Permalink
feat: handy interface getOption to transform all accepted types
Browse files Browse the repository at this point in the history
  • Loading branch information
moontai0724 committed Oct 7, 2024
1 parent 2da08a9 commit 432082d
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "@/calculator";
export * from "./transformers";
105 changes: 105 additions & 0 deletions src/transformers/get-option.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Type } from "@sinclair/typebox";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { Options } from "yargs";

const getArrayOption = vi.fn().mockReturnValue({ type: "mocked" });
const getBooleanOption = vi.fn().mockReturnValue({ type: "mocked" });
const getNumberOption = vi.fn().mockReturnValue({ type: "mocked" });
const getStringOption = vi.fn().mockReturnValue({ type: "mocked" });

let component: typeof import("./get-option");

beforeAll(async () => {
vi.doMock("./array", () => ({ getArrayOption }));
vi.doMock("./boolean", () => ({ getBooleanOption }));
vi.doMock("./number", () => ({ getNumberOption }));
vi.doMock("./string", () => ({ getStringOption }));
component = await import("./get-option");
});

beforeEach(() => {
vi.clearAllMocks();
});

describe("array", () => {
it("should pass schema to array transformer", () => {
const schema = Type.Array(Type.Unknown());
const result = component.getOption(schema);
expect(getArrayOption).toBeCalledWith(schema, {});
expect(result).toEqual({ type: "mocked" });
});

it("should pass override to array transformer", () => {
const schema = Type.Array(Type.Unknown());
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(getArrayOption).toBeCalledWith(schema, override);
expect(result).toEqual({ type: "mocked", alias: "aliased" });
});
});

describe("boolean", () => {
it("should pass schema to boolean transformer", () => {
const schema = Type.Boolean();
const result = component.getOption(schema);
expect(getBooleanOption).toBeCalledWith(schema, {});
expect(result).toEqual({ type: "mocked" });
});

it("should pass override to boolean transformer", () => {
const schema = Type.Boolean();
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(getBooleanOption).toBeCalledWith(schema, override);
expect(result).toEqual({ type: "mocked", alias: "aliased" });
});
});

describe("number", () => {
it("should pass schema to number transformer", () => {
const schema = Type.Number();
const result = component.getOption(schema);
expect(getNumberOption).toBeCalledWith(schema, {});
expect(result).toEqual({ type: "mocked" });
});

it("should pass override to number transformer", () => {
const schema = Type.Number();
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(getNumberOption).toBeCalledWith(schema, override);
expect(result).toEqual({ type: "mocked", alias: "aliased" });
});
});

describe("string", () => {
it("should pass schema to string transformer", () => {
const schema = Type.String();
const result = component.getOption(schema);
expect(getStringOption).toBeCalledWith(schema, {});
expect(result).toEqual({ type: "mocked" });
});

it("should pass override to string transformer", () => {
const schema = Type.String();
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(getStringOption).toBeCalledWith(schema, override);
expect(result).toEqual({ type: "mocked", alias: "aliased" });
});
});

describe("unaccepted type", () => {
it("should return empty object when type is not supported", () => {
const schema = Type.BigInt();
const result = component.getOption(schema);
expect(result).toEqual({});
});

it("should still be able to override", () => {
const schema = Type.BigInt();
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(result).toEqual({ alias: "aliased" });
});
});
22 changes: 22 additions & 0 deletions src/transformers/get-option.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { type TSchema, TypeGuard } from "@sinclair/typebox";
import type { Options } from "yargs";

import { getArrayOption } from "./array";
import { getBooleanOption } from "./boolean";
import { getNumberOption } from "./number";
import { getStringOption } from "./string";

export function getOption(schema: TSchema, override: Options = {}) {
const option: Options = (() => {
if (TypeGuard.IsNumber(schema)) return getNumberOption(schema, override);
if (TypeGuard.IsString(schema)) return getStringOption(schema, override);
if (TypeGuard.IsBoolean(schema)) return getBooleanOption(schema, override);
if (TypeGuard.IsArray(schema)) return getArrayOption(schema, override);

return {};
})();

Object.assign(option, override);

return option;
}
5 changes: 5 additions & 0 deletions src/transformers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from "./array";
export * from "./boolean";
export * from "./get-option";
export * from "./number";
export * from "./string";
104 changes: 104 additions & 0 deletions tests/get-option.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Type } from "@sinclair/typebox";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { Options } from "yargs";

let component: typeof import("@/index");

beforeAll(async () => {
component = await import("@/index");
});

beforeEach(() => {
vi.clearAllMocks();
});

describe("array", () => {
it("should pass schema to array transformer", () => {
const schema = Type.Array(Type.String());
const result = component.getOption(schema);
expect(result).toEqual({ type: "array", requiresArg: true });
});

it("should pass override to array transformer", () => {
const schema = Type.Array(Type.String());
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(result).toEqual({
type: "array",
requiresArg: true,
alias: "aliased",
});
});
});

describe("boolean", () => {
it("should pass schema to boolean transformer", () => {
const schema = Type.Boolean();
const result = component.getOption(schema);
expect(result).toEqual({ type: "boolean", requiresArg: true });
});

it("should pass override to boolean transformer", () => {
const schema = Type.Boolean();
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(result).toEqual({
type: "boolean",
requiresArg: true,
alias: "aliased",
});
});
});

describe("number", () => {
it("should pass schema to number transformer", () => {
const schema = Type.Number();
const result = component.getOption(schema);
expect(result).toEqual({ type: "number", requiresArg: true });
});

it("should pass override to number transformer", () => {
const schema = Type.Number();
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(result).toEqual({
type: "number",
requiresArg: true,
alias: "aliased",
});
});
});

describe("string", () => {
it("should pass schema to string transformer", () => {
const schema = Type.String();
const result = component.getOption(schema);
expect(result).toEqual({ type: "string", requiresArg: true });
});

it("should pass override to string transformer", () => {
const schema = Type.String();
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(result).toEqual({
type: "string",
requiresArg: true,
alias: "aliased",
});
});
});

describe("unaccepted type", () => {
it("should return empty object when type is not supported", () => {
const schema = Type.BigInt();
const result = component.getOption(schema);
expect(result).toEqual({});
});

it("should still be able to override", () => {
const schema = Type.BigInt();
const override: Options = { alias: "aliased" };
const result = component.getOption(schema, override);
expect(result).toEqual({ alias: "aliased" });
});
});

0 comments on commit 432082d

Please sign in to comment.