Skip to content

Commit 2568ce1

Browse files
authored
Merge pull request #7 from smallstack/add-more-string-utils
2 parents c1f8696 + 85934d9 commit 2568ce1

File tree

3 files changed

+113
-8
lines changed

3 files changed

+113
-8
lines changed

lib/modules/string/string.utils.test.ts

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { describe, expect, test } from "vitest";
2-
import { upperCaseFirst } from "./string.utils";
2+
import {
3+
camelCaseToSnakeCase,
4+
getTimeAsCharacters,
5+
lowerCaseFirst,
6+
snakeCaseToCamelCase,
7+
upperCaseFirst,
8+
} from "./string.utils";
39

410
describe("upperCaseFirst", () => {
511
test("should return an empty string when input is an empty string", () => {
@@ -27,3 +33,72 @@ describe("upperCaseFirst", () => {
2733
expect(upperCaseFirst(" hello")).toBe(" hello");
2834
});
2935
});
36+
37+
describe("lowerCaseFirst", () => {
38+
test("should return an empty string when input is an empty string", () => {
39+
expect(lowerCaseFirst("")).toBe("");
40+
expect(lowerCaseFirst(undefined as any)).toBe(undefined);
41+
});
42+
43+
test("should lowercase the first letter of a single character string", () => {
44+
expect(lowerCaseFirst("A")).toBe("a");
45+
});
46+
47+
test("should lowercase the first letter of a multiple character string", () => {
48+
expect(lowerCaseFirst("Hello")).toBe("hello");
49+
});
50+
51+
test("should return the same string if the first character is already lowercase", () => {
52+
expect(lowerCaseFirst("hello")).toBe("hello");
53+
});
54+
55+
test("should handle strings with special characters correctly", () => {
56+
expect(lowerCaseFirst("!Hello")).toBe("!Hello");
57+
expect(lowerCaseFirst("123Hello")).toBe("123Hello");
58+
});
59+
60+
test("should handle strings with leading whitespace correctly", () => {
61+
expect(lowerCaseFirst(" Hello")).toBe(" Hello");
62+
});
63+
});
64+
65+
describe("camelCaseToSnakeCase", () => {
66+
test("should convert camelCase to snake_case", () => {
67+
expect(camelCaseToSnakeCase("helloWorld")).toBe("hello_world");
68+
});
69+
70+
test("should handle strings with special characters correctly", () => {
71+
expect(camelCaseToSnakeCase("helloWorld!")).toBe("hello_world!");
72+
expect(camelCaseToSnakeCase("helloWorld123")).toBe("hello_world123");
73+
});
74+
75+
test("should handle strings with leading whitespace correctly", () => {
76+
expect(camelCaseToSnakeCase(" helloWorld")).toBe(" hello_world");
77+
});
78+
});
79+
80+
describe("snakeCaseToCamelCase", () => {
81+
test("should convert snake_case to camelCase", () => {
82+
expect(snakeCaseToCamelCase("hello_world")).toBe("HelloWorld");
83+
});
84+
85+
test("should convert snake_case to lowerCamelCase", () => {
86+
expect(snakeCaseToCamelCase("hello_world", true)).toBe("helloWorld");
87+
});
88+
89+
test("should handle strings with special characters correctly", () => {
90+
expect(snakeCaseToCamelCase("hello_world!")).toBe("HelloWorld!");
91+
expect(snakeCaseToCamelCase("hello_world123")).toBe("HelloWorld123");
92+
});
93+
94+
test("should handle strings with leading whitespace correctly", () => {
95+
expect(snakeCaseToCamelCase(" hello_world")).toBe(" helloWorld");
96+
});
97+
});
98+
99+
describe("getTimeAsCharacters", () => {
100+
test("should return a string based on the given timestamp", () => {
101+
const timestamp = 1732608080598;
102+
expect(getTimeAsCharacters(timestamp)).toBe("bhdcgaiaiafji");
103+
});
104+
});

lib/modules/string/string.utils.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,40 @@
1-
/**
2-
* Capitalize the first letter of a string
3-
*
4-
* @param str The input string
5-
* @returns The string with the first letter capitalized
6-
*/
1+
/** Capitalize the first letter of a string */
72
export function upperCaseFirst(str: string): string {
83
if (!str) return str;
94
return str.charAt(0).toUpperCase() + str.slice(1);
105
}
6+
7+
/** Lowercase the first letter of a string */
8+
export function lowerCaseFirst(str: string): string {
9+
if (typeof str !== "string") return str;
10+
return str.charAt(0).toLowerCase() + str.slice(1);
11+
}
12+
13+
/** Converts "HelloWorld" to "hello_world" */
14+
export function camelCaseToSnakeCase(str: string): string {
15+
return lowerCaseFirst(str).replace(
16+
/[A-Z]/g,
17+
(letter) => `_${letter.toLowerCase()}`
18+
);
19+
}
20+
21+
/** Converts "hello-world" or "hello_world" to "HelloWorld" */
22+
export function snakeCaseToCamelCase(
23+
str: string,
24+
lowerCamelCase = false
25+
): string {
26+
const camelCase = str.replace(/([-_][a-zA-Z])/g, (group) =>
27+
group.toUpperCase().replace("-", "").replace("_", "")
28+
);
29+
if (lowerCamelCase) return lowerCaseFirst(camelCase);
30+
return upperCaseFirst(camelCase);
31+
}
32+
33+
/** Returns a string based on the current (or given) timestamp */
34+
export function getTimeAsCharacters(timestamp = Date.now()): string {
35+
return timestamp
36+
.toString()
37+
.split("")
38+
.map((n) => (Number(n) + 10).toString(36))
39+
.join("");
40+
}

vite.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default defineConfig({
3434
coverage: {
3535
provider: "v8",
3636
include: ["lib/**"],
37-
exclude: ["node_modules/**", "lib/main.ts", "lib/**/index.ts"],
37+
exclude: ["node_modules/**", "lib/main.ts", "lib/**/index.ts", "lib/**/*.test.ts"],
3838
reporter: ["lcov", "clover", "text-summary"],
3939
reportsDirectory: "coverage",
4040
thresholds: {

0 commit comments

Comments
 (0)