mirror of
https://github.com/penpot/penpot.git
synced 2026-04-01 09:00:51 +02:00
193 lines
6.7 KiB
Clojure
193 lines
6.7 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 INC
|
|
|
|
(ns frontend-tests.helpers.wasm
|
|
"Test helpers for mocking WASM API boundary functions.
|
|
|
|
In the Node.js test environment the WASM binary is not available,
|
|
but the `render-wasm/v1` feature flag is enabled by default, so
|
|
every geometry-modifying event takes the WASM code path.
|
|
This namespace provides lightweight mock implementations that let
|
|
the Clojure-side logic execute normally while stubbing out every
|
|
call that would touch the WASM heap.
|
|
|
|
Each mock tracks how many times it was called via `call-counts`.
|
|
Use `(call-count :propagate-modifiers)` in test assertions to
|
|
verify the WASM code path was exercised."
|
|
(:require
|
|
[app.common.data :as d]
|
|
[app.render-wasm.api :as wasm.api]
|
|
[app.render-wasm.api.fonts :as wasm.fonts]))
|
|
|
|
;; --- Call tracking ---------------------------------------------------
|
|
|
|
(def ^:private call-counts
|
|
"Atom holding a map of mock-name → number of calls since last reset."
|
|
(atom {}))
|
|
|
|
(defn- track!
|
|
"Increment the call count for `mock-name`."
|
|
[mock-name]
|
|
(swap! call-counts update mock-name (fnil inc 0)))
|
|
|
|
(defn call-count
|
|
"Return how many times mock `mock-name` was called since setup.
|
|
`mock-name` is a keyword, e.g. `:propagate-modifiers`."
|
|
[mock-name]
|
|
(get @call-counts mock-name 0))
|
|
|
|
(defn reset-call-counts!
|
|
"Reset all call counts to zero."
|
|
[]
|
|
(reset! call-counts {}))
|
|
|
|
;; --- Mock implementations --------------------------------------------
|
|
|
|
(defn- mock-propagate-modifiers
|
|
"Passthrough mock for `wasm.api/propagate-modifiers`.
|
|
|
|
Receives `entries` — a vector of `[uuid {:transform matrix, :kind kw}]`
|
|
pairs produced by `parse-geometry-modifiers` — and returns a vector
|
|
of `[uuid matrix]` pairs that `apply-wasm-modifiers` converts to a
|
|
transforms map via `(into {} result)`.
|
|
|
|
This effectively tells the caller \"apply exactly the transform that
|
|
was requested\", which is what the real WASM engine does for simple
|
|
moves / resizes without constraints."
|
|
[entries _pixel-precision]
|
|
(track! :propagate-modifiers)
|
|
(when (d/not-empty? entries)
|
|
(into []
|
|
(map (fn [[id data]]
|
|
(d/vec2 id (:transform data))))
|
|
entries)))
|
|
|
|
(defn- mock-clean-modifiers
|
|
[]
|
|
(track! :clean-modifiers)
|
|
nil)
|
|
|
|
(defn- mock-set-structure-modifiers
|
|
[_entries]
|
|
(track! :set-structure-modifiers)
|
|
nil)
|
|
|
|
(defn- mock-set-shape-grow-type
|
|
[_grow-type]
|
|
(track! :set-shape-grow-type)
|
|
nil)
|
|
|
|
(defn- mock-set-shape-text-content
|
|
[_shape-id _content]
|
|
(track! :set-shape-text-content)
|
|
nil)
|
|
|
|
(defn- mock-set-shape-text-images
|
|
([_shape-id _content]
|
|
(track! :set-shape-text-images)
|
|
nil)
|
|
([_shape-id _content _thumbnail?]
|
|
(track! :set-shape-text-images)
|
|
nil))
|
|
|
|
(defn- mock-get-text-dimensions
|
|
([]
|
|
(track! :get-text-dimensions)
|
|
{:x 0 :y 0 :width 100 :height 20 :max-width 100})
|
|
([_id]
|
|
(track! :get-text-dimensions)
|
|
{:x 0 :y 0 :width 100 :height 20 :max-width 100}))
|
|
|
|
(defn- mock-font-stored?
|
|
[_font-data _emoji?]
|
|
(track! :font-stored?)
|
|
true)
|
|
|
|
(defn- mock-make-font-data
|
|
[font]
|
|
(track! :make-font-data)
|
|
{:wasm-id 0
|
|
:weight (or (:font-weight font) "400")
|
|
:style (or (:font-style font) "normal")
|
|
:emoji? false})
|
|
|
|
(defn- mock-get-content-fonts
|
|
[_content]
|
|
(track! :get-content-fonts)
|
|
[])
|
|
|
|
;; --- Persistent mock installation via `set!` --------------------------
|
|
;;
|
|
;; These use `set!` to directly mutate the module-level JS vars, making
|
|
;; the mocks persist across async boundaries. They are intended to be
|
|
;; used with `t/use-fixtures :each` which correctly sequences `:after`
|
|
;; to run only after the async test's `done` callback fires.
|
|
|
|
(def ^:private originals
|
|
"Stores the original WASM function values so they can be restored."
|
|
(atom {}))
|
|
|
|
(defn setup-wasm-mocks!
|
|
"Install WASM mocks via `set!` that persist across async boundaries.
|
|
Also resets call counts. Call `teardown-wasm-mocks!` to restore."
|
|
[]
|
|
;; Reset call tracking
|
|
(reset-call-counts!)
|
|
;; Save originals
|
|
(reset! originals
|
|
{:clean-modifiers wasm.api/clean-modifiers
|
|
:set-structure-modifiers wasm.api/set-structure-modifiers
|
|
:propagate-modifiers wasm.api/propagate-modifiers
|
|
:set-shape-grow-type wasm.api/set-shape-grow-type
|
|
:set-shape-text-content wasm.api/set-shape-text-content
|
|
:set-shape-text-images wasm.api/set-shape-text-images
|
|
:get-text-dimensions wasm.api/get-text-dimensions
|
|
:font-stored? wasm.fonts/font-stored?
|
|
:make-font-data wasm.fonts/make-font-data
|
|
:get-content-fonts wasm.fonts/get-content-fonts})
|
|
;; Install mocks
|
|
(set! wasm.api/clean-modifiers mock-clean-modifiers)
|
|
(set! wasm.api/set-structure-modifiers mock-set-structure-modifiers)
|
|
(set! wasm.api/propagate-modifiers mock-propagate-modifiers)
|
|
(set! wasm.api/set-shape-grow-type mock-set-shape-grow-type)
|
|
(set! wasm.api/set-shape-text-content mock-set-shape-text-content)
|
|
(set! wasm.api/set-shape-text-images mock-set-shape-text-images)
|
|
(set! wasm.api/get-text-dimensions mock-get-text-dimensions)
|
|
(set! wasm.fonts/font-stored? mock-font-stored?)
|
|
(set! wasm.fonts/make-font-data mock-make-font-data)
|
|
(set! wasm.fonts/get-content-fonts mock-get-content-fonts))
|
|
|
|
(defn teardown-wasm-mocks!
|
|
"Restore the original WASM functions saved by `setup-wasm-mocks!`."
|
|
[]
|
|
(let [orig @originals]
|
|
(set! wasm.api/clean-modifiers (:clean-modifiers orig))
|
|
(set! wasm.api/set-structure-modifiers (:set-structure-modifiers orig))
|
|
(set! wasm.api/propagate-modifiers (:propagate-modifiers orig))
|
|
(set! wasm.api/set-shape-grow-type (:set-shape-grow-type orig))
|
|
(set! wasm.api/set-shape-text-content (:set-shape-text-content orig))
|
|
(set! wasm.api/set-shape-text-images (:set-shape-text-images orig))
|
|
(set! wasm.api/get-text-dimensions (:get-text-dimensions orig))
|
|
(set! wasm.fonts/font-stored? (:font-stored? orig))
|
|
(set! wasm.fonts/make-font-data (:make-font-data orig))
|
|
(set! wasm.fonts/get-content-fonts (:get-content-fonts orig)))
|
|
(reset! originals {}))
|
|
|
|
(defn with-wasm-mocks*
|
|
"Calls `(thunk)` with all WASM API boundary functions replaced by
|
|
safe mocks, restoring the originals when the thunk returns.
|
|
|
|
NOTE: Teardown happens synchronously when `thunk` returns. For
|
|
async tests (e.g. those using `tohs/run-store-async`), use
|
|
`setup-wasm-mocks!` / `teardown-wasm-mocks!` via
|
|
`t/use-fixtures :each` instead."
|
|
[thunk]
|
|
(setup-wasm-mocks!)
|
|
(try
|
|
(thunk)
|
|
(finally
|
|
(teardown-wasm-mocks!))))
|