init
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
(ns lazygitclj.core-test
|
||||
"Unit tests for lazygitclj.core namespace - model and update functions"
|
||||
(:require [clojure.test :refer [deftest testing is]]
|
||||
[lazygitclj.core :as core]
|
||||
[tui.simple :as tui]))
|
||||
|
||||
;; Helper to create key messages in the format the TUI library uses
|
||||
(defn key-msg [k]
|
||||
(cond
|
||||
(char? k) [:key {:char k}]
|
||||
(keyword? k) [:key k]
|
||||
(and (vector? k) (= :ctrl (first k))) [:key {:ctrl true :char (second k)}]
|
||||
:else [:key k]))
|
||||
|
||||
;; === Model Tests ===
|
||||
|
||||
(deftest test-file-items
|
||||
(testing "combines staged and unstaged files"
|
||||
(let [model {:staged [{:path "a.txt"} {:path "b.txt"}]
|
||||
:unstaged [{:path "c.txt"}]}
|
||||
items (core/file-items model)]
|
||||
(is (= 3 (count items)))
|
||||
(is (= :staged (:type (first items))))
|
||||
(is (= :unstaged (:type (last items))))))
|
||||
|
||||
(testing "returns empty vector when no files"
|
||||
(let [model {:staged [] :unstaged []}]
|
||||
(is (= [] (core/file-items model))))))
|
||||
|
||||
(deftest test-current-items
|
||||
(testing "returns file items for files panel"
|
||||
(let [model {:panel :files
|
||||
:staged [{:path "a.txt"}]
|
||||
:unstaged [{:path "b.txt"}]}]
|
||||
(is (= 2 (count (core/current-items model))))))
|
||||
|
||||
(testing "returns commits for commits panel"
|
||||
(let [model {:panel :commits
|
||||
:commits-tab :commits
|
||||
:commits [{:sha "abc123"}]
|
||||
:reflog []}]
|
||||
(is (= 1 (count (core/current-items model))))))
|
||||
|
||||
(testing "returns reflog for commits panel with reflog tab"
|
||||
(let [model {:panel :commits
|
||||
:commits-tab :reflog
|
||||
:commits []
|
||||
:reflog [{:sha "def456"} {:sha "ghi789"}]}]
|
||||
(is (= 2 (count (core/current-items model))))))
|
||||
|
||||
(testing "returns branches for branches panel"
|
||||
(let [model {:panel :branches
|
||||
:branches-tab :local
|
||||
:branches ["main" "feature"]}]
|
||||
(is (= 2 (count (core/current-items model))))))
|
||||
|
||||
(testing "returns remote branches for branches panel with remotes tab"
|
||||
(let [model {:panel :branches
|
||||
:branches-tab :remotes
|
||||
:remote-branches ["origin/main"]}]
|
||||
(is (= 1 (count (core/current-items model))))))
|
||||
|
||||
(testing "returns tags for branches panel with tags tab"
|
||||
(let [model {:panel :branches
|
||||
:branches-tab :tags
|
||||
:tags ["v1.0.0" "v2.0.0"]}]
|
||||
(is (= 2 (count (core/current-items model))))))
|
||||
|
||||
(testing "returns stashes for stash panel"
|
||||
(let [model {:panel :stash
|
||||
:stashes [{:ref "stash@{0}"}]}]
|
||||
(is (= 1 (count (core/current-items model)))))))
|
||||
|
||||
(deftest test-clamp-cursor
|
||||
(testing "clamps cursor to valid range"
|
||||
(let [model {:panel :files
|
||||
:cursor 10
|
||||
:staged [{:path "a.txt"}]
|
||||
:unstaged []}
|
||||
clamped (core/clamp-cursor model)]
|
||||
(is (= 0 (:cursor clamped)))))
|
||||
|
||||
(testing "keeps cursor at valid position"
|
||||
(let [model {:panel :files
|
||||
:cursor 1
|
||||
:staged [{:path "a.txt"} {:path "b.txt"}]
|
||||
:unstaged []}
|
||||
clamped (core/clamp-cursor model)]
|
||||
(is (= 1 (:cursor clamped)))))
|
||||
|
||||
(testing "handles empty lists"
|
||||
(let [model {:panel :files
|
||||
:cursor 5
|
||||
:staged []
|
||||
:unstaged []}
|
||||
clamped (core/clamp-cursor model)]
|
||||
(is (= 0 (:cursor clamped))))))
|
||||
|
||||
(deftest test-truncate
|
||||
(testing "truncates long strings"
|
||||
(is (= "hello..." (core/truncate "hello world" 5))))
|
||||
|
||||
(testing "keeps short strings"
|
||||
(is (= "hi" (core/truncate "hi" 10))))
|
||||
|
||||
(testing "handles nil"
|
||||
(is (nil? (core/truncate nil 10)))))
|
||||
|
||||
;; === Update Tests ===
|
||||
|
||||
(deftest test-update-model-quit
|
||||
(testing "q returns quit command"
|
||||
(let [[model cmd] (core/update-model {} (key-msg \q))]
|
||||
(is (= [:quit] cmd))))
|
||||
|
||||
(testing "ctrl-c returns quit command"
|
||||
(let [[model cmd] (core/update-model {} [:key {:ctrl true :char \c}])]
|
||||
(is (= [:quit] cmd)))))
|
||||
|
||||
(deftest test-update-model-panel-switch
|
||||
(testing "number keys switch panels (2-5 matching lazygit)"
|
||||
(let [[model _] (core/update-model {:panel :commits :cursor 0
|
||||
:staged [] :unstaged []} (key-msg \2))]
|
||||
(is (= :files (:panel model))))
|
||||
|
||||
(let [[model _] (core/update-model {:panel :files :cursor 0
|
||||
:branches-tab :local
|
||||
:branches [] :remote-branches []
|
||||
:tags []} (key-msg \3))]
|
||||
(is (= :branches (:panel model))))
|
||||
|
||||
(let [[model _] (core/update-model {:panel :files :cursor 0
|
||||
:commits-tab :commits
|
||||
:commits [] :reflog []} (key-msg \4))]
|
||||
(is (= :commits (:panel model))))
|
||||
|
||||
(let [[model _] (core/update-model {:panel :files :cursor 0
|
||||
:stashes []} (key-msg \5))]
|
||||
(is (= :stash (:panel model)))))
|
||||
|
||||
(testing "l key cycles panels right (files → branches → commits → stash → files)"
|
||||
(let [[model _] (core/update-model {:panel :files :cursor 0
|
||||
:branches-tab :local
|
||||
:branches [] :remote-branches []
|
||||
:tags []} (key-msg \l))]
|
||||
(is (= :branches (:panel model))))
|
||||
|
||||
(let [[model _] (core/update-model {:panel :branches :cursor 0
|
||||
:commits-tab :commits
|
||||
:commits [] :reflog []} (key-msg \l))]
|
||||
(is (= :commits (:panel model))))
|
||||
|
||||
(let [[model _] (core/update-model {:panel :commits :cursor 0
|
||||
:stashes []} (key-msg \l))]
|
||||
(is (= :stash (:panel model))))
|
||||
|
||||
(let [[model _] (core/update-model {:panel :stash :cursor 0
|
||||
:staged [] :unstaged []} (key-msg \l))]
|
||||
(is (= :files (:panel model))))))
|
||||
|
||||
(deftest test-update-model-cursor-movement
|
||||
(testing "j moves cursor down"
|
||||
(let [[model _] (core/update-model {:panel :files :cursor 0
|
||||
:staged [{:path "a"} {:path "b"}]
|
||||
:unstaged []} (key-msg \j))]
|
||||
(is (= 1 (:cursor model)))))
|
||||
|
||||
(testing "k moves cursor up"
|
||||
(let [[model _] (core/update-model {:panel :files :cursor 1
|
||||
:staged [{:path "a"} {:path "b"}]
|
||||
:unstaged []} (key-msg \k))]
|
||||
(is (= 0 (:cursor model)))))
|
||||
|
||||
(testing "down arrow moves cursor down"
|
||||
(let [[model _] (core/update-model {:panel :files :cursor 0
|
||||
:staged [{:path "a"} {:path "b"}]
|
||||
:unstaged []} (key-msg :down))]
|
||||
(is (= 1 (:cursor model)))))
|
||||
|
||||
(testing "up arrow moves cursor up"
|
||||
(let [[model _] (core/update-model {:panel :files :cursor 1
|
||||
:staged [{:path "a"} {:path "b"}]
|
||||
:unstaged []} (key-msg :up))]
|
||||
(is (= 0 (:cursor model))))))
|
||||
|
||||
(deftest test-update-model-help-menu
|
||||
(testing "? opens help menu"
|
||||
(let [[model _] (core/update-model {:menu-mode nil} (key-msg \?))]
|
||||
(is (= :help (:menu-mode model))))))
|
||||
|
||||
(deftest test-update-model-reset-menu
|
||||
(testing "D opens reset options menu"
|
||||
(let [[model _] (core/update-model {:menu-mode nil} (key-msg \D))]
|
||||
(is (= :reset-options (:menu-mode model))))))
|
||||
|
||||
(deftest test-update-model-input-mode
|
||||
(testing "c in files panel opens commit input when staged files exist"
|
||||
(let [[model _] (core/update-model {:panel :files
|
||||
:staged [{:path "a.txt"}]
|
||||
:unstaged []} (key-msg \c))]
|
||||
(is (= :commit (:input-mode model)))))
|
||||
|
||||
(testing "c in files panel shows message when no staged files"
|
||||
(let [[model _] (core/update-model {:panel :files
|
||||
:staged []
|
||||
:unstaged []} (key-msg \c))]
|
||||
(is (= "Nothing staged to commit" (:message model))))))
|
||||
|
||||
(deftest test-update-input-mode
|
||||
(testing "escape cancels input mode"
|
||||
(let [[model _] (core/update-input-mode {:input-mode :commit
|
||||
:input-buffer "test"
|
||||
:input-context nil} (key-msg :escape))]
|
||||
(is (nil? (:input-mode model)))
|
||||
(is (= "" (:input-buffer model)))))
|
||||
|
||||
(testing "backspace removes last character"
|
||||
(let [[model _] (core/update-input-mode {:input-mode :commit
|
||||
:input-buffer "abc"
|
||||
:input-context nil} (key-msg :backspace))]
|
||||
(is (= "ab" (:input-buffer model))))))
|
||||
|
||||
(deftest test-update-commits-tabs
|
||||
(testing "] switches to reflog tab in commits panel"
|
||||
(let [[model _] (core/update-model {:panel :commits
|
||||
:commits-tab :commits
|
||||
:cursor 0
|
||||
:commits []
|
||||
:reflog []} (key-msg \]))]
|
||||
(is (= :reflog (:commits-tab model)))))
|
||||
|
||||
(testing "[ switches to commits tab in commits panel"
|
||||
(let [[model _] (core/update-model {:panel :commits
|
||||
:commits-tab :reflog
|
||||
:cursor 0
|
||||
:commits []
|
||||
:reflog []} (key-msg \[))]
|
||||
(is (= :commits (:commits-tab model))))))
|
||||
|
||||
(deftest test-update-branches-tabs
|
||||
(testing "] cycles branches tabs forward"
|
||||
(let [[model _] (core/update-branches {:branches-tab :local
|
||||
:cursor 0
|
||||
:branches []} (key-msg \]))]
|
||||
(is (= :remotes (:branches-tab model))))
|
||||
|
||||
(let [[model _] (core/update-branches {:branches-tab :remotes
|
||||
:cursor 0
|
||||
:remote-branches []} (key-msg \]))]
|
||||
(is (= :tags (:branches-tab model))))
|
||||
|
||||
(let [[model _] (core/update-branches {:branches-tab :tags
|
||||
:cursor 0
|
||||
:tags []} (key-msg \]))]
|
||||
(is (= :local (:branches-tab model)))))
|
||||
|
||||
(testing "[ cycles branches tabs backward"
|
||||
(let [[model _] (core/update-branches {:branches-tab :local
|
||||
:cursor 0
|
||||
:tags []} (key-msg \[))]
|
||||
(is (= :tags (:branches-tab model))))))
|
||||
|
||||
(deftest test-update-stash-menu
|
||||
(testing "escape closes stash menu"
|
||||
(let [[model _] (core/update-stash-menu {:menu-mode :stash-options} (key-msg :escape))]
|
||||
(is (nil? (:menu-mode model))))))
|
||||
|
||||
(deftest test-update-reset-menu
|
||||
(testing "escape closes reset menu"
|
||||
(let [[model _] (core/update-reset-menu {:menu-mode :reset-options} (key-msg :escape))]
|
||||
(is (nil? (:menu-mode model))))))
|
||||
|
||||
(deftest test-update-help
|
||||
(testing "escape closes help"
|
||||
(let [[model _] (core/update-help {:menu-mode :help} (key-msg :escape))]
|
||||
(is (nil? (:menu-mode model)))))
|
||||
|
||||
(testing "q closes help"
|
||||
(let [[model _] (core/update-help {:menu-mode :help} (key-msg \q))]
|
||||
(is (nil? (:menu-mode model)))))
|
||||
|
||||
(testing "? closes help"
|
||||
(let [[model _] (core/update-help {:menu-mode :help} (key-msg \?))]
|
||||
(is (nil? (:menu-mode model))))))
|
||||
|
||||
;; Run tests when executed directly
|
||||
(defn -main [& args]
|
||||
(clojure.test/run-tests 'lazygitclj.core-test))
|
||||
@@ -0,0 +1,323 @@
|
||||
(ns lazygitclj.git-test
|
||||
"Unit tests for lazygitclj.git namespace"
|
||||
(:require [clojure.test :refer [deftest testing is use-fixtures]]
|
||||
[lazygitclj.git :as git]
|
||||
[clojure.string :as str]
|
||||
[babashka.process :refer [shell]]))
|
||||
|
||||
;; === Test Fixtures ===
|
||||
|
||||
(def ^:dynamic *test-repo* nil)
|
||||
|
||||
(defn- sh [& args]
|
||||
(try
|
||||
(-> (apply shell {:out :string :err :string :dir *test-repo*} args)
|
||||
:out
|
||||
str/trim-newline)
|
||||
(catch Exception _ nil)))
|
||||
|
||||
(defn create-test-repo []
|
||||
(let [repo-dir (str "/tmp/lazygitclj-unit-test-" (System/currentTimeMillis))]
|
||||
(shell "mkdir" "-p" repo-dir)
|
||||
(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 (str repo-dir "/README.md") "# Test Project\n")
|
||||
(spit (str repo-dir "/file1.txt") "line1\n")
|
||||
(shell {:dir repo-dir} "git" "add" ".")
|
||||
(shell {:dir repo-dir} "git" "commit" "-m" "Initial commit")
|
||||
repo-dir))
|
||||
|
||||
(defn delete-test-repo [repo-dir]
|
||||
(shell "rm" "-rf" repo-dir))
|
||||
|
||||
(defn with-test-repo [f]
|
||||
(let [repo-dir (create-test-repo)]
|
||||
(try
|
||||
(binding [*test-repo* repo-dir]
|
||||
;; Change to test repo for git commands
|
||||
(let [original-dir (System/getProperty "user.dir")]
|
||||
(System/setProperty "user.dir" repo-dir)
|
||||
(try
|
||||
(f)
|
||||
(finally
|
||||
(System/setProperty "user.dir" original-dir)))))
|
||||
(finally
|
||||
(delete-test-repo repo-dir)))))
|
||||
|
||||
(use-fixtures :each with-test-repo)
|
||||
|
||||
;; === Status Tests ===
|
||||
|
||||
(deftest test-current-branch
|
||||
(testing "returns current branch name"
|
||||
(is (= "main" (sh "git" "branch" "--show-current")))))
|
||||
|
||||
(deftest test-head-sha
|
||||
(testing "returns short SHA of HEAD"
|
||||
(let [sha (sh "git" "rev-parse" "--short" "HEAD")]
|
||||
(is (string? sha))
|
||||
(is (>= (count sha) 7)))))
|
||||
|
||||
(deftest test-repo-root
|
||||
(testing "returns repo root directory"
|
||||
(let [root (sh "git" "rev-parse" "--show-toplevel")]
|
||||
(is (string? root))
|
||||
(is (str/starts-with? root "/tmp/lazygitclj-unit-test-")))))
|
||||
|
||||
;; === File Status Tests ===
|
||||
|
||||
(deftest test-staged-files
|
||||
(testing "returns empty list when nothing staged"
|
||||
;; Modify file but don't stage
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(let [staged (git/staged-files)]
|
||||
(is (empty? staged))))
|
||||
|
||||
(testing "returns staged files after git add"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(sh "git" "add" "file1.txt")
|
||||
(let [staged (git/staged-files)]
|
||||
(is (= 1 (count staged)))
|
||||
(is (= "file1.txt" (:path (first staged)))))))
|
||||
|
||||
(deftest test-unstaged-files
|
||||
(testing "returns modified unstaged files"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(let [unstaged (git/unstaged-files)]
|
||||
(is (= 1 (count unstaged)))
|
||||
(is (= "file1.txt" (:path (first unstaged))))))
|
||||
|
||||
(testing "returns untracked files"
|
||||
(spit (str *test-repo* "/newfile.txt") "new content\n")
|
||||
(let [unstaged (git/unstaged-files)]
|
||||
(is (some #(= "newfile.txt" (:path %)) unstaged)))))
|
||||
|
||||
;; === Branch Tests ===
|
||||
|
||||
(deftest test-branches
|
||||
(testing "returns list of local branches"
|
||||
(let [branches (git/branches)]
|
||||
(is (vector? branches))
|
||||
(is (some #(= "main" %) branches))))
|
||||
|
||||
(testing "includes newly created branches"
|
||||
(sh "git" "branch" "feature-branch")
|
||||
(let [branches (git/branches)]
|
||||
(is (some #(= "feature-branch" %) branches)))))
|
||||
|
||||
(deftest test-create-branch
|
||||
(testing "creates a new branch and switches to it"
|
||||
(git/create-branch "new-feature")
|
||||
(is (= "new-feature" (sh "git" "branch" "--show-current")))))
|
||||
|
||||
(deftest test-checkout-branch
|
||||
(testing "switches to existing branch"
|
||||
(sh "git" "branch" "other-branch")
|
||||
(git/checkout-branch "other-branch")
|
||||
(is (= "other-branch" (sh "git" "branch" "--show-current")))))
|
||||
|
||||
(deftest test-delete-branch
|
||||
(testing "deletes a branch"
|
||||
(sh "git" "branch" "to-delete")
|
||||
(git/delete-branch "to-delete")
|
||||
(let [branches (git/branches)]
|
||||
(is (not (some #(= "to-delete" %) branches))))))
|
||||
|
||||
(deftest test-rename-branch
|
||||
(testing "renames a branch"
|
||||
(sh "git" "branch" "old-name")
|
||||
(git/rename-branch "old-name" "new-name")
|
||||
(let [branches (git/branches)]
|
||||
(is (some #(= "new-name" %) branches))
|
||||
(is (not (some #(= "old-name" %) branches))))))
|
||||
|
||||
;; === Staging Tests ===
|
||||
|
||||
(deftest test-stage-file
|
||||
(testing "stages a modified file"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(git/stage-file "file1.txt")
|
||||
(let [staged (git/staged-files)]
|
||||
(is (= 1 (count staged))))))
|
||||
|
||||
(deftest test-unstage-file
|
||||
(testing "unstages a staged file"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(sh "git" "add" "file1.txt")
|
||||
(git/unstage-file "file1.txt")
|
||||
(let [staged (git/staged-files)]
|
||||
(is (empty? staged)))))
|
||||
|
||||
(deftest test-stage-all
|
||||
(testing "stages all changed files"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(spit (str *test-repo* "/newfile.txt") "new\n")
|
||||
(git/stage-all)
|
||||
(let [staged (git/staged-files)]
|
||||
(is (= 2 (count staged))))))
|
||||
|
||||
;; === Commit Tests ===
|
||||
|
||||
(deftest test-commit
|
||||
(testing "creates a commit with message"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(sh "git" "add" ".")
|
||||
(git/commit "Test commit message")
|
||||
(let [log (sh "git" "log" "--oneline" "-1")]
|
||||
(is (str/includes? log "Test commit message")))))
|
||||
|
||||
(deftest test-recent-commits
|
||||
(testing "returns recent commits"
|
||||
(let [commits (git/recent-commits 5)]
|
||||
(is (seq commits))
|
||||
(is (= "Initial commit" (:subject (first commits)))))))
|
||||
|
||||
;; === Stash Tests ===
|
||||
|
||||
(deftest test-stash-all
|
||||
(testing "stashes all changes"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(git/stash-all)
|
||||
(let [stashes (git/stash-list)]
|
||||
(is (= 1 (count stashes))))
|
||||
;; Working tree should be clean
|
||||
(let [unstaged (git/unstaged-files)]
|
||||
(is (empty? unstaged)))))
|
||||
|
||||
(deftest test-stash-pop
|
||||
(testing "pops stash and removes it from list"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(git/stash-all)
|
||||
(git/stash-pop)
|
||||
(let [stashes (git/stash-list)
|
||||
unstaged (git/unstaged-files)]
|
||||
(is (empty? stashes))
|
||||
(is (= 1 (count unstaged))))))
|
||||
|
||||
(deftest test-stash-apply
|
||||
(testing "applies stash but keeps it in list"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(git/stash-all)
|
||||
(git/stash-apply)
|
||||
(let [stashes (git/stash-list)
|
||||
unstaged (git/unstaged-files)]
|
||||
(is (= 1 (count stashes)))
|
||||
(is (= 1 (count unstaged))))))
|
||||
|
||||
(deftest test-stash-drop
|
||||
(testing "drops stash from list"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(git/stash-all)
|
||||
(git/stash-drop)
|
||||
(let [stashes (git/stash-list)]
|
||||
(is (empty? stashes)))))
|
||||
|
||||
;; === Reset Tests ===
|
||||
|
||||
(deftest test-discard-file
|
||||
(testing "discards unstaged changes to a file"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(git/discard-file "file1.txt")
|
||||
(let [content (slurp (str *test-repo* "/file1.txt"))]
|
||||
(is (= "line1\n" content)))))
|
||||
|
||||
(deftest test-discard-all-unstaged
|
||||
(testing "discards all unstaged changes"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(git/discard-all-unstaged)
|
||||
(let [unstaged (git/unstaged-files)]
|
||||
(is (empty? unstaged)))))
|
||||
|
||||
(deftest test-reset-staged
|
||||
(testing "unstages all staged files"
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(sh "git" "add" ".")
|
||||
(git/reset-staged)
|
||||
(let [staged (git/staged-files)]
|
||||
(is (empty? staged)))))
|
||||
|
||||
;; === Tag Tests ===
|
||||
|
||||
(deftest test-list-tags
|
||||
(testing "returns empty list when no tags"
|
||||
(let [tags (git/list-tags)]
|
||||
(is (empty? tags))))
|
||||
|
||||
(testing "returns tags after creating one"
|
||||
(sh "git" "tag" "v1.0.0")
|
||||
(let [tags (git/list-tags)]
|
||||
(is (some #(= "v1.0.0" %) tags)))))
|
||||
|
||||
(deftest test-create-tag
|
||||
(testing "creates a tag"
|
||||
(git/create-tag "v2.0.0")
|
||||
(let [tags (git/list-tags)]
|
||||
(is (some #(= "v2.0.0" %) tags)))))
|
||||
|
||||
(deftest test-delete-tag
|
||||
(testing "deletes a tag"
|
||||
(sh "git" "tag" "to-delete")
|
||||
(git/delete-tag "to-delete")
|
||||
(let [tags (git/list-tags)]
|
||||
(is (not (some #(= "to-delete" %) tags))))))
|
||||
|
||||
;; === Reflog Tests ===
|
||||
|
||||
(deftest test-reflog
|
||||
(testing "returns reflog entries"
|
||||
(let [reflog (git/reflog 10)]
|
||||
(is (seq reflog))
|
||||
(is (every? :sha reflog))
|
||||
(is (every? :ref reflog)))))
|
||||
|
||||
;; === Cherry-pick and Revert Tests ===
|
||||
|
||||
(deftest test-cherry-pick-commit
|
||||
(testing "cherry-picks a commit"
|
||||
;; Create a branch with a commit
|
||||
(sh "git" "checkout" "-b" "feature")
|
||||
(spit (str *test-repo* "/feature.txt") "feature content\n")
|
||||
(sh "git" "add" ".")
|
||||
(sh "git" "commit" "-m" "Feature commit")
|
||||
(let [feature-sha (sh "git" "rev-parse" "--short" "HEAD")]
|
||||
;; Go back to main
|
||||
(sh "git" "checkout" "main")
|
||||
;; Cherry-pick
|
||||
(git/cherry-pick-commit feature-sha)
|
||||
;; Verify file exists
|
||||
(is (.exists (java.io.File. (str *test-repo* "/feature.txt")))))))
|
||||
|
||||
(deftest test-revert-commit
|
||||
(testing "reverts a commit"
|
||||
;; Make a change and commit
|
||||
(spit (str *test-repo* "/file1.txt") "modified\n")
|
||||
(sh "git" "add" ".")
|
||||
(sh "git" "commit" "-m" "Change to revert")
|
||||
(let [sha (sh "git" "rev-parse" "--short" "HEAD")]
|
||||
;; Revert it
|
||||
(git/revert-commit sha)
|
||||
;; Verify content is back to original
|
||||
(let [content (slurp (str *test-repo* "/file1.txt"))]
|
||||
(is (= "line1\n" content))))))
|
||||
|
||||
;; === Merge Tests ===
|
||||
|
||||
(deftest test-merge-branch
|
||||
(testing "merges a branch into current"
|
||||
;; Create feature branch with changes
|
||||
(sh "git" "checkout" "-b" "to-merge")
|
||||
(spit (str *test-repo* "/merged.txt") "merged content\n")
|
||||
(sh "git" "add" ".")
|
||||
(sh "git" "commit" "-m" "Merge commit")
|
||||
;; Go back to main
|
||||
(sh "git" "checkout" "main")
|
||||
;; Merge
|
||||
(git/merge-branch "to-merge")
|
||||
;; Verify file exists on main
|
||||
(is (.exists (java.io.File. (str *test-repo* "/merged.txt"))))))
|
||||
|
||||
;; Run tests when executed directly
|
||||
(defn -main [& args]
|
||||
(clojure.test/run-tests 'lazygitclj.git-test))
|
||||
Reference in New Issue
Block a user