diff --git a/src/server/auth/org-slug.test.ts b/src/server/auth/org-slug.test.ts new file mode 100644 index 000000000..1f1919bce --- /dev/null +++ b/src/server/auth/org-slug.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from "vitest"; + +import { slugify, toHex } from "@/server/auth/org-slug"; + +describe("slugify", () => { + it("slugifies normal values", () => { + expect(slugify("My Workspace")).toBe("my-workspace"); + expect(slugify(" Hello, World! ")).toBe("hello-world"); + }); + + it("strips leading and trailing separators", () => { + expect(slugify("---weird---")).toBe("weird"); + }); + + it("falls back to 'workspace' when nothing is left", () => { + expect(slugify("")).toBe("workspace"); + expect(slugify("!!!")).toBe("workspace"); + }); + + it("does not leave a trailing dash when truncation lands on a separator", () => { + const value = `${"a".repeat(47)} extra words`; + const slug = slugify(value); + + expect(slug.length).toBeLessThanOrEqual(48); + expect(slug.endsWith("-")).toBe(false); + expect(slug).toBe("a".repeat(47)); + }); +}); + +describe("toHex", () => { + it("encodes a string as lowercase hex", () => { + expect(toHex("abc")).toBe("616263"); + }); +}); diff --git a/src/server/auth/org-slug.ts b/src/server/auth/org-slug.ts index ede1ff5b2..5971361a2 100644 --- a/src/server/auth/org-slug.ts +++ b/src/server/auth/org-slug.ts @@ -1,10 +1,12 @@ export function slugify(value: string) { + // Truncate before trimming dashes so a cut that lands on a "-" separator + // does not leave a leading or trailing dash in the final slug. const slug = value .toLowerCase() .trim() .replace(/[^a-z0-9]+/g, "-") - .replace(/^-+|-+$/g, "") - .slice(0, 48); + .slice(0, 48) + .replace(/^-+|-+$/g, ""); return slug || "workspace"; }