github.com/git-chglog/git-chglog@v0.15.5-0.20240126074033-6a6993d52d69/chglog_test.go (about)

     1  package chglog
     2  
     3  import (
     4  	"bytes"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	gitcmd "github.com/tsuyoshiwada/go-gitcmd"
    13  )
    14  
    15  var (
    16  	cwd                string
    17  	testRepoRoot       = ".tmp"
    18  	internalTimeFormat = "2006-01-02 15:04:05"
    19  )
    20  
    21  type commitFunc = func(date, subject, body string)
    22  type tagFunc = func(name string)
    23  
    24  func TestMain(m *testing.M) {
    25  	cwd, _ = os.Getwd()
    26  	cleanup()
    27  	code := m.Run()
    28  	cleanup()
    29  	os.Exit(code)
    30  }
    31  
    32  func setup(dir string, setupRepo func(commitFunc, tagFunc, gitcmd.Client)) {
    33  	testDir := filepath.Join(cwd, testRepoRoot, dir)
    34  
    35  	_ = os.RemoveAll(testDir)
    36  	_ = os.MkdirAll(testDir, os.ModePerm)
    37  	_ = os.Chdir(testDir)
    38  
    39  	loc, _ := time.LoadLocation("UTC")
    40  	time.Local = loc
    41  
    42  	git := gitcmd.New(nil)
    43  	_, _ = git.Exec("init")
    44  	_, _ = git.Exec("config", "user.name", "test_user")
    45  	_, _ = git.Exec("config", "user.email", "test@example.com")
    46  
    47  	var commit = func(date, subject, body string) {
    48  		msg := subject
    49  		if body != "" {
    50  			msg += "\n\n" + body
    51  		}
    52  		t, _ := time.Parse(internalTimeFormat, date)
    53  		d := t.Format("Mon Jan 2 15:04:05 2006 +0000")
    54  		_, _ = git.Exec("commit", "--allow-empty", "--date", d, "-m", msg)
    55  	}
    56  
    57  	var tag = func(name string) {
    58  		_, _ = git.Exec("tag", name)
    59  	}
    60  
    61  	setupRepo(commit, tag, git)
    62  
    63  	_ = os.Chdir(cwd)
    64  }
    65  
    66  func cleanup() {
    67  	_ = os.Chdir(cwd)
    68  	_ = os.RemoveAll(filepath.Join(cwd, testRepoRoot))
    69  }
    70  
    71  func TestGeneratorNotFoundTags(t *testing.T) {
    72  	assert := assert.New(t)
    73  	testName := "not_found"
    74  
    75  	setup(testName, func(commit commitFunc, _ tagFunc, _ gitcmd.Client) {
    76  		commit("2018-01-01 00:00:00", "feat(*): New feature", "")
    77  	})
    78  
    79  	gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
    80  		&Config{
    81  			Bin:        "git",
    82  			WorkingDir: filepath.Join(testRepoRoot, testName),
    83  			Template:   filepath.Join(cwd, "testdata", testName+".md"),
    84  			Info: &Info{
    85  				RepositoryURL: "https://github.com/git-chglog/git-chglog",
    86  			},
    87  			Options: &Options{},
    88  		})
    89  
    90  	buf := &bytes.Buffer{}
    91  	err := gen.Generate(buf, "")
    92  	expected := strings.TrimSpace(buf.String())
    93  
    94  	assert.Error(err)
    95  	assert.Contains(err.Error(), "git-tag does not exist")
    96  	assert.Equal("", expected)
    97  }
    98  
    99  func TestGeneratorNotFoundCommits(t *testing.T) {
   100  	assert := assert.New(t)
   101  	testName := "not_found"
   102  
   103  	setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
   104  		commit("2018-01-01 00:00:00", "feat(*): New feature", "")
   105  		tag("1.0.0")
   106  	})
   107  
   108  	gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
   109  		&Config{
   110  			Bin:        "git",
   111  			WorkingDir: filepath.Join(testRepoRoot, testName),
   112  			Template:   filepath.Join(cwd, "testdata", testName+".md"),
   113  			Info: &Info{
   114  				RepositoryURL: "https://github.com/git-chglog/git-chglog",
   115  			},
   116  			Options: &Options{},
   117  		})
   118  
   119  	buf := &bytes.Buffer{}
   120  	err := gen.Generate(buf, "foo")
   121  	expected := strings.TrimSpace(buf.String())
   122  
   123  	assert.Error(err)
   124  	assert.Equal("", expected)
   125  }
   126  
   127  func TestGeneratorNotFoundCommitsOne(t *testing.T) {
   128  	assert := assert.New(t)
   129  	testName := "not_found"
   130  
   131  	setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
   132  		commit("2018-01-01 00:00:00", "chore(*): First commit", "")
   133  		tag("1.0.0")
   134  	})
   135  
   136  	gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
   137  		&Config{
   138  			Bin:        "git",
   139  			WorkingDir: filepath.Join(testRepoRoot, testName),
   140  			Template:   filepath.Join(cwd, "testdata", testName+".md"),
   141  			Info: &Info{
   142  				RepositoryURL: "https://github.com/git-chglog/git-chglog",
   143  			},
   144  			Options: &Options{
   145  				CommitFilters:        map[string][]string{},
   146  				CommitSortBy:         "Scope",
   147  				CommitGroupBy:        "Type",
   148  				CommitGroupSortBy:    "Title",
   149  				CommitGroupTitleMaps: map[string]string{},
   150  				HeaderPattern:        "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$",
   151  				HeaderPatternMaps: []string{
   152  					"Type",
   153  					"Scope",
   154  					"Subject",
   155  				},
   156  				IssuePrefix: []string{
   157  					"#",
   158  					"gh-",
   159  				},
   160  				RefActions:   []string{},
   161  				MergePattern: "^Merge pull request #(\\d+) from (.*)$",
   162  				MergePatternMaps: []string{
   163  					"Ref",
   164  					"Source",
   165  				},
   166  				RevertPattern: "^Revert \"([\\s\\S]*)\"$",
   167  				RevertPatternMaps: []string{
   168  					"Header",
   169  				},
   170  				NoteKeywords: []string{
   171  					"BREAKING CHANGE",
   172  				},
   173  			},
   174  		})
   175  
   176  	buf := &bytes.Buffer{}
   177  	err := gen.Generate(buf, "foo")
   178  	expected := strings.TrimSpace(buf.String())
   179  
   180  	assert.Error(err)
   181  	assert.Contains(err.Error(), "\"foo\" was not found")
   182  	assert.Equal("", expected)
   183  }
   184  
   185  func TestGeneratorWithTypeScopeSubject(t *testing.T) {
   186  	assert := assert.New(t)
   187  	testName := "type_scope_subject"
   188  
   189  	setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
   190  		commit("2018-01-01 00:00:00", "chore(*): First commit", "")
   191  		commit("2018-01-01 00:01:00", "feat(core): Add foo bar", "")
   192  		commit("2018-01-01 00:02:00", "docs(readme): Update usage #123", "")
   193  		tag("1.0.0")
   194  
   195  		commit("2018-01-02 00:00:00", "feat(parser): New some super options #333", "")
   196  		commit("2018-01-02 00:01:00", "Merge pull request #999 from tsuyoshiwada/patch-1", "")
   197  		commit("2018-01-02 00:02:00", "Merge pull request #1000 from tsuyoshiwada/patch-1", "")
   198  		commit("2018-01-02 00:03:00", "Revert \"feat(core): Add foo bar @mention and issue #987\"", "")
   199  		tag("1.1.0")
   200  
   201  		commit("2018-01-03 00:00:00", "feat(context): Online breaking change", "BREAKING CHANGE: Online breaking change message.")
   202  		commit("2018-01-03 00:01:00", "feat(router): Multiple breaking change", `This is body,
   203  
   204  BREAKING CHANGE:
   205  Multiple
   206  breaking
   207  change message.`)
   208  		tag("2.0.0-beta.0")
   209  
   210  		commit("2018-01-04 00:00:00", "refactor(context): gofmt", "")
   211  		commit("2018-01-04 00:01:00", "fix(core): Fix commit\n\nThis is body message.", "")
   212  	})
   213  
   214  	gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
   215  		&Config{
   216  			Bin:        "git",
   217  			WorkingDir: filepath.Join(testRepoRoot, testName),
   218  			Template:   filepath.Join(cwd, "testdata", testName+".md"),
   219  			Info: &Info{
   220  				Title:         "CHANGELOG Example",
   221  				RepositoryURL: "https://github.com/git-chglog/git-chglog",
   222  			},
   223  			Options: &Options{
   224  				Sort: "date",
   225  				CommitFilters: map[string][]string{
   226  					"Type": {
   227  						"feat",
   228  						"fix",
   229  					},
   230  				},
   231  				CommitSortBy:      "Scope",
   232  				CommitGroupBy:     "Type",
   233  				CommitGroupSortBy: "Title",
   234  				CommitGroupTitleMaps: map[string]string{
   235  					"feat": "Features",
   236  					"fix":  "Bug Fixes",
   237  				},
   238  				HeaderPattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$",
   239  				HeaderPatternMaps: []string{
   240  					"Type",
   241  					"Scope",
   242  					"Subject",
   243  				},
   244  				IssuePrefix: []string{
   245  					"#",
   246  					"gh-",
   247  				},
   248  				RefActions:   []string{},
   249  				MergePattern: "^Merge pull request #(\\d+) from (.*)$",
   250  				MergePatternMaps: []string{
   251  					"Ref",
   252  					"Source",
   253  				},
   254  				RevertPattern: "^Revert \"([\\s\\S]*)\"$",
   255  				RevertPatternMaps: []string{
   256  					"Header",
   257  				},
   258  				NoteKeywords: []string{
   259  					"BREAKING CHANGE",
   260  				},
   261  			},
   262  		})
   263  
   264  	buf := &bytes.Buffer{}
   265  	err := gen.Generate(buf, "")
   266  	expected := strings.TrimSpace(buf.String())
   267  
   268  	assert.Nil(err)
   269  	assert.Equal(`<a name="unreleased"></a>
   270  ## [Unreleased]
   271  
   272  ### Bug Fixes
   273  - **core:** Fix commit
   274  
   275  
   276  <a name="2.0.0-beta.0"></a>
   277  ## [2.0.0-beta.0] - 2018-01-03
   278  ### Features
   279  - **context:** Online breaking change
   280  - **router:** Multiple breaking change
   281  
   282  ### BREAKING CHANGE
   283  
   284  Multiple
   285  breaking
   286  change message.
   287  
   288  Online breaking change message.
   289  
   290  
   291  <a name="1.1.0"></a>
   292  ## [1.1.0] - 2018-01-02
   293  ### Features
   294  - **parser:** New some super options #333
   295  
   296  ### Reverts
   297  - feat(core): Add foo bar @mention and issue #987
   298  
   299  ### Pull Requests
   300  - Merge pull request #1000 from tsuyoshiwada/patch-1
   301  - Merge pull request #999 from tsuyoshiwada/patch-1
   302  
   303  
   304  <a name="1.0.0"></a>
   305  ## 1.0.0 - 2018-01-01
   306  ### Features
   307  - **core:** Add foo bar
   308  
   309  
   310  [Unreleased]: https://github.com/git-chglog/git-chglog/compare/2.0.0-beta.0...HEAD
   311  [2.0.0-beta.0]: https://github.com/git-chglog/git-chglog/compare/1.1.0...2.0.0-beta.0
   312  [1.1.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...1.1.0`, expected)
   313  }
   314  
   315  func TestGeneratorWithNextTag(t *testing.T) {
   316  	assert := assert.New(t)
   317  	testName := "type_scope_subject"
   318  
   319  	setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
   320  		commit("2018-01-01 00:00:00", "feat(core): version 1.0.0", "")
   321  		tag("1.0.0")
   322  
   323  		commit("2018-02-01 00:00:00", "feat(core): version 2.0.0", "")
   324  		tag("2.0.0")
   325  
   326  		commit("2018-03-01 00:00:00", "feat(core): version 3.0.0", "")
   327  	})
   328  
   329  	gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
   330  		&Config{
   331  			Bin:        "git",
   332  			WorkingDir: filepath.Join(testRepoRoot, testName),
   333  			Template:   filepath.Join(cwd, "testdata", testName+".md"),
   334  			Info: &Info{
   335  				Title:         "CHANGELOG Example",
   336  				RepositoryURL: "https://github.com/git-chglog/git-chglog",
   337  			},
   338  			Options: &Options{
   339  				Sort:    "date",
   340  				NextTag: "3.0.0",
   341  				CommitFilters: map[string][]string{
   342  					"Type": {
   343  						"feat",
   344  					},
   345  				},
   346  				CommitSortBy:      "Scope",
   347  				CommitGroupBy:     "Type",
   348  				CommitGroupSortBy: "Title",
   349  				CommitGroupTitleMaps: map[string]string{
   350  					"feat": "Features",
   351  				},
   352  				HeaderPattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$",
   353  				HeaderPatternMaps: []string{
   354  					"Type",
   355  					"Scope",
   356  					"Subject",
   357  				},
   358  			},
   359  		})
   360  
   361  	buf := &bytes.Buffer{}
   362  	err := gen.Generate(buf, "")
   363  	expected := strings.TrimSpace(buf.String())
   364  
   365  	assert.Nil(err)
   366  	assert.Equal(`<a name="unreleased"></a>
   367  ## [Unreleased]
   368  
   369  
   370  <a name="3.0.0"></a>
   371  ## [3.0.0] - 2018-03-01
   372  ### Features
   373  - **core:** version 3.0.0
   374  
   375  
   376  <a name="2.0.0"></a>
   377  ## [2.0.0] - 2018-02-01
   378  ### Features
   379  - **core:** version 2.0.0
   380  
   381  
   382  <a name="1.0.0"></a>
   383  ## 1.0.0 - 2018-01-01
   384  ### Features
   385  - **core:** version 1.0.0
   386  
   387  
   388  [Unreleased]: https://github.com/git-chglog/git-chglog/compare/3.0.0...HEAD
   389  [3.0.0]: https://github.com/git-chglog/git-chglog/compare/2.0.0...3.0.0
   390  [2.0.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...2.0.0`, expected)
   391  
   392  	buf = &bytes.Buffer{}
   393  	err = gen.Generate(buf, "3.0.0")
   394  	expected = strings.TrimSpace(buf.String())
   395  
   396  	assert.Nil(err)
   397  	assert.Equal(`<a name="unreleased"></a>
   398  ## [Unreleased]
   399  
   400  
   401  <a name="3.0.0"></a>
   402  ## [3.0.0] - 2018-03-01
   403  ### Features
   404  - **core:** version 3.0.0
   405  
   406  
   407  [Unreleased]: https://github.com/git-chglog/git-chglog/compare/3.0.0...HEAD
   408  [3.0.0]: https://github.com/git-chglog/git-chglog/compare/2.0.0...3.0.0`, expected)
   409  }
   410  
   411  func TestGeneratorWithTagFiler(t *testing.T) {
   412  	assert := assert.New(t)
   413  	testName := "type_scope_subject"
   414  
   415  	setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
   416  		commit("2018-01-01 00:00:00", "feat(core): version dev-1.0.0", "")
   417  		tag("dev-1.0.0")
   418  
   419  		commit("2018-02-01 00:00:00", "feat(core): version v1.0.0", "")
   420  		tag("v1.0.0")
   421  	})
   422  
   423  	gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
   424  		&Config{
   425  			Bin:        "git",
   426  			WorkingDir: filepath.Join(testRepoRoot, testName),
   427  			Template:   filepath.Join(cwd, "testdata", testName+".md"),
   428  			Info: &Info{
   429  				Title:         "CHANGELOG Example",
   430  				RepositoryURL: "https://github.com/git-chglog/git-chglog",
   431  			},
   432  			Options: &Options{
   433  				TagFilterPattern: "^v",
   434  				CommitFilters: map[string][]string{
   435  					"Type": {
   436  						"feat",
   437  					},
   438  				},
   439  				CommitSortBy:      "Scope",
   440  				CommitGroupBy:     "Type",
   441  				CommitGroupSortBy: "Title",
   442  				CommitGroupTitleMaps: map[string]string{
   443  					"feat": "Features",
   444  				},
   445  				HeaderPattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$",
   446  				HeaderPatternMaps: []string{
   447  					"Type",
   448  					"Scope",
   449  					"Subject",
   450  				},
   451  			},
   452  		})
   453  
   454  	buf := &bytes.Buffer{}
   455  	err := gen.Generate(buf, "")
   456  	expected := strings.TrimSpace(buf.String())
   457  
   458  	assert.Nil(err)
   459  	assert.Equal(`<a name="unreleased"></a>
   460  ## [Unreleased]
   461  
   462  
   463  <a name="v1.0.0"></a>
   464  ## v1.0.0 - 2018-02-01
   465  ### Features
   466  - **core:** version v1.0.0
   467  - **core:** version dev-1.0.0
   468  
   469  
   470  [Unreleased]: https://github.com/git-chglog/git-chglog/compare/v1.0.0...HEAD`, expected)
   471  
   472  }
   473  
   474  func TestGeneratorWithTrimmedBody(t *testing.T) {
   475  	assert := assert.New(t)
   476  	testName := "trimmed_body"
   477  
   478  	setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
   479  		commit("2018-01-01 00:00:00", "feat: single line commit", "")
   480  		commit("2018-01-01 00:01:00", "feat: multi-line commit", `
   481  More details about the change and why it went in.
   482  
   483  BREAKING CHANGE:
   484  
   485  When using .TrimmedBody Notes are not included and can only appear in the Notes section.
   486  
   487  Signed-off-by: First Last <first.last@mail.com>
   488  
   489  Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>`)
   490  
   491  		commit("2018-01-01 00:00:00", "feat: another single line commit", "")
   492  		tag("1.0.0")
   493  	})
   494  
   495  	gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
   496  		&Config{
   497  			Bin:        "git",
   498  			WorkingDir: filepath.Join(testRepoRoot, testName),
   499  			Template:   filepath.Join(cwd, "testdata", testName+".md"),
   500  			Info: &Info{
   501  				Title:         "CHANGELOG Example",
   502  				RepositoryURL: "https://github.com/git-chglog/git-chglog",
   503  			},
   504  			Options: &Options{
   505  				CommitFilters: map[string][]string{
   506  					"Type": {
   507  						"feat",
   508  					},
   509  				},
   510  				CommitSortBy:      "Scope",
   511  				CommitGroupBy:     "Type",
   512  				CommitGroupSortBy: "Title",
   513  				CommitGroupTitleMaps: map[string]string{
   514  					"feat": "Features",
   515  				},
   516  				HeaderPattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$",
   517  				HeaderPatternMaps: []string{
   518  					"Type",
   519  					"Scope",
   520  					"Subject",
   521  				},
   522  				NoteKeywords: []string{
   523  					"BREAKING CHANGE",
   524  				},
   525  			},
   526  		})
   527  
   528  	buf := &bytes.Buffer{}
   529  	err := gen.Generate(buf, "")
   530  	expected := strings.TrimSpace(buf.String())
   531  
   532  	assert.Nil(err)
   533  	assert.Equal(`<a name="unreleased"></a>
   534  ## [Unreleased]
   535  
   536  
   537  <a name="1.0.0"></a>
   538  ## 1.0.0 - 2018-01-01
   539  ### Features
   540  - another single line commit
   541  - multi-line commit
   542    More details about the change and why it went in.
   543  - single line commit
   544  
   545  ### BREAKING CHANGE
   546  
   547  When using .TrimmedBody Notes are not included and can only appear in the Notes section.
   548  
   549  
   550  [Unreleased]: https://github.com/git-chglog/git-chglog/compare/1.0.0...HEAD`, expected)
   551  }
   552  
   553  func TestGeneratorWithSprig(t *testing.T) {
   554  	assert := assert.New(t)
   555  	testName := "with_sprig"
   556  
   557  	setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
   558  		commit("2018-01-01 00:00:00", "feat(core): version 1.0.0", "")
   559  		tag("1.0.0")
   560  
   561  		commit("2018-02-01 00:00:00", "feat(core): version 2.0.0", "")
   562  		tag("2.0.0")
   563  
   564  		commit("2018-03-01 00:00:00", "feat(core): version 3.0.0", "")
   565  	})
   566  
   567  	gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
   568  		&Config{
   569  			Bin:        "git",
   570  			WorkingDir: filepath.Join(testRepoRoot, testName),
   571  			Template:   filepath.Join(cwd, "testdata", testName+".md"),
   572  			Info: &Info{
   573  				Title:         "CHANGELOG Example",
   574  				RepositoryURL: "https://github.com/git-chglog/git-chglog",
   575  			},
   576  			Options: &Options{
   577  				Sort:    "date",
   578  				NextTag: "3.0.0",
   579  				CommitFilters: map[string][]string{
   580  					"Type": {
   581  						"feat",
   582  					},
   583  				},
   584  				CommitSortBy:      "Scope",
   585  				CommitGroupBy:     "Type",
   586  				CommitGroupSortBy: "Title",
   587  				CommitGroupTitleMaps: map[string]string{
   588  					"feat": "Features",
   589  				},
   590  				HeaderPattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$",
   591  				HeaderPatternMaps: []string{
   592  					"Type",
   593  					"Scope",
   594  					"Subject",
   595  				},
   596  			},
   597  		})
   598  
   599  	buf := &bytes.Buffer{}
   600  	err := gen.Generate(buf, "")
   601  	expected := strings.TrimSpace(buf.String())
   602  
   603  	assert.Nil(err)
   604  	assert.Equal(`My Changelog
   605  <a name="unreleased"></a>
   606  ## [Unreleased]
   607  
   608  
   609  <a name="3.0.0"></a>
   610  ## [3.0.0] - 2018-03-01
   611  ### Features
   612  - **CORE:** version 3.0.0
   613  
   614  
   615  <a name="2.0.0"></a>
   616  ## [2.0.0] - 2018-02-01
   617  ### Features
   618  - **CORE:** version 2.0.0
   619  
   620  
   621  <a name="1.0.0"></a>
   622  ## 1.0.0 - 2018-01-01
   623  ### Features
   624  - **CORE:** version 1.0.0
   625  
   626  
   627  [Unreleased]: https://github.com/git-chglog/git-chglog/compare/3.0.0...HEAD
   628  [3.0.0]: https://github.com/git-chglog/git-chglog/compare/2.0.0...3.0.0
   629  [2.0.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...2.0.0`, expected)
   630  
   631  }