def add(self): file = request.files.get('newfile') currentpath = request.form.get('currentpath') filename = self.filemanager.addfile(file=file, currentpath=currentpath) res = { "Path": currentpath, "Name": filename, "Error": "", "Code": 0 } return '<textarea>' + json_dumps(res) + '</textarea>'
def create_vector_layer(self, location, mapset, vector, region, parameter): # Remove potentially existing vector layer url = (f'{URL_PREFIX}/locations/{location}/mapsets/{mapset}/' f'vector_layers/{vector}') rv = self.server.delete(url, headers=self.user_auth_header) parameter["column"] = "z" region["res"] = 100000 # Create processing chain for random vector creation postbody = { "list": [{ "id": "set_region", "module": "g.region", "inputs": [{ "param": key, "value": str(val) } for key, val in region.items()] }, { "id": "create_vector", "module": "v.random", "inputs": [{ "param": key, "value": str(val) } for key, val in parameter.items()], "outputs": [{ "param": "output", "value": vector }], "flags": "z" }], "version": "1" } url = (f'{URL_PREFIX}/locations/{location}/mapsets/{mapset}/' f'processing_async') rv = self.server.post(url, headers=self.user_auth_header, data=json_dumps(postbody), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="finished") self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i" % rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s" % rv.mimetype)
def test_raster_import_export_sentinel_ndvi(self): rv = self.server.post( URL_PREFIX + '/locations/nc_spm_08/processing_async_export', headers=self.admin_auth_header, data=json_dumps( process_chain_sentinel_import_export_sentinel_ndvi), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="finished")
def test_create_strds_in_persistent_user_db_and_list_it(self): rv = self.server.post(URL_PREFIX + f'/locations/nc_spm_08/mapsets/{self.user_mapset}/processing_async', headers=self.admin_auth_header, data=json_dumps(process_chain_create_strds1), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="finished") rv2 = self.server.post( URL_PREFIX + f'/locations/nc_spm_08/mapsets/{self.user_mapset}/processing_async', headers=self.admin_auth_header, data=json_dumps(process_chain_list), content_type="application/json") self.waitAsyncStatusAssertHTTP( rv2, headers=self.admin_auth_header, http_status=200, status="finished") # check if strds 'modis' is in mapset self.check_strds_in_mapset(['modis']) # check if correct maps are listed i strds 'modis' self.check_modis_strds(self.raster_dict_modis, 'modis')
def test_error_4(self): rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/processing_async_export', headers=self.admin_auth_header, data=json_dumps(process_chain_error_4), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error", message_check="AsyncProcessError:")
def test_async_processing_sent_error_2(self): rv = self.server.post( URL_PREFIX + '/locations/nc_spm_08/process_chain_validation_sync', headers=self.admin_auth_header, data=json_dumps(process_chain_sent_2), content_type="application/json") pprint(json_loads(rv.data)) self.assertEqual(rv.status_code, 400, "HTML status code is wrong %i" % rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s" % rv.mimetype)
def test_4_create_global_mapset(self): rv = self.server.post( URL_PREFIX + '/locations/nc_spm_08/mapsets/PERMANENT/processing_async', headers=self.admin_auth_header, data=json_dumps(process_chain_long), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error")
def test_1_async_processing_postgis_validation(self): rv = self.server.post(URL_PREFIX + '/locations/LL/process_chain_validation_async', headers=self.admin_auth_header, data=json_dumps(process_chain_postgis), content_type="application/json") resp = self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="finished") self.assertEqual(len(resp["process_results"]), 1)
def test_2_merge_missing_target_mapset_error(self): """Missing target mapset test""" self.check_remove_test_mapsets() ############################################################################ # Try merge source mapsets into target mapset rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/mapsets/Target/merging_async', headers=self.admin_auth_header, data=json_dumps(["Source_A", "Source_B"]), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error", message_check="AsyncProcessError")
def test_large_Region_fail(self): # The cell limit exceeds the credentials settings of the user rv = self.server.post( URL_PREFIX + '/locations/nc_spm_08/processing_async_export', headers=self.user_auth_header, data=json_dumps(process_chain_short_large_region), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.user_auth_header, http_status=400, status="error", message_check="AsyncProcessError:")
def test_async_processing_new_ndvi_export_landsat(self): rv = self.server.post( URL_PREFIX + '/locations/latlong_wgs84/process_chain_validation_async', headers=self.admin_auth_header, data=json_dumps(process_chain_ndvi_landsat), content_type="application/json") resp = self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="finished") self.assertEqual(len(resp["process_results"]), 26)
def test_async_processing_error_9(self): """Wrong mapset in input definitions as user, hence authorization error""" pc = copy.deepcopy(process_chain_error_1) pc[1]["inputs"]["raster"] = "elevation@NO_Mapset" pc[1]["flags"] = "p" rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/processing_async', headers=self.user_auth_header, data=json_dumps(pc), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.user_auth_header, http_status=400, status="error", message_check="AsyncProcessError:")
def test_2_existing_mapset(self): """ An existing mapset and process :return: """ self.check_remove_test_mapset() # Create new mapset rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/mapsets/test_mapset', headers=self.admin_auth_header) print(rv.data) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i" % rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s" % rv.mimetype) # Run the processing using an existing mapset # Atemporary mapset will be created and merged in the existing rv = self.server.post( URL_PREFIX + '/locations/nc_spm_08/mapsets/test_mapset/processing_async', headers=self.admin_auth_header, data=json_dumps(process_chain_long), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header) rv = self.server.get( URL_PREFIX + '/locations/nc_spm_08/mapsets/test_mapset/raster_layers', headers=self.user_auth_header) print(rv.data) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i" % rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s" % rv.mimetype) map_list = json_load(rv.data)["process_results"] self.assertTrue("my_accumulation" in map_list) self.assertTrue("my_aspect" in map_list) self.assertTrue("my_slope" in map_list) # Remove the mapset rv = self.server.delete(URL_PREFIX + '/locations/nc_spm_08/mapsets/test_mapset', headers=self.admin_auth_header) print(rv.data) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i" % rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s" % rv.mimetype)
def test_job_resumption_error_by_running(self): """Test job resumption error by running process with processing_async endpoint """ tpl = Template(json_dumps(process_chain_2_error)) rv = self.server.post(URL_PREFIX + self.endpoint, headers=self.admin_auth_header, data=tpl.render(seconds=self.sleep_time), content_type="application/json") resp_data = json_loads(rv.data) rv_user_id = resp_data["user_id"] rv_resource_id = resp_data["resource_id"] waiting_for_running = True while waiting_for_running: rv_pull = self.server.get(URL_PREFIX + "/resources/%s/%s" % (rv_user_id, rv_resource_id), headers=self.admin_auth_header) resp_data_pull = json_loads(rv_pull.data) if resp_data_pull["status"] == "running": waiting_for_running = False elif resp_data_pull["status"] in [ "error", "terminated", "timeout" ]: self.assertTrue( False, "Process is not running it is %s" % resp_data_pull["status"]) status_url = resp_data_pull["urls"]["status"].split(URL_PREFIX)[-1] # job resumption by running job rv2 = self.server.put(URL_PREFIX + status_url, headers=self.admin_auth_header, data=json_dumps(process_chain_2_error), content_type="application/json") self.assertEqual(rv2.status_code, 404) resp_data2 = json_loads(rv2.data) self.assertEqual(resp_data2['status'], 'error') self.assertEqual(resp_data2['message'], 'Resource is running no restart possible')
def test_rename_raster_layers(self): new_mapset = "raster_test_mapset" self.create_new_mapset(new_mapset) map_list = ["test_rename_layer_1", "test_rename_layer_2"] new_map_list = ["test_rename_layer_1_new", "test_rename_layer_2_new"] rename_map_list = [("test_rename_layer_1", "test_rename_layer_1_new"), ("test_rename_layer_2", "test_rename_layer_2_new")] # Create raster layers for map_name in map_list: self.create_raster_layer(new_mapset, map_name) # Rename raster layer rv = self.server.put(URL_PREFIX + '/locations/nc_spm_08/mapsets/%s/raster_layers'%new_mapset, headers=self.user_auth_header, data=json_dumps(rename_map_list), content_type="application/json") print(rv.data.decode()) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i"%rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s"%rv.mimetype) # Rename raster layer rv = self.server.put(URL_PREFIX + '/locations/nc_spm_08/mapsets/%s/raster_layers'%new_mapset, headers=self.user_auth_header, data=json_dumps(rename_map_list), content_type="application/json") print(rv.data.decode()) self.assertEqual(rv.status_code, 400, "HTML status code is wrong %i"%rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s"%rv.mimetype) # Delete raster layers for map_name in new_map_list: rv = self.server.delete(URL_PREFIX + '/locations/nc_spm_08/mapsets/%s/raster_layers/%s'%(new_mapset, map_name), headers=self.user_auth_header) print(rv.data.decode()) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i"%rv.status_code)
def test_async_processing_error_1(self): """ Test the error handling in case the program was not found Returns: """ rv = self.server.post(URL_PREFIX + '/custom_process/uname_nopo', headers=self.admin_auth_header, data=json_dumps(["-a"]), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error")
def test_job_2_times_resumption_importer(self): """Test job 2 times resumption with processing_async endpoint and importer """ tpl = Template(json_dumps(process_chain_3_importer)) rv = self.server.post(URL_PREFIX + self.endpoint, headers=self.admin_auth_header, data=tpl.render(map1="elevation2@PERMANENT", map2="baum"), content_type="application/json") resp = self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error") status_url = resp["urls"]["status"].split(URL_PREFIX)[-1] # first job resumption rv2 = self.server.put(URL_PREFIX + status_url, headers=self.admin_auth_header, data=tpl.render(map1="elev_ned_30m_new", map2="baum1"), content_type="application/json") resp2 = self.waitAsyncStatusAssertHTTP(rv2, headers=self.admin_auth_header, http_status=400, status="error") status_url = resp2["urls"]["status"].split(URL_PREFIX)[-1] # check if interim results are saved resp_data = json_loads(rv2.data) rv_user_id = resp_data["user_id"] rv_resource_id = resp_data["resource_id"] interim_dir = os.path.join(global_config.GRASS_RESOURCE_DIR, rv_user_id, "interim", rv_resource_id) self.assertTrue( os.path.isdir(interim_dir), "Interim results are not stored in the expected folder") # second job resumption rv3 = self.server.put(URL_PREFIX + status_url, headers=self.admin_auth_header, data=tpl.render(map1="elev_ned_30m_new", map2="baum"), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv3, headers=self.admin_auth_header, http_status=200, status="finished") self.__class__.resource_user_id = rv_user_id self.__class__.resource_resource_id = rv_resource_id
def test_termination(self): rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/processing_async_export_gcs', headers=self.admin_auth_header, data=json_dumps(process_chain_long), content_type="application/json") resp = json_loads(rv.data) # Send the termination request self.server.delete(URL_PREFIX + "/resources/%s/%s" % (resp["user_id"], resp["resource_id"]), headers=self.admin_auth_header) self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="terminated", message_check="AsyncProcessTermination:")
def test_location_creation_and_deletion(self): # Delete a potentially existing location rv = self.server.delete(URL_PREFIX + '/locations/test_location', headers=self.admin_auth_header) # Create new location as admin rv = self.server.post(URL_PREFIX + '/locations/test_location', data=json_dumps({"epsg":"4326"}), content_type="application/json", headers=self.admin_auth_header) print(rv.data) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i"%rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s"%rv.mimetype) # ERROR: Try to create a location as admin that already exists rv = self.server.post(URL_PREFIX + '/locations/test_location', data=json_dumps({"epsg":"4326"}), content_type="application/json", headers=self.admin_auth_header) print(rv.data) self.assertEqual(rv.status_code, 400, "HTML status code is wrong %i"%rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s"%rv.mimetype) # Delete location rv = self.server.delete(URL_PREFIX + '/locations/test_location', headers=self.admin_auth_header) print(rv.data) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i"%rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s"%rv.mimetype) # ERROR: Delete should fail, since location does not exists rv = self.server.delete(URL_PREFIX + '/locations/test_location', headers=self.admin_auth_header) print(rv.data) self.assertEqual(rv.status_code, 400, "HTML status code is wrong %i"%rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s"%rv.mimetype)
def test_output_parsing_r_what(self): rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/processing_async', headers=self.admin_auth_header, data=json_dumps(r_what), content_type="application/json") resp = self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="finished") process_results = { "region": { "cells": "249324", "cols": "526", "e": "644971", "ewres": "28.5", "n": "228527.25", "nsres": "28.5", "projection": "99", "rows": "474", "s": "215018.25", "w": "629980", "zone": "0" }, "sample": [ [ "easting", "northing", "site_name", "landuse96_28m@PERMANENT", "landuse96_28m@PERMANENT_label" ], [ "633614.08", "224125.12", "", "15", "Southern Yellow Pine" ], [ "632972.36", "225382.87", "", "4", "Managed Herbaceous Cover" ] ] } self.assertEqual(resp["process_results"], process_results)
def test_job_resumption_exporter(self): """Test job resumption with processing_async_export endpoint and exporter """ tpl = Template(json_dumps(process_chain_4_exporter)) rv = self.server.post(URL_PREFIX + self.endpoint, headers=self.admin_auth_header, data=tpl.render(map1="elevation2@PERMANENT", map2="baum"), content_type="application/json") resp = self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error") status_url = resp["urls"]["status"].split(URL_PREFIX)[-1] # check if interim results are saved resp_data = json_loads(rv.data) rv_user_id = resp_data["user_id"] rv_resource_id = resp_data["resource_id"] interim_dir = os.path.join(global_config.GRASS_RESOURCE_DIR, rv_user_id, "interim", rv_resource_id) self.assertTrue( os.path.isdir(interim_dir), "Interim results are not stored in the expected folder") # resumption of the job rv2 = self.server.put(URL_PREFIX + status_url, headers=self.admin_auth_header, data=tpl.render(map1="elevation@PERMANENT", map2="baum"), content_type="application/json") resp2 = self.waitAsyncStatusAssertHTTP(rv2, headers=self.admin_auth_header, http_status=200, status="finished") # Get the exported results urls = resp2["urls"]["resources"] for url in urls: print(url) rv = self.server.get(url, headers=self.admin_auth_header) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i" % rv.status_code) if url.endswith('.tif'): self.assertEqual(rv.mimetype, "image/tiff", "Wrong mimetype %s" % rv.mimetype) elif url.endswith('.zip'): self.assertEqual(rv.mimetype, "application/zip", "Wrong mimetype %s" % rv.mimetype)
def test_async_processing_error_to_long(self): """ Test the error handling in case the program is running too long Returns: """ rv = self.server.post(URL_PREFIX + '/custom_process/sleep', headers=self.user_auth_header, data=json_dumps(["10"]), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="terminated", message_check="AsyncProcessTimeLimit:")
def test_2_async_processing_postgis_run(self): # Don't overwrite an existing layer self.gen_output_layer_name() rv = self.server.post(URL_PREFIX + '/locations/LL/processing_async_export', headers=self.admin_auth_header, data=json_dumps(process_chain_postgis), content_type="application/json") resp = self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="finished") self.assertEqual(len(resp["process_log"]), 2)
def test_async_processing_error_2(self): """ Test the error handling in case the program was not found Returns: """ rv = self.server.post(URL_PREFIX + '/custom_process/cat', headers=self.admin_auth_header, data=json_dumps(["non_existing_file"]), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error", message_check="AsyncProcessError:")
def test_stac_import(self): """ Code test STAC collection importation with http reponse 200 """ endpoint = URL_PREFIX + '/locations/nc_spm_08/processing_async_export' rv = self.server.post(endpoint, headers=self.admin_auth_header, data=json_dumps(process_chain_stac_import), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=200, status="finished")
def test_1_merge_no_access_to_target_mapset_error(self): """No access to target mapset error test""" # Try merge source mapsets into target mapset rv = self.server.post( URL_PREFIX + '/locations/nc_spm_08/mapsets/user1/merging_async', headers=self.user_auth_header, data=json_dumps(["Source_A", "Source_B"]), content_type="application/json") print(rv.data) self.waitAsyncStatusAssertHTTP(rv, headers=self.user_auth_header, http_status=400, status="error", message_check="AsyncProcessError")
def test_async_processing_unauthorized_access(self): """ Test the error handling in case the program is is not in access list Returns: """ rv = self.server.post(URL_PREFIX + '/custom_process/ps', headers=self.user_auth_header, data=json_dumps(["-rf"]), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error", message_check="AsyncProcessError:")
def create_raster_layer(self, mapset_name, raster_name): # Remove potentially existing raster layer rv = self.server.delete(URL_PREFIX + '/locations/nc_spm_08/mapsets/%s/raster_layers/%s'%(mapset_name, raster_name), headers=self.user_auth_header) # print(rv.data) # Create rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/mapsets/%s/raster_layers/%s'%(mapset_name, raster_name), headers=self.user_auth_header, data=json_dumps({"region":{"n":228500, "s":215000, "e":645000,"w":630000, "ewres": 50, "nsres": 50}, "expression": "1"}), content_type="application/json") # print(rv.data) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i"%rv.status_code) self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s"%rv.mimetype)
def test_async_processing_export(self): rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/processing_async_export_s3', headers=self.admin_auth_header, data=json_dumps(process_chain_long), content_type="application/json") resp = self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header) # Get the exported results urls = resp["urls"]["resources"] for url in urls: print(url) rv = requests.get(url) print(rv) self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i"%rv.status_code)
def test_async_processing_error_2(self): """ Wrong module error :return: """ rv = self.server.post(URL_PREFIX + '/locations/nc_spm_08/processing_async', headers=self.user_auth_header, data=json_dumps(process_chain_error_2), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.user_auth_header, http_status=400, status="error", message_check="AsyncProcessError:")
def test_stac_source_error_import(self): """ Code test STAC collection importation with http reponse 400, raising error on misstructured, undefined, or missing source ID. """ endpoint = URL_PREFIX + '/locations/nc_spm_08/processing_async_export' rv = self.server.post( endpoint, headers=self.admin_auth_header, data=json_dumps(process_chain_stac_source_error_import), content_type="application/json") self.waitAsyncStatusAssertHTTP(rv, headers=self.admin_auth_header, http_status=400, status="error")
def make_test_environ_builder( app, path='/', base_url=None, subdomain=None, url_scheme=None, *args, **kwargs ): """Creates a new test builder with some application defaults thrown in.""" assert ( not (base_url or subdomain or url_scheme) or (base_url is not None) != bool(subdomain or url_scheme) ), 'Cannot pass "subdomain" or "url_scheme" with "base_url".' if base_url is None: http_host = app.config.get('SERVER_NAME') or 'localhost' app_root = app.config['APPLICATION_ROOT'] if subdomain: http_host = '{0}.{1}'.format(subdomain, http_host) if url_scheme is None: url_scheme = app.config['PREFERRED_URL_SCHEME'] url = url_parse(path) base_url = '{scheme}://{netloc}/{path}'.format( scheme=url.scheme or url_scheme, netloc=url.netloc or http_host, path=app_root.lstrip('/') ) path = url.path if url.query: sep = b'?' if isinstance(url.query, bytes) else '?' path += sep + url.query if 'json' in kwargs: assert 'data' not in kwargs, ( "Client cannot provide both 'json' and 'data'." ) # push a context so flask.json can use app's json attributes with app.app_context(): kwargs['data'] = json_dumps(kwargs.pop('json')) if 'content_type' not in kwargs: kwargs['content_type'] = 'application/json' return EnvironBuilder(path, base_url, *args, **kwargs)
def make_test_environ_builder( app, path="/", base_url=None, subdomain=None, url_scheme=None, *args, **kwargs ): """Create a :class:`~werkzeug.test.EnvironBuilder`, taking some defaults from the application. :param app: The Flask application to configure the environment from. :param path: URL path being requested. :param base_url: Base URL where the app is being served, which ``path`` is relative to. If not given, built from :data:`PREFERRED_URL_SCHEME`, ``subdomain``, :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. :param subdomain: Subdomain name to append to :data:`SERVER_NAME`. :param url_scheme: Scheme to use instead of :data:`PREFERRED_URL_SCHEME`. :param json: If given, this is serialized as JSON and passed as ``data``. Also defaults ``content_type`` to ``application/json``. :param args: other positional arguments passed to :class:`~werkzeug.test.EnvironBuilder`. :param kwargs: other keyword arguments passed to :class:`~werkzeug.test.EnvironBuilder`. """ assert not (base_url or subdomain or url_scheme) or (base_url is not None) != bool( subdomain or url_scheme ), 'Cannot pass "subdomain" or "url_scheme" with "base_url".' if base_url is None: http_host = app.config.get("SERVER_NAME") or "localhost" app_root = app.config["APPLICATION_ROOT"] if subdomain: http_host = "{0}.{1}".format(subdomain, http_host) if url_scheme is None: url_scheme = app.config["PREFERRED_URL_SCHEME"] url = url_parse(path) base_url = "{scheme}://{netloc}/{path}".format( scheme=url.scheme or url_scheme, netloc=url.netloc or http_host, path=app_root.lstrip("/"), ) path = url.path if url.query: sep = b"?" if isinstance(url.query, bytes) else "?" path += sep + url.query if "json" in kwargs: assert "data" not in kwargs, "Client cannot provide both 'json' and 'data'." # push a context so flask.json can use app's json attributes with app.app_context(): kwargs["data"] = json_dumps(kwargs.pop("json")) if "content_type" not in kwargs: kwargs["content_type"] = "application/json" return EnvironBuilder(path, base_url, *args, **kwargs)