def before_all(context): """ Runs once before all tests. Set up some global state necessary to the tests and test runner. * Get the vendor config and attach it to the context. * Authorize against the vendor FHIR server and store the authorization. * Get the test plan so that we can show a progress meter. * Load the conformance statement so we know which resources are supported. """ # Get the vendor config and attach it to the context. vendor = getattr(context.config, 'vendor', os.getenv('VENDOR')) override = getattr(context.config, 'override', os.getenv('CONFIG_OVERRIDE', '')) vendor_config = get_config(vendor.lower(), override) context.vendor_config = vendor_config # Set the ElasticSearch logging endpoint context.config.es_url = os.getenv('ES_URL') # Authorize against the vendor FHIR server. context.oauth = factory(vendor_config) try: context.oauth.authorize() if getattr(context.oauth, 'patient', None) is not None: vendor_config['api']['patient'] = context.oauth.patient except AssertionError as error: logging.error(utils.bad_response_assert(error.args[0], '')) except authorize.AuthorizationException as err: error = oauth.ERROR_SELENIUM_SCREENSHOT.format( err.args[0], err.args[1], context.vendor_config['host'], ) raise Exception(error) # Get the test plan so that we can show a progress meter. context.config.plan = [] # There is no other way to get a feature list from the context. # Since this is for display purposes only, this should be safe. features = context._runner.features # pylint: disable=protected-access for feature in features: scenariolist = [] context.config.plan.append({ 'name': feature.name, 'location': str(feature.location), 'scenarios': scenariolist}) for scenario in feature.scenarios: scenariolist.append({ 'name': scenario.name, 'location': str(scenario.location)}) # Download the conformance statement try: context.conformance = fhir.get_conformance_statement(vendor_config['api']['url']) except ValueError as error: context.conformance = None logging.error(utils.bad_response_assert(error.response, '')) # Define a global cache context.cache = Cache(redis.StrictRedis())
def step_impl(context, field_name, value_set_url): path = field_name.split('.') filter_type = path.pop(0) resources = get_resources(context.response.json(), filter_type) for res in resources: found = traverse(res, path) if isinstance(found, str): found = [found] elif isinstance(found, dict): assert 'coding' in found, \ utils.bad_response_assert(context.response, ERROR_CODING_MISSING, field_name=field_name, json=json.dumps(found, indent=2)) found = [coding.get('code') for coding in found.get('coding')] for code in found: try: valid = systems.validate_code(code, value_set_url) except systems.SystemNotRecognized: valid = False assert valid, utils.bad_response_assert(context.response, ERROR_INVALID_BINDING, code=code, system=value_set_url)
def check_reference(reference, orig, context): """ Follow references and make sure they exist. Args: reference (str): A reference in the format: * Resource/id * http://example.com/base/Resource/id * #id orig (dict): The original resource, used when checking contained references. context: The behave context """ if reference.startswith('#'): matches = [ contained for contained in orig.get('contained', []) if contained['id'] == reference[1:] ] assert len(matches) == 1, \ utils.bad_response_assert(context.response, ERROR_UNRESOLVED_REFERENCE, reference=reference) else: response = utils.get_resource(context, reference) assert int(response.status_code) == 200, \ utils.bad_response_assert(context.response, ERROR_UNRESOLVED_REFERENCE, reference=reference)
def check_reference(reference, orig, context): """ Follow references and make sure they exist. Args: reference (str): A reference in the format: * Resource/id * http://example.com/base/Resource/id * #id orig (dict): The original resource, used when checking contained references. context: The behave context """ if reference.startswith('#'): matches = [contained for contained in orig.get('contained', []) if contained['id'] == reference[1:]] assert len(matches) == 1, \ utils.bad_response_assert(context.response, ERROR_UNRESOLVED_REFERENCE, reference=reference) else: response = utils.get_resource(context, reference) assert int(response.status_code) == 200, \ utils.bad_response_assert(context.response, ERROR_UNRESOLVED_REFERENCE, reference=reference)
def before_all(context): """ Runs once before all tests. Set up some global state necessary to the tests and test runner. * Get the vendor config and attach it to the context. * Authorize against the vendor FHIR server and store the authorization. * Get the test plan so that we can show a progress meter. * Load the conformance statement so we know which resources are supported. """ # Get the vendor config and attach it to the context. vendor = getattr(context.config, 'vendor', os.getenv('VENDOR')) vendor_config = get_config(vendor.lower()) context.vendor_config = vendor_config # Authorize against the vendor FHIR server. context.oauth = factory(vendor_config) try: context.oauth.authorize() if getattr(context.oauth, 'patient', None) is not None: vendor_config['api']['patient'] = context.oauth.patient except AssertionError as error: logging.error(utils.bad_response_assert(error.args[0], '')) except authorize.AuthorizationException as err: error = oauth.ERROR_SELENIUM_SCREENSHOT.format( err.args[0], err.args[1], context.vendor_config['host'], ) raise Exception(error) # Get the test plan so that we can show a progress meter. context.config.plan = [] # There is no other way to get a feature list from the context. # Since this is for display purposes only, this should be safe. features = context._runner.features # pylint: disable=protected-access for feature in features: scenariolist = [] context.config.plan.append({ 'name': feature.name, 'location': str(feature.location), 'scenarios': scenariolist }) for scenario in feature.scenarios: scenariolist.append({ 'name': scenario.name, 'location': str(scenario.location) }) # Download the conformance statement try: context.conformance = fhir.get_conformance_statement( vendor_config['api']['url']) except ValueError as error: context.conformance = None logging.error(utils.bad_response_assert(error.response, ''))
def step_impl(context, field_name, value): resource = context.response.json() assert resource.get(field_name) is not None, \ utils.bad_response_assert(context.response, ERROR_FIELD_MISSING, field_name=field_name) assert resource[field_name] == value, \ utils.bad_response_assert(context.response, ERROR_FIELD_UNEXPECTED_VALUE, field_name=field_name, expected=value, actual=resource[field_name])
def step_impl(context, field_name, value): path = field_name.split('.') filter_type = path.pop(0) resources = get_resources(context.response.json(), filter_type) for res in resources: found = traverse(res, path) assert found, utils.bad_response_assert(context.response, ERROR_FIELD_NOT_PRESENT, field=field_name, json=json.dumps(res, indent=2)) assert value in found, utils.bad_response_assert(context.response, ERROR_WRONG_FIXED, values=found, value=value)
def step_impl(context, field_name): resource = context.response.json() assert resource.get(field_name) is not None, \ utils.bad_response_assert(context.response, ERROR_FIELD_MISSING, field_name=field_name)
def assert_field_value_matches(context, resource, field_name, expected_value): assert resource[field_name] == expected_value, \ utils.bad_response_assert(context.response, ERROR_FIELD_UNEXPECTED_VALUE, field_name=field_name, expected=expected_value, actual=resource[field_name])
def step_impl(context): resource = context.response.json() assert "resourceType" in resource, \ "Resource has no resourceType: {res}".format(res=resource) url = "{url}{resource}/$validate".format( url='http://api:8080/baseDstu2/', resource=resource['resourceType'], ) headers = { 'Authorization': 'Bearer {0}'.format(context.oauth.access_token), 'Accept': 'application/json', 'Accept-Encoding': 'deflate,sdch', } try: resp = requests.post(url, json=resource, headers=headers) except requests.exceptions.ConnectionError as err: return context.scenario.skip(reason=str(err)) outcome = resp.json() issues = [ issue for issue in outcome.get('issue') if issue.get('severity') == 'error' ] assert not issues, \ utils.bad_response_assert(context.response, ERROR_VALIDATION_ISSUES, issues=json.dumps(issues, indent=4))
def step_impl(context, response_code): response_code = int(response_code) assert context.response.status_code != response_code, \ utils.bad_response_assert(context.response, ERROR_STATUS_CODE, status_code=context.response.status_code)
def step_impl(context, resource_type, field_name): if not StepDecider(context).should_run_test(): return path = field_name.split('.') filter_type = path.pop(0) resources = get_resources(context.response.json(), filter_type) for res in resources: try: reference = utils.traverse(res, path).get('reference') # Validate the reference for FHIR compliance formatting. # http://hl7.org/fhir/references.html reference_regex = r'((http|https)://([A-Za-z0-9\\\.\:\%\$]\/)*)?(' + \ resource_type + r')\/[A-Za-z0-9\-\.]{1,64}(\/_history\/[A-Za-z0-9\-\.]{1,64})?' compiled_regex = re.compile(reference_regex) regex_search_results = compiled_regex.search(reference) except AttributeError: reference = '' assert regex_search_results, \ utils.bad_response_assert(context.response, ERROR_REFERENCE_MATCH, reference=reference, resource_type=resource_type)
def step_impl(context, field): data = context.response.json() assert field in data, \ utils.bad_response_assert(context.response, ERROR_MISSING_FIELD, field=field, response_fields=list(data.keys()))
def before_all(context): """ Runs once before all tests. Set up some global state necessary to the tests and test runner. * Get the vendor config and attach it to the context. * Authorize against the vendor FHIR server and store the authorization. * Get the test plan so that we can show a progress meter. * Load the conformance statement so we know which resources are supported. """ # Get the vendor config and attach it to the context. vendor = getattr(context.config, 'vendor', os.getenv('VENDOR')) vendor_config = get_config(vendor.lower()) context.vendor_config = vendor_config # Authorize against the vendor FHIR server. context.oauth = factory(vendor_config) try: context.oauth.authorize() if getattr(context.oauth, 'patient', None) is not None: vendor_config['api']['patient'] = context.oauth.patient except AssertionError as error: logging.error(utils.bad_response_assert(error.args[0], '')) # Get the test plan so that we can show a progress meter. context.config.plan = [] # There is no other way to get a feature list from the context. # Since this is for display purposes only, this should be safe. features = context._runner.features # pylint: disable=protected-access for feature in features: scenariolist = [] context.config.plan.append({ 'name': feature.name, 'location': str(feature.location), 'scenarios': scenariolist}) for scenario in feature.scenarios: scenariolist.append({ 'name': scenario.name, 'location': str(scenario.location)}) # Download the conformance statement try: context.conformance = fhir.get_conformance_statement(vendor_config['api']['url']) except ValueError as error: context.conformance = None logging.error(utils.bad_response_assert(error.response, ''))
def step_impl(context): resource = context.response.json() entries = resource.get('entry', []) assert len(entries) >= 1, \ utils.bad_response_assert(context.response, ERROR_ENTRY_COUNT, count=len(entries))
def step_impl(context): query = s4s.MU_CCDS_MAPPINGS['Patient demographics'] query = query.format(patientId=context.vendor_config['versioned_api'].get('patient')) response = utils.get_resource(context, query) assert response.status_code == 200, \ utils.bad_response_assert(response, ERROR_NO_ACCESS)
def step_impl(context): query = s4s.MU_CCDS_MAPPINGS['Patient demographics'] query = query.format(patientId=context.vendor_config['api'].get('patient')) response = utils.get_resource(context, query) assert response.status_code == 200, \ utils.bad_response_assert(response, ERROR_NO_ACCESS)
def step_impl(context, name, field_name): path = field_name.split('.') filter_type = path.pop(0) resources = get_resources(context.response.json(), filter_type) for res in resources: found = traverse(res, path) assert len(found) > 0, utils.bad_response_assert(context.response, ERROR_REQUIRED, name=name)
def step_impl(context, resource_type): resource = context.response.json() entries = [entry['resource'] for entry in resource.get('entry', []) if entry.get('search', {}).get('mode', 'match') == 'match' and entry.get('resource', {}).get('resourceType') == resource_type] assert len(entries) >= 1, \ utils.bad_response_assert(context.response, ERROR_ENTRY_COUNT, count=len(entries))
def step_impl(context, field_name, value): path = field_name.split('.') filter_type = path.pop(0) resources = get_resources(context.response.json(), filter_type) found_one = found_at_least_one(resources, path, value) assert found_one, utils.bad_response_assert(response=context.response, message=ERROR_NO_VALID_ENTRIES, field_name=field_name, value=value)
def step_impl(context, resource_type): resource = context.response.json() entries = [ entry['resource'] for entry in resource.get('entry', []) if entry.get('search', {}).get('mode', 'match') == 'match' and entry.get('resource', {}).get('resourceType') == resource_type ] assert len(entries) >= 1, \ utils.bad_response_assert(context.response, ERROR_ENTRY_COUNT, count=len(entries))
def step_impl(context, field_name, value): path = field_name.split('.') filter_type = path.pop(0) resources = get_resources(context.response.json(), filter_type) found_one = found_at_least_one(resources, path, value) assert found_one, utils.bad_response_assert( response=context.response, message=ERROR_NO_VALID_ENTRIES, field_name=field_name, value=value)
def step_impl(context, field_name): resource = context.response.json() if resource['resourceType'] == 'Bundle': entries = [entry['resource'] for entry in resource.get('entry', [])] else: entries = [resource] for entry in entries: assert entry.get(field_name) is not None, \ utils.bad_response_assert(context.response, ERROR_FIELD_MISSING, field_name=field_name)
def step_impl(context, name, field_name): if not StepDecider(context).should_run_test(): return path = field_name.split('.') filter_type = path.pop(0) resources = get_resources(context.response.json(), filter_type) for res in resources: found = utils.traverse(res, path) assert len(found) > 0, utils.bad_response_assert(context.response, ERROR_REQUIRED, name=name)
def step_impl(context, resource_type, field_name): path = field_name.split('.') filter_type = path.pop(0) resources = get_resources(context.response.json(), filter_type) for res in resources: try: reference = traverse(res, path).get('reference') except AttributeError: reference = '' assert reference.startswith(resource_type), \ utils.bad_response_assert(context.response, ERROR_REFERENCE_MATCH, reference=reference, resource_type=resource_type)
def step_impl(context, field_name, sub_field): path = field_name.split('.') filter_type = path.pop(0) sub_path = sub_field.split('.') sub_type = sub_path.pop(0) resources = get_resources(context.response.json(), filter_type) for res in resources: found = traverse(res, path) for item in found: match = traverse(item, sub_path) assert match is not None, \ utils.bad_response_assert(context.response, ERROR_REQUIRED, name=sub_type)
def step_impl(context, name, field_one_name, field_two_name): path_one = field_one_name.split('.') path_two = field_two_name.split('.') filter_type = path_one.pop(0) assert filter_type == path_two.pop(0) resources = get_resources(context.response.json(), filter_type) for res in resources: found_one = traverse(res, path_one) found_two = traverse(res, path_two) assert (found_one is not None) or (found_two is not None), \ utils.bad_response_assert(context.response, ERROR_REQUIRED, name=name)
def step_impl(context): resource = context.response.json() if resource['resourceType'] == 'Bundle': entries = [ entry['resource'] for entry in resource.get('entry', []) if entry.get('search', {}).get('mode', 'match') == 'match' ] else: entries = [resource] context.scenario.systems = [] bad_codings = [] for entry in entries: found = utils.find_named_key(entry, 'coding') for codings in found: for coding in codings: if not coding: bad_codings.append(coding) continue try: valid = systems.validate_coding(coding) recognized = True except systems.SystemNotRecognized: valid = True recognized = False context.scenario.systems.append({ 'system': coding.get('system'), 'code': coding.get('code'), 'valid': valid, 'recognized': recognized, }) if not valid: bad_codings.append(coding) assert not bad_codings, \ utils.bad_response_assert(context.response, 'Bad codings: {codings}', codings=json.dumps(bad_codings, indent=2))
def step_impl(context): resource = context.response.json() if resource['resourceType'] == 'Bundle': entries = [entry['resource'] for entry in resource.get('entry', []) if entry.get('search', {}).get('mode', 'match') == 'match'] else: entries = [resource] context.scenario.systems = [] bad_codings = [] for entry in entries: found = utils.find_named_key(entry, 'coding') for codings in found: for coding in codings: if not coding: bad_codings.append(coding) continue try: valid = systems.validate_coding(coding) recognized = True except systems.SystemNotRecognized: valid = True recognized = False context.scenario.systems.append({ 'system': coding.get('system'), 'code': coding.get('code'), 'valid': valid, 'recognized': recognized, }) if not valid: bad_codings.append(coding) assert not bad_codings, \ utils.bad_response_assert(context.response, 'Bad codings: {codings}', codings=json.dumps(bad_codings, indent=2))
def step_impl(context, field_string, resource): if not StepDecider(context).should_run_test(): return fields_to_find = field_string.split(",") resources = get_resources(context.response.json(), resource) valid_resource_ids = set([ res.get("id") for res in resources if not ArgonautObservationDecider(res).should_validate() or utils.has_one_of(res, fields_to_find)]) all_resource_ids = set([res.get("id") for res in resources]) invalid_resource_ids = all_resource_ids - valid_resource_ids assert len(invalid_resource_ids) == 0, \ utils.bad_response_assert(context.response, ERROR_MISSING_FIELD, resource_ids=', '.join(invalid_resource_ids), field_list=field_string)
def step_impl(context, version_name): resource = context.response.json() assert "resourceType" in resource, \ "Resource has no resourceType: {res}".format(res=resource) server_config_key = "API_SERVER_{server_version}".format(server_version=version_name) assert server_config_key in context.env_config, \ "No API Server configured for this version ({v}).".format(v=version_name) url = "{url}/{resource}/$validate".format( url=context.env_config[server_config_key], resource=resource['resourceType'], ) headers = { 'Authorization': 'Bearer {0}'.format(context.oauth.access_token), 'Accept': 'application/json', 'Accept-Encoding': 'deflate,sdch', } try: resp = requests.post(url, json=resource, headers=headers) except requests.exceptions.ConnectionError as err: return context.scenario.skip(reason=str(err)) outcome = resp.json() issues = [issue for issue in outcome.get('issue') if issue.get('severity') == 'error'] assert not issues, \ utils.bad_response_assert(context.response, ERROR_VALIDATION_ISSUES, issues=json.dumps(issues, indent=4))
def assert_field_exists(context, resource, field_name): assert resource.get(field_name) is not None, \ utils.bad_response_assert(context.response, ERROR_FIELD_MISSING, field_name=field_name)
def before_all(context): """ Runs once before all tests. Set up some global state necessary to the tests and test runner. * Get the vendor config and attach it to the context. * Authorize against the vendor FHIR server and store the authorization. * Get the test plan so that we can show a progress meter. * Load the conformance statement so we know which resources are supported. """ # Get the vendor config and attach it to the context. vendor = getattr(context.config, 'vendor', os.getenv('VENDOR')) override = getattr(context.config, 'override', os.getenv('CONFIG_OVERRIDE', '')) vendor_config = get_vendor_config(vendor, override) # Get configuration from the test server's environment. env_config = get_env_config() # Attempt to retrieve the security URL for this version. vendor_config['versioned_auth']['aud'] = vendor_config['versioned_api'][ 'url'] context.vendor_config = copy.deepcopy(vendor_config) context.env_config = copy.deepcopy(env_config) # Filter out any tagged vendor config steps steps = vendor_config['versioned_auth'].get('steps', []) steps = [step for step in steps if 'when' not in step] vendor_config['versioned_auth']['steps'] = steps # Set the ElasticSearch logging endpoint context.config.es_url = os.getenv('ES_URL') # Authorize against the vendor FHIR server. try: context.oauth = factory(vendor_config) context.oauth.authorize() if getattr(context.oauth, 'patient', None) is not None: context.vendor_config['versioned_api'][ 'patient'] = context.oauth.patient except AssertionError as error: logging.error(utils.bad_response_assert(error.args[0], '')) raise Exception(utils.bad_response_assert(error.args[0], '')) except authorize.AuthorizationException as err: error = oauth.ERROR_SELENIUM_SCREENSHOT.format( err.args[0], err.args[1], err.args[2], context.vendor_config['host'], ) raise Exception(error) except ValueError as error: logging.error(utils.bad_response_assert(error.response, '')) raise Exception(utils.bad_response_assert(error.response, '')) # Get the test plan so that we can show a progress meter. context.config.plan = [] # There is no other way to get a feature list from the context. # Since this is for display purposes only, this should be safe. features = context._runner.features # pylint: disable=protected-access for feature in features: scenariolist = [] context.config.plan.append({ 'name': feature.name, 'location': str(feature.location), 'scenarios': scenariolist }) for scenario in feature.scenarios: scenariolist.append({ 'name': scenario.name, 'location': str(scenario.location) }) # Download the conformance statement try: context.conformance = fhir.get_conformance_statement( vendor_config['versioned_auth']['aud']) except ValueError as error: context.conformance = None logging.error(utils.bad_response_assert(error.response, '')) # Define a global cache context.cache = Cache(redis.StrictRedis())