;; 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]]})))