mirror of
https://github.com/penpot/penpot.git
synced 2026-10-31 06:50:33 +00:00
Use the same explicit group for inverse sync and every copy sync. Text reflow can finish after the update transaction closes; one undo must still restore the main, its copies and the source overrides together (F152). The five-operation text regression fails before this change. All 12 frontend generated replays pass: 865 assertions. Common and frontend lint and format pass. Shared benchmark ratios: mains 0.47/0.53/0.55; levels 0.51; chain 0.64; library 0.64; many shapes 0.96; switch 0.68, no flags. AI-assisted-by: GPT-6
97 lines
4.5 KiB
Clojure
97 lines
4.5 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 frontend-tests.composable-tests.generated-test
|
|
(:require
|
|
[app.common.test-helpers.composable.comp.undo-check :as uc]
|
|
[app.common.test-helpers.composable.core :as tm]
|
|
[app.common.test-helpers.composable.gen :as cg]
|
|
[app.common.test-helpers.composable.oracle :as oracle]
|
|
[app.common.test-helpers.normalize :as thn]
|
|
[cljs.test :as t :include-macros true]
|
|
[clojure.test.check.generators :as gen]
|
|
[frontend-tests.composable-tests.interpreter :as ftm]))
|
|
|
|
(t/use-fixtures :each ftm/fixture)
|
|
|
|
(defn- live-model
|
|
[state live]
|
|
(let [by-path (into {} (map (juxt :path (comp :id :shape))) (cg/tree live))]
|
|
(into {}
|
|
(keep (fn [{:keys [path shape]}]
|
|
(when-let [groups (get (:model state) (:id shape))]
|
|
(when-let [id (get by-path path)] [id groups]))))
|
|
(cg/tree (:situation state)))))
|
|
|
|
(defn ^:async replay
|
|
"Replay a JVM-shrunk EDN program against the async frontend. The pure
|
|
runner chooses targets independently and both must make the same choices."
|
|
[{:keys [world ops] :as program}]
|
|
(try
|
|
(let [initial (cg/initial-state world)]
|
|
(loop [state initial
|
|
live (ftm/start-generated (:situation initial))
|
|
tuples ops]
|
|
(if-let [tuple (first tuples)]
|
|
(let [state (cg/settle-state state)
|
|
pure (:situation state)
|
|
live (tm/with-file live (ftm/current-file))
|
|
expected (cg/resolve-op pure (:model state) tuple)
|
|
actual (if (#{:undo :redo} (first tuple))
|
|
expected
|
|
(cg/resolve-op live (live-model state live) tuple))]
|
|
(t/is (= (:trace expected) (:trace actual)) (str "Replay changed a target: " tuple))
|
|
(let [next-live (if-let [op (:op actual)]
|
|
(await (ftm/run-generated-step live op))
|
|
(do
|
|
(t/is (= :settled (await (ftm/await-step []))))
|
|
(tm/with-file live (ftm/current-file))))
|
|
next-state (-> state (cg/step tuple) (cg/settle-state))]
|
|
(when-not next-live
|
|
(throw (ex-info "Frontend step failed" {:program program :tuple tuple})))
|
|
(try
|
|
(oracle/check next-live (live-model next-state next-live))
|
|
(catch :default error
|
|
(throw (ex-info (str "Frontend oracle at " tuple ": " (ex-message error))
|
|
(ex-data error) error))))
|
|
(let [expected (oracle/canonical (:situation next-state))
|
|
actual (oracle/canonical next-live)]
|
|
(t/is (true? (= expected actual))
|
|
(str "Backend mismatch at " tuple "; replay " (pr-str program)
|
|
"; diff " (pr-str (thn/diff expected actual)))))
|
|
(t/is (empty? (uc/failures next-live)) (pr-str (uc/failures next-live)))
|
|
(recur next-state next-live (rest tuples))))
|
|
(let [checked (await (ftm/finish-generated live))]
|
|
(t/is (empty? (uc/failures checked)) (pr-str (uc/failures checked)))
|
|
(ftm/uninstall!)))))
|
|
(catch :default error
|
|
(ftm/uninstall!)
|
|
(t/is false (str (ex-message error) "\nReplay: " (pr-str program)
|
|
"\nDetails: " (pr-str (ex-data error)))))))
|
|
|
|
(t/deftest ^:async seeded-programs-replay-through-the-frontend
|
|
(doseq [seed [712 20261022 1792691]]
|
|
(await (replay (gen/generate cg/program-gen 20 seed)))))
|
|
|
|
(t/deftest ^:async detach-undo-shrunk-regression
|
|
(await (replay {:world [2 0] :ops [[:edit 0 0 1 1] [:detach 0] [:undo] [:redo]]})))
|
|
|
|
(t/deftest ^:async structure-programs-replay-through-the-frontend
|
|
(doseq [seed [712 20261022]]
|
|
(await (replay (gen/generate cg/structure-program-gen 10 seed)))))
|
|
|
|
(t/deftest ^:async nested-text-rotation-shrunk-regression
|
|
(await (replay {:world [2 0 {:text true}]
|
|
:ops [[:nest 0] [:detach 0] [:rotate 0]]})))
|
|
|
|
(t/deftest ^:async nesting-restores-default-constraints-on-undo
|
|
(await (replay {:world [2 0] :ops [[:nest 0]]})))
|
|
|
|
(t/deftest ^:async update-main-after-nesting-a-rotated-text-copy-undoes-together
|
|
(await (replay {:world [2 0 {:text true}]
|
|
:ops [[:duplicate 0] [:nest 0] [:rotate 0 0 0]
|
|
[:edit 0 0 1 1] [:update-main 0]]})))
|