|
| 1 | +from types import SimpleNamespace |
| 2 | + |
1 | 3 | import pytest |
2 | 4 | from django.test import RequestFactory |
| 5 | +from django.urls import ResolverMatch |
3 | 6 |
|
4 | | -from core.context_processors import current_version, active_nav_item |
| 7 | +from core.context_processors import ( |
| 8 | + active_nav_item, |
| 9 | + current_version, |
| 10 | + selected_version, |
| 11 | +) |
| 12 | +from libraries.constants import SELECTED_BOOST_VERSION_COOKIE_NAME |
| 13 | +from versions.managers import HeaderVersionData |
5 | 14 |
|
6 | 15 |
|
7 | 16 | def test_current_version_context( |
@@ -42,3 +51,99 @@ def test_active_nav_item(path, expected_nav_item): |
42 | 51 | request = RequestFactory().get(path) |
43 | 52 | context = active_nav_item(request) |
44 | 53 | assert context["active_nav_item"] == expected_nav_item |
| 54 | + |
| 55 | + |
| 56 | +def _stub_header_data(request): |
| 57 | + most_recent = SimpleNamespace(slug="boost-1-88-0", display_name="1.88.0") |
| 58 | + older = SimpleNamespace(slug="boost-1-87-0", display_name="1.87.0") |
| 59 | + request._header_version_data = HeaderVersionData( |
| 60 | + options=[most_recent, older], |
| 61 | + most_recent=most_recent, |
| 62 | + most_recent_beta=None, |
| 63 | + ) |
| 64 | + return most_recent, older |
| 65 | + |
| 66 | + |
| 67 | +def _attach_resolver(request, *, route, kwargs, view_name=""): |
| 68 | + request.resolver_match = ResolverMatch( |
| 69 | + func=lambda r: None, |
| 70 | + args=(), |
| 71 | + kwargs=kwargs, |
| 72 | + url_name=view_name or None, |
| 73 | + route=route, |
| 74 | + ) |
| 75 | + |
| 76 | + |
| 77 | +def test_selected_version_url_driven_for_boost_route(rf): |
| 78 | + request = rf.get("/releases/1.88.0/") |
| 79 | + most_recent, older = _stub_header_data(request) |
| 80 | + _attach_resolver( |
| 81 | + request, |
| 82 | + route="releases/<boostversionslug:version_slug>/", |
| 83 | + kwargs={"version_slug": "boost-1-88-0"}, |
| 84 | + view_name="release-detail", |
| 85 | + ) |
| 86 | + ctx = selected_version(request) |
| 87 | + assert ctx["selected_version_is_url_driven"] is True |
| 88 | + assert ctx["selected_version_is_non_latest"] is True |
| 89 | + assert ctx["selected_version_label"] == "1.88.0" |
| 90 | + assert ctx["selected_version"] is most_recent |
| 91 | + assert ctx["latest_href"] == "/releases/latest/" |
| 92 | + assert most_recent.href == "/releases/1.88.0/" |
| 93 | + assert older.href == "/releases/1.87.0/" |
| 94 | + |
| 95 | + |
| 96 | +def test_selected_version_url_driven_with_latest_slug(rf): |
| 97 | + """`/releases/latest/` is URL-driven but the label should still read |
| 98 | + 'Latest' and the version should fall back to most_recent.""" |
| 99 | + request = rf.get("/releases/latest/") |
| 100 | + most_recent, _ = _stub_header_data(request) |
| 101 | + _attach_resolver( |
| 102 | + request, |
| 103 | + route="releases/<boostversionslug:version_slug>/", |
| 104 | + kwargs={"version_slug": "latest"}, |
| 105 | + view_name="release-detail", |
| 106 | + ) |
| 107 | + ctx = selected_version(request) |
| 108 | + assert ctx["selected_version_is_url_driven"] is True |
| 109 | + assert ctx["selected_version_is_non_latest"] is False |
| 110 | + assert ctx["selected_version_label"] == "Latest" |
| 111 | + assert ctx["selected_version"] is most_recent |
| 112 | + |
| 113 | + |
| 114 | +def test_selected_version_cookie_driven(rf): |
| 115 | + """Cookie mode: no URL slug, cookie picks the version, dropdown renders |
| 116 | + POST forms (no `latest_href`, no per-option `.href`).""" |
| 117 | + request = rf.get("/") |
| 118 | + request.COOKIES[SELECTED_BOOST_VERSION_COOKIE_NAME] = "boost-1-87-0" |
| 119 | + _, older = _stub_header_data(request) |
| 120 | + ctx = selected_version(request) |
| 121 | + assert ctx["selected_version_is_url_driven"] is False |
| 122 | + assert ctx["selected_version_is_non_latest"] is True |
| 123 | + assert ctx["selected_version_label"] == "1.87.0" |
| 124 | + assert ctx["selected_version"] is older |
| 125 | + assert ctx["latest_href"] == "" |
| 126 | + |
| 127 | + |
| 128 | +def test_selected_version_ignores_foreign_route_with_same_kwarg(rf): |
| 129 | + """A route declaring `version_slug` via a different converter must NOT be |
| 130 | + treated as URL-driven — the guard against silent coupling.""" |
| 131 | + request = rf.get("/elsewhere/anything/") |
| 132 | + _stub_header_data(request) |
| 133 | + _attach_resolver( |
| 134 | + request, |
| 135 | + route="elsewhere/<str:version_slug>/", |
| 136 | + kwargs={"version_slug": "anything"}, |
| 137 | + view_name="some-other-view", |
| 138 | + ) |
| 139 | + ctx = selected_version(request) |
| 140 | + assert ctx["selected_version_is_url_driven"] is False |
| 141 | + assert ctx["selected_version_label"] == "Latest" |
| 142 | + |
| 143 | + |
| 144 | +def test_selected_version_no_resolver_match(rf): |
| 145 | + request = rf.get("/") |
| 146 | + _stub_header_data(request) |
| 147 | + ctx = selected_version(request) |
| 148 | + assert ctx["selected_version_is_url_driven"] is False |
| 149 | + assert ctx["selected_version_label"] == "Latest" |
0 commit comments