diff --git a/.github/workflows/clj-e2e.yml b/.github/workflows/clj-e2e.yml index b43874c972..c031783962 100644 --- a/.github/workflows/clj-e2e.yml +++ b/.github/workflows/clj-e2e.yml @@ -86,3 +86,11 @@ jobs: run: cd clj-e2e && bb dev env: DEBUG: "pw:api" + + - name: Collect screenshots + if: ${{ failure() }} + uses: actions/upload-artifact@v4 + with: + name: e2e-screenshots + path: e2e-dump/* + retention-days: 1 diff --git a/clj-e2e/dev/user.clj b/clj-e2e/dev/user.clj index c3dc0697c5..ef15d972cf 100644 --- a/clj-e2e/dev/user.clj +++ b/clj-e2e/dev/user.clj @@ -18,6 +18,7 @@ (reset! config/*port 3001) ;; show ui (reset! config/*headless false) +(reset! config/*slow-mo 100) (def *futures (atom {})) @@ -46,6 +47,13 @@ (->> (future (run-tests 'logseq.e2e.multi-tabs-test)) (swap! *futures assoc :multi-tabs-test))) +(defn run-all-test + [] + (run-tests 'logseq.e2e.commands-test + 'logseq.e2e.multi-tabs-test + 'logseq.e2e.outliner-test + 'logseq.e2e.rtc-basic-test)) + (comment (future diff --git a/clj-e2e/test/logseq/e2e/custom_report.clj b/clj-e2e/test/logseq/e2e/custom_report.clj new file mode 100644 index 0000000000..555b4cdceb --- /dev/null +++ b/clj-e2e/test/logseq/e2e/custom_report.clj @@ -0,0 +1,40 @@ +(ns logseq.e2e.custom-report + (:require [clojure.stacktrace :as stack] + [clojure.string :as string] + [clojure.test :as t] + [logseq.e2e.playwright-page :as pw-page]) + (:import (com.microsoft.playwright Page$ScreenshotOptions))) + +(def ^:dynamic *pw-contexts* + "Set of pw-contexts. + record all playwright contexts in this dynamic var" + nil) + +(defn- screenshot + [page test-name] + (println :screenshot test-name) + (.screenshot + page + (-> (Page$ScreenshotOptions.) + (.setPath (java.nio.file.Paths/get "e2e-dump/" + (into-array [(format "./screenshot-%s-%s.png" test-name (System/currentTimeMillis))])))))) + +(defmethod t/report :error + [m] + ;; copy from default impl + (t/with-test-out + (t/inc-report-counter :error) + (println "\nERROR in" (t/testing-vars-str m)) + (when (seq t/*testing-contexts*) (println (t/testing-contexts-str))) + (when-let [message (:message m)] (println message)) + (println "expected:" (pr-str (:expected m))) + (print " actual: ") + (let [actual (:actual m)] + (if (instance? Throwable actual) + (stack/print-cause-trace actual t/*stack-trace-depth*) + (prn actual)))) + + ;; screenshot for all pw pages when :error + (when-let [all-contexts (seq *pw-contexts*)] + (doseq [page (mapcat pw-page/get-pages all-contexts)] + (screenshot page (string/join "-" (map (comp str :name meta) t/*testing-vars*)))))) diff --git a/clj-e2e/test/logseq/e2e/fixtures.clj b/clj-e2e/test/logseq/e2e/fixtures.clj index f892b0c1ba..e5dd2e5a01 100644 --- a/clj-e2e/test/logseq/e2e/fixtures.clj +++ b/clj-e2e/test/logseq/e2e/fixtures.clj @@ -1,9 +1,8 @@ (ns logseq.e2e.fixtures (:require [logseq.e2e.config :as config] - [logseq.e2e.playwright-page :as pw-page] - [logseq.e2e.util :as util] - [wally.main :as w] - [logseq.e2e.page :as page])) + [logseq.e2e.custom-report :as custom-report] + [logseq.e2e.page :as page] + [wally.main :as w])) ;; TODO: save trace ;; TODO: parallel support @@ -13,8 +12,9 @@ (w/make-page {:headless (or headless @config/*headless) :persistent false :slow-mo @config/*slow-mo}) - (w/navigate (str "http://localhost:" (or port @config/*port))) - (f))) + (binding [custom-report/*pw-contexts* #{(.context (w/get-page))}] + (w/navigate (str "http://localhost:" (or port @config/*port))) + (f)))) (def *page1 (atom nil)) (def *page2 (atom nil)) @@ -29,15 +29,17 @@ p1 (w/make-page page-opts) p2 (w/make-page page-opts) port' (or port @config/*port)] - (run! - #(w/with-page % - (w/navigate (str "http://localhost:" port'))) - [p1 p2]) - (reset! *page1 p1) (reset! *page2 p2) - (binding [w/*page* (delay (throw (ex-info "Don't use *page*, use *page1* and *page2* instead" {})))] + (binding [custom-report/*pw-contexts* (set [(.context @p1) (.context @p2)]) + w/*page* (delay (throw (ex-info "Don't use *page*, use *page1* and *page2* instead" {})))] + (run! + #(w/with-page % + (w/navigate (str "http://localhost:" port'))) + [p1 p2]) (f)) + + ;; use with-page-open to release resources (w/with-page-open p1) (w/with-page-open p2))) @@ -53,7 +55,8 @@ ;; context for p is no longer needed (.close (.context p)) (w/with-page-open p) ; use with-page-open to close playwright instance - (binding [*pw-ctx* ctx] + (binding [custom-report/*pw-contexts* #{ctx} + *pw-ctx* ctx] (f) (.close (.browser *pw-ctx*)))))