Coverage for tests/test_prepare_release.py: 100%
87 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-11-09 00:25 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-11-09 00:25 +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.18.0", BumpType.major, "1.0.0"),
23 ("0.18.0", BumpType.minor, "0.19.0"),
24 ("0.18.0", BumpType.patch, "0.18.1"),
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 2jbkblbmbnbobpb
31def test_update_version_file() -> None: 1abcdefg
32 content = '__version__ = "0.18.0"\n' 1JKLMNOP
34 new_content = update_version_file( 1JKLMNOP
35 content, "0.18.1", Path("src/fastapi_cloud_cli/__init__.py")
36 )
38 assert new_content == '__version__ = "0.18.1"\n' 1JKLMNOP
41def test_update_version_file_requires_newer_version() -> None: 1abcdefg
42 content = '__version__ = "0.18.0"\n' 1QRSTUVW
44 with pytest.raises(RuntimeError, match="must be greater"): 1QRSTUVW
45 update_version_file( 1QRSTUVW
46 content, "0.18.0", Path("src/fastapi_cloud_cli/__init__.py")
47 )
50def test_update_release_notes() -> None: 1abcdefg
51 content = """# Release Notes 1XYZ0123
53## Latest Changes
55### Fixes
57* Fix something.
59## 0.18.0 (2026-05-22)
61### Fixes
63* Previous fix.
64"""
66 new_content = update_release_notes( 1XYZ0123
67 content, "0.18.1", date(2026, 5, 30), Path("release-notes.md")
68 )
70 assert ( 1XYZ0123
71 new_content
72 == """# Release Notes
74## Latest Changes
76## 0.18.1 (2026-05-30)
78### Fixes
80* Fix something.
82## 0.18.0 (2026-05-22)
84### Fixes
86* Previous fix.
87"""
88 )
91def test_update_release_notes_rejects_existing_version() -> None: 1abcdefg
92 content = """# Release Notes 1456789!
94## Latest Changes
96## 0.18.1 (2026-05-30)
97"""
99 with pytest.raises(RuntimeError, match="already contain"): 1456789!
100 update_release_notes( 1456789!
101 content, "0.18.1", date(2026, 5, 30), Path("release-notes.md")
102 )
105def test_get_release_notes_body_with_dated_heading() -> None: 1abcdefg
106 content = """# Release Notes 1#$%'()*
108## Latest Changes
110## 0.18.1 (2026-05-30)
112### Fixes
114* Fix something.
116## 0.18.0 (2026-05-22)
118### Fixes
120* Previous fix.
121"""
123 body = get_release_notes_body(content, "0.18.1", Path("release-notes.md")) 1#$%'()*
125 assert ( 1#$%'()*
126 body
127 == """### Fixes
129* Fix something.
130"""
131 )
134def test_get_release_notes_body_with_plain_heading() -> None: 1abcdefg
135 content = """# Release Notes 1+,-./:;
137## Latest Changes
139## 0.18.1
141### Fixes
143* Fix something.
144"""
146 body = get_release_notes_body(content, "0.18.1", Path("release-notes.md")) 1+,-./:;
148 assert body == "### Fixes\n\n* Fix something.\n" 1+,-./:;
151def test_get_release_notes_body_allows_non_version_h2_content() -> None: 1abcdefg
152 content = """# Release Notes 1=?@[]^_
154## Latest Changes
156## 0.18.1
158## Highlights
160* Fix something.
162## 0.18.0
164* Previous fix.
165"""
167 body = get_release_notes_body(content, "0.18.1", Path("release-notes.md")) 1=?@[]^_
169 assert body == "## Highlights\n\n* Fix something.\n" 1=?@[]^_
172def test_get_release_notes_body_requires_version_section() -> None: 1abcdefg
173 content = "# Release Notes\n\n## Latest Changes\n" 2` { | } ~ abbb
175 with pytest.raises(RuntimeError, match="Could not find"): 2` { | } ~ abbb
176 get_release_notes_body(content, "0.18.1", Path("release-notes.md")) 2` { | } ~ abbb
179def test_get_release_notes_body_requires_non_empty_section() -> None: 1abcdefg
180 content = """# Release Notes 2cbdbebfbgbhbib
182## Latest Changes
184## 0.18.1
186## 0.18.0
188* Previous fix.
189"""
191 with pytest.raises(RuntimeError, match="is empty"): 2cbdbebfbgbhbib
192 get_release_notes_body(content, "0.18.1", Path("release-notes.md")) 2cbdbebfbgbhbib
195def test_cli_updates_configured_files(tmp_path: Path) -> None: 1abcdefg
196 version_file = tmp_path / "src" / "fastapi_cloud_cli" / "__init__.py" 1opqrstu
197 version_file.parent.mkdir(parents=True) 1opqrstu
198 version_file.write_text('__version__ = "0.18.0"\n') 1opqrstu
199 release_notes_file = tmp_path / "release-notes.md" 1opqrstu
200 release_notes_file.write_text( 1opqrstu
201 """# Release Notes
203## Latest Changes
205### Fixes
207* Fix something.
208"""
209 )
211 result = runner.invoke( 1opqrstu
212 app,
213 [
214 "prepare",
215 "patch",
216 "--version-file",
217 str(version_file),
218 "--release-notes-file",
219 str(release_notes_file),
220 "--date",
221 "2026-05-30",
222 ],
223 )
225 assert result.exit_code == 0, result.output 1opqrstu
226 assert "Prepared release 0.18.1 (2026-05-30)" in result.output 1opqrstu
227 assert version_file.read_text() == '__version__ = "0.18.1"\n' 1opqrstu
228 assert "## 0.18.1 (2026-05-30)" in release_notes_file.read_text() 1opqrstu
231def test_cli_accepts_env_vars(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: 1abcdefg
232 version_file = tmp_path / "src" / "fastapi_cloud_cli" / "__init__.py" 1hijklmn
233 version_file.parent.mkdir(parents=True) 1hijklmn
234 version_file.write_text('__version__ = "0.18.0"\n') 1hijklmn
235 release_notes_file = tmp_path / "release-notes.md" 1hijklmn
236 release_notes_file.write_text("# Release Notes\n\n## Latest Changes\n") 1hijklmn
237 monkeypatch.setenv("PREPARE_RELEASE_BUMP", "minor") 1hijklmn
238 monkeypatch.setenv("PREPARE_RELEASE_VERSION_FILE", str(version_file)) 1hijklmn
239 monkeypatch.setenv("PREPARE_RELEASE_RELEASE_NOTES_FILE", str(release_notes_file)) 1hijklmn
240 monkeypatch.setenv("PREPARE_RELEASE_DATE", "2026-05-30") 1hijklmn
242 result = runner.invoke(app, ["prepare"]) 1hijklmn
244 assert result.exit_code == 0, result.output 1hijklmn
245 assert "Prepared release 0.19.0 (2026-05-30)" in result.output 1hijklmn
246 assert version_file.read_text() == '__version__ = "0.19.0"\n' 1hijklmn
247 assert "## 0.19.0 (2026-05-30)" in release_notes_file.read_text() 1hijklmn
250def test_cli_prints_current_version(tmp_path: Path) -> None: 1abcdefg
251 version_file = tmp_path / "src" / "fastapi_cloud_cli" / "__init__.py" 1CDEFGHI
252 version_file.parent.mkdir(parents=True) 1CDEFGHI
253 version_file.write_text('__version__ = "0.18.0"\n') 1CDEFGHI
255 result = runner.invoke( 1CDEFGHI
256 app,
257 [
258 "current-version",
259 "--version-file",
260 str(version_file),
261 ],
262 )
264 assert result.exit_code == 0, result.output 1CDEFGHI
265 assert result.output == "0.18.0\n" 1CDEFGHI
268def test_cli_prints_release_notes(tmp_path: Path) -> None: 1abcdefg
269 version_file = tmp_path / "src" / "fastapi_cloud_cli" / "__init__.py" 1vwxyzAB
270 version_file.parent.mkdir(parents=True) 1vwxyzAB
271 version_file.write_text('__version__ = "0.18.1"\n') 1vwxyzAB
272 release_notes_file = tmp_path / "release-notes.md" 1vwxyzAB
273 release_notes_file.write_text( 1vwxyzAB
274 """# Release Notes
276## Latest Changes
278## 0.18.1 (2026-05-30)
280### Fixes
282* Fix something.
283"""
284 )
286 result = runner.invoke( 1vwxyzAB
287 app,
288 [
289 "release-notes",
290 "--version-file",
291 str(version_file),
292 "--release-notes-file",
293 str(release_notes_file),
294 ],
295 )
297 assert result.exit_code == 0, result.output 1vwxyzAB
298 assert result.output == "### Fixes\n\n* Fix something.\n" 1vwxyzAB