Browse Source

Merge remote-tracking branch 'upstream/master' into whiteboards

Peng Xiao 3 years ago
parent
commit
66a08f8916

+ 1 - 1
deps/db/package.json

@@ -3,6 +3,6 @@
   "version": "1.0.0",
   "private": true,
   "devDependencies": {
-    "@logseq/nbb-logseq": "^0.5.103"
+    "@logseq/nbb-logseq": "^0.6.125"
   }
 }

+ 4 - 4
deps/db/yarn.lock

@@ -2,10 +2,10 @@
 # yarn lockfile v1
 
 
-"@logseq/nbb-logseq@^0.5.103":
-  version "0.5.103"
-  resolved "https://registry.yarnpkg.com/@logseq/nbb-logseq/-/nbb-logseq-0.5.103.tgz#1084380cd54c92ca8cc94a8934cc777206e45cc0"
-  integrity sha512-V9UW0XrCaaadHUc6/Hp9wfGpQqkzqzoqnDGeSVZkWR6l3QwyqGi9mkhnhVcfTwAvxIfOgrfz93GcaeepV4pYNA==
+"@logseq/nbb-logseq@^0.6.125":
+  version "0.6.125"
+  resolved "https://registry.yarnpkg.com/@logseq/nbb-logseq/-/nbb-logseq-0.6.125.tgz#197dbb01040f9cfdf7040399b9fbed9b862dee5b"
+  integrity sha512-1UB4Urt6O95Cwwni68B/f05x+wsL+ju+dCGLE47WTvF9F8WQwhiADfWhMbFOt35ImswLSzM1rgVGIMIj0g6fkQ==
   dependencies:
     import-meta-resolve "^1.1.1"
 

+ 1 - 1
deps/graph-parser/package.json

@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "devDependencies": {
-    "@logseq/nbb-logseq": "^0.5.103"
+    "@logseq/nbb-logseq": "^0.6.125"
   },
   "dependencies": {
     "mldoc": "^1.3.9"

+ 4 - 4
deps/graph-parser/src/logseq/graph_parser/block.cljs

@@ -480,8 +480,8 @@
       (d/squuid)))
 
 (defn get-page-refs-from-properties
-  [format properties db date-formatter]
-  (let [page-refs (get-page-ref-names-from-properties format properties {})]
+  [format properties db date-formatter user-config]
+  (let [page-refs (get-page-ref-names-from-properties format properties user-config)]
     (map (fn [page] (page-name->map page true db true date-formatter)) page-refs)))
 
 (defn- with-page-block-refs
@@ -493,7 +493,7 @@
           (update :refs (fn [col] (remove nil? col)))))
 
 (defn- with-pre-block-if-exists
-  [blocks body pre-block-properties encoded-content {:keys [supported-formats db date-formatter]}]
+  [blocks body pre-block-properties encoded-content {:keys [supported-formats db date-formatter user-config]}]
   (let [first-block (first blocks)
         format (or (:block/format first-block) :markdown)
         first-block-start-pos (get-in first-block [:block/meta :start_pos])
@@ -506,7 +506,7 @@
                    (let [content (utf8/substring encoded-content 0 first-block-start-pos)
                          {:keys [properties properties-order]} pre-block-properties
                          id (get-custom-id-or-new-id {:properties properties})
-                         property-refs (->> (get-page-refs-from-properties format properties db date-formatter)
+                         property-refs (->> (get-page-refs-from-properties format properties db date-formatter user-config)
                                             (map :block/original-name))
                          block {:uuid id
                                 :content content

+ 3 - 6
deps/graph-parser/src/logseq/graph_parser/extract.cljc

@@ -247,9 +247,6 @@
          (map (partial apply merge))
          (with-block-uuid))))
 
-#?(:org.babashka/nbb
-   (alter-var-root #'gp-mldoc/parse-property (constantly text/parse-property))
-   :default
-   ;; TODO: Properly fix this circular dependency:
-   ;; mldoc/->edn > text/parse-property > mldoc/link? ->mldoc/inline->edn + mldoc/default-config
-   (set! gp-mldoc/parse-property text/parse-property))
+;; TODO: Properly fix this circular dependency:
+;; mldoc/->edn > text/parse-property > mldoc/link? ->mldoc/inline->edn + mldoc/default-config
+(set! gp-mldoc/parse-property text/parse-property)

+ 1 - 1
deps/graph-parser/src/logseq/graph_parser/property.cljs

@@ -43,7 +43,7 @@
    #{:id :custom-id :background-color :background_color :heading :collapsed
      :created-at :updated-at :last-modified-at :created_at :last_modified_at
      :query-table :query-properties :query-sort-by :query-sort-desc :ls-type
-     :hl-type :hl-page :hl-stamp :file-path}
+     :hl-type :hl-page :hl-stamp}
    (set (map keyword markers))
    @built-in-extended-properties))
 

+ 18 - 3
deps/graph-parser/test/logseq/graph_parser/extract_test.cljs

@@ -1,19 +1,19 @@
 (ns logseq.graph-parser.extract-test
-  (:require [cljs.test :refer [deftest is]]
+  (:require [cljs.test :refer [deftest is are]]
             [logseq.graph-parser.extract :as extract]
             [clojure.pprint :as pprint]))
 
 (defn- extract
   [text]
   (let [{:keys [blocks]} (extract/extract "a.md" text {:block-pattern "-"})
-          lefts (map (juxt :block/parent :block/left) blocks)]
+        lefts (map (juxt :block/parent :block/left) blocks)]
     (if (not= (count lefts) (count (distinct lefts)))
       (do
         (pprint/pprint (map (fn [x] (select-keys x [:block/uuid :block/level :block/content :block/left])) blocks))
         (throw (js/Error. ":block/parent && :block/left conflicts")))
       (mapv :block/content blocks))))
 
-(deftest test-extract
+(deftest extract-blocks-for-headings
   []
   (is (= ["a" "b" "c"]
          (extract
@@ -41,6 +41,21 @@
   - i
 - j"))))
 
+(deftest extract-blocks-with-property-pages-config
+  []
+  (are [extract-args expected-refs]
+       (= expected-refs
+          (->> (apply extract/extract extract-args)
+               :blocks
+               (mapcat #(->> % :block/refs (map :block/name)))
+               set))
+
+       ["a.md" "foo:: #bar\nbaz:: #bing" {:block-pattern "-" :user-config {:property-pages/enabled? true}}]
+       #{"bar" "bing" "foo" "baz"}
+
+       ["a.md" "foo:: #bar\nbaz:: #bing" {:block-pattern "-" :user-config {:property-pages/enabled? false}}]
+       #{"bar" "bing"}))
+
 (deftest test-regression-1902
   []
   (is (= ["line1" "line2" "line3" "line4"]

+ 4 - 4
deps/graph-parser/yarn.lock

@@ -2,10 +2,10 @@
 # yarn lockfile v1
 
 
-"@logseq/nbb-logseq@^0.5.103":
-  version "0.5.103"
-  resolved "https://registry.yarnpkg.com/@logseq/nbb-logseq/-/nbb-logseq-0.5.103.tgz#1084380cd54c92ca8cc94a8934cc777206e45cc0"
-  integrity sha512-V9UW0XrCaaadHUc6/Hp9wfGpQqkzqzoqnDGeSVZkWR6l3QwyqGi9mkhnhVcfTwAvxIfOgrfz93GcaeepV4pYNA==
+"@logseq/nbb-logseq@^0.6.125":
+  version "0.6.125"
+  resolved "https://registry.yarnpkg.com/@logseq/nbb-logseq/-/nbb-logseq-0.6.125.tgz#197dbb01040f9cfdf7040399b9fbed9b862dee5b"
+  integrity sha512-1UB4Urt6O95Cwwni68B/f05x+wsL+ju+dCGLE47WTvF9F8WQwhiADfWhMbFOt35ImswLSzM1rgVGIMIj0g6fkQ==
   dependencies:
     import-meta-resolve "^1.1.1"
 

+ 15 - 0
docs/dev-practices.md

@@ -88,6 +88,10 @@ Our unit tests use the [shadow-cljs test-runner](https://shadow-cljs.github.io/d
 yarn test
 ```
 
+By convention, a namespace's tests are found at a corresponding namespace
+of the same name with an added `-test` suffix. For example, tests
+for `frontend.db.model` are found in `frontend.db.model-test`.
+
 There are a couple different ways to develop with tests:
 
 #### Focus Tests
@@ -115,6 +119,17 @@ To run tests automatically on file save, run `clojure -M:test watch test
 the `:ns-regexp` option e.g. `clojure -M:test watch test --config-merge
 '{:autorun true :ns-regexp "frontend.util.page-property-test"}'`.
 
+#### Database tests
+
+To write a test that uses a datascript db:
+
+* Be sure your test ns has test fixtures from `test-helper` ns to create and
+  destroy test databases after each test.
+* The easiest way to set up test data is to use `test-helper/load-test-files`.
+* For the repo argument that most fns take, pass it `test-helper/test-db`
+
+For examples of these tests, see `frontend.db.query-dsl-test` and `frontend.db.model-test`.
+
 ## Logging
 
 For logging, we use https://github.com/lambdaisland/glogi. When in development,

+ 1 - 1
e2e-tests/flashcards.spec.ts

@@ -3,7 +3,7 @@ import { test } from './fixtures'
 import { createRandomPage } from './utils'
 
 
-test('flashcard demo', async ({ page, block }) => {
+test.skip('flashcard demo', async ({ page, block }) => {
   await createRandomPage(page)
 
   await block.mustFill('Why do you add cards? #card #logseq')

+ 2 - 0
resources/css/common.css

@@ -1084,6 +1084,8 @@ mark {
   font-family: MonoLisa, 'Fira Code', Monaco, Menlo, Consolas, 'COURIER NEW',
     monospace;
   letter-spacing: 0;
+  background-color: var(--ls-page-inline-code-bg-color, #eee);
+  color: var(--ls-page-inline-code-color);
   word-spacing: -0.15em;
   text-rendering: optimizeSpeed;
 }

BIN
resources/icons/logseq_big_sur.icns


BIN
resources/icons/logseq_big_sur.ico


BIN
resources/icons/logseq_big_sur.png


+ 2 - 1
src/main/frontend/components/block.cljs

@@ -1946,7 +1946,8 @@
    (and (util/sup? target)
         (dom/has-class? target "fn"))
    (dom/has-class? target "image-resize")
-   (dom/closest target "a")))
+   (dom/closest target "a")
+   (dom/closest target ".query-table")))
 
 (defn- block-content-on-mouse-down
   [e block block-id _content edit-input-id]

+ 1 - 1
src/main/frontend/components/onboarding/quick_tour.cljs

@@ -71,7 +71,7 @@
    {:id                "nav-journal-page"
     :text              (h/render-html [:section [:h2 "📆 Daily Journal Page"]
                                        [:p
-                                        [:span "This is today’s daily journal page. Here yo can dump your thoughts, learnings and ideas. Don’t worry about organizing. Just write and"]
+                                        [:span "This is today’s daily journal page. Here you can dump your thoughts, learnings and ideas. Don’t worry about organizing. Just write and"]
                                         [:a "[[link]]"]
                                         [:span "your thoughts."]]])
 

+ 17 - 3
src/main/frontend/components/page.cljs

@@ -452,6 +452,7 @@
 (defonce *orphan-pages? (atom true))
 (defonce *builtin-pages? (atom nil))
 (defonce *excluded-pages? (atom true))
+(defonce *show-journals-in-page-graph? (atom nil))
 
 (rum/defc ^:large-vars/cleanup-todo graph-filters < rum/reactive
   [graph settings n-hops]
@@ -648,9 +649,21 @@
         graph (update graph :nodes #(filter-graph-nodes % search-graph-filters))]
     (global-graph-inner graph settings theme)))
 
-(rum/defc page-graph-inner < rum/static
+(rum/defc page-graph-inner < rum/reactive
   [_page graph dark?]
+   (let [ show-journals-in-page-graph? (rum/react *show-journals-in-page-graph?) ]
   [:div.sidebar-item.flex-col
+             [:div.flex.items-center.justify-between.mb-0
+              [:span (t :right-side-bar/show-journals)]
+              [:div.mt-1
+               (ui/toggle show-journals-in-page-graph? ;my-val;
+                           (fn []
+                             (let [value (not show-journals-in-page-graph?)]
+                               (reset! *show-journals-in-page-graph? value)
+                               ))
+                          true)]
+              ]
+
    (graph/graph-2d {:nodes (:nodes graph)
                     :links (:links graph)
                     :width 600
@@ -658,7 +671,7 @@
                     :dark? dark?
                     :register-handlers-fn
                     (fn [graph]
-                      (graph-register-handlers graph (atom nil) (atom nil) dark?))})])
+                      (graph-register-handlers graph (atom nil) (atom nil) dark?))})]))
 
 (rum/defc page-graph < db-mixins/query rum/reactive
   []
@@ -668,9 +681,10 @@
               (date/today))
         theme (:ui/theme @state/state)
         dark? (= theme "dark")
+        show-journals-in-page-graph (rum/react *show-journals-in-page-graph?)
         graph (if (util/uuid-string? page)
                 (graph-handler/build-block-graph (uuid page) theme)
-                (graph-handler/build-page-graph page theme))]
+                (graph-handler/build-page-graph page theme show-journals-in-page-graph))]
     (when (seq (:nodes graph))
       (page-graph-inner page graph dark?))))
 

+ 2 - 1
src/main/frontend/components/query_table.cljs

@@ -112,7 +112,8 @@
                                  desc?
                                  result)]
       [:div.overflow-x-auto {:on-mouse-down (fn [e] (.stopPropagation e))
-                             :style {:width "100%"}}
+                             :style {:width "100%"}
+                             :class (when-not page? "query-table")}
        [:table.table-auto
         [:thead
          [:tr.cursor

+ 1 - 1
src/main/frontend/components/right_sidebar.cljs

@@ -129,8 +129,8 @@
            [:div.flex.flex-col
             [:div.flex.flex-row.justify-between
              [:div.flex.flex-row.justify-center
+              {:on-click #(state/sidebar-block-toggle-collapse! db-id)}
               [:a.opacity-50.hover:opacity-100.flex.items-center.pr-1
-               {:on-click #(state/sidebar-block-toggle-collapse! db-id)}
                (ui/rotating-arrow collapse?)]
               [:div.ml-1.font-medium
                title]]

+ 13 - 8
src/main/frontend/db/model.cljs

@@ -1121,18 +1121,23 @@
 ;; get pages who mentioned this page
 ;; TODO: use :block/_refs
 (defn get-pages-that-mentioned-page
-  [repo page]
+  [repo page include-journals]
   (when (conn/get-db repo)
     (let [page-id (:db/id (db-utils/entity [:block/name (util/safe-page-name-sanity-lc page)]))
           pages (page-alias-set repo page)
+          query-base '[:find ?mentioned-page-name
+                       :in $ ?pages ?page-name
+                       :where
+                       [?block :block/refs ?p]
+                       [(contains? ?pages ?p)]
+                       [?block :block/page ?mentioned-page]
+                       [?mentioned-page :block/name ?mentioned-page-name]]
+          query  (if include-journals
+                   query-base
+                   (conj query-base '[?mentioned-page :block/journal? false]))
+
           mentioned-pages (->> (react/q repo [:frontend.db.react/page<-pages page-id] {:use-cache? false}
-                                        '[:find ?mentioned-page-name
-                                          :in $ ?pages ?page-name
-                                          :where
-                                          [?block :block/refs ?p]
-                                          [(contains? ?pages ?p)]
-                                          [?block :block/page ?mentioned-page]
-                                          [?mentioned-page :block/name ?mentioned-page-name]]
+                                        query
                                         pages
                                         page)
                                react

+ 2 - 0
src/main/frontend/dicts.cljc

@@ -68,6 +68,7 @@
         :right-side-bar/all-pages "All pages"
         :right-side-bar/flashcards "Flashcards"
         :right-side-bar/new-page "New page"
+        :right-side-bar/show-journals "Show Journals"
         :left-side-bar/journals "Journals"
         :left-side-bar/new-page "New page"
         :left-side-bar/nav-favorites "Favorites"
@@ -3207,6 +3208,7 @@
         :right-side-bar/all-pages "Tutte le pagine"
         :right-side-bar/flashcards "Flashcard"
         :right-side-bar/new-page "Nuova pagina"
+        :right-side-bar/show-journals "Mostra diari"
         :left-side-bar/journals "Diario"
         :left-side-bar/new-page "Nuova pagina"
         :left-side-bar/nav-favorites "Preferiti"

+ 2 - 2
src/main/frontend/extensions/pdf/highlights.cljs

@@ -122,7 +122,7 @@
                         "copy"
                         (do
                           (util/copy-to-clipboard!
-                            (or (:text content) (.toString selection)))
+                            (or (:text content) (pdf-utils/fix-selection-text-breakline (.toString selection))))
                           (pdf-utils/clear-all-selection))
 
                         "link"
@@ -575,7 +575,7 @@
                              {:id         nil
                               :page       page
                               :position   sc-pos
-                              :content    {:text (.toString selection)}
+                              :content    {:text (pdf-utils/fix-selection-text-breakline (.toString selection))}
                               :properties {}})))]
 
             ;; show ctx menu

+ 12 - 1
src/main/frontend/extensions/pdf/utils.cljs

@@ -4,7 +4,8 @@
             [frontend.util :as util]
             ["/frontend/extensions/pdf/utils" :as js-utils]
             [frontend.db :as front-db]
-            [frontend.loader :refer [load]]))
+            [frontend.loader :refer [load]]
+            [clojure.string :as string]))
 
 (defonce MAX-SCALE 5.0)
 (defonce MIN-SCALE 0.25)
@@ -156,6 +157,16 @@
                      :height (.-height rect)})]
         (optimize-client-reacts rects)))))
 
+(defn fix-selection-text-breakline
+  [text]
+
+  (when-not (string/blank? text)
+    (let [sp "@#~#@"]
+      (-> text
+          (string/replace #"[\r\n]+" sp)
+          (string/replace (str "-" sp) "")
+          (string/replace sp " ")))))
+
 ;; TODO: which viewer instance?
 (defn next-page
   []

+ 4 - 2
src/main/frontend/handler/editor.cljs

@@ -660,9 +660,11 @@
 (defn properties-block
   [properties format page]
   (let [content (property/insert-properties format "" properties)
-        refs (gp-block/get-page-refs-from-properties format properties
+        refs (gp-block/get-page-refs-from-properties format
+                                                     properties
                                                      (db/get-db (state/get-current-repo))
-                                                     (state/get-date-formatter))]
+                                                     (state/get-date-formatter)
+                                                     (state/get-config))]
     {:block/pre-block? true
      :block/uuid (db/new-block-id)
      :block/properties properties

+ 3 - 3
src/main/frontend/handler/graph.cljs

@@ -120,7 +120,7 @@
           :page-name->original-name page-name->original-name})))))
 
 (defn build-page-graph
-  [page theme]
+  [page theme show-journal]
   (let [dark? (= "dark" theme)]
     (when-let [repo (state/get-current-repo)]
       (let [page (util/page-name-sanity-lc page)
@@ -128,7 +128,7 @@
             tags (:tags (:block/properties page-entity))
             tags (remove #(= page %) tags)
             ref-pages (db/get-page-referenced-pages repo page)
-            mentioned-pages (db/get-pages-that-mentioned-page repo page)
+            mentioned-pages (db/get-pages-that-mentioned-page repo page show-journal)
             namespaces (db/get-all-namespace-relation repo)
             links (concat
                    namespaces
@@ -148,7 +148,7 @@
                                  (let [ref-pages (-> (map first (db/get-page-referenced-pages repo page))
                                                      (set)
                                                      (set/intersection other-pages))
-                                       mentioned-pages (-> (map first (db/get-pages-that-mentioned-page repo page))
+                                       mentioned-pages (-> (map first (db/get-pages-that-mentioned-page repo page show-journal))
                                                            (set)
                                                            (set/intersection other-pages))]
                                    (concat

+ 4 - 2
src/main/frontend/handler/page.cljs

@@ -75,9 +75,11 @@
    (let [p (common-handler/get-page-default-properties title)
          ps (merge p properties)
          content (page-property/insert-properties format "" ps)
-         refs (gp-block/get-page-refs-from-properties format properties
+         refs (gp-block/get-page-refs-from-properties format
+                                                      properties
                                                       (db/get-db (state/get-current-repo))
-                                                      (state/get-date-formatter))]
+                                                      (state/get-date-formatter)
+                                                      (state/get-config))]
      {:block/uuid (db/new-block-id)
       :block/properties ps
       :block/properties-order (keys ps)

+ 9 - 0
src/main/frontend/modules/shortcut/config.cljs

@@ -17,6 +17,8 @@
             [frontend.state :as state]
             [frontend.util :refer [mac?] :as util]
             [frontend.commands :as commands]
+            [electron.ipc :as ipc]
+            [promesa.core :as p]
             [clojure.data :as data]
             [medley.core :as medley]))
 
@@ -291,6 +293,11 @@
    :graph/save                     {:fn #(state/pub-event! [:graph/save])
                                     :binding false}
 
+   :graph/re-index                 {:fn (fn []
+                                          (p/let [multiple-windows? (ipc/ipc "graphHasMultipleWindows" (state/get-current-repo))]
+                                                 (state/pub-event! [:graph/ask-for-re-index multiple-windows?])))
+                                    :binding false}
+
    :command/run                    {:binding "mod+shift+1"
                                     :inactive (not (util/electron?))
                                     :fn      #(do
@@ -459,6 +466,7 @@
                           :graph/remove
                           :graph/add
                           :graph/save
+                          :graph/re-index
                           :editor/cycle-todo
                           :editor/up
                           :editor/down
@@ -643,6 +651,7 @@
     :graph/remove
     :graph/add
     :graph/save
+    :graph/re-index
     :sidebar/clear
     :sidebar/open-today-page
     :search/re-index

+ 2 - 2
src/main/frontend/modules/shortcut/dicts.cljc

@@ -90,6 +90,7 @@
    :graph/remove                   "Remove a graph"
    :graph/add                      "Add a graph"
    :graph/save                     "Save current graph to disk"
+   :graph/re-index                 "Re-index current graph"
    :command/run                    "Run git command"
    :go/home                        "Go to home"
    :go/all-pages                   "Go to all pages"
@@ -106,7 +107,7 @@
    :ui/toggle-help                 "Toggle help"
    :ui/toggle-theme                "Toggle between dark/light theme"
    :ui/toggle-contents             "Toggle Contents in sidebar"
-  ;;  :ui/open-new-window             "Open another window"
+   ;;  :ui/open-new-window             "Open another window"
    :command/toggle-favorite        "Add to/remove from favorites"
    :editor/open-file-in-default-app "Open file in default app"
    :editor/open-file-in-directory   "Open file in parent directory"
@@ -1016,7 +1017,6 @@
              :command.editor/copy-text                "Copia le selezioni come testo"
              :command.pdf/close                       "Chiudi anteprima PDF"}
 
-   
    :tr      {:shortcut.category/basics "Temel bilgiler"
              :shortcut.category/formatting "Biçimlendirme"
              :shortcut.category/navigating "Gezinme"

+ 29 - 0
src/test/frontend/db/model_test.cljs

@@ -82,4 +82,33 @@
 ;;       1 (count a-ref-blocks)
 ;;       (set ["b" "c"]) (set alias-names))))
 
+(deftest get-pages-that-mentioned-page-with-show-journal
+  (load-test-files [{:file/path "journals/2020_08_15.md"
+                     :file/content "link 1 to [[page ONE]] and link to [[generic page]]"}
+                    {:file/path "journals/2020_09_18.md"
+                     :file/content "link 2 to [[page ONE]]"}
+                    {:file/path "pages/page ONE.md"
+                     :file/content "tags:: a tag
+- page one has link to [[Dec 26th, 2020]] journal page"}
+                    {:file/path "pages/a tag.md"
+                     :file/content "i'm a tag"}
+                    {:file/path "pages/generic page.md"
+                     :file/content "- link to page one [[page ONE]]"}])
+
+  (is (= '("sep 18th, 2020" "aug 15th, 2020" "generic page")
+         (map first (model/get-pages-that-mentioned-page test-helper/test-db "page ONE" true)))
+      "Must be 'generic page' + 2 journals")
+
+  (is (= '("generic page")
+         (map first (model/get-pages-that-mentioned-page test-helper/test-db "page ONE" false)))
+      "Must be only 'generic page'")
+
+  (is (= '("aug 15th, 2020")
+         (map first (model/get-pages-that-mentioned-page test-helper/test-db "generic page" true)))
+      "Must show only 'aug 15th, 2020'")
+
+  (is (= '()
+         (map first (model/get-pages-that-mentioned-page test-helper/test-db "generic page" false)))
+      "Must be empty"))
+
 #_(cljs.test/test-ns 'frontend.db.model-test)