mirror of
https://github.com/penpot/penpot.git
synced 2026-11-01 23:50:38 +00:00
Several actions built their changes in frontend events, step by step, each step its own commit, so the pure runner could not run them and one undo could revert half an action. - Renaming a variant member in the layers panel sent three events, each in its own undo transaction: update the properties from the typed formula, remove the properties no member gives a value, and set or clear the member's error. One undo reverted only the last. clvp/generate-rename-member builds the three steps in one changes (with generate-update-properties and generate-remove-empty-properties), and dwv/rename-member commits it once with the same analytics events. update-properties-names-and-values goes; remove-empty-properties and update-error stay for the design tab. - Transforming a component into a variant sent about fourteen events, and combining components as variants that transform and eight more. clv/generate-transform-in-variant and clv/generate-combine-as-variants build those steps as one changes, from the generators common already had, and the events commit them once. The flex layout initializer moves to common as cls/layout-initializer. Combine still sizes the board with two frontend dimension updates inside its undo transaction: the frontend applies them through modifiers, which common has no step for. - update-component split the changes of an update main (the copy's, marked :local-change?, from the main's, which may belong to a library) with two transducers; cll/split-local-changes does it. Its undo-group argument, never passed, goes, and the main's library is the copy head's :component-file, which it looked up through the file data only to read its id back. - dwv/valid-variant-switch? read the libraries from the state and repeated the lookup of clv/find-switch-target. clv/valid-switch? takes the libraries and asks find-switch-target; the plugin's switchVariant and the frontend test call it. Behavior changes: - One undo after a rename of a member, a transform or a combine reverts all of it. After a transform, it reverted only the sync of the copies' names (F6 in case AT); its pins go. - The transform no longer sends the "create-board" analytics event of the board it creates around the main. In the composable suites, renaming a member in the layers panel, removing the empty properties and setting a member's error are variant property edits both runners run, and case AW joins the JVM set. Its rename node drives the real layers-panel rename, which removes the empty properties too, so the step that removed them goes. The golden masters are recorded again for AW (the JVM one gains the case, the frontend one loses that step) and for AT (its final states no longer list the F6 undo failures). AI-assisted-by: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
166 lines
6.8 KiB
Clojure
166 lines
6.8 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 common-tests.logic.composable-sync-test
|
|
"Runs the shared composable component cases through the pure runner, on the
|
|
JVM and in JS. Only the frontend interpreter runs the geometry cases (N, Z,
|
|
AI and the rotation case), whose modifiers come from frontend events, case X,
|
|
which needs a pending frontend sync, case AJ, which needs the frontend
|
|
reflow, and cases AT..AX, whose variant actions are frontend events."
|
|
(:require
|
|
[app.common.test-helpers.composable.comp.cases :as cases]
|
|
[app.common.test-helpers.composable.comp.runner :as r]
|
|
[app.common.test-helpers.composable.comp.undo-check :as uc]
|
|
[app.common.test-helpers.composable.core :as tm]
|
|
[app.common.test-helpers.ids-map :as thi]
|
|
[clojure.test :as t]))
|
|
|
|
(t/use-fixtures :each thi/test-fixture)
|
|
|
|
(defn- check
|
|
"Run every variant of `case-map`, apply its asserter to each result before
|
|
the next variant runs and assert that its undo/redo round trip passed. A
|
|
variant whose inline tests and asserter make no assertion fails, and so
|
|
does a known undo failure that applies to no variant."
|
|
[{:keys [asserter] :as case-map}]
|
|
(let [applied (atom #{})]
|
|
(tm/counting-assertions
|
|
(fn [made]
|
|
(r/run-each case-map
|
|
(fn [situation]
|
|
(t/testing (str "operations:\n " (tm/describe-applied situation))
|
|
(when asserter
|
|
(asserter situation))
|
|
(let [n @made]
|
|
(t/is (pos? n) "the variant made no assertion"))
|
|
(uc/check! situation case-map)
|
|
(swap! applied into (uc/applying-marks situation case-map))
|
|
(reset! made 0))))))
|
|
(uc/check-marks-applied! case-map :pure @applied)))
|
|
|
|
(t/deftest case-b-copy-override-survives-later-main-change
|
|
(check (cases/copy-override-survives-later-main-change)))
|
|
|
|
(t/deftest case-c-attribute-sweep-propagates-to-clean-copy
|
|
(check (cases/attribute-sweep-propagates-to-clean-copy)))
|
|
|
|
(t/deftest case-d-add-shape-to-main-propagates-to-clean-copy
|
|
(check (cases/add-shape-to-main-propagates-to-clean-copy)))
|
|
|
|
(t/deftest case-e-remove-shape-from-main-propagates-to-clean-copy
|
|
(check (cases/remove-shape-from-main-propagates-to-clean-copy)))
|
|
|
|
(t/deftest case-f-move-shape-in-main-propagates-order-to-clean-copy
|
|
(check (cases/move-shape-in-main-propagates-order-to-clean-copy)))
|
|
|
|
(t/deftest case-h-library-change-propagates-across-file-boundary-on-sync
|
|
(check (cases/library-change-propagates-across-file-boundary-on-sync)))
|
|
|
|
(t/deftest case-i-undo-reverts-edit-and-its-propagation
|
|
(check (cases/undo-reverts-edit-and-its-propagation)))
|
|
|
|
(t/deftest case-p-redo-reapplies-edit-and-its-propagation
|
|
(check (cases/redo-reapplies-edit-and-its-propagation)))
|
|
|
|
(t/deftest case-k-synchronisation-scenarios
|
|
(check (cases/synchronisation-scenarios)))
|
|
|
|
(t/deftest case-l-swap-scenarios
|
|
(check (cases/swap-scenarios)))
|
|
|
|
(t/deftest case-m-variant-switch-scenarios
|
|
(check (cases/variant-switch-scenarios)))
|
|
|
|
(t/deftest case-o-variant-switch-keeps-override-only-where-mains-agree
|
|
(check (cases/variant-switch-keeps-override-only-where-mains-agree)))
|
|
|
|
(t/deftest case-q-detach-keeps-nested-copies-linked
|
|
(check (cases/detach-keeps-nested-copies-linked)))
|
|
|
|
(t/deftest case-r-update-main-reaches-other-copies
|
|
(check (cases/update-main-reaches-other-copies)))
|
|
|
|
(t/deftest case-s-deleted-component-copies-sync-again-after-restore
|
|
(check (cases/deleted-component-copies-sync-again-after-restore)))
|
|
|
|
(t/deftest case-t-duplicated-copy-keeps-overrides-and-link
|
|
(check (cases/duplicated-copy-keeps-overrides-and-link)))
|
|
|
|
(t/deftest case-u-nested-copy-reaches-copies-of-the-receiving-main
|
|
(check (cases/nested-copy-reaches-copies-of-the-receiving-main)))
|
|
|
|
(t/deftest case-v-new-edit-after-undo-clears-redo
|
|
(check (cases/new-edit-after-undo-clears-redo)))
|
|
|
|
(t/deftest case-w-undo-several-steps-over-nested-cascades
|
|
(check (cases/undo-several-steps-over-nested-cascades)))
|
|
|
|
(t/deftest case-y-text-override-merges-with-main-text-change
|
|
(check (cases/text-override-merges-with-main-text-change)))
|
|
|
|
(t/deftest case-ba-text-style-override-against-main-style-change
|
|
(check (cases/text-style-override-against-main-style-change)))
|
|
|
|
(t/deftest case-aa-copy-swap-survives-main-changes
|
|
(check (cases/copy-swap-survives-main-changes)))
|
|
|
|
(t/deftest case-ab-reset-of-nested-swap-keeps-top-copy-overrides
|
|
(check (cases/reset-of-nested-swap-keeps-top-copy-overrides)))
|
|
|
|
(t/deftest case-ac-second-variant-switch-keeps-root-overrides
|
|
(check (cases/second-variant-switch-keeps-root-overrides)))
|
|
|
|
(t/deftest case-ad-update-main-pushes-a-swapped-child
|
|
(check (cases/update-main-pushes-a-swapped-child)))
|
|
|
|
(t/deftest case-ae-detached-or-duplicated-swapped-copy-follows-its-component
|
|
(check (cases/detached-or-duplicated-swapped-copy-follows-its-component)))
|
|
|
|
(t/deftest case-af-grid-cell-move-reaches-a-swapped-copy-child
|
|
(check (cases/grid-cell-move-reaches-a-swapped-copy-child)))
|
|
|
|
(t/deftest case-ag-main-reorder-keeps-copy-sub-heads-aligned
|
|
(check (cases/main-reorder-keeps-copy-sub-heads-aligned)))
|
|
|
|
(t/deftest case-ah-copy-sub-head-delete-keeps-others-aligned
|
|
(check (cases/copy-sub-head-delete-keeps-others-aligned)))
|
|
|
|
(t/deftest case-ak-update-main-pushes-grid-cells
|
|
(check (cases/update-main-pushes-grid-cells)))
|
|
|
|
(t/deftest case-al-update-main-renames-the-component
|
|
(check (cases/update-main-renames-the-component)))
|
|
|
|
(t/deftest case-am-update-main-pushes-a-swap-inside-a-group
|
|
(check (cases/update-main-pushes-a-swap-inside-a-group)))
|
|
|
|
(t/deftest case-an-flex-child-override-follows-sync-reset-and-update-main
|
|
(check (cases/flex-child-override-follows-sync-reset-and-update-main)))
|
|
|
|
(t/deftest case-ao-copy-dropped-into-a-grid-cell-reaches-copies
|
|
(check (cases/copy-dropped-into-a-grid-cell-reaches-copies)))
|
|
|
|
(t/deftest case-ap-library-main-child-removal-reaches-copy
|
|
(check (cases/library-main-child-removal-reaches-copy)))
|
|
|
|
(t/deftest case-aq-main-change-reaches-a-copy-nested-in-a-sub-board
|
|
(check (cases/main-change-reaches-a-copy-nested-in-a-sub-board)))
|
|
|
|
(t/deftest case-ar-variant-property-edits-keep-copies
|
|
(check (cases/variant-property-edits-keep-copies)))
|
|
|
|
(t/deftest case-as-added-variant-is-a-switch-target
|
|
(check (cases/added-variant-is-a-switch-target)))
|
|
|
|
(t/deftest case-aw-variant-layer-rename-and-cleanup
|
|
(check (cases/variant-layer-rename-and-cleanup)))
|
|
|
|
(t/deftest case-ay-token-on-a-main-reaches-copies
|
|
(check (cases/token-on-a-main-reaches-copies)))
|
|
|
|
(t/deftest case-az-copy-moved-out-of-its-main-keeps-inherited-overrides
|
|
(check (cases/copy-moved-out-of-its-main-keeps-inherited-overrides)))
|