Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: third_party/google-endpoints/endpoints/test/openapi_generator_test.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Tests for endpoints.openapi_generator."""
16
17 import json
18 import unittest
19
20 import endpoints.api_config as api_config
21
22 from protorpc import message_types
23 from protorpc import messages
24 from protorpc import remote
25
26 import endpoints.resource_container as resource_container
27 import endpoints.openapi_generator as openapi_generator
28 import test_util
29
30
31 package = 'OpenApiGeneratorTest'
32
33
34 class Nested(messages.Message):
35 """Message class to be used in a message field."""
36 int_value = messages.IntegerField(1)
37 string_value = messages.StringField(2)
38
39
40 class SimpleEnum(messages.Enum):
41 """Simple enumeration type."""
42 VAL1 = 1
43 VAL2 = 2
44
45
46 class AllFields(messages.Message):
47 """Contains all field types."""
48
49 bool_value = messages.BooleanField(1, variant=messages.Variant.BOOL)
50 bytes_value = messages.BytesField(2, variant=messages.Variant.BYTES)
51 double_value = messages.FloatField(3, variant=messages.Variant.DOUBLE)
52 enum_value = messages.EnumField(SimpleEnum, 4)
53 float_value = messages.FloatField(5, variant=messages.Variant.FLOAT)
54 int32_value = messages.IntegerField(6, variant=messages.Variant.INT32)
55 int64_value = messages.IntegerField(7, variant=messages.Variant.INT64)
56 string_value = messages.StringField(8, variant=messages.Variant.STRING)
57 uint32_value = messages.IntegerField(9, variant=messages.Variant.UINT32)
58 uint64_value = messages.IntegerField(10, variant=messages.Variant.UINT64)
59 sint32_value = messages.IntegerField(11, variant=messages.Variant.SINT32)
60 sint64_value = messages.IntegerField(12, variant=messages.Variant.SINT64)
61 message_field_value = messages.MessageField(Nested, 13)
62 datetime_value = message_types.DateTimeField(14)
63
64
65 # This is used test "all fields" as query parameters instead of the body
66 # in a request.
67 ALL_FIELDS_AS_PARAMETERS = resource_container.ResourceContainer(
68 **{field.name: field for field in AllFields.all_fields()})
69
70
71 class BaseOpenApiGeneratorTest(unittest.TestCase):
72
73 @classmethod
74 def setUpClass(cls):
75 cls.maxDiff = None
76
77 def setUp(self):
78 self.generator = openapi_generator.OpenApiGenerator()
79
80 def _def_path(self, path):
81 return '#/definitions/' + path
82
83
84 class OpenApiGeneratorTest(BaseOpenApiGeneratorTest):
85
86 def testAllFieldTypes(self):
87
88 class PutRequest(messages.Message):
89 """Message with just a body field."""
90 body = messages.MessageField(AllFields, 1)
91
92 # pylint: disable=invalid-name
93 class ItemsPutRequest(messages.Message):
94 """Message with path params and a body field."""
95 body = messages.MessageField(AllFields, 1)
96 entryId = messages.StringField(2, required=True)
97
98 class ItemsPutRequestForContainer(messages.Message):
99 """Message with path params and a body field."""
100 body = messages.MessageField(AllFields, 1)
101 items_put_request_container = resource_container.ResourceContainer(
102 ItemsPutRequestForContainer,
103 entryId=messages.StringField(2, required=True))
104
105 # pylint: disable=invalid-name
106 class EntryPublishRequest(messages.Message):
107 """Message with two required params, one in path, one in body."""
108 title = messages.StringField(1, required=True)
109 entryId = messages.StringField(2, required=True)
110
111 class EntryPublishRequestForContainer(messages.Message):
112 """Message with two required params, one in path, one in body."""
113 title = messages.StringField(1, required=True)
114 entry_publish_request_container = resource_container.ResourceContainer(
115 EntryPublishRequestForContainer,
116 entryId=messages.StringField(2, required=True))
117
118 class BooleanMessageResponse(messages.Message):
119 result = messages.BooleanField(1, required=True)
120
121 @api_config.api(name='root', hostname='example.appspot.com', version='v1')
122 class MyService(remote.Service):
123 """Describes MyService."""
124
125 @api_config.method(AllFields, message_types.VoidMessage, path='entries',
126 http_method='GET', name='entries.get')
127 def entries_get(self, unused_request):
128 """All field types in the query parameters."""
129 return message_types.VoidMessage()
130
131 @api_config.method(ALL_FIELDS_AS_PARAMETERS, message_types.VoidMessage,
132 path='entries/container', http_method='GET',
133 name='entries.getContainer')
134 def entries_get_container(self, unused_request):
135 """All field types in the query parameters."""
136 return message_types.VoidMessage()
137
138 @api_config.method(PutRequest, BooleanMessageResponse, path='entries',
139 name='entries.put')
140 def entries_put(self, unused_request):
141 """Request body is in the body field."""
142 return BooleanMessageResponse(result=True)
143
144 @api_config.method(AllFields, message_types.VoidMessage, path='process',
145 name='entries.process')
146 def entries_process(self, unused_request):
147 """Message is the request body."""
148 return message_types.VoidMessage()
149
150 @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
151 name='entries.nested.collection.action',
152 path='nested')
153 def entries_nested_collection_action(self, unused_request):
154 """A VoidMessage for a request body."""
155 return message_types.VoidMessage()
156
157 @api_config.method(AllFields, AllFields, name='entries.roundtrip',
158 path='roundtrip')
159 def entries_roundtrip(self, unused_request):
160 """All field types in the request and response."""
161 pass
162
163 # Test a method with a required parameter in the request body.
164 @api_config.method(EntryPublishRequest, message_types.VoidMessage,
165 path='entries/{entryId}/publish',
166 name='entries.publish')
167 def entries_publish(self, unused_request):
168 """Path has a parameter and request body has a required param."""
169 return message_types.VoidMessage()
170
171 @api_config.method(entry_publish_request_container,
172 message_types.VoidMessage,
173 path='entries/container/{entryId}/publish',
174 name='entries.publishContainer')
175 def entries_publish_container(self, unused_request):
176 """Path has a parameter and request body has a required param."""
177 return message_types.VoidMessage()
178
179 # Test a method with a parameter in the path and a request body.
180 @api_config.method(ItemsPutRequest, message_types.VoidMessage,
181 path='entries/{entryId}/items',
182 name='entries.items.put')
183 def items_put(self, unused_request):
184 """Path has a parameter and request body is in the body field."""
185 return message_types.VoidMessage()
186
187 @api_config.method(items_put_request_container, message_types.VoidMessage,
188 path='entries/container/{entryId}/items',
189 name='entries.items.putContainer')
190 def items_put_container(self, unused_request):
191 """Path has a parameter and request body is in the body field."""
192 return message_types.VoidMessage()
193
194 api = json.loads(self.generator.pretty_print_config_to_json(MyService))
195
196 # Some constants to shorten line length in expected OpenAPI output
197 prefix = 'OpenApiGeneratorTest'
198 boolean_response = prefix + 'BooleanMessageResponse'
199 all_fields = prefix + 'AllFields'
200 nested = prefix + 'Nested'
201 entry_publish_request = prefix + 'EntryPublishRequest'
202 publish_request_for_container = prefix + 'EntryPublishRequestForContainer'
203 items_put_request = prefix + 'ItemsPutRequest'
204 put_request_for_container = prefix + 'ItemsPutRequestForContainer'
205 put_request = prefix + 'PutRequest'
206
207 expected_openapi = {
208 'swagger': '2.0',
209 'info': {
210 'title': 'root',
211 'description': 'Describes MyService.',
212 'version': 'v1',
213 },
214 'host': 'example.appspot.com',
215 'consumes': ['application/json'],
216 'produces': ['application/json'],
217 'schemes': ['https'],
218 'basePath': '/_ah/api',
219 'paths': {
220 '/root/v1/entries': {
221 'get': {
222 'operationId': 'MyService_entriesGet',
223 'parameters': [
224 {
225 'name': 'bool_value',
226 'in': 'query',
227 'type': 'boolean',
228 },
229 {
230 'name': 'bytes_value',
231 'in': 'query',
232 'type': 'string',
233 'format': 'byte',
234 },
235 {
236 'name': 'double_value',
237 'in': 'query',
238 'type': 'number',
239 'format': 'double',
240 },
241 {
242 'name': 'enum_value',
243 'in': 'query',
244 'type': 'string',
245 'enum': [
246 'VAL1',
247 'VAL2',
248 ],
249 },
250 {
251 'name': 'float_value',
252 'in': 'query',
253 'type': 'number',
254 'format': 'float',
255 },
256 {
257 'name': 'int32_value',
258 'in': 'query',
259 'type': 'integer',
260 'format': 'int32',
261 },
262 {
263 'name': 'int64_value',
264 'in': 'query',
265 'type': 'string',
266 'format': 'int64',
267 },
268 {
269 'name': 'string_value',
270 'in': 'query',
271 'type': 'string',
272 },
273 {
274 'name': 'uint32_value',
275 'in': 'query',
276 'type': 'integer',
277 'format': 'uint32',
278 },
279 {
280 'name': 'uint64_value',
281 'in': 'query',
282 'type': 'string',
283 'format': 'uint64',
284 },
285 {
286 'name': 'sint32_value',
287 'in': 'query',
288 'type': 'integer',
289 'format': 'int32',
290 },
291 {
292 'name': 'sint64_value',
293 'in': 'query',
294 'type': 'string',
295 'format': 'int64',
296 }
297 ],
298 'responses': {
299 '200': {
300 'description': 'A successful response',
301 },
302 },
303 },
304 'post': {
305 'operationId': 'MyService_entriesPut',
306 'parameters': [],
307 'responses': {
308 '200': {
309 'description': 'A successful response',
310 'schema': {
311 '$ref': self._def_path(boolean_response),
312 },
313 },
314 },
315 },
316 },
317 '/root/v1/entries/container': {
318 'get': {
319 'operationId': 'MyService_entriesGetContainer',
320 'parameters': [
321 {
322 'name': 'bool_value',
323 'in': 'query',
324 'type': 'boolean',
325 },
326 {
327 'name': 'bytes_value',
328 'in': 'query',
329 'type': 'string',
330 'format': 'byte',
331 },
332 {
333 'name': 'double_value',
334 'in': 'query',
335 'type': 'number',
336 'format': 'double',
337 },
338 {
339 'name': 'enum_value',
340 'in': 'query',
341 'type': 'string',
342 'enum': [
343 'VAL1',
344 'VAL2',
345 ],
346 },
347 {
348 'name': 'float_value',
349 'in': 'query',
350 'type': 'number',
351 'format': 'float',
352 },
353 {
354 'name': 'int32_value',
355 'in': 'query',
356 'type': 'integer',
357 'format': 'int32',
358 },
359 {
360 'name': 'int64_value',
361 'in': 'query',
362 'type': 'string',
363 'format': 'int64',
364 },
365 {
366 'name': 'string_value',
367 'in': 'query',
368 'type': 'string',
369 },
370 {
371 'name': 'uint32_value',
372 'in': 'query',
373 'type': 'integer',
374 'format': 'uint32',
375 },
376 {
377 'name': 'uint64_value',
378 'in': 'query',
379 'type': 'string',
380 'format': 'uint64',
381 },
382 {
383 'name': 'sint32_value',
384 'in': 'query',
385 'type': 'integer',
386 'format': 'int32',
387 },
388 {
389 'name': 'sint64_value',
390 'in': 'query',
391 'type': 'string',
392 'format': 'int64',
393 },
394 ],
395 'responses': {
396 '200': {
397 'description': 'A successful response',
398 },
399 },
400 },
401 },
402 '/root/v1/entries/container/{entryId}/items': {
403 'post': {
404 'operationId': 'MyService_itemsPutContainer',
405 'parameters': [
406 {
407 'name': 'entryId',
408 'in': 'path',
409 'required': True,
410 'type': 'string',
411 },
412 ],
413 'responses': {
414 '200': {
415 'description': 'A successful response',
416 },
417 },
418 },
419 },
420 '/root/v1/entries/container/{entryId}/publish': {
421 'post': {
422 'operationId': 'MyService_entriesPublishContainer',
423 'parameters': [
424 {
425 'name': 'entryId',
426 'in': 'path',
427 'required': True,
428 'type': 'string',
429 },
430 ],
431 'responses': {
432 '200': {
433 'description': 'A successful response',
434 },
435 },
436 },
437 },
438 '/root/v1/entries/{entryId}/items': {
439 'post': {
440 'operationId': 'MyService_itemsPut',
441 'parameters': [
442 {
443 'name': 'entryId',
444 'in': 'path',
445 'required': True,
446 'type': 'string',
447 },
448 ],
449 'responses': {
450 '200': {
451 'description': 'A successful response',
452 },
453 },
454 },
455 },
456 '/root/v1/entries/{entryId}/publish': {
457 'post': {
458 'operationId': 'MyService_entriesPublish',
459 'parameters': [
460 {
461 'name': 'entryId',
462 'in': 'path',
463 'required': True,
464 'type': 'string',
465 },
466 ],
467 'responses': {
468 '200': {
469 'description': 'A successful response',
470 },
471 },
472 },
473 },
474 '/root/v1/nested': {
475 'post': {
476 'operationId': 'MyService_entriesNestedCollectionAction',
477 'parameters': [],
478 'responses': {
479 '200': {
480 'description': 'A successful response',
481 },
482 },
483 },
484 },
485 '/root/v1/process': {
486 'post': {
487 'operationId': 'MyService_entriesProcess',
488 'parameters': [],
489 'responses': {
490 '200': {
491 'description': 'A successful response',
492 },
493 },
494 },
495 },
496 '/root/v1/roundtrip': {
497 'post': {
498 'operationId': 'MyService_entriesRoundtrip',
499 'parameters': [],
500 'responses': {
501 '200': {
502 'description': 'A successful response',
503 'schema': {
504 '$ref': self._def_path(all_fields)
505 },
506 },
507 },
508 },
509 },
510 },
511 'definitions': {
512 all_fields: {
513 'type': 'object',
514 'properties': {
515 'bool_value': {
516 'type': 'boolean',
517 },
518 'bytes_value': {
519 'type': 'string',
520 'format': 'byte',
521 },
522 'datetime_value': {
523 'type': 'string',
524 'format': 'date-time',
525 },
526 'double_value': {
527 'type': 'number',
528 'format': 'double',
529 },
530 'enum_value': {
531 'type': 'string',
532 'enum': [
533 'VAL1',
534 'VAL2',
535 ],
536 },
537 'float_value': {
538 'type': 'number',
539 'format': 'float',
540 },
541 'int32_value': {
542 'type': 'integer',
543 'format': 'int32',
544 },
545 'int64_value': {
546 'type': 'string',
547 'format': 'int64',
548 },
549 'message_field_value': {
550 '$ref': self._def_path(nested),
551 'description':
552 'Message class to be used in a message field.',
553 },
554 'sint32_value': {
555 'type': 'integer',
556 'format': 'int32',
557 },
558 'sint64_value': {
559 'type': 'string',
560 'format': 'int64',
561 },
562 'string_value': {
563 'type': 'string',
564 },
565 'uint32_value': {
566 'type': 'integer',
567 'format': 'uint32',
568 },
569 'uint64_value': {
570 'type': 'string',
571 'format': 'uint64',
572 },
573 },
574 },
575 boolean_response: {
576 'type': 'object',
577 'properties': {
578 'result': {
579 'type': 'boolean',
580 },
581 },
582 'required': ['result'],
583 },
584 entry_publish_request: {
585 'type': 'object',
586 'properties': {
587 'entryId': {
588 'type': 'string',
589 },
590 'title': {
591 'type': 'string',
592 },
593 },
594 'required': [
595 'entryId',
596 'title',
597 ]
598 },
599 publish_request_for_container: {
600 'type': 'object',
601 'properties': {
602 'title': {
603 'type': 'string',
604 },
605 },
606 'required': [
607 'title',
608 ]
609 },
610 items_put_request: {
611 'type': 'object',
612 'properties': {
613 'body': {
614 '$ref': self._def_path(all_fields),
615 'description': 'Contains all field types.'
616 },
617 'entryId': {
618 'type': 'string',
619 },
620 },
621 'required': [
622 'entryId',
623 ]
624 },
625 nested: {
626 'type': 'object',
627 'properties': {
628 'int_value': {
629 'type': 'string',
630 'format': 'int64',
631 },
632 'string_value': {
633 'type': 'string',
634 },
635 },
636 },
637 put_request: {
638 'type': 'object',
639 'properties': {
640 'body': {
641 '$ref': self._def_path(all_fields),
642 'description': 'Contains all field types.',
643 },
644 },
645 },
646 put_request_for_container: {
647 'type': 'object',
648 'properties': {
649 'body': {
650 '$ref': self._def_path(all_fields),
651 'description': 'Contains all field types.',
652 },
653 },
654 },
655 },
656 'securityDefinitions': {
657 'google_id_token': {
658 'authorizationUrl': '',
659 'flow': 'implicit',
660 'type': 'oauth2',
661 'x-issuer': 'accounts.google.com',
662 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
663 },
664 },
665 }
666
667 test_util.AssertDictEqual(expected_openapi, api, self)
668
669 def testLocalhost(self):
670 @api_config.api(name='root', hostname='localhost:8080', version='v1')
671 class MyService(remote.Service):
672 """Describes MyService."""
673
674 @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
675 path='noop', http_method='GET', name='noop')
676 def noop_get(self, unused_request):
677 return message_types.VoidMessage()
678
679 api = json.loads(self.generator.pretty_print_config_to_json(MyService))
680
681 expected_openapi = {
682 'swagger': '2.0',
683 'info': {
684 'title': 'root',
685 'description': 'Describes MyService.',
686 'version': 'v1',
687 },
688 'host': 'localhost:8080',
689 'consumes': ['application/json'],
690 'produces': ['application/json'],
691 'schemes': ['http'],
692 'basePath': '/_ah/api',
693 'paths': {
694 '/root/v1/noop': {
695 'get': {
696 'operationId': 'MyService_noopGet',
697 'parameters': [],
698 'responses': {
699 '200': {
700 'description': 'A successful response',
701 },
702 },
703 },
704 },
705 },
706 'securityDefinitions': {
707 'google_id_token': {
708 'authorizationUrl': '',
709 'flow': 'implicit',
710 'type': 'oauth2',
711 'x-issuer': 'accounts.google.com',
712 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
713 },
714 },
715 }
716
717 test_util.AssertDictEqual(expected_openapi, api, self)
718
719 def testApiKeyRequired(self):
720
721 @api_config.api(name='root', hostname='example.appspot.com', version='v1',
722 api_key_required=True)
723 class MyService(remote.Service):
724 """Describes MyService."""
725
726 @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
727 path='noop', http_method='GET', name='noop')
728 def noop_get(self, unused_request):
729 return message_types.VoidMessage()
730
731 @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
732 path='override', http_method='GET', name='override',
733 api_key_required=False)
734 def override_get(self, unused_request):
735 return message_types.VoidMessage()
736
737 api = json.loads(self.generator.pretty_print_config_to_json(MyService))
738
739 expected_openapi = {
740 'swagger': '2.0',
741 'info': {
742 'title': 'root',
743 'description': 'Describes MyService.',
744 'version': 'v1',
745 },
746 'host': 'example.appspot.com',
747 'consumes': ['application/json'],
748 'produces': ['application/json'],
749 'schemes': ['https'],
750 'basePath': '/_ah/api',
751 'paths': {
752 '/root/v1/noop': {
753 'get': {
754 'operationId': 'MyService_noopGet',
755 'parameters': [],
756 'responses': {
757 '200': {
758 'description': 'A successful response',
759 },
760 },
761 'security': [
762 {
763 'api_key': [],
764 }
765 ],
766 },
767 },
768 '/root/v1/override': {
769 'get': {
770 'operationId': 'MyService_overrideGet',
771 'parameters': [],
772 'responses': {
773 '200': {
774 'description': 'A successful response',
775 },
776 },
777 },
778 },
779 },
780 'securityDefinitions': {
781 'google_id_token': {
782 'authorizationUrl': '',
783 'flow': 'implicit',
784 'type': 'oauth2',
785 'x-issuer': 'accounts.google.com',
786 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
787 },
788 'api_key': {
789 'type': 'apiKey',
790 'name': 'key',
791 'in': 'query',
792 },
793 },
794 }
795
796 test_util.AssertDictEqual(expected_openapi, api, self)
797
798 def testCustomUrl(self):
799
800 @api_config.api(name='root', hostname='example.appspot.com', version='v1',
801 base_path='/my/base/path/')
802 class MyService(remote.Service):
803 """Describes MyService."""
804
805 @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
806 path='noop', http_method='GET', name='noop')
807 def noop_get(self, unused_request):
808 return message_types.VoidMessage()
809
810 api = json.loads(self.generator.pretty_print_config_to_json(MyService))
811
812 expected_openapi = {
813 'swagger': '2.0',
814 'info': {
815 'title': 'root',
816 'description': 'Describes MyService.',
817 'version': 'v1',
818 },
819 'host': 'example.appspot.com',
820 'consumes': ['application/json'],
821 'produces': ['application/json'],
822 'schemes': ['https'],
823 'basePath': '/my/base/path',
824 'paths': {
825 '/root/v1/noop': {
826 'get': {
827 'operationId': 'MyService_noopGet',
828 'parameters': [],
829 'responses': {
830 '200': {
831 'description': 'A successful response',
832 },
833 },
834 },
835 },
836 },
837 'securityDefinitions': {
838 'google_id_token': {
839 'authorizationUrl': '',
840 'flow': 'implicit',
841 'type': 'oauth2',
842 'x-issuer': 'accounts.google.com',
843 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
844 },
845 },
846 }
847
848 test_util.AssertDictEqual(expected_openapi, api, self)
849
850 class DevServerOpenApiGeneratorTest(BaseOpenApiGeneratorTest,
851 test_util.DevServerTest):
852
853 def setUp(self):
854 super(DevServerOpenApiGeneratorTest, self).setUp()
855 self.env_key, self.orig_env_value = (test_util.DevServerTest.
856 setUpDevServerEnv())
857 self.addCleanup(test_util.DevServerTest.restoreEnv,
858 self.env_key, self.orig_env_value)
859
860 def testDevServerOpenApi(self):
861
862 @api_config.api(name='root', hostname='example.appspot.com', version='v1')
863 class MyService(remote.Service):
864 """Describes MyService."""
865
866 @api_config.method(message_types.VoidMessage, message_types.VoidMessage,
867 path='noop', http_method='GET', name='noop')
868 def noop_get(self, unused_request):
869 return message_types.VoidMessage()
870
871 api = json.loads(self.generator.pretty_print_config_to_json(MyService))
872
873 expected_openapi = {
874 'swagger': '2.0',
875 'info': {
876 'title': 'root',
877 'description': 'Describes MyService.',
878 'version': 'v1',
879 },
880 'host': 'example.appspot.com',
881 'consumes': ['application/json'],
882 'produces': ['application/json'],
883 'schemes': ['http'],
884 'basePath': '/_ah/api',
885 'paths': {
886 '/root/v1/noop': {
887 'get': {
888 'operationId': 'MyService_noopGet',
889 'parameters': [],
890 'responses': {
891 '200': {
892 'description': 'A successful response',
893 },
894 },
895 },
896 },
897 },
898 'securityDefinitions': {
899 'google_id_token': {
900 'authorizationUrl': '',
901 'flow': 'implicit',
902 'type': 'oauth2',
903 'x-issuer': 'accounts.google.com',
904 'x-jwks_uri': 'https://www.googleapis.com/oauth2/v1/certs',
905 },
906 },
907 }
908
909 test_util.AssertDictEqual(expected_openapi, api, self)
910
911
912 if __name__ == '__main__':
913 unittest.main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698