|
5 | 5 | from django.test import TestCase, override_settings |
6 | 6 | from django.urls import reverse |
7 | 7 |
|
8 | | -from ..templatetags.download_tags import get_eol_info, get_release_cycle_data |
| 8 | +from ..templatetags.download_tags import ( |
| 9 | + get_eol_info, |
| 10 | + get_release_cycle_data, |
| 11 | + render_active_releases, |
| 12 | +) |
9 | 13 | from .base import BaseDownloadTests |
10 | 14 |
|
11 | 15 | MOCK_RELEASE_CYCLE = { |
12 | | - "2.7": {"status": "end-of-life", "end_of_life": "2020-01-01"}, |
13 | | - "3.8": {"status": "end-of-life", "end_of_life": "2024-10-07"}, |
14 | | - "3.10": {"status": "security", "end_of_life": "2026-10-04"}, |
| 16 | + "2.7": {"status": "end-of-life", "end_of_life": "2020-01-01", "pep": 373}, |
| 17 | + "3.8": {"status": "end-of-life", "end_of_life": "2024-10-07", "pep": 569}, |
| 18 | + "3.9": {"status": "end-of-life", "end_of_life": "2025-10-31", "pep": 596}, |
| 19 | + "3.10": {"status": "security", "end_of_life": "2026-10-04", "pep": 619}, |
| 20 | + "3.14": {"status": "bugfix", "first_release": "2025-10-07", "end_of_life": "2030-10", "pep": 745}, |
| 21 | + "3.15": {"status": "feature", "first_release": "2026-10-01", "end_of_life": "2031-10", "pep": 790}, |
15 | 22 | } |
16 | 23 |
|
17 | 24 |
|
@@ -166,3 +173,77 @@ def test_eol_banner_visibility(self, mock_get_data): |
166 | 173 | self.assertContains(response, "no longer supported") |
167 | 174 | else: |
168 | 175 | self.assertNotContains(response, "level-error") |
| 176 | + |
| 177 | + |
| 178 | +@override_settings(CACHES=TEST_CACHES) |
| 179 | +class RenderActiveReleasesTests(BaseDownloadTests): |
| 180 | + def setUp(self): |
| 181 | + super().setUp() |
| 182 | + cache.clear() |
| 183 | + |
| 184 | + @mock.patch("downloads.templatetags.download_tags.get_release_cycle_data") |
| 185 | + def test_versions_sorted_descending(self, mock_get_data): |
| 186 | + """Test that versions are sorted in descending order.""" |
| 187 | + mock_get_data.return_value = MOCK_RELEASE_CYCLE |
| 188 | + |
| 189 | + result = render_active_releases() |
| 190 | + |
| 191 | + versions = [r["version"] for r in result["releases"]] |
| 192 | + # 3.15, 3.14, 3.10, 3.9 (first EOL); 3.8 and 2.7 skipped (older EOL) |
| 193 | + self.assertEqual(versions, ["3.15", "3.14", "3.10", "3.9"]) |
| 194 | + |
| 195 | + @mock.patch("downloads.templatetags.download_tags.get_release_cycle_data") |
| 196 | + def test_feature_status_becomes_prerelease(self, mock_get_data): |
| 197 | + """Test that 'feature' status is converted to 'pre-release'.""" |
| 198 | + mock_get_data.return_value = MOCK_RELEASE_CYCLE |
| 199 | + |
| 200 | + result = render_active_releases() |
| 201 | + |
| 202 | + prerelease = result["releases"][0] |
| 203 | + self.assertEqual(prerelease["version"], "3.15") |
| 204 | + self.assertEqual(prerelease["status"], "pre-release") |
| 205 | + |
| 206 | + @mock.patch("downloads.templatetags.download_tags.get_release_cycle_data") |
| 207 | + def test_feature_first_release_shows_planned(self, mock_get_data): |
| 208 | + """Test that feature releases show (planned) in first_release.""" |
| 209 | + mock_get_data.return_value = MOCK_RELEASE_CYCLE |
| 210 | + |
| 211 | + result = render_active_releases() |
| 212 | + |
| 213 | + prerelease = result["releases"][0] |
| 214 | + self.assertEqual(prerelease["first_release"], "2026-10-01 (planned)") |
| 215 | + |
| 216 | + @mock.patch("downloads.templatetags.download_tags.get_release_cycle_data") |
| 217 | + def test_only_one_eol_release_included(self, mock_get_data): |
| 218 | + """Test that only the most recent EOL release is included.""" |
| 219 | + mock_get_data.return_value = MOCK_RELEASE_CYCLE |
| 220 | + |
| 221 | + result = render_active_releases() |
| 222 | + |
| 223 | + versions = [r["version"] for r in result["releases"]] |
| 224 | + # 3.9 is included (most recent EOL), 3.8 and 2.7 are not |
| 225 | + self.assertIn("3.9", versions) |
| 226 | + self.assertNotIn("3.8", versions) |
| 227 | + self.assertNotIn("2.7", versions) |
| 228 | + |
| 229 | + @mock.patch("downloads.templatetags.download_tags.get_release_cycle_data") |
| 230 | + def test_eol_status_includes_last_release_link(self, mock_get_data): |
| 231 | + """Test that EOL status includes last release link.""" |
| 232 | + mock_get_data.return_value = MOCK_RELEASE_CYCLE |
| 233 | + |
| 234 | + result = render_active_releases() |
| 235 | + |
| 236 | + eol_release = next(r for r in result["releases"] if r["version"] == "3.9") |
| 237 | + status = str(eol_release["status"]) |
| 238 | + self.assertIn("end-of-life", status) |
| 239 | + self.assertIn("last release was", status) |
| 240 | + self.assertIn("<a href=", status) |
| 241 | + |
| 242 | + @mock.patch("downloads.templatetags.download_tags.get_release_cycle_data") |
| 243 | + def test_api_failure_returns_empty_releases(self, mock_get_data): |
| 244 | + """Test that API failure returns empty releases list.""" |
| 245 | + mock_get_data.return_value = None |
| 246 | + |
| 247 | + result = render_active_releases() |
| 248 | + |
| 249 | + self.assertEqual(result["releases"], []) |
0 commit comments