mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-09 20:44:03 -08:00
627 lines
16 KiB
Go
627 lines
16 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
const (
|
|
changesColor = "#BD8BDE"
|
|
)
|
|
|
|
func TestEnabledGitNotFound(t *testing.T) {
|
|
env := new(MockedEnvironment)
|
|
env.On("hasCommand", "git").Return(false)
|
|
g := &git{
|
|
env: env,
|
|
}
|
|
assert.False(t, g.enabled())
|
|
}
|
|
|
|
func TestEnabledInWorkingDirectory(t *testing.T) {
|
|
env := new(MockedEnvironment)
|
|
env.On("hasCommand", "git").Return(true)
|
|
env.On("runCommand", "git", []string{"rev-parse", "--is-inside-work-tree"}).Return("true", nil)
|
|
g := &git{
|
|
env: env,
|
|
}
|
|
assert.True(t, g.enabled())
|
|
}
|
|
|
|
func TestGetGitOutputForCommand(t *testing.T) {
|
|
args := []string{"-c", "core.quotepath=false", "-c", "color.status=false"}
|
|
commandArgs := []string{"symbolic-ref", "--short", "HEAD"}
|
|
want := "je suis le output"
|
|
env := new(MockedEnvironment)
|
|
env.On("runCommand", "git", append(args, commandArgs...)).Return(want, nil)
|
|
g := &git{
|
|
env: env,
|
|
}
|
|
got := g.getGitCommandOutput(commandArgs...)
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
type detachedContext struct {
|
|
currentCommit string
|
|
rebase string
|
|
rebaseMerge bool
|
|
rebaseApply bool
|
|
origin string
|
|
onto string
|
|
step string
|
|
total string
|
|
branchName string
|
|
tagName string
|
|
cherryPick bool
|
|
cherryPickSHA string
|
|
merge bool
|
|
mergeHEAD string
|
|
}
|
|
|
|
func setupHEADContextEnv(context *detachedContext) *git {
|
|
env := new(MockedEnvironment)
|
|
env.On("hasFolder", "/.git/rebase-merge").Return(context.rebaseMerge)
|
|
env.On("hasFolder", "/.git/rebase-apply").Return(context.rebaseApply)
|
|
env.On("getFileContent", "/.git/rebase-merge/orig-head").Return(context.origin)
|
|
env.On("getFileContent", "/.git/rebase-merge/onto").Return(context.onto)
|
|
env.On("getFileContent", "/.git/rebase-merge/msgnum").Return(context.step)
|
|
env.On("getFileContent", "/.git/rebase-apply/next").Return(context.step)
|
|
env.On("getFileContent", "/.git/rebase-merge/end").Return(context.total)
|
|
env.On("getFileContent", "/.git/rebase-apply/last").Return(context.total)
|
|
env.On("getFileContent", "/.git/rebase-apply/head-name").Return(context.origin)
|
|
env.On("getFileContent", "/.git/CHERRY_PICK_HEAD").Return(context.cherryPickSHA)
|
|
env.On("getFileContent", "/.git/MERGE_HEAD").Return(context.mergeHEAD)
|
|
env.On("hasFiles", "/.git/CHERRY_PICK_HEAD").Return(context.cherryPick)
|
|
env.On("hasFiles", "/.git/MERGE_HEAD").Return(context.merge)
|
|
env.mockGitCommand(context.currentCommit, "rev-parse", "--short", "HEAD")
|
|
env.mockGitCommand(context.tagName, "describe", "--tags", "--exact-match")
|
|
env.mockGitCommand(context.origin, "name-rev", "--name-only", "--exclude=tags/*", context.origin)
|
|
env.mockGitCommand(context.onto, "name-rev", "--name-only", "--exclude=tags/*", context.onto)
|
|
env.mockGitCommand(context.cherryPickSHA, "name-rev", "--name-only", "--exclude=tags/*", context.cherryPickSHA)
|
|
env.mockGitCommand(context.mergeHEAD, "name-rev", "--name-only", "--exclude=tags/*", context.mergeHEAD)
|
|
g := &git{
|
|
env: env,
|
|
repo: &gitRepo{
|
|
root: "",
|
|
},
|
|
}
|
|
return g
|
|
}
|
|
|
|
func (m *MockedEnvironment) mockGitCommand(returnValue string, args ...string) {
|
|
args = append([]string{"-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
|
|
m.On("runCommand", "git", args).Return(returnValue, nil)
|
|
}
|
|
|
|
func TestGetGitDetachedCommitHash(t *testing.T) {
|
|
want := "\uf417lalasha1"
|
|
context := &detachedContext{
|
|
currentCommit: "lalasha1",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetGitHEADContextTagName(t *testing.T) {
|
|
want := "\uf412lalasha1"
|
|
context := &detachedContext{
|
|
currentCommit: "whatever",
|
|
tagName: "lalasha1",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetGitHEADContextRebaseMerge(t *testing.T) {
|
|
want := "\ue728 \ue0a0cool-feature-bro onto \ue0a0main (2/3) at \uf417whatever"
|
|
context := &detachedContext{
|
|
currentCommit: "whatever",
|
|
rebase: "true",
|
|
rebaseMerge: true,
|
|
origin: "cool-feature-bro",
|
|
onto: "main",
|
|
step: "2",
|
|
total: "3",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetGitHEADContextRebaseApply(t *testing.T) {
|
|
want := "\ue728 \ue0a0cool-feature-bro (2/3) at \uf417whatever"
|
|
context := &detachedContext{
|
|
currentCommit: "whatever",
|
|
rebase: "true",
|
|
rebaseApply: true,
|
|
origin: "cool-feature-bro",
|
|
step: "2",
|
|
total: "3",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetGitHEADContextRebaseUnknown(t *testing.T) {
|
|
want := "\uf417whatever"
|
|
context := &detachedContext{
|
|
currentCommit: "whatever",
|
|
rebase: "true",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetGitHEADContextCherryPickOnBranch(t *testing.T) {
|
|
want := "\ue29b pickme onto \ue0a0main"
|
|
context := &detachedContext{
|
|
currentCommit: "whatever",
|
|
branchName: "main",
|
|
cherryPick: true,
|
|
cherryPickSHA: "pickme",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("main")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetGitHEADContextCherryPickOnTag(t *testing.T) {
|
|
want := "\ue29b pickme onto \uf412v3.4.6"
|
|
context := &detachedContext{
|
|
currentCommit: "whatever",
|
|
tagName: "v3.4.6",
|
|
cherryPick: true,
|
|
cherryPickSHA: "pickme",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetGitHEADContextMerge(t *testing.T) {
|
|
want := "\ue727 \ue0a0feat into \ue0a0main"
|
|
context := &detachedContext{
|
|
merge: true,
|
|
mergeHEAD: "feat",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("main")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetGitHEADContextMergeTag(t *testing.T) {
|
|
want := "\ue727 \ue0a0feat into \uf412v3.4.6"
|
|
context := &detachedContext{
|
|
tagName: "v3.4.6",
|
|
merge: true,
|
|
mergeHEAD: "feat",
|
|
}
|
|
g := setupHEADContextEnv(context)
|
|
got := g.getGitHEADContext("")
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetStashContextZeroEntries(t *testing.T) {
|
|
want := ""
|
|
env := new(MockedEnvironment)
|
|
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "rev-list", "--walk-reflogs", "--count", "refs/stash"}).Return("", nil)
|
|
g := &git{
|
|
env: env,
|
|
}
|
|
got := g.getStashContext()
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestGetStashContextMultipleEntries(t *testing.T) {
|
|
want := "2"
|
|
env := new(MockedEnvironment)
|
|
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "rev-list", "--walk-reflogs", "--count", "refs/stash"}).Return("2", nil)
|
|
g := &git{
|
|
env: env,
|
|
}
|
|
got := g.getStashContext()
|
|
assert.Equal(t, want, got)
|
|
}
|
|
|
|
func TestParseGitBranchInfoEqual(t *testing.T) {
|
|
g := git{}
|
|
branchInfo := "## master...origin/master"
|
|
got := g.parseGitStatusInfo(branchInfo)
|
|
assert.Equal(t, "master", got["local"])
|
|
assert.Equal(t, "origin/master", got["upstream"])
|
|
assert.Empty(t, got["ahead"])
|
|
assert.Empty(t, got["behind"])
|
|
}
|
|
|
|
func TestParseGitBranchInfoAhead(t *testing.T) {
|
|
g := git{}
|
|
branchInfo := "## master...origin/master [ahead 1]"
|
|
got := g.parseGitStatusInfo(branchInfo)
|
|
assert.Equal(t, "master", got["local"])
|
|
assert.Equal(t, "origin/master", got["upstream"])
|
|
assert.Equal(t, "1", got["ahead"])
|
|
assert.Empty(t, got["behind"])
|
|
}
|
|
|
|
func TestParseGitBranchInfoBehind(t *testing.T) {
|
|
g := git{}
|
|
branchInfo := "## master...origin/master [behind 1]"
|
|
got := g.parseGitStatusInfo(branchInfo)
|
|
assert.Equal(t, "master", got["local"])
|
|
assert.Equal(t, "origin/master", got["upstream"])
|
|
assert.Equal(t, "1", got["behind"])
|
|
assert.Empty(t, got["ahead"])
|
|
}
|
|
|
|
func TestParseGitBranchInfoBehindandAhead(t *testing.T) {
|
|
g := git{}
|
|
branchInfo := "## master...origin/master [ahead 1, behind 2]"
|
|
got := g.parseGitStatusInfo(branchInfo)
|
|
assert.Equal(t, "master", got["local"])
|
|
assert.Equal(t, "origin/master", got["upstream"])
|
|
assert.Equal(t, "2", got["behind"])
|
|
assert.Equal(t, "1", got["ahead"])
|
|
}
|
|
|
|
func TestParseGitBranchInfoNoRemote(t *testing.T) {
|
|
g := git{}
|
|
branchInfo := "## master"
|
|
got := g.parseGitStatusInfo(branchInfo)
|
|
assert.Equal(t, "master", got["local"])
|
|
assert.Empty(t, got["upstream"])
|
|
}
|
|
|
|
func TestParseGitBranchInfoRemoteGone(t *testing.T) {
|
|
g := git{}
|
|
branchInfo := "## test-branch...origin/test-branch [gone]"
|
|
got := g.parseGitStatusInfo(branchInfo)
|
|
assert.Equal(t, "test-branch", got["local"])
|
|
assert.Equal(t, "gone", got["upstream_status"])
|
|
}
|
|
|
|
func TestGitStatusUnmerged(t *testing.T) {
|
|
expected := "<#123456>working: x1</>"
|
|
status := &gitStatus{
|
|
unmerged: 1,
|
|
}
|
|
assert.Equal(t, expected, status.string("working:", "#123456"))
|
|
}
|
|
|
|
func TestGitStatusUnmergedModified(t *testing.T) {
|
|
expected := "<#123456>working: ~3 x1</>"
|
|
status := &gitStatus{
|
|
unmerged: 1,
|
|
modified: 3,
|
|
}
|
|
assert.Equal(t, expected, status.string("working:", "#123456"))
|
|
}
|
|
|
|
func TestGitStatusEmpty(t *testing.T) {
|
|
expected := ""
|
|
status := &gitStatus{}
|
|
assert.Equal(t, expected, status.string("working:", "#123456"))
|
|
}
|
|
|
|
func TestParseGitStatsWorking(t *testing.T) {
|
|
g := &git{}
|
|
output := []string{
|
|
"## amazing-feat",
|
|
" M change.go",
|
|
"DD change.go",
|
|
" ? change.go",
|
|
" ? change.go",
|
|
" A change.go",
|
|
" U change.go",
|
|
" R change.go",
|
|
" C change.go",
|
|
}
|
|
status := g.parseGitStats(output, true)
|
|
assert.Equal(t, 3, status.modified)
|
|
assert.Equal(t, 1, status.unmerged)
|
|
assert.Equal(t, 1, status.added)
|
|
assert.Equal(t, 1, status.deleted)
|
|
assert.Equal(t, 2, status.untracked)
|
|
assert.True(t, status.changed)
|
|
}
|
|
|
|
func TestParseGitStatsStaging(t *testing.T) {
|
|
g := &git{}
|
|
output := []string{
|
|
"## amazing-feat",
|
|
" M change.go",
|
|
"DD change.go",
|
|
" ? change.go",
|
|
"?? change.go",
|
|
" A change.go",
|
|
"DU change.go",
|
|
"MR change.go",
|
|
"AC change.go",
|
|
}
|
|
status := g.parseGitStats(output, false)
|
|
assert.Equal(t, 1, status.modified)
|
|
assert.Equal(t, 0, status.unmerged)
|
|
assert.Equal(t, 1, status.added)
|
|
assert.Equal(t, 2, status.deleted)
|
|
assert.Equal(t, 0, status.untracked)
|
|
assert.True(t, status.changed)
|
|
}
|
|
|
|
func TestParseGitStatsNoChanges(t *testing.T) {
|
|
g := &git{}
|
|
expected := &gitStatus{}
|
|
output := []string{
|
|
"## amazing-feat",
|
|
}
|
|
status := g.parseGitStats(output, false)
|
|
assert.Equal(t, expected, status)
|
|
assert.False(t, status.changed)
|
|
}
|
|
|
|
func TestParseGitStatsInvalidLine(t *testing.T) {
|
|
g := &git{}
|
|
expected := &gitStatus{}
|
|
output := []string{
|
|
"## amazing-feat",
|
|
"#",
|
|
}
|
|
status := g.parseGitStats(output, false)
|
|
assert.Equal(t, expected, status)
|
|
assert.False(t, status.changed)
|
|
}
|
|
|
|
func bootstrapUpstreamTest(upstream string) *git {
|
|
env := &MockedEnvironment{}
|
|
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "remote", "get-url", "origin"}).Return(upstream, nil)
|
|
props := &properties{
|
|
values: map[Property]interface{}{
|
|
GithubIcon: "GH",
|
|
GitlabIcon: "GL",
|
|
BitbucketIcon: "BB",
|
|
GitIcon: "G",
|
|
},
|
|
}
|
|
g := &git{
|
|
env: env,
|
|
repo: &gitRepo{
|
|
upstream: "origin/main",
|
|
},
|
|
props: props,
|
|
}
|
|
return g
|
|
}
|
|
|
|
func TestGetUpstreamSymbolGitHub(t *testing.T) {
|
|
g := bootstrapUpstreamTest("github.com/test")
|
|
upstreamIcon := g.getUpstreamSymbol()
|
|
assert.Equal(t, "GH", upstreamIcon)
|
|
}
|
|
|
|
func TestGetUpstreamSymbolGitLab(t *testing.T) {
|
|
g := bootstrapUpstreamTest("gitlab.com/test")
|
|
upstreamIcon := g.getUpstreamSymbol()
|
|
assert.Equal(t, "GL", upstreamIcon)
|
|
}
|
|
|
|
func TestGetUpstreamSymbolBitBucket(t *testing.T) {
|
|
g := bootstrapUpstreamTest("bitbucket.org/test")
|
|
upstreamIcon := g.getUpstreamSymbol()
|
|
assert.Equal(t, "BB", upstreamIcon)
|
|
}
|
|
|
|
func TestGetUpstreamSymbolGit(t *testing.T) {
|
|
g := bootstrapUpstreamTest("gitstash.com/test")
|
|
upstreamIcon := g.getUpstreamSymbol()
|
|
assert.Equal(t, "G", upstreamIcon)
|
|
}
|
|
|
|
func TestGetStatusColorLocalChangesStaging(t *testing.T) {
|
|
expected := changesColor
|
|
repo := &gitRepo{
|
|
staging: &gitStatus{
|
|
changed: true,
|
|
},
|
|
}
|
|
g := &git{
|
|
repo: repo,
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
LocalChangesColor: expected,
|
|
},
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
|
|
}
|
|
|
|
func TestGetStatusColorLocalChangesWorking(t *testing.T) {
|
|
expected := changesColor
|
|
repo := &gitRepo{
|
|
staging: &gitStatus{},
|
|
working: &gitStatus{
|
|
changed: true,
|
|
},
|
|
}
|
|
g := &git{
|
|
repo: repo,
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
LocalChangesColor: expected,
|
|
},
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
|
|
}
|
|
|
|
func TestGetStatusColorAheadAndBehind(t *testing.T) {
|
|
expected := changesColor
|
|
repo := &gitRepo{
|
|
staging: &gitStatus{},
|
|
working: &gitStatus{},
|
|
ahead: 1,
|
|
behind: 3,
|
|
}
|
|
g := &git{
|
|
repo: repo,
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
AheadAndBehindColor: expected,
|
|
},
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
|
|
}
|
|
|
|
func TestGetStatusColorAhead(t *testing.T) {
|
|
expected := changesColor
|
|
repo := &gitRepo{
|
|
staging: &gitStatus{},
|
|
working: &gitStatus{},
|
|
ahead: 1,
|
|
behind: 0,
|
|
}
|
|
g := &git{
|
|
repo: repo,
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
AheadColor: expected,
|
|
},
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
|
|
}
|
|
|
|
func TestGetStatusColorBehind(t *testing.T) {
|
|
expected := changesColor
|
|
repo := &gitRepo{
|
|
staging: &gitStatus{},
|
|
working: &gitStatus{},
|
|
ahead: 0,
|
|
behind: 5,
|
|
}
|
|
g := &git{
|
|
repo: repo,
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
BehindColor: expected,
|
|
},
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
|
|
}
|
|
|
|
func TestGetStatusColorDefault(t *testing.T) {
|
|
expected := changesColor
|
|
repo := &gitRepo{
|
|
staging: &gitStatus{},
|
|
working: &gitStatus{},
|
|
ahead: 0,
|
|
behind: 0,
|
|
}
|
|
g := &git{
|
|
repo: repo,
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
BehindColor: changesColor,
|
|
},
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusColor(expected))
|
|
}
|
|
|
|
func TestSetStatusColorBackground(t *testing.T) {
|
|
expected := changesColor
|
|
repo := &gitRepo{
|
|
staging: &gitStatus{
|
|
changed: true,
|
|
},
|
|
}
|
|
g := &git{
|
|
repo: repo,
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
LocalChangesColor: changesColor,
|
|
ColorBackground: false,
|
|
},
|
|
foreground: "#ffffff",
|
|
background: "#111111",
|
|
},
|
|
}
|
|
g.SetStatusColor()
|
|
assert.Equal(t, expected, g.props.foreground)
|
|
}
|
|
|
|
func TestSetStatusColorForeground(t *testing.T) {
|
|
expected := changesColor
|
|
repo := &gitRepo{
|
|
staging: &gitStatus{
|
|
changed: true,
|
|
},
|
|
}
|
|
g := &git{
|
|
repo: repo,
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
LocalChangesColor: changesColor,
|
|
ColorBackground: true,
|
|
},
|
|
foreground: "#ffffff",
|
|
background: "#111111",
|
|
},
|
|
}
|
|
g.SetStatusColor()
|
|
assert.Equal(t, expected, g.props.background)
|
|
}
|
|
|
|
func TestGetStatusDetailStringDefault(t *testing.T) {
|
|
expected := "<#111111>icon +1</>"
|
|
status := &gitStatus{
|
|
changed: true,
|
|
added: 1,
|
|
}
|
|
g := &git{
|
|
props: &properties{
|
|
foreground: "#111111",
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
|
|
}
|
|
|
|
func TestGetStatusDetailStringNoStatus(t *testing.T) {
|
|
expected := "<#111111>icon</>"
|
|
status := &gitStatus{
|
|
changed: true,
|
|
added: 1,
|
|
}
|
|
g := &git{
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
DisplayStatusDetail: false,
|
|
},
|
|
foreground: "#111111",
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
|
|
}
|
|
|
|
func TestGetStatusDetailStringNoStatusColorOverride(t *testing.T) {
|
|
expected := "<#123456>icon</>"
|
|
status := &gitStatus{
|
|
changed: true,
|
|
added: 1,
|
|
}
|
|
g := &git{
|
|
props: &properties{
|
|
values: map[Property]interface{}{
|
|
DisplayStatusDetail: false,
|
|
WorkingColor: "#123456",
|
|
},
|
|
foreground: "#111111",
|
|
},
|
|
}
|
|
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
|
|
}
|