|
1 | 1 | import pytest |
2 | 2 | from django.conf.urls import re_path |
3 | 3 | from rest_framework import status |
| 4 | +from rest_framework.fields import SkipField |
4 | 5 | from rest_framework.routers import SimpleRouter |
| 6 | +from rest_framework.serializers import Serializer |
5 | 7 |
|
6 | 8 | from rest_framework_json_api.exceptions import Conflict |
7 | | -from rest_framework_json_api.relations import HyperlinkedRelatedField |
| 9 | +from rest_framework_json_api.relations import ( |
| 10 | + HyperlinkedRelatedField, |
| 11 | + SerializerMethodHyperlinkedRelatedField, |
| 12 | +) |
| 13 | +from rest_framework_json_api.utils import format_link_segment |
8 | 14 | from rest_framework_json_api.views import ModelViewSet, RelationshipView |
9 | 15 | from tests.models import BasicModel |
10 | 16 | from tests.serializers import ( |
|
14 | 20 | ) |
15 | 21 |
|
16 | 22 |
|
17 | | -@pytest.mark.urls(__name__) |
18 | | -@pytest.mark.parametrize( |
19 | | - "format_related_links,expected_url_segment", |
20 | | - [ |
21 | | - (None, "relatedField_name"), |
22 | | - ("dasherize", "related-field-name"), |
23 | | - ("camelize", "relatedFieldName"), |
24 | | - ("capitalize", "RelatedFieldName"), |
25 | | - ("underscore", "related_field_name"), |
26 | | - ], |
27 | | -) |
28 | | -def test_relationship_urls_respect_format_related_links_setting( |
29 | | - settings, format_related_links, expected_url_segment |
30 | | -): |
31 | | - settings.JSON_API_FORMAT_RELATED_LINKS = format_related_links |
32 | | - |
33 | | - model = BasicModel(text="Some text") |
34 | | - |
35 | | - field = HyperlinkedRelatedField( |
36 | | - self_link_view_name="basic-model-relationships", |
37 | | - related_link_view_name="basic-model-related", |
38 | | - read_only=True, |
39 | | - ) |
40 | | - field.field_name = "relatedField_name" |
41 | | - |
42 | | - expected = { |
43 | | - "self": f"/basic_models/{model.pk}/relationships/{expected_url_segment}/", |
44 | | - "related": f"/basic_models/{model.pk}/{expected_url_segment}/", |
45 | | - } |
46 | | - |
47 | | - actual = field.get_links(model) |
48 | | - |
49 | | - assert expected == actual |
50 | | - |
51 | | - |
52 | 23 | @pytest.mark.django_db |
53 | 24 | class TestResourceRelatedField: |
54 | 25 | @pytest.mark.parametrize( |
@@ -201,6 +172,97 @@ def test_invalid_resource_id_object(self, resource_identifier, error): |
201 | 172 | assert serializer.errors == {"target": [error]} |
202 | 173 |
|
203 | 174 |
|
| 175 | +class TestHyperlinkedRelatedField: |
| 176 | + @pytest.fixture |
| 177 | + def instance(self): |
| 178 | + # dummy instance |
| 179 | + return object() |
| 180 | + |
| 181 | + @pytest.fixture |
| 182 | + def serializer(self): |
| 183 | + class HyperlinkedRelatedFieldSerializer(Serializer): |
| 184 | + single = HyperlinkedRelatedField( |
| 185 | + self_link_view_name="basic-model-relationships", |
| 186 | + related_link_view_name="basic-model-related", |
| 187 | + read_only=True, |
| 188 | + ) |
| 189 | + many = HyperlinkedRelatedField( |
| 190 | + self_link_view_name="basic-model-relationships", |
| 191 | + related_link_view_name="basic-model-related", |
| 192 | + read_only=True, |
| 193 | + many=True, |
| 194 | + ) |
| 195 | + single_serializer_method = SerializerMethodHyperlinkedRelatedField( |
| 196 | + self_link_view_name="basic-model-relationships", |
| 197 | + related_link_view_name="basic-model-related", |
| 198 | + read_only=True, |
| 199 | + ) |
| 200 | + many_serializer_method = SerializerMethodHyperlinkedRelatedField( |
| 201 | + self_link_view_name="basic-model-relationships", |
| 202 | + related_link_view_name="basic-model-related", |
| 203 | + read_only=True, |
| 204 | + many=True, |
| 205 | + ) |
| 206 | + |
| 207 | + def get_single_serializer_method(self, obj): # pragma: no cover |
| 208 | + raise NotImplementedError |
| 209 | + |
| 210 | + def get_many_serializer_method(self, obj): # pragma: no cover |
| 211 | + raise NotImplementedError |
| 212 | + |
| 213 | + return HyperlinkedRelatedFieldSerializer() |
| 214 | + |
| 215 | + @pytest.fixture( |
| 216 | + params=["single", "many", "single_serializer_method", "many_serializer_method"] |
| 217 | + ) |
| 218 | + def field(self, serializer, request): |
| 219 | + field = serializer.fields[request.param] |
| 220 | + field.field_name = request.param |
| 221 | + return field |
| 222 | + |
| 223 | + def test_get_attribute(self, model, field): |
| 224 | + with pytest.raises(SkipField): |
| 225 | + field.get_attribute(model) |
| 226 | + |
| 227 | + def test_to_representation(self, model, field): |
| 228 | + with pytest.raises(NotImplementedError): |
| 229 | + field.to_representation(model) |
| 230 | + |
| 231 | + @pytest.mark.urls(__name__) |
| 232 | + @pytest.mark.parametrize( |
| 233 | + "format_related_links", |
| 234 | + [ |
| 235 | + None, |
| 236 | + "dasherize", |
| 237 | + "camelize", |
| 238 | + "capitalize", |
| 239 | + "underscore", |
| 240 | + ], |
| 241 | + ) |
| 242 | + def test_get_links( |
| 243 | + self, |
| 244 | + format_related_links, |
| 245 | + field, |
| 246 | + settings, |
| 247 | + model, |
| 248 | + ): |
| 249 | + settings.JSON_API_FORMAT_RELATED_LINKS = format_related_links |
| 250 | + |
| 251 | + link_segment = format_link_segment(field.field_name) |
| 252 | + |
| 253 | + expected = { |
| 254 | + "self": f"/basic_models/{model.pk}/relationships/{link_segment}/", |
| 255 | + "related": f"/basic_models/{model.pk}/{link_segment}/", |
| 256 | + } |
| 257 | + |
| 258 | + if hasattr(field, "child_relation"): |
| 259 | + # many case |
| 260 | + field = field.child_relation |
| 261 | + |
| 262 | + actual = field.get_links(model) |
| 263 | + assert expected == actual |
| 264 | + |
| 265 | + |
204 | 266 | # Routing setup |
205 | 267 |
|
206 | 268 |
|
|
0 commit comments