def test_method_security_headers(self): api = restplus.Api(self.app, authorizations={ 'apikey': { 'type': 'apiKey', 'in': 'header', 'name': 'X-API' } }) @api.route('/secure/') class Secure(restplus.Resource): @api.doc('secure', security='apikey') def get(self): pass @api.route('/unsecure/') class Unsecure(restplus.Resource): @api.doc('unsecure') def get(self): pass data = api.as_postman() validate(data, schema) requests = dict((r['name'], r['headers']) for r in data['requests']) self.assertEqual(requests['unsecure'], '') self.assertEqual(requests['secure'], 'X-API:')
def test_url_variables_enabled(self): api = restplus.Api(self.app) parser = api.parser() parser.add_argument('int', type=int) parser.add_argument('default', type=int, default=5) parser.add_argument('str', type=str) @api.route('/test/') class Test(restplus.Resource): @api.doc(parser=parser) def get(self): pass data = api.as_postman(urlvars=True) validate(data, schema) self.assertEqual(len(data['requests']), 1) request = data['requests'][0] qs = parse_qs(urlparse(request['url']).query, keep_blank_values=True) self.assertIn('int', qs) self.assertEqual(qs['int'][0], '0') self.assertIn('default', qs) self.assertEqual(qs['default'][0], '5') self.assertIn('str', qs) self.assertEqual(qs['str'][0], '')
def test_root_endpoint(self): api = restplus.Api(self.app, version='1.0') with self.context(): url = url_for('root') self.assertEqual(url, '/') self.assertEqual(api.base_url, 'http://localhost/')
def test_export_with_namespace(self): api = restplus.Api(self.app) ns = api.namespace('test', 'A test namespace') @ns.route('/test') class Test(restplus.Resource): @api.doc('test_post') def post(self): '''A test post''' pass data = api.as_postman() validate(data, schema) self.assertEqual(len(data['requests']), 1) request = data['requests'][0] self.assertEqual(request['name'], 'test_post') self.assertEqual(request['description'], 'A test post') self.assertEqual(len(data['folders']), 2) folder = data['folders'][1] self.assertEqual(folder['name'], 'test') self.assertEqual(folder['description'], 'A test namespace') self.assertEqual(request['folder'], folder['id'])
def test_errorhandler_lazy(self): api = restplus.Api() class CustomException(RuntimeError): pass @api.route('/test/', endpoint='test') class TestResource(restplus.Resource): def get(self): raise CustomException('error') @api.errorhandler(CustomException) def handle_custom_exception(error): return {'message': str(error), 'test': 'value'}, 400 api.init_app(self.app) with self.app.test_client() as client: response = client.get('/test/') self.assertEquals(response.status_code, 400) self.assertEquals(response.content_type, 'application/json') data = json.loads(response.data.decode('utf8')) self.assertEqual(data, { 'message': 'error', 'test': 'value', })
def test_validation_on_list(self): '''It should perform validation on lists''' api = restplus.Api(self.app, validate=True) person = api.model('Person', { 'name': restplus.fields.String(required=True), 'age': restplus.fields.Integer(required=True), }) family = api.model('Family', { 'name': restplus.fields.String(required=True), 'members': restplus.fields.List(restplus.fields.Nested(person)) }) @api.route('/validation/') class List(restplus.Resource): @api.expect(family) def post(self): return {} response = self.post('/validation/', { 'name': 'Doe', 'members': [{'name': 'Jonn'}, {'age': 42}] }) self.assert_errors(response, 'members.0.age', 'members.1.name')
def test_validation_with_inheritance(self): '''It should perform validation with inheritance (allOf/$ref)''' api = restplus.Api(self.app, validate=True) fields = api.model('Parent', { 'name': restplus.fields.String(required=True), }) child_fields = api.inherit('Child', fields, { 'age': restplus.fields.Integer, }) @api.route('/validation/') class Inheritance(restplus.Resource): @api.expect(child_fields) def post(self): return {} response = self.post('/validation/', { 'name': 'John Doe', 'age': 15, }) self.assertEquals(response.status_code, 200) response = self.post('/validation/', { 'age': '15', }) self.assert_errors(response, 'name', 'age')
def test_api_payload(self): api = restplus.Api(self.app, validate=True) fields = api.model('Person', { 'name': restplus.fields.String(required=True), 'age': restplus.fields.Integer, 'birthdate': restplus.fields.DateTime, }) @api.route('/validation/') class Payload(restplus.Resource): payload = None @api.expect(fields) def post(self): Payload.payload = api.payload return {} data = { 'name': 'John Doe', 'age': 15, } response = self.post('/validation/', data) self.assertEquals(response.status_code, 200) self.assertEquals(Payload.payload, data)
def test_default_apidoc_on_root(self): restplus.Api(self.app, version='1.0') with self.context(), self.app.test_client() as client: response = client.get(url_for('root')) self.assertEquals(response.status_code, 200) self.assertEquals(response.content_type, 'text/html; charset=utf-8')
def test_id_is_the_same(self): api = restplus.Api(self.app) first = api.as_postman() second = api.as_postman() self.assertEqual(first['id'], second['id'])
def test_basic_export(self): api = restplus.Api(self.app) data = api.as_postman() validate(data, schema) self.assertEqual(len(data['requests']), 0)
def test_root_endpoint_with_blueprint(self): blueprint = Blueprint('api', __name__, url_prefix='/api') api = restplus.Api(blueprint, version='1.0') # api.init_app(self.app) self.app.register_blueprint(blueprint) with self.context(): url = url_for('api.root') self.assertEqual(url, '/api/') self.assertEqual(api.base_url, 'http://localhost/api/')
def test_default_apidoc_on_root_with_blueprint(self): blueprint = Blueprint('api', __name__, url_prefix='/api') restplus.Api(blueprint, version='1.0') self.app.register_blueprint(blueprint) with self.context(), self.app.test_client() as client: response = client.get(url_for('api.root')) self.assertEquals(response.status_code, 200) self.assertEquals(response.content_type, 'text/html; charset=utf-8')
def test_doc_decorator(self): api = restplus.Api(self.app, prefix='/api', version='1.0') params = {'q': {'description': 'some description'}} @api.doc(params=params) class TestResource(restplus.Resource): pass self.assertTrue(hasattr(TestResource, '__apidoc__')) self.assertEqual(TestResource.__apidoc__, {'params': params})
def test_disabled_apidoc(self): restplus.Api(self.app, version='1.0', doc=False) with self.context(): with self.app.test_client() as client: with self.assertRaises(BuildError): url_for('doc') response = client.get(url_for('root')) self.assertEquals(response.status_code, 404)
def test_apidoc_with_custom_validator(self): self.app.config['SWAGGER_VALIDATOR_URL'] = 'http://somewhere.com/validator' restplus.Api(self.app, version='1.0') with self.context(): with self.app.test_client() as client: response = client.get(url_for('doc')) self.assertEquals(response.status_code, 200) self.assertEquals(response.content_type, 'text/html; charset=utf-8') self.assertIn('validatorUrl: "http://somewhere.com/validator" || null,', str(response.data))
def test_default_apidoc_on_root_lazy(self): api = restplus.Api(version='1.0') api.init_app(self.app) with self.context(): self.assertEqual(url_for('doc'), url_for('root')) with self.app.test_client() as client: response = client.get(url_for('doc')) self.assertEquals(response.status_code, 200) self.assertEquals(response.content_type, 'text/html; charset=utf-8')
def test_custom_apidoc_page(self): api = restplus.Api(self.app, version='1.0') content = 'My Custom API Doc' @api.documentation def api_doc(): return content with self.context(): with self.app.test_client() as client: response = client.get(url_for('doc')) self.assertEquals(response.status_code, 200) self.assertEquals(response.data.decode('utf8'), content)
def test_export_with_swagger(self): api = restplus.Api(self.app) data = api.as_postman(swagger=True) validate(data, schema) self.assertEqual(len(data['requests']), 1) request = data['requests'][0] self.assertEqual(request['name'], 'Swagger specifications') self.assertEqual(request['description'], 'The API Swagger specifications as JSON') self.assertEqual(request['url'], 'http://localhost/swagger.json')
def test_export_infos(self): api = restplus.Api( self.app, version='1.0', title='My API', description='This is a testing API', ) data = api.as_postman() validate(data, schema) self.assertEqual(data['name'], 'My API 1.0') self.assertEqual(data['description'], 'This is a testing API')
def test_abort_on_exception(self): api = restplus.Api(self.app) @api.route('/test/', endpoint='test') class TestResource(restplus.Resource): def get(self): raise ValueError() with self.app.test_client() as client: response = client.get('/test/') self.assertEquals(response.status_code, 500) self.assertEquals(response.content_type, 'application/json') data = json.loads(response.data.decode('utf8')) self.assertIn('message', data)
def test_abort_with_message(self): api = restplus.Api(self.app) @api.route('/test/', endpoint='test') class TestResource(restplus.Resource): def get(self): api.abort(403, 'A message') with self.app.test_client() as client: response = client.get('/test/') self.assertEquals(response.status_code, 403) self.assertEquals(response.content_type, 'application/json') data = json.loads(response.data.decode('utf8')) self.assertEqual(data['message'], 'A message')
def test_content_type_header(self): api = restplus.Api(self.app) form_parser = api.parser() form_parser.add_argument('param', type=int, help='Some param', location='form') file_parser = api.parser() file_parser.add_argument('in_files', type=FileStorage, location='files') @api.route('/json/') class TestJson(restplus.Resource): @api.doc('json') def post(self): pass @api.route('/form/') class TestForm(restplus.Resource): @api.doc('form', parser=form_parser) def post(self): pass @api.route('/file/') class TestFile(restplus.Resource): @api.doc('file', parser=file_parser) def post(self): pass @api.route('/get/') class TestGet(restplus.Resource): @api.doc('get') def get(self): pass data = api.as_postman(urlvars=True) validate(data, schema) requests = dict((r['name'], r['headers']) for r in data['requests']) self.assertEqual(requests['json'], 'Content-Type:application/json') self.assertEqual(requests['form'], 'Content-Type:multipart/form-data') self.assertEqual(requests['file'], 'Content-Type:multipart/form-data') # No content-type on get self.assertEqual(requests['get'], '')
def test_custom_apidoc_page_lazy(self): blueprint = Blueprint('api', __name__, url_prefix='/api') api = restplus.Api(blueprint, version='1.0') content = 'My Custom API Doc' @api.documentation def api_doc(): return content self.app.register_blueprint(blueprint) with self.context(): with self.app.test_client() as client: response = client.get(url_for('api.doc')) self.assertEquals(response.status_code, 200) self.assertEquals(response.data.decode('utf8'), content)
def init(apis): """Module initialization.""" blueprint = flask.Blueprint('v3', __name__, url_prefix='/v3') api = restplus.Api(blueprint, version='3.0', ui=False, title="Treadmill's API Server - v3", description="Treadmill's API server") @blueprint.route('/docs/', endpoint='docs') def _swagger_ui(): """Swagger documentation route""" return restplus.apidoc.ui_for(api) rest.FLASK_APP.register_blueprint(blueprint) rest.FLASK_APP.register_blueprint(restplus.apidoc.apidoc) # TODO: origin must be configurable. cors = webutils.cors(origin='.*', content_type='application/json', credentials=True) def user_clbk(): """Get current user from the request.""" return flask.request.environ.get('REMOTE_USER') authorizer = authz.PluginAuthorizer(user_clbk) for apiname in apis: try: apimod = apiname.replace('-', '_') _LOGGER.info('Loading api: %s', apimod) api_restmod = importlib.import_module('treadmill.rest.v3.' + apimod) api_implmod = importlib.import_module('treadmill.api.' + apimod) api_impl = api_implmod.init(authorizer) api_restmod.init(api, cors, api_impl) except ImportError as err: _LOGGER.warn('Unable to load %s api: %s', apimod, err) return ['/v3/' + apimod.replace('_', '-') for apimod in apis]
def test_custom_apidoc_url(self): restplus.Api(self.app, version='1.0', doc='/doc/') with self.context(): with self.app.test_client() as client: doc_url = url_for('doc') root_url = url_for('root') self.assertNotEqual(doc_url, root_url) response = client.get(root_url) self.assertEquals(response.status_code, 404) self.assertEqual(doc_url, '/doc/') response = client.get(doc_url) self.assertEquals(response.status_code, 200) self.assertEquals(response.content_type, 'text/html; charset=utf-8')
def test_custom_apidoc_url(self): blueprint = Blueprint('api', __name__, url_prefix='/api') api = restplus.Api(blueprint, version='1.0', ui=False) @blueprint.route('/doc/', endpoint='doc') def swagger_ui(): return restplus.apidoc.ui_for(api) self.app.register_blueprint(blueprint) with self.context(), self.app.test_client() as client: response = client.get(url_for('api.root')) self.assertEquals(response.status_code, 404) response = client.get(url_for('api.doc')) self.assertEquals(response.status_code, 200) self.assertEquals(response.content_type, 'text/html; charset=utf-8')
def test_apidoc_doc_expansion_parameter(self): restplus.Api(self.app) with self.context(): with self.app.test_client() as client: response = client.get(url_for('doc')) self.assertIn('docExpansion: "none"', str(response.data)) self.app.config['SWAGGER_UI_DOC_EXPANSION'] = 'list' with self.context(): with self.app.test_client() as client: response = client.get(url_for('doc')) self.assertIn('docExpansion: "list"', str(response.data)) self.app.config['SWAGGER_UI_DOC_EXPANSION'] = 'full' with self.context(): with self.app.test_client() as client: response = client.get(url_for('doc')) self.assertIn('docExpansion: "full"', str(response.data))
def test_headers(self): api = restplus.Api(self.app) @api.route('/headers/') class TestHeaders(restplus.Resource): @api.doc('headers') @api.header('X-Header-1', default='xxx') @api.header('X-Header-2', required=True) def get(self): pass data = api.as_postman(urlvars=True) validate(data, schema) request = data['requests'][0] headers = dict(r.split(':') for r in request['headers'].splitlines()) self.assertEqual(headers['X-Header-1'], 'xxx') self.assertEqual(headers['X-Header-2'], '')
def test_validation_true_on_constructor_with_override(self): api = restplus.Api(self.app, validate=True) fields = api.model('Person', { 'name': restplus.fields.String(required=True), 'age': restplus.fields.Integer, 'birthdate': restplus.fields.DateTime, }) @api.route('/validation/') class ValidationOff(restplus.Resource): @api.expect(fields, validate=False) def post(self): return {} data = {} response = self.post('/validation/', data) self.assert_errors(response, 'name')