design nosepass template, add tests, add template previews

This commit is contained in:
Amruth Pillai
2023-11-17 08:31:12 +01:00
parent 0b4cb71320
commit 34247f13b6
92 changed files with 24440 additions and 35518 deletions

View File

@ -0,0 +1,162 @@
import { describe, expect, it } from "vitest";
import { findItemInLayout, moveItemInLayout, removeItemInLayout } from "../array";
describe("findItemInLayout", () => {
it("should find the correct location of an item", () => {
const layout = [
[["item1"], ["item2"]],
[["item3"], ["item4"]],
];
const item = "item3";
const expectedLocation = { page: 1, column: 0, section: 0 };
const location = findItemInLayout(item, layout);
expect(location).toEqual(expectedLocation);
});
it("should return null if the item is not found", () => {
const layout = [
[["item1"], ["item2"]],
[["item3"], ["item4"]],
];
const item = "item5";
const location = findItemInLayout(item, layout);
expect(location).toBeNull();
});
});
describe("removeItemInLayout", () => {
it("should remove the item and return its location", () => {
const layout = [
[["item1"], ["item2"]],
[["item3"], ["item4"]],
];
const item = "item3";
const expectedLocation = { page: 1, column: 0, section: 0 };
const location = removeItemInLayout(item, layout);
expect(location).toEqual(expectedLocation);
expect(layout[1][0]).not.toContain(item);
});
it("should return null and not modify layout if the item is not found", () => {
const layout = [
[["item1"], ["item2"]],
[["item3"], ["item4"]],
];
const item = "item5";
const location = removeItemInLayout(item, layout);
expect(location).toBeNull();
expect(layout).toEqual([
[["item1"], ["item2"]],
[["item3"], ["item4"]],
]);
});
});
describe("moveItemInLayout", () => {
it("should move an item from the current location to the target location", () => {
const layout = [
[["item1"], ["item2"]],
[["item3"], ["item4"]],
];
const current = { page: 0, column: 1, section: 0 };
const target = { page: 1, column: 0, section: 1 };
const expectedLayout = [
[["item1"], []],
[["item3", "item2"], ["item4"]],
];
const newLayout = moveItemInLayout(current, target, layout);
expect(newLayout).toEqual(expectedLayout);
});
it("should not mutate the original layout array", () => {
const layout = [
[["item1"], ["item2"]],
[["item3"], ["item4"]],
];
const layoutCopy = JSON.parse(JSON.stringify(layout));
const current = { page: 0, column: 1, section: 0 };
const target = { page: 1, column: 0, section: 1 };
moveItemInLayout(current, target, layout);
expect(layout).toEqual(layoutCopy);
});
it("should handle the case where the current and target locations are the same", () => {
const layout = [
[["item1"], ["item2"]],
[["item3"], ["item4"]],
];
const current = { page: 1, column: 0, section: 0 };
const target = { page: 1, column: 0, section: 0 };
const newLayout = moveItemInLayout(current, target, layout);
expect(newLayout).toEqual(layout);
});
it("moves an item to the specified target location", () => {
const layout = [
[["A", "B"], ["C"]],
[["D"], ["E", "F"]],
];
const current = { page: 0, column: 0, section: 1 };
const target = { page: 1, column: 1, section: 1 };
const result = moveItemInLayout(current, target, layout);
expect(result).toEqual([
[["A"], ["C"]],
[["D"], ["E", "B", "F"]],
]);
});
it("handles moving an item within the same column", () => {
const layout = [[["A", "B"]], [["C", "D"]]];
const current = { page: 0, column: 0, section: 0 };
const target = { page: 0, column: 0, section: 1 };
const result = moveItemInLayout(current, target, layout);
expect(result).toEqual([[["B", "A"]], [["C", "D"]]]);
});
it("handles moving an item to the beginning of a column", () => {
const layout = [[["A"], ["B", "C"]], [["D"]]];
const current = { page: 1, column: 0, section: 0 };
const target = { page: 0, column: 1, section: 0 };
const result = moveItemInLayout(current, target, layout);
expect(result).toEqual([[["A"], ["D", "B", "C"]], [[]]]);
});
it("handles moving an item to an empty column", () => {
const layout = [[["A"], []], [["B"]]];
const current = { page: 0, column: 0, section: 0 };
const target = { page: 0, column: 1, section: 0 };
const result = moveItemInLayout(current, target, layout);
expect(result).toEqual([[[], ["A"]], [["B"]]]);
});
it("returns the same layout if the current location is invalid", () => {
const layout = [[["A"], ["B"]]];
const current = { page: 2, column: 0, section: 0 };
const target = { page: 0, column: 1, section: 0 };
const result = moveItemInLayout(current, target, layout);
expect(result).toEqual(layout);
});
it("returns the same layout if the target location is invalid", () => {
const layout = [[["A"], ["B"]]];
const current = { page: 0, column: 0, section: 0 };
const target = { page: 2, column: 0, section: 0 };
const result = moveItemInLayout(current, target, layout);
expect(result).toEqual(layout);
});
});

View File

@ -0,0 +1,107 @@
import { describe, expect, it } from "vitest";
import { deepSearchAndParseDates, sortByDate } from "../date";
type TestType = { date?: Date };
describe("sortByDate", () => {
it("sorts by date in descending order when desc is true", () => {
const a: TestType = { date: new Date("2023-01-01") };
const b: TestType = { date: new Date("2023-01-02") };
expect(sortByDate(a, b, "date")).toBe(1);
expect(sortByDate(b, a, "date")).toBe(-1);
});
it("sorts by date in ascending order when desc is false", () => {
const a: TestType = { date: new Date("2023-01-01") };
const b: TestType = { date: new Date("2023-01-02") };
expect(sortByDate(a, b, "date", false)).toBe(-1);
expect(sortByDate(b, a, "date", false)).toBe(1);
});
it("returns 0 if one of the dates is missing", () => {
const a: TestType = { date: new Date("2023-01-01") };
const b: TestType = {};
expect(sortByDate(a, b, "date")).toBe(0);
});
it("returns 0 if one of the values is not a date", () => {
const a: TestType = { date: new Date("2023-01-01") };
const b: TestType = { date: "2023-01-02" as unknown as Date };
expect(sortByDate(a, b, "date")).toBe(0);
});
it("handles equal dates", () => {
const a: TestType = { date: new Date("2023-01-01") };
const b: TestType = { date: new Date("2023-01-01") };
expect(sortByDate(a, b, "date")).toBe(0);
expect(sortByDate(a, b, "date", false)).toBe(0);
});
});
describe("deepSearchAndParseDates", () => {
it("parses dates at various nesting levels", () => {
const input = {
level1: {
date: "2021-08-17T00:00:00Z",
nested: {
date: "2022-08-17T00:00:00Z",
},
},
otherKey: "value",
};
const dateKeys = ["date"];
const output = deepSearchAndParseDates(input, dateKeys);
expect(output.level1.date).toBeInstanceOf(Date);
expect(output.level1.nested.date).toBeInstanceOf(Date);
expect(output.otherKey).toBe("value");
});
it("does not parse invalid date strings", () => {
const input = {
date: "not a date",
};
const dateKeys = ["date"];
const output = deepSearchAndParseDates(input, dateKeys);
expect(output.date).toBe("not a date");
});
it("does not modify non-object input", () => {
const input = "2021-08-17T00:00:00Z";
const dateKeys = ["date"];
const output = deepSearchAndParseDates(input, dateKeys);
expect(output).toBe(input);
});
it("returns null for null input", () => {
const input = null;
const dateKeys = ["date"];
const output = deepSearchAndParseDates(input, dateKeys);
expect(output).toBeNull();
});
it("handles arrays with date strings", () => {
const input = ["2021-08-17T00:00:00Z", "2022-08-17"];
const dateKeys = ["0", "1"]; // Assuming the keys are stringified indices
const output = deepSearchAndParseDates(input, dateKeys);
expect(output[0]).toBeInstanceOf(Date);
expect(output[1]).toBeInstanceOf(Date);
});
it("ignores keys that are not in the dateKeys", () => {
const input = {
date: "2021-08-17T00:00:00Z",
notADate: "2021-08-17T00:00:00Z",
};
const dateKeys = ["date"];
const output = deepSearchAndParseDates(input, dateKeys);
expect(output.date).toBeInstanceOf(Date);
expect(output.notADate).toBe("2021-08-17T00:00:00Z");
});
});

View File

@ -0,0 +1,53 @@
import { describe, expect, it } from "vitest";
import { linearTransform } from "../number";
describe("linearTransform", () => {
it("transforms values from one range to another", () => {
const value = 5;
const result = linearTransform(value, 0, 10, 0, 100);
expect(result).toBe(50);
});
it("handles negative ranges", () => {
const value = -5;
const result = linearTransform(value, -10, 0, 0, 100);
expect(result).toBe(50);
});
it("correctly transforms the minimum input value to the minimum output value", () => {
const value = 0;
const result = linearTransform(value, 0, 10, 0, 100);
expect(result).toBe(0);
});
it("correctly transforms the maximum input value to the maximum output value", () => {
const value = 10;
const result = linearTransform(value, 0, 10, 0, 100);
expect(result).toBe(100);
});
it("transforms values outside the input range", () => {
const value = 15;
const result = linearTransform(value, 0, 10, 0, 100);
expect(result).toBe(150);
});
it("handles inverted output ranges", () => {
const value = 5;
const result = linearTransform(value, 0, 10, 100, 0);
expect(result).toBe(50);
});
it("returns NaN if input maximum equals input minimum", () => {
const value = 5;
const result = linearTransform(value, 0, 0, 0, 100);
expect(result).toBe(NaN);
});
it("returns NaN if input range is zero (avoids division by zero)", () => {
const value = 5;
const result = linearTransform(value, 10, 10, 0, 100);
expect(result).toBeNaN();
});
});

View File

@ -0,0 +1,75 @@
import { describe, expect, it } from "vitest";
import { exclude } from "../object";
describe("exclude", () => {
type TestObject = {
id: number;
name: string;
age: number;
email: string;
};
it("excludes specified keys from the object", () => {
const object: TestObject = {
id: 1,
name: "Alice",
age: 30,
email: "alice@example.com",
};
const result = exclude(object, ["age", "email"]);
expect(result).toEqual({ id: 1, name: "Alice" });
expect(result).not.toHaveProperty("age");
expect(result).not.toHaveProperty("email");
});
it("returns the same object if no keys are specified", () => {
const object: TestObject = {
id: 1,
name: "Alice",
age: 30,
email: "alice@example.com",
};
const keysToExclude: Array<keyof TestObject> = [];
const result = exclude(object, keysToExclude);
expect(result).toEqual(object);
});
it("does not modify the original object", () => {
const object: TestObject = {
id: 1,
name: "Alice",
age: 30,
email: "alice@example.com",
};
exclude(object, ["age", "email"]);
expect(object).toHaveProperty("age");
expect(object).toHaveProperty("email");
});
it("handles cases where keys to exclude are not present in the object", () => {
const object: TestObject = {
id: 1,
name: "Alice",
age: 30,
email: "alice@example.com",
};
const keysToExclude = ["nonExistentKey" as keyof TestObject];
const result = exclude(object, keysToExclude);
expect(result).toEqual(object);
});
it("returns the input if it is not an object", () => {
const object: unknown = null;
const keysToExclude = ["id"];
// @ts-expect-error passing invalid input type for tests
const result = exclude(object, keysToExclude);
expect(result).toBeNull();
});
});

View File

@ -0,0 +1,66 @@
import { describe, expect, it } from "vitest";
import {
extractUrl,
generateRandomName,
getInitials,
isEmptyString,
isUrl,
kebabCase,
processUsername,
} from "../string";
describe("getInitials", () => {
it("returns the initials of a name", () => {
expect(getInitials("John Doe")).toBe("JD");
expect(getInitials("Mary Jane Watson")).toBe("MW");
});
});
describe("isUrl", () => {
it("checks if a string is a URL", () => {
expect(isUrl("https://example.com")).toBe(true);
expect(isUrl("not a url")).toBe(false);
});
});
describe("isEmptyString", () => {
it("checks if a string is empty or only contains whitespace", () => {
expect(isEmptyString("")).toBe(true);
expect(isEmptyString(" ")).toBe(true);
expect(isEmptyString("<p></p>")).toBe(true);
expect(isEmptyString("not empty")).toBe(false);
});
});
describe("extractUrl", () => {
it("extracts a URL from a string", () => {
expect(extractUrl("Visit https://example.com today!")).toBe("https://example.com");
expect(extractUrl("No URL here.")).toBeNull();
});
});
describe("kebabCase", () => {
it("converts a string to kebab-case", () => {
expect(kebabCase("fooBar")).toBe("foo-bar");
expect(kebabCase("Foo Bar")).toBe("foo-bar");
expect(kebabCase("foo_bar")).toBe("foo-bar");
expect(kebabCase("")).toBe("");
expect(kebabCase(null)).toBe("");
});
});
describe("generateRandomName", () => {
it("generates a random name", () => {
const name = generateRandomName();
expect(name).toMatch(/^[A-Z][a-z]+ [A-Z][a-z]+ [A-Z][a-z]+$/);
});
});
describe("processUsername", () => {
it("processes a username by removing non-alphanumeric characters", () => {
expect(processUsername("User@Name!")).toBe("username");
expect(processUsername("")).toBe("");
expect(processUsername(null)).toBe("");
});
});