Skip to content

Commit 60aa9be

Browse files
committed
test: improve test coverage across core packages
Add tests for stringutil, convcommits, semver, vcs, and changelog packages covering key behaviours, edge cases, and error conditions.
1 parent 164d5cd commit 60aa9be

8 files changed

Lines changed: 823 additions & 0 deletions

File tree

changelog/read_test.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package changelog
2+
3+
import (
4+
"os"
5+
"path"
6+
"reflect"
7+
"testing"
8+
)
9+
10+
func TestResolveChangelogFile(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
dir string
14+
fileName string
15+
want string
16+
}{
17+
{
18+
name: "simple filename",
19+
dir: "/repo",
20+
fileName: "CHANGELOG.md",
21+
want: "/repo/CHANGELOG.md",
22+
},
23+
{
24+
name: "absolute path with forward slash",
25+
dir: "/repo",
26+
fileName: "/other/CHANGELOG.md",
27+
want: "/other/CHANGELOG.md",
28+
},
29+
}
30+
for _, tt := range tests {
31+
t.Run(tt.name, func(t *testing.T) {
32+
if got := ResolveChangelogFile(tt.dir, tt.fileName); got != tt.want {
33+
t.Errorf("ResolveChangelogFile() = %v, want %v", got, tt.want)
34+
}
35+
})
36+
}
37+
}
38+
39+
func TestReadFile(t *testing.T) {
40+
dir := t.TempDir()
41+
filePath := path.Join(dir, "test.md")
42+
err := os.WriteFile(filePath, []byte("line1\nline2\nline3"), 0644)
43+
if err != nil {
44+
t.Fatal(err)
45+
}
46+
47+
got, err := ReadFile(filePath)
48+
if err != nil {
49+
t.Fatalf("ReadFile() error = %v", err)
50+
}
51+
want := []string{"line1", "line2", "line3"}
52+
if !reflect.DeepEqual(got, want) {
53+
t.Errorf("ReadFile() = %v, want %v", got, want)
54+
}
55+
}
56+
57+
func TestReadFile_nonExistent(t *testing.T) {
58+
_, err := ReadFile("/nonexistent/file.md")
59+
if err == nil {
60+
t.Error("ReadFile() expected error for non-existent file")
61+
}
62+
}
63+
64+
func TestParseChangelog(t *testing.T) {
65+
dir := t.TempDir()
66+
filePath := path.Join(dir, "CHANGELOG.md")
67+
content := `# Changelog
68+
69+
## [1.0.0] - 2024-01-01
70+
### Added
71+
- feat: something new
72+
73+
## [0.9.0] - 2023-12-01
74+
### Fixed
75+
- fix: old bug
76+
`
77+
err := os.WriteFile(filePath, []byte(content), 0644)
78+
if err != nil {
79+
t.Fatal(err)
80+
}
81+
82+
got, err := ParseChangelog(filePath, "1.0.0", false)
83+
if err != nil {
84+
t.Fatalf("ParseChangelog() error = %v", err)
85+
}
86+
want := []string{"### Added", "- feat: something new"}
87+
if !reflect.DeepEqual(got, want) {
88+
t.Errorf("ParseChangelog() = %v, want %v", got, want)
89+
}
90+
}
91+
92+
func TestParseChangelog_withHeader(t *testing.T) {
93+
dir := t.TempDir()
94+
filePath := path.Join(dir, "CHANGELOG.md")
95+
content := `# Changelog
96+
97+
## [1.0.0] - 2024-01-01
98+
### Added
99+
- feat: something new
100+
101+
## [0.9.0] - 2023-12-01
102+
### Fixed
103+
- fix: old bug
104+
`
105+
err := os.WriteFile(filePath, []byte(content), 0644)
106+
if err != nil {
107+
t.Fatal(err)
108+
}
109+
110+
got, err := ParseChangelog(filePath, "1.0.0", true)
111+
if err != nil {
112+
t.Fatalf("ParseChangelog() error = %v", err)
113+
}
114+
if len(got) == 0 {
115+
t.Fatal("ParseChangelog() returned empty result")
116+
}
117+
if got[0] != "## [1.0.0] - 2024-01-01" {
118+
t.Errorf("ParseChangelog() first line = %v, want version header", got[0])
119+
}
120+
}
121+
122+
func Test_readChanges_firstVersion(t *testing.T) {
123+
lines := []string{
124+
"# Changelog",
125+
"",
126+
"## [1.0.0] - 2024-01-01",
127+
"### Added",
128+
"- feat: foo",
129+
"",
130+
"## [0.9.0] - 2023-12-01",
131+
"- fix: bar",
132+
}
133+
got := readChanges(lines, "", false)
134+
want := []string{"### Added", "- feat: foo"}
135+
if !reflect.DeepEqual(got, want) {
136+
t.Errorf("readChanges() = %v, want %v", got, want)
137+
}
138+
}

changelog/write_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package changelog
2+
3+
import (
4+
"os"
5+
"path"
6+
"testing"
7+
)
8+
9+
func TestWriteChangelog(t *testing.T) {
10+
dir := t.TempDir()
11+
filePath := path.Join(dir, "CHANGELOG.md")
12+
13+
content := "# Changelog\n\n## [1.0.0]\n- feat: foo\n"
14+
err := WriteChangelog(filePath, content)
15+
if err != nil {
16+
t.Fatalf("WriteChangelog() error = %v", err)
17+
}
18+
19+
got, err := os.ReadFile(filePath)
20+
if err != nil {
21+
t.Fatal(err)
22+
}
23+
// WriteChangelog appends a newline
24+
want := content + "\n"
25+
if string(got) != want {
26+
t.Errorf("WriteChangelog() file content = %q, want %q", string(got), want)
27+
}
28+
}
29+
30+
func TestWriteChangelog_overwrite(t *testing.T) {
31+
dir := t.TempDir()
32+
filePath := path.Join(dir, "CHANGELOG.md")
33+
34+
// write initial content
35+
err := os.WriteFile(filePath, []byte("old content"), 0644)
36+
if err != nil {
37+
t.Fatal(err)
38+
}
39+
40+
newContent := "# New Changelog"
41+
err = WriteChangelog(filePath, newContent)
42+
if err != nil {
43+
t.Fatalf("WriteChangelog() error = %v", err)
44+
}
45+
46+
got, err := os.ReadFile(filePath)
47+
if err != nil {
48+
t.Fatal(err)
49+
}
50+
want := newContent + "\n"
51+
if string(got) != want {
52+
t.Errorf("WriteChangelog() file content = %q, want %q", string(got), want)
53+
}
54+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package convcommits
2+
3+
import (
4+
"sort"
5+
"testing"
6+
)
7+
8+
func TestCategoriseByType_scopedCommits(t *testing.T) {
9+
commits := []string{"feat(api): add endpoint", "fix(ui): correct layout"}
10+
got := CategoriseByType(commits)
11+
12+
if len(got) != 2 {
13+
t.Fatalf("expected 2 categories, got %d", len(got))
14+
}
15+
if _, ok := got["feat"]; !ok {
16+
t.Errorf("expected 'feat' category, got keys: %v", got)
17+
}
18+
if _, ok := got["fix"]; !ok {
19+
t.Errorf("expected 'fix' category, got keys: %v", got)
20+
}
21+
}
22+
23+
func TestCategoriseByType_breakingChange(t *testing.T) {
24+
commits := []string{"feat!: breaking feature"}
25+
got := CategoriseByType(commits)
26+
27+
if _, ok := got["BREAKING CHANGE"]; !ok {
28+
t.Errorf("expected 'BREAKING CHANGE' category, got keys: %v", got)
29+
}
30+
}
31+
32+
func TestCategoriseByType_noPrefix(t *testing.T) {
33+
commits := []string{"some random commit message"}
34+
got := CategoriseByType(commits)
35+
36+
if _, ok := got[""]; !ok {
37+
t.Errorf("expected empty prefix category, got keys: %v", got)
38+
}
39+
}
40+
41+
func TestDetermineTypes(t *testing.T) {
42+
commits := []string{"feat: foo", "fix: bar", "feat: baz"}
43+
got := DetermineTypes(commits)
44+
sort.Strings(got)
45+
46+
want := []string{"feat", "fix"}
47+
sort.Strings(want)
48+
49+
if len(got) != len(want) {
50+
t.Fatalf("DetermineTypes() length = %d, want %d", len(got), len(want))
51+
}
52+
for i := range got {
53+
if got[i] != want[i] {
54+
t.Errorf("DetermineTypes()[%d] = %v, want %v", i, got[i], want[i])
55+
}
56+
}
57+
}

semver/versions_test_extra_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package semver
2+
3+
import "testing"
4+
5+
func TestGetNextVersion_withVPrefix(t *testing.T) {
6+
got := GetNextVersion("1.2.3", true, []string{"feat: new feature"})
7+
want := "v1.3.0"
8+
if got != want {
9+
t.Errorf("GetNextVersion() with vPrefix = %v, want %v", got, want)
10+
}
11+
}
12+
13+
func TestGetNextVersion_noChanges(t *testing.T) {
14+
got := GetNextVersion("1.2.3", false, []string{"unknown: something"})
15+
want := ""
16+
if got != want {
17+
t.Errorf("GetNextVersion() with no recognised changes = %v, want %v", got, want)
18+
}
19+
}
20+
21+
func TestDetermineChangeType_allPatchTypes(t *testing.T) {
22+
patchTypes := []string{"build", "chore", "ci", "docs", "fix", "refactor", "security", "style", "test"}
23+
for _, pt := range patchTypes {
24+
t.Run(pt, func(t *testing.T) {
25+
got := DetermineChangeType([]string{pt})
26+
if got != ComponentPatch {
27+
t.Errorf("DetermineChangeType(%v) = %v, want %v", pt, got, ComponentPatch)
28+
}
29+
})
30+
}
31+
}
32+
33+
func TestDetermineChangeType_none(t *testing.T) {
34+
got := DetermineChangeType([]string{"unknown"})
35+
if got != ComponentNone {
36+
t.Errorf("DetermineChangeType(unknown) = %v, want %v", got, ComponentNone)
37+
}
38+
}
39+
40+
func TestDetermineChangeType_majorTakesPrecedence(t *testing.T) {
41+
got := DetermineChangeType([]string{"feat", "BREAKING CHANGE", "fix"})
42+
if got != ComponentMajor {
43+
t.Errorf("DetermineChangeType() = %v, want %v", got, ComponentMajor)
44+
}
45+
}
46+
47+
func TestBumpVersion(t *testing.T) {
48+
tests := []struct {
49+
name string
50+
version string
51+
component Component
52+
want string
53+
}{
54+
{
55+
name: "bump major resets minor and patch",
56+
version: "1.5.9",
57+
component: ComponentMajor,
58+
want: "2.0.0",
59+
},
60+
{
61+
name: "bump minor resets patch",
62+
version: "1.5.9",
63+
component: ComponentMinor,
64+
want: "1.6.0",
65+
},
66+
{
67+
name: "bump patch only",
68+
version: "1.5.9",
69+
component: ComponentPatch,
70+
want: "1.5.10",
71+
},
72+
}
73+
for _, tt := range tests {
74+
t.Run(tt.name, func(t *testing.T) {
75+
if got := bumpVersion(tt.version, tt.component); got != tt.want {
76+
t.Errorf("bumpVersion() = %v, want %v", got, tt.want)
77+
}
78+
})
79+
}
80+
}

0 commit comments

Comments
 (0)