🐛 Fix Numeric inputs rejects values with leading whitespaces

This commit is contained in:
Eva Marco 2026-05-20 17:38:16 +02:00 committed by GitHub
parent d96442483e
commit 857aa4175c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 110 additions and 28 deletions

View File

@ -0,0 +1,80 @@
import { test, expect } from "@playwright/test";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WasmWorkspacePage.init(page);
await WasmWorkspacePage.mockConfigFlags(page, ["enable-feature-token-input"]);
});
test("BUG 14226: Numeric inputs in the design panel reject values with leading whitespace", async ({
page,
}) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.mockRPC(
/get\-file\?/,
"workspace/get-file-copy-paste.json",
);
await workspacePage.mockRPC(
"get-file-fragment?file-id=*&fragment-id=*",
"workspace/get-file-copy-paste-fragment.json",
);
await workspacePage.goToWorkspace({
fileId: "870f9f10-87b5-8137-8005-934804124660",
pageId: "870f9f10-87b5-8137-8005-934804124661",
});
// Select first shape
await page.getByTestId("layer-item").getByRole("button").first().click();
await workspacePage.layers.getByTestId("layer-row").nth(0).click();
// Check if measures section is visible
const measuresSection = workspacePage.rightSidebar.getByRole("region", {
name: "shape-measures-section",
});
await expect(measuresSection).toBeVisible();
// Width
const widthInput = measuresSection.getByRole("textbox", {
name: "Width",
exact: true,
});
await expect(widthInput).toHaveValue("360");
await widthInput.fill("100");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
await widthInput.fill(" 100");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
await widthInput.fill(" 100 ");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
await widthInput.fill("100 ");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
await widthInput.fill("98+2");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
await widthInput.fill("98 + 2");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
await widthInput.fill(" 98 + 2 ");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
await widthInput.fill(" 98+2 ");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
await widthInput.fill(" asdasdasdasd ");
await widthInput.press("Enter");
await expect(widthInput).toHaveValue("100");
});

View File

@ -291,33 +291,35 @@
(mf/use-fn
(mf/deps on-change update-input value nillable min max)
(fn [raw-value]
(if-let [parsed (parse-value raw-value (mf/ref-val last-value*) min max nillable)]
(when-not (= parsed (mf/ref-val last-value*))
(mf/set-ref-val! last-value* parsed)
(reset! token-applied-name* nil)
(when (fn? on-change)
(on-change parsed))
(mf/set-ref-val! raw-value* (fmt/format-number parsed))
(update-input (fmt/format-number parsed)))
(if (and nillable (empty? raw-value))
(let [raw-value (str/trim (str raw-value))]
(if-let [parsed (parse-value raw-value (mf/ref-val last-value*) min max nillable)]
(do
(mf/set-ref-val! last-value* nil)
(mf/set-ref-val! raw-value* "")
(reset! token-applied-name* nil)
(update-input "")
(when (fn? on-change)
(on-change nil)))
(when-not (= parsed (mf/ref-val last-value*))
(mf/set-ref-val! last-value* parsed)
(reset! token-applied-name* nil)
(when (fn? on-change)
(on-change parsed)))
(let [fallback-value (or (mf/ref-val last-value*) default)]
(mf/set-ref-val! raw-value* fallback-value)
(mf/set-ref-val! last-value* fallback-value)
(reset! token-applied-name* nil)
(update-input (fmt/format-number fallback-value))
(mf/set-ref-val! raw-value* (fmt/format-number parsed))
(update-input (fmt/format-number parsed)))
(when (and (fn? on-change) (not= fallback-value (str value)))
(on-change fallback-value)))))))
(if (and nillable (empty? raw-value))
(do
(mf/set-ref-val! last-value* nil)
(mf/set-ref-val! raw-value* "")
(reset! token-applied-name* nil)
(update-input "")
(when (fn? on-change)
(on-change nil)))
(let [fallback-value (or (mf/ref-val last-value*) default)]
(mf/set-ref-val! raw-value* fallback-value)
(mf/set-ref-val! last-value* fallback-value)
(reset! token-applied-name* nil)
(update-input (fmt/format-number fallback-value))
(when (and (fn? on-change) (not= fallback-value (str value)))
(on-change fallback-value))))))))
apply-token
(mf/use-fn
@ -466,7 +468,7 @@
(dom/prevent-default event)
(handle-focus-change options focused-id* new-index (mf/ref-val nodes-ref)))
(let [parsed (parse-value (mf/ref-val raw-value*) (mf/ref-val last-value*) min max nillable)
(let [parsed (parse-value (str/trim (mf/ref-val raw-value*)) (mf/ref-val last-value*) min max nillable)
current-value (or parsed default)
new-val (increment current-value step min max)]
(dom/prevent-default event)
@ -479,7 +481,7 @@
(dom/prevent-default event)
(handle-focus-change options focused-id* new-index (mf/ref-val nodes-ref)))
(let [parsed (parse-value (mf/ref-val raw-value*) (mf/ref-val last-value*) min max nillable)
(let [parsed (parse-value (str/trim (mf/ref-val raw-value*)) (mf/ref-val last-value*) min max nillable)
current-value (or parsed default)
new-val (decrement current-value step min max)]
(dom/prevent-default event)
@ -508,7 +510,7 @@
(let [inc? (->> (dom/get-delta-position event)
:y
(neg?))
parsed (parse-value (mf/ref-val raw-value*) (mf/ref-val last-value*) min max nillable)
parsed (parse-value (str/trim (mf/ref-val raw-value*)) (mf/ref-val last-value*) min max nillable)
current-value (or parsed default)
new-val (if inc?
(increment current-value step min max)
@ -527,7 +529,7 @@
has-token (some? (deref token-applied-name*))]
(when-not (or is-focused has-token)
(let [client-x (.-clientX event)
parsed (parse-value (mf/ref-val raw-value*) (mf/ref-val last-value*) min max nillable)
parsed (parse-value (str/trim (mf/ref-val raw-value*)) (mf/ref-val last-value*) min max nillable)
start-val (or parsed default 0)]
(mf/set-ref-val! drag-state* :maybe-dragging)
(mf/set-ref-val! drag-start-x* client-x)