From 389a2083e98fd63cd4b13cab4391ebb1080977ea Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 10:58:45 +0300 Subject: [PATCH 01/42] fix: stopOnError: word has no effect in nospace --- .../input/helpers/validation.spec.ts | 18 ++++------------- .../ts/input/handlers/before-insert-text.ts | 8 ++++---- frontend/src/ts/input/handlers/insert-text.ts | 11 ++++------ frontend/src/ts/input/helpers/validation.ts | 20 ++++++++----------- 4 files changed, 20 insertions(+), 37 deletions(-) diff --git a/frontend/__tests__/input/helpers/validation.spec.ts b/frontend/__tests__/input/helpers/validation.spec.ts index 681394cb863e..efeed75a0c1d 100644 --- a/frontend/__tests__/input/helpers/validation.spec.ts +++ b/frontend/__tests__/input/helpers/validation.spec.ts @@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach, afterAll } from "vitest"; import { isCharCorrect, isWordCorrect, - shouldInsertSpaceCharacter, + isJumpToNextWordBlocked, } from "../../../src/ts/input/helpers/validation"; import { __testing } from "../../../src/ts/config/testing"; import * as FunboxList from "../../../src/ts/test/funbox/list"; @@ -155,7 +155,7 @@ describe("isCharCorrect", () => { }); }); -describe("shouldInsertSpaceCharacter", () => { +describe("isJumpToNextWordBlocked", () => { beforeEach(() => { replaceConfig({ mode: "time", @@ -169,20 +169,10 @@ describe("shouldInsertSpaceCharacter", () => { replaceConfig({}); }); - it("returns null if data is not a space", () => { - expect( - shouldInsertSpaceCharacter({ - data: "a", - inputValue: "test", - targetWord: "test", - }), - ).toBe(null); - }); - it("returns false in zen mode", () => { replaceConfig({ mode: "zen" }); expect( - shouldInsertSpaceCharacter({ + isJumpToNextWordBlocked({ data: " ", inputValue: "test", targetWord: "test", @@ -286,7 +276,7 @@ describe("shouldInsertSpaceCharacter", () => { ])("$desc", ({ inputValue, targetWord, config, expected }) => { replaceConfig(config as any); expect( - shouldInsertSpaceCharacter({ + isJumpToNextWordBlocked({ data: " ", inputValue, targetWord, diff --git a/frontend/src/ts/input/handlers/before-insert-text.ts b/frontend/src/ts/input/handlers/before-insert-text.ts index 3c5f56419e6e..b62c70c7eda5 100644 --- a/frontend/src/ts/input/handlers/before-insert-text.ts +++ b/frontend/src/ts/input/handlers/before-insert-text.ts @@ -7,7 +7,7 @@ import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import { isSpace } from "../../utils/strings"; import { getInputElementValue } from "../input-element"; import { isAwaitingNextWord } from "../state"; -import { shouldInsertSpaceCharacter } from "../helpers/validation"; +import { isJumpToNextWordBlocked } from "../helpers/validation"; import * as SlowTimer from "../../legacy-states/slow-timer"; import { wordsHaveNewline } from "../../states/test"; @@ -31,7 +31,7 @@ export function onBeforeInsertText(data: string): boolean { const { inputValue } = getInputElementValue(); const dataIsSpace = isSpace(data); - const shouldInsertSpaceAsCharacter = shouldInsertSpaceCharacter({ + const isNextWordBlocked = isJumpToNextWordBlocked({ data, inputValue, targetWord: TestWords.words.getCurrentText(), @@ -62,7 +62,7 @@ export function onBeforeInsertText(data: string): boolean { const inputLimit = Config.mode === "zen" ? 30 : TestWords.words.getCurrentText().length + 20; const overLimit = getCurrentInput().length >= inputLimit; - if (overLimit && (shouldInsertSpaceAsCharacter === true || !dataIsSpace)) { + if (overLimit && (isNextWordBlocked || !dataIsSpace)) { console.error("Hitting word limit"); return true; } @@ -79,7 +79,7 @@ export function onBeforeInsertText(data: string): boolean { !Config.blindMode && !Config.hideExtraLetters && inputIsLongerThanOrEqualToWord && - (shouldInsertSpaceAsCharacter === true || !dataIsSpace) && + (isNextWordBlocked || !dataIsSpace) && Config.mode !== "zen" ) { // make sure to only check this when really necessary diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 70ae26173981..89bfe9050c05 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -34,7 +34,7 @@ import { onBeforeInsertText } from "./before-insert-text"; import { isCharCorrect, isWordCorrect, - shouldInsertSpaceCharacter, + isJumpToNextWordBlocked, } from "../helpers/validation"; import { getCurrentInput, logTestEvent } from "../../test/events/data"; @@ -119,8 +119,8 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const wordIndex = TestState.activeWordIndex; const charIsSpace = isSpace(data); const charIsNewline = data === "\n"; - const shouldInsertSpace = - shouldInsertSpaceCharacter({ + const isNextWordBlocked = + isJumpToNextWordBlocked({ data, inputValue: testInput, targetWord: currentWord, @@ -150,7 +150,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { (testInput + data).length === TestWords.words.getCurrentText().length; // does this input try to move to the next word (before removeLastChar can block it) const goingToNextWord = - ((charIsSpace || charIsNewline) && !shouldInsertSpace) || noSpaceForce; + (charIsSpace || charIsNewline || noSpaceForce) && !isNextWordBlocked; // when moving to the next word, correctness is word-level (a correct word-completing // space has charCorrect === false, so charCorrect can't be used below) @@ -246,9 +246,6 @@ export async function onInsertText(options: OnInsertTextParams): Promise { /* Probably a good place to explain what the heck is going on with all these space related variables: - spaceOrNewLine: did the user input a space or a new line? - - shouldInsertSpace: should space be treated as a character, or should it move us to the next word - monkeytype doesnt actually have space characters in words, so we need this distinction - and also moving to the next word might get blocked by things like stop on error - shouldGoToNextWord: IF input is space and we DONT insert a space CHARACTER, we will TRY to go to the next word - increasedWordIndex: the only reason this is here because on the last word we dont move to the next word */ diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index a2712335b3b2..12a6a1543c37 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -60,24 +60,20 @@ export function isWordCorrect(options: { * @param options.targetWord - Target word * @returns Boolean if data is space, null if not */ -export function shouldInsertSpaceCharacter(options: { +export function isJumpToNextWordBlocked(options: { data: string; inputValue: string; targetWord: string; }): boolean | null { - const { data, inputValue, targetWord } = options; - if (!isSpace(data)) { - return null; - } - if (Config.mode === "zen") { - return false; - } - const correctSoFar = `${targetWord} `.startsWith(`${inputValue} `); + const { data, inputValue } = options; + + const correct = isWordCorrect({ ...options, correctShiftUsed: null }); + const stopOnErrorLetterAndIncorrect = - Config.stopOnError === "letter" && !correctSoFar; - const stopOnErrorWordAndIncorrect = - Config.stopOnError === "word" && !correctSoFar; + Config.stopOnError === "letter" && !correct; + const stopOnErrorWordAndIncorrect = Config.stopOnError === "word" && !correct; const strictSpace = + isSpace(data) && inputValue.length === 0 && (Config.strictSpace || Config.difficulty !== "normal"); return ( From d6343dba72549e7dcd4b24667d1b066aa9a7d967 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 11:09:32 +0300 Subject: [PATCH 02/42] Return type --- frontend/src/ts/input/helpers/validation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 12a6a1543c37..ac6825655e38 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -64,7 +64,7 @@ export function isJumpToNextWordBlocked(options: { data: string; inputValue: string; targetWord: string; -}): boolean | null { +}): boolean { const { data, inputValue } = options; const correct = isWordCorrect({ ...options, correctShiftUsed: null }); From f8e377f411bcc34f6c5d4fbad98e4f476430239d Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 11:16:08 +0300 Subject: [PATCH 03/42] Remove --- frontend/src/ts/input/handlers/insert-text.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 89bfe9050c05..6cbaa08fd94d 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -119,12 +119,11 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const wordIndex = TestState.activeWordIndex; const charIsSpace = isSpace(data); const charIsNewline = data === "\n"; - const isNextWordBlocked = - isJumpToNextWordBlocked({ - data, - inputValue: testInput, - targetWord: currentWord, - }) === true; + const isNextWordBlocked = isJumpToNextWordBlocked({ + data, + inputValue: testInput, + targetWord: currentWord, + }); const correctShiftUsed = Config.oppositeShiftMode === "off" ? null : isCorrectShiftUsed(); From daf2ea8828f788f3aa428beb1c412d163e32a246 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 11:29:08 +0300 Subject: [PATCH 04/42] =?UTF-8?q?=F0=9F=90=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/ts/input/helpers/validation.ts | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index ac6825655e38..5a0d4993e3b7 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -1,5 +1,7 @@ import { Config } from "../../config/store"; import { isSpace } from "../../utils/strings"; +import { isFunboxActiveWithProperty } from "../../test/funbox/list"; +import * as TestWords from "../../test/test-words"; /** * Check if the input data is correct @@ -80,3 +82,28 @@ export function isJumpToNextWordBlocked(options: { stopOnErrorLetterAndIncorrect || stopOnErrorWordAndIncorrect || strictSpace ); } + +export function shouldJumpToNextWord(options: { + data: string; + inputValue: string; + targetWord: string; + charIsSpace?: boolean; + charIsNewline?: boolean; +}): boolean { + const { + data, + inputValue, + targetWord, + charIsSpace = isSpace(data), + charIsNewline = data === "\n", + } = options; + const isNextWordBlocked = isJumpToNextWordBlocked({ + data, + inputValue, + targetWord, + }); + const noSpaceForce = + isFunboxActiveWithProperty("nospace") && + (inputValue + data).length === TestWords.words.getCurrentText().length; + return (charIsSpace || charIsNewline || noSpaceForce) && !isNextWordBlocked; +} From a0d87c409e1f7a80c23bfcb882c0e69bfa48ae64 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 11:31:36 +0300 Subject: [PATCH 05/42] More --- frontend/src/ts/input/handlers/insert-text.ts | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 6cbaa08fd94d..0a9e25bb3f4e 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -14,10 +14,7 @@ import { import { areCharactersVisuallyEqual, isSpace } from "../../utils/strings"; import * as TestState from "../../test/test-state"; import * as TestLogic from "../../test/test-logic"; -import { - findSingleActiveFunboxWithFunction, - isFunboxActiveWithProperty, -} from "../../test/funbox/list"; +import { findSingleActiveFunboxWithFunction } from "../../test/funbox/list"; import { Config } from "../../config/store"; import { flash } from "../../events/keymap"; import * as WeakSpot from "../../test/weak-spot"; @@ -34,7 +31,7 @@ import { onBeforeInsertText } from "./before-insert-text"; import { isCharCorrect, isWordCorrect, - isJumpToNextWordBlocked, + shouldJumpToNextWord, } from "../helpers/validation"; import { getCurrentInput, logTestEvent } from "../../test/events/data"; @@ -119,11 +116,6 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const wordIndex = TestState.activeWordIndex; const charIsSpace = isSpace(data); const charIsNewline = data === "\n"; - const isNextWordBlocked = isJumpToNextWordBlocked({ - data, - inputValue: testInput, - targetWord: currentWord, - }); const correctShiftUsed = Config.oppositeShiftMode === "off" ? null : isCorrectShiftUsed(); @@ -143,13 +135,14 @@ export async function onInsertText(options: OnInsertTextParams): Promise { correctShiftUsed, }); - // word navigation check - const noSpaceForce = - isFunboxActiveWithProperty("nospace") && - (testInput + data).length === TestWords.words.getCurrentText().length; // does this input try to move to the next word (before removeLastChar can block it) - const goingToNextWord = - (charIsSpace || charIsNewline || noSpaceForce) && !isNextWordBlocked; + const goingToNextWord = shouldJumpToNextWord({ + data, + inputValue: testInput, + targetWord: currentWord, + charIsSpace, + charIsNewline, + }); // when moving to the next word, correctness is word-level (a correct word-completing // space has charCorrect === false, so charCorrect can't be used below) @@ -224,16 +217,12 @@ export async function onInsertText(options: OnInsertTextParams): Promise { // this needs to be called after event logging WeakSpot.updateScore(data, correct); - const commitCorrect = noSpaceForce - ? testInput + data === currentWord - : correct; - // going to next word let increasedWordIndex: null | boolean = null; let lastBurst: null | number = null; if (shouldGoToNextWord) { const result = await goToNextWord({ - correctInsert: commitCorrect, + correctInsert: correct, isCompositionEnding: isCompositionEnding === true, zenNewline: charIsNewline && Config.mode === "zen", now, From 44c25f2f1d6f822959416202d641b2063488de46 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 11:35:18 +0300 Subject: [PATCH 06/42] More --- .../src/ts/input/handlers/before-insert-text.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/frontend/src/ts/input/handlers/before-insert-text.ts b/frontend/src/ts/input/handlers/before-insert-text.ts index b62c70c7eda5..ded765fc89c4 100644 --- a/frontend/src/ts/input/handlers/before-insert-text.ts +++ b/frontend/src/ts/input/handlers/before-insert-text.ts @@ -7,7 +7,7 @@ import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import { isSpace } from "../../utils/strings"; import { getInputElementValue } from "../input-element"; import { isAwaitingNextWord } from "../state"; -import { isJumpToNextWordBlocked } from "../helpers/validation"; +import { shouldJumpToNextWord } from "../helpers/validation"; import * as SlowTimer from "../../legacy-states/slow-timer"; import { wordsHaveNewline } from "../../states/test"; @@ -31,11 +31,6 @@ export function onBeforeInsertText(data: string): boolean { const { inputValue } = getInputElementValue(); const dataIsSpace = isSpace(data); - const isNextWordBlocked = isJumpToNextWordBlocked({ - data, - inputValue, - targetWord: TestWords.words.getCurrentText(), - }); //prevent space from being inserted if input is empty //allow if strict space is enabled @@ -58,11 +53,17 @@ export function onBeforeInsertText(data: string): boolean { return true; } + const shouldGoToNextWord = shouldJumpToNextWord({ + data, + inputValue, + targetWord: TestWords.words.getCurrentText(), + }); + // block input if the word is too long const inputLimit = Config.mode === "zen" ? 30 : TestWords.words.getCurrentText().length + 20; const overLimit = getCurrentInput().length >= inputLimit; - if (overLimit && (isNextWordBlocked || !dataIsSpace)) { + if (overLimit && !shouldGoToNextWord) { console.error("Hitting word limit"); return true; } @@ -79,7 +80,7 @@ export function onBeforeInsertText(data: string): boolean { !Config.blindMode && !Config.hideExtraLetters && inputIsLongerThanOrEqualToWord && - (isNextWordBlocked || !dataIsSpace) && + !shouldGoToNextWord && Config.mode !== "zen" ) { // make sure to only check this when really necessary From 1456108bf85f7d0e2a954b3f26a9b8a17c52c88c Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Mon, 22 Jun 2026 09:39:43 +0300 Subject: [PATCH 07/42] Comment --- frontend/src/ts/input/helpers/validation.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 5a0d4993e3b7..2425a5bc9a01 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -34,6 +34,7 @@ export function isCharCorrect(options: { /** * Check if the input data is correct * @param options - Options object + * @param options.data - Input data * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) * @param options.targetWord - Target word * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled From f08bc73eeedb00d7fd78bd9467a70692cb0de45a Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 12:06:52 +0300 Subject: [PATCH 08/42] Comment --- frontend/src/ts/input/helpers/validation.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 2425a5bc9a01..b397592f1dba 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -61,7 +61,6 @@ export function isWordCorrect(options: { * @param options.data - Input data * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) * @param options.targetWord - Target word - * @returns Boolean if data is space, null if not */ export function isJumpToNextWordBlocked(options: { data: string; From e51ec2b8015deab8b3eb03ab40faec19e4582d8e Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 13:10:11 +0300 Subject: [PATCH 09/42] More --- .../ts/input/handlers/before-insert-text.ts | 8 ++++- frontend/src/ts/input/handlers/insert-text.ts | 11 ++++--- .../src/ts/input/helpers/fail-or-finish.ts | 18 +++++------ frontend/src/ts/input/helpers/validation.ts | 31 +++++++++++-------- 4 files changed, 41 insertions(+), 27 deletions(-) diff --git a/frontend/src/ts/input/handlers/before-insert-text.ts b/frontend/src/ts/input/handlers/before-insert-text.ts index ded765fc89c4..5ea865175b38 100644 --- a/frontend/src/ts/input/handlers/before-insert-text.ts +++ b/frontend/src/ts/input/handlers/before-insert-text.ts @@ -7,7 +7,7 @@ import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import { isSpace } from "../../utils/strings"; import { getInputElementValue } from "../input-element"; import { isAwaitingNextWord } from "../state"; -import { shouldJumpToNextWord } from "../helpers/validation"; +import { shouldJumpToNextWord, isCommitChar } from "../helpers/validation"; import * as SlowTimer from "../../legacy-states/slow-timer"; import { wordsHaveNewline } from "../../states/test"; @@ -53,10 +53,16 @@ export function onBeforeInsertText(data: string): boolean { return true; } + const isCommitData = isCommitChar({ + data, + inputValue, + }); + const shouldGoToNextWord = shouldJumpToNextWord({ data, inputValue, targetWord: TestWords.words.getCurrentText(), + isCommitData, }); // block input if the word is too long diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 0a9e25bb3f4e..d583110432dd 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -32,6 +32,7 @@ import { isCharCorrect, isWordCorrect, shouldJumpToNextWord, + isCommitChar, } from "../helpers/validation"; import { getCurrentInput, logTestEvent } from "../../test/events/data"; @@ -135,13 +136,14 @@ export async function onInsertText(options: OnInsertTextParams): Promise { correctShiftUsed, }); + const isCommitData = isCommitChar({ data, inputValue: testInput }); + // does this input try to move to the next word (before removeLastChar can block it) const goingToNextWord = shouldJumpToNextWord({ data, inputValue: testInput, targetWord: currentWord, - charIsSpace, - charIsNewline, + isCommitData, }); // when moving to the next word, correctness is word-level (a correct word-completing @@ -258,9 +260,10 @@ export async function onInsertText(options: OnInsertTextParams): Promise { if (!CompositionState.getComposing() && lastInMultiOrSingle) { if ( checkIfFailedDueToDifficulty({ - testInputWithData: testInput + data, + data, + inputValue: testInput, correct, - spaceOrNewline: charIsSpace || charIsNewline, + isCommitData, }) ) { TestLogic.fail("difficulty"); diff --git a/frontend/src/ts/input/helpers/fail-or-finish.ts b/frontend/src/ts/input/helpers/fail-or-finish.ts index 6c096a42c10b..d70c26e74695 100644 --- a/frontend/src/ts/input/helpers/fail-or-finish.ts +++ b/frontend/src/ts/input/helpers/fail-or-finish.ts @@ -36,26 +36,26 @@ export function checkIfFailedDueToMinBurst(options: { /** * Check if the test should fail due to difficulty settings * @param options - Options object - * @param options.testInputWithData - Current test input result (after adding data) + * @param options.data - Input data + * @param options.inputValue - Current test input result * @param options.correct - Was the last input correct - * @param options.spaceOrNewline - Is the input a space or newline + * @param options.isCommitData - Whether the entered character finishes the word */ export function checkIfFailedDueToDifficulty(options: { - testInputWithData: string; + data: string; + inputValue: string; correct: boolean; - spaceOrNewline: boolean; + isCommitData: boolean; }): boolean { - const { testInputWithData, correct, spaceOrNewline } = options; - // Using space or newline instead of shouldInsertSpace or increasedWordIndex - // because we want expert mode to fail no matter if confidence or stop on error is on + const { data, inputValue, correct, isCommitData } = options; if (Config.mode === "zen") return false; const shouldFailDueToExpert = Config.difficulty === "expert" && !correct && - spaceOrNewline && - testInputWithData.length > 1; + isCommitData && + (inputValue + data).length > 1; const shouldFailDueToMaster = Config.difficulty === "master" && !correct; diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index b397592f1dba..f195ae2d0a39 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -83,27 +83,32 @@ export function isJumpToNextWordBlocked(options: { ); } +export function isCommitChar(options: { + data: string; + inputValue: string; +}): boolean { + const { data, inputValue } = options; + + const charIsSpace = isSpace(data); + const charIsNewline = data === "\n"; + const noSpaceForce = + isFunboxActiveWithProperty("nospace") && + (inputValue + data).length === TestWords.words.getCurrentText().length; + + return charIsSpace || charIsNewline || noSpaceForce; +} + export function shouldJumpToNextWord(options: { data: string; inputValue: string; targetWord: string; - charIsSpace?: boolean; - charIsNewline?: boolean; + isCommitData: boolean; }): boolean { - const { - data, - inputValue, - targetWord, - charIsSpace = isSpace(data), - charIsNewline = data === "\n", - } = options; + const { data, inputValue, targetWord, isCommitData } = options; const isNextWordBlocked = isJumpToNextWordBlocked({ data, inputValue, targetWord, }); - const noSpaceForce = - isFunboxActiveWithProperty("nospace") && - (inputValue + data).length === TestWords.words.getCurrentText().length; - return (charIsSpace || charIsNewline || noSpaceForce) && !isNextWordBlocked; + return isCommitData && !isNextWordBlocked; } From cbd267da173948567e5a5ac726e118a035a9a666 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 14:21:47 +0300 Subject: [PATCH 10/42] Remove charIsSpace --- frontend/src/ts/input/handlers/insert-text.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index d583110432dd..74a3c0869564 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -11,7 +11,7 @@ import { checkIfFailedDueToMinBurst, checkIfFinished, } from "../helpers/fail-or-finish"; -import { areCharactersVisuallyEqual, isSpace } from "../../utils/strings"; +import { areCharactersVisuallyEqual } from "../../utils/strings"; import * as TestState from "../../test/test-state"; import * as TestLogic from "../../test/test-logic"; import { findSingleActiveFunboxWithFunction } from "../../test/funbox/list"; @@ -115,7 +115,6 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const lastInMultiOrSingle = lastInMultiIndex === true || lastInMultiIndex === undefined; const wordIndex = TestState.activeWordIndex; - const charIsSpace = isSpace(data); const charIsNewline = data === "\n"; const correctShiftUsed = Config.oppositeShiftMode === "off" ? null : isCorrectShiftUsed(); @@ -170,7 +169,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { removeLastChar = true; } - if (!charIsSpace && correctShiftUsed === false) { + if (correctShiftUsed === false) { removeLastChar = true; visualInputOverride = undefined; incrementIncorrectShiftsInARow(); From 3b6c7a5a050632f0361bcde57124d547111135bd Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 14:50:51 +0300 Subject: [PATCH 11/42] Remove charIsNewline --- frontend/src/ts/input/handlers/insert-text.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 74a3c0869564..2bd8f88c9e84 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -115,7 +115,6 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const lastInMultiOrSingle = lastInMultiIndex === true || lastInMultiIndex === undefined; const wordIndex = TestState.activeWordIndex; - const charIsNewline = data === "\n"; const correctShiftUsed = Config.oppositeShiftMode === "off" ? null : isCorrectShiftUsed(); @@ -225,7 +224,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const result = await goToNextWord({ correctInsert: correct, isCompositionEnding: isCompositionEnding === true, - zenNewline: charIsNewline && Config.mode === "zen", + zenNewline: data === "\n" && Config.mode === "zen", now, }); lastBurst = result.lastBurst; From 5f5476dc62b450eefdcb034149e5f10a1ef30928 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 14:57:20 +0300 Subject: [PATCH 12/42] Optional --- frontend/src/ts/input/helpers/validation.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index f195ae2d0a39..0e114c1f0c2b 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -43,12 +43,12 @@ export function isWordCorrect(options: { data: string; inputValue: string; targetWord: string; - correctShiftUsed: boolean | null; //null means disabled + correctShiftUsed?: boolean; }): boolean { - const { data, inputValue, targetWord, correctShiftUsed } = options; + const { data, inputValue, targetWord, correctShiftUsed = true } = options; if (Config.mode === "zen") return true; - if (correctShiftUsed === false) return false; + if (!correctShiftUsed) return false; const finalInputValue = inputValue + (isSpace(data) ? "" : data); return finalInputValue === targetWord; @@ -69,7 +69,7 @@ export function isJumpToNextWordBlocked(options: { }): boolean { const { data, inputValue } = options; - const correct = isWordCorrect({ ...options, correctShiftUsed: null }); + const correct = isWordCorrect(options); const stopOnErrorLetterAndIncorrect = Config.stopOnError === "letter" && !correct; From 09848442d005d53da56212068d4059c2f5ce2df6 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:03:18 +0300 Subject: [PATCH 13/42] Revert "Optional" This reverts commit 5f5476dc62b450eefdcb034149e5f10a1ef30928. --- frontend/src/ts/input/helpers/validation.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 0e114c1f0c2b..f195ae2d0a39 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -43,12 +43,12 @@ export function isWordCorrect(options: { data: string; inputValue: string; targetWord: string; - correctShiftUsed?: boolean; + correctShiftUsed: boolean | null; //null means disabled }): boolean { - const { data, inputValue, targetWord, correctShiftUsed = true } = options; + const { data, inputValue, targetWord, correctShiftUsed } = options; if (Config.mode === "zen") return true; - if (!correctShiftUsed) return false; + if (correctShiftUsed === false) return false; const finalInputValue = inputValue + (isSpace(data) ? "" : data); return finalInputValue === targetWord; @@ -69,7 +69,7 @@ export function isJumpToNextWordBlocked(options: { }): boolean { const { data, inputValue } = options; - const correct = isWordCorrect(options); + const correct = isWordCorrect({ ...options, correctShiftUsed: null }); const stopOnErrorLetterAndIncorrect = Config.stopOnError === "letter" && !correct; From 85fd6117ed5e3775f193b73d9c77455225e3047c Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:09:25 +0300 Subject: [PATCH 14/42] Less --- frontend/src/ts/input/handlers/insert-text.ts | 3 +-- frontend/src/ts/input/helpers/fail-or-finish.ts | 10 ++++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 2bd8f88c9e84..090432d9e403 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -258,8 +258,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { if (!CompositionState.getComposing() && lastInMultiOrSingle) { if ( checkIfFailedDueToDifficulty({ - data, - inputValue: testInput, + testInputWithData: testInput + data, correct, isCommitData, }) diff --git a/frontend/src/ts/input/helpers/fail-or-finish.ts b/frontend/src/ts/input/helpers/fail-or-finish.ts index d70c26e74695..2a093ea37d8b 100644 --- a/frontend/src/ts/input/helpers/fail-or-finish.ts +++ b/frontend/src/ts/input/helpers/fail-or-finish.ts @@ -36,18 +36,16 @@ export function checkIfFailedDueToMinBurst(options: { /** * Check if the test should fail due to difficulty settings * @param options - Options object - * @param options.data - Input data - * @param options.inputValue - Current test input result + * @param options.testInputWithData - Current test input result (after adding data) * @param options.correct - Was the last input correct * @param options.isCommitData - Whether the entered character finishes the word */ export function checkIfFailedDueToDifficulty(options: { - data: string; - inputValue: string; + testInputWithData: string; correct: boolean; isCommitData: boolean; }): boolean { - const { data, inputValue, correct, isCommitData } = options; + const { testInputWithData, correct, isCommitData } = options; if (Config.mode === "zen") return false; @@ -55,7 +53,7 @@ export function checkIfFailedDueToDifficulty(options: { Config.difficulty === "expert" && !correct && isCommitData && - (inputValue + data).length > 1; + testInputWithData.length > 1; const shouldFailDueToMaster = Config.difficulty === "master" && !correct; From a8b2e7b4f526f214f128ecaa914b08812bedb361 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:13:11 +0300 Subject: [PATCH 15/42] Fix tests --- .../input/helpers/fail-or-finish.spec.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/frontend/__tests__/input/helpers/fail-or-finish.spec.ts b/frontend/__tests__/input/helpers/fail-or-finish.spec.ts index 0d9faaaaf21f..310495155700 100644 --- a/frontend/__tests__/input/helpers/fail-or-finish.spec.ts +++ b/frontend/__tests__/input/helpers/fail-or-finish.spec.ts @@ -139,7 +139,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "zen mode, master - never fails", config: { mode: "zen", difficulty: "master" }, correct: false, - spaceOrNewline: true, + isCommitData: true, input: "hello", expected: false, }, @@ -147,7 +147,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "zen mode - never fails", config: { mode: "zen", difficulty: "normal" }, correct: false, - spaceOrNewline: true, + isCommitData: true, input: "hello", expected: false, }, @@ -156,7 +156,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "normal typing incorrect- never fails", config: { difficulty: "normal" }, correct: false, - spaceOrNewline: false, + isCommitData: false, input: "hello", expected: false, }, @@ -164,7 +164,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "normal typing space incorrect - never fails", config: { difficulty: "normal" }, correct: false, - spaceOrNewline: true, + isCommitData: true, input: "hello", expected: false, }, @@ -172,7 +172,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "normal typing correct - never fails", config: { difficulty: "normal" }, correct: true, - spaceOrNewline: false, + isCommitData: false, input: "hello", expected: false, }, @@ -180,7 +180,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "normal typing space correct - never fails", config: { difficulty: "normal" }, correct: true, - spaceOrNewline: true, + isCommitData: true, input: "hello", expected: false, }, @@ -189,7 +189,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "expert - fail if incorrect space", config: { difficulty: "expert" }, correct: false, - spaceOrNewline: true, + isCommitData: true, input: "he", expected: true, }, @@ -197,7 +197,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "expert - dont fail if space is the first character", config: { difficulty: "expert" }, correct: false, - spaceOrNewline: true, + isCommitData: true, input: " ", expected: false, }, @@ -205,7 +205,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "expert: - dont fail if just typing", config: { difficulty: "expert" }, correct: false, - spaceOrNewline: false, + isCommitData: false, input: "h", expected: false, }, @@ -213,7 +213,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "expert: - dont fail if just typing", config: { difficulty: "expert" }, correct: true, - spaceOrNewline: false, + isCommitData: false, input: "h", expected: false, }, @@ -222,7 +222,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "master - fail if incorrect char", config: { difficulty: "master" }, correct: false, - spaceOrNewline: false, + isCommitData: false, input: "h", expected: true, }, @@ -230,7 +230,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "master - fail if incorrect first space", config: { difficulty: "master" }, correct: true, - spaceOrNewline: true, + isCommitData: true, input: " ", expected: false, }, @@ -238,7 +238,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "master - dont fail if correct char", config: { difficulty: "master" }, correct: true, - spaceOrNewline: false, + isCommitData: false, input: "a", expected: false, }, @@ -246,16 +246,16 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "master - dont fail if correct space", config: { difficulty: "master" }, correct: true, - spaceOrNewline: true, + isCommitData: true, input: " ", expected: false, }, - ])("$desc", ({ config, correct, spaceOrNewline, input, expected }) => { + ])("$desc", ({ config, correct, isCommitData, input, expected }) => { replaceConfig(config as any); const result = checkIfFailedDueToDifficulty({ testInputWithData: input, correct, - spaceOrNewline, + isCommitData, }); expect(result).toBe(expected); }); From 4a0cf88d157748d711698f773506c859563719ec Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:17:55 +0300 Subject: [PATCH 16/42] Guard + comment --- frontend/src/ts/input/handlers/insert-text.ts | 1 + frontend/src/ts/input/helpers/validation.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 090432d9e403..7938a1a831fa 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -134,6 +134,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { correctShiftUsed, }); + // Whether this character finishes the current word const isCommitData = isCommitChar({ data, inputValue: testInput }); // does this input try to move to the next word (before removeLastChar can block it) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index f195ae2d0a39..b180fa69cc90 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -69,6 +69,10 @@ export function isJumpToNextWordBlocked(options: { }): boolean { const { data, inputValue } = options; + if (Config.mode === "zen") { + return false; + } + const correct = isWordCorrect({ ...options, correctShiftUsed: null }); const stopOnErrorLetterAndIncorrect = From 24f6f024f6721c14e0bf56b52296ac62328a06bd Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:23:30 +0300 Subject: [PATCH 17/42] Refactor --- .../src/ts/input/handlers/before-insert-text.ts | 15 ++++++++------- frontend/src/ts/input/handlers/insert-text.ts | 15 ++++++++------- frontend/src/ts/input/helpers/validation.ts | 15 --------------- 3 files changed, 16 insertions(+), 29 deletions(-) diff --git a/frontend/src/ts/input/handlers/before-insert-text.ts b/frontend/src/ts/input/handlers/before-insert-text.ts index 5ea865175b38..4e41216f0e7d 100644 --- a/frontend/src/ts/input/handlers/before-insert-text.ts +++ b/frontend/src/ts/input/handlers/before-insert-text.ts @@ -7,7 +7,7 @@ import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import { isSpace } from "../../utils/strings"; import { getInputElementValue } from "../input-element"; import { isAwaitingNextWord } from "../state"; -import { shouldJumpToNextWord, isCommitChar } from "../helpers/validation"; +import { isJumpToNextWordBlocked, isCommitChar } from "../helpers/validation"; import * as SlowTimer from "../../legacy-states/slow-timer"; import { wordsHaveNewline } from "../../states/test"; @@ -58,12 +58,13 @@ export function onBeforeInsertText(data: string): boolean { inputValue, }); - const shouldGoToNextWord = shouldJumpToNextWord({ - data, - inputValue, - targetWord: TestWords.words.getCurrentText(), - isCommitData, - }); + const shouldGoToNextWord = + isCommitData && + !isJumpToNextWordBlocked({ + data, + inputValue, + targetWord: TestWords.words.getCurrentText(), + }); // block input if the word is too long const inputLimit = diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 7938a1a831fa..6485ba60ad12 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -31,7 +31,7 @@ import { onBeforeInsertText } from "./before-insert-text"; import { isCharCorrect, isWordCorrect, - shouldJumpToNextWord, + isJumpToNextWordBlocked, isCommitChar, } from "../helpers/validation"; import { getCurrentInput, logTestEvent } from "../../test/events/data"; @@ -138,12 +138,13 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const isCommitData = isCommitChar({ data, inputValue: testInput }); // does this input try to move to the next word (before removeLastChar can block it) - const goingToNextWord = shouldJumpToNextWord({ - data, - inputValue: testInput, - targetWord: currentWord, - isCommitData, - }); + const goingToNextWord = + isCommitData && + !isJumpToNextWordBlocked({ + data, + inputValue: testInput, + targetWord: currentWord, + }); // when moving to the next word, correctness is word-level (a correct word-completing // space has charCorrect === false, so charCorrect can't be used below) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index b180fa69cc90..4a377c553ec1 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -101,18 +101,3 @@ export function isCommitChar(options: { return charIsSpace || charIsNewline || noSpaceForce; } - -export function shouldJumpToNextWord(options: { - data: string; - inputValue: string; - targetWord: string; - isCommitData: boolean; -}): boolean { - const { data, inputValue, targetWord, isCommitData } = options; - const isNextWordBlocked = isJumpToNextWordBlocked({ - data, - inputValue, - targetWord, - }); - return isCommitData && !isNextWordBlocked; -} From 332da717b51a82d0904ca7f8ac7dd8d3bbae89a1 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:30:46 +0300 Subject: [PATCH 18/42] Refactor --- .../input/helpers/validation.spec.ts | 9 +++-- .../ts/input/handlers/before-insert-text.ts | 13 ++----- frontend/src/ts/input/handlers/insert-text.ts | 14 +++---- frontend/src/ts/input/helpers/validation.ts | 37 ++++++++++--------- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/frontend/__tests__/input/helpers/validation.spec.ts b/frontend/__tests__/input/helpers/validation.spec.ts index efeed75a0c1d..d30a0e029c8c 100644 --- a/frontend/__tests__/input/helpers/validation.spec.ts +++ b/frontend/__tests__/input/helpers/validation.spec.ts @@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach, afterAll } from "vitest"; import { isCharCorrect, isWordCorrect, - isJumpToNextWordBlocked, + shouldJumpToNextWord, } from "../../../src/ts/input/helpers/validation"; import { __testing } from "../../../src/ts/config/testing"; import * as FunboxList from "../../../src/ts/test/funbox/list"; @@ -13,6 +13,7 @@ const { replaceConfig } = __testing; // Mock dependencies vi.mock("../../../src/ts/test/funbox/list", () => ({ findSingleActiveFunboxWithFunction: vi.fn(), + isFunboxActiveWithProperty: vi.fn(), })); vi.mock("../../../src/ts/utils/strings", async () => { @@ -155,7 +156,7 @@ describe("isCharCorrect", () => { }); }); -describe("isJumpToNextWordBlocked", () => { +describe("shouldJumpToNextWord", () => { beforeEach(() => { replaceConfig({ mode: "time", @@ -172,7 +173,7 @@ describe("isJumpToNextWordBlocked", () => { it("returns false in zen mode", () => { replaceConfig({ mode: "zen" }); expect( - isJumpToNextWordBlocked({ + shouldJumpToNextWord({ data: " ", inputValue: "test", targetWord: "test", @@ -276,7 +277,7 @@ describe("isJumpToNextWordBlocked", () => { ])("$desc", ({ inputValue, targetWord, config, expected }) => { replaceConfig(config as any); expect( - isJumpToNextWordBlocked({ + shouldJumpToNextWord({ data: " ", inputValue, targetWord, diff --git a/frontend/src/ts/input/handlers/before-insert-text.ts b/frontend/src/ts/input/handlers/before-insert-text.ts index 4e41216f0e7d..ded765fc89c4 100644 --- a/frontend/src/ts/input/handlers/before-insert-text.ts +++ b/frontend/src/ts/input/handlers/before-insert-text.ts @@ -7,7 +7,7 @@ import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import { isSpace } from "../../utils/strings"; import { getInputElementValue } from "../input-element"; import { isAwaitingNextWord } from "../state"; -import { isJumpToNextWordBlocked, isCommitChar } from "../helpers/validation"; +import { shouldJumpToNextWord } from "../helpers/validation"; import * as SlowTimer from "../../legacy-states/slow-timer"; import { wordsHaveNewline } from "../../states/test"; @@ -53,19 +53,12 @@ export function onBeforeInsertText(data: string): boolean { return true; } - const isCommitData = isCommitChar({ + const shouldGoToNextWord = shouldJumpToNextWord({ data, inputValue, + targetWord: TestWords.words.getCurrentText(), }); - const shouldGoToNextWord = - isCommitData && - !isJumpToNextWordBlocked({ - data, - inputValue, - targetWord: TestWords.words.getCurrentText(), - }); - // block input if the word is too long const inputLimit = Config.mode === "zen" ? 30 : TestWords.words.getCurrentText().length + 20; diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 6485ba60ad12..cd44ff03960c 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -31,7 +31,7 @@ import { onBeforeInsertText } from "./before-insert-text"; import { isCharCorrect, isWordCorrect, - isJumpToNextWordBlocked, + shouldJumpToNextWord, isCommitChar, } from "../helpers/validation"; import { getCurrentInput, logTestEvent } from "../../test/events/data"; @@ -138,13 +138,11 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const isCommitData = isCommitChar({ data, inputValue: testInput }); // does this input try to move to the next word (before removeLastChar can block it) - const goingToNextWord = - isCommitData && - !isJumpToNextWordBlocked({ - data, - inputValue: testInput, - targetWord: currentWord, - }); + const goingToNextWord = shouldJumpToNextWord({ + data, + inputValue: testInput, + targetWord: currentWord, + }); // when moving to the next word, correctness is word-level (a correct word-completing // space has charCorrect === false, so charCorrect can't be used below) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 4a377c553ec1..8943ce5d9428 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -54,6 +54,21 @@ export function isWordCorrect(options: { return finalInputValue === targetWord; } +export function isCommitChar(options: { + data: string; + inputValue: string; +}): boolean { + const { data, inputValue } = options; + + const charIsSpace = isSpace(data); + const charIsNewline = data === "\n"; + const noSpaceForce = + isFunboxActiveWithProperty("nospace") && + (inputValue + data).length === TestWords.words.getCurrentText().length; + + return charIsSpace || charIsNewline || noSpaceForce; +} + /** * Determines if a space character should be inserted as a character, or act * as a "control character" (moving to the next word) @@ -62,7 +77,7 @@ export function isWordCorrect(options: { * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) * @param options.targetWord - Target word */ -export function isJumpToNextWordBlocked(options: { +export function shouldJumpToNextWord(options: { data: string; inputValue: string; targetWord: string; @@ -83,21 +98,9 @@ export function isJumpToNextWordBlocked(options: { inputValue.length === 0 && (Config.strictSpace || Config.difficulty !== "normal"); return ( - stopOnErrorLetterAndIncorrect || stopOnErrorWordAndIncorrect || strictSpace + isCommitChar({ data, inputValue }) && + (stopOnErrorLetterAndIncorrect || + stopOnErrorWordAndIncorrect || + strictSpace) ); } - -export function isCommitChar(options: { - data: string; - inputValue: string; -}): boolean { - const { data, inputValue } = options; - - const charIsSpace = isSpace(data); - const charIsNewline = data === "\n"; - const noSpaceForce = - isFunboxActiveWithProperty("nospace") && - (inputValue + data).length === TestWords.words.getCurrentText().length; - - return charIsSpace || charIsNewline || noSpaceForce; -} From 2895c0fa44ed90913f2c241e52347baace2ff757 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:33:36 +0300 Subject: [PATCH 19/42] Comment --- frontend/src/ts/input/helpers/validation.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 8943ce5d9428..a4fb8d10149e 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -54,6 +54,12 @@ export function isWordCorrect(options: { return finalInputValue === targetWord; } +/** + * Determines if a character should commit the current word + * @param options - Options object + * @param options.data - Input data + * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) + */ export function isCommitChar(options: { data: string; inputValue: string; @@ -70,8 +76,7 @@ export function isCommitChar(options: { } /** - * Determines if a space character should be inserted as a character, or act - * as a "control character" (moving to the next word) + * Determines if we should move on to the next word or not. * @param options - Options object * @param options.data - Input data * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) From c8a8091872aac9fc1dbb0cbbd9646e8d707b1be7 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:27:45 +0300 Subject: [PATCH 20/42] Rename --- .../input/helpers/fail-or-finish.spec.ts | 32 +++++++++---------- frontend/src/ts/input/handlers/insert-text.ts | 6 ++-- .../src/ts/input/helpers/fail-or-finish.ts | 8 ++--- frontend/src/ts/input/helpers/validation.ts | 4 +-- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/frontend/__tests__/input/helpers/fail-or-finish.spec.ts b/frontend/__tests__/input/helpers/fail-or-finish.spec.ts index 310495155700..3e10cb0d8a53 100644 --- a/frontend/__tests__/input/helpers/fail-or-finish.spec.ts +++ b/frontend/__tests__/input/helpers/fail-or-finish.spec.ts @@ -139,7 +139,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "zen mode, master - never fails", config: { mode: "zen", difficulty: "master" }, correct: false, - isCommitData: true, + isCommitChar: true, input: "hello", expected: false, }, @@ -147,7 +147,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "zen mode - never fails", config: { mode: "zen", difficulty: "normal" }, correct: false, - isCommitData: true, + isCommitChar: true, input: "hello", expected: false, }, @@ -156,7 +156,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "normal typing incorrect- never fails", config: { difficulty: "normal" }, correct: false, - isCommitData: false, + isCommitChar: false, input: "hello", expected: false, }, @@ -164,7 +164,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "normal typing space incorrect - never fails", config: { difficulty: "normal" }, correct: false, - isCommitData: true, + isCommitChar: true, input: "hello", expected: false, }, @@ -172,7 +172,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "normal typing correct - never fails", config: { difficulty: "normal" }, correct: true, - isCommitData: false, + isCommitChar: false, input: "hello", expected: false, }, @@ -180,7 +180,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "normal typing space correct - never fails", config: { difficulty: "normal" }, correct: true, - isCommitData: true, + isCommitChar: true, input: "hello", expected: false, }, @@ -189,7 +189,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "expert - fail if incorrect space", config: { difficulty: "expert" }, correct: false, - isCommitData: true, + isCommitChar: true, input: "he", expected: true, }, @@ -197,7 +197,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "expert - dont fail if space is the first character", config: { difficulty: "expert" }, correct: false, - isCommitData: true, + isCommitChar: true, input: " ", expected: false, }, @@ -205,7 +205,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "expert: - dont fail if just typing", config: { difficulty: "expert" }, correct: false, - isCommitData: false, + isCommitChar: false, input: "h", expected: false, }, @@ -213,7 +213,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "expert: - dont fail if just typing", config: { difficulty: "expert" }, correct: true, - isCommitData: false, + isCommitChar: false, input: "h", expected: false, }, @@ -222,7 +222,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "master - fail if incorrect char", config: { difficulty: "master" }, correct: false, - isCommitData: false, + isCommitChar: false, input: "h", expected: true, }, @@ -230,7 +230,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "master - fail if incorrect first space", config: { difficulty: "master" }, correct: true, - isCommitData: true, + isCommitChar: true, input: " ", expected: false, }, @@ -238,7 +238,7 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "master - dont fail if correct char", config: { difficulty: "master" }, correct: true, - isCommitData: false, + isCommitChar: false, input: "a", expected: false, }, @@ -246,16 +246,16 @@ describe("checkIfFailedDueToDifficulty", () => { desc: "master - dont fail if correct space", config: { difficulty: "master" }, correct: true, - isCommitData: true, + isCommitChar: true, input: " ", expected: false, }, - ])("$desc", ({ config, correct, isCommitData, input, expected }) => { + ])("$desc", ({ config, correct, isCommitChar, input, expected }) => { replaceConfig(config as any); const result = checkIfFailedDueToDifficulty({ testInputWithData: input, correct, - isCommitData, + isCommitChar, }); expect(result).toBe(expected); }); diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index cd44ff03960c..cac9beec157b 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -32,7 +32,7 @@ import { isCharCorrect, isWordCorrect, shouldJumpToNextWord, - isCommitChar, + isCommitCharacter, } from "../helpers/validation"; import { getCurrentInput, logTestEvent } from "../../test/events/data"; @@ -135,7 +135,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { }); // Whether this character finishes the current word - const isCommitData = isCommitChar({ data, inputValue: testInput }); + const isCommitChar = isCommitCharacter({ data, inputValue: testInput }); // does this input try to move to the next word (before removeLastChar can block it) const goingToNextWord = shouldJumpToNextWord({ @@ -260,7 +260,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { checkIfFailedDueToDifficulty({ testInputWithData: testInput + data, correct, - isCommitData, + isCommitChar, }) ) { TestLogic.fail("difficulty"); diff --git a/frontend/src/ts/input/helpers/fail-or-finish.ts b/frontend/src/ts/input/helpers/fail-or-finish.ts index 2a093ea37d8b..761d8192f833 100644 --- a/frontend/src/ts/input/helpers/fail-or-finish.ts +++ b/frontend/src/ts/input/helpers/fail-or-finish.ts @@ -38,21 +38,21 @@ export function checkIfFailedDueToMinBurst(options: { * @param options - Options object * @param options.testInputWithData - Current test input result (after adding data) * @param options.correct - Was the last input correct - * @param options.isCommitData - Whether the entered character finishes the word + * @param options.isCommitChar - Whether the entered character finishes the word */ export function checkIfFailedDueToDifficulty(options: { testInputWithData: string; correct: boolean; - isCommitData: boolean; + isCommitChar: boolean; }): boolean { - const { testInputWithData, correct, isCommitData } = options; + const { testInputWithData, correct, isCommitChar } = options; if (Config.mode === "zen") return false; const shouldFailDueToExpert = Config.difficulty === "expert" && !correct && - isCommitData && + isCommitChar && testInputWithData.length > 1; const shouldFailDueToMaster = Config.difficulty === "master" && !correct; diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index a4fb8d10149e..dcb87c71c518 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -60,7 +60,7 @@ export function isWordCorrect(options: { * @param options.data - Input data * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) */ -export function isCommitChar(options: { +export function isCommitCharacter(options: { data: string; inputValue: string; }): boolean { @@ -103,7 +103,7 @@ export function shouldJumpToNextWord(options: { inputValue.length === 0 && (Config.strictSpace || Config.difficulty !== "normal"); return ( - isCommitChar({ data, inputValue }) && + isCommitCharacter({ data, inputValue }) && (stopOnErrorLetterAndIncorrect || stopOnErrorWordAndIncorrect || strictSpace) From a2a8a57fbd7713159b5115e0b70beedc08dd7055 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:32:49 +0300 Subject: [PATCH 21/42] Less calls --- frontend/src/ts/input/handlers/insert-text.ts | 1 + frontend/src/ts/input/helpers/validation.ts | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index cac9beec157b..ca5fa1c940e2 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -142,6 +142,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { data, inputValue: testInput, targetWord: currentWord, + isCommitChar, }); // when moving to the next word, correctness is word-level (a correct word-completing diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index dcb87c71c518..bd802f42bbb1 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -81,13 +81,19 @@ export function isCommitCharacter(options: { * @param options.data - Input data * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) * @param options.targetWord - Target word + * @param options.isCommitChar - Whether this character commits the current word */ export function shouldJumpToNextWord(options: { data: string; inputValue: string; targetWord: string; + isCommitChar?: boolean; }): boolean { - const { data, inputValue } = options; + const { + data, + inputValue, + isCommitChar = isCommitCharacter({ data, inputValue }), + } = options; if (Config.mode === "zen") { return false; @@ -102,8 +108,9 @@ export function shouldJumpToNextWord(options: { isSpace(data) && inputValue.length === 0 && (Config.strictSpace || Config.difficulty !== "normal"); + return ( - isCommitCharacter({ data, inputValue }) && + isCommitChar && (stopOnErrorLetterAndIncorrect || stopOnErrorWordAndIncorrect || strictSpace) From 82d73611980d973ea5a96fd6adcffe8f364c8031 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:33:33 +0300 Subject: [PATCH 22/42] Comment --- frontend/src/ts/input/handlers/insert-text.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index ca5fa1c940e2..a4d5059c2c38 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -134,7 +134,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { correctShiftUsed, }); - // Whether this character finishes the current word + // Whether this character commits the current word const isCommitChar = isCommitCharacter({ data, inputValue: testInput }); // does this input try to move to the next word (before removeLastChar can block it) From 1ea7034a9480bd8b77e54289dbfa387a476a0e45 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:35:19 +0300 Subject: [PATCH 23/42] Invert --- frontend/src/ts/input/helpers/validation.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index bd802f42bbb1..9280893ff485 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -111,8 +111,10 @@ export function shouldJumpToNextWord(options: { return ( isCommitChar && - (stopOnErrorLetterAndIncorrect || + !( + stopOnErrorLetterAndIncorrect || stopOnErrorWordAndIncorrect || - strictSpace) + strictSpace + ) ); } From 68f9d70e28c2f873a848c0af05f9975219b82ee4 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:41:25 +0300 Subject: [PATCH 24/42] Comment --- frontend/src/ts/input/helpers/fail-or-finish.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ts/input/helpers/fail-or-finish.ts b/frontend/src/ts/input/helpers/fail-or-finish.ts index 761d8192f833..22f6f2f551fc 100644 --- a/frontend/src/ts/input/helpers/fail-or-finish.ts +++ b/frontend/src/ts/input/helpers/fail-or-finish.ts @@ -38,7 +38,7 @@ export function checkIfFailedDueToMinBurst(options: { * @param options - Options object * @param options.testInputWithData - Current test input result (after adding data) * @param options.correct - Was the last input correct - * @param options.isCommitChar - Whether the entered character finishes the word + * @param options.isCommitChar - Whether the entered character commits the current word */ export function checkIfFailedDueToDifficulty(options: { testInputWithData: string; From a4359674bde4d73b7152949e40408555bdc11a57 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:49:36 +0300 Subject: [PATCH 25/42] Options --- frontend/src/ts/input/helpers/validation.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 9280893ff485..90e749208c0d 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -92,6 +92,7 @@ export function shouldJumpToNextWord(options: { const { data, inputValue, + targetWord, isCommitChar = isCommitCharacter({ data, inputValue }), } = options; @@ -99,7 +100,12 @@ export function shouldJumpToNextWord(options: { return false; } - const correct = isWordCorrect({ ...options, correctShiftUsed: null }); + const correct = isWordCorrect({ + data, + inputValue, + targetWord, + correctShiftUsed: null, + }); const stopOnErrorLetterAndIncorrect = Config.stopOnError === "letter" && !correct; From 3ed2414ac4c4bc08ee0940d4eb35759ee97b2bd4 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:51:56 +0300 Subject: [PATCH 26/42] Type --- frontend/src/ts/input/helpers/validation.ts | 49 ++++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 90e749208c0d..c8f851c76aef 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -3,6 +3,12 @@ import { isSpace } from "../../utils/strings"; import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import * as TestWords from "../../test/test-words"; +type sharedOptions = { + data: string; + inputValue: string; + targetWord: string; +}; + /** * Check if the input data is correct * @param options - Options object @@ -11,12 +17,11 @@ import * as TestWords from "../../test/test-words"; * @param options.targetWord - Target word * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled */ -export function isCharCorrect(options: { - data: string; - inputValue: string; - targetWord: string; - correctShiftUsed: boolean | null; //null means disabled -}): boolean { +export function isCharCorrect( + options: sharedOptions & { + correctShiftUsed: boolean | null; //null means disabled + }, +): boolean { const { data, inputValue, targetWord, correctShiftUsed } = options; if (Config.mode === "zen") return true; @@ -39,12 +44,11 @@ export function isCharCorrect(options: { * @param options.targetWord - Target word * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled */ -export function isWordCorrect(options: { - data: string; - inputValue: string; - targetWord: string; - correctShiftUsed: boolean | null; //null means disabled -}): boolean { +export function isWordCorrect( + options: sharedOptions & { + correctShiftUsed: boolean | null; //null means disabled + }, +): boolean { const { data, inputValue, targetWord, correctShiftUsed } = options; if (Config.mode === "zen") return true; @@ -60,10 +64,12 @@ export function isWordCorrect(options: { * @param options.data - Input data * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) */ -export function isCommitCharacter(options: { - data: string; - inputValue: string; -}): boolean { +export function isCommitCharacter( + options: Omit & { + data: string; + inputValue: string; + }, +): boolean { const { data, inputValue } = options; const charIsSpace = isSpace(data); @@ -83,12 +89,11 @@ export function isCommitCharacter(options: { * @param options.targetWord - Target word * @param options.isCommitChar - Whether this character commits the current word */ -export function shouldJumpToNextWord(options: { - data: string; - inputValue: string; - targetWord: string; - isCommitChar?: boolean; -}): boolean { +export function shouldJumpToNextWord( + options: sharedOptions & { + isCommitChar?: boolean; + }, +): boolean { const { data, inputValue, From 3303c4d70c79249a812fa08355a89ce7a9d76662 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:53:07 +0300 Subject: [PATCH 27/42] Rename --- frontend/src/ts/input/helpers/validation.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index c8f851c76aef..37171f67e177 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -3,7 +3,7 @@ import { isSpace } from "../../utils/strings"; import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import * as TestWords from "../../test/test-words"; -type sharedOptions = { +type SharedOptions = { data: string; inputValue: string; targetWord: string; @@ -18,7 +18,7 @@ type sharedOptions = { * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled */ export function isCharCorrect( - options: sharedOptions & { + options: SharedOptions & { correctShiftUsed: boolean | null; //null means disabled }, ): boolean { @@ -45,7 +45,7 @@ export function isCharCorrect( * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled */ export function isWordCorrect( - options: sharedOptions & { + options: SharedOptions & { correctShiftUsed: boolean | null; //null means disabled }, ): boolean { @@ -65,7 +65,7 @@ export function isWordCorrect( * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) */ export function isCommitCharacter( - options: Omit & { + options: Omit & { data: string; inputValue: string; }, @@ -90,7 +90,7 @@ export function isCommitCharacter( * @param options.isCommitChar - Whether this character commits the current word */ export function shouldJumpToNextWord( - options: sharedOptions & { + options: SharedOptions & { isCommitChar?: boolean; }, ): boolean { From ce8d72351c05e39732a284521c0b6b8c20c8f160 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:53:54 +0300 Subject: [PATCH 28/42] Remove intersection --- frontend/src/ts/input/helpers/validation.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 37171f67e177..2b4fbbdea424 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -65,10 +65,7 @@ export function isWordCorrect( * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) */ export function isCommitCharacter( - options: Omit & { - data: string; - inputValue: string; - }, + options: Omit, ): boolean { const { data, inputValue } = options; From 4fe8adfc6b3ecfbcb12d65b19573b0d2bdccc86c Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:55:09 +0300 Subject: [PATCH 29/42] Revert "Remove intersection" This reverts commit ce8d72351c05e39732a284521c0b6b8c20c8f160. --- frontend/src/ts/input/helpers/validation.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 2b4fbbdea424..37171f67e177 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -65,7 +65,10 @@ export function isWordCorrect( * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) */ export function isCommitCharacter( - options: Omit, + options: Omit & { + data: string; + inputValue: string; + }, ): boolean { const { data, inputValue } = options; From b03d333cec979da641809b53fa7b1b100a909309 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:55:15 +0300 Subject: [PATCH 30/42] Revert "Rename" This reverts commit 3303c4d70c79249a812fa08355a89ce7a9d76662. --- frontend/src/ts/input/helpers/validation.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 37171f67e177..c8f851c76aef 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -3,7 +3,7 @@ import { isSpace } from "../../utils/strings"; import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import * as TestWords from "../../test/test-words"; -type SharedOptions = { +type sharedOptions = { data: string; inputValue: string; targetWord: string; @@ -18,7 +18,7 @@ type SharedOptions = { * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled */ export function isCharCorrect( - options: SharedOptions & { + options: sharedOptions & { correctShiftUsed: boolean | null; //null means disabled }, ): boolean { @@ -45,7 +45,7 @@ export function isCharCorrect( * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled */ export function isWordCorrect( - options: SharedOptions & { + options: sharedOptions & { correctShiftUsed: boolean | null; //null means disabled }, ): boolean { @@ -65,7 +65,7 @@ export function isWordCorrect( * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) */ export function isCommitCharacter( - options: Omit & { + options: Omit & { data: string; inputValue: string; }, @@ -90,7 +90,7 @@ export function isCommitCharacter( * @param options.isCommitChar - Whether this character commits the current word */ export function shouldJumpToNextWord( - options: SharedOptions & { + options: sharedOptions & { isCommitChar?: boolean; }, ): boolean { From 722a61a1089e7af4d54a11a275d44b3c28207421 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:55:20 +0300 Subject: [PATCH 31/42] Revert "Type" This reverts commit 3ed2414ac4c4bc08ee0940d4eb35759ee97b2bd4. --- frontend/src/ts/input/helpers/validation.ts | 49 +++++++++------------ 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index c8f851c76aef..90e749208c0d 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -3,12 +3,6 @@ import { isSpace } from "../../utils/strings"; import { isFunboxActiveWithProperty } from "../../test/funbox/list"; import * as TestWords from "../../test/test-words"; -type sharedOptions = { - data: string; - inputValue: string; - targetWord: string; -}; - /** * Check if the input data is correct * @param options - Options object @@ -17,11 +11,12 @@ type sharedOptions = { * @param options.targetWord - Target word * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled */ -export function isCharCorrect( - options: sharedOptions & { - correctShiftUsed: boolean | null; //null means disabled - }, -): boolean { +export function isCharCorrect(options: { + data: string; + inputValue: string; + targetWord: string; + correctShiftUsed: boolean | null; //null means disabled +}): boolean { const { data, inputValue, targetWord, correctShiftUsed } = options; if (Config.mode === "zen") return true; @@ -44,11 +39,12 @@ export function isCharCorrect( * @param options.targetWord - Target word * @param options.correctShiftUsed - Whether the correct shift state was used. Null means disabled */ -export function isWordCorrect( - options: sharedOptions & { - correctShiftUsed: boolean | null; //null means disabled - }, -): boolean { +export function isWordCorrect(options: { + data: string; + inputValue: string; + targetWord: string; + correctShiftUsed: boolean | null; //null means disabled +}): boolean { const { data, inputValue, targetWord, correctShiftUsed } = options; if (Config.mode === "zen") return true; @@ -64,12 +60,10 @@ export function isWordCorrect( * @param options.data - Input data * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) */ -export function isCommitCharacter( - options: Omit & { - data: string; - inputValue: string; - }, -): boolean { +export function isCommitCharacter(options: { + data: string; + inputValue: string; +}): boolean { const { data, inputValue } = options; const charIsSpace = isSpace(data); @@ -89,11 +83,12 @@ export function isCommitCharacter( * @param options.targetWord - Target word * @param options.isCommitChar - Whether this character commits the current word */ -export function shouldJumpToNextWord( - options: sharedOptions & { - isCommitChar?: boolean; - }, -): boolean { +export function shouldJumpToNextWord(options: { + data: string; + inputValue: string; + targetWord: string; + isCommitChar?: boolean; +}): boolean { const { data, inputValue, From cc66762ad00184ae8c3368a9cb62f83906af54b0 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 18:10:00 +0300 Subject: [PATCH 32/42] Fix --- frontend/src/ts/input/handlers/insert-text.ts | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index a4d5059c2c38..b10d30ced96f 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -145,16 +145,17 @@ export async function onInsertText(options: OnInsertTextParams): Promise { isCommitChar, }); + const wordCorrect = isWordCorrect({ + data, + inputValue: testInput, + targetWord: currentWord, + correctShiftUsed, + }); + // when moving to the next word, correctness is word-level (a correct word-completing // space has charCorrect === false, so charCorrect can't be used below) const correct = goingToNextWord - ? (funboxCorrect ?? - isWordCorrect({ - data, - inputValue: testInput, - targetWord: currentWord, - correctShiftUsed, - })) + ? (funboxCorrect ?? wordCorrect) : charCorrect; // handing cases where last char needs to be removed @@ -260,7 +261,12 @@ export async function onInsertText(options: OnInsertTextParams): Promise { if ( checkIfFailedDueToDifficulty({ testInputWithData: testInput + data, - correct, + // We need to use `wordCorrect` here instead of `correct`, because when stop on + // error = word and nospace is enabled and difficulty = expert, submitting an incorrect + // word will do letter comparison when calculating `correct` (as we aren't moving + // to the next word because of stop on error), but we always want to do word + // comparison for expert mode. + correct: wordCorrect, isCommitChar, }) ) { From 7eac0dd5a44dc31c5f6265bdad8957e514db0faf Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 18:11:04 +0300 Subject: [PATCH 33/42] Remove --- frontend/src/ts/input/handlers/insert-text.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index b10d30ced96f..160298902659 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -235,7 +235,6 @@ export async function onInsertText(options: OnInsertTextParams): Promise { /* Probably a good place to explain what the heck is going on with all these space related variables: - - spaceOrNewLine: did the user input a space or a new line? - shouldGoToNextWord: IF input is space and we DONT insert a space CHARACTER, we will TRY to go to the next word - increasedWordIndex: the only reason this is here because on the last word we dont move to the next word */ From f75ebf6427803188c652784059cae7387ea327df Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 18:14:19 +0300 Subject: [PATCH 34/42] Better --- frontend/src/ts/input/handlers/insert-text.ts | 11 +++++----- frontend/src/ts/input/helpers/validation.ts | 20 ++++++++++--------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 160298902659..e2f776c13e08 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -137,19 +137,20 @@ export async function onInsertText(options: OnInsertTextParams): Promise { // Whether this character commits the current word const isCommitChar = isCommitCharacter({ data, inputValue: testInput }); - // does this input try to move to the next word (before removeLastChar can block it) - const goingToNextWord = shouldJumpToNextWord({ + const wordCorrect = isWordCorrect({ data, inputValue: testInput, targetWord: currentWord, - isCommitChar, + correctShiftUsed, }); - const wordCorrect = isWordCorrect({ + // does this input try to move to the next word (before removeLastChar can block it) + const goingToNextWord = shouldJumpToNextWord({ data, inputValue: testInput, targetWord: currentWord, - correctShiftUsed, + isCommitChar, + wordCorrect, }); // when moving to the next word, correctness is word-level (a correct word-completing diff --git a/frontend/src/ts/input/helpers/validation.ts b/frontend/src/ts/input/helpers/validation.ts index 90e749208c0d..7f187f7e4fc4 100644 --- a/frontend/src/ts/input/helpers/validation.ts +++ b/frontend/src/ts/input/helpers/validation.ts @@ -82,34 +82,36 @@ export function isCommitCharacter(options: { * @param options.inputValue - Current input value (use getCurrentInput(), not input element value) * @param options.targetWord - Target word * @param options.isCommitChar - Whether this character commits the current word + * @param options.wordCorrect - Whether the current word is correct */ export function shouldJumpToNextWord(options: { data: string; inputValue: string; targetWord: string; isCommitChar?: boolean; + wordCorrect?: boolean; }): boolean { const { data, inputValue, targetWord, isCommitChar = isCommitCharacter({ data, inputValue }), + wordCorrect = isWordCorrect({ + data, + inputValue, + targetWord, + correctShiftUsed: null, + }), } = options; if (Config.mode === "zen") { return false; } - const correct = isWordCorrect({ - data, - inputValue, - targetWord, - correctShiftUsed: null, - }); - const stopOnErrorLetterAndIncorrect = - Config.stopOnError === "letter" && !correct; - const stopOnErrorWordAndIncorrect = Config.stopOnError === "word" && !correct; + Config.stopOnError === "letter" && !wordCorrect; + const stopOnErrorWordAndIncorrect = + Config.stopOnError === "word" && !wordCorrect; const strictSpace = isSpace(data) && inputValue.length === 0 && From 07d4dd99b4250bc0eab4a6176a5028f4c0028de2 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 23 Jun 2026 18:23:21 +0300 Subject: [PATCH 35/42] Fix tests --- .../__tests__/input/helpers/validation.spec.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/__tests__/input/helpers/validation.spec.ts b/frontend/__tests__/input/helpers/validation.spec.ts index d30a0e029c8c..1c82173a9dc5 100644 --- a/frontend/__tests__/input/helpers/validation.spec.ts +++ b/frontend/__tests__/input/helpers/validation.spec.ts @@ -193,7 +193,7 @@ describe("shouldJumpToNextWord", () => { strictSpace: false, difficulty: "normal", }, - expected: false, + expected: true, }, { desc: "submit incorrect word (stopOnError off)", @@ -204,7 +204,7 @@ describe("shouldJumpToNextWord", () => { strictSpace: false, difficulty: "normal", }, - expected: false, + expected: true, }, // Stop on error { @@ -216,7 +216,7 @@ describe("shouldJumpToNextWord", () => { strictSpace: false, difficulty: "normal", }, - expected: true, + expected: false, }, { desc: "insert space if incorrect (stopOnError word)", @@ -227,7 +227,7 @@ describe("shouldJumpToNextWord", () => { strictSpace: false, difficulty: "normal", }, - expected: true, + expected: false, }, { desc: "submit if correct (stopOnError letter)", @@ -238,7 +238,7 @@ describe("shouldJumpToNextWord", () => { strictSpace: false, difficulty: "normal", }, - expected: false, + expected: true, }, // Strict space / Difficulty { @@ -250,7 +250,7 @@ describe("shouldJumpToNextWord", () => { strictSpace: true, difficulty: "normal", }, - expected: true, + expected: false, }, { desc: "insert space if empty input (difficulty not normal - expert or master)", @@ -261,7 +261,7 @@ describe("shouldJumpToNextWord", () => { strictSpace: false, difficulty: "expert", }, - expected: true, + expected: false, }, { desc: "submit if not empty input (strictSpace on)", @@ -272,7 +272,7 @@ describe("shouldJumpToNextWord", () => { strictSpace: true, difficulty: "normal", }, - expected: false, + expected: true, }, ])("$desc", ({ inputValue, targetWord, config, expected }) => { replaceConfig(config as any); From c925cec1d4d401c9f32fc45c8177c851fef86d78 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 24 Jun 2026 09:36:42 +0300 Subject: [PATCH 36/42] Ref --- frontend/src/ts/input/handlers/insert-text.ts | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index e2f776c13e08..3dc07f333944 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -125,14 +125,6 @@ export async function onInsertText(options: OnInsertTextParams): Promise { data, currentWord[(testInput + data).length - 1] ?? "", ); - const charCorrect = - funboxCorrect ?? - isCharCorrect({ - data, - inputValue: testInput, - targetWord: currentWord, - correctShiftUsed, - }); // Whether this character commits the current word const isCommitChar = isCommitCharacter({ data, inputValue: testInput }); @@ -154,10 +146,16 @@ export async function onInsertText(options: OnInsertTextParams): Promise { }); // when moving to the next word, correctness is word-level (a correct word-completing - // space has charCorrect === false, so charCorrect can't be used below) - const correct = goingToNextWord - ? (funboxCorrect ?? wordCorrect) - : charCorrect; + // space has isCharCorrect === false, so isCharCorrect can't be used below) + const correct = + (funboxCorrect ?? goingToNextWord) + ? wordCorrect + : isCharCorrect({ + data, + inputValue: testInput, + targetWord: currentWord, + correctShiftUsed, + }); // handing cases where last char needs to be removed // this is here and not in beforeInsertText because we want to penalize for incorrect spaces From b8b3e441b1e7796fc7b5e560aee8ac404f3ce4bc Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 24 Jun 2026 09:39:23 +0300 Subject: [PATCH 37/42] Fix --- frontend/src/ts/input/handlers/insert-text.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 3dc07f333944..9dd6d5733d12 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -148,14 +148,15 @@ export async function onInsertText(options: OnInsertTextParams): Promise { // when moving to the next word, correctness is word-level (a correct word-completing // space has isCharCorrect === false, so isCharCorrect can't be used below) const correct = - (funboxCorrect ?? goingToNextWord) + funboxCorrect ?? + (goingToNextWord ? wordCorrect : isCharCorrect({ data, inputValue: testInput, targetWord: currentWord, correctShiftUsed, - }); + })); // handing cases where last char needs to be removed // this is here and not in beforeInsertText because we want to penalize for incorrect spaces From 87ec508ade3a43d8dbb1513fbeb3835361ad4264 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 24 Jun 2026 09:41:57 +0300 Subject: [PATCH 38/42] Better --- frontend/src/ts/input/handlers/insert-text.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 9dd6d5733d12..548224963baa 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -149,7 +149,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { // space has isCharCorrect === false, so isCharCorrect can't be used below) const correct = funboxCorrect ?? - (goingToNextWord + (goingToNextWord || wordCorrect ? wordCorrect : isCharCorrect({ data, From 1322d678c22a781257589b3bb6e005b061cc6a66 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 24 Jun 2026 09:49:17 +0300 Subject: [PATCH 39/42] Remove comment --- frontend/src/ts/input/handlers/insert-text.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 548224963baa..9a4a90abb585 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -145,11 +145,9 @@ export async function onInsertText(options: OnInsertTextParams): Promise { wordCorrect, }); - // when moving to the next word, correctness is word-level (a correct word-completing - // space has isCharCorrect === false, so isCharCorrect can't be used below) const correct = funboxCorrect ?? - (goingToNextWord || wordCorrect + (goingToNextWord ? wordCorrect : isCharCorrect({ data, From 04e40336a98ff62340696f8bc9a2ab7bef7d4728 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:09:19 +0300 Subject: [PATCH 40/42] Remove --- frontend/src/ts/input/handlers/insert-text.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 9a4a90abb585..50767715a30a 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -126,7 +126,6 @@ export async function onInsertText(options: OnInsertTextParams): Promise { currentWord[(testInput + data).length - 1] ?? "", ); - // Whether this character commits the current word const isCommitChar = isCommitCharacter({ data, inputValue: testInput }); const wordCorrect = isWordCorrect({ From 1d22a19e43b51a791292f5cb3f9140948df464a1 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:10:44 +0300 Subject: [PATCH 41/42] Add back --- frontend/src/ts/input/handlers/insert-text.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 50767715a30a..ab33aced985c 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -146,7 +146,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { const correct = funboxCorrect ?? - (goingToNextWord + (goingToNextWord || wordCorrect ? wordCorrect : isCharCorrect({ data, From a8c85b15544964b5ea452430d71eb889a07dfcc4 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:20:10 +0300 Subject: [PATCH 42/42] Tests --- frontend/__tests__/input/helpers/validation.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/__tests__/input/helpers/validation.spec.ts b/frontend/__tests__/input/helpers/validation.spec.ts index 1c82173a9dc5..39d400403459 100644 --- a/frontend/__tests__/input/helpers/validation.spec.ts +++ b/frontend/__tests__/input/helpers/validation.spec.ts @@ -208,7 +208,7 @@ describe("shouldJumpToNextWord", () => { }, // Stop on error { - desc: "insert space if incorrect (stopOnError letter)", + desc: "not submit if incorrect (stopOnError letter)", inputValue: "hel", targetWord: "hello", config: { @@ -219,7 +219,7 @@ describe("shouldJumpToNextWord", () => { expected: false, }, { - desc: "insert space if incorrect (stopOnError word)", + desc: "not submit if incorrect (stopOnError word)", inputValue: "hel", targetWord: "hello", config: { @@ -242,7 +242,7 @@ describe("shouldJumpToNextWord", () => { }, // Strict space / Difficulty { - desc: "insert space if empty input (strictSpace on)", + desc: "not submit if empty input (strictSpace on)", inputValue: "", targetWord: "hello", config: { @@ -253,7 +253,7 @@ describe("shouldJumpToNextWord", () => { expected: false, }, { - desc: "insert space if empty input (difficulty not normal - expert or master)", + desc: "not submit if empty input (difficulty not normal - expert or master)", inputValue: "", targetWord: "hello", config: {