mirror of
https://github.com/penpot/penpot.git
synced 2026-09-22 20:06:16 +00:00
209 lines
11 KiB
Clojure
209 lines
11 KiB
Clojure
;; 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 SUBSIDIARY SL
|
|
|
|
(ns common-tests.files-migrations-test
|
|
(:require
|
|
[app.common.data :as d]
|
|
[app.common.files.migrations :as cfm]
|
|
[app.common.types.file :as ctf]
|
|
[app.common.types.shape :as cts]
|
|
[app.common.uuid :as uuid]
|
|
[clojure.test :as t]))
|
|
|
|
(defmethod cfm/migrate-data "test/1" [data _] (update data :sum inc))
|
|
(defmethod cfm/migrate-data "test/2" [data _] (update data :sum inc))
|
|
(defmethod cfm/migrate-data "test/3" [data _] (update data :sum inc))
|
|
|
|
(t/deftest generic-migration-subsystem-1
|
|
(let [migrations (into (d/ordered-set) ["test/1" "test/2" "test/3"])]
|
|
(with-redefs [cfm/available-migrations migrations
|
|
ctf/check-file-data identity]
|
|
(let [file {:data {:sum 1}
|
|
:id 1
|
|
:migrations (d/ordered-set "test/1")}
|
|
file' (cfm/migrate file nil)]
|
|
(t/is (= cfm/available-migrations (:migrations file')))
|
|
(t/is (= 3 (:sum (:data file'))))))))
|
|
|
|
(t/deftest migration-0024b-fix-stroke-cap-placement
|
|
(let [shape-id (uuid/next)
|
|
page-id (uuid/next)
|
|
data {:pages-index
|
|
{page-id
|
|
{:objects
|
|
{shape-id {:id shape-id
|
|
:type :path
|
|
:stroke-cap-start "round"
|
|
:stroke-cap-end "round"
|
|
:strokes [{:stroke-color "#000000"
|
|
:stroke-opacity 1
|
|
:stroke-style :svg
|
|
:stroke-width 2}
|
|
{:stroke-color "#000000"
|
|
:stroke-cap-start "round"
|
|
:stroke-cap-end "round"
|
|
:stroke-opacity 1
|
|
:stroke-style :svg
|
|
:stroke-width 2}]}}}}}
|
|
data' (cfm/migrate-data data "0024b-fix-stroke-cap-placement")]
|
|
|
|
(let [shape (get-in data' [:pages-index page-id :objects shape-id])]
|
|
(t/is (nil? (:stroke-cap-start shape)) "top-level cap removed")
|
|
(t/is (nil? (:stroke-cap-end shape)) "top-level cap removed")
|
|
(t/is (= :round (get-in shape [:strokes 0 :stroke-cap-start])) "cap moved into stroke")
|
|
(t/is (= :round (get-in shape [:strokes 0 :stroke-cap-end])) "cap moved into stroke")
|
|
(t/is (= :round (get-in shape [:strokes 1 :stroke-cap-start])) "correct cap type")
|
|
(t/is (= :round (get-in shape [:strokes 1 :stroke-cap-end])) "correct cap type"))))
|
|
|
|
(t/deftest migration-0024-fix-stroke-cap-no-strokes
|
|
(let [shape-id (uuid/next)
|
|
page-id (uuid/next)
|
|
data {:pages-index
|
|
{page-id
|
|
{:objects
|
|
{shape-id {:id shape-id
|
|
:type :path
|
|
:stroke-cap-start :round
|
|
:stroke-cap-end :round
|
|
:strokes []}}}}}
|
|
data' (cfm/migrate-data data "0024b-fix-stroke-cap-placement")]
|
|
|
|
(let [shape (get-in data' [:pages-index page-id :objects shape-id])]
|
|
(t/is (nil? (:stroke-cap-start shape)) "top-level cap removed even with no strokes")
|
|
(t/is (nil? (:stroke-cap-end shape)) "top-level cap removed even with no strokes"))))
|
|
|
|
(t/deftest migration-0027-normalizes-constrained-shape-values
|
|
(let [file-id (uuid/next)
|
|
page-id (uuid/next)
|
|
shape-id (uuid/next)
|
|
shape (-> (cts/setup-shape {:id shape-id :type :frame})
|
|
(assoc :r1 -1
|
|
:r2 -2
|
|
:r3 -3
|
|
:r4 -4
|
|
:layout-gap {:row-gap -5 :column-gap -6}
|
|
:layout-padding {:p1 -7 :p2 -8 :p3 -9 :p4 -10}
|
|
:layout-grid-rows [{:type :fixed :value -11}]
|
|
:layout-grid-columns [{:type :percent :value -12}]
|
|
:layout-item-min-w -13
|
|
:layout-item-max-w -14
|
|
:layout-item-min-h -15
|
|
:layout-item-max-h -16
|
|
:strokes [{:stroke-color "#000000"
|
|
:stroke-width -17
|
|
:stroke-width-top -18
|
|
:stroke-width-right -19
|
|
:stroke-width-bottom -20
|
|
:stroke-width-left -21}]
|
|
:shadow [{:id nil
|
|
:style :drop-shadow
|
|
:offset-x 0
|
|
:offset-y 0
|
|
:blur -22
|
|
:spread 0
|
|
:hidden false
|
|
:color {:color "#000000" :opacity 1}}]
|
|
:blur {:id (uuid/next)
|
|
:type :layer-blur
|
|
:value -23
|
|
:hidden false}
|
|
:background-blur {:id (uuid/next)
|
|
:type :background-blur
|
|
:value -24
|
|
:hidden false}
|
|
:exports [{:type :png :scale 0 :suffix ""}]
|
|
:grids [{:type :square
|
|
:display true
|
|
:params {:size 0
|
|
:color {:color "#000000" :opacity 1}}}
|
|
{:type :column
|
|
:display true
|
|
:params {:size -25
|
|
:color {:color "#000000" :opacity 1}}}]))
|
|
data (-> (ctf/make-file-data file-id page-id)
|
|
(assoc-in [:pages-index page-id :objects shape-id] shape))]
|
|
|
|
(t/is (thrown? #?(:clj Exception :cljs js/Error)
|
|
(ctf/check-file-data data))
|
|
"new schemas reject legacy negative values")
|
|
|
|
(let [data' (cfm/migrate-data data "0027-normalize-constrained-values")
|
|
shape' (get-in data' [:pages-index page-id :objects shape-id])]
|
|
(t/is (= data' (ctf/check-file-data data')) "migrated file data passes the schema")
|
|
(t/is (every? zero? (map #(get shape' %) [:r1 :r2 :r3 :r4])) "corner radii clamped")
|
|
(t/is (= {:row-gap 0 :column-gap 0} (:layout-gap shape')) "layout gaps clamped")
|
|
(t/is (= {:p1 0 :p2 0 :p3 0 :p4 0} (:layout-padding shape')) "layout padding clamped")
|
|
(t/is (= [0] (mapv :value (:layout-grid-rows shape'))) "row tracks clamped")
|
|
(t/is (= [0] (mapv :value (:layout-grid-columns shape'))) "column tracks clamped")
|
|
(t/is (every? zero?
|
|
(map #(get shape' %)
|
|
[:layout-item-min-w :layout-item-max-w
|
|
:layout-item-min-h :layout-item-max-h]))
|
|
"layout item bounds clamped")
|
|
(t/is (every? zero?
|
|
(map (first (:strokes shape'))
|
|
[:stroke-width :stroke-width-top :stroke-width-right
|
|
:stroke-width-bottom :stroke-width-left]))
|
|
"stroke widths clamped")
|
|
(t/is (zero? (get-in shape' [:shadow 0 :blur])) "shadow blur clamped")
|
|
(t/is (zero? (get-in shape' [:blur :value])) "layer blur clamped")
|
|
(t/is (zero? (get-in shape' [:background-blur :value])) "background blur clamped")
|
|
(t/is (= 1 (get-in shape' [:exports 0 :scale])) "export scale reset to default")
|
|
(t/is (= 0.01 (get-in shape' [:grids 0 :params :size])) "square grid size clamped")
|
|
(t/is (= 1 (get-in shape' [:grids 1 :params :size])) "column grid count clamped"))))
|
|
|
|
(t/deftest migration-0027-normalizes-page-grids-and-variant-properties
|
|
(let [file-id (uuid/next)
|
|
page-id (uuid/next)
|
|
component-id (uuid/next)
|
|
long-name (apply str (repeat 61 "n"))
|
|
long-value (apply str (repeat 61 "v"))
|
|
data (-> (ctf/make-file-data file-id page-id)
|
|
(assoc-in [:pages-index page-id :default-grids]
|
|
{:square {:size -1
|
|
:color {:color "#000000" :opacity 1}}
|
|
:row {:size 0.5
|
|
:color {:color "#000000" :opacity 1}}
|
|
:column {:size -2
|
|
:color {:color "#000000" :opacity 1}}})
|
|
(assoc-in [:components component-id]
|
|
{:id component-id
|
|
:name "Variant"
|
|
:variant-properties [{:name long-name
|
|
:value long-value}]}))
|
|
data' (cfm/migrate-data data "0027-normalize-constrained-values")]
|
|
|
|
(t/is (= 0.01 (get-in data' [:pages-index page-id :default-grids :square :size]))
|
|
"default square grid size clamped")
|
|
(t/is (= 1 (get-in data' [:pages-index page-id :default-grids :row :size]))
|
|
"default row grid count reset")
|
|
(t/is (= 1 (get-in data' [:pages-index page-id :default-grids :column :size]))
|
|
"default column grid count reset")
|
|
(t/is (= 60 (count (get-in data' [:components component-id :variant-properties 0 :name])))
|
|
"variant property name truncated")
|
|
(t/is (= 60 (count (get-in data' [:components component-id :variant-properties 0 :value])))
|
|
"variant property value truncated")
|
|
(t/is (= data' (cfm/migrate-data data' "0027-normalize-constrained-values"))
|
|
"migration is idempotent")))
|
|
|
|
(t/deftest migration-0027-runs-through-file-migration
|
|
(let [migration-id "0027-normalize-constrained-values"
|
|
shape-id (uuid/next)
|
|
file (ctf/make-file {:name "Legacy constrained values"})
|
|
page-id (first (get-in file [:data :pages]))
|
|
shape (-> (cts/setup-shape {:id shape-id :type :rect})
|
|
(assoc :r1 -1))
|
|
file (-> file
|
|
(assoc :migrations (disj cfm/available-migrations migration-id))
|
|
(assoc-in [:data :pages-index page-id :objects shape-id] shape))
|
|
file' (cfm/migrate-file file {})]
|
|
|
|
(t/is (cfm/need-migration? file) "new migration detected")
|
|
(t/is (not (cfm/need-migration? file')) "new migration recorded")
|
|
(t/is (contains? (:migrations file') migration-id) "migration id persisted")
|
|
(t/is (zero? (get-in file' [:data :pages-index page-id :objects shape-id :r1]))
|
|
"migration repaired file data before schema validation")))
|