def test_init(): """Test extension initialization.""" app = Flask('testapp') ext = InvenioREST(app) assert 'invenio-rest' in app.extensions app = Flask('testapp') ext = InvenioREST() assert 'invenio-rest' not in app.extensions ext.init_app(app) assert 'invenio-rest' in app.extensions
def test_match_serializers_query_arg(app): """Test match serializers query argument.""" v = ContentNegotiatedMethodView( method_serializers=dict( GET={ 'application/json': 'json-get', 'application/marcxml+xml': 'xml-get'} ), serializers_query_aliases={ 'json': 'application/json', 'marcxml': 'application/marcxml+xml', }, default_media_type='application/marcxml+xml', default_method_media_type=dict( GET='application/marcxml+xml', ) ) # enable serialization by query arg app.config['REST_MIMETYPE_QUERY_ARG_NAME'] = 'format' InvenioREST(app) arg_name = app.config['REST_MIMETYPE_QUERY_ARG_NAME'] tests = [ # Should serialize to marcxml (urlencode({arg_name: 'marcxml'}), 'application/json', 'xml-get'), # Should serialize to json (urlencode({arg_name: 'json'}), 'application/marcxml+xml', 'json-get'), # Should serialize to json (urlencode({}), 'application/json', 'json-get'), # Should serialize to default (marcxml) (urlencode({'wrong_name': 'marcxml'}), None, 'xml-get'), ] for arg, accept, expected_serializer in tests: params = dict(headers=[('Accept', accept)], query_string=arg) if accept else {} _test_march_serializers(app, v, params, 'GET', accept, expected_serializer) # disable query arg, should serialize by headers even if query arg passed app.config['REST_MIMETYPE_QUERY_ARG_NAME'] = None InvenioREST(app) accept = 'application/json' params = dict(headers=[('Accept', accept)], query_string='format=marcxml') _test_march_serializers(app, v, params, 'GET', accept, 'json-get')
def test_error_handlers(app): """Error handlers view.""" InvenioREST(app) @app.route("/<int:status_code>", methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'TRACE', 'OPTIONS']) def test_view(status_code): abort(status_code) error_codes = [ 400, 401, 403, 404, 405, 406, 409, 410, 412, 422, 415, 429, 500, 501, 502, 503, 504] with app.test_client() as client: verbs = [client.get, client.post, client.put, client.delete, client.patch, client.trace, client.options, client.get] for s in error_codes: for verb in verbs: res = verb("/{0}".format(s)) assert res.status_code == s if pkg_resources.get_distribution("werkzeug").\ version == '0.14.1' and s == 412: # skip test because of the following issue: # https://github.com/pallets/werkzeug/issues/1231 continue if verb != client.head: data = json.loads(res.get_data(as_text=True)) assert data['status'] == s assert data['message']
def app(request): """Flask application fixture.""" instance_path = tempfile.mkdtemp() app = Flask('testapp', instance_path=instance_path) app.config.update( TESTING=True, SERVER_NAME='localhost:5000', SQLALCHEMY_DATABASE_URI=os.environ.get( 'SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db' ) ) FlaskCLI(app) InvenioDB(app) InvenioREST(app) InvenioRecords(app) InvenioPIDStore(app) InvenioRecordsREST(app) with app.app_context(): if not database_exists(str(db.engine.url)) and \ app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://': create_database(db.engine.url) db.drop_all() db.create_all() def finalize(): with app.app_context(): db.drop_all() if app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://': drop_database(db.engine.url) shutil.rmtree(instance_path) request.addfinalizer(finalize) return app
def test_error_handlers(app): """Error handlers view.""" InvenioREST(app) @app.route("/<int:status_code>", methods=[ 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'TRACE', 'OPTIONS' ]) def test_view(status_code): abort(status_code) error_codes = [ 400, 401, 403, 404, 405, 406, 409, 410, 412, 415, 429, 500, 501, 502, 503, 504 ] with app.test_client() as client: verbs = [ client.get, client.post, client.put, client.delete, client.patch, client.trace, client.options, client.get ] for s in error_codes: for verb in verbs: res = verb("/{0}".format(s)) assert res.status_code == s if verb != client.head: data = json.loads(res.get_data(as_text=True)) assert data['status'] == s assert data['message']
def app_with_flexible_registration(request): """Flask application fixture with Invenio Accounts.""" from webargs import fields from invenio_accounts.views.rest import RegisterView, use_kwargs class MyRegisterView(RegisterView): post_args = { **RegisterView.post_args, 'active': fields.Boolean(required=True) } @use_kwargs(post_args) def post(self, **kwargs): """Register a user.""" return super(MyRegisterView, self).post(**kwargs) api_app = _app_factory() InvenioREST(api_app) InvenioAccountsREST(api_app) api_app.config['ACCOUNTS_REST_AUTH_VIEWS']['register'] = MyRegisterView api_app.register_blueprint(create_blueprint(api_app)) _database_setup(api_app, request) yield api_app
def app(request): """Flask application fixture.""" instance_path = tempfile.mkdtemp() app = Flask('testapp', instance_path=instance_path) app.config.update( TESTING=True, SERVER_NAME='localhost:5000', SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'), SQLALCHEMY_TRACK_MODIFICATIONS=True, RECORDS_REST_ENDPOINTS=config.RECORDS_REST_ENDPOINTS, # No permission checking RECORDS_REST_DEFAULT_CREATE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_READ_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_UPDATE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_DELETE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_SEARCH_INDEX=ES_INDEX, RECORDS_REST_SORT_OPTIONS={ ES_INDEX: dict(year=dict(fields=['year'], )) }, ) app.config['RECORDS_REST_ENDPOINTS']['recid']['search_class'] = TestSearch # update the application with the configuration provided by the test if hasattr(request, 'param') and 'config' in request.param: app.config.update(**request.param['config']) FlaskCLI(app) InvenioDB(app) InvenioREST(app) InvenioRecords(app) InvenioPIDStore(app) InvenioSearch(app) InvenioAccess(app) InvenioRecordsREST(app) with app.app_context(): # Setup app if not database_exists(str(db.engine.url)) and \ app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://': create_database(db.engine.url) db.drop_all() db.create_all() if current_search_client.indices.exists(ES_INDEX): current_search_client.indices.delete(ES_INDEX) current_search_client.indices.create(ES_INDEX) prepare_indexing(app) with app.app_context(): # Yield app in request context with app.test_request_context(): yield app with app.app_context(): # Teardown app db.drop_all() if app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://': drop_database(db.engine.url) shutil.rmtree(instance_path)
def app(request): """Flask application fixture.""" instance_path = tempfile.mkdtemp() app = Flask('testapp', instance_path=instance_path) es_index = 'invenio_records_rest_test_index' app.config.update( TESTING=True, SERVER_NAME='localhost:5000', SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'), SQLALCHEMY_TRACK_MODIFICATIONS=True, RECORDS_REST_ENDPOINTS=config.RECORDS_REST_ENDPOINTS, # No permission checking RECORDS_REST_DEFAULT_CREATE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_READ_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_UPDATE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_DELETE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_SEARCH_INDEX=es_index, RECORDS_REST_SORT_OPTIONS={ es_index: dict(year=dict(fields=['year'], )) }, SEARCH_QUERY_ENHANCERS=[filter_record_access_query_enhancer], ) app.config['RECORDS_REST_ENDPOINTS']['recid']['search_index'] = es_index # update the application with the configuration provided by the test if hasattr(request, 'param') and 'config' in request.param: app.config.update(**request.param['config']) FlaskCLI(app) InvenioDB(app) InvenioREST(app) InvenioRecords(app) InvenioPIDStore(app) InvenioSearch(app) InvenioAccess(app) InvenioRecordsREST(app) with app.app_context(): if not database_exists(str(db.engine.url)) and \ app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://': create_database(db.engine.url) db.drop_all() db.create_all() if current_search_client.indices.exists(es_index): current_search_client.indices.delete(es_index) current_search_client.indices.create(es_index) prepare_indexing(app) def finalize(): with app.app_context(): db.drop_all() if app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://': drop_database(db.engine.url) shutil.rmtree(instance_path) request.addfinalizer(finalize) return app
def app(base_app): """Flask application fixture.""" base_app._internal_jsonschemas = InvenioJSONSchemas(base_app) InvenioREST(base_app) InvenioRecordsREST(base_app) InvenioRecords(base_app) InvenioPIDStore(base_app) base_app.url_map.converters['pid'] = PIDConverter base_app.register_blueprint(create_blueprint_from_app(base_app)) app_loaded.send(None, app=base_app) with base_app.app_context(): yield base_app
def test_cors(app): """Test CORS support.""" app.config['REST_ENABLE_CORS'] = True InvenioREST(app) @app.route('/') def cors_test(): return 'test' with app.test_client() as client: res = client.get('/') assert not res.headers.get('Access-Control-Allow-Origin', False) res = client.get('/', headers=[('Origin', 'http://example.com')]) assert res.headers['Access-Control-Allow-Origin'] == '*'
def app(base_app): """Flask full application fixture.""" Breadcrumbs(base_app) InvenioDB(base_app) InvenioAccess(base_app) InvenioAccounts(base_app) InvenioFilesREST(base_app) InvenioOAuth2Server(base_app) InvenioOAuth2ServerREST(base_app) InvenioREST(base_app) InvenioSIPStore(base_app) base_app.register_blueprint(server_blueprint) base_app.register_blueprint(blueprint) with base_app.app_context(): yield base_app
def app(base_app): """Flask application fixture.""" Babel(base_app) InvenioAccounts(base_app) InvenioAccess(base_app) InvenioDB(base_app) InvenioFilesREST(base_app) InvenioRecords(base_app) InvenioRecordsUI(base_app) InvenioREST(base_app) InvenioIIIFAPI(base_app) InvenioIIIFManifest(base_app) with base_app.app_context(): yield base_app
def api(request): """Flask application fixture.""" api_app = _app_factory( dict( SQLALCHEMY_DATABASE_URI=os.environ.get( 'SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'), SERVER_NAME='localhost', TESTING=True, )) InvenioREST(api_app) InvenioAccountsREST(api_app) api_app.register_blueprint(create_blueprint(api_app)) _database_setup(api_app, request) yield api_app
def test_custom_httpexception(app): """Test custom HTTPException.""" InvenioREST(app) class CustomBadRequest(HTTPException): code = 400 description = 'test' @app.route('/') def test_view(): raise CustomBadRequest() with app.test_client() as client: res = client.get('/') assert res.status_code == 400 data = json.loads(res.get_data(as_text=True)) assert data['message'] == 'test' assert data['status'] == 400
def app(request): """Basic Flask application.""" instance_path = tempfile.mkdtemp() app = Flask("testapp") app.config.update( SQLALCHEMY_DATABASE_URI=os.getenv("SQLALCHEMY_DATABASE_URI", "sqlite://"), SQLALCHEMY_TRACK_MODIFICATIONS=False, TESTING=True, SECRET_KEY="testing", # SERVER_NAME='localhost:5000', ) app.url_map.converters['pid'] = PIDConverter InvenioDB(app) InvenioPIDStore(app) InvenioRecords(app) InvenioAccounts(app) InvenioAccess(app) InvenioIndexer(app) InvenioSearch(app) InvenioREST(app) InvenioRecordsREST(app) InvenioConfigDefault(app) with app.app_context(): db_url = str(db.engine.url) if db_url != "sqlite://" and not database_exists(db_url): create_database(db_url) db.create_all() def teardown(): with app.app_context(): db_url = str(db.engine.url) db.session.close() if db_url != "sqlite://": drop_database(db_url) shutil.rmtree(instance_path) request.addfinalizer(teardown) app.test_request_context().push() return app
def test_cors(app): """Test CORS support.""" app.config['REST_ENABLE_CORS'] = True app.config['CORS_ALWAYS_SEND'] = False InvenioREST(app) @app.route('/') def cors_test(): return 'test' with app.test_client() as client: res = client.get('/') assert not res.headers.get('Access-Control-Allow-Origin', False) assert not res.headers.get('Access-Control-Expose-Headers', False) res = client.get('/', headers=[('Origin', 'http://example.com')]) assert res.headers['Access-Control-Allow-Origin'] == '*' assert len(res.headers['Access-Control-Expose-Headers'].split(',')) \ == len(app.config['CORS_EXPOSE_HEADERS'])
def app(base_app): """Flask application fixture.""" base_app._internal_jsonschemas = InvenioJSONSchemas(base_app) InvenioREST(base_app) InvenioRecordsREST(base_app) InvenioRecords(base_app) InvenioPIDStore(base_app) base_app.url_map.converters['pid'] = PIDConverter SampleExt(base_app) OARepoMappingIncludesExt(base_app) LoginManager(base_app) Permission(base_app) InvenioAccess(base_app) Principal(base_app) OARepoValidate(base_app) Actions(base_app) base_app.register_blueprint( invenio_records_rest.views.create_blueprint_from_app(base_app)) login_manager = LoginManager() login_manager.init_app(base_app) login_manager.login_view = 'login' @login_manager.user_loader def basic_user_loader(user_id): user_obj = User.query.get(int(user_id)) return user_obj @base_app.route('/test/login/<int:id>', methods=['GET', 'POST']) def test_login(id): print("test: logging user with id", id) response = make_response() user = User.query.get(id) login_user(user) set_identity(user) return response app_loaded.send(None, app=base_app) with base_app.app_context(): yield base_app
def test_require_content_types(app): """Error handlers view.""" InvenioREST(app) @app.route("/", methods=['POST']) @require_content_types('application/json', 'text/plain') def test_view(): return "OK" with app.test_client() as client: res = client.post("/", content_type='application/json', data="{}") assert res.status_code == 200 res = client.post("/", content_type='text/plain', data="test") assert res.status_code == 200 res = client.post("/", content_type='application/xml', data="<d></d>") assert res.status_code == 415 data = json.loads(res.get_data(as_text=True)) assert data['status'] == 415 assert 'application/json' in data['message'] assert 'text/plain' in data['message']
def test_errors(app): """Error handlers view.""" InvenioREST(app) @app.route('/', methods=['GET']) def test_rest(): raise RESTException(description='error description') @app.route('/contenttype', methods=['GET']) def test_content_type(): raise InvalidContentType(allowed_content_types=['application/json']) @app.route('/validationerror', methods=['GET']) def test_validation_error(): raise RESTValidationError( errors=[FieldError('myfield', 'mymessage', code=10)]) with app.test_client() as client: res = client.get('/') assert res.status_code == 200 data = json.loads(res.get_data(as_text=True)) assert data['status'] is None assert data['message'] == 'error description' res = client.get('/contenttype') assert res.status_code == 415 data = json.loads(res.get_data(as_text=True)) assert data['status'] == 415 assert 'application/json' in data['message'] res = client.get('/validationerror') assert res.status_code == 400 data = json.loads(res.get_data(as_text=True)) print(data) assert data['status'] == 400 assert data['message'] == 'Validation error.' assert data['errors'] == [ dict(field='myfield', message='mymessage', code=10) ]
def app(): """Flask applicat-ion fixture.""" instance_path = os.path.join(sys.prefix, 'var', 'test-instance') # empty the instance path if os.path.exists(instance_path): shutil.rmtree(instance_path) os.makedirs(instance_path) os.environ['INVENIO_INSTANCE_PATH'] = instance_path app_ = Flask('invenio-records-draft-testapp', instance_path=instance_path) app_.config.update( TESTING=True, JSON_AS_ASCII=True, SERVER_NAME='localhost:5000', SQLALCHEMY_TRACK_MODIFICATIONS=False, SQLALCHEMY_DATABASE_URI=os.environ.get( 'SQLALCHEMY_DATABASE_URI', 'sqlite:///:memory:'), SECURITY_PASSWORD_SALT='TEST_SECURITY_PASSWORD_SALT', SECRET_KEY='TEST_SECRET_KEY', INVENIO_INSTANCE_PATH=instance_path, RECORDS_REST_ENDPOINTS={}, ) InvenioDB(app_) InvenioREST(app_) InvenioIIIFAPI(app_) OARepoIIIFExt(app_) app_.register_blueprint(invenio_iiif.previewer.blueprint, url_prefix='/api/iiif/') app_loaded.send(None, app=app_) with app_.app_context(): yield app_
def test_ratelimt(app): """Test CORS support.""" app.config['RATELIMIT_GLOBAL'] = '1/day' app.config['RATELIMIT_STORAGE_URL'] = 'memory://' ext = InvenioREST(app) for handler in app.logger.handlers: ext.limiter.logger.addHandler(handler) @app.route('/a') def view_a(): return 'a' @app.route('/b') def view_b(): return 'b' with app.test_client() as client: res = client.get('/a') assert res.status_code == 200 assert res.headers['X-RateLimit-Limit'] == '1' assert res.headers['X-RateLimit-Remaining'] == '0' assert res.headers['X-RateLimit-Reset'] res = client.get('/a') assert res.status_code == 429 assert res.headers['X-RateLimit-Limit'] assert res.headers['X-RateLimit-Remaining'] assert res.headers['X-RateLimit-Reset'] # Global limit is per view. res = client.get('/b') assert res.status_code == 200 assert res.headers['X-RateLimit-Limit'] assert res.headers['X-RateLimit-Remaining'] assert res.headers['X-RateLimit-Reset']
def test_errors(app): """Error handlers view.""" InvenioREST(app) @app.route('/', methods=['GET']) def test_rest(): raise RESTException(description='error description') @app.route('/contenttype', methods=['GET']) def test_content_type(): raise InvalidContentType(allowed_contet_types=['application/json']) with app.test_client() as client: res = client.get('/') assert res.status_code == 200 data = json.loads(res.get_data(as_text=True)) assert data['status'] is None assert data['message'] == 'error description' res = client.get('/contenttype') assert res.status_code == 415 data = json.loads(res.get_data(as_text=True)) assert data['status'] == 415 assert 'application/json' in data['message']
def app(request, search_class): """Flask application fixture. Note that RECORDS_REST_ENDPOINTS is used during application creation to create blueprints on the fly, hence once you have this fixture in a test, it's too late to customize the configuration variable. You can however customize it using parameterized tests: .. code-block:: python @pytest.mark.parametrize('app', [dict( endpoint=dict( search_class='conftest:TestSearch', ) def test_mytest(app, db, es): # ... This will parameterize the default 'recid' endpoint in RECORDS_REST_ENDPOINTS. Alternatively: .. code-block:: python @pytest.mark.parametrize('app', [dict( records_rest_endpoints=dict( recid=dict( search_class='conftest:TestSearch', ) ) def test_mytest(app, db, es): # ... This will fully parameterize RECORDS_REST_ENDPOINTS. """ instance_path = tempfile.mkdtemp() app = Flask('testapp', instance_path=instance_path) from records import config app.config.update( ACCOUNTS_JWT_ENABLE=False, INDEXER_DEFAULT_DOC_TYPE='record-v1.0.0', INDEXER_DEFAULT_INDEX=search_class.Meta.index, RECORDS_REST_ENDPOINTS=copy.deepcopy(config.RECORDS_REST_ENDPOINTS), RECORDS_REST_DEFAULT_CREATE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_DELETE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_READ_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_UPDATE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_SEARCH_INDEX=search_class.Meta.index, SERVER_NAME='localhost:5000', CELERY_ALWAYS_EAGER=True, CELERY_RESULT_BACKEND='cache', CELERY_CACHE_BACKEND='memory', CELERY_EAGER_PROPAGATES_EXCEPTIONS=True, SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'), SQLALCHEMY_TRACK_MODIFICATIONS=True, TESTING=True, ) app.config['RECORDS_REST_ENDPOINTS']['recid']['search_class'] = \ search_class app.config['RECORDS_REST_ENDPOINTS']['recid']['create_permission_factory_imp'] = \ user_id_1_perm app.config['RECORDS_REST_ENDPOINTS']['recid']['record_class'] = \ SchemaEnforcingRecord app.secret_key = 'changeme' # Parameterize application. if hasattr(request, 'param'): if 'endpoint' in request.param: app.config['RECORDS_REST_ENDPOINTS']['recid'].update( request.param['endpoint']) if 'records_rest_endpoints' in request.param: original_endpoint = app.config['RECORDS_REST_ENDPOINTS']['recid'] del app.config['RECORDS_REST_ENDPOINTS']['recid'] for new_endpoint_prefix, new_endpoint_value in \ request.param['records_rest_endpoints'].items(): new_endpoint = dict(original_endpoint) new_endpoint.update(new_endpoint_value) app.config['RECORDS_REST_ENDPOINTS'][new_endpoint_prefix] = \ new_endpoint app.url_map.converters['pid'] = PIDConverter InvenioDB(app) InvenioREST(app) InvenioRecords(app) schemas = InvenioJSONSchemas(app) indexer = InvenioIndexer(app) InvenioPIDStore(app) search = InvenioSearch(app) search.register_mappings(search_class.Meta.index, 'records.mappings') schemas._state.register_schemas_dir( os.path.join(os.path.dirname(__file__), 'records', 'jsonschemas')) InvenioRecordsREST(app) InvenioAccess(app) explicit_acls = InvenioExplicitAcls(app) principal = Principal(app) login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'login' @login_manager.user_loader def basic_user_loader(user_id): user_obj = User.query.get(int(user_id)) return user_obj app.register_blueprint(create_blueprint_from_app(app)) @app.route('/test/login/<int:id>', methods=['GET', 'POST']) def test_login(id): print("test: logging user with id", id) response = make_response() user = User.query.get(id) login_user(user) set_identity(user) return response with app.app_context(): yield app # Teardown instance path. shutil.rmtree(instance_path)
def base_app(request, test_metadata_format): """Flask application fixture.""" instance_path = tempfile.mkdtemp() def init_app(app_): app_.config.update( CELERY_ALWAYS_EAGER=False, CELERY_CACHE_BACKEND="memory", CELERY_EAGER_PROPAGATES_EXCEPTIONS=True, CELERY_RESULT_BACKEND="cache", JSONSCHEMAS_URL_SCHEME="http", SECRET_KEY="CHANGE_ME", SECURITY_PASSWORD_SALT="CHANGE_ME_ALSO", SQLALCHEMY_DATABASE_URI=os.environ.get("SQLALCHEMY_DATABASE_URI", "sqlite:///test.db"), SQLALCHEMY_TRACK_MODIFICATIONS=True, SQLALCHEMY_ECHO=False, TESTING=True, WTF_CSRF_ENABLED=False, DEPOSIT_SEARCH_API="/api/search", SECURITY_PASSWORD_HASH="plaintext", SECURITY_PASSWORD_SCHEMES=["plaintext"], SECURITY_DEPRECATED_PASSWORD_SCHEMES=[], THEME_SITENAME="Test Site", OAUTHLIB_INSECURE_TRANSPORT=True, OAUTH2_CACHE_TYPE="simple", ACCOUNTS_JWT_ENABLE=False, # This allows access to files across all of invenio-files-rest FILES_REST_PERMISSION_FACTORY=lambda *a, **kw: type( "Allow", (object, ), {"can": lambda self: True})(), FILES_REST_MULTIPART_CHUNKSIZE_MIN=10, ) Babel(app_) FlaskCeleryExt(app_) Breadcrumbs(app_) OAuth2Provider(app_) InvenioDB(app_) InvenioAccounts(app_) InvenioAccess(app_) InvenioIndexer(app_) InvenioJSONSchemas(app_) InvenioOAuth2Server(app_) InvenioPIDStore(app_) InvenioRecords(app_) search = InvenioSearch(app_) search.register_mappings("deposits", "invenio_deposit.mappings") api_app = Flask("testapiapp", instance_path=instance_path) api_app.url_map.converters["pid"] = PIDConverter # initialize InvenioDeposit first in order to detect any invalid dependency InvenioDepositREST(api_app) init_app(api_app) InvenioREST(api_app) InvenioOAuth2ServerREST(api_app) InvenioRecordsREST(api_app) InvenioFilesREST(api_app) InvenioSword(api_app) api_app.register_blueprint(files_rest_blueprint) # api_app.register_blueprint(records_files_bp(api_app)) api_app.register_blueprint(records_rest_bp(api_app)) api_app.register_blueprint(invenio_files_rest_blueprint) # Register a test (alternate) metadata format api_app.config["SWORD_ENDPOINTS"]["depid"]["metadata_formats"][ test_metadata_format] = TestMetadata app = Flask("testapp", instance_path=instance_path) app.url_map.converters["pid"] = PIDConverter # initialize InvenioDeposit first in order to detect any invalid dependency InvenioDeposit(app) init_app(app) app.register_blueprint(accounts_blueprint) app.register_blueprint(oauth2server_settings_blueprint) InvenioAssets(app) InvenioSearchUI(app) InvenioRecordsUI(app) app.register_blueprint(records_ui_bp(app)) app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {"/api": api_app.wsgi_app}) with app.app_context(): if str(db.engine.url) != "sqlite://" and not database_exists( str(db.engine.url)): create_database(str(db.engine.url)) db.create_all() yield app with app.app_context(): if str(db.engine.url) != "sqlite://": drop_database(str(db.engine.url)) shutil.rmtree(instance_path)
def base_app(request): """Flask application fixture.""" instance_path = tempfile.mkdtemp() def init_app(app_): app_.config.update( CELERY_ALWAYS_EAGER=True, CELERY_CACHE_BACKEND='memory', CELERY_EAGER_PROPAGATES_EXCEPTIONS=True, CELERY_RESULT_BACKEND='cache', JSONSCHEMAS_URL_SCHEME='http', SECRET_KEY='CHANGE_ME', SECURITY_PASSWORD_SALT='CHANGE_ME_ALSO', SQLALCHEMY_DATABASE_URI=os.environ.get( 'SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'), SQLALCHEMY_TRACK_MODIFICATIONS=True, SQLALCHEMY_ECHO=False, TESTING=True, WTF_CSRF_ENABLED=False, DEPOSIT_SEARCH_API='/api/search', SECURITY_PASSWORD_HASH='plaintext', SECURITY_PASSWORD_SCHEMES=['plaintext'], SECURITY_DEPRECATED_PASSWORD_SCHEMES=[], OAUTHLIB_INSECURE_TRANSPORT=True, OAUTH2_CACHE_TYPE='simple', ACCOUNTS_JWT_ENABLE=False, ) Babel(app_) FlaskCeleryExt(app_) Breadcrumbs(app_) OAuth2Provider(app_) InvenioDB(app_) InvenioAccounts(app_) InvenioAccess(app_) InvenioIndexer(app_) InvenioJSONSchemas(app_) InvenioOAuth2Server(app_) InvenioFilesREST(app_) InvenioPIDStore(app_) InvenioRecords(app_) search = InvenioSearch(app_) search.register_mappings('deposits', 'invenio_deposit.mappings') api_app = Flask('testapiapp', instance_path=instance_path) api_app.url_map.converters['pid'] = PIDConverter # initialize InvenioDeposit first in order to detect any invalid dependency InvenioDepositREST(api_app) init_app(api_app) InvenioREST(api_app) InvenioOAuth2ServerREST(api_app) InvenioRecordsREST(api_app) app = Flask('testapp', instance_path=instance_path) app.url_map.converters['pid'] = PIDConverter # initialize InvenioDeposit first in order to detect any invalid dependency InvenioDeposit(app) init_app(app) app.register_blueprint(accounts_blueprint) app.register_blueprint(oauth2server_settings_blueprint) InvenioAssets(app) InvenioSearchUI(app) InvenioRecordsUI(app) app.register_blueprint(records_ui_bp(app)) app.register_blueprint(records_rest_bp(app)) app.wsgi_app = DispatcherMiddleware(app.wsgi_app, { '/api': api_app.wsgi_app }) with app.app_context(): if str(db.engine.url) != 'sqlite://' and \ not database_exists(str(db.engine.url)): create_database(str(db.engine.url)) db.create_all() yield app with app.app_context(): if str(db.engine.url) != 'sqlite://': drop_database(str(db.engine.url)) shutil.rmtree(instance_path)
# Set jinja loader to first grab templates from the app's folder. app.jinja_loader = jinja2.ChoiceLoader([ jinja2.FileSystemLoader(join(dirname(__file__), "templates")), app.jinja_loader ]) InvenioDB(app) InvenioTheme(app) InvenioJSONSchemas(app) InvenioAccounts(app) InvenioRecords(app) InvenioRecordsUI(app) search = InvenioSearch(app) # search.register_mappings('testrecords', 'data') InvenioSearchUI(app) InvenioREST(app) InvenioIndexer(app) InvenioPIDStore(app) InvenioAdmin(app) InvenioOAuth2Server(app) InvenioRecordsREST(app) InvenioFilesREST(app) assets = InvenioAssets(app) assets.env.register('invenio_search_ui_search_js', js) InvenioDeposit(app) InvenioDepositREST(app) app.register_blueprint(accounts_blueprint)
def app(request, search_class): """Flask application fixture. Note that RECORDS_REST_ENDPOINTS is used during application creation to create blueprints on the fly, hence once you have this fixture in a test, it's too late to customize the configuration variable. You can however customize it using parameterized tests: .. code-block:: python @pytest.mark.parametrize('app', [dict( endpoint=dict( search_class='conftest:TestSearch', ) def test_mytest(app, db, es): # ... This will parameterize the default 'recid' endpoint in RECORDS_REST_ENDPOINTS. Alternatively: .. code-block:: python @pytest.mark.parametrize('app', [dict( records_rest_endpoints=dict( recid=dict( search_class='conftest:TestSearch', ) ) def test_mytest(app, db, es): # ... This will fully parameterize RECORDS_REST_ENDPOINTS. """ instance_path = tempfile.mkdtemp() app = Flask('testapp', instance_path=instance_path) app.config.update( ACCOUNTS_JWT_ENABLE=False, INDEXER_DEFAULT_DOC_TYPE='testrecord', INDEXER_DEFAULT_INDEX=search_class.Meta.index, RECORDS_REST_ENDPOINTS=copy.deepcopy(config.RECORDS_REST_ENDPOINTS), RECORDS_REST_DEFAULT_CREATE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_DELETE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_READ_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_UPDATE_PERMISSION_FACTORY=None, RECORDS_REST_DEFAULT_SEARCH_INDEX=search_class.Meta.index, RECORDS_REST_FACETS={ search_class.Meta.index: { 'aggs': { 'stars': { 'terms': { 'field': 'stars' } } }, 'post_filters': { 'stars': terms_filter('stars'), } } }, RECORDS_REST_SORT_OPTIONS={ search_class.Meta.index: dict(year=dict(fields=['year'], )) }, SERVER_NAME='localhost:5000', SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'), SQLALCHEMY_TRACK_MODIFICATIONS=True, TESTING=True, ) app.config['RECORDS_REST_ENDPOINTS']['recid']['search_class'] = \ search_class # Parameterize application. if hasattr(request, 'param'): if 'endpoint' in request.param: app.config['RECORDS_REST_ENDPOINTS']['recid'].update( request.param['endpoint']) if 'records_rest_endpoints' in request.param: original_endpoint = app.config['RECORDS_REST_ENDPOINTS']['recid'] del app.config['RECORDS_REST_ENDPOINTS']['recid'] for new_endpoint_prefix, new_endpoint_value in \ request.param['records_rest_endpoints'].items(): new_endpoint = dict(original_endpoint) new_endpoint.update(new_endpoint_value) app.config['RECORDS_REST_ENDPOINTS'][new_endpoint_prefix] = \ new_endpoint app.url_map.converters['pid'] = PIDConverter InvenioDB(app) InvenioREST(app) InvenioRecords(app) InvenioIndexer(app) InvenioPIDStore(app) search = InvenioSearch(app) search.register_mappings(search_class.Meta.index, 'mock_module.mappings') InvenioRecordsREST(app) with app.app_context(): yield app # Teardown instance path. shutil.rmtree(instance_path)
def app(base_app): """Flask application fixture.""" base_app._internal_jsonschemas = InvenioJSONSchemas(base_app) InvenioREST(base_app) InvenioRecordsREST(base_app) InvenioRecords(base_app) InvenioPIDStore(base_app) base_app.url_map.converters['pid'] = PIDConverter OARepoValidate(base_app) SampleExt(base_app) try: from invenio_files_rest.ext import InvenioFilesREST from invenio_records_files.ext import InvenioRecordsFiles InvenioFilesREST(base_app) InvenioRecordsFiles(base_app) except ImportError: pass base_app.register_blueprint( invenio_records_rest.views.create_blueprint_from_app(base_app)) principal = Principal(base_app) login_manager = LoginManager() login_manager.init_app(base_app) login_manager.login_view = 'login' @login_manager.user_loader def basic_user_loader(user_id): user_obj = User.query.get(int(user_id)) return user_obj @base_app.route('/test/login/<int:id>', methods=['GET', 'POST']) def test_login(id): print("test: logging user with id", id) response = make_response() user = User.query.get(id) print('User is', user) login_user(user) set_identity(user) return response @base_app.route('/test/logout', methods=['GET', 'POST']) def test_logout(): print("test: logging out") response = make_response() logout_user() # Remove session keys set by Flask-Principal for key in ('identity.name', 'identity.auth_type'): session.pop(key, None) # Tell Flask-Principal the user is anonymous identity_changed.send(current_app._get_current_object(), identity=AnonymousIdentity()) return response app_loaded.send(None, app=base_app) with base_app.app_context(): yield base_app