Improve RelatedField and callable default handling

- callable default values will now be properly called 
  - PrimaryKeyRelatedField and SlugRelatedField will now return an appropriate type based on the relation model's Field
  - mock views now have a request object bound even when public is True
This commit is contained in:
Cristi Vîjdea
2017-12-23 11:52:31 +01:00
parent f05889292a
commit 9f6ee4da87
17 changed files with 274 additions and 142 deletions
+20 -9
View File
@@ -3,6 +3,9 @@ import json
import os
import pytest
from django.contrib.auth.models import User
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
from ruamel import yaml
from drf_yasg import openapi, codecs
@@ -10,11 +13,16 @@ from drf_yasg.generators import OpenAPISchemaGenerator
@pytest.fixture
def generator():
return OpenAPISchemaGenerator(
info=openapi.Info(title="Test generator", default_version="v1"),
version="v2",
)
def mock_schema_request(db):
from rest_framework.test import force_authenticate
factory = APIRequestFactory()
user = User.objects.create_user(username='admin', is_staff=True, is_superuser=True)
request = factory.get('/swagger.json')
force_authenticate(request, user=user)
request = APIView().initialize_request(request)
return request
@pytest.fixture
@@ -28,13 +36,16 @@ def codec_yaml():
@pytest.fixture
def swagger(generator):
return generator.get_schema(None, True)
def swagger(mock_schema_request):
generator = OpenAPISchemaGenerator(
info=openapi.Info(title="Test generator", default_version="v1"),
version="v2",
)
return generator.get_schema(mock_schema_request, True)
@pytest.fixture
def swagger_dict(generator):
swagger = generator.get_schema(None, True)
def swagger_dict(swagger):
json_bytes = codec_json().encode(swagger)
return json.loads(json_bytes.decode('utf-8'))
+29 -2
View File
@@ -178,6 +178,7 @@ paths:
description: slug model help_text
required: true
type: string
format: slug
pattern: '[a-z0-9]+(?:-[a-z0-9]+)'
/articles/{slug}/image/:
get:
@@ -231,6 +232,7 @@ paths:
description: slug model help_text
required: true
type: string
format: slug
pattern: '[a-z0-9]+(?:-[a-z0-9]+)'
/plain/:
get:
@@ -355,12 +357,12 @@ paths:
- name: username
in: query
description: this field is generated from a query_serializer
required: true
required: false
type: string
- name: is_staff
in: query
description: this one too!
required: true
required: false
type: boolean
responses:
'200':
@@ -464,6 +466,11 @@ definitions:
title:
description: title model help_text
type: string
author:
description: The ID of the user that created this article; if none is provided,
defaults to the currently logged in user.
type: integer
default: 1
body:
description: body serializer help_text
type: string
@@ -523,6 +530,12 @@ definitions:
type: integer
readOnly: true
owner:
description: The ID of the user that created this snippet; if none is provided,
defaults to the currently logged in user.
type: integer
default: 1
owner_as_string:
description: The ID of the user that created this snippet.
type: string
readOnly: true
title:
@@ -1022,10 +1035,12 @@ definitions:
difficulty_factor:
description: this is here just to test FloatField
type: number
default: 6.9
readOnly: true
UserSerializerrr:
required:
- username
- articles
- snippets
type: object
properties:
@@ -1039,6 +1054,11 @@ definitions:
email:
type: string
format: email
articles:
type: array
items:
type: integer
uniqueItems: true
snippets:
type: array
items:
@@ -1054,6 +1074,13 @@ definitions:
type: string
format: date
readOnly: true
article_slugs:
type: array
items:
type: string
readOnly: true
uniqueItems: true
readOnly: true
securityDefinitions:
basic:
type: basic
+1 -1
View File
@@ -2,7 +2,6 @@ from datadiff.tools import assert_equal
def test_reference_schema(swagger_dict, reference_schema):
# formatted better than pytest diff
swagger_dict = dict(swagger_dict)
reference_schema = dict(reference_schema)
ignore = ['info', 'host', 'schemes', 'basePath', 'securityDefinitions']
@@ -10,4 +9,5 @@ def test_reference_schema(swagger_dict, reference_schema):
swagger_dict.pop(attr, None)
reference_schema.pop(attr, None)
# formatted better than pytest diff
assert_equal(swagger_dict, reference_schema)
+8 -16
View File
@@ -7,16 +7,11 @@ from drf_yasg import openapi, codecs
from drf_yasg.generators import OpenAPISchemaGenerator
def test_schema_generates_without_errors(generator):
generator.get_schema(None, True)
def test_schema_is_valid(generator, codec_yaml):
swagger = generator.get_schema(request=None, public=False)
def test_schema_is_valid(swagger, codec_yaml):
codec_yaml.encode(swagger)
def test_invalid_schema_fails(codec_json):
def test_invalid_schema_fails(codec_json, mock_schema_request):
# noinspection PyTypeChecker
bad_generator = OpenAPISchemaGenerator(
info=openapi.Info(
@@ -26,40 +21,37 @@ def test_invalid_schema_fails(codec_json):
version="v2",
)
swagger = bad_generator.get_schema(None, True)
swagger = bad_generator.get_schema(mock_schema_request, True)
with pytest.raises(codecs.SwaggerValidationError):
codec_json.encode(swagger)
def test_json_codec_roundtrip(codec_json, generator, validate_schema):
swagger = generator.get_schema(None, True)
def test_json_codec_roundtrip(codec_json, swagger, validate_schema):
json_bytes = codec_json.encode(swagger)
validate_schema(json.loads(json_bytes.decode('utf-8')))
def test_yaml_codec_roundtrip(codec_yaml, generator, validate_schema):
swagger = generator.get_schema(None, True)
def test_yaml_codec_roundtrip(codec_yaml, swagger, validate_schema):
yaml_bytes = codec_yaml.encode(swagger)
assert b'omap' not in yaml_bytes # ensure no ugly !!omap is outputted
assert b'&id' not in yaml_bytes and b'*id' not in yaml_bytes # ensure no YAML references are generated
validate_schema(yaml.safe_load(yaml_bytes.decode('utf-8')))
def test_yaml_and_json_match(codec_yaml, codec_json, generator):
swagger = generator.get_schema(None, True)
def test_yaml_and_json_match(codec_yaml, codec_json, swagger):
yaml_schema = yaml.safe_load(codec_yaml.encode(swagger).decode('utf-8'))
json_schema = json.loads(codec_json.encode(swagger).decode('utf-8'))
assert yaml_schema == json_schema
def test_basepath_only():
def test_basepath_only(mock_schema_request):
generator = OpenAPISchemaGenerator(
info=openapi.Info(title="Test generator", default_version="v1"),
version="v2",
url='/basepath/',
)
swagger = generator.get_schema(None, public=True)
swagger = generator.get_schema(mock_schema_request, public=True)
assert 'host' not in swagger
assert 'schemes' not in swagger
assert swagger['basePath'] == '/' # base path is not implemented for now