Coverage for tests / test_prepare_release.py: 100%
88 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-06-01 03:58 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-06-01 03:58 +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.0.17", "major", "1.0.0"),
23 ("0.0.17", "minor", "0.1.0"),
24 ("0.0.17", "patch", "0.0.18"),
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.0.17"\n\nfrom ._main import syncify as syncify\n' 1JKLMNOP
34 new_content = update_version_file(content, "0.0.18", Path("asyncer/__init__.py")) 1JKLMNOP
36 assert ( 1JKLMNOP
37 new_content
38 == '__version__ = "0.0.18"\n\nfrom ._main import syncify as syncify\n'
39 )
42def test_update_version_file_requires_newer_version() -> None: 1abcdefg
43 content = '__version__ = "0.0.17"\n' 1QRSTUVW
45 with pytest.raises(RuntimeError, match="must be greater"): 1QRSTUVW
46 update_version_file(content, "0.0.17", Path("asyncer/__init__.py")) 1QRSTUVW
49def test_update_release_notes() -> None: 1abcdefg
50 content = """# Release Notes 1XYZ0123
52## Latest Changes
54### Fixes
56* Fix something.
58## 0.0.17 (2026-02-21)
60### Fixes
62* Previous fix.
63"""
65 new_content = update_release_notes( 1XYZ0123
66 content, "0.0.18", date(2026, 5, 30), Path("docs/release-notes.md")
67 )
69 assert ( 1XYZ0123
70 new_content
71 == """# Release Notes
73## Latest Changes
75## 0.0.18 (2026-05-30)
77### Fixes
79* Fix something.
81## 0.0.17 (2026-02-21)
83### Fixes
85* Previous fix.
86"""
87 )
90def test_update_release_notes_rejects_existing_version() -> None: 1abcdefg
91 content = """# Release Notes 1456789!
93## Latest Changes
95## 0.0.18 (2026-05-30)
96"""
98 with pytest.raises(RuntimeError, match="already contain"): 1456789!
99 update_release_notes( 1456789!
100 content, "0.0.18", date(2026, 5, 30), Path("docs/release-notes.md")
101 )
104def test_get_release_notes_body_with_dated_heading() -> None: 1abcdefg
105 content = """# Release Notes 1#$%'()*
107## Latest Changes
109## 0.0.18 (2026-05-30)
111### Fixes
113* Fix something.
115## 0.0.17 (2026-02-21)
117### Fixes
119* Previous fix.
120"""
122 body = get_release_notes_body(content, "0.0.18", Path("docs/release-notes.md")) 1#$%'()*
124 assert ( 1#$%'()*
125 body
126 == """### Fixes
128* Fix something.
129"""
130 )
133def test_get_release_notes_body_with_plain_heading() -> None: 1abcdefg
134 content = """# Release Notes 1+,-./:;
136## Latest Changes
138## 0.0.18
140### Fixes
142* Fix something.
143"""
145 body = get_release_notes_body(content, "0.0.18", Path("docs/release-notes.md")) 1+,-./:;
147 assert body == "### Fixes\n\n* Fix something.\n" 1+,-./:;
150def test_get_release_notes_body_allows_non_version_h2_content() -> None: 1abcdefg
151 content = """# Release Notes 1=?@[]^_
153## Latest Changes
155## 0.0.18
157## Highlights
159* Fix something.
161## 0.0.17
163* Previous fix.
164"""
166 body = get_release_notes_body(content, "0.0.18", Path("docs/release-notes.md")) 1=?@[]^_
168 assert body == "## Highlights\n\n* Fix something.\n" 1=?@[]^_
171def test_get_release_notes_body_requires_version_section() -> None: 1abcdefg
172 content = "# Release Notes\n\n## Latest Changes\n" 2` { | } ~ abbb
174 with pytest.raises(RuntimeError, match="Could not find"): 2` { | } ~ abbb
175 get_release_notes_body(content, "0.0.18", Path("docs/release-notes.md")) 2` { | } ~ abbb
178def test_get_release_notes_body_requires_non_empty_section() -> None: 1abcdefg
179 content = """# Release Notes 2cbdbebfbgbhbib
181## Latest Changes
183## 0.0.18
185## 0.0.17
187* Previous fix.
188"""
190 with pytest.raises(RuntimeError, match="is empty"): 2cbdbebfbgbhbib
191 get_release_notes_body(content, "0.0.18", Path("docs/release-notes.md")) 2cbdbebfbgbhbib
194def test_cli_updates_configured_files(tmp_path: Path) -> None: 1abcdefg
195 version_file = tmp_path / "asyncer" / "__init__.py" 1opqrstu
196 version_file.parent.mkdir() 1opqrstu
197 version_file.write_text('__version__ = "0.0.17"\n') 1opqrstu
198 release_notes_file = tmp_path / "release-notes.md" 1opqrstu
199 release_notes_file.write_text( 1opqrstu
200 """# Release Notes
202## Latest Changes
204### Fixes
206* Fix something.
207"""
208 )
210 result = runner.invoke( 1opqrstu
211 app,
212 [
213 "prepare",
214 "patch",
215 "--version-file",
216 str(version_file),
217 "--release-notes-file",
218 str(release_notes_file),
219 "--date",
220 "2026-05-30",
221 ],
222 )
224 assert result.exit_code == 0, result.output 1opqrstu
225 assert "Prepared release 0.0.18 (2026-05-30)" in result.output 1opqrstu
226 assert version_file.read_text() == '__version__ = "0.0.18"\n' 1opqrstu
227 assert "## 0.0.18 (2026-05-30)" in release_notes_file.read_text() 1opqrstu
230def test_cli_accepts_env_vars(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: 1abcdefg
231 version_file = tmp_path / "asyncer" / "__init__.py" 1hijklmn
232 version_file.parent.mkdir() 1hijklmn
233 version_file.write_text('__version__ = "0.0.17"\n') 1hijklmn
234 release_notes_file = tmp_path / "docs" / "release-notes.md" 1hijklmn
235 release_notes_file.parent.mkdir() 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.1.0 (2026-05-30)" in result.output 1hijklmn
246 assert version_file.read_text() == '__version__ = "0.1.0"\n' 1hijklmn
247 assert "## 0.1.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 / "asyncer" / "__init__.py" 1CDEFGHI
252 version_file.parent.mkdir() 1CDEFGHI
253 version_file.write_text('__version__ = "0.0.17"\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.0.17\n" 1CDEFGHI
268def test_cli_prints_release_notes(tmp_path: Path) -> None: 1abcdefg
269 version_file = tmp_path / "asyncer" / "__init__.py" 1vwxyzAB
270 version_file.parent.mkdir() 1vwxyzAB
271 version_file.write_text('__version__ = "0.0.18"\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.0.18 (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