package releaseprep_test import ( "os" "path/filepath" "testing" "git.hrafn.xyz/aether/vociferate/internal/releaseprep" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) type PrepareSuite struct { suite.Suite rootDir string } func TestPrepareSuite(t *testing.T) { suite.Run(t, new(PrepareSuite)) } func (s *PrepareSuite) SetupTest() { s.rootDir = s.T().TempDir() versionDir := filepath.Join(s.rootDir, "internal", "releaseprep", "version") require.NoError(s.T(), os.MkdirAll(versionDir, 0o755)) require.NoError(s.T(), os.WriteFile( filepath.Join(versionDir, "version.go"), []byte("package version\n\nconst String = \"1.1.6\"\n"), 0o644, )) require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, "changelog.md"), []byte("# Changelog\n\n## [Unreleased]\n\n### Breaking\n\n### Added\n\n- New thing.\n\n### Fixed\n\n- Old thing.\n\n## [1.1.6] - 2017-12-20\n\n### Fixed\n\n- Historical note.\n"), 0o644, )) } func (s *PrepareSuite) TestPrepare_UpdatesVersionAndPromotesUnreleasedNotes() { err := releaseprep.Prepare(s.rootDir, "v1.1.7", "2026-03-20", releaseprep.Options{}) require.NoError(s.T(), err) versionBytes, err := os.ReadFile(filepath.Join(s.rootDir, "internal", "releaseprep", "version", "version.go")) require.NoError(s.T(), err) require.Equal(s.T(), "package version\n\nconst String = \"1.1.7\"\n", string(versionBytes)) changelogBytes, err := os.ReadFile(filepath.Join(s.rootDir, "changelog.md")) require.NoError(s.T(), err) require.Equal(s.T(), "# Changelog\n\n## [Unreleased]\n\n## [1.1.7] - 2026-03-20\n\n### Breaking\n\n### Added\n\n- New thing.\n\n### Fixed\n\n- Old thing.\n\n## [1.1.6] - 2017-12-20\n\n### Fixed\n\n- Historical note.\n", string(changelogBytes)) } func (s *PrepareSuite) TestPrepare_ReturnsErrorWhenUnreleasedSectionMissing() { require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, "changelog.md"), []byte("# Changelog\n\n## [1.1.6] - 2017-12-20\n"), 0o644, )) err := releaseprep.Prepare(s.rootDir, "1.1.7", "2026-03-20", releaseprep.Options{}) require.ErrorContains(s.T(), err, "unreleased section") } func (s *PrepareSuite) TestPrepare_ReturnsErrorWhenUnreleasedSectionIsEmpty() { require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, "changelog.md"), []byte("# Changelog\n\n## [Unreleased]\n\n## [1.1.6] - 2017-12-20\n"), 0o644, )) err := releaseprep.Prepare(s.rootDir, "1.1.7", "2026-03-20", releaseprep.Options{}) require.ErrorContains(s.T(), err, "unreleased section is empty") } func (s *PrepareSuite) TestRecommendedTag_UsesMajorBumpWhenBreakingHeadingExists() { tag, err := releaseprep.RecommendedTag(s.rootDir, releaseprep.Options{}) require.NoError(s.T(), err) require.Equal(s.T(), "v2.0.0", tag) } func (s *PrepareSuite) TestRecommendedTag_UsesPatchBumpForFixOnlyChanges() { require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, "changelog.md"), []byte("# Changelog\n\n## [Unreleased]\n\n### Fixed\n\n- Patch note.\n\n## [1.1.6] - 2017-12-20\n"), 0o644, )) tag, err := releaseprep.RecommendedTag(s.rootDir, releaseprep.Options{}) require.NoError(s.T(), err) require.Equal(s.T(), "v1.1.7", tag) } func (s *PrepareSuite) TestRecommendedTag_UsesMajorBumpWhenRemovedEntriesExist() { require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, "changelog.md"), []byte("# Changelog\n\n## [Unreleased]\n\n### Removed\n\n- Breaking removal.\n\n## [1.1.6] - 2017-12-20\n"), 0o644, )) tag, err := releaseprep.RecommendedTag(s.rootDir, releaseprep.Options{}) require.NoError(s.T(), err) require.Equal(s.T(), "v2.0.0", tag) } func (s *PrepareSuite) TestRecommendedTag_UsesMajorBumpWhenBreakingEntriesExist() { require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, "changelog.md"), []byte("# Changelog\n\n## [Unreleased]\n\n### Breaking\n\n- Changed API contract.\n\n### Changed\n\n- Updated defaults.\n\n## [1.1.6] - 2017-12-20\n"), 0o644, )) tag, err := releaseprep.RecommendedTag(s.rootDir, releaseprep.Options{}) require.NoError(s.T(), err) require.Equal(s.T(), "v2.0.0", tag) } func (s *PrepareSuite) TestPrepare_UsesCustomVersionFileAndPattern() { customVersionFile := filepath.Join("custom", "VERSION.txt") require.NoError(s.T(), os.MkdirAll(filepath.Join(s.rootDir, "custom"), 0o755)) require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, customVersionFile), []byte("VERSION=1.1.6\n"), 0o644, )) err := releaseprep.Prepare(s.rootDir, "1.1.8", "2026-03-20", releaseprep.Options{ VersionFile: customVersionFile, VersionPattern: `VERSION=([^\n]+)`, }) require.NoError(s.T(), err) versionBytes, err := os.ReadFile(filepath.Join(s.rootDir, customVersionFile)) require.NoError(s.T(), err) require.Equal(s.T(), "VERSION=1.1.8\n", string(versionBytes)) } func (s *PrepareSuite) TestPrepare_AllowsUnchangedVersionValue() { require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, "internal", "releaseprep", "version", "version.go"), []byte("package version\n\nconst String = \"1.1.6\"\n"), 0o644, )) err := releaseprep.Prepare(s.rootDir, "1.1.6", "2026-03-20", releaseprep.Options{}) require.NoError(s.T(), err) versionBytes, readErr := os.ReadFile(filepath.Join(s.rootDir, "internal", "releaseprep", "version", "version.go")) require.NoError(s.T(), readErr) require.Equal(s.T(), "package version\n\nconst String = \"1.1.6\"\n", string(versionBytes)) } func (s *PrepareSuite) TestRecommendedTag_UsesCustomVersionFileAndPattern() { customVersionFile := filepath.Join("custom", "VERSION.txt") require.NoError(s.T(), os.MkdirAll(filepath.Join(s.rootDir, "custom"), 0o755)) require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, customVersionFile), []byte("VERSION=2.3.4\n"), 0o644, )) require.NoError(s.T(), os.WriteFile( filepath.Join(s.rootDir, "changelog.md"), []byte("# Changelog\n\n## [Unreleased]\n\n### Added\n\n- Feature.\n\n## [2.3.4] - 2026-03-10\n"), 0o644, )) tag, err := releaseprep.RecommendedTag(s.rootDir, releaseprep.Options{ VersionFile: customVersionFile, VersionPattern: `VERSION=([^\n]+)`, }) require.NoError(s.T(), err) require.Equal(s.T(), "v2.4.0", tag) }