+19
-12
@@ -1,3 +1,4 @@
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
|
||||
@@ -27,8 +28,13 @@ def codec_yaml():
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def swagger_dict():
|
||||
swagger = generator().get_schema(None, True)
|
||||
def swagger(generator):
|
||||
return generator.get_schema(None, True)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def swagger_dict(generator):
|
||||
swagger = generator.get_schema(None, True)
|
||||
json_bytes = codec_json().encode(swagger)
|
||||
return json.loads(json_bytes.decode('utf-8'))
|
||||
|
||||
@@ -46,16 +52,17 @@ def validate_schema():
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bad_settings():
|
||||
from drf_swagger.app_settings import swagger_settings, SWAGGER_DEFAULTS
|
||||
bad_security = {
|
||||
'bad': {
|
||||
'bad_attribute': 'should not be accepted'
|
||||
}
|
||||
}
|
||||
SWAGGER_DEFAULTS['SECURITY_DEFINITIONS'].update(bad_security)
|
||||
yield swagger_settings
|
||||
del SWAGGER_DEFAULTS['SECURITY_DEFINITIONS']['bad']
|
||||
def swagger_settings(settings):
|
||||
swagger_settings = copy.deepcopy(settings.SWAGGER_SETTINGS)
|
||||
settings.SWAGGER_SETTINGS = swagger_settings
|
||||
return swagger_settings
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def redoc_settings(settings):
|
||||
redoc_settings = copy.deepcopy(settings.REDOC_SETTINGS)
|
||||
settings.REDOC_SETTINGS = redoc_settings
|
||||
return redoc_settings
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
+125
-58
@@ -141,17 +141,6 @@ paths:
|
||||
- application/json
|
||||
tags:
|
||||
- articles
|
||||
delete:
|
||||
operationId: articles_delete
|
||||
description: destroy method docstring
|
||||
parameters: []
|
||||
responses:
|
||||
'204':
|
||||
description: ''
|
||||
consumes:
|
||||
- application/json
|
||||
tags:
|
||||
- articles
|
||||
patch:
|
||||
operationId: articles_partial_update
|
||||
description: partial_update description override
|
||||
@@ -172,6 +161,17 @@ paths:
|
||||
- application/json
|
||||
tags:
|
||||
- articles
|
||||
delete:
|
||||
operationId: articles_delete
|
||||
description: destroy method docstring
|
||||
parameters: []
|
||||
responses:
|
||||
'204':
|
||||
description: ''
|
||||
consumes:
|
||||
- application/json
|
||||
tags:
|
||||
- articles
|
||||
parameters:
|
||||
- name: slug
|
||||
in: path
|
||||
@@ -197,6 +197,24 @@ paths:
|
||||
operationId: articles_image_create
|
||||
description: image method docstring
|
||||
parameters:
|
||||
- name: what_am_i_doing
|
||||
in: formData
|
||||
description: test
|
||||
required: true
|
||||
type: string
|
||||
pattern: ^69$
|
||||
- name: image_styles
|
||||
in: formData
|
||||
description: Parameter with Items
|
||||
required: true
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- wide
|
||||
- tall
|
||||
- thumb
|
||||
- social
|
||||
- name: upload
|
||||
in: formData
|
||||
description: image serializer help_text
|
||||
@@ -216,6 +234,19 @@ paths:
|
||||
required: true
|
||||
type: string
|
||||
pattern: '[a-z0-9]+(?:-[a-z0-9]+)'
|
||||
/plain/:
|
||||
get:
|
||||
operationId: plain_list
|
||||
description: ''
|
||||
parameters: []
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
consumes:
|
||||
- application/json
|
||||
tags:
|
||||
- plain
|
||||
parameters: []
|
||||
/snippets/:
|
||||
get:
|
||||
operationId: snippets_list
|
||||
@@ -283,17 +314,6 @@ paths:
|
||||
- application/json
|
||||
tags:
|
||||
- snippets
|
||||
delete:
|
||||
operationId: snippets_delete
|
||||
description: delete method docstring
|
||||
parameters: []
|
||||
responses:
|
||||
'204':
|
||||
description: ''
|
||||
consumes:
|
||||
- application/json
|
||||
tags:
|
||||
- snippets
|
||||
patch:
|
||||
operationId: snippets_partial_update
|
||||
description: patch method docstring
|
||||
@@ -312,6 +332,17 @@ paths:
|
||||
- application/json
|
||||
tags:
|
||||
- snippets
|
||||
delete:
|
||||
operationId: snippets_delete
|
||||
description: delete method docstring
|
||||
parameters: []
|
||||
responses:
|
||||
'204':
|
||||
description: ''
|
||||
consumes:
|
||||
- application/json
|
||||
tags:
|
||||
- snippets
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
@@ -329,7 +360,7 @@ paths:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/User'
|
||||
$ref: '#/definitions/UserSerializerrr'
|
||||
consumes:
|
||||
- application/json
|
||||
tags:
|
||||
@@ -381,7 +412,7 @@ paths:
|
||||
'200':
|
||||
description: response description
|
||||
schema:
|
||||
$ref: '#/definitions/User'
|
||||
$ref: '#/definitions/UserSerializerrr'
|
||||
consumes:
|
||||
- application/json
|
||||
tags:
|
||||
@@ -394,12 +425,12 @@ paths:
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/User'
|
||||
$ref: '#/definitions/UserSerializerrr'
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/User'
|
||||
$ref: '#/definitions/UserSerializerrr'
|
||||
consumes:
|
||||
- application/json
|
||||
tags:
|
||||
@@ -414,6 +445,8 @@ definitions:
|
||||
required:
|
||||
- title
|
||||
- body
|
||||
- references
|
||||
- uuid
|
||||
type: object
|
||||
properties:
|
||||
title:
|
||||
@@ -426,6 +459,7 @@ definitions:
|
||||
description: slug model help_text
|
||||
type: string
|
||||
format: slug
|
||||
pattern: ^[-a-zA-Z0-9_]+$
|
||||
date_created:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -434,6 +468,17 @@ definitions:
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
references:
|
||||
description: this is a really bad example
|
||||
type: object
|
||||
additionalProperties:
|
||||
description: but i needed to test these 2 fields somehow
|
||||
type: string
|
||||
format: uri
|
||||
uuid:
|
||||
description: should articles have UUIDs?
|
||||
type: string
|
||||
format: uuid
|
||||
Project:
|
||||
required:
|
||||
- project_name
|
||||
@@ -451,6 +496,7 @@ definitions:
|
||||
- code
|
||||
- language
|
||||
- example_projects
|
||||
- difficulty_factor
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
@@ -908,38 +954,43 @@ definitions:
|
||||
- yaml
|
||||
- yaml+jinja
|
||||
- zephir
|
||||
style:
|
||||
type: string
|
||||
enum:
|
||||
- abap
|
||||
- algol
|
||||
- algol_nu
|
||||
- arduino
|
||||
- autumn
|
||||
- borland
|
||||
- bw
|
||||
- colorful
|
||||
- default
|
||||
- emacs
|
||||
default: python
|
||||
styles:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- abap
|
||||
- algol
|
||||
- algol_nu
|
||||
- arduino
|
||||
- autumn
|
||||
- borland
|
||||
- bw
|
||||
- colorful
|
||||
- default
|
||||
- emacs
|
||||
- friendly
|
||||
- fruity
|
||||
- igor
|
||||
- lovelace
|
||||
- manni
|
||||
- monokai
|
||||
- murphy
|
||||
- native
|
||||
- paraiso-dark
|
||||
- paraiso-light
|
||||
- pastie
|
||||
- perldoc
|
||||
- rainbow_dash
|
||||
- rrt
|
||||
- tango
|
||||
- trac
|
||||
- vim
|
||||
- vs
|
||||
- xcode
|
||||
default:
|
||||
- friendly
|
||||
- fruity
|
||||
- igor
|
||||
- lovelace
|
||||
- manni
|
||||
- monokai
|
||||
- murphy
|
||||
- native
|
||||
- paraiso-dark
|
||||
- paraiso-light
|
||||
- pastie
|
||||
- perldoc
|
||||
- rainbow_dash
|
||||
- rrt
|
||||
- tango
|
||||
- trac
|
||||
- vim
|
||||
- vs
|
||||
- xcode
|
||||
lines:
|
||||
type: array
|
||||
items:
|
||||
@@ -948,7 +999,10 @@ definitions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Project'
|
||||
User:
|
||||
difficulty_factor:
|
||||
description: this is here just to test FloatField
|
||||
type: number
|
||||
UserSerializerrr:
|
||||
required:
|
||||
- username
|
||||
- snippets
|
||||
@@ -961,11 +1015,24 @@ definitions:
|
||||
description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
|
||||
only.
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
snippets:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
uniqueItems: true
|
||||
last_connected_ip:
|
||||
description: i'm out of ideas
|
||||
type: string
|
||||
format: ipv4
|
||||
readOnly: true
|
||||
last_connected_at:
|
||||
description: really?
|
||||
type: string
|
||||
format: date
|
||||
readOnly: true
|
||||
securityDefinitions:
|
||||
basic:
|
||||
type: basic
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from drf_swagger import renderers
|
||||
|
||||
|
||||
def _check_swagger_setting(swagger, setting, expected):
|
||||
context = {}
|
||||
renderer = renderers.SwaggerUIRenderer()
|
||||
renderer.set_context(context, swagger)
|
||||
|
||||
swagger_settings = json.loads(context['swagger_settings'])
|
||||
assert swagger_settings[setting] == expected
|
||||
|
||||
|
||||
def _check_setting(swagger, setting, expected):
|
||||
context = {}
|
||||
renderer = renderers.SwaggerUIRenderer()
|
||||
renderer.set_context(context, swagger)
|
||||
assert context[setting] == expected
|
||||
|
||||
|
||||
def test_validator_url(swagger_settings, swagger):
|
||||
swagger_settings['VALIDATOR_URL'] = None
|
||||
_check_swagger_setting(swagger, 'validatorUrl', None)
|
||||
|
||||
swagger_settings['VALIDATOR_URL'] = 'not none'
|
||||
_check_swagger_setting(swagger, 'validatorUrl', 'not none')
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
swagger_settings['VALIDATOR_URL'] = ''
|
||||
_check_swagger_setting(swagger, 'validatorUrl', None)
|
||||
|
||||
|
||||
@pytest.mark.urls('urlconfs.login_test_urls')
|
||||
def test_login_logout(swagger_settings, swagger):
|
||||
swagger_settings['LOGIN_URL'] = 'login'
|
||||
_check_setting(swagger, 'LOGIN_URL', '/test/login')
|
||||
|
||||
swagger_settings['LOGOUT_URL'] = 'logout'
|
||||
_check_setting(swagger, 'LOGOUT_URL', '/test/logout')
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
swagger_settings['LOGIN_URL'] = None
|
||||
_check_setting(swagger, 'LOGIN_URL', None)
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
swagger_settings['LOGOUT_URL'] = None
|
||||
_check_setting(swagger, 'LOGOUT_URL', None)
|
||||
@@ -12,7 +12,7 @@ def test_schema_generates_without_errors(generator):
|
||||
|
||||
|
||||
def test_schema_is_valid(generator, codec_yaml):
|
||||
swagger = generator.get_schema(None, True)
|
||||
swagger = generator.get_schema(request=None, public=False)
|
||||
codec_yaml.encode(swagger)
|
||||
|
||||
|
||||
@@ -42,3 +42,17 @@ def test_yaml_codec_roundtrip(codec_yaml, generator, validate_schema):
|
||||
yaml_bytes = codec_yaml.encode(swagger)
|
||||
assert b'omap' not in yaml_bytes
|
||||
validate_schema(yaml.safe_load(yaml_bytes.decode('utf-8')))
|
||||
|
||||
|
||||
def test_basepath_only():
|
||||
generator = OpenAPISchemaGenerator(
|
||||
info=openapi.Info(title="Test generator", default_version="v1"),
|
||||
version="v2",
|
||||
url='/basepath/',
|
||||
)
|
||||
|
||||
swagger = generator.get_schema(None, public=True)
|
||||
assert 'host' not in swagger
|
||||
assert 'schemes' not in swagger
|
||||
assert swagger['basePath'] == '/' # base path is not implemented for now
|
||||
assert swagger['info']['version'] == 'v2'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from ruamel import yaml
|
||||
|
||||
|
||||
@@ -23,7 +24,13 @@ def test_swagger_yaml(client, validate_schema):
|
||||
_validate_text_schema_view(client, validate_schema, "/swagger.yaml", yaml.safe_load)
|
||||
|
||||
|
||||
def test_exception_middleware(client, bad_settings):
|
||||
def test_exception_middleware(client, swagger_settings):
|
||||
swagger_settings['SECURITY_DEFINITIONS'] = {
|
||||
'bad': {
|
||||
'bad_attribute': 'should not be accepted'
|
||||
}
|
||||
}
|
||||
|
||||
response = client.get('/swagger.json')
|
||||
assert response.status_code == 500
|
||||
assert 'errors' in json.loads(response.content.decode('utf-8'))
|
||||
@@ -37,3 +44,10 @@ def test_swagger_ui(client, validate_schema):
|
||||
def test_redoc(client, validate_schema):
|
||||
_validate_ui_schema_view(client, '/redoc/', 'redoc/redoc.min.js')
|
||||
_validate_text_schema_view(client, validate_schema, '/redoc/?format=openapi', json.loads)
|
||||
|
||||
|
||||
@pytest.mark.urls('urlconfs.non_public_urls')
|
||||
def test_non_public(client):
|
||||
response = client.get('/private/swagger.yaml')
|
||||
swagger = yaml.safe_load(response.content.decode('utf-8'))
|
||||
assert len(swagger['paths']) == 0
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from django.conf.urls import url
|
||||
|
||||
|
||||
def dummy(request):
|
||||
pass
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^test/login$', dummy, name='login'),
|
||||
url(r'^test/logout$', dummy, name='logout'),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import include
|
||||
from rest_framework import permissions
|
||||
|
||||
import testproj.urls
|
||||
from drf_swagger import openapi
|
||||
from drf_swagger.views import get_schema_view
|
||||
|
||||
view = get_schema_view(
|
||||
openapi.Info('bla', 'ble'),
|
||||
public=False,
|
||||
permission_classes=(permissions.AllowAny,)
|
||||
)
|
||||
view = view.without_ui(cache_timeout=None)
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^', include(testproj.urls)),
|
||||
url(r'^private/swagger.yaml', view, name='schema-private'),
|
||||
]
|
||||
Reference in New Issue
Block a user