diff --git a/app/utils/zod.test.ts b/app/utils/zod.test.ts index 8bc407578..7e7566646 100644 --- a/app/utils/zod.test.ts +++ b/app/utils/zod.test.ts @@ -1,5 +1,9 @@ import { describe, expect, it } from "vitest"; -import { hasZalgo, normalizeFriendCode } from "./zod"; +import { + actuallyNonEmptyStringOrNull, + hasZalgo, + normalizeFriendCode, +} from "./zod"; describe("normalizeFriendCode", () => { it("returns well formatted friend code as is", () => { @@ -40,3 +44,36 @@ describe("hasZalgo", () => { expect(hasZalgo("こんにちは")).toBe(false); }); }); + +describe("actuallyNonEmptyStringOrNull", () => { + it("returns null for an empty string", () => { + expect(actuallyNonEmptyStringOrNull("")).toBeNull(); + }); + + it("returns null for a string with only spaces", () => { + expect(actuallyNonEmptyStringOrNull(" ")).toBeNull(); + }); + + it("returns trimmed string for a string with visible characters and spaces", () => { + expect(actuallyNonEmptyStringOrNull(" hello world ")).toBe("hello world"); + }); + + it("removes invisible characters and trims", () => { + expect(actuallyNonEmptyStringOrNull("​​​​test​​​​")).toBe("test"); + }); + + it("returns original value if not a string", () => { + expect(actuallyNonEmptyStringOrNull(123)).toBe(123); + expect(actuallyNonEmptyStringOrNull(null)).toBe(null); + expect(actuallyNonEmptyStringOrNull(undefined)).toBe(undefined); + expect(actuallyNonEmptyStringOrNull({})).toEqual({}); + }); + + it("returns null for a string with only zero width spaces", () => { + expect(actuallyNonEmptyStringOrNull("​​​​​​​​​​")).toBeNull(); + }); + + it("returns null for a string with only tag space emoji", () => { + expect(actuallyNonEmptyStringOrNull("󠀠󠀠󠀠󠀠󠀠")).toBeNull(); + }); +}); diff --git a/app/utils/zod.ts b/app/utils/zod.ts index f841e99e1..81b8cc262 100644 --- a/app/utils/zod.ts +++ b/app/utils/zod.ts @@ -148,7 +148,7 @@ export function safeJSONParse(value: unknown): unknown { } } -const EMPTY_CHARACTERS = ["\u200B", "\u200C", "\u200D", "\u200E", "\u200F"]; +const EMPTY_CHARACTERS = ["\u200B", "\u200C", "\u200D", "\u200E", "\u200F", "󠀠"]; const EMPTY_CHARACTERS_REGEX = new RegExp(EMPTY_CHARACTERS.join("|"), "g"); const zalgoRe = /%CC%/g; @@ -197,7 +197,7 @@ export const safeNullableStringSchema = ({ /** * Processes the input value and returns a non-empty string with invisible characters cleaned out or null. */ -function actuallyNonEmptyStringOrNull(value: unknown) { +export function actuallyNonEmptyStringOrNull(value: unknown) { if (typeof value !== "string") return value; const trimmed = value.replace(EMPTY_CHARACTERS_REGEX, "").trim();