The boxes wrote nothing until blur, so a spinner click showed nothing on screen. Now every keystroke and step is an edit, and history holds the step open from focus to blur, so typing 4 then 5 is seen as 4, then 45, and undone once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
74 lines
3.3 KiB
Clojure
74 lines
3.3 KiB
Clojure
(ns arthur.domain.history-test
|
|
(:require [cljs.test :refer [deftest is testing]]
|
|
[arthur.domain.history :as history]))
|
|
|
|
(def empty-doc {"t" 1})
|
|
|
|
(deftest undo-and-redo-walk-your-own-steps
|
|
(let [made (assoc empty-doc "b" :shape)
|
|
moved (assoc made "b" :moved)
|
|
h (-> nil
|
|
(history/record empty-doc made 0)
|
|
(history/record made moved 5000))
|
|
one (history/undo h moved)
|
|
two (history/undo (:history one) (:leaves one))]
|
|
(is (= made (:leaves one)))
|
|
(is (= empty-doc (:leaves two)))
|
|
(is (nil? (history/undo (:history two) (:leaves two))))
|
|
(is (= made (:leaves (history/redo (:history two) (:leaves two)))))))
|
|
|
|
(deftest a-drag-is-one-step
|
|
(let [h (reduce (fn [h [x t]] (history/record h {"v" (dec x)} {"v" x} t))
|
|
nil [[1 0] [2 100] [3 200]])]
|
|
(is (= 1 (count (:done h))))
|
|
(is (= {"v" 0} (:leaves (history/undo h {"v" 3}))))))
|
|
|
|
(deftest typing-into-a-field-is-one-step-however-slow
|
|
(let [h (-> nil
|
|
(history/record {"w" 1} {"w" 2} 0)
|
|
history/hold
|
|
(history/record {"w" 2} {"w" 4} 100)
|
|
(history/record {"w" 4} {"w" 45} 9000)
|
|
history/settle
|
|
(history/record {"w" 45} {"w" 46} 9100))]
|
|
(is (= 3 (count (:done h))) "the edit before focus and the one after blur stand apart")
|
|
(is (= {"w" 2} (:leaves (history/undo (:history (history/undo h {"w" 46})) {"w" 45}))))))
|
|
|
|
(deftest their-write-between-two-of-mine-keeps-them-apart
|
|
(let [h (-> nil
|
|
(history/record {"fps" 30} {"fps" 12} 0)
|
|
;; theirs lands: 12 -> 9, not recorded
|
|
(history/record {"fps" 9} {"fps" 15} 300))]
|
|
(is (= 2 (count (:done h))))
|
|
(is (= {"fps" 9} (:leaves (history/undo h {"fps" 15}))))))
|
|
|
|
(deftest undo-never-takes-somebody-elses-work
|
|
(testing "I make b; they edit it; I edit it; I undo twice"
|
|
(let [made {"b" :shape}
|
|
theirs {"b" :their-edit}
|
|
mine {"b" :my-edit}
|
|
h (-> nil
|
|
(history/record {} made 0)
|
|
;; their edit arrives as a remote write: not recorded
|
|
(history/record theirs mine 5000))
|
|
one (history/undo h mine)
|
|
two (history/undo (:history one) (:leaves one))]
|
|
(is (= theirs (:leaves one)) "my edit comes off, theirs is what is left")
|
|
(is (:blocked two) "removing b would remove their edit, so it is refused")
|
|
(is (empty? (:done (:history two))) "and the refused step is dropped"))))
|
|
|
|
(deftest a-new-edit-clears-redo
|
|
(let [h (history/record nil {} {"a" 1} 0)
|
|
u (history/undo h {"a" 1})
|
|
h (history/record (:history u) (:leaves u) {"c" 1} 9000)]
|
|
(is (nil? (history/redo h {"c" 1})))))
|
|
|
|
(deftest a-step-says-what-it-was
|
|
(let [node "clip/u/symbol/main/node/b"
|
|
pts "clip/u/symbol/main/channel/b/geom.pts"
|
|
made {node {:id :b :name "shape 3"} pts :p}]
|
|
(is (= "add shape 3" (history/label {} made [node pts])))
|
|
(is (= "edit shape 3" (history/label made (assoc made pts :q) [pts])))
|
|
(is (= "delete shape 3" (history/label made {} [node pts])))
|
|
(is (= "project settings" (history/label {} {"clip/u/timing" {:fps 9}} ["clip/u/timing"])))
|
|
(is (= ["add shape 3"] (:done (history/steps (history/record nil {} made 0)))))))
|