0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-09 08:20:45 -05:00
penpot/backend/test/backend_tests/helpers.clj

441 lines
14 KiB
Clojure
Raw Normal View History

;; 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/.
;;
2022-09-20 16:23:22 -05:00
;; Copyright (c) KALEIDOS INC
(ns backend-tests.helpers
(:require
2021-01-31 11:02:10 -05:00
[app.common.data :as d]
[app.common.flags :as flags]
[app.common.pages :as cp]
2022-06-30 08:11:41 -05:00
[app.common.pprint :as pp]
2021-01-31 11:02:10 -05:00
[app.common.spec :as us]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
[app.main :as main]
[app.media]
[app.migrations]
2022-11-07 10:56:02 -05:00
[app.rpc.helpers :as rph]
2022-06-30 08:11:41 -05:00
[app.rpc.commands.auth :as cmd.auth]
[app.rpc.commands.files :as files]
[app.rpc.commands.files.create :as files.create]
[app.rpc.commands.files.update :as files.update]
[app.rpc.mutations.profile :as profile]
[app.rpc.mutations.projects :as projects]
[app.rpc.mutations.teams :as teams]
[app.util.blob :as blob]
[app.util.services :as sv]
[app.util.time :as dt]
[clojure.java.io :as io]
[clojure.spec.alpha :as s]
[clojure.test :as t]
[cuerdas.core :as str]
[datoteka.core :as fs]
[environ.core :refer [env]]
2021-01-31 11:02:10 -05:00
[expound.alpha :as expound]
[integrant.core :as ig]
[mockery.core :as mk]
2022-06-30 08:11:41 -05:00
[promesa.core :as p]
[yetti.request :as yrq])
(:import
java.util.UUID
org.postgresql.ds.PGSimpleDataSource))
(def ^:dynamic *system* nil)
(def ^:dynamic *pool* nil)
2021-03-30 08:35:18 -05:00
(def defaults
{:database-uri "postgresql://postgres/penpot_test"
:redis-uri "redis://redis/1"})
(def config
(->> (cf/read-env "penpot-test")
(merge cf/defaults defaults)
(us/conform ::cf/config)))
2022-09-20 17:46:22 -05:00
(def default-flags
[:enable-secure-session-cookies
:enable-email-verification
:enable-smtp])
(defn state-init
[next]
(let [templates [{:id "test"
:name "test"
:file-uri "test"
:thumbnail-uri "test"
:path (-> "backend_tests/test_files/template.penpot" io/resource fs/path)}]
2022-09-20 17:46:22 -05:00
system (-> (merge main/system-config main/worker-config)
(assoc-in [:app.redis/redis :app.redis/uri] (:redis-uri config))
2021-03-30 08:35:18 -05:00
(assoc-in [:app.db/pool :uri] (:database-uri config))
(assoc-in [:app.db/pool :username] (:database-username config))
(assoc-in [:app.db/pool :password] (:database-password config))
(assoc-in [:app.rpc/methods :templates] templates)
(dissoc :app.srepl/server
:app.http/server
:app.http/router
:app.http.awsns/handler
:app.http.session/updater
2022-06-30 08:11:41 -05:00
:app.auth.oidc/google-provider
:app.auth.oidc/gitlab-provider
:app.auth.oidc/github-provider
:app.auth.oidc/generic-provider
:app.setup/builtin-templates
2022-06-30 08:11:41 -05:00
:app.auth.oidc/routes
:app.worker/executors-monitor
:app.http.oauth/handler
:app.notifications/handler
:app.loggers.sentry/reporter
:app.loggers.mattermost/reporter
:app.loggers.loki/reporter
:app.loggers.database/reporter
:app.loggers.zmq/receiver
:app.worker/cron
2022-08-12 01:52:36 -05:00
:app.worker/worker))
2022-09-20 17:46:22 -05:00
_ (ig/load-namespaces system)
system (-> (ig/prep system)
(ig/init))]
(try
(binding [*system* system
*pool* (:app.db/pool system)]
2022-09-20 17:46:22 -05:00
(with-redefs [app.config/flags (flags/parse flags/default default-flags (:flags config))
app.config/config config
app.rpc.commands.auth/derive-password identity
app.rpc.commands.auth/verify-password (fn [a b] {:valid (= a b)})]
(next)))
(finally
(ig/halt! system)))))
(defn database-reset
[next]
(let [sql (str "SELECT table_name "
" FROM information_schema.tables "
" WHERE table_schema = 'public' "
" AND table_name != 'migrations';")]
(db/with-atomic [conn *pool*]
(let [result (->> (db/exec! conn [sql])
(map :table-name))]
(db/exec! conn [(str "TRUNCATE "
(apply str (interpose ", " result))
" CASCADE;")]))))
2021-01-30 05:31:51 -05:00
(next))
2021-01-31 11:02:10 -05:00
(defn clean-storage
[next]
2021-02-01 08:06:06 -05:00
(let [path (fs/path "/tmp/penpot")]
(when (fs/exists? path)
(fs/delete (fs/path "/tmp/penpot")))
(next)))
2021-01-31 11:02:10 -05:00
(defn serial
[& funcs]
(fn [next]
(loop [f (first funcs)
fs (rest funcs)]
(when f
(let [prm (promise)]
(f #(deliver prm true))
(deref prm)
(recur (first fs)
(rest fs)))))
(next)))
(defn mk-uuid
[prefix & args]
(UUID/nameUUIDFromBytes (-> (apply str prefix args)
(.getBytes "UTF-8"))))
;; --- FACTORIES
2021-01-31 11:02:10 -05:00
(defn create-profile*
([i] (create-profile* *pool* i {}))
([i params] (create-profile* *pool* i params))
([pool i params]
2021-01-31 11:02:10 -05:00
(let [params (merge {:id (mk-uuid "profile" i)
:fullname (str "Profile " i)
:email (str "profile" i ".test@nodomain.com")
:password "123123"
:is-demo false}
2021-01-31 11:02:10 -05:00
params)]
(with-open [conn (db/open pool)]
(->> params
(cmd.auth/create-profile conn)
(cmd.auth/create-profile-relations conn))))))
2021-01-31 11:02:10 -05:00
(defn create-project*
([i params] (create-project* *pool* i params))
([pool i {:keys [profile-id team-id] :as params}]
2021-01-31 11:02:10 -05:00
(us/assert uuid? profile-id)
(us/assert uuid? team-id)
(with-open [conn (db/open pool)]
(->> (merge {:id (mk-uuid "project" i)
:name (str "project" i)}
params)
(#'projects/create-project conn)))))
2021-01-31 11:02:10 -05:00
(defn create-file*
([i params]
(create-file* *pool* i params))
([pool i {:keys [profile-id project-id] :as params}]
2021-01-31 11:02:10 -05:00
(us/assert uuid? profile-id)
(us/assert uuid? project-id)
(with-open [conn (db/open pool)]
(files.create/create-file conn
(merge {:id (mk-uuid "file" i)
:name (str "file" i)
:components-v2 true}
params)))))
2021-01-31 11:02:10 -05:00
(defn mark-file-deleted*
([params] (mark-file-deleted* *pool* params))
([conn {:keys [id] :as params}]
(#'files/mark-file-deleted conn {:id id})))
2021-01-31 11:02:10 -05:00
(defn create-team*
([i params] (create-team* *pool* i params))
([pool i {:keys [profile-id] :as params}]
2021-01-31 11:02:10 -05:00
(us/assert uuid? profile-id)
(with-open [conn (db/open pool)]
(let [id (mk-uuid "team" i)]
(teams/create-team conn {:id id
:profile-id profile-id
:name (str "team" i)})))))
2021-01-31 11:02:10 -05:00
(defn create-file-media-object*
([params] (create-file-media-object* *pool* params))
([pool {:keys [name width height mtype file-id is-local media-id]
:or {name "sample" width 100 height 100 mtype "image/svg+xml" is-local true}}]
(with-open [conn (db/open pool)]
(db/insert! conn :file-media-object
{:id (uuid/next)
:file-id file-id
:is-local is-local
:name name
:media-id media-id
:width width
:height height
:mtype mtype}))))
(defn link-file-to-library*
([params] (link-file-to-library* *pool* params))
([pool {:keys [file-id library-id] :as params}]
(with-open [conn (db/open pool)]
(#'files/link-file-to-library conn {:file-id file-id :library-id library-id}))))
(defn create-complaint-for
[pool {:keys [id created-at type]}]
(with-open [conn (db/open pool)]
(db/insert! conn :profile-complaint-report
{:profile-id id
:created-at (or created-at (dt/now))
:type (name type)
:content (db/tjson {})})))
(defn create-global-complaint-for
[pool {:keys [email type created-at]}]
(with-open [conn (db/open pool)]
(db/insert! conn :global-complaint-report
{:email email
:type (name type)
:created-at (or created-at (dt/now))
:content (db/tjson {})})))
(defn create-team-role*
([params] (create-team-role* *pool* params))
([pool {:keys [team-id profile-id role] :or {role :owner}}]
(with-open [conn (db/open pool)]
(#'teams/create-team-role conn {:team-id team-id
:profile-id profile-id
:role role}))))
(defn create-project-role*
([params] (create-project-role* *pool* params))
([pool {:keys [project-id profile-id role] :or {role :owner}}]
(with-open [conn (db/open pool)]
(#'projects/create-project-role conn {:project-id project-id
:profile-id profile-id
:role role}))))
(defn create-file-role*
([params] (create-file-role* *pool* params))
([pool {:keys [file-id profile-id role] :or {role :owner}}]
(with-open [conn (db/open pool)]
(files.create/create-file-role! conn {:file-id file-id
:profile-id profile-id
:role role}))))
(defn update-file*
([params] (update-file* *pool* params))
([pool {:keys [file-id changes session-id profile-id revn]
:or {session-id (uuid/next) revn 0}}]
(with-open [conn (db/open pool)]
(let [msgbus (:app.msgbus/msgbus *system*)
metrics (:app.metrics/metrics *system*)
features #{"components/v2"}]
(files.update/update-file {:conn conn
:msgbus msgbus
:metrics metrics}
{:id file-id
:revn revn
:features features
:changes changes
:session-id session-id
:profile-id profile-id})))))
;; --- RPC HELPERS
2021-01-31 11:02:10 -05:00
(defn handle-error
[^Throwable err]
(if (instance? java.util.concurrent.ExecutionException err)
(handle-error (.getCause err))
err))
(defmacro try-on!
[expr]
`(try
(let [result# (deref ~expr)
2022-11-07 10:56:02 -05:00
result# (cond-> result# (rph/wrapped? result#) deref)]
{:error nil
:result result#})
(catch Exception e#
{:error (handle-error e#)
:result nil})))
2022-06-30 08:11:41 -05:00
(defn command!
[{:keys [::type] :as data}]
(let [method-fn (get-in *system* [:app.rpc/methods :commands type])]
;; (app.common.pprint/pprint (:app.rpc/methods *system*))
(try-on! (method-fn (dissoc data ::type)))))
(defn mutation!
[{:keys [::type] :as data}]
2022-06-30 08:11:41 -05:00
(let [method-fn (get-in *system* [:app.rpc/methods :mutations type])]
(try-on! (method-fn (dissoc data ::type)))))
(defn query!
[{:keys [::type] :as data}]
2022-06-30 08:11:41 -05:00
(let [method-fn (get-in *system* [:app.rpc/methods :queries type])]
(try-on! (method-fn (dissoc data ::type)))))
(defn run-task!
([name]
(run-task! name {}))
([name params]
(let [tasks (:app.worker/registry *system*)]
(let [task-fn (get tasks (d/name name))]
(task-fn params)))))
;; --- UTILS
(defn print-error!
[error]
(let [data (ex-data error)]
(cond
(= :spec-validation (:code data))
(println
(us/pretty-explain data))
(= :service-error (:type data))
(print-error! (.getCause ^Throwable error))
:else
(.printStackTrace ^Throwable error))))
(defn print-result!
[{:keys [error result]}]
(if error
(do
(println "====> START ERROR")
(print-error! error)
(println "====> END ERROR"))
(do
(println "====> START RESPONSE")
(pp/pprint result)
(println "====> END RESPONSE"))))
(defn exception?
[v]
(instance? Throwable v))
(defn ex-info?
[v]
(instance? clojure.lang.ExceptionInfo v))
(defn ex-type
[e]
(:type (ex-data e)))
(defn ex-code
[e]
(:code (ex-data e)))
(defn ex-of-type?
[e type]
(let [data (ex-data e)]
(= type (:type data))))
(defn ex-of-code?
[e code]
(let [data (ex-data e)]
(= code (:code data))))
(defn ex-with-code?
[e code]
(let [data (ex-data e)]
(= code (:code data))))
(defn success?
[{:keys [result error]}]
(nil? error))
(defn tempfile
[source]
(let [rsc (io/resource source)
tmp (fs/create-tempfile)]
(io/copy (io/file rsc)
(io/file tmp))
tmp))
2021-01-31 11:02:10 -05:00
2021-11-03 07:10:49 -05:00
(defn pause
[]
(let [^java.io.Console cnsl (System/console)]
(println "[waiting RETURN]")
(.readLine cnsl)
nil))
(defn db-exec!
[sql]
(db/exec! *pool* sql))
(defn db-insert!
[& params]
(apply db/insert! *pool* params))
(defn db-query
[& params]
(apply db/query *pool* params))
(defn sleep
[ms-or-duration]
(Thread/sleep (inst-ms (dt/duration ms-or-duration))))
(defn config-get-mock
[data]
(fn
([key]
(get data key (get cf/config key)))
([key default]
(get data key (get cf/config key default)))))
(defn reset-mock!
[m]
2022-11-30 09:38:48 -05:00
(swap! m (fn [m]
(-> m
(assoc :called? false)
(assoc :call-count 0)
(assoc :return-list [])
(assoc :call-args nil)
(assoc :call-args-list [])))))