Coverage for tests/test_end_to_end.py: 100.00%

83 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-02 00:26 +0200

1"""End-to-end tests.""" 

2 

3from __future__ import annotations 

4 

5import re 

6from typing import TYPE_CHECKING 

7from urllib.parse import urlsplit, urlunsplit 

8 

9import pytest 

10 

11from git_changelog import Changelog 

12from git_changelog.cli import build_and_render 

13from git_changelog.commit import AngularConvention 

14from git_changelog.templates import get_template 

15from git_changelog.versioning import bump_semver 

16 

17if TYPE_CHECKING: 

18 from pathlib import Path 

19 

20 from tests.helpers import GitRepo 

21 

22VERSIONS = ("0.1.0", "0.2.0", "0.2.1", "1.0.0", "1.1.0", "") 

23VERSIONS_V = ("v0.1.0", "v0.2.0", "v0.2.1", "v1.0.0", "v1.1.0", "") 

24KEEP_A_CHANGELOG = get_template("keepachangelog") 

25 

26 

27@pytest.mark.parametrize("repo", [VERSIONS, VERSIONS_V], indirect=True) 

28def test_bumping_latest(repo: GitRepo) -> None: 

29 """Bump latest version. 

30 

31 Parameters: 

32 repo: Temporary Git repository (fixture). 

33 """ 

34 changelog = Changelog(repo.path, convention=AngularConvention, bump="auto") 

35 # features, no breaking changes: minor bumped 

36 assert changelog.versions_list[0].planned_tag is not None 

37 assert changelog.versions_list[0].planned_tag.lstrip("v") == bump_semver( 

38 VERSIONS[-2], 

39 "minor", 

40 ) 

41 rendered = KEEP_A_CHANGELOG.render(changelog=changelog) 

42 assert "Unreleased" not in rendered 

43 

44 

45@pytest.mark.parametrize("repo", [VERSIONS, VERSIONS_V], indirect=True) 

46def test_not_bumping_latest(repo: GitRepo) -> None: 

47 """Don't bump latest version. 

48 

49 Parameters: 

50 repo: Temporary Git repository (fixture). 

51 """ 

52 changelog = Changelog(repo.path, convention=AngularConvention, bump=None) 

53 assert changelog.versions_list[0].planned_tag is None 

54 rendered = KEEP_A_CHANGELOG.render(changelog=changelog) 

55 assert "Unreleased" in rendered 

56 

57 

58@pytest.mark.parametrize("repo", [VERSIONS, VERSIONS_V], indirect=True) 

59def test_rendering_custom_sections(repo: GitRepo) -> None: 

60 """Render custom sections. 

61 

62 Parameters: 

63 repo: Temporary Git repository (fixture). 

64 """ 

65 changelog = Changelog(repo.path, convention=AngularConvention, sections=["feat"]) 

66 rendered = KEEP_A_CHANGELOG.render(changelog=changelog) 

67 for section_type, section_title in AngularConvention.TYPES.items(): 

68 if section_type != "feat": 

69 assert section_title not in rendered 

70 

71 

72@pytest.mark.parametrize("repo", [VERSIONS, VERSIONS_V], indirect=True) 

73def test_rendering_in_place(repo: GitRepo, tmp_path: Path) -> None: 

74 """Render changelog in-place. 

75 

76 Parameters: 

77 repo: Temporary Git repository (fixture). 

78 tmp_path: A temporary path to write the changelog into. 

79 """ 

80 output = tmp_path.joinpath("changelog.md") 

81 _, rendered = build_and_render( 

82 str(repo.path), 

83 convention="angular", 

84 bump=None, 

85 output=output.as_posix(), 

86 template="keepachangelog", 

87 ) 

88 assert len(re.findall("<!-- insertion marker -->", rendered)) == 2 

89 assert "Unreleased" in rendered 

90 latest_tag = "91.6.14" 

91 assert latest_tag not in rendered 

92 repo.git("tag", latest_tag) 

93 build_and_render( 

94 str(repo.path), 

95 convention="angular", 

96 bump="auto", 

97 output=output.as_posix(), 

98 template="keepachangelog", 

99 in_place=True, 

100 ) 

101 rendered = output.read_text() 

102 assert len(re.findall("<!-- insertion marker -->", rendered)) == 1 

103 assert "Unreleased" not in rendered 

104 assert latest_tag in rendered 

105 repo.git("tag", "-d", latest_tag) 

106 

107 

108@pytest.mark.parametrize("repo", [VERSIONS, VERSIONS_V], indirect=True) 

109def test_no_duplicate_rendering(repo: GitRepo, tmp_path: Path) -> None: 

110 """Render changelog in-place, and check for duplicate entries. 

111 

112 Parameters: 

113 repo: Temporary Git repository (fixture). 

114 tmp_path: A temporary path to write the changelog into. 

115 """ 

116 output = tmp_path.joinpath("changelog.md") 

117 _, rendered = build_and_render( 

118 str(repo.path), 

119 convention="angular", 

120 bump="auto", 

121 output=output.as_posix(), 

122 template="keepachangelog", 

123 ) 

124 

125 # When bump_latest is True, there's only one insertion marker 

126 assert len(re.findall("<!-- insertion marker -->", rendered)) == 1 

127 latest_tag = "1.2.0" 

128 assert latest_tag in rendered 

129 

130 rendered = output.read_text() 

131 # The latest tag should appear exactly three times in the changelog 

132 assert rendered.count(latest_tag) == 3 

133 

134 # Without tagging a new version, we should get an error 

135 with pytest.raises(ValueError, match=r"Version .* already in changelog"): 

136 build_and_render( 

137 str(repo.path), 

138 convention="angular", 

139 bump="auto", 

140 output=output.as_posix(), 

141 template="keepachangelog", 

142 in_place=True, 

143 ) 

144 

145 rendered = output.read_text() 

146 # The latest tag should still appear exactly three times in the changelog 

147 assert rendered.count(latest_tag) == 3 

148 

149 

150@pytest.mark.parametrize("repo", [VERSIONS, VERSIONS_V], indirect=True) 

151def test_removing_credentials_from_remotes(repo: GitRepo) -> None: 

152 """Remove credentials from remotes. 

153 

154 Parameters: 

155 repo: Temporary Git repository (fixture). 

156 """ 

157 credentials = [ 

158 "ghp_abcdefghijklmnOPQRSTUVWXYZ0123456789", 

159 "ghs_abcdefghijklmnOPQRSTUVWXYZ0123456789", 

160 "github_pat_abcdefgOPQRS0123456789_abcdefghijklmnOPQRSTUVWXYZ0123456789abcdefgOPQRS0123456789A", 

161 "user:password", 

162 ] 

163 for creds in credentials: 

164 repo.git("remote", "set-url", "origin", f"https://{creds}@github.com:example/example") 

165 changelog = Changelog(repo.path) 

166 assert creds not in changelog.remote_url 

167 assert urlunsplit(urlsplit(changelog.remote_url)) == changelog.remote_url 

168 

169 

170@pytest.mark.parametrize("repo", [VERSIONS, VERSIONS_V], indirect=True) 

171def test_filter_commits_option(repo: GitRepo) -> None: 

172 """Filter commit by revision-range argument. 

173 

174 Parameters: 

175 repo: Temporary Git repository (fixture). 

176 """ 

177 is_tag_with_v = repo.git("tag").split("\n")[0].startswith("v") 

178 

179 range = "1.0.0.." 

180 expected = ["", "1.1.0"] 

181 if is_tag_with_v: 

182 range = "v1.0.0.." 

183 expected = ["", "v1.1.0"] 

184 

185 changelog = Changelog(repo.path, filter_commits=range) 

186 taglist = [version.tag for version in changelog.versions_list] 

187 

188 assert taglist == expected 

189 

190 err_msg = "Maybe the provided git-log revision-range is not valid" 

191 with pytest.raises(ValueError, match=err_msg): 

192 changelog = Changelog(repo.path, filter_commits="invalid")