Coverage for tests / test_prepare_release.py: 100%
88 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-09 00:15 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-09 00:15 +0000
1from datetime import date 1abcdefg
2from pathlib import Path 1abcdefg
4import pytest 1abcdefg
5from typer.testing import CliRunner 1abcdefg
7from scripts.prepare_release import ( 1abcdefg
8 BumpType,
9 app,
10 bump_version,
11 get_release_notes_body,
12 update_release_notes,
13 update_version_file,
14)
16runner = CliRunner() 1abcdefg
19@pytest.mark.parametrize( 1abcdefg
20 ("current_version", "bump", "new_version"),
21 [
22 ("0.26.2", "major", "1.0.0"),
23 ("0.26.2", "minor", "0.27.0"),
24 ("0.26.2", "patch", "0.26.3"),
25 ],
26)
27def test_bump_version(current_version: str, bump: BumpType, new_version: str) -> None: 1abcdefg
28 assert bump_version(current_version, bump) == new_version 1abcdefg
31def test_update_version_file() -> None: 1abcdefg
32 content = '"""Typer."""\n\n__version__ = "0.26.2"\n' 1abcdefg
34 new_content = update_version_file(content, "0.26.3", Path("typer/__init__.py")) 1abcdefg
36 assert new_content == '"""Typer."""\n\n__version__ = "0.26.3"\n' 1abcdefg
39def test_update_version_file_requires_newer_version() -> None: 1abcdefg
40 content = '__version__ = "0.26.2"\n' 1abcdefg
42 with pytest.raises(RuntimeError, match="must be greater"): 1abcdefg
43 update_version_file(content, "0.26.2", Path("typer/__init__.py")) 1abcdefg
46def test_update_release_notes() -> None: 1abcdefg
47 content = """# Release Notes 1abcdefg
49## Latest Changes
51### Fixes
53* Fix something.
55## 0.26.2 (2026-05-27)
57### Fixes
59* Previous fix.
60"""
62 new_content = update_release_notes( 1abcdefg
63 content, "0.26.3", date(2026, 5, 28), Path("docs/release-notes.md")
64 )
66 assert ( 1abcdefg
67 new_content
68 == """# Release Notes
70## Latest Changes
72## 0.26.3 (2026-05-28)
74### Fixes
76* Fix something.
78## 0.26.2 (2026-05-27)
80### Fixes
82* Previous fix.
83"""
84 )
87def test_update_release_notes_rejects_existing_version() -> None: 1abcdefg
88 content = """# Release Notes 1abcdefg
90## Latest Changes
92## 0.26.3 (2026-05-28)
93"""
95 with pytest.raises(RuntimeError, match="already contain"): 1abcdefg
96 update_release_notes( 1abcdefg
97 content, "0.26.3", date(2026, 5, 28), Path("docs/release-notes.md")
98 )
101def test_get_release_notes_body_with_dated_heading() -> None: 1abcdefg
102 content = """# Release Notes 1abcdefg
104## Latest Changes
106## 0.26.3 (2026-05-28)
108### Fixes
110* Fix something.
112## 0.26.2 (2026-05-27)
114### Fixes
116* Previous fix.
117"""
119 body = get_release_notes_body(content, "0.26.3", Path("docs/release-notes.md")) 1abcdefg
121 assert ( 1abcdefg
122 body
123 == """### Fixes
125* Fix something.
126"""
127 )
130def test_get_release_notes_body_with_plain_heading() -> None: 1abcdefg
131 content = """# Release Notes 1abcdefg
133## Latest Changes
135## 0.26.3
137### Fixes
139* Fix something.
140"""
142 body = get_release_notes_body(content, "0.26.3", Path("docs/release-notes.md")) 1abcdefg
144 assert body == "### Fixes\n\n* Fix something.\n" 1abcdefg
147def test_get_release_notes_body_allows_non_version_h2_content() -> None: 1abcdefg
148 content = """# Release Notes 1abcdefg
150## Latest Changes
152## 0.26.3
154## Highlights
156* Fix something.
158## 0.26.2
160* Previous fix.
161"""
163 body = get_release_notes_body(content, "0.26.3", Path("docs/release-notes.md")) 1abcdefg
165 assert body == "## Highlights\n\n* Fix something.\n" 1abcdefg
168def test_get_release_notes_body_requires_version_section() -> None: 1abcdefg
169 content = "# Release Notes\n\n## Latest Changes\n" 1abcdefg
171 with pytest.raises(RuntimeError, match="Could not find"): 1abcdefg
172 get_release_notes_body(content, "0.26.3", Path("docs/release-notes.md")) 1abcdefg
175def test_get_release_notes_body_requires_non_empty_section() -> None: 1abcdefg
176 content = """# Release Notes 1abcdefg
178## Latest Changes
180## 0.26.3
182## 0.26.2
184* Previous fix.
185"""
187 with pytest.raises(RuntimeError, match="is empty"): 1abcdefg
188 get_release_notes_body(content, "0.26.3", Path("docs/release-notes.md")) 1abcdefg
191def test_cli_updates_configured_files(tmp_path: Path) -> None: 1abcdefg
192 version_file = tmp_path / "package" / "__init__.py" 1abcdefg
193 version_file.parent.mkdir() 1abcdefg
194 version_file.write_text('__version__ = "0.26.2"\n') 1abcdefg
195 release_notes_file = tmp_path / "release-notes.md" 1abcdefg
196 release_notes_file.write_text( 1abcdefg
197 """# Release Notes
199## Latest Changes
201### Fixes
203* Fix something.
204"""
205 )
207 result = runner.invoke( 1abcdefg
208 app,
209 [
210 "prepare",
211 "patch",
212 "--version-file",
213 str(version_file),
214 "--release-notes-file",
215 str(release_notes_file),
216 "--date",
217 "2026-05-28",
218 ],
219 )
221 assert result.exit_code == 0, result.output 1abcdefg
222 assert "Prepared release 0.26.3 (2026-05-28)" in result.output 1abcdefg
223 assert version_file.read_text() == '__version__ = "0.26.3"\n' 1abcdefg
224 assert "## 0.26.3 (2026-05-28)" in release_notes_file.read_text() 1abcdefg
227def test_cli_accepts_env_vars(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: 1abcdefg
228 version_file = tmp_path / "package" / "__init__.py" 1abcdefg
229 version_file.parent.mkdir() 1abcdefg
230 version_file.write_text('__version__ = "0.26.2"\n') 1abcdefg
231 release_notes_file = tmp_path / "docs" / "release-notes.md" 1abcdefg
232 release_notes_file.parent.mkdir() 1abcdefg
233 release_notes_file.write_text("# Release Notes\n\n## Latest Changes\n") 1abcdefg
234 monkeypatch.setenv("PREPARE_RELEASE_BUMP", "minor") 1abcdefg
235 monkeypatch.setenv("PREPARE_RELEASE_VERSION_FILE", str(version_file)) 1abcdefg
236 monkeypatch.setenv("PREPARE_RELEASE_RELEASE_NOTES_FILE", str(release_notes_file)) 1abcdefg
237 monkeypatch.setenv("PREPARE_RELEASE_DATE", "2026-05-28") 1abcdefg
239 result = runner.invoke(app, ["prepare"]) 1abcdefg
241 assert result.exit_code == 0, result.output 1abcdefg
242 assert "Prepared release 0.27.0 (2026-05-28)" in result.output 1abcdefg
243 assert version_file.read_text() == '__version__ = "0.27.0"\n' 1abcdefg
244 assert "## 0.27.0 (2026-05-28)" in release_notes_file.read_text() 1abcdefg
247def test_cli_prints_current_version(tmp_path: Path) -> None: 1abcdefg
248 version_file = tmp_path / "package" / "__init__.py" 1abcdefg
249 version_file.parent.mkdir() 1abcdefg
250 version_file.write_text('__version__ = "0.26.2"\n') 1abcdefg
252 result = runner.invoke( 1abcdefg
253 app,
254 [
255 "current-version",
256 "--version-file",
257 str(version_file),
258 ],
259 )
261 assert result.exit_code == 0, result.output 1abcdefg
262 assert result.output == "0.26.2\n" 1abcdefg
265def test_cli_prints_release_notes(tmp_path: Path) -> None: 1abcdefg
266 version_file = tmp_path / "package" / "__init__.py" 1abcdefg
267 version_file.parent.mkdir() 1abcdefg
268 version_file.write_text('__version__ = "0.26.3"\n') 1abcdefg
269 release_notes_file = tmp_path / "release-notes.md" 1abcdefg
270 release_notes_file.write_text( 1abcdefg
271 """# Release Notes
273## Latest Changes
275## 0.26.3 (2026-05-28)
277### Fixes
279* Fix something.
280"""
281 )
283 result = runner.invoke( 1abcdefg
284 app,
285 [
286 "release-notes",
287 "--version-file",
288 str(version_file),
289 "--release-notes-file",
290 str(release_notes_file),
291 ],
292 )
294 assert result.exit_code == 0, result.output 1abcdefg
295 assert result.output == "### Fixes\n\n* Fix something.\n" 1abcdefg