diff --git a/frontend/__tests__/test/custom-text.spec.ts b/frontend/__tests__/test/custom-text.spec.ts new file mode 100644 index 000000000000..e025fd7fd2af --- /dev/null +++ b/frontend/__tests__/test/custom-text.spec.ts @@ -0,0 +1,80 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +async function importCustomText(): Promise< + typeof import("../../src/ts/test/custom-text") +> { + vi.resetModules(); + window.localStorage.clear(); + return await import("../../src/ts/test/custom-text"); +} + +describe("custom text", () => { + beforeEach(() => { + window.localStorage.clear(); + }); + + it("uses language words when custom text is untouched default", async () => { + const CustomText = await importCustomText(); + + expect(CustomText.getEffectiveText(["uno", "dos", "tres"])).toEqual([ + "uno", + "dos", + "tres", + ]); + }); + + it("keeps user custom text instead of language words", async () => { + const CustomText = await importCustomText(); + + CustomText.setText(["custom", "words"]); + + expect(CustomText.getEffectiveText(["uno", "dos", "tres"])).toEqual([ + "custom", + "words", + ]); + }); + + it("keeps explicitly set default text instead of language words", async () => { + const CustomText = await importCustomText(); + + CustomText.setText([ + "The", + "quick", + "brown", + "fox", + "jumps", + "over", + "the", + "lazy", + "dog", + ]); + + expect(CustomText.getEffectiveText(["uno", "dos", "tres"])).toEqual([ + "The", + "quick", + "brown", + "fox", + "jumps", + "over", + "the", + "lazy", + "dog", + ]); + }); + + it("returns stored text for UI", async () => { + const CustomText = await importCustomText(); + + expect(CustomText.getStoredText()).toEqual([ + "The", + "quick", + "brown", + "fox", + "jumps", + "over", + "the", + "lazy", + "dog", + ]); + }); +}); diff --git a/frontend/src/ts/components/modals/CustomTextModal.tsx b/frontend/src/ts/components/modals/CustomTextModal.tsx index 602cda856cab..db6122aca13d 100644 --- a/frontend/src/ts/components/modals/CustomTextModal.tsx +++ b/frontend/src/ts/components/modals/CustomTextModal.tsx @@ -244,7 +244,7 @@ export function CustomTextModal(): JSXElement { if ( mode === "repeat" && CustomText.getLimitMode() !== "time" && - CustomText.getLimitValue() === CustomText.getText().length + CustomText.getLimitValue() === CustomText.getStoredText().length ) { mode = "simple"; } @@ -264,7 +264,7 @@ export function CustomTextModal(): JSXElement { } } - const text = CustomText.getText() + const text = CustomText.getStoredText() .join(pipeDelimiter ? "|" : " ") .replace(/^ +/gm, ""); diff --git a/frontend/src/ts/test/custom-text.ts b/frontend/src/ts/test/custom-text.ts index 43271d92b57b..9581648d0605 100644 --- a/frontend/src/ts/test/custom-text.ts +++ b/frontend/src/ts/test/custom-text.ts @@ -27,12 +27,30 @@ const customTextLongLS = new LocalStorageWithSchema({ fallback: {}, }); +const userEditedSettingsText = new LocalStorageWithSchema({ + key: "customTextSettingsUserEdited", + schema: z.boolean(), + fallback: false, +}); + type CustomTextLimit = z.infer["limit"]; +const defaultCustomText = [ + "The", + "quick", + "brown", + "fox", + "jumps", + "over", + "the", + "lazy", + "dog", +]; + const defaultCustomTextSettings: CustomTextSettings = { - text: ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"], + text: defaultCustomText, mode: "repeat", - limit: { value: 9, mode: "word" }, + limit: { value: defaultCustomText.length, mode: "word" }, pipeDelimiter: false, }; @@ -57,12 +75,28 @@ const customTextSettings = new LocalStorageWithSchema({ }, }); -export function getText(): string[] { +function isDefaultCustomText(text: string[]): boolean { + return ( + text.length === defaultCustomText.length && + text.every((word, index) => word === defaultCustomText[index]) + ); +} + +export function getStoredText(): string[] { return customTextSettings.get().text; } +export function getEffectiveText(languageWords: string[]): string[] { + const text = customTextSettings.get().text; + if (!userEditedSettingsText.get() && isDefaultCustomText(text)) { + return languageWords.slice(0, text.length); + } + return text; +} + export function setText(txt: string[]): void { const currentSettings = customTextSettings.get(); + userEditedSettingsText.set(true); customTextSettings.set({ ...currentSettings, text: txt, diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index 4876d02826f2..454628d1a67b 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -536,7 +536,7 @@ async function init(): Promise { }, customText: { ...CustomText.getData(), - text: `${CustomText.getText().length} words`, + text: `${CustomText.getStoredText().length} words`, }, mode: Config.mode, mode2: Misc.getMode2(Config, null), diff --git a/frontend/src/ts/test/words-generator.ts b/frontend/src/ts/test/words-generator.ts index 52a3c9c1e4d2..1e64587ca0fb 100644 --- a/frontend/src/ts/test/words-generator.ts +++ b/frontend/src/ts/test/words-generator.ts @@ -638,7 +638,7 @@ export async function generateWords( let wordList = language.words; if (Config.mode === "custom") { - wordList = CustomText.getText(); + wordList = CustomText.getEffectiveText(language.words); } else if (Config.mode === "quote") { wordList = await getQuoteWordList(language, wordOrder); } else if (Config.mode === "zen") {