Add tests for bumpversion logic

This commit is contained in:
2025-12-24 10:38:58 +03:00
parent 04298cad4e
commit 3628a7898b

222
src/main_test.go Normal file
View File

@@ -0,0 +1,222 @@
package main
import (
"os"
"path/filepath"
"reflect"
"strings"
"testing"
)
func TestGetBumpConfig(t *testing.T) {
tmpDir := t.TempDir()
cfgPath := filepath.Join(tmpDir, ".bumpversion.cfg")
cfg := `
[bumpversion]
current_version = 1.2.3
commit = true
tag = true
tag_name = v{new_version}
parse = ^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$
serialize = {major}.{minor}.{patch}
message = Release {new_version}
[bumpversion:file:VERSION]
[bumpversion:file:README.md]
`
if err := os.WriteFile(cfgPath, []byte(cfg), 0o644); err != nil {
t.Fatalf("write config: %v", err)
}
got, err := getBumpConfig(cfgPath)
if err != nil {
t.Fatalf("getBumpConfig returned error: %v", err)
}
if got.CurrentVersion != "1.2.3" {
t.Fatalf("CurrentVersion = %q, want 1.2.3", got.CurrentVersion)
}
if !got.Commit || !got.Tag {
t.Fatalf("expected commit and tag to be true, got commit=%v tag=%v", got.Commit, got.Tag)
}
if got.TagName != "v{new_version}" {
t.Fatalf("TagName = %q, want v{new_version}", got.TagName)
}
if strings.TrimSpace(got.Serialize) != "{major}.{minor}.{patch}" {
t.Fatalf("Serialize = %q, want {major}.{minor}.{patch}", got.Serialize)
}
if got.Parse != `^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$` {
t.Fatalf("Parse = %q, want regex string", got.Parse)
}
wantPaths := map[string]bool{
"VERSION": true,
"README.md": true,
}
for _, p := range got.FilePaths {
delete(wantPaths, p)
}
if len(wantPaths) != 0 {
t.Fatalf("FilePaths missing entries: %v", reflect.ValueOf(wantPaths).MapKeys())
}
}
func TestUpdateConfigFile(t *testing.T) {
tmpDir := t.TempDir()
cfgPath := filepath.Join(tmpDir, ".bumpversion.cfg")
cfg := `
[bumpversion]
current_version = 0.0.1
commit = false
`
if err := os.WriteFile(cfgPath, []byte(cfg), 0o644); err != nil {
t.Fatalf("write config: %v", err)
}
if err := updateConfigFile(cfgPath, "0.0.2"); err != nil {
t.Fatalf("updateConfigFile returned error: %v", err)
}
updated, err := getBumpConfig(cfgPath)
if err != nil {
t.Fatalf("getBumpConfig returned error: %v", err)
}
if updated.CurrentVersion != "0.0.2" {
t.Fatalf("CurrentVersion = %q, want 0.0.2", updated.CurrentVersion)
}
}
func TestBumpVersion(t *testing.T) {
bc := &BumpConfig{
CurrentVersion: "1.2.3",
Parse: `^v?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$`,
Serialize: "{major}.{minor}.{patch}",
}
tests := []struct {
name string
part string
want string
wantErr bool
}{
{name: "major", part: "major", want: "2.0.0"},
{name: "minor", part: "minor", want: "1.3.0"},
{name: "patch", part: "patch", want: "1.2.4"},
{name: "unknown", part: "build", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := bumpVersion(bc, tt.part)
if (err != nil) != tt.wantErr {
t.Fatalf("bumpVersion error = %v, wantErr %v", err, tt.wantErr)
}
if err == nil && got != tt.want {
t.Fatalf("bumpVersion = %q, want %q", got, tt.want)
}
})
}
}
func TestBumpVersionInvalidCurrent(t *testing.T) {
bc := &BumpConfig{
CurrentVersion: "1.2",
Parse: `^v?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$`,
Serialize: "{major}.{minor}.{patch}",
}
if _, err := bumpVersion(bc, "patch"); err == nil {
t.Fatalf("expected error for invalid current_version")
}
}
func TestUpdateFiles(t *testing.T) {
tmpDir := t.TempDir()
oldV := "1.2.3"
newV := "1.2.4"
filePaths := []string{
filepath.Join(tmpDir, "VERSION"),
filepath.Join(tmpDir, "README.md"),
}
for _, p := range filePaths {
contents := "project version " + oldV + "\n"
if err := os.WriteFile(p, []byte(contents), 0o644); err != nil {
t.Fatalf("write %s: %v", p, err)
}
}
updateFiles(filePaths, oldV, newV)
for _, p := range filePaths {
data, err := os.ReadFile(p)
if err != nil {
t.Fatalf("read %s: %v", p, err)
}
if !strings.Contains(string(data), newV) || strings.Contains(string(data), oldV) {
t.Fatalf("%s not updated correctly: %s", p, string(data))
}
}
}
func TestResolveFlag(t *testing.T) {
boolPtr := func(b bool) *bool { return &b }
tests := []struct {
name string
positive *bool
negative *bool
defaultValue bool
want bool
wantPanic bool
}{
{
name: "positive wins",
positive: boolPtr(true),
negative: boolPtr(false),
defaultValue: false,
want: true,
},
{
name: "negative wins",
positive: boolPtr(false),
negative: boolPtr(true),
defaultValue: true,
want: false,
},
{
name: "default used",
positive: boolPtr(false),
negative: boolPtr(false),
defaultValue: true,
want: true,
},
{
name: "panic on conflict",
positive: boolPtr(true),
negative: boolPtr(true),
defaultValue: false,
wantPanic: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer func() {
if r := recover(); tt.wantPanic && r == nil {
t.Fatalf("expected panic but function returned")
} else if !tt.wantPanic && r != nil {
t.Fatalf("unexpected panic: %v", r)
}
}()
got := resolveFlag(tt.positive, tt.negative, tt.defaultValue)
if tt.wantPanic {
return
}
if got != tt.want {
t.Fatalf("resolveFlag = %v, want %v", got, tt.want)
}
})
}
}