Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions cfg/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package cfg

import (
"os"
"path"
"reflect"
"testing"
)
Expand Down Expand Up @@ -63,3 +65,31 @@ func Test_loadConfig(t *testing.T) {
})
}
}

func TestLoadConfig(t *testing.T) {
dir := t.TempDir()
content := "requireBranch: main\nbefore:\n - command: echo\n args:\n - hello world\n"
if err := os.WriteFile(path.Join(dir, defaultConfigFile), []byte(content), 0644); err != nil {
t.Fatal(err)
}

got, err := LoadConfig(dir)
if err != nil {
t.Fatalf("LoadConfig() error = %v", err)
}
want := SinceConfig{RequireBranch: "main", Before: []Hook{{Command: "echo", Args: []string{"hello world"}}}}
if !reflect.DeepEqual(got, want) {
t.Errorf("LoadConfig() got = %v, want %v", got, want)
}
}

func TestLoadConfig_missingFile(t *testing.T) {
// a directory with no since.yaml should yield an empty config, not an error
got, err := LoadConfig(t.TempDir())
if err != nil {
t.Fatalf("LoadConfig() error = %v", err)
}
if !reflect.DeepEqual(got, SinceConfig{}) {
t.Errorf("LoadConfig() got = %v, want empty config", got)
}
}
33 changes: 33 additions & 0 deletions changelog/changelog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"os"
"path"
"reflect"
"strings"
"testing"
"time"
)
Expand Down Expand Up @@ -304,6 +305,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
}
}

func TestInitChangelog(t *testing.T) {
repoDir := createTestRepo(t)
// add an unreleased commit so there are changes to render
commitChange(t, repoDir, "README.md", "unreleased\r\n", "feat: unreleased change", time.Now())

changelogFile := path.Join(repoDir, "CHANGELOG.md")

updated, err := InitChangelog(cfg.SinceConfig{}, vcs.CommitConfig{}, changelogFile, vcs.TagOrderSemver, repoDir)
if err != nil {
t.Fatalf("InitChangelog() error = %v", err)
}

// the rendered changelog should retain the boilerplate header and contain
// at least one version section
if !strings.HasPrefix(updated, "# Changelog") {
t.Errorf("InitChangelog() output missing boilerplate header, got: %q", updated)
}
if !strings.Contains(updated, "## [") {
t.Errorf("InitChangelog() output missing version section, got: %q", updated)
}

// the file written to disk should match the returned content (with the
// trailing newline WriteChangelog appends)
onDisk, err := os.ReadFile(changelogFile)
if err != nil {
t.Fatal(err)
}
if string(onDisk) != updated+"\n" {
t.Errorf("InitChangelog() file content = %q, want %q", string(onDisk), updated+"\n")
}
}

// createTestRepo creates a test repo with two tags:
// 0.0.1 and 0.1.0
// The first tag is created 10 seconds before the second tag.
Expand Down
39 changes: 39 additions & 0 deletions changelog/errors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package changelog

import "testing"

func TestNoChangesError_Error(t *testing.T) {
tests := []struct {
name string
err NoChangesError
want string
}{
{
name: "excluded commits with start tag",
err: NoChangesError{StartTag: "0.1.0", ExcludedCount: 3},
want: "no eligible commits since 0.1.0 — 3 commit(s) were excluded by ignore patterns in since.yaml",
},
{
name: "excluded commits without start tag",
err: NoChangesError{ExcludedCount: 2},
want: "no eligible commits found — 2 commit(s) were excluded by ignore patterns in since.yaml",
},
{
name: "start tag with no exclusions",
err: NoChangesError{StartTag: "1.2.3"},
want: "no commits since 1.2.3",
},
{
name: "no start tag and no exclusions",
err: NoChangesError{},
want: "no commits found",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.err.Error(); got != tt.want {
t.Errorf("Error() = %q, want %q", got, tt.want)
}
})
}
}
65 changes: 65 additions & 0 deletions changelog/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,71 @@ func TestParseChangelog_withHeader(t *testing.T) {
}
}

func TestParseChangelog_nonExistent(t *testing.T) {
_, err := ParseChangelog("/nonexistent/CHANGELOG.md", "1.0.0", false)
if err == nil {
t.Error("ParseChangelog() expected error for non-existent file")
}
}

func Test_readChanges_versionNotFound(t *testing.T) {
lines := []string{
"# Changelog",
"",
"## [1.0.0] - 2024-01-01",
"- feat: foo",
}
_, err := readChanges(lines, "9.9.9", false)
if err == nil {
t.Fatal("readChanges() expected error for missing version")
}
want := "could not find version 9.9.9 in changelog"
if err.Error() != want {
t.Errorf("readChanges() error = %q, want %q", err.Error(), want)
}
}

func Test_readChanges_noVersionSections(t *testing.T) {
lines := []string{
"# Changelog",
"",
"All notable changes are documented here.",
}
_, err := readChanges(lines, "", false)
if err == nil {
t.Fatal("readChanges() expected error when no version sections present")
}
want := "changelog contains no version sections"
if err.Error() != want {
t.Errorf("readChanges() error = %q, want %q", err.Error(), want)
}
}

func Test_readChanges_lastVersionToEndOfFile(t *testing.T) {
// trailing empty string mirrors ReadFile splitting a file that ends in a
// newline; readChanges relies on it to bound the final section
lines := []string{
"# Changelog",
"",
"## [1.0.0] - 2024-01-01",
"### Added",
"- feat: foo",
"",
"## [0.9.0] - 2023-12-01",
"### Fixed",
"- fix: bar",
"",
}
got, err := readChanges(lines, "0.9.0", true)
if err != nil {
t.Fatalf("readChanges() error = %v", err)
}
want := []string{"## [0.9.0] - 2023-12-01", "### Fixed", "- fix: bar"}
if !reflect.DeepEqual(got, want) {
t.Errorf("readChanges() = %v, want %v", got, want)
}
}

func Test_readChanges_firstVersion(t *testing.T) {
lines := []string{
"# Changelog",
Expand Down
52 changes: 51 additions & 1 deletion semver/versions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ limitations under the License.

package semver

import "testing"
import (
"os"
"testing"
"time"

"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/release-tools/since/vcs"
)

func TestGetNextVersion(t *testing.T) {
type args struct {
Expand Down Expand Up @@ -75,6 +83,48 @@ func TestGetNextVersion(t *testing.T) {
}
}

// TestGetCurrentVersion verifies that a "v" prefixed tag is reported with the
// prefix stripped and vPrefix set. Note: vcs caches the latest tag in a
// package-level variable that this package cannot reset, so this test performs
// a single repository lookup to avoid cross-test contamination.
func TestGetCurrentVersion(t *testing.T) {
repoDir := t.TempDir()

repo, err := git.PlainInit(repoDir, false)
if err != nil {
t.Fatal(err)
}
w, err := repo.Worktree()
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(repoDir+"/README.md", []byte("hello"), 0644); err != nil {
t.Fatal(err)
}
if _, err := w.Add("README.md"); err != nil {
t.Fatal(err)
}
sig := &object.Signature{Name: "user", Email: "user@example.com", When: time.Now()}
c, err := w.Commit("feat: first", &git.CommitOptions{Author: sig, Committer: sig})
if err != nil {
t.Fatal(err)
}
if _, err := repo.CreateTag("v2.3.4", c, nil); err != nil {
t.Fatal(err)
}

version, vPrefix, err := GetCurrentVersion(repoDir, vcs.TagOrderSemver)
if err != nil {
t.Fatalf("GetCurrentVersion() error = %v", err)
}
if version != "2.3.4" {
t.Errorf("GetCurrentVersion() version = %q, want %q", version, "2.3.4")
}
if !vPrefix {
t.Errorf("GetCurrentVersion() vPrefix = %v, want true", vPrefix)
}
}

func TestDetermineChangeType(t *testing.T) {
type args struct {
types []string
Expand Down
23 changes: 23 additions & 0 deletions vcs/operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,29 @@ func TestCheckBranch_wrongBranch(t *testing.T) {
}
}

func TestCheckBranch_matchingBranch(t *testing.T) {
repoDir := createTestRepo(t)

// resolve the repo's actual current branch so the test does not depend on
// whether go-git initialises HEAD as "master" or "main"
branch, err := getCurrentBranch(repoDir)
if err != nil {
t.Fatalf("getCurrentBranch() error = %v", err)
}

config := cfg.SinceConfig{RequireBranch: branch}
if err := CheckBranch(repoDir, config); err != nil {
t.Errorf("CheckBranch() on required branch error = %v", err)
}
}

func TestCheckBranch_invalidRepo(t *testing.T) {
config := cfg.SinceConfig{RequireBranch: "main"}
if err := CheckBranch(t.TempDir(), config); err == nil {
t.Error("CheckBranch() expected error for invalid repo")
}
}

func TestCommitChangelog(t *testing.T) {
repoDir := createTestRepo(t)

Expand Down
Loading