| Index: third_party/google-endpoints/endpoints/test/openapi_generator_test.py
|
| diff --git a/third_party/google-endpoints/endpoints/test/openapi_generator_test.py b/third_party/google-endpoints/endpoints/test/openapi_generator_test.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5ee656cc3cac04eb0ec364b020a52cc1ef1646a5
|
| --- /dev/null
|
| +++ b/third_party/google-endpoints/endpoints/test/openapi_generator_test.py
|
| @@ -0,0 +1,913 @@
|
| +# Copyright 2016 Google Inc. All Rights Reserved.
|
| +#
|
| +# Licensed under the Apache License, Version 2.0 (the "License");
|
| +# you may not use this file except in compliance with the License.
|
| +# You may obtain a copy of the License at
|
| +#
|
| +# http://www.apache.org/licenses/LICENSE-2.0
|
| +#
|
| +# Unless required by applicable law or agreed to in writing, software
|
| +# distributed under the License is distributed on an "AS IS" BASIS,
|
| +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +# See the License for the specific language governing permissions and
|
| +# limitations under the License.
|
| +
|
| +"""Tests for endpoints.openapi_generator."""
|
| +
|
| +import json
|
| +import unittest
|
| +
|
| +import endpoints.api_config as api_config
|
| +
|
| +from protorpc import message_types
|
| +from protorpc import messages
|
| +from protorpc import remote
|
| +
|
| +import endpoints.resource_container as resource_container
|
| +import endpoints.openapi_generator as openapi_generator
|
| +import test_util
|
| +
|
| +
|
| +package = 'OpenApiGeneratorTest'
|
| +
|
| +
|
| +class Nested(messages.Message):
|
| + """Message class to be used in a message field."""
|
| + int_value = messages.IntegerField(1)
|
| + string_value = messages.StringField(2)
|
| +
|
| +
|
| +class SimpleEnum(messages.Enum):
|
| + """Simple enumeration type."""
|
| + VAL1 = 1
|
| + VAL2 = 2
|
| +
|
| +
|
| +class AllFields(messages.Message):
|
| + """Contains all field types."""
|
| +
|
| + bool_value = messages.BooleanField(1, variant=messages.Variant.BOOL)
|
| + bytes_value = messages.BytesField(2, variant=messages.Variant.BYTES)
|
| + double_value = messages.FloatField(3, variant=messages.Variant.DOUBLE)
|
| + enum_value = messages.EnumField(SimpleEnum, 4)
|
| + float_value = messages.FloatField(5, variant=messages.Variant.FLOAT)
|
| + int32_value = messages.IntegerField(6, variant=messages.Variant.INT32)
|
| + int64_value = messages.IntegerField(7, variant=messages.Variant.INT64)
|
| + string_value = messages.StringField(8, variant=messages.Variant.STRING)
|
| + uint32_value = messages.IntegerField(9, variant=messages.Variant.UINT32)
|
| + uint64_value = messages.IntegerField(10, variant=messages.Variant.UINT64)
|
| + sint32_value = messages.IntegerField(11, variant=messages.Variant.SINT32)
|
| + sint64_value = messages.IntegerField(12, variant=messages.Variant.SINT64)
|
| + message_field_value = messages.MessageField(Nested, 13)
|
| + datetime_value = message_types.DateTimeField(14)
|
| +
|
| +
|
| +# This is used test "all fields" as query parameters instead of the body
|
| +# in a request.
|
| +ALL_FIELDS_AS_PARAMETERS = resource_container.ResourceContainer(
|
| + **{field.name: field for field in AllFields.all_fields()})
|
| +
|
| +
|
| +class BaseOpenApiGeneratorTest(unittest.TestCase):
|
| +
|
| + @classmethod
|
| + def setUpClass(cls):
|
| + cls.maxDiff = None
|
| +
|
| + def setUp(self):
|
| + self.generator = openapi_generator.OpenApiGenerator()
|
| +
|
| + def _def_path(self, path):
|
| + return '#/definitions/' + path
|
| +
|
| +
|
| +class OpenApiGeneratorTest(BaseOpenApiGeneratorTest):
|
| +
|
| + def testAllFieldTypes(self):
|
| +
|
| + class PutRequest(messages.Message):
|
| + """Message with just a body field."""
|
| + body = messages.MessageField(AllFields, 1)
|
| +
|
| + # pylint: disable=invalid-name
|
| + class ItemsPutRequest(messages.Message):
|
| + """Message with path params and a body field."""
|
| + body = messages.MessageField(AllFields, 1)
|
| + entryId = messages.StringField(2, required=True)
|
| +
|
| + class ItemsPutRequestForContainer(messages.Message):
|
| + """Message with path params and a body field."""
|
| + body = messages.MessageField(AllFields, 1)
|
| + items_put_request_container = resource_container.ResourceContainer(
|
| + ItemsPutRequestForContainer,
|
| + entryId=messages.StringField(2, required=True))
|
| +
|
| + # pylint: disable=invalid-name
|
| + class EntryPublishRequest(messages.Message):
|
| + """Message with two required params, one in path, one in body."""
|
| + title = messages.StringField(1, required=True)
|
| + entryId = messages.StringField(2, required=True)
|
| +
|
| + class EntryPublishRequestForContainer(messages.Message):
|
| + """Message with two required params, one in path, one in body."""
|
| + title = messages.StringField(1, required=True)
|
| + entry_publish_request_container = resource_container.ResourceContainer(
|
| + EntryPublishRequestForContainer,
|
| + entryId=messages.StringField(2, required=True))
|
| +
|
| + class BooleanMessageResponse(messages.Message):
|
| + result = messages.BooleanField(1, required=True)
|
| +
|
| + @api_config.api(name='root', hostname='example.appspot.com', version='v1')
|
| + class MyService(remote.Service):
|
| + """Describes MyService."""
|
| +
|
| + @api_config.method(AllFields, message_types.VoidMessage, path='entries',
|
| + http_method='GET', name='entries.get')
|
| + def entries_get(self, unused_request):
|
| + """All field types in the query parameters."""
|
| + return message_types.VoidMessage()
|
| +
|
| + @api_config.method(ALL_FIELDS_AS_PARAMETERS, message_types.VoidMessage,
|
| + path='entries/container', http_method='GET',
|
| + name='entries.getContainer')
|
| + def entries_get_container(self, unused_request):
|
| + """All field types in the query parameters."""
|
| + return message_types.VoidMessage()
|
| +
|
| + @api_config.method(PutRequest, BooleanMessageResponse, path='entries',
|
| + name='entries.put')
|
| + def entries_put(self, unused_request):
|
| + """Request body is in the body field."""
|
| + return BooleanMessageResponse(result=True)
|
| +
|
| + @api_config.method(AllFields, message_types.VoidMessage, path='process',
|
| + name='entries.process')
|
| + def entries_process(self, unused_request):
|
| + """Message is the request body."""
|
| + return message_types.VoidMessage()
|
| +
|
| + @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
|
| + name='entries.nested.collection.action',
|
| + path='nested')
|
| + def entries_nested_collection_action(self, unused_request):
|
| + """A VoidMessage for a request body."""
|
| + return message_types.VoidMessage()
|
| +
|
| + @api_config.method(AllFields, AllFields, name='entries.roundtrip',
|
| + path='roundtrip')
|
| + def entries_roundtrip(self, unused_request):
|
| + """All field types in the request and response."""
|
| + pass
|
| +
|
| + # Test a method with a required parameter in the request body.
|
| + @api_config.method(EntryPublishRequest, message_types.VoidMessage,
|
| + path='entries/{entryId}/publish',
|
| + name='entries.publish')
|
| + def entries_publish(self, unused_request):
|
| + """Path has a parameter and request body has a required param."""
|
| + return message_types.VoidMessage()
|
| +
|
| + @api_config.method(entry_publish_request_container,
|
| + message_types.VoidMessage,
|
| + path='entries/container/{entryId}/publish',
|
| + name='entries.publishContainer')
|
| + def entries_publish_container(self, unused_request):
|
| + """Path has a parameter and request body has a required param."""
|
| + return message_types.VoidMessage()
|
| +
|
| + # Test a method with a parameter in the path and a request body.
|
| + @api_config.method(ItemsPutRequest, message_types.VoidMessage,
|
| + path='entries/{entryId}/items',
|
| + name='entries.items.put')
|
| + def items_put(self, unused_request):
|
| + """Path has a parameter and request body is in the body field."""
|
| + return message_types.VoidMessage()
|
| +
|
| + @api_config.method(items_put_request_container, message_types.VoidMessage,
|
| + path='entries/container/{entryId}/items',
|
| + name='entries.items.putContainer')
|
| + def items_put_container(self, unused_request):
|
| + """Path has a parameter and request body is in the body field."""
|
| + return message_types.VoidMessage()
|
| +
|
| + api = json.loads(self.generator.pretty_print_config_to_json(MyService))
|
| +
|
| + # Some constants to shorten line length in expected OpenAPI output
|
| + prefix = 'OpenApiGeneratorTest'
|
| + boolean_response = prefix + 'BooleanMessageResponse'
|
| + all_fields = prefix + 'AllFields'
|
| + nested = prefix + 'Nested'
|
| + entry_publish_request = prefix + 'EntryPublishRequest'
|
| + publish_request_for_container = prefix + 'EntryPublishRequestForContainer'
|
| + items_put_request = prefix + 'ItemsPutRequest'
|
| + put_request_for_container = prefix + 'ItemsPutRequestForContainer'
|
| + put_request = prefix + 'PutRequest'
|
| +
|
| + expected_openapi = {
|
| + 'swagger': '2.0',
|
| + 'info': {
|
| + 'title': 'root',
|
| + 'description': 'Describes MyService.',
|
| + 'version': 'v1',
|
| + },
|
| + 'host': 'example.appspot.com',
|
| + 'consumes': ['application/json'],
|
| + 'produces': ['application/json'],
|
| + 'schemes': ['https'],
|
| + 'basePath': '/_ah/api',
|
| + 'paths': {
|
| + '/root/v1/entries': {
|
| + 'get': {
|
| + 'operationId': 'MyService_entriesGet',
|
| + 'parameters': [
|
| + {
|
| + 'name': 'bool_value',
|
| + 'in': 'query',
|
| + 'type': 'boolean',
|
| + },
|
| + {
|
| + 'name': 'bytes_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'format': 'byte',
|
| + },
|
| + {
|
| + 'name': 'double_value',
|
| + 'in': 'query',
|
| + 'type': 'number',
|
| + 'format': 'double',
|
| + },
|
| + {
|
| + 'name': 'enum_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'enum': [
|
| + 'VAL1',
|
| + 'VAL2',
|
| + ],
|
| + },
|
| + {
|
| + 'name': 'float_value',
|
| + 'in': 'query',
|
| + 'type': 'number',
|
| + 'format': 'float',
|
| + },
|
| + {
|
| + 'name': 'int32_value',
|
| + 'in': 'query',
|
| + 'type': 'integer',
|
| + 'format': 'int32',
|
| + },
|
| + {
|
| + 'name': 'int64_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'format': 'int64',
|
| + },
|
| + {
|
| + 'name': 'string_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + },
|
| + {
|
| + 'name': 'uint32_value',
|
| + 'in': 'query',
|
| + 'type': 'integer',
|
| + 'format': 'uint32',
|
| + },
|
| + {
|
| + 'name': 'uint64_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'format': 'uint64',
|
| + },
|
| + {
|
| + 'name': 'sint32_value',
|
| + 'in': 'query',
|
| + 'type': 'integer',
|
| + 'format': 'int32',
|
| + },
|
| + {
|
| + 'name': 'sint64_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'format': 'int64',
|
| + }
|
| + ],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + 'post': {
|
| + 'operationId': 'MyService_entriesPut',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + 'schema': {
|
| + '$ref': self._def_path(boolean_response),
|
| + },
|
| + },
|
| + },
|
| + },
|
| + },
|
| + '/root/v1/entries/container': {
|
| + 'get': {
|
| + 'operationId': 'MyService_entriesGetContainer',
|
| + 'parameters': [
|
| + {
|
| + 'name': 'bool_value',
|
| + 'in': 'query',
|
| + 'type': 'boolean',
|
| + },
|
| + {
|
| + 'name': 'bytes_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'format': 'byte',
|
| + },
|
| + {
|
| + 'name': 'double_value',
|
| + 'in': 'query',
|
| + 'type': 'number',
|
| + 'format': 'double',
|
| + },
|
| + {
|
| + 'name': 'enum_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'enum': [
|
| + 'VAL1',
|
| + 'VAL2',
|
| + ],
|
| + },
|
| + {
|
| + 'name': 'float_value',
|
| + 'in': 'query',
|
| + 'type': 'number',
|
| + 'format': 'float',
|
| + },
|
| + {
|
| + 'name': 'int32_value',
|
| + 'in': 'query',
|
| + 'type': 'integer',
|
| + 'format': 'int32',
|
| + },
|
| + {
|
| + 'name': 'int64_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'format': 'int64',
|
| + },
|
| + {
|
| + 'name': 'string_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + },
|
| + {
|
| + 'name': 'uint32_value',
|
| + 'in': 'query',
|
| + 'type': 'integer',
|
| + 'format': 'uint32',
|
| + },
|
| + {
|
| + 'name': 'uint64_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'format': 'uint64',
|
| + },
|
| + {
|
| + 'name': 'sint32_value',
|
| + 'in': 'query',
|
| + 'type': 'integer',
|
| + 'format': 'int32',
|
| + },
|
| + {
|
| + 'name': 'sint64_value',
|
| + 'in': 'query',
|
| + 'type': 'string',
|
| + 'format': 'int64',
|
| + },
|
| + ],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + '/root/v1/entries/container/{entryId}/items': {
|
| + 'post': {
|
| + 'operationId': 'MyService_itemsPutContainer',
|
| + 'parameters': [
|
| + {
|
| + 'name': 'entryId',
|
| + 'in': 'path',
|
| + 'required': True,
|
| + 'type': 'string',
|
| + },
|
| + ],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + '/root/v1/entries/container/{entryId}/publish': {
|
| + 'post': {
|
| + 'operationId': 'MyService_entriesPublishContainer',
|
| + 'parameters': [
|
| + {
|
| + 'name': 'entryId',
|
| + 'in': 'path',
|
| + 'required': True,
|
| + 'type': 'string',
|
| + },
|
| + ],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + '/root/v1/entries/{entryId}/items': {
|
| + 'post': {
|
| + 'operationId': 'MyService_itemsPut',
|
| + 'parameters': [
|
| + {
|
| + 'name': 'entryId',
|
| + 'in': 'path',
|
| + 'required': True,
|
| + 'type': 'string',
|
| + },
|
| + ],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + '/root/v1/entries/{entryId}/publish': {
|
| + 'post': {
|
| + 'operationId': 'MyService_entriesPublish',
|
| + 'parameters': [
|
| + {
|
| + 'name': 'entryId',
|
| + 'in': 'path',
|
| + 'required': True,
|
| + 'type': 'string',
|
| + },
|
| + ],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + '/root/v1/nested': {
|
| + 'post': {
|
| + 'operationId': 'MyService_entriesNestedCollectionAction',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + '/root/v1/process': {
|
| + 'post': {
|
| + 'operationId': 'MyService_entriesProcess',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + '/root/v1/roundtrip': {
|
| + 'post': {
|
| + 'operationId': 'MyService_entriesRoundtrip',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + 'schema': {
|
| + '$ref': self._def_path(all_fields)
|
| + },
|
| + },
|
| + },
|
| + },
|
| + },
|
| + },
|
| + 'definitions': {
|
| + all_fields: {
|
| + 'type': 'object',
|
| + 'properties': {
|
| + 'bool_value': {
|
| + 'type': 'boolean',
|
| + },
|
| + 'bytes_value': {
|
| + 'type': 'string',
|
| + 'format': 'byte',
|
| + },
|
| + 'datetime_value': {
|
| + 'type': 'string',
|
| + 'format': 'date-time',
|
| + },
|
| + 'double_value': {
|
| + 'type': 'number',
|
| + 'format': 'double',
|
| + },
|
| + 'enum_value': {
|
| + 'type': 'string',
|
| + 'enum': [
|
| + 'VAL1',
|
| + 'VAL2',
|
| + ],
|
| + },
|
| + 'float_value': {
|
| + 'type': 'number',
|
| + 'format': 'float',
|
| + },
|
| + 'int32_value': {
|
| + 'type': 'integer',
|
| + 'format': 'int32',
|
| + },
|
| + 'int64_value': {
|
| + 'type': 'string',
|
| + 'format': 'int64',
|
| + },
|
| + 'message_field_value': {
|
| + '$ref': self._def_path(nested),
|
| + 'description':
|
| + 'Message class to be used in a message field.',
|
| + },
|
| + 'sint32_value': {
|
| + 'type': 'integer',
|
| + 'format': 'int32',
|
| + },
|
| + 'sint64_value': {
|
| + 'type': 'string',
|
| + 'format': 'int64',
|
| + },
|
| + 'string_value': {
|
| + 'type': 'string',
|
| + },
|
| + 'uint32_value': {
|
| + 'type': 'integer',
|
| + 'format': 'uint32',
|
| + },
|
| + 'uint64_value': {
|
| + 'type': 'string',
|
| + 'format': 'uint64',
|
| + },
|
| + },
|
| + },
|
| + boolean_response: {
|
| + 'type': 'object',
|
| + 'properties': {
|
| + 'result': {
|
| + 'type': 'boolean',
|
| + },
|
| + },
|
| + 'required': ['result'],
|
| + },
|
| + entry_publish_request: {
|
| + 'type': 'object',
|
| + 'properties': {
|
| + 'entryId': {
|
| + 'type': 'string',
|
| + },
|
| + 'title': {
|
| + 'type': 'string',
|
| + },
|
| + },
|
| + 'required': [
|
| + 'entryId',
|
| + 'title',
|
| + ]
|
| + },
|
| + publish_request_for_container: {
|
| + 'type': 'object',
|
| + 'properties': {
|
| + 'title': {
|
| + 'type': 'string',
|
| + },
|
| + },
|
| + 'required': [
|
| + 'title',
|
| + ]
|
| + },
|
| + items_put_request: {
|
| + 'type': 'object',
|
| + 'properties': {
|
| + 'body': {
|
| + '$ref': self._def_path(all_fields),
|
| + 'description': 'Contains all field types.'
|
| + },
|
| + 'entryId': {
|
| + 'type': 'string',
|
| + },
|
| + },
|
| + 'required': [
|
| + 'entryId',
|
| + ]
|
| + },
|
| + nested: {
|
| + 'type': 'object',
|
| + 'properties': {
|
| + 'int_value': {
|
| + 'type': 'string',
|
| + 'format': 'int64',
|
| + },
|
| + 'string_value': {
|
| + 'type': 'string',
|
| + },
|
| + },
|
| + },
|
| + put_request: {
|
| + 'type': 'object',
|
| + 'properties': {
|
| + 'body': {
|
| + '$ref': self._def_path(all_fields),
|
| + 'description': 'Contains all field types.',
|
| + },
|
| + },
|
| + },
|
| + put_request_for_container: {
|
| + 'type': 'object',
|
| + 'properties': {
|
| + 'body': {
|
| + '$ref': self._def_path(all_fields),
|
| + 'description': 'Contains all field types.',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + 'securityDefinitions': {
|
| + 'google_id_token': {
|
| + 'authorizationUrl': '',
|
| + 'flow': 'implicit',
|
| + 'type': 'oauth2',
|
| + 'x-issuer': 'accounts.google.com',
|
| + 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
|
| + },
|
| + },
|
| + }
|
| +
|
| + test_util.AssertDictEqual(expected_openapi, api, self)
|
| +
|
| + def testLocalhost(self):
|
| + @api_config.api(name='root', hostname='localhost:8080', version='v1')
|
| + class MyService(remote.Service):
|
| + """Describes MyService."""
|
| +
|
| + @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
|
| + path='noop', http_method='GET', name='noop')
|
| + def noop_get(self, unused_request):
|
| + return message_types.VoidMessage()
|
| +
|
| + api = json.loads(self.generator.pretty_print_config_to_json(MyService))
|
| +
|
| + expected_openapi = {
|
| + 'swagger': '2.0',
|
| + 'info': {
|
| + 'title': 'root',
|
| + 'description': 'Describes MyService.',
|
| + 'version': 'v1',
|
| + },
|
| + 'host': 'localhost:8080',
|
| + 'consumes': ['application/json'],
|
| + 'produces': ['application/json'],
|
| + 'schemes': ['http'],
|
| + 'basePath': '/_ah/api',
|
| + 'paths': {
|
| + '/root/v1/noop': {
|
| + 'get': {
|
| + 'operationId': 'MyService_noopGet',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + },
|
| + 'securityDefinitions': {
|
| + 'google_id_token': {
|
| + 'authorizationUrl': '',
|
| + 'flow': 'implicit',
|
| + 'type': 'oauth2',
|
| + 'x-issuer': 'accounts.google.com',
|
| + 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
|
| + },
|
| + },
|
| + }
|
| +
|
| + test_util.AssertDictEqual(expected_openapi, api, self)
|
| +
|
| + def testApiKeyRequired(self):
|
| +
|
| + @api_config.api(name='root', hostname='example.appspot.com', version='v1',
|
| + api_key_required=True)
|
| + class MyService(remote.Service):
|
| + """Describes MyService."""
|
| +
|
| + @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
|
| + path='noop', http_method='GET', name='noop')
|
| + def noop_get(self, unused_request):
|
| + return message_types.VoidMessage()
|
| +
|
| + @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
|
| + path='override', http_method='GET', name='override',
|
| + api_key_required=False)
|
| + def override_get(self, unused_request):
|
| + return message_types.VoidMessage()
|
| +
|
| + api = json.loads(self.generator.pretty_print_config_to_json(MyService))
|
| +
|
| + expected_openapi = {
|
| + 'swagger': '2.0',
|
| + 'info': {
|
| + 'title': 'root',
|
| + 'description': 'Describes MyService.',
|
| + 'version': 'v1',
|
| + },
|
| + 'host': 'example.appspot.com',
|
| + 'consumes': ['application/json'],
|
| + 'produces': ['application/json'],
|
| + 'schemes': ['https'],
|
| + 'basePath': '/_ah/api',
|
| + 'paths': {
|
| + '/root/v1/noop': {
|
| + 'get': {
|
| + 'operationId': 'MyService_noopGet',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + 'security': [
|
| + {
|
| + 'api_key': [],
|
| + }
|
| + ],
|
| + },
|
| + },
|
| + '/root/v1/override': {
|
| + 'get': {
|
| + 'operationId': 'MyService_overrideGet',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + },
|
| + 'securityDefinitions': {
|
| + 'google_id_token': {
|
| + 'authorizationUrl': '',
|
| + 'flow': 'implicit',
|
| + 'type': 'oauth2',
|
| + 'x-issuer': 'accounts.google.com',
|
| + 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
|
| + },
|
| + 'api_key': {
|
| + 'type': 'apiKey',
|
| + 'name': 'key',
|
| + 'in': 'query',
|
| + },
|
| + },
|
| + }
|
| +
|
| + test_util.AssertDictEqual(expected_openapi, api, self)
|
| +
|
| + def testCustomUrl(self):
|
| +
|
| + @api_config.api(name='root', hostname='example.appspot.com', version='v1',
|
| + base_path='/my/base/path/')
|
| + class MyService(remote.Service):
|
| + """Describes MyService."""
|
| +
|
| + @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
|
| + path='noop', http_method='GET', name='noop')
|
| + def noop_get(self, unused_request):
|
| + return message_types.VoidMessage()
|
| +
|
| + api = json.loads(self.generator.pretty_print_config_to_json(MyService))
|
| +
|
| + expected_openapi = {
|
| + 'swagger': '2.0',
|
| + 'info': {
|
| + 'title': 'root',
|
| + 'description': 'Describes MyService.',
|
| + 'version': 'v1',
|
| + },
|
| + 'host': 'example.appspot.com',
|
| + 'consumes': ['application/json'],
|
| + 'produces': ['application/json'],
|
| + 'schemes': ['https'],
|
| + 'basePath': '/my/base/path',
|
| + 'paths': {
|
| + '/root/v1/noop': {
|
| + 'get': {
|
| + 'operationId': 'MyService_noopGet',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + },
|
| + 'securityDefinitions': {
|
| + 'google_id_token': {
|
| + 'authorizationUrl': '',
|
| + 'flow': 'implicit',
|
| + 'type': 'oauth2',
|
| + 'x-issuer': 'accounts.google.com',
|
| + 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
|
| + },
|
| + },
|
| + }
|
| +
|
| + test_util.AssertDictEqual(expected_openapi, api, self)
|
| +
|
| +class DevServerOpenApiGeneratorTest(BaseOpenApiGeneratorTest,
|
| + test_util.DevServerTest):
|
| +
|
| + def setUp(self):
|
| + super(DevServerOpenApiGeneratorTest, self).setUp()
|
| + self.env_key, self.orig_env_value = (test_util.DevServerTest.
|
| + setUpDevServerEnv())
|
| + self.addCleanup(test_util.DevServerTest.restoreEnv,
|
| + self.env_key, self.orig_env_value)
|
| +
|
| + def testDevServerOpenApi(self):
|
| +
|
| + @api_config.api(name='root', hostname='example.appspot.com', version='v1')
|
| + class MyService(remote.Service):
|
| + """Describes MyService."""
|
| +
|
| + @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
|
| + path='noop', http_method='GET', name='noop')
|
| + def noop_get(self, unused_request):
|
| + return message_types.VoidMessage()
|
| +
|
| + api = json.loads(self.generator.pretty_print_config_to_json(MyService))
|
| +
|
| + expected_openapi = {
|
| + 'swagger': '2.0',
|
| + 'info': {
|
| + 'title': 'root',
|
| + 'description': 'Describes MyService.',
|
| + 'version': 'v1',
|
| + },
|
| + 'host': 'example.appspot.com',
|
| + 'consumes': ['application/json'],
|
| + 'produces': ['application/json'],
|
| + 'schemes': ['http'],
|
| + 'basePath': '/_ah/api',
|
| + 'paths': {
|
| + '/root/v1/noop': {
|
| + 'get': {
|
| + 'operationId': 'MyService_noopGet',
|
| + 'parameters': [],
|
| + 'responses': {
|
| + '200': {
|
| + 'description': 'A successful response',
|
| + },
|
| + },
|
| + },
|
| + },
|
| + },
|
| + 'securityDefinitions': {
|
| + 'google_id_token': {
|
| + 'authorizationUrl': '',
|
| + 'flow': 'implicit',
|
| + 'type': 'oauth2',
|
| + 'x-issuer': 'accounts.google.com',
|
| + 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
|
| + },
|
| + },
|
| + }
|
| +
|
| + test_util.AssertDictEqual(expected_openapi, api, self)
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + unittest.main()
|
|
|