🐛 Accept fractional border radius in plugin API shape setters

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 <noreply@anthropic.com>
Signed-off-by: Filip Sajdak <filip.sajdak@siili.com>
This commit is contained in:
Filip Sajdak 2026-06-23 00:12:06 +02:00 committed by Alonso Torres
parent c7ee54e849
commit 1c5c6ee072
2 changed files with 23 additions and 5 deletions

View File

@ -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"))

View File

@ -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")))))))