From 1c5c6ee072f1b8d1c0ca20a6a9336b5c310b1ce0 Mon Sep 17 00:00:00 2001 From: Filip Sajdak Date: Tue, 23 Jun 2026 00:12:06 +0200 Subject: [PATCH] :bug: Accept fractional border radius in plugin API shape setters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ShapeProxy `borderRadius` setters (`borderRadius` and the four per-corner variants) validated with `sm/valid-safe-int?`, so a fractional radius (e.g. `shape.borderRadius = 7.5`) was rejected as invalid. The data model types `:r1`-`:r4` as `::sm/safe-number` (shape.cljc), the radius sidebar input only constrains `min 0` (not integer), and `set-radius-*` store the value verbatim — so the plugin API was stricter than the model. Same class of defect as the merged #9780. Switch those 5 guards to `sm/valid-safe-number?`, keeping the existing non-negative guard on the all-corners setter. Integer-only setters in the file (`getRange` bounds, `setParentIndex`) keep `valid-safe-int?`. Adds a regression test asserting fractional radius values are accepted (with throwValidationErrors enabled). Co-authored-by: Claude Opus 4.8 Signed-off-by: Filip Sajdak --- frontend/src/app/plugins/shape.cljs | 10 +++++----- .../plugins/page_active_validation_test.cljs | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index cccc32c625..b049788c05 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -422,7 +422,7 @@ (fn [self value] (let [id (obj/get self "$id")] (cond - (or (not (sm/valid-safe-int? value)) (< value 0)) + (or (not (sm/valid-safe-number? value)) (< value 0)) (u/not-valid plugin-id :borderRadius value) (not (r/check-permission plugin-id "content:write")) @@ -441,7 +441,7 @@ (fn [self value] (let [id (obj/get self "$id")] (cond - (not (sm/valid-safe-int? value)) + (not (sm/valid-safe-number? value)) (u/not-valid plugin-id :borderRadiusTopLeft value) (not (r/check-permission plugin-id "content:write")) @@ -460,7 +460,7 @@ (fn [self value] (let [id (obj/get self "$id")] (cond - (not (sm/valid-safe-int? value)) + (not (sm/valid-safe-number? value)) (u/not-valid plugin-id :borderRadiusTopRight value) (not (r/check-permission plugin-id "content:write")) @@ -479,7 +479,7 @@ (fn [self value] (let [id (obj/get self "$id")] (cond - (not (sm/valid-safe-int? value)) + (not (sm/valid-safe-number? value)) (u/not-valid plugin-id :borderRadiusBottomRight value) (not (r/check-permission plugin-id "content:write")) @@ -498,7 +498,7 @@ (fn [self value] (let [id (obj/get self "$id")] (cond - (not (sm/valid-safe-int? value)) + (not (sm/valid-safe-number? value)) (u/not-valid plugin-id :borderRadiusBottomLeft value) (not (r/check-permission plugin-id "content:write")) diff --git a/frontend/test/frontend_tests/plugins/page_active_validation_test.cljs b/frontend/test/frontend_tests/plugins/page_active_validation_test.cljs index 080e662dae..6f3651e81a 100644 --- a/frontend/test/frontend_tests/plugins/page_active_validation_test.cljs +++ b/frontend/test/frontend_tests/plugins/page_active_validation_test.cljs @@ -298,3 +298,21 @@ ["grid.leftPadding" #(set! (.-leftPadding grid) 1.5)]]] (t/is (not (throws? thunk)) (str label " must accept a fractional value"))))))) +(t/deftest test-border-radius-accepts-fractional-values + ;; Regression: the ShapeProxy borderRadius setters validated with + ;; `valid-safe-int?`, but the model types `:r1`-`:r4` as `safe-number` (and the + ;; radius sidebar input has min 0, not integer-only), so a fractional radius was + ;; wrongly rejected. With `throwValidationErrors` on and page2 active, a + ;; fractional radius must be accepted (no throw). + (thw/with-wasm-mocks* + (fn [] + (let [{:keys [store page2-id ^js rect]} (setup)] + (activate-page! store page2-id) + (doseq [[label thunk] + [["borderRadius" #(set! (.-borderRadius rect) 7.5)] + ["borderRadiusTopLeft" #(set! (.-borderRadiusTopLeft rect) 2.5)] + ["borderRadiusTopRight" #(set! (.-borderRadiusTopRight rect) 2.5)] + ["borderRadiusBottomRight" #(set! (.-borderRadiusBottomRight rect) 2.5)] + ["borderRadiusBottomLeft" #(set! (.-borderRadiusBottomLeft rect) 2.5)]]] + (t/is (not (throws? thunk)) (str label " must accept a fractional value"))))))) +