diff --git a/frontend/__tests__/test/funbox/funbox-functions.spec.ts b/frontend/__tests__/test/funbox/funbox-functions.spec.ts new file mode 100644 index 000000000000..5bbd0b52fd45 --- /dev/null +++ b/frontend/__tests__/test/funbox/funbox-functions.spec.ts @@ -0,0 +1,60 @@ +import { describe, it, expect } from "vitest"; +import { + getFunboxFunctions, + FunboxFunctions, +} from "../../../src/ts/test/funbox/funbox-functions"; + +describe("funbox functions", () => { + describe("l33t funbox", () => { + const funboxFunctions = getFunboxFunctions(); + const l33tFunbox = funboxFunctions.l33t as Required< + Pick + >; + + const alterText = (word: string): string => + l33tFunbox.alterText(word, 0, word.length); + + it("should convert lowercase letters to l33t speak", () => { + expect(alterText("hello world")).toBe("h3110 w0r1d"); + }); + + it("should handle uppercase letters", () => { + expect(alterText("Hello")).toBe("H3110"); + }); + + it("should handle mixed case", () => { + expect(alterText("HeLLo")).toBe("H3110"); + }); + + it("should keep non-letter characters unchanged", () => { + expect(alterText("h3llo!")).toBe("h3110!"); + }); + + it("should handle spaces", () => { + const result = alterText("hello world"); + expect(result.startsWith("h3110 ")).toBe(true); + expect(result.endsWith("w0r1d")).toBe(true); + expect(result).not.toContain("/"); + }); + + it("should handle all l33t characters", () => { + expect(alterText("abcdefg")).toBe("4bcd3f6"); + }); + + it("should handle all l33t characters (uppercase)", () => { + expect(alterText("ABCDEFG")).toBe("4BCD3F6"); + }); + + it("should convert xyz to l33t", () => { + expect(alterText("xyz")).toBe("xy2"); + }); + + it("should handle empty string", () => { + expect(alterText("")).toBe(""); + }); + + it("should handle string with no letters", () => { + expect(alterText("123 !@#")).toBe("123 !@#"); + }); + }); +}); diff --git a/frontend/src/ts/test/funbox/funbox-functions.ts b/frontend/src/ts/test/funbox/funbox-functions.ts index 7430c0b6bae6..5d229e007fbd 100644 --- a/frontend/src/ts/test/funbox/funbox-functions.ts +++ b/frontend/src/ts/test/funbox/funbox-functions.ts @@ -173,6 +173,19 @@ export class PolyglotWordset extends Wordset { } } +const l33tMap: Record = { + a: "4", + e: "3", + + g: "6", + i: "1", + l: "1", + o: "0", + s: "5", + t: "7", + z: "2", +}; + const list: Partial> = { "58008": { getWord(): string { @@ -650,6 +663,13 @@ const list: Partial> = { return word.toUpperCase(); }, }, + l33t: { + alterText(word: string): string { + return word.replace(/[a-zA-Z]/g, (ch) => { + return l33tMap[ch.toLowerCase()] ?? ch; + }); + }, + }, polyglot: { async withWords(_words) { const promises = Config.customPolyglot.map(async (language) => diff --git a/packages/funbox/src/list.ts b/packages/funbox/src/list.ts index 866decc7d7e7..179ba6a29727 100644 --- a/packages/funbox/src/list.ts +++ b/packages/funbox/src/list.ts @@ -480,6 +480,14 @@ const list: Record = { difficultyLevel: 0, name: "no_quit", }, + l33t: { + description: "1 533t 5p34k. C0nv3r7 7h3 73x7 70 l337.", + canGetPb: true, + difficultyLevel: 1, + properties: ["changesCapitalisation"], + frontendFunctions: ["alterText"], + name: "l33t", + }, }; export function getObject(): Record { diff --git a/packages/schemas/src/configs.ts b/packages/schemas/src/configs.ts index 36c979dafcde..ff104b021388 100644 --- a/packages/schemas/src/configs.ts +++ b/packages/schemas/src/configs.ts @@ -334,6 +334,7 @@ export const FunboxNameSchema = z.enum([ "polyglot", "asl", "rot13", + "l33t", "no_quit", ]); export type FunboxName = z.infer;