mirror of
https://github.com/zulip/zulip.git
synced 2025-11-04 14:03:30 +00:00
Automatically detect if the OpenAPI spec file has been modified since the last time it was loaded into memory, and if it has, automatically reload it to have the latest version. This feature is designed with development environments in mind. The main benefit is being able to see the changes made to the OpenAPI document without needing to restart the development server, which is tedious and slows the documentation workflow down.
135 lines
4.9 KiB
Python
135 lines
4.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from typing import Dict, Any
|
|
|
|
import zerver.lib.openapi as openapi
|
|
from zerver.lib.test_classes import ZulipTestCase
|
|
from zerver.lib.openapi import (
|
|
get_openapi_fixture, get_openapi_parameters,
|
|
validate_against_openapi_schema, to_python_type, SchemaError, openapi_spec
|
|
)
|
|
|
|
TEST_ENDPOINT = '/messages/{message_id}'
|
|
TEST_METHOD = 'patch'
|
|
TEST_RESPONSE_BAD_REQ = '400'
|
|
TEST_RESPONSE_SUCCESS = '200'
|
|
|
|
|
|
class OpenAPIToolsTest(ZulipTestCase):
|
|
"""Make sure that the tools we use to handle our OpenAPI specification
|
|
(located in zerver/lib/openapi.py) work as expected.
|
|
|
|
These tools are mostly dedicated to fetching parts of the -already parsed-
|
|
specification, and comparing them to objects returned by our REST API.
|
|
"""
|
|
def test_get_openapi_fixture(self) -> None:
|
|
actual = get_openapi_fixture(TEST_ENDPOINT, TEST_METHOD,
|
|
TEST_RESPONSE_BAD_REQ)
|
|
expected = {
|
|
'code': 'BAD_REQUEST',
|
|
'msg': 'You don\'t have permission to edit this message',
|
|
'result': 'error'
|
|
}
|
|
self.assertEqual(actual, expected)
|
|
|
|
def test_get_openapi_parameters(self) -> None:
|
|
actual = get_openapi_parameters(TEST_ENDPOINT, TEST_METHOD)
|
|
expected_item = {
|
|
'name': 'message_id',
|
|
'in': 'path',
|
|
'description':
|
|
'The ID of the message that you wish to edit/update.',
|
|
'example': 42,
|
|
'required': True,
|
|
'schema': {'type': 'integer'}
|
|
}
|
|
assert(expected_item in actual)
|
|
|
|
def test_validate_against_openapi_schema(self) -> None:
|
|
with self.assertRaises(SchemaError,
|
|
msg=('Extraneous key "foo" in '
|
|
'the response\'scontent')):
|
|
bad_content = {
|
|
'msg': '',
|
|
'result': 'success',
|
|
'foo': 'bar'
|
|
} # type: Dict[str, Any]
|
|
validate_against_openapi_schema(bad_content,
|
|
TEST_ENDPOINT,
|
|
TEST_METHOD,
|
|
TEST_RESPONSE_SUCCESS)
|
|
|
|
with self.assertRaises(SchemaError,
|
|
msg=("Expected type <class 'str'> for key "
|
|
"\"msg\", but actually got "
|
|
"<class 'int'>")):
|
|
bad_content = {
|
|
'msg': 42,
|
|
'result': 'success',
|
|
}
|
|
validate_against_openapi_schema(bad_content,
|
|
TEST_ENDPOINT,
|
|
TEST_METHOD,
|
|
TEST_RESPONSE_SUCCESS)
|
|
|
|
with self.assertRaises(SchemaError,
|
|
msg='Expected to find the "msg" required key'):
|
|
bad_content = {
|
|
'result': 'success',
|
|
}
|
|
validate_against_openapi_schema(bad_content,
|
|
TEST_ENDPOINT,
|
|
TEST_METHOD,
|
|
TEST_RESPONSE_SUCCESS)
|
|
|
|
# No exceptions should be raised here.
|
|
good_content = {
|
|
'msg': '',
|
|
'result': 'success',
|
|
}
|
|
validate_against_openapi_schema(good_content,
|
|
TEST_ENDPOINT,
|
|
TEST_METHOD,
|
|
TEST_RESPONSE_SUCCESS)
|
|
|
|
# Overwrite the exception list with a mocked one
|
|
openapi.EXCLUDE_PROPERTIES = {
|
|
TEST_ENDPOINT: {
|
|
TEST_METHOD: {
|
|
TEST_RESPONSE_SUCCESS: ['foo']
|
|
}
|
|
}
|
|
}
|
|
good_content = {
|
|
'msg': '',
|
|
'result': 'success',
|
|
'foo': 'bar'
|
|
}
|
|
validate_against_openapi_schema(good_content,
|
|
TEST_ENDPOINT,
|
|
TEST_METHOD,
|
|
TEST_RESPONSE_SUCCESS)
|
|
|
|
def test_to_python_type(self) -> None:
|
|
TYPES = {
|
|
'string': str,
|
|
'number': float,
|
|
'integer': int,
|
|
'boolean': bool,
|
|
'array': list,
|
|
'object': dict
|
|
}
|
|
|
|
for oa_type, py_type in TYPES.items():
|
|
self.assertEqual(to_python_type(oa_type), py_type)
|
|
|
|
def test_live_reload(self) -> None:
|
|
# Force the reload by making the last update date < the file's last
|
|
# modified date
|
|
openapi_spec.last_update = 0
|
|
get_openapi_fixture(TEST_ENDPOINT, TEST_METHOD)
|
|
|
|
# Check that the file has been reloaded by verifying that the last
|
|
# update date isn't zero anymore
|
|
self.assertNotEqual(openapi_spec.last_update, 0)
|