smart_app_launch_test_kit 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbcdac5d671ebac20ff73778eddb755fb7a3774ef4ac3000260f6d6d6cb4d7f0
4
- data.tar.gz: 1f34741969397758075cab6802652dd7f8895d137d3f9b819c28ea7662a64d27
3
+ metadata.gz: 1565daad4304e65881d1a3a373d29c8674d19d57bf46342a1cdc95db6c29b6f4
4
+ data.tar.gz: 4923648577e4d53631a8efa7ccae1f254957d490e579359415ca4f9d426ac5fe
5
5
  SHA512:
6
- metadata.gz: 8b6bbae2d20d3039b3c2e701e66a85eb4dad83f4f6e8b7f044eac044f7de4582a03a9bbca2d2e38febcf41cf51216fcd0651c863fe90c890fbac2be284ff2bc2
7
- data.tar.gz: cbeca0cdb3c88e163e5e41ab7d8015715d8d4fd1192d69865b0936a1ab98fe6328053f7060f1c4e6aa7d2ef78fb0f0b445ebb1751ee9c3e346b622fa3e8631f1
6
+ metadata.gz: c1266d06f6b1bd55a93e84b93cdd0de9d628ac5d5eb084dc38817e5639869a35ccb2f5173163f0966786937ef3821a5b1e317233af2be5e042afca840f4649c3
7
+ data.tar.gz: 5101dabbab6be10be047d9e378f43fc939d605f7adcb5277c07c738f2aabbf80e5b565cb1a1885ed35184ac5b5bdf2b9a4311396498bb02766ed925986ce2433
@@ -0,0 +1,54 @@
1
+ require_relative 'ehr_launch_group_stu2'
2
+ require_relative 'token_response_body_test_stu2_2'
3
+
4
+ module SMARTAppLaunch
5
+ class EHRLaunchGroupSTU22 < EHRLaunchGroupSTU2
6
+ id :smart_ehr_launch_stu2_2
7
+ description %(
8
+ # Background
9
+
10
+ The [EHR
11
+ Launch](http://hl7.org/fhir/smart-app-launch/STU2.2/app-launch.html#launch-app-ehr-launch)
12
+ is one of two ways in which an app can be launched, the other being
13
+ Standalone launch. In an EHR launch, the app is launched from an
14
+ existing EHR session or portal by a redirect to the registered launch
15
+ URL. The EHR provides the app two parameters:
16
+
17
+ * `iss` - Which contains the FHIR server url
18
+ * `launch` - An identifier needed for authorization
19
+
20
+ # Test Methodology
21
+
22
+ Inferno will wait for the EHR server redirect upon execution. When the
23
+ redirect is received Inferno will check for the presence of the `iss`
24
+ and `launch` parameters. The security of the authorization endpoint is
25
+ then checked and authorization is attempted using the provided `launch`
26
+ identifier.
27
+
28
+ For more information on the #{title} see:
29
+
30
+ * [SMART EHR Launch Sequence](http://hl7.org/fhir/smart-app-launch/STU2.2/app-launch.html#launch-app-ehr-launch)
31
+ )
32
+
33
+ config(
34
+ inputs: {
35
+ use_pkce: {
36
+ default: 'true',
37
+ locked: true
38
+ },
39
+ pkce_code_challenge_method: {
40
+ default: 'S256',
41
+ locked: true
42
+ },
43
+ requested_scopes: {
44
+ default: 'launch openid fhirUser offline_access user/*.rs'
45
+ }
46
+ }
47
+ )
48
+
49
+ test from: :smart_token_response_body_stu2_2
50
+
51
+ token_response_body_index = children.find_index { |child| child.id.to_s.end_with? 'token_response_body' }
52
+ children[token_response_body_index] = children.pop
53
+ end
54
+ end
@@ -0,0 +1,198 @@
1
+ {
2
+ "resourceType": "CapabilityStatement",
3
+ "id": "examplehealth-r4",
4
+ "text": {
5
+ "status": "generated",
6
+ "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n\t\t\t<p>The EHR Server supports the following transactions for the resource Person: read, vread, \n update, history, search(name,gender), create and updates.</p>\n\t\t\t<p>The EHR System supports the following message: admin-notify::Person.</p>\n\t\t\t<p>The EHR Application has a \n <a href=\"http://fhir.hl7.org/base/Profilebc054d23-75e1-4dc6-aca5-838b6b1ac81d/_history/b5fdd9fc-b021-4ea1-911a-721a60663796\">general document profile</a>.\n </p>\n\t\t</div>"
7
+ },
8
+ "url": "urn:uuid:68D043B5-9ECF-4559-A57A-396E0D452311",
9
+ "version": "20130510",
10
+ "name": "ACME-EHR",
11
+ "title": "ACME EHR capability statement",
12
+ "status": "draft",
13
+ "experimental": true,
14
+ "date": "2012-01-04",
15
+ "publisher": "ACME Corporation",
16
+ "contact": [
17
+ {
18
+ "name": "System Administrator",
19
+ "telecom": [
20
+ {
21
+ "system": "email",
22
+ "value": "wile@acme.org"
23
+ }
24
+ ]
25
+ }
26
+ ],
27
+ "description": "This is the FHIR capability statement for the main EHR at ACME for the private interface - it does not describe the public interface",
28
+ "useContext": [
29
+ {
30
+ "code": {
31
+ "system": "http://terminology.hl7.org/CodeSystem/usage-context-type",
32
+ "code": "focus"
33
+ },
34
+ "valueCodeableConcept": {
35
+ "coding": [
36
+ {
37
+ "system": "http://terminology.hl7.org/CodeSystem/variant-state",
38
+ "code": "positive"
39
+ }
40
+ ]
41
+ }
42
+ }
43
+ ],
44
+ "jurisdiction": [
45
+ {
46
+ "coding": [
47
+ {
48
+ "system": "urn:iso:std:iso:3166",
49
+ "code": "US",
50
+ "display": "United States of America (the)"
51
+ }
52
+ ]
53
+ }
54
+ ],
55
+ "purpose": "Main EHR capability statement, published for contracting and operational support",
56
+ "copyright": "Copyright © Acme Healthcare and GoodCorp EHR Systems",
57
+ "kind": "instance",
58
+ "instantiates": [
59
+ "http://ihe.org/fhir/CapabilityStatement/pixm-client"
60
+ ],
61
+ "software": {
62
+ "name": "EHR",
63
+ "version": "0.00.020.2134",
64
+ "releaseDate": "2012-01-04"
65
+ },
66
+ "implementation": {
67
+ "description": "main EHR at ACME",
68
+ "url": "http://10.2.3.4/fhir"
69
+ },
70
+ "fhirVersion": "4.0.1",
71
+ "format": [
72
+ "xml",
73
+ "json"
74
+ ],
75
+ "patchFormat": [
76
+ "application/xml-patch+xml",
77
+ "application/json-patch+json"
78
+ ],
79
+ "implementationGuide": [
80
+ "http://hl7.org/fhir/us/lab"
81
+ ],
82
+ "rest": [
83
+ {
84
+ "mode": "server",
85
+ "documentation": "Main FHIR endpoint for acem health",
86
+ "security": {
87
+ "cors": true,
88
+ "service": [
89
+ {
90
+ "coding": [
91
+ {
92
+ "system": "http://terminology.hl7.org/CodeSystem/restful-security-service",
93
+ "code": "SMART-on-FHIR"
94
+ }
95
+ ]
96
+ }
97
+ ],
98
+ "description": "See Smart on FHIR documentation"
99
+ },
100
+ "resource": [
101
+ {
102
+ "type": "Patient",
103
+ "profile": "http://registry.fhir.org/r4/StructureDefinition/7896271d-57f6-4231-89dc-dcc91eab2416",
104
+ "supportedProfile": [
105
+ "http://registry.fhir.org/r4/StructureDefinition/00ab9e7a-06c7-4f77-9234-4154ca1e3347"
106
+ ],
107
+ "documentation": "This server does not let the clients create identities.",
108
+ "interaction": [
109
+ {
110
+ "code": "read"
111
+ },
112
+ {
113
+ "code": "vread",
114
+ "documentation": "Only supported for patient records since 12-Dec 2012"
115
+ },
116
+ {
117
+ "code": "update"
118
+ },
119
+ {
120
+ "code": "history-instance"
121
+ },
122
+ {
123
+ "code": "create"
124
+ },
125
+ {
126
+ "code": "history-type"
127
+ }
128
+ ],
129
+ "versioning": "versioned-update",
130
+ "readHistory": true,
131
+ "updateCreate": false,
132
+ "conditionalCreate": true,
133
+ "conditionalRead": "full-support",
134
+ "conditionalUpdate": false,
135
+ "conditionalDelete": "not-supported",
136
+ "searchInclude": [
137
+ "Organization"
138
+ ],
139
+ "searchRevInclude": [
140
+ "Person"
141
+ ],
142
+ "searchParam": [
143
+ {
144
+ "name": "identifier",
145
+ "definition": "http://hl7.org/fhir/SearchParameter/Patient-identifier",
146
+ "type": "token",
147
+ "documentation": "Only supports search by institution MRN"
148
+ },
149
+ {
150
+ "name": "general-practitioner",
151
+ "definition": "http://hl7.org/fhir/SearchParameter/Patient-general-practitioner",
152
+ "type": "reference"
153
+ }
154
+ ]
155
+ }
156
+ ],
157
+ "interaction": [
158
+ {
159
+ "code": "transaction"
160
+ },
161
+ {
162
+ "code": "history-system"
163
+ }
164
+ ],
165
+ "compartment": [
166
+ "http://hl7.org/fhir/CompartmentDefinition/patient"
167
+ ]
168
+ }
169
+ ],
170
+ "messaging": [
171
+ {
172
+ "endpoint": [
173
+ {
174
+ "protocol": {
175
+ "system": "http://terminology.hl7.org/CodeSystem/message-transport",
176
+ "code": "mllp"
177
+ },
178
+ "address": "mllp:10.1.1.10:9234"
179
+ }
180
+ ],
181
+ "reliableCache": 30,
182
+ "documentation": "ADT A08 equivalent for external system notifications",
183
+ "supportedMessage": [
184
+ {
185
+ "mode": "receiver",
186
+ "definition": "MessageDefinition/example"
187
+ }
188
+ ]
189
+ }
190
+ ],
191
+ "document": [
192
+ {
193
+ "mode": "consumer",
194
+ "documentation": "Basic rules for all documents in the EHR system",
195
+ "profile": "http://fhir.hl7.org/base/Profilebc054d23-75e1-4dc6-aca5-838b6b1ac81d/_history/b5fdd9fc-b021-4ea1-911a-721a60663796"
196
+ }
197
+ ]
198
+ }
@@ -0,0 +1,59 @@
1
+ require_relative 'smart_access_brands_validation_group'
2
+ require_relative 'smart_access_brands_retrieval_group'
3
+
4
+ module SMARTAppLaunch
5
+ class SMARTAccessBrandsGroup < Inferno::TestGroup
6
+ id :retrieve_and_validate_smart_access_brands
7
+ title 'Retrieve and Validate SMART Access Brands Bundle'
8
+ description %(
9
+ Verify that the Brand Bundle Publisher makes its User-access Brands publication publicly available
10
+ in the format defined by the [User Access Brand Bundle Profile](https://hl7.org/fhir/smart-app-launch/STU2.2/StructureDefinition-user-access-brands-bundle.html)
11
+ with valid Endpoint and Organization entries according to the
12
+ [User Access Endpoint Profile](https://hl7.org/fhir/smart-app-launch/STU2.2/StructureDefinition-user-access-endpoint.html)
13
+ and the [User Access Brand Profile](https://hl7.org/fhir/smart-app-launch/STU2.2/StructureDefinition-user-access-brand.html)
14
+ respectively. This test group will issue a HTTP GET request against the supplied URL to retrieve the publisher's
15
+ User-access Brands list and ensure the list is publicly accessible. It will then ensure that the returned
16
+ User-access Brands list publication is in the User Access Brand Bundle Profile format with valid User Access
17
+ Brands and User Access Endpoints.
18
+
19
+ For systems that provide the User Access Brands Bundle at a public endpoint, please run
20
+ this test with the User Access Brands Publication URL input populated and the User Access Brands Bundle
21
+ input left blank. While it is the expectation of the specification for the User Access Brands Bundle to be served
22
+ at a public-facing endpoint, testers can validate a User Access Brands Bundle not served at a public endpoint by
23
+ running these tests with the User Access Brands Bundle input populated and the User Access Brands Publication URL
24
+ input left blank. This will cause these group of retrieval group of tests to skip, rather than pass completely,
25
+ as being served at an stable location is considered a requirement of the spec.
26
+ )
27
+
28
+ input_instructions <<~INSTRUCTIONS
29
+ For systems that make their User Access Brand Bundle available at a public endpoint, please input
30
+ the User Access Brand Publication URL to retrieve the Bundle from there in order to perform validation, and leave
31
+ the User Access Brand Bundle input blank.
32
+
33
+ While it is the expectation of the specification for the User Access Brands Bundle to be publicly available,
34
+ for systems that do not have a User Access Brand Bundle served at a public endpoint, testers can validate by
35
+ providing the User Access Brand Bundle as an input and leaving the User Access Brand Publication URL input blank.
36
+ INSTRUCTIONS
37
+
38
+ run_as_group
39
+
40
+ input :user_access_brands_publication_url,
41
+ title: 'User Access Brands Publication URL',
42
+ description: %(The URL to the developer's public User Access Brands Publication. Insert your User Access
43
+ Brands publication URL if you host your Bundle at a public-facing endpoint and want Inferno to retrieve the
44
+ Bundle from there.),
45
+ optional: true
46
+
47
+ input :user_access_brands_bundle,
48
+ title: 'User Access Brands Bundle',
49
+ description: %(The developer's User Access Brands Publication in the JSON string format. If this input is
50
+ populated, Inferno will use the Bundle inserted here to do validation. Insert your User Access Brands
51
+ Bundle in the JSON format in this input to validate your list without Inferno needing to access the Bundle
52
+ via a public-facing endpoint.),
53
+ type: 'textarea',
54
+ optional: true
55
+
56
+ group from: :smart_access_brands_retrieval
57
+ group from: :smart_access_brands_validation
58
+ end
59
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'smart_access_brands_retrieve_bundle_test'
2
+
3
+ module SMARTAppLaunch
4
+ class SMARTAccessBrandsRetrievalGroup < Inferno::TestGroup
5
+ id :smart_access_brands_retrieval
6
+ title 'Retrieve SMART Access Brands Bundle'
7
+ description %(
8
+ A publisher's User Access Brand Bundle must be publicly available. This test
9
+ issues a HTTP GET request against the supplied URL and expects to receive
10
+ the User Access Brand Bundle at this location.
11
+ )
12
+ run_as_group
13
+
14
+ http_client do
15
+ url :user_access_brands_publication_url
16
+ headers Accept: 'application/json, application/fhir+json'
17
+ end
18
+
19
+ test from: :smart_access_brands_retrieve_bundle
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ module SMARTAppLaunch
2
+ class SMARTAccessBrandsRetrievalTest < Inferno::Test
3
+ id :smart_access_brands_retrieve_bundle
4
+ title 'Server returns publicly accessible SMART Access Brands Bundle'
5
+ description %(
6
+ Verify that the publisher's User Access Brands Bundle can be publicly
7
+ accessed at the supplied URL location.
8
+ )
9
+
10
+ makes_request :bundle_request
11
+
12
+ input :user_access_brands_publication_url,
13
+ optional: true
14
+
15
+ run do
16
+ skip_if user_access_brands_publication_url.blank?, %(
17
+ No User Access Brands Publication endpoint URL inputted. It is an expectation of the specification for the
18
+ User Access Brands Bundle to be publicly available'
19
+ )
20
+
21
+ get(tags: ['smart_access_brands_bundle'])
22
+ assert_response_status(200)
23
+ assert(request.headers.any? { |header| header.name == 'access-control-allow-origin' }, %(
24
+ All GET requests must support Cross-Origin Resource Sharing (CORS) for all GET requests to the artifacts
25
+ described in this guide.))
26
+ unless request.headers.any? { |header| header.name == 'etag' }
27
+ add_message('warning', 'Brand Bundle HTTP responses should include an Etag header')
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,77 @@
1
+ require_relative 'smart_access_brands_group'
2
+
3
+ module SMARTAppLaunch
4
+ class SMARTAccessBrandsSuite < Inferno::TestSuite
5
+ id 'smart_access_brands'
6
+ title 'SMART User-access Brands and Endpoints STU2.2'
7
+ short_title 'SMART User-access Brands'
8
+ version VERSION
9
+
10
+ description <<~DESCRIPTION
11
+ The SMART User-access Brands Test Suite verifies that Brand Bundle Publishers publish valid User-access
12
+ Brand Bundles according to the SMART App Launch IG
13
+ [User-access Brands and Endpoints](https://hl7.org/fhir/smart-app-launch/STU2.2/brands.html#user-access-brands-and-endpoints)
14
+ requirements.
15
+
16
+ The specification defines FHIR profiles for Endpoint, Organization, and Bundle resources that help users connect
17
+ their apps to health data providers. It outlines the process for data providers to publish FHIR Endpoint and
18
+ Organization resources, where each Organization includes essential branding information such as the organization's
19
+ name, logo, and user access details. Apps present branded Organizations to help users select the right data
20
+ providers.
21
+
22
+ This test suite is currently designed to fetch and validate a single User-Access Brand Bundle. It does not
23
+ currently evaluate the system's ability to allow Health Data Providers to manage all data elements marked
24
+ "Must-Support" in the "User Access Brand" and "User Access Endpoint" profiles.
25
+ DESCRIPTION
26
+
27
+ input_instructions <<~INSTRUCTIONS
28
+ For systems that make their User Access Brand Bundle available at a public endpoint, please input
29
+ the User Access Brand Publication URL to retrieve the Bundle from there in order to perform validation, and leave
30
+ the User Access Brand Bundle input blank.
31
+
32
+ Although it is expected that systems do have their Bundle publicly available, for systems that do not have a
33
+ User Access Brand Bundle served at a public endpoint, testers can validate by providing the User Access Brand
34
+ Bundle as an input and leaving the User Access Brand Publication URL input blank.
35
+ INSTRUCTIONS
36
+
37
+ VALIDATION_MESSAGE_FILTERS = [
38
+ /\A\S+: \S+: URL value '.*' does not resolve/,
39
+ %r{\A\S+: \S+: Bundled or contained reference not found within the bundle/resource} # Validator issue with Brand profile: https://chat.fhir.org/#narrow/stream/291844-FHIR-Validator/topic/SMART.20v2.2E2.20User.20Access.20Brands.3A.20Brand.20validation.20error.3F/near/466321024
40
+ ].freeze
41
+
42
+ fhir_resource_validator do
43
+ igs 'hl7.fhir.uv.smart-app-launch#2.2.0'
44
+
45
+ cli_context({
46
+ # Allow example URLs because we give tester option to follow URLs anyhow
47
+ # (configurable) and its nice to be able to have the examples in the IG pass
48
+ allowExampleUrls: true
49
+ })
50
+
51
+ message_filters = VALIDATION_MESSAGE_FILTERS
52
+
53
+ exclude_message do |message|
54
+ message_filters.any? { |filter| filter.match? message.message }
55
+ end
56
+ end
57
+
58
+ Dir.each_child(File.join(__dir__, '/smart_access_brands_examples/')) do |filename|
59
+ resource_example = File.read(File.join(__dir__, '/smart_access_brands_examples/', filename))
60
+ if filename.end_with?('.erb')
61
+ erb_template = ERB.new(resource_example)
62
+ resource_example = JSON.parse(erb_template.result).to_json
63
+ filename = filename.delete_suffix('.erb')
64
+ headers = { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*',
65
+ 'Etag' => SecureRandom.hex(32) }
66
+ else
67
+ filename = "#{filename.delete_suffix('.json')}/metadata"
68
+ headers = { 'Content-Type' => 'application/json' }
69
+ end
70
+ route_handler = proc { [200, headers, [resource_example]] }
71
+
72
+ route :get, File.join('/examples/', filename), route_handler
73
+ end
74
+
75
+ group from: :retrieve_and_validate_smart_access_brands
76
+ end
77
+ end
@@ -0,0 +1,104 @@
1
+ module SMARTAppLaunch
2
+ class SMARTAccessBrandsValidateBrands < Inferno::Test
3
+ id :smart_access_brands_valid_brands
4
+ title 'Service Base URL List contains valid Brand resources'
5
+ description %(
6
+ Verify that Bundle of User Access Brands and Endpoints contains Brands that are valid
7
+ Organization resources according to the [User Access Brand Profile](https://hl7.org/fhir/smart-app-launch/STU2.2/StructureDefinition-user-access-brand.html).
8
+
9
+ Along with validating the Organization resources, this test also ensures:
10
+ - Each endpoint referenced in the Organization portal extension also appear in Organization.endpoint
11
+ - Any endpoints referenced by the Organization must appear in the Bundle
12
+
13
+ This test does not currently validate availability or format of Brand or Portal logos.
14
+ )
15
+
16
+ input :user_access_brands_bundle,
17
+ optional: true
18
+
19
+ def find_referenced_endpoint(bundle_resource, endpoint_id_ref)
20
+ bundle_resource
21
+ .entry
22
+ .map(&:resource)
23
+ .select { |resource| resource.resourceType == 'Endpoint' }
24
+ .map(&:id)
25
+ .select { |endpoint_id| endpoint_id_ref.include? endpoint_id }
26
+ end
27
+
28
+ def find_extension(extension_array, extension_name)
29
+ extension_array.find do |extension|
30
+ extension.url.ends_with?(extension_name)
31
+ end
32
+ end
33
+
34
+ def find_all_extensions(extension_array, extension_name)
35
+ extension_array.select do |extension|
36
+ extension.url == extension_name
37
+ end
38
+ end
39
+
40
+ def check_portal_endpoints(portal_endpoints, organization_endpoints)
41
+ portal_endpoints.each do |portal_endpoint|
42
+ portal_endpoint_found = organization_endpoints.any? do |endpoint_reference|
43
+ portal_endpoint.valueReference.reference == endpoint_reference
44
+ end
45
+ assert(portal_endpoint_found, %(
46
+ Portal endpoints must also appear at Organization.endpoint. The portal endpoint with reference
47
+ #{portal_endpoint.valueReference.reference} was not found at Organization.endpoint.))
48
+ end
49
+ end
50
+
51
+ def skip_message
52
+ %(
53
+ No User Access Brands request was made in the previous test, and no User Access Brands Bundle was provided as
54
+ input instead. Either provide a User Access Brands Publication URL to retrieve the Bundle via a HTTP GET
55
+ request, or provide the Bundle as an input.
56
+ )
57
+ end
58
+
59
+ run do
60
+ bundle_response = if user_access_brands_bundle.blank?
61
+ load_tagged_requests('smart_access_brands_bundle')
62
+ skip skip_message if requests.length != 1
63
+ requests.first.response_body
64
+ else
65
+ user_access_brands_bundle
66
+ end
67
+
68
+ skip_if bundle_response.blank?, 'No SMART Access Brands Bundle contained in the response'
69
+
70
+ assert_valid_json(bundle_response)
71
+ bundle_resource = FHIR.from_contents(bundle_response)
72
+
73
+ skip_if bundle_resource.entry.empty?, 'The given Bundle does not contain any resources'
74
+ assert_valid_bundle_entries(bundle: bundle_resource,
75
+ resource_types: {
76
+ Organization: 'http://hl7.org/fhir/smart-app-launch/StructureDefinition/user-access-brand'
77
+ })
78
+
79
+ organization_resources = bundle_resource
80
+ .entry
81
+ .map(&:resource)
82
+ .select { |resource| resource.resourceType == 'Organization' }
83
+
84
+ organization_resources.each do |organization|
85
+ endpoint_references = organization.endpoint.map(&:reference)
86
+
87
+ if organization.extension.present?
88
+ portal_extension = find_extension(organization.extension, '/organization-portal')
89
+ if portal_extension.present?
90
+ portal_endpoints = find_all_extensions(portal_extension.extension, 'portalEndpoint')
91
+ check_portal_endpoints(portal_endpoints, endpoint_references)
92
+ end
93
+ end
94
+
95
+ endpoint_references.each do |endpoint_id_ref|
96
+ organization_referenced_endpts = find_referenced_endpoint(bundle_resource, endpoint_id_ref)
97
+ assert !organization_referenced_endpts.empty?,
98
+ "Organization with id: #{organization.id} references an Endpoint that is not contained in this
99
+ bundle."
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,45 @@
1
+ module SMARTAppLaunch
2
+ class SMARTAccessBrandsValidateBundle < Inferno::Test
3
+ id :smart_access_brands_valid_bundle
4
+ title 'Server returns valid Bundle resource according to the User Access Brands Bundle Profile'
5
+ description %(
6
+ Verify that the returned Bundle is a valid User Access Brands Bundle according to the
7
+ [User Access Brand Bundle Profile](https://hl7.org/fhir/smart-app-launch/STU2.2/StructureDefinition-user-access-brands-bundle.html).
8
+
9
+ This test also ensures the Bundle is the 'collection' type and that it is not empty.
10
+ )
11
+
12
+ input :user_access_brands_bundle,
13
+ optional: true
14
+
15
+ def skip_message
16
+ %(
17
+ No User Access Brands request was made in the previous test, and no User Access Brands Bundle was provided as
18
+ input instead. Either provide a User Access Brands Publication URL to retrieve the Bundle via a HTTP GET
19
+ request, or provide the Bundle as an input.
20
+ )
21
+ end
22
+
23
+ run do
24
+ bundle_response = if user_access_brands_bundle.blank?
25
+ load_tagged_requests('smart_access_brands_bundle')
26
+ skip skip_message if requests.length != 1
27
+ requests.first.response_body
28
+ else
29
+ user_access_brands_bundle
30
+ end
31
+
32
+ skip_if bundle_response.blank?, 'No SMART Access Brands Bundle contained in the response'
33
+
34
+ assert_valid_json(bundle_response)
35
+ bundle_resource = FHIR.from_contents(bundle_response)
36
+ assert_resource_type(:bundle, resource: bundle_resource)
37
+ assert_valid_resource(resource: bundle_resource, profile_url: 'http://hl7.org/fhir/smart-app-launch/StructureDefinition/user-access-brands-bundle')
38
+
39
+ assert(bundle_resource.type == 'collection', 'The SMART Access Brands Bundle must be type `collection`')
40
+ assert(bundle_resource.timestamp.present?,
41
+ 'Bundle.timestamp must be populated to advertise the timestamp of the last change to the contents')
42
+ assert !bundle_resource.entry.empty?, 'The given Bundle does not contain any brands or endpoints.'
43
+ end
44
+ end
45
+ end