From 9bb5861322bc03c2bb87ab8e8f99820af65085f8 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 31 Jul 2026 13:09:18 +0200 Subject: [PATCH] :bug: Fix undo delete pages change order (#10969) --- .../src/app/main/data/workspace/pages.cljs | 2 +- .../data/workspace_pages_test.cljs | 129 ++++++++++++++++++ frontend/test/frontend_tests/runner.cljs | 2 + 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 frontend/test/frontend_tests/data/workspace_pages_test.cljs diff --git a/frontend/src/app/main/data/workspace/pages.cljs b/frontend/src/app/main/data/workspace/pages.cljs index 0bfa559469..260ebef9e1 100644 --- a/frontend/src/app/main/data/workspace/pages.cljs +++ b/frontend/src/app/main/data/workspace/pages.cljs @@ -489,7 +489,7 @@ (pcb/del-page page)))) (-> (pcb/empty-changes it) (pcb/with-library-data fdata)) - del-ids)] + (reverse del-ids))] (if (empty? del-ids) (rx/empty) diff --git a/frontend/test/frontend_tests/data/workspace_pages_test.cljs b/frontend/test/frontend_tests/data/workspace_pages_test.cljs new file mode 100644 index 0000000000..f5d2d9d2eb --- /dev/null +++ b/frontend/test/frontend_tests/data/workspace_pages_test.cljs @@ -0,0 +1,129 @@ +;; 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 Sucursal en EspaƱa SL + +(ns frontend-tests.data.workspace-pages-test + (:require + [app.common.data :as d] + [app.common.files.changes-builder :as pcb] + [app.common.test-helpers.files :as cthf] + [app.common.test-helpers.ids-map :as cthi] + [app.main.data.workspace.pages :as dwpg] + [cljs.test :as t :include-macros true] + [frontend-tests.helpers.state :as ths])) + +(t/use-fixtures :each + {:before cthi/reset-idmap!}) + +(defn- pages + [state] + (let [file-id (:current-file-id state)] + (get-in state [:files file-id :data :pages]))) + +(defn- make-five-pages + [] + (-> (cthf/sample-file :file1 :page-label :page1) + (cthf/add-sample-page :page2) + (cthf/add-sample-page :page3) + (cthf/add-sample-page :page4) + (cthf/add-sample-page :page5) + (cthf/switch-to-page :page1))) + +;; --------------------------------------------------------------------------- +;; Verify the order of undo changes so that when pages are restored they +;; appear in the original page order (not reversed). +;; --------------------------------------------------------------------------- + +(defn- add-page-ids-from-undo-changes + "Extract the sequence of page ids from the `:add-page` undo changes list." + [changes] + (->> (:undo-changes changes) + (keep (fn [change] + (when (= :add-page (:type change)) + (:id change)))))) + +(t/deftest delete-pages-undo-changes-are-in-page-order + (let [file (make-five-pages) + fdata (:data file) + pindex (:pages-index fdata) + pages (:pages fdata) + page2-id (cthi/id :page2) + page4-id (cthi/id :page4) + del-ids (filter #{page2-id page4-id} pages) + + ;; Simulate the reduction from delete-pages but in REVERSE order + ;; (the fix iterates (reverse del-ids) so undo changes are in correct order) + changes (reduce + (fn [changes id] + (let [page (-> (get pindex id) + (assoc :index (d/index-of pages id)))] + (pcb/del-page changes page))) + (pcb/empty-changes) + del-ids) + + undo-before-fix (add-page-ids-from-undo-changes changes) + + changes-fixed (reduce + (fn [changes id] + (let [page (-> (get pindex id) + (assoc :index (d/index-of pages id)))] + (pcb/del-page changes page))) + (pcb/empty-changes) + (reverse del-ids)) + + undo-after-fix (add-page-ids-from-undo-changes changes-fixed)] + + (t/is (= [page4-id page2-id] undo-before-fix) + "before fix: undo changes are reversed (page order)") + (t/is (= [page2-id page4-id] undo-after-fix) + "after fix: undo changes are in correct page order"))) + +;; --------------------------------------------------------------------------- +;; delete-pages removes the correct pages and keeps remaining pages in order +;; --------------------------------------------------------------------------- + +(t/deftest delete-pages-removes-pages-and-keeps-remaining-in-order + (t/async + done + (let [file (make-five-pages) + page2-id (cthi/id :page2) + page4-id (cthi/id :page4) + store (ths/setup-store file) + events [(dwpg/delete-pages [page2-id page4-id])]] + + (ths/run-store + store done events + (fn [state] + (let [pgs (pages state)] + (t/is (= 3 (count pgs)) + "3 pages remain after deleting 2") + (t/is (= [(cthi/id :page1) (cthi/id :page3) (cthi/id :page5)] + pgs) + "remaining pages stay in the original order"))))))) + +;; --------------------------------------------------------------------------- +;; delete-pages keeps at least one page in the file +;; --------------------------------------------------------------------------- + +(t/deftest delete-pages-keeps-at-least-one-page + (t/async + done + (let [file (make-five-pages) + page1-id (cthi/id :page1) + page2-id (cthi/id :page2) + page3-id (cthi/id :page3) + page4-id (cthi/id :page4) + page5-id (cthi/id :page5) + store (ths/setup-store file) + events [(dwpg/delete-pages [page1-id page2-id page3-id page4-id page5-id])]] + + (ths/run-store + store done events + (fn [state] + (let [pgs (pages state)] + (t/is (= 1 (count pgs)) + "at least one page remains") + (t/is (= page1-id (first pgs)) + "the first page (in page order) is kept"))))))) diff --git a/frontend/test/frontend_tests/runner.cljs b/frontend/test/frontend_tests/runner.cljs index 2fc48be9bf..f7c58d2aea 100644 --- a/frontend/test/frontend_tests/runner.cljs +++ b/frontend/test/frontend_tests/runner.cljs @@ -19,6 +19,7 @@ [frontend-tests.data.workspace-interactions-test] [frontend-tests.data.workspace-mcp-test] [frontend-tests.data.workspace-media-test] + [frontend-tests.data.workspace-pages-test] [frontend-tests.data.workspace-reflow-test] [frontend-tests.data.workspace-shortcuts-test] [frontend-tests.data.workspace-texts-test] @@ -108,6 +109,7 @@ 'frontend-tests.data.workspace-interactions-test 'frontend-tests.data.workspace-mcp-test 'frontend-tests.data.workspace-media-test + 'frontend-tests.data.workspace-pages-test 'frontend-tests.data.workspace-reflow-test 'frontend-tests.data.workspace-shortcuts-test 'frontend-tests.data.workspace-texts-test