(ns e2e "E2E test utilities and runner for VHS tape tests." (:require [babashka.fs :as fs] [babashka.process :refer [shell]] [clojure.string :as str])) (defn sh "Run shell command, return exit code." [& args] (:exit (apply shell {:continue true :out :inherit :err :inherit} args))) (defn sh-quiet "Run shell command quietly, return exit code." [& args] (:exit (apply shell {:continue true :out nil :err nil} args))) (defn setup-test-repo "Setup a test git repository for e2e tests. Usage: (setup-test-repo) or (setup-test-repo \"/tmp/my-repo\")" ([] (setup-test-repo "/tmp/lazygitclj-e2e-test")) ([repo-dir] (fs/delete-tree repo-dir) (fs/create-dirs repo-dir) ;; Initialize repo (shell {:dir repo-dir} "git" "init" "-b" "main") (shell {:dir repo-dir} "git" "config" "user.email" "test@example.com") (shell {:dir repo-dir} "git" "config" "user.name" "Test User") ;; Create initial files (spit (fs/file repo-dir "README.md") "# Test Project\n") (spit (fs/file repo-dir "file1.txt") "line1\n") (spit (fs/file repo-dir "file2.txt") "line2\n") (shell {:dir repo-dir} "git" "add" ".") (shell {:dir repo-dir} "git" "commit" "-m" "Initial commit") ;; Create feature branch with changes (shell {:dir repo-dir} "git" "checkout" "-b" "feature-branch") (spit (fs/file repo-dir "feature.txt") "feature content\n") (shell {:dir repo-dir} "git" "add" ".") (shell {:dir repo-dir} "git" "commit" "-m" "Add feature") ;; Go back to main and make uncommitted changes (shell {:dir repo-dir} "git" "checkout" "main") (spit (fs/file repo-dir "file1.txt") "line1\nmodified\n") (spit (fs/file repo-dir "new-file.txt") "new file\n") (println "Test repo created at" repo-dir) repo-dir)) (defn setup-cursor-test-repo "Setup test repo with many files for cursor navigation tests." ([] (setup-cursor-test-repo "/tmp/lazygitclj-e2e-cursor")) ([repo-dir] (fs/delete-tree repo-dir) (fs/create-dirs repo-dir) ;; Initialize repo (shell {:dir repo-dir} "git" "init" "-b" "main") (shell {:dir repo-dir} "git" "config" "user.email" "test@test.com") (shell {:dir repo-dir} "git" "config" "user.name" "Test") ;; Create 20 files (doseq [i (range 1 21)] (spit (fs/file repo-dir (str "file" i ".txt")) (str "content " i "\n"))) (shell {:dir repo-dir} "git" "add" ".") (shell {:dir repo-dir} "git" "commit" "-m" "Initial") ;; Modify all files to create unstaged changes (doseq [i (range 1 21)] (spit (fs/file repo-dir (str "file" i ".txt")) (str "content " i "\nmodified " i "\n"))) (println "Cursor test repo created at" repo-dir) repo-dir)) (defn setup-branch-order-test-repo "Setup test repo with branches having different commit dates to test sorting. Creates branches in alphabetical order but with commits in reverse order, so date-sorted results should differ from alphabetical. Commit dates: - main: 2024-01-04 (newest, so it appears first) - gamma-branch: 2024-01-03 - beta-branch: 2024-01-02 - alpha-branch: 2024-01-01 (oldest) Expected date-sorted order: main, gamma-branch, beta-branch, alpha-branch Alphabetical order would be: alpha-branch, beta-branch, gamma-branch, main" ([] (setup-branch-order-test-repo "/tmp/lazygitclj-e2e-branch-order")) ([repo-dir] (fs/delete-tree repo-dir) (fs/create-dirs repo-dir) ;; Initialize repo (shell {:dir repo-dir} "git" "init" "-b" "main") (shell {:dir repo-dir} "git" "config" "user.email" "test@example.com") (shell {:dir repo-dir} "git" "config" "user.name" "Test User") ;; Initial commit on main (will be updated later with a specific date) (spit (fs/file repo-dir "README.md") "# Branch Order Test\n") (shell {:dir repo-dir} "git" "add" ".") (shell {:dir repo-dir :extra-env {"GIT_COMMITTER_DATE" "2024-01-04T10:00:00"}} "git" "commit" "-m" "Initial commit" "--date=2024-01-04T10:00:00") ;; Create branches with commits in specific order (oldest to newest): ;; alpha-branch (oldest) -> beta-branch -> gamma-branch -> main (newest) ;; This way, date-sorted order should be: main, gamma, beta, alpha ;; while alphabetical would be: alpha, beta, gamma, main ;; Create alpha-branch (oldest) (shell {:dir repo-dir} "git" "checkout" "-b" "alpha-branch") (spit (fs/file repo-dir "alpha.txt") "alpha content\n") (shell {:dir repo-dir} "git" "add" ".") ;; Use GIT_COMMITTER_DATE to set specific commit times (shell {:dir repo-dir :extra-env {"GIT_COMMITTER_DATE" "2024-01-01T10:00:00"}} "git" "commit" "-m" "Add alpha" "--date=2024-01-01T10:00:00") ;; Create beta-branch (middle) (shell {:dir repo-dir} "git" "checkout" "main") (shell {:dir repo-dir} "git" "checkout" "-b" "beta-branch") (spit (fs/file repo-dir "beta.txt") "beta content\n") (shell {:dir repo-dir} "git" "add" ".") (shell {:dir repo-dir :extra-env {"GIT_COMMITTER_DATE" "2024-01-02T10:00:00"}} "git" "commit" "-m" "Add beta" "--date=2024-01-02T10:00:00") ;; Create gamma-branch (shell {:dir repo-dir} "git" "checkout" "main") (shell {:dir repo-dir} "git" "checkout" "-b" "gamma-branch") (spit (fs/file repo-dir "gamma.txt") "gamma content\n") (shell {:dir repo-dir} "git" "add" ".") (shell {:dir repo-dir :extra-env {"GIT_COMMITTER_DATE" "2024-01-03T10:00:00"}} "git" "commit" "-m" "Add gamma" "--date=2024-01-03T10:00:00") ;; Return to main (shell {:dir repo-dir} "git" "checkout" "main") (println "Branch order test repo created at" repo-dir) (println "Expected date-sorted order: main, gamma-branch, beta-branch, alpha-branch") repo-dir)) (defn cleanup-branch-order-test-repo "Clean up the branch order test repo." ([] (cleanup-branch-order-test-repo "/tmp/lazygitclj-e2e-branch-order")) ([repo-dir] (fs/delete-tree repo-dir) (println "Cleaned up" repo-dir))) (def tests "List of e2e test tapes." ["test/e2e/navigation.tape" "test/e2e/cursor-navigation.tape" "test/e2e/staging.tape" "test/e2e/commit.tape" "test/e2e/commit-verify.tape" "test/e2e/branches.tape" "test/e2e/branch-operations.tape" "test/e2e/branches-tabs.tape" "test/e2e/branch-order.tape" "test/e2e/commits-tabs.tape" "test/e2e/stash-operations.tape" "test/e2e/stash-menu.tape" "test/e2e/help-panel.tape" "test/e2e/reset-menu.tape" "test/e2e/undo-redo.tape"]) (defn run-tape "Run a single VHS tape, return true if passed." [tape] (println) (println "Running:" tape) (println "---") (let [exit-code (sh-quiet "timeout" "60" "vhs" tape)] (if (zero? exit-code) (do (println "PASSED:" tape) true) (do (println "FAILED:" tape) false)))) (defn run-all "Run all VHS e2e tests." [] (println "Running lazygitclj VHS e2e tests...") (println "=================================") (let [results (map run-tape tests) passed (count (filter true? results)) failed (count (filter false? results))] (println) (println "=================================") (println (str "Results: " passed " passed, " failed " failed")) (println "=================================") (when (pos? failed) (System/exit 1)))) ;; Allow running from command line (when (= *file* (System/getProperty "babashka.file")) (let [args *command-line-args*] (case (first args) "setup" (setup-test-repo (or (second args) "/tmp/lazygitclj-e2e-test")) "setup-cursor" (setup-cursor-test-repo (or (second args) "/tmp/lazygitclj-e2e-cursor")) "setup-branch-order" (setup-branch-order-test-repo (or (second args) "/tmp/lazygitclj-e2e-branch-order")) "cleanup-branch-order" (cleanup-branch-order-test-repo (or (second args) "/tmp/lazygitclj-e2e-branch-order")) "run" (run-all) (run-all))))