Procházet zdrojové kódy

test(e2e): add asset-blocks-validate-after-init-downloaded-test

rcmerci před 6 dny
rodič
revize
8d7ce39897

+ 1 - 18
AGENTS.md

@@ -1,5 +1,4 @@
 ## Repository Layout
-- Use clojure-mcp `clojure_inspect_project` to get project structure.
 - `src/`: Core source code
   - `src/main/`: The core logic of the application
     - `src/main/mobile/`: Mobile app code
@@ -21,10 +20,7 @@
 - Run single focused unit-test:
   - Add the `:focus` keyword to the test case: `(deftest ^:focus test-name ...)`
   - `bb dev:test -i focus`
-- Run e2e basic tests:
-  - `bb dev:e2e-basic-test`
-- Run e2e rtc extra tests:
-  - `bb dev:e2e-rtc-extra-test`
+- E2E tests files are located in `/clj-e2e`
 
 ## Common used cljs keywords
 - All commonly used ClojureScript keywords are defined using `logseq.common.defkeywords/defkeyword`.
@@ -37,16 +33,3 @@
 - Linters and unit-tests must pass
 - Check the review notes listed in `prompts/review.md`.
 
-# *IMPORTANT RULES*
-
-WARNING: The following are non-negotiable, highest-priority instructions. They *MUST* be followed unconditionally in all cases. Failure to comply with these rules will result in task failure.
-
-1. Clojure Code Editing Rules
-    * Instruction: When editing any .clj, .cljs, or .cljc file, you MUST and ONLY use the clojure-mcp toolkit.
-    * Prohibition: Absolutely do NOT use any general file writing tools (such as file_edit, file_write) to modify Clojure source files.
-    * Reason: This is to ensure the integrity of the code structure, avoid syntax errors, and maintain the project's code style.
-
-2. Code Review/Modification Prerequisites
-    * Instruction: Before EACH “review” or “modification” of the code, you MUST first execute the `clojure_inspect_project` tool.
-    * Prohibition: Do NOT begin analyzing or modifying code directly without obtaining project-wide information.
-    * Reason: This is to obtain complete, up-to-date project context, which is the foundation for making correct judgments and modifications.

+ 6 - 1
bb.edn

@@ -166,7 +166,12 @@
   logseq.tasks.dev/e2e-basic-test
 
   dev:e2e-rtc-extra-test
-  logseq.tasks.dev/e2e-rtc-extra-test
+  {:doc "Run e2e rtc extra tests. HTTP server should be available at localhost:3001"
+   :task (clojure {:dir "clj-e2e"} "-X:dev-run-rtc-extra-test")}
+
+  dev:e2e-rtc-extra-part2-test
+  {:doc "Run e2e rtc extra part2 tests. HTTP server should be available at localhost:3001"
+   :task (clojure {:dir "clj-e2e"} "-X:dev-run-rtc-extra-part2-test")}
 
   dev:gen-malli-kondo-config
   logseq.tasks.dev/gen-malli-kondo-config

+ 23 - 0
clj-e2e/AGENTS.md

@@ -0,0 +1,23 @@
+# E2E test Guide
+
+- Source Layout (`src/logseq/e2e/`)
+  - `assert.clj`: Custom assertion functions
+  - `block.clj`: Block manipulation helpers
+  - `config.clj`: Configuration settings
+  - `const.clj`: Shared constants
+  - `graph.clj`: Graph management helpers
+  - `keyboard.clj`: Keyboard shortcut helpers
+  - `locator.clj`: Playwright locator utilities
+  - `page.clj`: Page operations helpers
+  - `playwright_page.clj`: Playwright page initialization
+  - `rtc.clj`: RTC testing helpers
+  - `settings.clj`: Logseq settings manipulation
+  - `util.clj`: General utilities
+- Tests (`test/logseq/e2e/`)
+  - `fixtures.clj`: Test fixtures
+  - Basic Tests: `*_basic_test.clj`
+  - RTC Tests: `rtc_*_test.clj`
+- Run tests commands (in `clj-e2e` directory)
+  - `clojure -X:dev-run-rtc-extra-test`
+  - `clojure -X:dev-run-rtc-extra-part2-test`
+  - `clojure -X:dev-run-all-basic-test`

+ 2 - 0
clj-e2e/deps.edn

@@ -21,5 +21,7 @@
   :dev {:extra-paths ["dev" "test"]}
   :dev-run-rtc-extra-test {:extra-paths ["dev" "test"]
                            :exec-fn user/run-rtc-extra-test2}
+  :dev-run-rtc-extra-part2-test {:extra-paths ["dev" "test"]
+                                 :exec-fn user/run-rtc-extra-part2-test2}
   :dev-run-all-basic-test {:extra-paths ["dev" "test"]
                            :exec-fn user/run-all-basic-test}}}

+ 6 - 0
clj-e2e/dev/user.clj

@@ -15,6 +15,7 @@
             [logseq.e2e.property-basic-test]
             [logseq.e2e.reference-basic-test]
             [logseq.e2e.rtc-basic-test]
+            [logseq.e2e.rtc-extra-part2-test]
             [logseq.e2e.rtc-extra-test]
             [logseq.e2e.tag-basic-test]
             [logseq.e2e.util :as util]
@@ -79,6 +80,11 @@
   (run-tests 'logseq.e2e.rtc-extra-test)
   (System/exit 0))
 
+(defn run-rtc-extra-part2-test2
+  [& _args]
+  (run-tests 'logseq.e2e.rtc-extra-part2-test)
+  (System/exit 0))
+
 (defn run-editor-basic-test
   []
   (->> (future (run-tests 'logseq.e2e.editor-basic-test))

+ 2 - 0
clj-e2e/src/logseq/e2e/const.clj

@@ -7,3 +7,5 @@
 (def *page2
   "this 'page' means playwright-page, not logseq-page. it points to the client2 when testing rtc"
   (atom nil))
+
+(def ^:dynamic *graph-name* nil)

+ 11 - 2
clj-e2e/src/logseq/e2e/graph.clj

@@ -59,6 +59,15 @@
                              (format "div[data-testid='logseq_db_%s']" graph-name)
                              refresh-all-remote-graphs))
 
+(defn remove-local-graph
+  [graph-name]
+  (wait-for-remote-graph graph-name)
+  (let [action-btn
+        (.first (w/-query (format "div[data-testid='logseq_db_%s'] .graph-action-btn" graph-name)))]
+    (w/click action-btn)
+    (w/click ".delete-local-graph-menu-item")
+    (w/click "div[role='alertdialog'] button:text('ok')")))
+
 (defn remove-remote-graph
   [graph-name]
   (wait-for-remote-graph graph-name)
@@ -69,11 +78,11 @@
     (w/click "div[role='alertdialog'] button:text('ok')")))
 
 (defn switch-graph
-  [to-graph-name wait-sync?]
+  [to-graph-name wait-sync? need-input-password?]
   (goto-all-graphs)
   (w/click (.last (w/-query (format "div[data-testid='logseq_db_%1$s'] span:has-text('%1$s')" to-graph-name))))
   (when wait-sync?
-    (input-e2ee-password)
+    (when need-input-password? (input-e2ee-password))
     (w/wait-for "button.cloud.on.idle" {:timeout 20000}))
   (assert/assert-graph-loaded?))
 

+ 16 - 11
clj-e2e/src/logseq/e2e/page.clj

@@ -18,6 +18,10 @@
       (k/esc)
       (util/search-and-click page-name))))
 
+(defn get-page-name
+  []
+  (util/get-text "div[data-testid='page title'] .block-title-wrap"))
+
 (defn new-page
   [title]
   ;; Question: what's the best way to close all the popups?
@@ -42,17 +46,18 @@
   (k/esc))
 
 (defn- set-tag-extends
-  [extends & [in-retry?]]
-  (util/wait-timeout 500)
-  (w/click (loc/filter ".property-value" :has-text "root tag"))
-  (let [extends-visible? (mapv #(w/visible? (format "div:has(> button):has(div:text('%s'))" %)) extends)]
-    (if (every? identity extends-visible?)
-      (doseq [extend extends]
-        (w/click (format "div:has(> button):has(div:text('%s'))" extend)))
-      (if in-retry?
-        (throw (ex-info "parent-tag not found" {:extends extends :visible? extends-visible?}))
-        (do (k/esc)
-            (set-tag-extends extends true))))))
+  [extends & [retry-count]]
+  (let [retry-count (or retry-count 5)]
+    (util/wait-timeout 500)
+    (w/click (loc/filter ".property-value" :has-text "root tag"))
+    (let [extends-visible? (mapv #(w/visible? (format "div:has(> button):has(div:text('%s'))" %)) extends)]
+      (if (every? identity extends-visible?)
+        (doseq [extend extends]
+          (w/click (format "div:has(> button):has(div:text('%s'))" extend)))
+        (if (zero? retry-count)
+          (throw (ex-info "parent-tag not found" {:extends extends :visible? extends-visible?}))
+          (do (k/esc)
+              (set-tag-extends extends (dec retry-count))))))))
 
 (defn convert-to-tag
   [page-name & {:keys [extends]}]

+ 4 - 3
clj-e2e/test/logseq/e2e/fixtures.clj

@@ -2,7 +2,7 @@
   (:require [com.climate.claypoole :as cp]
             [logseq.e2e.assert :as assert]
             [logseq.e2e.config :as config]
-            [logseq.e2e.const :refer [*page1 *page2]]
+            [logseq.e2e.const :refer [*page1 *page2 *graph-name*]]
             [logseq.e2e.custom-report :as custom-report]
             [logseq.e2e.graph :as graph]
             [logseq.e2e.page :as page]
@@ -148,9 +148,10 @@
       (graph/new-graph graph-name true))
     (w/with-page @*page2
       (graph/wait-for-remote-graph graph-name)
-      (graph/switch-graph graph-name true))
+      (graph/switch-graph graph-name true true))
 
-    (binding [custom-report/*preserve-graph* false]
+    (binding [custom-report/*preserve-graph* false
+              *graph-name* graph-name]
       (f)
       ;; cleanup
       (if custom-report/*preserve-graph*

+ 3 - 3
clj-e2e/test/logseq/e2e/multi_tabs_basic_test.clj

@@ -34,15 +34,15 @@
                 (w/with-page p2
                   (util/goto-journals)
                   (assert/assert-in-normal-mode?)
-                  (graph/switch-graph graph-name false))
+                  (graph/switch-graph graph-name false false))
                 (w/with-page p3
                   (util/goto-journals)
                   (assert/assert-in-normal-mode?)
-                  (graph/switch-graph graph-name false))
+                  (graph/switch-graph graph-name false false))
                 (w/with-page p1
                   (util/goto-journals)
                   (assert/assert-in-normal-mode?)
-                  (graph/switch-graph graph-name false))
+                  (graph/switch-graph graph-name false false))
                 (let [graph-new-blocks (map #(str graph-name "-b1-" %) (range 5))]
                   (add-blocks-and-check-on-other-tabs graph-new-blocks p1 [p2 p3])))]
         (w/with-page p1

+ 1 - 1
clj-e2e/test/logseq/e2e/rtc_basic_test.clj

@@ -30,7 +30,7 @@
         (graph/new-graph graph-name true))
       (w/with-page @*page2
         (graph/wait-for-remote-graph graph-name)
-        (graph/switch-graph graph-name true)))
+        (graph/switch-graph graph-name true true)))
     (testing "logseq pages add/delete"
       (doseq [page-name page-names]
         (let [{:keys [_local-tx remote-tx]}

+ 37 - 3
clj-e2e/test/logseq/e2e/rtc_extra_part2_test.clj

@@ -1,9 +1,9 @@
 (ns logseq.e2e.rtc-extra-part2-test
-  (:require [clojure.string :as string]
-            [clojure.test :refer [deftest testing is use-fixtures run-test]]
+  (:require [clojure.test :refer [deftest testing is use-fixtures run-test]]
             [logseq.e2e.block :as b]
-            [logseq.e2e.const :refer [*page1 *page2]]
+            [logseq.e2e.const :refer [*page1 *page2 *graph-name*]]
             [logseq.e2e.fixtures :as fixtures]
+            [logseq.e2e.graph :as graph]
             [logseq.e2e.page :as page]
             [logseq.e2e.rtc :as rtc]
             [logseq.e2e.util :as util]
@@ -101,3 +101,37 @@ wait for 5-10 seconds, will found that \"aaa/bbb\" became \"aaa/<encrypted-strin
                (util/get-page-blocks-contents)))))
 
     (rtc/validate-graphs-in-2-pw-pages)))
+
+(deftest asset-blocks-validate-after-init-downloaded-test
+  (testing "
+- add some assets in client1
+- remove local graph in client2
+- re-download the remote graph in client2
+- compare asset-blocks data in both clients"
+    (let [asset-file "../assets/icon.png"
+          page-title (w/with-page @*page1 (page/get-page-name))]
+      (w/with-page @*page1
+        (let [p (w/get-page)]
+          (.onFileChooser p (reify java.util.function.Consumer
+                              (accept [_ fc]
+                                (.setFiles fc (into-array java.nio.file.Path [(java.nio.file.Paths/get asset-file (into-array String []))])))))
+          (b/new-block "asset block")
+          (util/input-command "Upload an asset")
+          (w/wait-for ".ls-block img")))
+
+      (let [{:keys [remote-tx]}
+            (w/with-page @*page1
+              (rtc/with-wait-tx-updated
+                (b/new-block "sync done")))]
+        (w/with-page @*page2
+          (rtc/wait-tx-update-to remote-tx)))
+
+      (w/with-page @*page2
+        (graph/remove-local-graph *graph-name*)
+        (graph/wait-for-remote-graph *graph-name*)
+        (graph/switch-graph *graph-name* true false)
+        (page/goto-page page-title)
+        (w/wait-for ".ls-block img")
+        (is (some? (.getAttribute (w/-query ".ls-block img") "src"))))
+
+      (rtc/validate-graphs-in-2-pw-pages))))

+ 6 - 0
src/main/frontend/worker/rtc/log_and_state.cljs

@@ -81,6 +81,12 @@
   (->> (m/latest vector (create-local-t-flow graph-uuid) (create-remote-t-flow graph-uuid))
        (m/eduction (filter (fn [[local-t remote-t]] (>= remote-t local-t))))))
 
+(defn clean-cached-graph-local-and-remote-t
+  [graph-uuid]
+  (let [graph-uuid (ensure-uuid graph-uuid)]
+    (swap! *graph-uuid->local-t dissoc graph-uuid)
+    (swap! *graph-uuid->remote-t dissoc graph-uuid)))
+
 (defn update-local-t
   [graph-uuid local-t]
   (let [graph-uuid (ensure-uuid graph-uuid)