0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-08 07:50:43 -05:00

Merge pull request #4499 from penpot/hiru-test-helpers

 Add helpers to build files for testing
This commit is contained in:
Alejandro 2024-04-26 13:29:52 +02:00 committed by GitHub
commit 013dbf1f76
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 651 additions and 511 deletions

View file

@ -93,7 +93,7 @@ jobs:
working_directory: "./common"
command: |
yarn test
clojure -X:dev:test :patterns '["common-tests.*-test"]'
clojure -M:dev:test
- run:
name: "frontend tests"

View file

@ -6,13 +6,10 @@
(ns app.rpc.commands.files-create
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.features :as cfeat]
[app.common.files.defaults :refer [version]]
[app.common.schema :as sm]
[app.common.types.file :as ctf]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
[app.features.fdata :as feat.fdata]
@ -40,7 +37,7 @@
(defn create-file
[{:keys [::db/conn] :as cfg}
{:keys [id name project-id is-shared revn
modified-at deleted-at create-page
modified-at deleted-at create-page page-id
ignore-sync-until features]
:or {is-shared false revn 0 create-page true}
:as params}]
@ -51,23 +48,17 @@
(binding [pmap/*tracked* (pmap/create-tracked)
cfeat/*current* features]
(let [id (or id (uuid/next))
data (if create-page
(ctf/make-file-data id)
(ctf/make-file-data id nil))
file {:id id
:project-id project-id
:name name
:revn revn
:is-shared is-shared
:version version
:data data
:features features
:ignore-sync-until ignore-sync-until
:modified-at modified-at
:deleted-at deleted-at}
(let [file (ctf/make-file {:id id
:project-id project-id
:name name
:revn revn
:is-shared is-shared
:features features
:ignore-sync-until ignore-sync-until
:modified-at modified-at
:deleted-at deleted-at
:create-page create-page
:page-id page-id})
file (if (contains? features "fdata/objects-map")
(feat.fdata/enable-objects-map file)
@ -75,9 +66,7 @@
file (if (contains? features "fdata/pointer-map")
(feat.fdata/enable-pointer-map file)
file)
file (d/without-nils file)]
file)]
(db/insert! conn :file
(-> file
@ -86,9 +75,9 @@
{::db/return-keys false})
(when (contains? features "fdata/pointer-map")
(feat.fdata/persist-pointers! cfg id))
(feat.fdata/persist-pointers! cfg (:id file)))
(->> (assoc params :file-id id :role :owner)
(->> (assoc params :file-id (:id file) :role :owner)
(create-file-role! conn))
(db/update! conn :project

View file

@ -76,12 +76,8 @@
:ns-default build}
:test
{:extra-paths ["test"]
:extra-deps
{io.github.cognitect-labs/test-runner
{:git/tag "v0.5.1" :git/sha "dfb30dd"}}
:main-opts ["-m" "cognitect.test-runner"]
:exec-fn cognitect.test-runner.api/test}
{:main-opts ["-m" "kaocha.runner"]
:extra-deps {lambdaisland/kaocha {:mvn/version "1.88.1376"}}}
:shadow-cljs
{:main-opts ["-m" "shadow.cljs.devtools.cli"]}

View file

@ -147,7 +147,7 @@
[file data]
(dm/assert! (nil? (:current-component-id file)))
(let [page-id (or (:id data) (uuid/next))
page (-> (ctp/make-empty-page page-id "Page 1")
page (-> (ctp/make-empty-page {:id page-id :name "Page 1"})
(d/deep-merge data))]
(-> file
(commit-change

View file

@ -578,7 +578,7 @@
(ex/raise :type :conflict
:hint "id+name or page should be provided, never both"))
(let [page (if (and (string? name) (uuid? id))
(ctp/make-empty-page id name)
(ctp/make-empty-page {:id id :name name})
page)]
(ctpl/add-page data page)))

View file

@ -13,6 +13,7 @@
[app.common.types.color.generic :as-alias color-generic]
[app.common.types.color.gradient :as-alias color-gradient]
[app.common.types.color.gradient.stop :as-alias color-gradient-stop]
[app.common.uuid :as uuid]
[clojure.test.check.generators :as tgen]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -105,6 +106,22 @@
;; HELPERS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; --- factory
(defn make-color
[{:keys [id name path value color opacity ref-id ref-file gradient image]}]
(-> {:id (or id (uuid/next))
:name (or name color "Black")
:path path
:value value
:color (or color "#000000")
:opacity (or opacity 1)
:ref-id ref-id
:ref-file ref-file
:gradient gradient
:image image}
(d/without-nils)))
;; --- fill
(defn fill->shape-color

View file

@ -9,6 +9,7 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.features :as cfeat]
[app.common.files.defaults :refer [version]]
[app.common.files.helpers :as cfh]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
@ -78,7 +79,7 @@
([file-id page-id]
(let [page (when (some? page-id)
(ctp/make-empty-page page-id "Page 1"))]
(ctp/make-empty-page {:id page-id :name "Page 1"}))]
(cond-> (assoc empty-file-data :id file-id)
(some? page-id)
@ -87,6 +88,34 @@
(contains? cfeat/*current* "components/v2")
(assoc-in [:options :components-v2] true)))))
(defn make-file
[{:keys [id project-id name revn is-shared features
ignore-sync-until modified-at deleted-at
create-page page-id]
:or {is-shared false revn 0 create-page true}}]
(let [id (or id (uuid/next))
data (if create-page
(if page-id
(make-file-data id page-id)
(make-file-data id))
(make-file-data id nil))
file {:id id
:project-id project-id
:name name
:revn revn
:is-shared is-shared
:version version
:data data
:features features
:ignore-sync-until ignore-sync-until
:modified-at modified-at
:deleted-at deleted-at}]
(d/without-nils file)))
;; Helpers
(defn file-data
@ -457,7 +486,7 @@
(gpt/point 0 0)
(ctn/shapes-seq library-page))]
[file-data (:id library-page) position])
(let [library-page (ctp/make-empty-page (uuid/next) "Main components")]
(let [library-page (ctp/make-empty-page {:id (uuid/next) :name "Main components"})]
[(ctpl/add-page file-data library-page) (:id library-page) (gpt/point 0 0)]))))
(defn- absorb-components

View file

@ -69,10 +69,10 @@
:name "Root Frame"})}})
(defn make-empty-page
[id name]
[{:keys [id name]}]
(-> empty-page-data
(assoc :id id)
(assoc :name name)))
(assoc :id (or id (uuid/next)))
(assoc :name (or name "Page 1"))))
;; --- Helpers for flow

View file

@ -6,8 +6,10 @@
(ns app.common.types.typography
(:require
[app.common.data :as d]
[app.common.schema :as sm]
[app.common.text :as txt]))
[app.common.text :as txt]
[app.common.uuid :as uuid]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SCHEMA
@ -36,6 +38,23 @@
;; HELPERS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn make-typography
[{:keys [id name path font-id font-family font-variant-id font-size
font-weight font-style line-height letter-spacing text-transform]}]
(-> {:id (or id (uuid/next))
:name (or name "Typography 1")
:path path
:font-id (or font-id "sourcesanspro")
:font-family (or font-family "sourcesanspro")
:font-variant-id (or font-variant-id "regular")
:font-size (or font-size "14")
:font-weight (or font-weight "480")
:font-style (or font-style "normal")
:line-height (or line-height "1.2")
:letter-spacing (or letter-spacing "0")
:text-transform (or text-transform "none")}
(d/without-nils)))
(defn uses-library-typographies?
"Check if the shape uses any typography in the given library."
[shape library-id]

View file

@ -203,7 +203,7 @@
(t/is (mth/close? 1.5 (:x rs)))
(t/is (mth/close? 3.5 (:y rs)))))
(t/deftest transform-point
(t/deftest ^:kaocha/skip transform-point
;;todo
)

View file

@ -1,146 +0,0 @@
;; 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
(ns common-tests.helpers.components
(:require
[app.common.files.helpers :as cfh]
[app.common.types.component :as ctk]
[app.common.types.container :as ctn]
[app.common.types.file :as ctf]
[clojure.test :as t]))
;; ---- Helpers to manage libraries and synchronization
(defn check-instance-root
[shape]
(t/is (some? (:shape-ref shape)))
(t/is (some? (:component-id shape)))
(t/is (= (:component-root shape) true)))
(defn check-instance-subroot
[shape]
(t/is (some? (:shape-ref shape)))
(t/is (some? (:component-id shape)))
(t/is (nil? (:component-root shape))))
(defn check-instance-child
[shape]
(t/is (some? (:shape-ref shape)))
(t/is (nil? (:component-id shape)))
(t/is (nil? (:component-file shape)))
(t/is (nil? (:component-root shape))))
(defn check-instance-inner
[shape]
(if (some? (:component-id shape))
(check-instance-subroot shape)
(check-instance-child shape)))
(defn check-noninstance
[shape]
(t/is (nil? (:shape-ref shape)))
(t/is (nil? (:component-id shape)))
(t/is (nil? (:component-file shape)))
(t/is (nil? (:component-root shape)))
(t/is (nil? (:remote-synced? shape)))
(t/is (nil? (:touched shape))))
(defn check-from-file
[shape file]
(t/is (= (:component-file shape)
(:id file))))
(defn resolve-instance
"Get the shape with the given id and all its children, and
verify that they are a well constructed instance tree."
[page root-inst-id]
(let [root-inst (ctn/get-shape page root-inst-id)
shapes-inst (cfh/get-children-with-self (:objects page)
root-inst-id)]
(check-instance-root (first shapes-inst))
(run! check-instance-inner (rest shapes-inst))
shapes-inst))
(defn resolve-noninstance
"Get the shape with the given id and all its children, and
verify that they are not a component instance."
[page root-inst-id]
(let [root-inst (ctn/get-shape page root-inst-id)
shapes-inst (cfh/get-children-with-self (:objects page)
root-inst-id)]
(run! check-noninstance shapes-inst)
shapes-inst))
(defn resolve-instance-and-main
"Get the shape with the given id and all its children, and also
the main component and all its shapes."
[page root-inst-id libraries]
(let [root-inst (ctn/get-shape page root-inst-id)
component (ctf/get-component libraries (:component-file root-inst) (:component-id root-inst))
shapes-inst (cfh/get-children-with-self (:objects page) root-inst-id)
shapes-main (cfh/get-children-with-self (:objects component) (:shape-ref root-inst))
unique-refs (into #{} (map :shape-ref) shapes-inst)
main-exists? (fn [shape]
(let [component-shape
(ctn/get-component-shape (:objects page) shape)
component
(ctf/get-component libraries (:component-file component-shape) (:component-id component-shape))
main-shape
(ctn/get-shape component (:shape-ref shape))]
(t/is (some? main-shape))))]
;; Validate that the instance tree is well constructed
(check-instance-root (first shapes-inst))
(run! check-instance-inner (rest shapes-inst))
(t/is (= (count shapes-inst)
(count shapes-main)
(count unique-refs)))
(run! main-exists? shapes-inst)
[shapes-inst shapes-main component]))
(defn resolve-instance-and-main-allow-dangling
"Get the shape with the given id and all its children, and also
the main component and all its shapes. Allows shapes with the
corresponding component shape missing."
[page root-inst-id libraries]
(let [root-inst (ctn/get-shape page root-inst-id)
component (ctf/get-component libraries (:component-file root-inst) (:component-id root-inst))
shapes-inst (cfh/get-children-with-self (:objects page) root-inst-id)
shapes-main (cfh/get-children-with-self (:objects component) (:shape-ref root-inst))
unique-refs (into #{} (map :shape-ref) shapes-inst)
main-exists? (fn [shape]
(let [component-shape
(ctn/get-component-shape (:objects page) shape)
component
(ctf/get-component libraries (:component-file component-shape) (:component-id component-shape))
main-shape
(ctn/get-shape component (:shape-ref shape))]
(t/is (some? main-shape))))]
;; Validate that the instance tree is well constructed
(check-instance-root (first shapes-inst))
[shapes-inst shapes-main component]))

View file

@ -0,0 +1,42 @@
;; 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
(ns common-tests.helpers.compositions
(:require
[common-tests.helpers.files :as thf]))
(defn add-rect
[file rect-label]
(thf/add-sample-shape file rect-label
:type :rect
:name "Rect1"))
(defn add-frame
[file frame-label]
(thf/add-sample-shape file frame-label
:type :frame
:name "Frame1"))
(defn add-frame-with-child
[file frame-label child-label]
(-> file
(add-frame frame-label)
(thf/add-sample-shape child-label
:type :rect
:name "Rect1"
:parent-label frame-label)))
(defn add-simple-component
[file component-label root-label child-label]
(-> file
(add-frame-with-child root-label child-label)
(thf/make-component component-label root-label)))
(defn add-simple-component-with-copy
[file component-label main-root-label main-child-label copy-root-label]
(-> file
(add-simple-component component-label main-root-label main-child-label)
(thf/instantiate-component component-label copy-root-label)))

View file

@ -6,150 +6,278 @@
(ns common-tests.helpers.files
(:require
[app.common.data.macros :as dm]
[app.common.features :as ffeat]
[app.common.files.changes :as cfc]
[app.common.files.helpers :as cfh]
[app.common.files.validate :as cfv]
[app.common.geom.point :as gpt]
[app.common.pprint :refer [pprint]]
[app.common.types.color :as ctc]
[app.common.types.colors-list :as ctcl]
[app.common.types.components-list :as ctkl]
[app.common.types.container :as ctn]
[app.common.types.file :as ctf]
[app.common.types.page :as ctp]
[app.common.types.pages-list :as ctpl]
[app.common.types.shape :as cts]
[app.common.types.shape-tree :as ctst]
[app.common.types.typographies-list :as ctyl]
[app.common.uuid :as uuid]))
[app.common.types.typographies-list :as cttl]
[app.common.types.typography :as ctt]
[common-tests.helpers.ids-map :as thi]))
(defn- make-file-data
[file-id page-id]
(binding [ffeat/*current* #{"components/v2"}]
(ctf/make-file-data file-id page-id)))
(def ^:private idmap (atom {}))
(defn reset-idmap!
[next]
(reset! idmap {})
(next))
(defn id
[label]
(get @idmap label))
;; ----- Files
(defn sample-file
([file-id page-id] (sample-file file-id page-id nil))
([file-id page-id props]
(merge {:id file-id
:name (get props :name "File1")
:data (make-file-data file-id page-id)}
props)))
[label & {:keys [page-label name] :as params}]
(binding [ffeat/*current* #{"components/v2"}]
(let [params (cond-> params
label
(assoc :id (thi/new-id! label))
page-label
(assoc :page-id (thi/new-id! page-label))
(nil? name)
(assoc :name "Test file"))
file (-> (ctf/make-file (dissoc params :page-label))
(assoc :features #{"components/v2"}))
page (-> file
:data
(ctpl/pages-seq)
(first))]
(with-meta file
{:current-page-id (:id page)}))))
(defn validate-file!
([file] (validate-file! file {}))
([file libraries]
(cfv/validate-file-schema! file)
(cfv/validate-file! file libraries)))
(defn apply-changes
[file changes]
(let [file' (ctf/update-file-data file #(cfc/process-changes % (:redo-changes changes) true))]
(validate-file! file')
file'))
(declare current-page-id)
(declare get-page)
(defn dump-file
[file & {:keys [page-label libraries] :as params}]
(let [params (-> params
(or {:show-ids true :show-touched true})
(dissoc page-label libraries))
page (if (some? page-label)
(:id (get-page file page-label))
(current-page-id file))
libraries (or libraries {})]
(ctf/dump-tree file page libraries params)))
(defn pprint-file
[file & {:keys [level length] :or {level 10 length 1000}}]
(pprint file {:level level :length length}))
;; ----- Pages
(defn sample-page
[label & {:keys [] :as params}]
(ctp/make-empty-page (assoc params :id (thi/new-id! label))))
(defn add-sample-page
[file label & {:keys [] :as params}]
(let [page (sample-page label params)]
(-> file
(ctf/update-file-data #(ctpl/add-page % page))
(vary-meta assoc :current-page-id (:id page)))))
(defn get-page
[file label]
(ctpl/get-page (:data file) (thi/id label)))
(defn current-page-id
[file]
(:current-page-id (meta file)))
(defn current-page
[file]
(ctpl/get-page (:data file) (current-page-id file)))
(defn switch-to-page
[file label]
(vary-meta file assoc :current-page-id (thi/id label)))
;; ----- Shapes
(defn sample-shape
[file label type page-id props]
(ctf/update-file-data
file
(fn [file-data]
(let [frame-id (get props :frame-id uuid/zero)
parent-id (get props :parent-id uuid/zero)
shape (cts/setup-shape
(-> {:type type
:width 1
:height 1}
(merge props)))]
[label & {:keys [type] :as params}]
(let [params (cond-> params
label
(assoc :id (thi/new-id! label))
(swap! idmap assoc label (:id shape))
(nil? type)
(assoc :type :rect))]
(cts/setup-shape params)))
(defn add-sample-shape
[file label & {:keys [parent-label] :as params}]
(let [page (current-page file)
shape (sample-shape label (dissoc params :parent-label))
parent-id (when parent-label
(thi/id parent-label))
parent (when parent-id
(ctst/get-shape page parent-id))
frame-id (if (cfh/frame-shape? parent)
(:id parent)
(:frame-id parent))]
(ctf/update-file-data
file
(fn [file-data]
(ctpl/update-page file-data
page-id
(:id page)
#(ctst/add-shape (:id shape)
shape
%
frame-id
parent-id
0
nil
true))))))
(defn sample-component
[file label page-id shape-id]
(ctf/update-file-data
file
(fn [file-data]
(let [page (ctpl/get-page file-data page-id)
(defn get-shape
[file label & {:keys [page-label]}]
(let [page (if page-label
(get-page file page-label)
(current-page file))]
(ctst/get-shape page (thi/id label))))
[component-shape component-shapes updated-shapes]
(ctn/make-component-shape (ctn/get-shape page shape-id)
(:objects page)
(:id file)
true)]
(defn get-shape-by-id
[file id & {:keys [page-label]}]
(let [page (if page-label
(get-page file page-label)
(current-page file))]
(ctst/get-shape page id)))
(swap! idmap assoc label (:id component-shape))
(-> file-data
(ctpl/update-page page-id
#(reduce (fn [page shape] (ctst/set-shape page shape))
%
updated-shapes))
(ctkl/add-component {:id (:id component-shape)
:name (:name component-shape)
:path ""
:main-instance-id shape-id
:main-instance-page page-id
:shapes component-shapes}))))))
;; ----- Components
(defn sample-instance
[file label page-id library component-id]
(ctf/update-file-data
file
(fn [file-data]
(let [[instance-shape instance-shapes]
(ctn/make-component-instance (ctpl/get-page file-data page-id)
(ctkl/get-component (:data library) component-id)
(:data library)
(gpt/point 0 0)
true)]
(defn make-component
[file label root-label]
(let [page (current-page file)
root (get-shape file root-label)]
(swap! idmap assoc label (:id instance-shape))
(-> file-data
(ctpl/update-page page-id
#(reduce (fn [page shape]
(ctst/add-shape (:id shape)
shape
page
uuid/zero
(:parent-id shape)
0
true))
%
instance-shapes)))))))
(dm/assert!
"Need that root is already a frame"
(cfh/frame-shape? root))
(let [[_new-root _new-shapes updated-shapes]
(ctn/convert-shape-in-component root (:objects page) (:id file))
updated-root (first updated-shapes)] ; Can't use new-root because it has a new id
(thi/set-id! label (:component-id updated-root))
(ctf/update-file-data
file
(fn [file-data]
(as-> file-data $
(reduce (fn [file-data shape]
(ctpl/update-page file-data
(:id page)
#(update % :objects assoc (:id shape) shape)))
$
updated-shapes)
(ctkl/add-component $
{:id (:component-id updated-root)
:name (:name updated-root)
:main-instance-id (:id updated-root)
:main-instance-page (:id page)
:shapes updated-shapes})))))))
(defn get-component
[file label]
(ctkl/get-component (:data file) (thi/id label)))
(defn get-component-by-id
[file id]
(ctkl/get-component (:data file) id))
(defn instantiate-component
[file component-label copy-root-label & {:keys [parent-label library] :as params}]
(let [page (current-page file)
library (or library file)
component (get-component library component-label)
parent-id (when parent-label
(thi/id parent-label))
parent (when parent-id
(ctst/get-shape page parent-id))
frame-id (if (cfh/frame-shape? parent)
(:id parent)
(:frame-id parent))
[copy-root copy-shapes]
(ctn/make-component-instance page
component
(:data library)
(gpt/point 100 100)
true
{:force-id (thi/new-id! copy-root-label)
:force-frame-id frame-id})
copy-root' (cond-> copy-root
(some? parent)
(assoc :parent-id parent-id)
(some? frame-id)
(assoc :frame-id frame-id)
(and (some? parent) (ctn/in-any-component? (:objects page) parent))
(dissoc :component-root))]
(ctf/update-file-data
file
(fn [file-data]
(as-> file-data $
(ctpl/update-page $
(:id page)
#(ctst/add-shape (:id copy-root')
copy-root'
%
frame-id
parent-id
nil
true))
(reduce (fn [file-data shape]
(ctpl/update-page file-data
(:id page)
#(ctst/add-shape (:id shape)
shape
%
(:parent-id shape)
(:frame-id shape)
nil
true)))
$
(remove #(= (:id %) (:did copy-root')) copy-shapes)))))))
(defn sample-color
[file label props]
(ctf/update-file-data
file
(fn [file-data]
(let [id (uuid/next)
props (merge {:id id
:name "Color 1"
:color "#000000"
:opacity 1}
props)]
(swap! idmap assoc label id)
(ctcl/add-color file-data props)))))
[label & {:keys [] :as params}]
(ctc/make-color (assoc params :id (thi/new-id! label))))
(defn add-sample-color
[file label & {:keys [] :as params}]
(let [color (sample-color label params)]
(ctf/update-file-data file #(ctcl/add-color % color))))
(defn sample-typography
[file label props]
(ctf/update-file-data
file
(fn [file-data]
(let [id (uuid/next)
props (merge {:id id
:name "Typography 1"
:font-id "sourcesanspro"
:font-family "sourcesanspro"
:font-size "14"
:font-style "normal"
:font-variant-id "regular"
:font-weight "400"
:line-height "1.2"
:letter-spacing "0"
:text-transform "none"}
props)]
(swap! idmap assoc label id)
(ctyl/add-typography file-data props)))))
[label & {:keys [] :as params}]
(ctt/make-typography (assoc params :id (thi/new-id! label))))
(defn add-sample-typography
[file label & {:keys [] :as params}]
(let [typography (sample-typography label params)]
(ctf/update-file-data file #(cttl/add-typography % typography))))

View file

@ -0,0 +1,36 @@
;; 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
(ns common-tests.helpers.ids-map
(:require
[app.common.uuid :as uuid]))
;; ---- Helpers to manage ids as known identifiers
(def ^:private idmap (atom {}))
(defn reset-idmap! []
(reset! idmap {}))
(defn set-id!
[label id]
(swap! idmap assoc label id))
(defn new-id!
[label]
(let [id (uuid/next)]
(set-id! label id)
id))
(defn id
[label]
(get @idmap label))
(defn test-fixture
;; Ensure that each test starts with a clean ids map
[f]
(reset-idmap!)
(f))

View file

@ -0,0 +1,45 @@
;; 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
(ns common-tests.logic.logic-comp-creation-test
(:require
[app.common.files.changes-builder :as pcb]
[app.common.files.libraries-helpers :as cflh]
[clojure.test :as t]
[common-tests.helpers.files :as thf]
[common-tests.helpers.ids-map :as thi]))
(t/use-fixtures :each thi/test-fixture)
(t/deftest test-add-component-from-single-shape
(let [; Setup
file (-> (thf/sample-file :file1)
(thf/add-sample-shape :shape1 :type :frame))
page (thf/current-page file)
shape1 (thf/get-shape file :shape1)
; Action
[_ component-id changes]
(cflh/generate-add-component (pcb/empty-changes)
[shape1]
(:objects page)
(:id page)
(:id file)
true
nil
nil)
file' (thf/apply-changes file changes)
; Get
component (thf/get-component-by-id file' component-id)
root (thf/get-shape-by-id file' (:main-instance-id component))]
; Check
(t/is (some? component))
(t/is (some? root))
(t/is (= (:component-id root) (:id component)))))

View file

@ -27,7 +27,6 @@
(t/testing "unknown assoc"
(let [o (assoc o :c 176)]
(prn o)
(t/is (= 1 (:a o)))
(t/is (= 2 (:b o)))
(t/is (= 176 (:c o)))))

View file

@ -0,0 +1,189 @@
;; 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
(ns common-tests.types.types-libraries-test
(:require
[app.common.data :as d]
[app.common.text :as txt]
[app.common.types.colors-list :as ctcl]
[app.common.types.component :as ctk]
[app.common.types.components-list :as ctkl]
[app.common.types.file :as ctf]
[app.common.types.pages-list :as ctpl]
[app.common.types.typographies-list :as ctyl]
[clojure.test :as t]
[common-tests.helpers.compositions :as tho]
[common-tests.helpers.files :as thf]
[common-tests.helpers.ids-map :as thi]))
(t/use-fixtures :each thi/test-fixture)
(t/deftest test-create-file
(let [f1 (thf/sample-file :file1)
f2 (thf/sample-file :file2 :page-label :page1)
f3 (thf/sample-file :file3 :name "testing file")
f4 (-> (thf/sample-file :file4 :page-label :page2)
(thf/add-sample-page :page3 :name "testing page")
(thf/add-sample-shape :shape1))
f5 (-> f4
(thf/add-sample-shape :shape2)
(thf/switch-to-page :page2)
(thf/add-sample-shape :shape3 :name "testing shape" :width 100))
s1 (thf/get-shape f4 :shape1)
s2 (thf/get-shape f5 :shape2 :page-label :page3)
s3 (thf/get-shape f5 :shape3)]
;; (thf/pprint-file f4)
(t/is (= (:name f1) "Test file"))
(t/is (= (:name f3) "testing file"))
(t/is (= (:id f2) (thi/id :file2)))
(t/is (= (:id f4) (thi/id :file4)))
(t/is (= (-> f4 :data :pages-index vals first :id) (thi/id :page2)))
(t/is (= (-> f4 :data :pages-index vals first :name) "Page 1"))
(t/is (= (-> f4 :data :pages-index vals second :id) (thi/id :page3)))
(t/is (= (-> f4 :data :pages-index vals second :name) "testing page"))
(t/is (= (:id (thf/current-page f2)) (thi/id :page1)))
(t/is (= (:id (thf/current-page f4)) (thi/id :page3)))
(t/is (= (:id (thf/current-page f5)) (thi/id :page2)))
(t/is (= (:id s1) (thi/id :shape1)))
(t/is (= (:name s1) "Rectangle"))
(t/is (= (:id s2) (thi/id :shape2)))
(t/is (= (:name s2) "Rectangle"))
(t/is (= (:id s3) (thi/id :shape3)))
(t/is (= (:name s3) "testing shape"))
(t/is (= (:width s3) 100))
(t/is (= (:width (:selrect s3)) 100))))
(t/deftest test-create-components
(let [f1 (-> (thf/sample-file :file1)
(tho/add-simple-component-with-copy :component1 :main-root :main-child :copy-root))]
#_(thf/dump-file f1)
#_(thf/pprint-file f4)
(t/is (= (:name f1) "Test file"))))
(t/deftest test-absorb-components
(let [; Setup
library (-> (thf/sample-file :library :is-shared true)
(tho/add-simple-component :component1 :main-root :rect1))
file (-> (thf/sample-file :file)
(thf/instantiate-component :component1 :copy-root :library library))
; Action
file' (ctf/update-file-data
file
#(ctf/absorb-assets % (:data library)))
_ (thf/validate-file! file')
; Get
pages' (ctpl/pages-seq (ctf/file-data file'))
components' (ctkl/components-seq (ctf/file-data file'))
component' (first components')
copy-root' (thf/get-shape file' :copy-root)
main-root' (ctf/get-ref-shape (ctf/file-data file') component' copy-root')]
; Check
(t/is (= (count pages') 2))
(t/is (= (:name (first pages')) "Page 1"))
(t/is (= (:name (second pages')) "Main components"))
(t/is (= (count components') 1))
(t/is (ctk/instance-of? copy-root' (:id file') (:id component')))
(t/is (ctk/is-main-of? main-root' copy-root' true))
(t/is (ctk/main-instance-of? (:id main-root') (:id (second pages')) component'))))
(t/deftest test-absorb-colors
(let [; Setup
library (-> (thf/sample-file :library :is-shared true)
(thf/add-sample-color :color1 {:name "Test color"
:color "#abcdef"}))
file (-> (thf/sample-file :file)
(thf/add-sample-shape :shape1
:type :rect
:name "Rect1"
:fills [{:fill-color "#abcdef"
:fill-opacity 1
:fill-color-ref-id (thi/id :color1)
:fill-color-ref-file (thi/id :library)}]))
; Action
file' (ctf/update-file-data
file
#(ctf/absorb-assets % (:data library)))
_ (thf/validate-file! file')
; Get
colors' (ctcl/colors-seq (ctf/file-data file'))
shape1' (thf/get-shape file' :shape1)
fill' (first (:fills shape1'))]
; Check
(t/is (= (count colors') 1))
(t/is (= (:id (first colors')) (thi/id :color1)))
(t/is (= (:name (first colors')) "Test color"))
(t/is (= (:color (first colors')) "#abcdef"))
(t/is (= (:fill-color fill') "#abcdef"))
(t/is (= (:fill-color-ref-id fill') (thi/id :color1)))
(t/is (= (:fill-color-ref-file fill') (:id file')))))
(t/deftest test-absorb-typographies
(let [; Setup
library (-> (thf/sample-file :library :is-shared true)
(thf/add-sample-typography :typography1 {:name "Test typography"}))
file (-> (thf/sample-file :file)
(thf/add-sample-shape :shape1
:type :text
:name "Text1"
:content {:type "root"
:children [{:type "paragraph-set"
:children [{:type "paragraph"
:key "67uep"
:children [{:text "Example text"
:typography-ref-id (thi/id :typography1)
:typography-ref-file (thi/id :library)
:line-height "1.2"
:font-style "normal"
:text-transform "none"
:text-align "left"
:font-id "sourcesanspro"
:font-family "sourcesanspro"
:font-size "14"
:font-weight "400"
:font-variant-id "regular"
:text-decoration "none"
:letter-spacing "0"
:fills [{:fill-color "#000000"
:fill-opacity 1}]}]}]}]}))
; Action
file' (ctf/update-file-data
file
#(ctf/absorb-assets % (:data library)))
_ (thf/validate-file! file')
; Get
typographies' (ctyl/typographies-seq (ctf/file-data file'))
shape1' (thf/get-shape file' :shape1)
text-node' (d/seek #(some? (:text %)) (txt/node-seq (:content shape1')))]
(t/is (= (count typographies') 1))
(t/is (= (:id (first typographies')) (thi/id :typography1)))
(t/is (= (:name (first typographies')) "Test typography"))
(t/is (= (:typography-ref-id text-node') (thi/id :typography1)))
(t/is (= (:typography-ref-file text-node') (:id file')))))

View file

@ -1,207 +0,0 @@
;; 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
(ns common-tests.types-file-test
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
[app.common.text :as txt]
[app.common.types.colors-list :as ctcl]
[app.common.types.component :as ctk]
[app.common.types.components-list :as ctkl]
[app.common.types.container :as ctn]
[app.common.types.file :as ctf]
[app.common.types.pages-list :as ctpl]
[app.common.types.shape :as cts]
[app.common.types.shape-tree :as ctst]
[app.common.types.typographies-list :as ctyl]
[app.common.uuid :as uuid]
[clojure.pprint :refer [pprint]]
[clojure.test :as t]
[common-tests.helpers.components :as thk]
[common-tests.helpers.files :as thf]
[cuerdas.core :as str]))
(t/use-fixtures :each thf/reset-idmap!)
#_(t/deftest test-absorb-components
(let [library-id (uuid/custom 1 1)
library-page-id (uuid/custom 2 2)
file-id (uuid/custom 3 3)
file-page-id (uuid/custom 4 4)
library (-> (thf/sample-file library-id library-page-id {:is-shared true})
(thf/sample-shape :group1
:group
library-page-id
{:name "Group1"})
(thf/sample-shape :shape1
:rect
library-page-id
{:name "Rect1"
:parent-id (thf/id :group1)})
(thf/sample-component :component1
library-page-id
(thf/id :group1)))
file (-> (thf/sample-file file-id file-page-id)
(thf/sample-instance :instance1
file-page-id
library
(thf/id :component1)))
absorbed-file (ctf/update-file-data
file
#(ctf/absorb-assets % (:data library)))
pages (ctpl/pages-seq (ctf/file-data absorbed-file))
components (ctkl/components-seq (ctf/file-data absorbed-file))
shapes-1 (ctn/shapes-seq (first pages))
shapes-2 (ctn/shapes-seq (second pages))
[[p-group p-shape] [c-group1 c-shape1] component1]
(thk/resolve-instance-and-main
(first pages)
(:id (second shapes-1))
{file-id absorbed-file})
[[lp-group lp-shape] [c-group2 c-shape2] component2]
(thk/resolve-instance-and-main
(second pages)
(:id (second shapes-2))
{file-id absorbed-file})]
;; Uncomment to debug
;; (println "\n===== library")
;; (ctf/dump-tree (:data library)
;; library-page-id
;; {}
;; true)
;; (println "\n===== file")
;; (ctf/dump-tree (:data file)
;; file-page-id
;; {library-id library}
;; true)
;; (println "\n===== absorbed file")
;; (println (str "\n<" (:name (first pages)) ">"))
;; (ctf/dump-tree (:data absorbed-file)
;; (:id (first pages))
;; {file-id absorbed-file}
;; false)
;; (println (str "\n<" (:name (second pages)) ">"))
;; (ctf/dump-tree (:data absorbed-file)
;; (:id (second pages))
;; {file-id absorbed-file}
;; false)
(t/is (= (count pages) 2))
(t/is (= (:name (first pages)) "Page 1"))
(t/is (= (:name (second pages)) "Main components"))
(t/is (= (count components) 1))
(t/is (= (:name p-group) "Group1"))
(t/is (ctk/instance-of? p-group file-id (:id component1)))
(t/is (not (:main-instance? p-group)))
(t/is (not (ctk/main-instance-of? (:id p-group) file-page-id component1)))
(t/is (ctk/is-main-of? c-group1 p-group))
(t/is (= (:name p-shape) "Rect1"))
(t/is (ctk/is-main-of? c-shape1 p-shape))))
(t/deftest test-absorb-colors
(let [library-id (uuid/custom 1 1)
library-page-id (uuid/custom 2 2)
file-id (uuid/custom 3 3)
file-page-id (uuid/custom 4 4)
library (-> (thf/sample-file library-id library-page-id {:is-shared true})
(thf/sample-color :color1 {:name "Test color"
:color "#abcdef"}))
file (-> (thf/sample-file file-id file-page-id)
(thf/sample-shape :shape1
:rect
file-page-id
{:name "Rect1"
:fills [{:fill-color "#abcdef"
:fill-opacity 1
:fill-color-ref-id (thf/id :color1)
:fill-color-ref-file library-id}]}))
absorbed-file (ctf/update-file-data
file
#(ctf/absorb-assets % (:data library)))
colors (ctcl/colors-seq (ctf/file-data absorbed-file))
page (ctpl/get-page (ctf/file-data absorbed-file) file-page-id)
shape1 (ctn/get-shape page (thf/id :shape1))
fill (first (:fills shape1))]
(t/is (= (count colors) 1))
(t/is (= (:id (first colors)) (thf/id :color1)))
(t/is (= (:name (first colors)) "Test color"))
(t/is (= (:color (first colors)) "#abcdef"))
(t/is (= (:fill-color fill) "#abcdef"))
(t/is (= (:fill-color-ref-id fill) (thf/id :color1)))
(t/is (= (:fill-color-ref-file fill) file-id))))
(t/deftest test-absorb-typographies
(let [library-id (uuid/custom 1 1)
library-page-id (uuid/custom 2 2)
file-id (uuid/custom 3 3)
file-page-id (uuid/custom 4 4)
library (-> (thf/sample-file library-id library-page-id {:is-shared true})
(thf/sample-typography :typography1 {:name "Test typography"}))
file (-> (thf/sample-file file-id file-page-id)
(thf/sample-shape :shape1
:text
file-page-id
{:name "Text1"
:content {:type "root"
:children [{:type "paragraph-set"
:children [{:type "paragraph"
:key "67uep"
:children [{:text "Example text"
:typography-ref-id (thf/id :typography1)
:typography-ref-file library-id
:line-height "1.2"
:font-style "normal"
:text-transform "none"
:text-align "left"
:font-id "sourcesanspro"
:font-family "sourcesanspro"
:font-size "14"
:font-weight "400"
:font-variant-id "regular"
:text-decoration "none"
:letter-spacing "0"
:fills [{:fill-color "#000000"
:fill-opacity 1}]}]}]}]}}))
absorbed-file (ctf/update-file-data
file
#(ctf/absorb-assets % (:data library)))
typographies (ctyl/typographies-seq (ctf/file-data absorbed-file))
page (ctpl/get-page (ctf/file-data absorbed-file) file-page-id)
shape1 (ctn/get-shape page (thf/id :shape1))
text-node (d/seek #(some? (:text %)) (txt/node-seq (:content shape1)))]
(t/is (= (count typographies) 1))
(t/is (= (:id (first typographies)) (thf/id :typography1)))
(t/is (= (:name (first typographies)) "Test typography"))
(t/is (= (:typography-ref-id text-node) (thf/id :typography1)))
(t/is (= (:typography-ref-file text-node) file-id))))

4
common/tests.edn Normal file
View file

@ -0,0 +1,4 @@
#kaocha/v1
{:tests [{:id :unit
:test-paths ["test"]}]
:kaocha/reporter [kaocha.report/dots]}