def generate_curl_example(endpoint: str, method: str, api_url: str, auth_email: str = DEFAULT_AUTH_EMAIL, auth_api_key: str = DEFAULT_AUTH_API_KEY, exclude: Optional[List[str]] = None, include: Optional[List[str]] = None) -> List[str]: if exclude is not None and include is not None: raise AssertionError( "exclude and include cannot be set at the same time.") lines = ["```curl"] operation = endpoint + ":" + method.lower() operation_entry = openapi_spec.spec()['paths'][endpoint][method.lower()] global_security = openapi_spec.spec()['security'] operation_params = operation_entry.get("parameters", []) operation_request_body = operation_entry.get("requestBody", None) operation_security = operation_entry.get("security", None) if settings.RUNNING_OPENAPI_CURL_TEST: # nocoverage from zerver.openapi.curl_param_value_generators import patch_openapi_example_values operation_params, operation_request_body = patch_openapi_example_values( operation, operation_params, operation_request_body) format_dict = {} for param in operation_params: if param["in"] != "path": continue example_value = get_openapi_param_example_value_as_string( endpoint, method, param) format_dict[param["name"]] = example_value example_endpoint = endpoint.format_map(format_dict) curl_first_line_parts = ["curl"] + curl_method_arguments( example_endpoint, method, api_url) lines.append(" ".join(curl_first_line_parts)) insecure_operations = ['/dev_fetch_api_key:post'] if operation_security is None: if global_security == [{'basicAuth': []}]: authentication_required = True else: raise AssertionError( "Unhandled global securityScheme." + " Please update the code to handle this scheme.") elif operation_security == []: if operation in insecure_operations: authentication_required = False else: raise AssertionError( "Unknown operation without a securityScheme. " + "Please update insecure_operations.") else: raise AssertionError( "Unhandled securityScheme. Please update the code to handle this scheme." ) if authentication_required: lines.append(f" -u {auth_email}:{auth_api_key}") for param in operation_params: if param["in"] == "path": continue param_name = param["name"] if include is not None and param_name not in include: continue if exclude is not None and param_name in exclude: continue example_value = get_openapi_param_example_value_as_string( endpoint, method, param, curl_argument=True) lines.append(example_value) if "requestBody" in operation_entry: properties = operation_entry["requestBody"]["content"][ "multipart/form-data"]["schema"]["properties"] for key, property in properties.items(): lines.append(' -F "{}=@{}"'.format(key, property["example"])) for i in range(1, len(lines) - 1): lines[i] = lines[i] + " \\" lines.append("```") return lines
def test_validate_against_openapi_schema(self) -> None: with self.assertRaises(ValidationError, msg=("Additional properties are not" + " allowed ('foo' was unexpected)")): bad_content: Dict[str, object] = { 'msg': '', 'result': 'success', 'foo': 'bar', } validate_against_openapi_schema(bad_content, TEST_ENDPOINT, TEST_METHOD, TEST_RESPONSE_SUCCESS) with self.assertRaises(ValidationError, msg=("42 is not of type string")): bad_content = { 'msg': 42, 'result': 'success', } validate_against_openapi_schema(bad_content, TEST_ENDPOINT, TEST_METHOD, TEST_RESPONSE_SUCCESS) with self.assertRaises(ValidationError, 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 test_dict: Dict[str, Any] = {} # Check that validate_against_openapi_schema correctly # descends into 'deep' objects and arrays. Test 1 should # pass, Test 2 has a 'deep' extraneous key and Test 3 has a # 'deep' opaque object. Also the parameters are a heterogenous # mix of arrays and objects to verify that our descent logic # correctly gets to the the deeply nested objects. with open( os.path.join(os.path.dirname(OPENAPI_SPEC_PATH), "testing.yaml")) as test_file: test_dict = yaml.safe_load(test_file) openapi_spec.spec()['paths']['testing'] = test_dict try: validate_against_openapi_schema( (test_dict['test1']['responses']['200']['content'] ['application/json']['example']), 'testing', 'test1', '200') with self.assertRaises( ValidationError, msg='Extraneous key "str4" in response\'s content'): validate_against_openapi_schema( (test_dict['test2']['responses']['200']['content'] ['application/json']['example']), 'testing', 'test2', '200') with self.assertRaises(SchemaError, msg='Opaque object "obj"'): # Checks for opaque objects validate_schema((test_dict['test3']['responses']['200'] ['content']['application/json']['schema'])) finally: openapi_spec.spec()['paths'].pop('testing', None)