0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-08 13:01:24 -05:00

♻️ Refactor common module tests and add generative testing for types

This commit is contained in:
Andrey Antukh 2022-11-02 18:11:50 +01:00
parent 1f73558f1b
commit 111cf54ff6
33 changed files with 415 additions and 332 deletions

View file

@ -94,7 +94,7 @@ jobs:
working_directory: "./common"
name: common tests (clj)
command: |
clojure -X:dev:test
clojure -X:dev:test :patterns '["common-tests.test-.*"]'
environment:
PATH: /usr/local/nodejs/bin/:/usr/local/bin:/bin:/usr/bin

View file

@ -63,7 +63,6 @@
{:extra-deps
{com.bhauman/rebel-readline {:mvn/version "RELEASE"}
org.clojure/tools.namespace {:mvn/version "RELEASE"}
org.clojure/test.check {:mvn/version "RELEASE"}
clojure-humanize/clojure-humanize {:mvn/version "0.2.2"}
org.clojure/data.csv {:mvn/version "RELEASE"}
com.clojure-goes-fast/clj-async-profiler {:mvn/version "RELEASE"}

View file

@ -29,8 +29,8 @@
[clojure.pprint :refer [pprint print-table]]
[clojure.repl :refer :all]
[clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as sgen]
[clojure.test :as test]
[clojure.test.check.generators :as gen]
[clojure.tools.namespace.repl :as repl]
[clojure.walk :refer [macroexpand-all]]
[criterium.core :as crit]

View file

@ -4,6 +4,7 @@
org.clojure/tools.cli {:mvn/version "1.0.206"}
metosin/jsonista {:mvn/version "0.3.6"}
org.clojure/clojurescript {:mvn/version "1.11.60"}
org.clojure/test.check {:mvn/version "1.1.1"}
;; Logging
org.apache.logging.log4j/log4j-api {:mvn/version "2.19.0"}
@ -16,6 +17,7 @@
selmer/selmer {:mvn/version "1.12.55"}
criterium/criterium {:mvn/version "0.4.6"}
expound/expound {:mvn/version "0.9.0"}
com.cognitect/transit-clj {:mvn/version "1.0.329"}
com.cognitect/transit-cljs {:mvn/version "0.8.280"}
@ -41,7 +43,6 @@
{:dev
{:extra-deps
{org.clojure/tools.namespace {:mvn/version "RELEASE"}
org.clojure/test.check {:mvn/version "RELEASE"}
thheller/shadow-cljs {:mvn/version "2.20.2"}
com.bhauman/rebel-readline {:mvn/version "RELEASE"}
criterium/criterium {:mvn/version "RELEASE"}

View file

@ -2,7 +2,7 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns user
(:require
@ -12,32 +12,33 @@
[clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as sgen]
[clojure.test :as test]
[clojure.test.check.generators :as gen]
[clojure.tools.namespace.repl :as repl]
[clojure.walk :refer [macroexpand-all]]
[criterium.core :refer [quick-bench bench with-progress-reporting]]))
[criterium.core :as crit]))
;; --- Benchmarking Tools
(defmacro run-quick-bench
[& exprs]
`(with-progress-reporting (quick-bench (do ~@exprs) :verbose)))
`(crit/with-progress-reporting (crit/quick-bench (do ~@exprs) :verbose)))
(defmacro run-quick-bench'
[& exprs]
`(quick-bench (do ~@exprs)))
`(crit/quick-bench (do ~@exprs)))
(defmacro run-bench
[& exprs]
`(with-progress-reporting (bench (do ~@exprs) :verbose)))
`(crit/with-progress-reporting (crit/bench (do ~@exprs) :verbose)))
(defmacro run-bench'
[& exprs]
`(bench (do ~@exprs)))
`(crit/bench (do ~@exprs)))
;; --- Development Stuff
(defn- run-tests
([] (run-tests #"^app.common.*-test$"))
([] (run-tests #"^common-tests.test-.*$"))
([o]
(repl/refresh)
(cond

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
export PENPOT_FLAGS="enable-asserts enable-audit-log $PENPOT_FLAGS"
export OPTIONS="-A:dev -J-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -J-XX:+UseG1GC -J-XX:-OmitStackTraceInFastThrow -J-Xms50m -J-Xmx512m";
export OPTIONS="-A:dev -J-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -J-XX:+UseG1GC -J-XX:-OmitStackTraceInFastThrow -J-Xms50m -J-Xmx1024m";
export OPTIONS_EVAL="nil"
# export OPTIONS_EVAL="(set! *warn-on-reflection* true)"

View file

@ -8,7 +8,7 @@
{:target :node-test
:output-to "target/test.js"
:output-dir "target/test/"
:ns-regexp "^app.common.*-test$"
:ns-regexp "^common-tests.test-.*$"
:autorun true
:compiler-options

View file

@ -12,7 +12,8 @@
[app.common.geom.point :as gpt]
[app.common.math :as mth]
[app.common.spec :as us]
[clojure.spec.alpha :as s]))
[clojure.spec.alpha :as s]
[clojure.test.check.generators :as tgen]))
(def precision 6)
@ -39,16 +40,6 @@
[v]
(instance? Matrix v))
(s/def ::a ::us/safe-number)
(s/def ::b ::us/safe-number)
(s/def ::c ::us/safe-number)
(s/def ::d ::us/safe-number)
(s/def ::e ::us/safe-number)
(s/def ::f ::us/safe-number)
(s/def ::matrix
(s/and (s/keys :req-un [::a ::b ::c ::d ::e ::f]) matrix?))
(defn matrix
"Create a new matrix instance."
([]
@ -56,6 +47,21 @@
([a b c d e f]
(Matrix. a b c d e f)))
(s/def ::a ::us/safe-float)
(s/def ::b ::us/safe-float)
(s/def ::c ::us/safe-float)
(s/def ::d ::us/safe-float)
(s/def ::e ::us/safe-float)
(s/def ::f ::us/safe-float)
(s/def ::matrix-attrs
(s/keys :req-un [::a ::b ::c ::d ::e ::f]))
(s/def ::matrix
(s/with-gen
(s/and ::matrix-attrs matrix?)
#(tgen/fmap map->Matrix (s/gen ::matrix-attrs))))
(def number-regex #"[+-]?\d*(\.\d+)?(e[+-]?\d+)?")
(defn str->matrix

View file

@ -13,7 +13,8 @@
:clj [clojure.core :as c])
[app.common.math :as mth]
[app.common.spec :as us]
[clojure.spec.alpha :as s]))
[clojure.spec.alpha :as s]
[clojure.test.check.generators :as tgen]))
;; --- Point Impl
@ -30,8 +31,11 @@
(s/def ::x ::us/safe-number)
(s/def ::y ::us/safe-number)
(s/def ::point-attrs (s/keys :req-un [::x ::y]))
(s/def ::point
(s/and (s/keys :req-un [::x ::y]) point?))
(s/with-gen (s/and ::point-attrs point?)
#(tgen/fmap map->Point (s/gen ::point-attrs))))
(defn point-like?
[{:keys [x y] :as v}]

View file

@ -18,6 +18,7 @@
[app.common.exceptions :as ex]
[app.common.uri :as u]
[app.common.uuid :as uuid]
[clojure.test.check.generators :as tgen]
[cuerdas.core :as str]
[expound.alpha :as expound]))
@ -47,7 +48,9 @@
::s/invalid)))
(unformer [v]
(dm/str v))]
(s/def ::uuid (s/conformer conformer unformer)))
(s/def ::uuid
(s/with-gen (s/conformer conformer unformer)
#(tgen/fmap (fn [_] (uuid/random)) tgen/any))))
;; --- SPEC: boolean
@ -61,7 +64,9 @@
::s/invalid)))
(unformer [v]
(if v "true" "false"))]
(s/def ::boolean (s/conformer conformer unformer)))
(s/def ::boolean
(s/with-gen (s/conformer conformer unformer)
(constantly tgen/boolean))))
;; --- SPEC: number
@ -71,7 +76,9 @@
(str/numeric? v) #?(:cljs (js/parseFloat v)
:clj (Double/parseDouble v))
:else ::s/invalid))]
(s/def ::number (s/conformer conformer str)))
(s/def ::number
(s/with-gen (s/conformer conformer str)
#(s/gen ::safe-number))))
;; --- SPEC: integer
@ -84,7 +91,9 @@
:cljs (js/parseInt v 10))
::s/invalid)
:else ::s/invalid))]
(s/def ::integer (s/conformer conformer str)))
(s/def ::integer
(s/with-gen (s/conformer conformer str)
#(s/gen ::safe-integer))))
;; --- SPEC: keyword
@ -96,7 +105,10 @@
(unformer [v]
(name v))]
(s/def ::keyword (s/conformer conformer unformer)))
(s/def ::keyword
(s/with-gen (s/conformer conformer unformer)
#(->> (s/gen ::not-empty-string)
(tgen/fmap keyword)))))
;; --- SPEC: email
@ -110,7 +122,13 @@
(or (parse-email v) ::s/invalid))
(unformer [v]
(dm/str v))]
(s/def ::email (s/conformer conformer unformer)))
(s/def ::email
(s/with-gen (s/conformer conformer unformer)
#(as-> (tgen/let [p1 (s/gen ::not-empty-string)
p2 (s/gen ::not-empty-string)
p3 (tgen/elements ["com" "net"])]
(str p1 "@" p2 "." p3)) $
(tgen/such-that (partial re-matches email-re) $ 50)))))
;; -- SPEC: uri
@ -121,17 +139,34 @@
:else ::s/invalid))
(unformer [v]
(dm/str v))]
(s/def ::uri (s/conformer conformer unformer)))
(s/def ::uri
(s/with-gen (s/conformer conformer unformer)
#(tgen/let [scheme (tgen/elements ["http" "https"])
domain (as-> (s/gen ::not-empty-string) $
(tgen/such-that (fn [x] (> (count x) 5)) $ 100)
(tgen/fmap str/lower $))
ext (tgen/elements ["net" "com" "org" "app" "io"])]
(u/uri (str scheme "://" domain "." ext))))))
;; --- SPEC: color string
(def rgb-color-str-re
#"^#(?:[0-9a-fA-F]{3}){1,2}$")
(letfn [(conformer [v]
(if (and (string? v) (re-matches #"^#(?:[0-9a-fA-F]{3}){1,2}$" v))
(if (and (string? v) (re-matches rgb-color-str-re v))
v
::s/invalid))
(unformer [v]
(dm/str v))]
(s/def ::rgb-color-str (s/conformer conformer unformer)))
(s/def ::rgb-color-str
(s/with-gen (s/conformer conformer unformer)
#(->> tgen/any
(tgen/fmap (fn [_]
#?(:clj (format "%x" (rand-int 16rFFFFFF))
:cljs (.toString (rand-int 16rFFFFFF) 16))))
(tgen/fmap (fn [x]
(str "#" x)))))))
;; --- SPEC: set/vector of Keywords
@ -142,17 +177,19 @@
(keyword? s) s
:else nil)))]
(cond
(set? s) (into dest xform s)
(coll? s) (into dest xform s)
(string? s) (into dest xform (str/words s))
:else ::s/invalid)))
(unformer-fn [v]
(str/join " " (map name v)))]
(s/def ::set-of-keywords
(s/conformer (partial conformer-fn #{}) unformer-fn))
(s/with-gen (s/conformer (partial conformer-fn #{}) unformer-fn)
#(tgen/set (s/gen ::keyword))))
(s/def ::vector-of-keywords
(s/conformer (partial conformer-fn []) unformer-fn)))
(s/with-gen (s/conformer (partial conformer-fn []) unformer-fn)
#(tgen/vector (s/gen ::keyword)))))
;; --- SPEC: set/vector of strings
@ -164,18 +201,18 @@
(letfn [(conformer-fn [dest v]
(cond
(coll? v) (into dest non-empty-strings-xf v)
(string? v) (into dest non-empty-strings-xf (str/split v #"[\s,]+"))
(vector? v) (into dest non-empty-strings-xf v)
(set? v) (into dest non-empty-strings-xf v)
:else ::s/invalid))
(unformer-fn [v]
(str/join "," v))]
(s/def ::set-of-strings
(s/conformer (partial conformer-fn #{}) unformer-fn))
(s/with-gen (s/conformer (partial conformer-fn #{}) unformer-fn)
#(tgen/set (s/gen ::not-empty-string))))
(s/def ::vector-of-strings
(s/conformer (partial conformer-fn []) unformer-fn)))
(s/with-gen (s/conformer (partial conformer-fn []) unformer-fn)
#(tgen/vector (s/gen ::not-empty-string)))))
;; --- SPEC: set-of-valid-emails
@ -192,24 +229,27 @@
:else ::s/invalid))
(unformer [v]
(str/join " " v))]
(s/def ::set-of-valid-emails (s/conformer conformer unformer)))
;; --- SPEC: query-string
(letfn [(conformer [s]
(if (string? s)
(ex/try* #(u/query-string->map s) (constantly ::s/invalid))
s))
(unformer [s]
(u/map->query-string s))]
(s/def ::query-string (s/conformer conformer unformer)))
(s/def ::set-of-valid-emails
(s/with-gen (s/conformer conformer unformer)
#(tgen/set (s/gen ::email)))))
;; --- SPECS WITHOUT CONFORMER
(s/def ::inst inst?)
(s/def ::string string?)
(s/def ::not-empty-string (s/and string? #(not (str/empty? %))))
(s/def ::url string?)
(s/def ::string
(s/with-gen string?
(fn []
(tgen/such-that (fn [o]
(re-matches #"\w+" o))
tgen/string-alphanumeric
50))))
(s/def ::not-empty-string
(s/with-gen (s/and string? #(not (str/empty? %)))
#(tgen/such-that (complement str/empty?) (s/gen ::string))))
(s/def ::url ::string)
(s/def ::fn fn?)
(s/def ::id ::uuid)
@ -231,20 +271,34 @@
:cljs (or (instance? js/Uint8Array x)
(instance? js/ArrayBuffer x)))))
(s/def ::bytes bytes?)
(s/def ::bytes
#?(:clj (s/with-gen bytes? (constantly tgen/bytes))
:cljs bytes?))
(defn safe-number?
[x]
(and (number? x)
(>= x min-safe-int)
(<= x max-safe-int)))
(defn safe-int? [x]
(and (safe-number? x) (int? x)))
(defn safe-float? [x]
(and (safe-number? x) (float? x)))
(s/def ::safe-integer
#(and
(int? %)
(>= % min-safe-int)
(<= % max-safe-int)))
(s/with-gen safe-int? (constantly tgen/small-integer)))
(s/def ::safe-float
(s/with-gen safe-float? #(tgen/double* {:inifinite? false
:NaN? false
:min min-safe-int
:max max-safe-int})))
(s/def ::safe-number
#(and
(or (int? %)
(float? %))
(>= % min-safe-int)
(<= % max-safe-int)))
(s/with-gen safe-number? #(tgen/one-of [(s/gen ::safe-integer)
(s/gen ::safe-float)])))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MACROS

View file

@ -27,7 +27,7 @@
(s/def ::color-gradient/end-y ::us/safe-number)
(s/def ::color-gradient/width ::us/safe-number)
(s/def ::color-gradient-stop/color string?)
(s/def ::color-gradient-stop/color ::us/rgb-color-str)
(s/def ::color-gradient-stop/opacity ::us/safe-number)
(s/def ::color-gradient-stop/offset ::us/safe-number)
@ -53,7 +53,7 @@
(s/def ::color-generic/name string?)
(s/def ::color-generic/path (s/nilable string?))
(s/def ::color-generic/value (s/nilable string?))
(s/def ::color-generic/color (s/nilable string?))
(s/def ::color-generic/color (s/nilable ::us/rgb-color-str))
(s/def ::color-generic/opacity (s/nilable ::us/safe-number))
(s/def ::color-generic/gradient (s/nilable ::gradient))
(s/def ::color-generic/ref-id uuid?)
@ -76,10 +76,14 @@
::color-generic/gradient]))
(s/def ::recent-color
(s/keys :opt-un [::color-generic/value
::color-generic/color
::color-generic/opacity
::color-generic/gradient]))
(s/and
(s/keys :opt-un [::color-generic/value
::color-generic/color
::color-generic/opacity
::color-generic/gradient])
(fn [o]
(or (contains? o :gradient)
(contains? o :color)))))
;; --- Helpers for color in different parts of a shape
@ -159,7 +163,7 @@
[shape position color opacity gradient]
(update-in shape [:shadow position :color]
(fn [shadow-color]
(d/without-nils (assoc shadow-color
(d/without-nils (assoc shadow-color
:color color
:opacity opacity
:gradient gradient)))))
@ -190,7 +194,7 @@
[shape position color opacity gradient]
(update-in shape [:grids position :params :color]
(fn [grid-color]
(d/without-nils (assoc grid-color
(d/without-nils (assoc grid-color
:color color
:opacity opacity
:gradient gradient)))))

View file

@ -15,13 +15,12 @@
(s/def ::type #{:page :component})
(s/def ::id uuid?)
(s/def ::name string?)
(s/def ::path (s/nilable string?))
(s/def ::name ::us/string)
(s/def ::path (s/nilable ::us/string))
(s/def ::container
;; (s/keys :req-un [::id ::name ::ctst/objects]
(s/keys :req-un [::id ::name]
:opt-un [::type ::path]))
:opt-un [::type ::path ::ctst/objects]))
(defn make-container
[page-or-component type]

View file

@ -37,7 +37,7 @@
(s/coll-of ::ctc/recent-color :kind vector?))
(s/def ::typographies
(s/map-of uuid? :ctst/typography))
(s/map-of uuid? ::cty/typography))
(s/def ::pages
(s/coll-of uuid? :kind vector?))
@ -49,12 +49,13 @@
(s/map-of uuid? ::ctp/page))
(s/def ::components
(s/map-of uuid? ::ctp/container))
(s/map-of uuid? ::ctn/container))
(s/def ::data
(s/keys :req-un [::pages-index
::pages]
:opt-un [::colors
::components
::recent-colors
::typographies
::media]))

View file

@ -8,6 +8,7 @@
(:require
[app.common.data :as d]
[app.common.files.features :as ffeat]
[app.common.spec :as us]
[app.common.types.page.flow :as ctpf]
[app.common.types.page.grid :as ctpg]
[app.common.types.page.guide :as ctpu]
@ -17,7 +18,7 @@
;; --- Background color
(s/def ::background string?)
(s/def ::background ::us/rgb-color-str)
;; --- Page options

View file

@ -25,18 +25,19 @@
[app.common.types.shape.text :as ctsx]
[app.common.uuid :as uuid]
[clojure.set :as set]
[clojure.spec.alpha :as s]))
[clojure.spec.alpha :as s]
[clojure.test.check.generators :as tgen]))
;; --- Specs
(s/def ::frame-id uuid?)
(s/def ::id uuid?)
(s/def ::name string?)
(s/def ::path (s/nilable string?))
(s/def ::name ::us/string)
(s/def ::path (s/nilable ::us/string))
(s/def ::page-id uuid?)
(s/def ::parent-id uuid?)
(s/def ::string string?)
(s/def ::type keyword?)
(s/def ::string ::us/string)
(s/def ::type #{:frame :text :rect :path :image :circle :group :bool :svg-raw})
(s/def ::uuid uuid?)
(s/def ::component-id uuid?)
@ -54,7 +55,7 @@
(s/def ::blocked boolean?)
(s/def ::collapsed boolean?)
(s/def ::fill-color string?)
(s/def ::fill-color ::us/rgb-color-str)
(s/def ::fill-opacity ::us/safe-number)
(s/def ::fill-color-gradient (s/nilable ::ctc/gradient))
(s/def ::fill-color-ref-file (s/nilable uuid?))
@ -66,10 +67,10 @@
(s/def ::file-thumbnail boolean?)
(s/def ::masked-group? boolean?)
(s/def ::font-family string?)
(s/def ::font-family ::us/string)
(s/def ::font-size ::us/safe-integer)
(s/def ::font-style string?)
(s/def ::font-weight string?)
(s/def ::font-style ::us/string)
(s/def ::font-weight ::us/string)
(s/def ::hidden boolean?)
(s/def ::letter-spacing ::us/safe-number)
(s/def ::line-height ::us/safe-number)
@ -77,7 +78,7 @@
(s/def ::page-id uuid?)
(s/def ::proportion ::us/safe-number)
(s/def ::proportion-lock boolean?)
(s/def ::stroke-color string?)
(s/def ::stroke-color ::us/string)
(s/def ::stroke-color-gradient (s/nilable ::ctc/gradient))
(s/def ::stroke-color-ref-file (s/nilable uuid?))
(s/def ::stroke-color-ref-id (s/nilable uuid?))
@ -120,11 +121,12 @@
(s/every uuid? :kind vector?))
(s/def ::fill
(s/keys :opt-un [::fill-color
::fill-opacity
::fill-color-gradient
::fill-color-ref-file
::fill-color-ref-id]))
(s/and (s/keys :opt-un [::fill-color
::fill-opacity
::fill-color-gradient
::fill-color-ref-file
::fill-color-ref-id])
(comp boolean seq)))
(s/def ::fills
(s/coll-of ::fill :kind vector?))
@ -164,72 +166,70 @@
:color
:luminosity})
(s/def ::shape-base-attrs
(s/keys :opt-un [::id
::name
::component-id
::component-file
::component-root?
::shape-ref
::selrect
::points
::blocked
::collapsed
::fills
::hide-fill-on-export
::font-family
::font-size
::font-style
::font-weight
::hidden
::letter-spacing
::line-height
::locked
::proportion
::proportion-lock
::constraints-h
::constraints-v
::fixed-scroll
::ctsr/rx
::ctsr/ry
::ctsr/r1
::ctsr/r2
::ctsr/r3
::ctsr/r4
::x
::y
::exports
::shapes
::strokes
::text-align
::transform
::transform-inverse
::width
::height
::masked-group?
::ctsi/interactions
::ctss/shadow
::ctsb/blur
::opacity
::blend-mode]))
(s/def ::shape-attrs
(s/and
::ctsl/layout-container-props
::ctsl/layout-child-props
(s/keys :opt-un [::id
::type
::name
::component-id
::component-file
::component-root?
::shape-ref
::selrect
::points
::blocked
::collapsed
::fills
::fill-color ;; TODO: remove these attributes
::fill-opacity ;; when backward compatibility
::fill-color-gradient ;; is no longer needed
::fill-color-ref-file ;;
::fill-color-ref-id ;;
::hide-fill-on-export
::font-family
::font-size
::font-style
::font-weight
::hidden
::letter-spacing
::line-height
::locked
::proportion
::proportion-lock
::constraints-h
::constraints-v
::fixed-scroll
::ctsr/rx
::ctsr/ry
::ctsr/r1
::ctsr/r2
::ctsr/r3
::ctsr/r4
::x
::y
::exports
::shapes
::strokes
::stroke-color ;; TODO: same thing
::stroke-color-ref-file ;;
::stroke-color-ref-id ;;
::stroke-opacity ;;
::stroke-style
::stroke-width
::stroke-alignment
::stroke-cap-start
::stroke-cap-end
::text-align
::transform
::transform-inverse
::width
::height
::masked-group?
::ctsi/interactions
::ctss/shadow
::ctsb/blur
::opacity
::blend-mode])))
(s/with-gen
(s/merge
::shape-base-attrs
::ctsl/layout-container-props
::ctsl/layout-child-props
;; For BACKWARD COMPATIBILITY we need to spec fill and stroke
;; attrs as shape toplevel attrs
::fill
::stroke)
#(tgen/let [attrs1 (s/gen ::shape-base-attrs)
attrs2 (s/gen ::ctsl/layout-container-props)
attrs3 (s/gen ::ctsl/layout-child-props)]
(merge attrs1 attrs2 attrs3))))
(defmulti shape-spec :type)
@ -237,26 +237,31 @@
(s/spec ::shape-attrs))
(defmethod shape-spec :text [_]
(s/and ::shape-attrs
(s/keys :opt-un [::ctsx/content
::ctsx/position-data])))
(s/merge ::shape-attrs
(s/keys :opt-un [::ctsx/content
::ctsx/position-data])))
(defmethod shape-spec :path [_]
(s/and ::shape-attrs
(s/keys :opt-un [::ctsp/content])))
(s/merge ::shape-attrs
(s/keys :opt-un [::ctsp/content])))
(defmethod shape-spec :frame [_]
(s/and ::shape-attrs
(s/keys :opt-un [::file-thumbnail
::hide-fill-on-export
::show-content
::hide-in-viewer])))
(s/merge ::shape-attrs
(s/keys :opt-un [::file-thumbnail
::hide-fill-on-export
::show-content
::hide-in-viewer])))
(s/def ::shape
(s/and (s/multi-spec shape-spec :type)
#(contains? % :type)
#(contains? % :name)))
(s/with-gen
(s/merge
(s/keys :req-un [::type ::name])
(s/multi-spec shape-spec :type))
(fn []
(tgen/let [type (s/gen ::type)
name (s/gen ::name)
attrs (s/gen ::shape-attrs)]
(assoc attrs :type type :name name)))))
;; --- Initialization

View file

@ -9,9 +9,9 @@
[app.common.spec :as us]
[clojure.spec.alpha :as s]))
(s/def ::suffix string?)
(s/def ::suffix ::us/string)
(s/def ::scale ::us/safe-number)
(s/def ::type keyword?)
(s/def ::type ::us/keyword)
(s/def ::export
(s/keys :req-un [::type

View file

@ -22,12 +22,13 @@
;; -- Options depending on event type
(s/def ::event-type #{:click
:mouse-press
:mouse-over
:mouse-enter
:mouse-leave
:after-delay})
(s/def ::event-type
#{:click
:mouse-press
:mouse-over
:mouse-enter
:mouse-leave
:after-delay})
(s/def ::delay ::us/safe-integer)
@ -40,26 +41,21 @@
(s/keys :req-un []))
(s/def ::event-opts
(s/multi-spec event-opts-spec ::event-type))
(s/multi-spec event-opts-spec :event-type))
;; -- Animation options
(s/def ::animation-type #{:dissolve
:slide
:push})
(s/def ::animation-type #{:dissolve :slide :push})
(s/def ::duration ::us/safe-integer)
(s/def ::easing #{:linear
:ease
:ease-in
:ease-out
:ease-in-out})
(s/def ::way #{:in
:out})
(s/def ::direction #{:right
:left
:up
:down})
(s/def ::way #{:in :out})
(s/def ::direction #{:right :left :up :down})
(s/def ::offset-effect ::us/boolean)
(s/def ::easing
#{:linear
:ease
:ease-in
:ease-out
:ease-in-out})
(defmulti animation-spec :animation-type)
@ -80,26 +76,29 @@
::direction]))
(s/def ::animation
(s/multi-spec animation-spec ::animation-type))
(s/multi-spec animation-spec :animation-type))
;; -- Options depending on action type
(s/def ::action-type #{:navigate
:open-overlay
:toggle-overlay
:close-overlay
:prev-screen
:open-url})
(s/def ::action-type
#{:navigate
:open-overlay
:toggle-overlay
:close-overlay
:prev-screen
:open-url})
(s/def ::overlay-pos-type
#{:manual
:center
:top-left
:top-right
:top-center
:bottom-left
:bottom-right
:bottom-center})
(s/def ::destination (s/nilable ::us/uuid))
(s/def ::overlay-pos-type #{:manual
:center
:top-left
:top-right
:top-center
:bottom-left
:bottom-right
:bottom-center})
(s/def ::overlay-position ::gpt/point)
(s/def ::url ::us/string)
(s/def ::close-click-outside ::us/boolean)
@ -140,7 +139,7 @@
(s/keys :req-un [::url]))
(s/def ::action-opts
(s/multi-spec action-opts-spec ::action-type))
(s/multi-spec action-opts-spec :action-type))
;; -- Interaction
@ -412,6 +411,7 @@
(us/verify (s/nilable ::animation-type) animation-type)
(assert (has-animation? interaction))
(assert (allowed-animation? (:action-type interaction) animation-type))
(if (= (-> interaction :animation :animation-type) animation-type)
interaction
(if (nil? animation-type)

View file

@ -30,6 +30,7 @@
(s/def ::row-gap ::us/safe-number)
(s/def ::column-gap ::us/safe-number)
(s/def ::layout-type #{:flex :grid})
(s/def ::layout-gap
(s/keys :req-un [::row-gap ::column-gap]))

View file

@ -1,58 +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) UXBOX Labs SL
(ns app.common.data-test
(:require
[app.common.data :as d]
[clojure.test :as t]))
(t/deftest concat-vec
(t/is (= [1 2 3]
(d/concat-vec [1] #{2} [3])))
(t/is (= [1 2]
(d/concat-vec '(1) [2])))
(t/is (= [1]
(d/concat-vec [1])))
(t/is (= [] (d/concat-vec))))
(t/deftest concat-set
(t/is (= #{} (d/concat-set)))
(t/is (= #{1 2}
(d/concat-set [1] [2]))))
(t/deftest remove-at-index
(t/is (= [1 2 3 4]
(d/remove-at-index [1 2 3 4 5] 4)))
(t/is (= [1 2 3 4]
(d/remove-at-index [5 1 2 3 4] 0)))
(t/is (= [1 2 3 4]
(d/remove-at-index [1 5 2 3 4] 1)))
)
(t/deftest with-next
(t/is (= [[0 1] [1 2] [2 3] [3 4] [4 nil]]
(d/with-next (range 5)))))
(t/deftest with-prev
(t/is (= [[0 nil] [1 0] [2 1] [3 2] [4 3]]
(d/with-prev (range 5)))))
(t/deftest with-prev-next
(t/is (= [[0 nil 1] [1 0 2] [2 1 3] [3 2 4] [4 3 nil]]
(d/with-prev-next (range 5)))))
(t/deftest join
(t/is (= [[1 :a] [1 :b] [2 :a] [2 :b] [3 :a] [3 :b]]
(d/join [1 2 3] [:a :b])))
(t/is (= [1 10 100 2 20 200 3 30 300]
(d/join [1 2 3] [1 10 100] *))))

View file

@ -2,9 +2,9 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.data-test
(ns common-tests.test-data
(:require
[app.common.data :as d]
[clojure.test :as t]))

View file

@ -2,9 +2,9 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.geom-test
(ns common-tests.test-geom
(:require
[clojure.test :as t]
[app.common.math :as mth]

View file

@ -2,9 +2,9 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.geom-shapes-test
(ns common-tests.test-geom-shapes
(:require
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]

View file

@ -1,4 +1,10 @@
(ns app.common.test-helpers.components
;; 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.test-helpers.components
(:require
[clojure.test :as t]
[app.common.pages.helpers :as cph]
@ -136,7 +142,7 @@
[shapes-inst shapes-main component]))
(defn resolve-component
"Get the component with the given id and all its shapes."
"Get the component with the given id and all its shapes."
[page component-id libraries]
(let [component (cph/get-component libraries component-id)
root-main (ctk/get-component-root component)

View file

@ -2,9 +2,9 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.test-helpers.files
(ns common-tests.test-helpers.files
(:require
[app.common.files.features :as ffeat]
[app.common.geom.point :as gpt]

View file

@ -2,9 +2,9 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.pages-test
(ns common-tests.test-pages
(:require
[app.common.files.features :as ffeat]
[app.common.pages :as cp]
@ -438,7 +438,7 @@
:frame-id frame-id
:parent-id frame-id
:id shape-1-id
:obj {:type :shape
:obj {:type :rect
:name "Shape 1"}}
{:type :add-obj
:page-id page-id

View file

@ -2,9 +2,9 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.pages-helpers-test
(ns common-tests.test-pages-helpers
(:require
[clojure.test :as t]
[clojure.pprint :refer [pprint]]

View file

@ -2,9 +2,9 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.pages-migrations-test
(ns common-tests.test-pages-migrations
(:require
[clojure.test :as t]
[clojure.pprint :refer [pprint]]

View file

@ -1,4 +1,4 @@
(ns app.common.setup-test
(ns common-tests.test-setup
(:require
[clojure.test :as t]))

View file

@ -1,4 +1,10 @@
(ns app.common.text-test
;; 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.test-text
(:require
[app.common.data :as d]
[app.common.text :as txt]

View file

@ -0,0 +1,59 @@
;; 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.test-types
(:require
[clojure.spec.alpha :as s]
[clojure.test :as t]
[clojure.test.check.clojure-test :refer [defspec]]
[clojure.test.check.generators :as gen]
[clojure.test.check.properties :as props]
[app.common.spec :as us]
[app.common.transit :as transit]
[app.common.types.shape :as cts]
[app.common.types.page :as ctp]
[app.common.types.file :as ctf]))
(defspec transit-encode-decode-with-shape 30
(props/for-all
[fdata (s/gen ::cts/shape)]
(let [res (-> fdata transit/encode-str transit/decode-str)]
(t/is (= res fdata)))))
(defspec types-shape-spec 10
(props/for-all
[fdata (s/gen ::cts/shape)]
(t/is (us/valid? ::cts/shape fdata))))
(defspec types-page-spec 10
(props/for-all
[fdata (s/gen ::ctp/page)]
(t/is (us/valid? ::ctp/page fdata))))
(defspec types-file-colors-spec 30
(props/for-all
[fdata (s/gen ::ctf/colors)]
(t/is (us/valid? ::ctf/colors fdata))))
(defspec types-file-recent-colors-spec 30
(props/for-all
[fdata (s/gen ::ctf/recent-colors)]
(t/is (us/valid? ::ctf/recent-colors fdata))))
(defspec types-file-typographies-spec 30
(props/for-all
[fdata (s/gen ::ctf/typographies)]
(t/is (us/valid? ::ctf/typographies fdata))))
(defspec types-file-media-spec 30
(props/for-all
[fdata (s/gen ::ctf/media)]
(t/is (us/valid? ::ctf/media fdata))))
(defspec types-file-components-spec 10
(props/for-all
[fdata (s/gen ::ctf/components)]
(t/is (us/valid? ::ctf/components fdata))))

View file

@ -2,29 +2,28 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.types.file-test
(ns common-tests.test-types-file
(:require
;; Uncomment to debug
;; [clojure.pprint :refer [pprint]]
;; [cuerdas.core :as str]
[clojure.test :as t]
[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]
[app.common.test-helpers.files :as thf]
[app.common.test-helpers.components :as thk]))
[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.test-helpers.components :as thk]
[common-tests.test-helpers.files :as thf]
[cuerdas.core :as str]))
(t/use-fixtures :each thf/reset-idmap!)

View file

@ -2,17 +2,17 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.types.shape.spec-interactions-test
(ns common-tests.test-types-shape-interactions
(:require
[clojure.test :as t]
[clojure.pprint :refer [pprint]]
[app.common.exceptions :as ex]
[app.common.geom.point :as gpt]
[app.common.types.shape :as cts]
[app.common.types.shape.interactions :as ctsi]
[app.common.uuid :as uuid]
[app.common.geom.point :as gpt]))
[clojure.pprint :refer [pprint]]
[clojure.test :as t]))
(t/deftest set-event-type
(let [interaction ctsi/default-interaction
@ -497,7 +497,6 @@
(t/is (= :down (:direction a-up')))
(t/is (= :up (:direction a-down')))))))
(t/deftest option-offset-effect
(let [i1 ctsi/default-interaction
i2 (ctsi/set-animation-type ctsi/default-interaction :slide)

View file

@ -2,26 +2,22 @@
;; 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) UXBOX Labs SL
;; Copyright (c) KALEIDOS INC
(ns app.common.uuid-test
(ns common-tests.test-uuid
(:require
[app.common.spec :as us]
[app.common.uuid :as uuid]
[clojure.spec.alpha :as s]
[clojure.test :as t]
[clojure.test.check.clojure-test :refer (defspec)]
[clojure.test.check.clojure-test :refer [defspec]]
[clojure.test.check.generators :as gen]
[clojure.test.check.properties :as props]))
(def uuid-gen
(->> gen/large-integer (gen/fmap (fn [_] (uuid/next)))))
(defspec non-repeating-uuid-next-1 100000
(defspec non-repeating-uuid-next-1 5000
(props/for-all
[uuid1 uuid-gen
uuid2 uuid-gen
uuid3 uuid-gen
uuid4 uuid-gen
uuid5 uuid-gen]
(t/is (not= uuid1 uuid2 uuid3 uuid4 uuid5))))
[uuid1 (s/gen ::us/uuid)
uuid2 (s/gen ::us/uuid)]
(t/is (not= uuid1 uuid2))))