mirror of
https://github.com/penpot/penpot.git
synced 2026-08-04 20:09:05 +00:00
🐛 Fix array format in plugins properties (#10246)
This commit is contained in:
parent
ecabe7ec32
commit
bbf63e1136
@ -22,9 +22,10 @@
|
|||||||
(when kw (d/name kw)))
|
(when kw (d/name kw)))
|
||||||
|
|
||||||
(defn format-array
|
(defn format-array
|
||||||
|
"Formats a collection into a JS array, applying `format-fn` to each item.
|
||||||
|
Always returns an array; an empty array is returned for a nil/empty `coll`."
|
||||||
[format-fn coll]
|
[format-fn coll]
|
||||||
(when (some? coll)
|
(apply array (keep format-fn coll)))
|
||||||
(apply array (keep format-fn coll))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn format-mixed
|
(defn format-mixed
|
||||||
@ -174,9 +175,7 @@
|
|||||||
|
|
||||||
(defn format-shadows
|
(defn format-shadows
|
||||||
[shadows]
|
[shadows]
|
||||||
(if (some? shadows)
|
(format-array format-shadow shadows))
|
||||||
(format-array format-shadow shadows)
|
|
||||||
(array)))
|
|
||||||
|
|
||||||
;;export interface Fill {
|
;;export interface Fill {
|
||||||
;; fillColor?: string;
|
;; fillColor?: string;
|
||||||
@ -258,8 +257,7 @@
|
|||||||
|
|
||||||
(defn format-exports
|
(defn format-exports
|
||||||
[exports]
|
[exports]
|
||||||
(when (some? exports)
|
(format-array format-export exports))
|
||||||
(format-array format-export exports)))
|
|
||||||
|
|
||||||
;; export interface GuideColumnParams {
|
;; export interface GuideColumnParams {
|
||||||
;; color: { color: string; opacity: number };
|
;; color: { color: string; opacity: number };
|
||||||
@ -341,8 +339,7 @@
|
|||||||
|
|
||||||
(defn format-frame-guides
|
(defn format-frame-guides
|
||||||
[guides]
|
[guides]
|
||||||
(when (some? guides)
|
(format-array format-frame-guide guides))
|
||||||
(format-array format-frame-guide guides)))
|
|
||||||
|
|
||||||
;;interface PathCommand {
|
;;interface PathCommand {
|
||||||
;; command:
|
;; command:
|
||||||
@ -396,8 +393,7 @@
|
|||||||
|
|
||||||
(defn format-path-content
|
(defn format-path-content
|
||||||
[content]
|
[content]
|
||||||
(when (some? content)
|
(format-array format-command content))
|
||||||
(format-array format-command content)))
|
|
||||||
|
|
||||||
;; export type TrackType = 'flex' | 'fixed' | 'percent' | 'auto';
|
;; export type TrackType = 'flex' | 'fixed' | 'percent' | 'auto';
|
||||||
;;
|
;;
|
||||||
@ -414,8 +410,7 @@
|
|||||||
|
|
||||||
(defn format-tracks
|
(defn format-tracks
|
||||||
[tracks]
|
[tracks]
|
||||||
(when (some? tracks)
|
(format-array format-track tracks))
|
||||||
(format-array format-track tracks)))
|
|
||||||
|
|
||||||
|
|
||||||
;; export interface Dissolve {
|
;; export interface Dissolve {
|
||||||
|
|||||||
@ -382,3 +382,23 @@
|
|||||||
(t/is (pos? (thw/call-count :clean-modifiers)))
|
(t/is (pos? (thw/call-count :clean-modifiers)))
|
||||||
(t/is (pos? (thw/call-count :set-structure-modifiers)))
|
(t/is (pos? (thw/call-count :set-structure-modifiers)))
|
||||||
(t/is (pos? (thw/call-count :propagate-modifiers))))))))
|
(t/is (pos? (thw/call-count :propagate-modifiers))))))))
|
||||||
|
|
||||||
|
(t/deftest test-array-properties-return-empty-array-when-no-items
|
||||||
|
;; Array-typed properties must always return an array, never null,
|
||||||
|
;; even when the shape has no items for that property.
|
||||||
|
(thw/with-wasm-mocks*
|
||||||
|
(fn []
|
||||||
|
(let [store (ths/setup-store (cthf/sample-file :file1 :page-label :page1))
|
||||||
|
^js context (api/create-context "00000000-0000-0000-0000-000000000000")
|
||||||
|
_ (set! st/state store)
|
||||||
|
^js shape (.createRectangle context)]
|
||||||
|
|
||||||
|
(t/testing " - exports (no exports set)"
|
||||||
|
(let [exports (.-exports shape)]
|
||||||
|
(t/is (array? exports))
|
||||||
|
(t/is (= 0 (.-length exports)))))
|
||||||
|
|
||||||
|
(t/testing " - shadows (no shadows set)"
|
||||||
|
(let [shadows (.-shadows shape)]
|
||||||
|
(t/is (array? shadows))
|
||||||
|
(t/is (= 0 (.-length shadows)))))))))
|
||||||
|
|||||||
40
frontend/test/frontend_tests/plugins/format_test.cljs
Normal file
40
frontend/test/frontend_tests/plugins/format_test.cljs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC Sucursal en España SL
|
||||||
|
|
||||||
|
(ns frontend-tests.plugins.format-test
|
||||||
|
(:require
|
||||||
|
[app.plugins.format :as format]
|
||||||
|
[cljs.test :as t :include-macros true]))
|
||||||
|
|
||||||
|
(t/deftest test-format-array-always-returns-array
|
||||||
|
(t/testing "nil collection returns an empty array"
|
||||||
|
(let [result (format/format-array identity nil)]
|
||||||
|
(t/is (array? result))
|
||||||
|
(t/is (= 0 (.-length result)))))
|
||||||
|
|
||||||
|
(t/testing "empty collection returns an empty array"
|
||||||
|
(let [result (format/format-array identity [])]
|
||||||
|
(t/is (array? result))
|
||||||
|
(t/is (= 0 (.-length result)))))
|
||||||
|
|
||||||
|
(t/testing "non-empty collection maps each item"
|
||||||
|
(let [result (format/format-array inc [1 2 3])]
|
||||||
|
(t/is (array? result))
|
||||||
|
(t/is (= [2 3 4] (vec result)))))
|
||||||
|
|
||||||
|
(t/testing "items dropped by format-fn (nil) are removed"
|
||||||
|
(let [result (format/format-array #(when (odd? %) %) [1 2 3 4])]
|
||||||
|
(t/is (= [1 3] (vec result))))))
|
||||||
|
|
||||||
|
(t/deftest test-array-wrappers-return-empty-array-on-nil
|
||||||
|
;; Each wrapper backs a non-nullable array-typed Plugin API property and
|
||||||
|
;; must return an empty array (never nil) when the source collection is nil.
|
||||||
|
(t/are [result] (and (array? result) (= 0 (.-length result)))
|
||||||
|
(format/format-shadows nil)
|
||||||
|
(format/format-exports nil)
|
||||||
|
(format/format-frame-guides nil)
|
||||||
|
(format/format-tracks nil)
|
||||||
|
(format/format-path-content nil)))
|
||||||
@ -100,6 +100,15 @@
|
|||||||
|
|
||||||
(mock-page-initialized store page2-id))))
|
(mock-page-initialized store page2-id))))
|
||||||
|
|
||||||
|
(t/deftest test-flows-returns-empty-array-when-no-flows
|
||||||
|
;; page.flows must always return an array, even when the page has no flows
|
||||||
|
(let [{:keys [context]} (setup)
|
||||||
|
^js pages (.. context -currentFile -pages)
|
||||||
|
^js page1 (aget pages 0)
|
||||||
|
^js flows (.-flows page1)]
|
||||||
|
(t/is (array? flows))
|
||||||
|
(t/is (= 0 (.-length flows)))))
|
||||||
|
|
||||||
(t/deftest test-open-page-does-not-resolve-for-wrong-page
|
(t/deftest test-open-page-does-not-resolve-for-wrong-page
|
||||||
;; Promise should not resolve when a different page is initialized
|
;; Promise should not resolve when a different page is initialized
|
||||||
(t/async done
|
(t/async done
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
[frontend-tests.logic.pasting-in-containers-test]
|
[frontend-tests.logic.pasting-in-containers-test]
|
||||||
[frontend-tests.main-errors-test]
|
[frontend-tests.main-errors-test]
|
||||||
[frontend-tests.plugins.context-shapes-test]
|
[frontend-tests.plugins.context-shapes-test]
|
||||||
|
[frontend-tests.plugins.format-test]
|
||||||
[frontend-tests.plugins.interactions-test]
|
[frontend-tests.plugins.interactions-test]
|
||||||
[frontend-tests.plugins.page-active-validation-test]
|
[frontend-tests.plugins.page-active-validation-test]
|
||||||
[frontend-tests.plugins.page-test]
|
[frontend-tests.plugins.page-test]
|
||||||
@ -85,6 +86,7 @@
|
|||||||
frontend-tests.plugins.context-shapes-test
|
frontend-tests.plugins.context-shapes-test
|
||||||
frontend-tests.plugins.page-active-validation-test
|
frontend-tests.plugins.page-active-validation-test
|
||||||
frontend-tests.plugins.interactions-test
|
frontend-tests.plugins.interactions-test
|
||||||
|
frontend-tests.plugins.format-test
|
||||||
frontend-tests.plugins.page-test
|
frontend-tests.plugins.page-test
|
||||||
frontend-tests.plugins.parser-test
|
frontend-tests.plugins.parser-test
|
||||||
frontend-tests.plugins.tokens-test
|
frontend-tests.plugins.tokens-test
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
- **plugins-runtime**: changes outside the current page now raise a validation error when the target belongs to a page that is not currently active, instead of silently operating on the active page.
|
- **plugins-runtime**: changes outside the current page now raise a validation error when the target belongs to a page that is not currently active, instead of silently operating on the active page.
|
||||||
- **plugins-runtime**: Fix inverted validation that rejected valid values (and accepted invalid ones) on text range `align`, `direction`, `textDecoration`, `letterSpacing` and on layout child `zIndex`.
|
- **plugins-runtime**: Fix inverted validation that rejected valid values (and accepted invalid ones) on text range `align`, `direction`, `textDecoration`, `letterSpacing` and on layout child `zIndex`.
|
||||||
|
- **plugins-runtime**: Array-typed properties (e.g. `page.flows`, `shape.exports`, `shape.shadows`, layout `rows`/`columns`, ruler guides, path `commands`) now always return an array, returning an empty array instead of `null` when there are no items
|
||||||
- **plugins-runtime**: Added `version` field that returns the current version
|
- **plugins-runtime**: Added `version` field that returns the current version
|
||||||
- **plugins-runtime**: Added optional parameter `throwOnError` to `penpot.ui.sendMessage` (default false, backwards-compatible)
|
- **plugins-runtime**: Added optional parameter `throwOnError` to `penpot.ui.sendMessage` (default false, backwards-compatible)
|
||||||
- **plugin-types**: Added a flags subcontexts with the flag `naturalChildrenOrdering`
|
- **plugin-types**: Added a flags subcontexts with the flag `naturalChildrenOrdering`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user