From 5b4143c1743d30394776ed7c8dfa49108a8f48d1 Mon Sep 17 00:00:00 2001 From: Elsa Date: Wed, 25 Sep 2024 11:22:01 -0400 Subject: [PATCH 01/10] Upgrade inferno template --- .env | 2 - .env.development | 3 +- .env.production | 2 + .env.test | 2 +- .ruby-version | 2 +- .tool-versions | 2 +- Dockerfile | 2 +- Gemfile | 4 + Gemfile.lock | 313 ++++++++++++-------- Procfile | 2 + README.md | 30 +- config/nginx.background.conf | 102 +++++++ config/nginx.conf | 16 + docker-compose.background.yml | 41 +++ docker-compose.yml | 48 ++- inferno_template.gemspec | 18 +- lib/inferno_template.rb | 27 +- lib/inferno_template/igs/.keep | 0 lib/inferno_template/igs/README.md | 21 ++ lib/inferno_template/patient_group.rb | 6 +- run.sh | 4 +- setup.sh | 6 +- spec/inferno_template/patient_group_spec.rb | 35 ++- 23 files changed, 493 insertions(+), 195 deletions(-) create mode 100644 .env.production create mode 100644 Procfile create mode 100644 config/nginx.background.conf create mode 100644 docker-compose.background.yml create mode 100644 lib/inferno_template/igs/.keep create mode 100644 lib/inferno_template/igs/README.md diff --git a/.env b/.env index 8e29e83..d3cc9c6 100644 --- a/.env +++ b/.env @@ -1,3 +1 @@ JS_HOST="" -VALIDATOR_URL=http://validator_service:4567 -REDIS_URL=redis://redis:6379/0 diff --git a/.env.development b/.env.development index 994744e..e8690f6 100644 --- a/.env.development +++ b/.env.development @@ -1 +1,2 @@ -VALIDATOR_URL=http://validator_service:4567 \ No newline at end of file +FHIR_RESOURCE_VALIDATOR_URL=http://localhost/hl7validatorapi +REDIS_URL=redis://localhost:6379/0 \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..719b168 --- /dev/null +++ b/.env.production @@ -0,0 +1,2 @@ +REDIS_URL=redis://redis:6379/0 +FHIR_RESOURCE_VALIDATOR_URL=http://hl7_validator_service:3500 \ No newline at end of file diff --git a/.env.test b/.env.test index 9e95769..1545bfc 100644 --- a/.env.test +++ b/.env.test @@ -1,2 +1,2 @@ -VALIDATOR_URL=https://example.com/validatorapi +FHIR_RESOURCE_VALIDATOR_URL=https://example.com/validatorapi ASYNC_JOBS=false diff --git a/.ruby-version b/.ruby-version index e2bdf6e..6ebad14 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.3 \ No newline at end of file +3.1.2 \ No newline at end of file diff --git a/.tool-versions b/.tool-versions index fde9f5b..b8ab7ea 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 2.7.3 \ No newline at end of file +ruby 3.1.2 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 9eb5ec7..d32710c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.7.3 +FROM ruby:3.1.2 ENV INSTALL_PATH=/opt/inferno/ ENV APP_ENV=production diff --git a/Gemfile b/Gemfile index be173b2..382378e 100644 --- a/Gemfile +++ b/Gemfile @@ -3,3 +3,7 @@ source "https://rubygems.org" gemspec + +group :development, :test do + gem 'debug' +end diff --git a/Gemfile.lock b/Gemfile.lock index 75ee7b2..6802f3a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,74 +2,65 @@ PATH remote: . specs: inferno_template (0.0.1) - inferno_core (~> 0.3.0) + inferno_core (~> 0.4.38) GEM remote: https://rubygems.org/ specs: - activesupport (6.1.6) + activesupport (6.1.7.8) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + base62-rb (0.3.1) + base64 (0.2.0) bcp47 (0.3.3) i18n + bigdecimal (3.1.8) blueprinter (0.25.2) byebug (11.1.3) coderay (1.1.3) - concurrent-ruby (1.1.10) - connection_pool (2.2.5) - crack (0.4.5) + concurrent-ruby (1.3.1) + connection_pool (2.4.1) + crack (1.0.0) + bigdecimal rexml database_cleaner (1.99.0) database_cleaner-sequel (1.99.0) database_cleaner (~> 1.99.0) sequel date_time_precision (0.8.1) - diff-lcs (1.5.0) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) - dotenv (2.7.6) - dry-auto_inject (0.9.0) - dry-container (>= 0.3.4) - dry-configurable (0.12.0) + debug (1.9.2) + irb (~> 1.10) + reline (>= 0.3.8) + diff-lcs (1.5.1) + domain_name (0.6.20240107) + dotenv (2.8.1) + dry-auto_inject (1.0.1) + dry-core (~> 1.0) + zeitwerk (~> 2.6) + dry-configurable (1.0.0) + dry-core (~> 1.0, < 2) + zeitwerk (~> 2.6) + dry-container (0.10.0) concurrent-ruby (~> 1.0) - dry-core (~> 0.5, >= 0.5.0) - dry-container (0.8.0) + dry-core (1.0.0) concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (0.7.1) - concurrent-ruby (~> 1.0) - dry-equalizer (0.3.0) - dry-inflector (0.2.1) - dry-logic (1.2.0) - concurrent-ruby (~> 1.0) - dry-core (~> 0.5, >= 0.5) - dry-struct (1.4.0) - dry-core (~> 0.5, >= 0.5) - dry-types (~> 1.5) - ice_nine (~> 0.11) - dry-system (0.18.1) - concurrent-ruby (~> 1.0) - dry-auto_inject (>= 0.4.0) - dry-configurable (~> 0.11, >= 0.11.1) - dry-container (~> 0.7, >= 0.7.2) - dry-core (~> 0.3, >= 0.3.1) - dry-equalizer (~> 0.2) - dry-inflector (~> 0.1, >= 0.1.2) - dry-struct (~> 1.0) - dry-types (1.5.1) - concurrent-ruby (~> 1.0) - dry-container (~> 0.3) - dry-core (~> 0.5, >= 0.5) - dry-inflector (~> 0.1, >= 0.1.2) - dry-logic (~> 1.0, >= 1.0.2) - factory_bot (6.2.0) + zeitwerk (~> 2.6) + dry-inflector (1.0.0) + dry-system (1.0.0) + dry-auto_inject (~> 1.0.0.rc1, < 2) + dry-configurable (~> 1.0, < 2) + dry-core (~> 1.0, < 2) + dry-inflector (~> 1.0, < 2) + dry-transformer (1.0.1) + zeitwerk (~> 2.6) + factory_bot (6.4.6) activesupport (>= 5.0.0) - faraday (1.10.0) + faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -85,13 +76,15 @@ GEM faraday-em_synchrony (1.0.0) faraday-excon (1.1.0) faraday-httpclient (1.0.1) - faraday-multipart (1.0.3) - multipart-post (>= 1.2, < 3) + faraday-multipart (1.0.4) + multipart-post (~> 2) faraday-net_http (1.0.1) faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) faraday-rack (1.0.0) faraday-retry (1.0.3) + faraday_middleware (1.2.0) + faraday (~> 1.0) fhir_client (5.0.3) activesupport (>= 3) addressable (>= 2.3) @@ -103,149 +96,217 @@ GEM rack (>= 1.5) rest-client (~> 2.0) tilt (>= 1.1) - fhir_dstu2_models (1.1.1) + fhir_dstu2_models (1.2.0) bcp47 (>= 0.3) date_time_precision (>= 0.8) mime-types (>= 3.0) nokogiri (>= 1.11.4) - fhir_models (4.2.1) + fhir_models (4.3.0) bcp47 (>= 0.3) date_time_precision (>= 0.8) mime-types (>= 3.0) nokogiri (>= 1.11.4) - fhir_stu3_models (3.1.1) + fhir_stu3_models (3.2.0) bcp47 (>= 0.3) date_time_precision (>= 0.8) mime-types (>= 3.0) nokogiri (>= 1.11.4) - hanami-controller (1.3.3) - hanami-utils (~> 1.3) + hanami-controller (2.0.0) + dry-configurable (~> 1.0, < 2) + dry-core (~> 1.0) + hanami-utils (~> 2.0) rack (~> 2.0) - hanami-router (1.3.2) - hanami-utils (~> 1.3) - http_router (= 0.11.2) + zeitwerk (~> 2.6) + hanami-router (2.0.0) + mustermann (~> 1.0) + mustermann-contrib (~> 1.0) rack (~> 2.0) - hanami-utils (1.3.8) + hanami-utils (2.1.0) concurrent-ruby (~> 1.0) - transproc (~> 1.0) - hashdiff (1.0.1) + dry-core (~> 1.0, < 2) + dry-transformer (~> 1.0, < 2) + hansi (0.2.1) + hashdiff (1.1.0) http-accept (1.7.0) - http-cookie (1.0.5) + http-cookie (1.0.6) domain_name (~> 0.5) - http_router (0.11.2) - rack (>= 1.0.0) - url_mount (~> 0.2.1) - i18n (1.10.0) + i18n (1.14.5) concurrent-ruby (~> 1.0) - ice_nine (0.11.2) - inferno_core (0.3.3) - activesupport (~> 6.1) + inferno_core (0.4.38) + activesupport (~> 6.1.7.5) + base62-rb (= 0.3.1) blueprinter (= 0.25.2) dotenv (~> 2.7) - dry-configurable (= 0.12.0) - dry-system (= 0.18.1) + dry-configurable (= 1.0.0) + dry-container (= 0.10.0) + dry-core (= 1.0.0) + dry-inflector (= 1.0.0) + dry-system (= 1.0.0) faraday (~> 1.2) + faraday_middleware (~> 1.2) fhir_client (>= 5.0.3) - fhir_models (~> 4.2.0) - hanami-controller (~> 1.3) - hanami-router (~> 1.3) + fhir_models (>= 4.2.2) + hanami-controller (= 2.0.0) + hanami-router (= 2.0.0) oj (= 3.11.0) pry pry-byebug - puma (~> 5.3) + puma (~> 5.6.7) rake (~> 13.0) sequel (~> 5.42.0) - sidekiq (~> 6.4.0) + sidekiq (~> 7.2.4) sqlite3 (~> 1.4) - thor (~> 1.1.0) - jwt (2.3.0) - method_source (1.0.0) - mime-types (3.4.1) + thor (~> 1.2.1) + tty-markdown (~> 0.7.1) + io-console (0.7.2) + irb (1.13.1) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + jwt (2.8.1) + base64 + kramdown (2.4.0) + rexml + method_source (1.1.0) + mime-types (3.5.2) mime-types-data (~> 3.2015) - mime-types-data (3.2022.0105) - minitest (5.15.0) + mime-types-data (3.2024.0507) + mini_portile2 (2.8.7) + minitest (5.23.1) multi_json (1.15.0) - multi_xml (0.6.0) - multipart-post (2.1.1) + multi_xml (0.7.1) + bigdecimal (~> 3.1) + multipart-post (2.4.1) + mustermann (1.1.2) + ruby2_keywords (~> 0.0.1) + mustermann-contrib (1.1.2) + hansi (~> 0.2.0) + mustermann (= 1.1.2) netrc (0.11.0) - nio4r (2.5.8) - nokogiri (1.13.6-x86_64-darwin) + nio4r (2.7.3) + nokogiri (1.16.5) + mini_portile2 (~> 2.8.2) + racc (~> 1.4) + nokogiri (1.16.5-aarch64-linux) racc (~> 1.4) - nokogiri (1.13.6-x86_64-linux) + nokogiri (1.16.5-arm-linux) racc (~> 1.4) - oauth2 (1.4.9) + nokogiri (1.16.5-arm64-darwin) + racc (~> 1.4) + nokogiri (1.16.5-x86-linux) + racc (~> 1.4) + nokogiri (1.16.5-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.16.5-x86_64-linux) + racc (~> 1.4) + oauth2 (1.4.11) faraday (>= 0.17.3, < 3.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) - rack (>= 1.2, < 3) + rack (>= 1.2, < 4) oj (3.11.0) - pry (0.14.1) + pastel (0.8.0) + tty-color (~> 0.5) + pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) - pry-byebug (3.8.0) + pry-byebug (3.10.1) byebug (~> 11.0) - pry (~> 0.10) - public_suffix (4.0.7) - puma (5.6.4) + pry (>= 0.13, < 0.15) + psych (5.1.2) + stringio + public_suffix (5.0.5) + puma (5.6.8) nio4r (~> 2.0) - racc (1.6.0) - rack (2.2.3) - rake (13.0.6) - redis (4.6.0) + racc (1.8.0) + rack (2.2.9) + rake (13.2.1) + rdoc (6.7.0) + psych (>= 4.0.0) + redis-client (0.22.2) + connection_pool + reline (0.5.8) + io-console (~> 0.5) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rexml (3.2.5) - rspec (3.11.0) - rspec-core (~> 3.11.0) - rspec-expectations (~> 3.11.0) - rspec-mocks (~> 3.11.0) - rspec-core (3.11.0) - rspec-support (~> 3.11.0) - rspec-expectations (3.11.0) + rexml (3.2.8) + strscan (>= 3.0.9) + rouge (4.2.1) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-mocks (3.11.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-support (3.11.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) ruby2_keywords (0.0.5) sequel (5.42.0) - sidekiq (6.4.2) - connection_pool (>= 2.2.2) - rack (~> 2.0) - redis (>= 4.2.0) - sqlite3 (1.4.2) - thor (1.1.0) - tilt (2.0.10) - transproc (1.1.1) - tzinfo (2.0.4) + sidekiq (7.2.4) + concurrent-ruby (< 2) + connection_pool (>= 2.3.0) + rack (>= 2.2.4) + redis-client (>= 0.19.0) + sqlite3 (1.7.3) + mini_portile2 (~> 2.8.0) + sqlite3 (1.7.3-aarch64-linux) + sqlite3 (1.7.3-arm-linux) + sqlite3 (1.7.3-arm64-darwin) + sqlite3 (1.7.3-x86-linux) + sqlite3 (1.7.3-x86_64-darwin) + sqlite3 (1.7.3-x86_64-linux) + stringio (3.1.0) + strings (0.2.1) + strings-ansi (~> 0.2) + unicode-display_width (>= 1.5, < 3.0) + unicode_utils (~> 1.4) + strings-ansi (0.2.0) + strscan (3.1.0) + thor (1.2.2) + tilt (2.3.0) + tty-color (0.6.0) + tty-markdown (0.7.2) + kramdown (>= 1.16.2, < 3.0) + pastel (~> 0.8) + rouge (>= 3.14, < 5.0) + strings (~> 0.2.0) + tty-color (~> 0.5) + tty-screen (~> 0.8) + tty-screen (0.8.2) + tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.8.1) - url_mount (0.2.1) - rack - webmock (3.14.0) + unicode-display_width (2.5.0) + unicode_utils (1.4.0) + webmock (3.23.1) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - zeitwerk (2.5.4) + zeitwerk (2.6.15) PLATFORMS - x86_64-darwin-19 - x86_64-darwin-20 + aarch64-linux + arm-linux + arm64-darwin + ruby + x86-linux + x86_64-darwin x86_64-linux DEPENDENCIES database_cleaner-sequel (~> 1.8) + debug factory_bot (~> 6.1) inferno_template! rspec (~> 3.10) webmock (~> 3.11) BUNDLED WITH - 2.3.14 + 2.5.11 diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..4f784b9 --- /dev/null +++ b/Procfile @@ -0,0 +1,2 @@ +web: bundle exec puma +worker: bundle exec sidekiq -r ./worker.rb diff --git a/README.md b/README.md index c3f6d26..f6320b2 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,26 @@ -# Inferno Test Writing Tutorial +# Inferno Template Test Kit -This repository provides a step-by-step tutorial for users interested in writing -FHIR tests using the [Inferno Framework](https://inferno-framework.github.io/inferno-core/). +Inferno template [Inferno](https://github.com/inferno-community/inferno-core) Test Kit +for FHIR testing. -To get started, visit the [Tutorial Wiki](https://github.com/inferno-training/inferno-tutorial/wiki). +## Instructions for Developing Your Test Kit -This test kit was generated from the -[Inferno Test Kit Template](https://github.com/inferno-framework/inferno-template). +Refer to the Inferno documentation for information about [setting up +your development environment and running your Test Kit](https://inferno-framework.github.io/docs/getting-started/). + +More information about what is included in this repository can be [found here](https://inferno-framework.github.io/docs/getting-started/repo-layout-and-organization.html). + +## Documentation +- [Inferno documentation](https://inferno-framework.github.io/docs/) +- [Ruby API documentation](https://inferno-framework.github.io/inferno-core/docs/) +- [JSON API documentation](https://inferno-framework.github.io/inferno-core/api-docs/) + +## Example Inferno Test Kits + +A list of all Test Kits registered with the Inferno Team can be found on the [Test Kit Registry](https://inferno-framework.github.io/community/test-kits.html) page. ## License -Copyright 2022 The MITRE Corporation +Copyright 2024 TODO Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the @@ -21,3 +32,8 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +## Trademark Notice + +HL7, FHIR and the FHIR [FLAME DESIGN] are the registered trademarks of Health +Level Seven International and their use does not constitute endorsement by HL7. diff --git a/config/nginx.background.conf b/config/nginx.background.conf new file mode 100644 index 0000000..885866b --- /dev/null +++ b/config/nginx.background.conf @@ -0,0 +1,102 @@ +# this sets the user nginx will run as, +#and the number of worker processes +user nobody nogroup; +worker_processes 2; +#user www-data; +#worker_processes auto; + +# setup where nginx will log errors to +# and where the nginx process id resides +error_log /var/log/nginx/error.log; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + # set to on if you have more than 1 worker_processes + accept_mutex on; +} + +http { + include /etc/nginx/mime.types; + + default_type application/octet-stream; + access_log /tmp/nginx.access.log combined; + + # use the kernel sendfile + # sendfile on; # this causes over-caching because modified timestamps lost in VM + # prepend http headers before sendfile() + tcp_nopush on; + + keepalive_timeout 600; + tcp_nodelay on; + + gzip on; + gzip_vary on; + gzip_min_length 500; + + gzip_disable "MSIE [1-6]\.(?!.*SV1)"; + gzip_types text/plain text/xml text/css + text/comma-separated-values + text/javascript application/x-javascript + application/atom+xml image/x-icon; + + # configure the virtual host + server { + # replace with your domain name + # server_name inferno-server; + + # port to listen for requests on + listen 80; + + # maximum accepted body size of client request + client_max_body_size 4G; + # the server will close connections after this time + keepalive_timeout 600; + + location /validator { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Port $server_port; + proxy_redirect off; + proxy_set_header Connection ''; + proxy_http_version 1.1; + chunked_transfer_encoding off; + proxy_buffering off; + proxy_cache off; + + proxy_pass http://fhir_validator_app; + } + + location /validatorapi/ { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Port $server_port; + proxy_redirect off; + proxy_set_header Connection ''; + proxy_http_version 1.1; + chunked_transfer_encoding off; + proxy_buffering off; + proxy_cache off; + + proxy_pass http://validator_service:4567/; + } + + location /hl7validatorapi/ { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Port $server_port; + proxy_redirect off; + proxy_set_header Connection ''; + proxy_http_version 1.1; + chunked_transfer_encoding off; + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 600s; + + proxy_pass http://hl7_validator_service:3500/; + } + } +} diff --git a/config/nginx.conf b/config/nginx.conf index af4b461..a0d6000 100644 --- a/config/nginx.conf +++ b/config/nginx.conf @@ -97,5 +97,21 @@ http { proxy_pass http://validator_service:4567/; } + + location /hl7validatorapi/ { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Port $server_port; + proxy_redirect off; + proxy_set_header Connection ''; + proxy_http_version 1.1; + chunked_transfer_encoding off; + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 600s; + + proxy_pass http://hl7_validator_service:3500/; + } } } diff --git a/docker-compose.background.yml b/docker-compose.background.yml new file mode 100644 index 0000000..3d3591e --- /dev/null +++ b/docker-compose.background.yml @@ -0,0 +1,41 @@ +version: '3' +services: + hl7_validator_service: + image: infernocommunity/inferno-resource-validator + environment: + # Defines how long validator sessions last if unused, in minutes: + # Negative values mean sessions never expire, 0 means sessions immediately expire + SESSION_CACHE_DURATION: -1 + volumes: + - ./lib/inferno_template/igs:/app/igs + # To let the service share your local FHIR package cache, + # uncomment the below line + # - ~/.fhir:/home/ktor/.fhir + validator_service: + image: infernocommunity/fhir-validator-service + # Update this path to match your directory structure + volumes: + - ./lib/inferno_template/igs:/home/igs + fhir_validator_app: + image: infernocommunity/fhir-validator-app + depends_on: + - validator_service + environment: + EXTERNAL_VALIDATOR_URL: http://localhost/validatorapi + VALIDATOR_BASE_PATH: /validator + nginx: + image: nginx + volumes: + - ./config/nginx.background.conf:/etc/nginx/nginx.conf + ports: + - "80:80" + command: [nginx, '-g', 'daemon off;'] + depends_on: + - fhir_validator_app + redis: + image: redis + ports: + - "6379:6379" + volumes: + - ./data/redis:/data + command: redis-server --appendonly yes diff --git a/docker-compose.yml b/docker-compose.yml index 8d25543..eaa6736 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,32 +7,6 @@ services: - ./data:/opt/inferno/data depends_on: - validator_service - validator_service: - image: infernocommunity/fhir-validator-service - # Update this path to match your directory structure - volumes: - - ./lib/inferno_template/igs:/home/igs - fhir_validator_app: - image: infernocommunity/fhir-validator-app - depends_on: - - validator_service - environment: - EXTERNAL_VALIDATOR_URL: http://localhost/validatorapi - VALIDATOR_BASE_PATH: /validator - nginx: - image: nginx - volumes: - - ./config/nginx.conf:/etc/nginx/nginx.conf - ports: - - "80:80" - command: [nginx, '-g', 'daemon off;'] - depends_on: - - fhir_validator_app - redis: - image: redis - volumes: - - ./data/redis:/data - command: redis-server --appendonly yes worker: build: context: ./ @@ -41,3 +15,25 @@ services: command: bundle exec sidekiq -r ./worker.rb depends_on: - redis + hl7_validator_service: + extends: + file: docker-compose.background.yml + service: hl7_validator_service + validator_service: + extends: + file: docker-compose.background.yml + service: validator_service + fhir_validator_app: + extends: + file: docker-compose.background.yml + service: fhir_validator_app + nginx: + extends: + file: docker-compose.background.yml + service: nginx + volumes: + - ./config/nginx.conf:/etc/nginx/nginx.conf + redis: + extends: + file: docker-compose.background.yml + service: redis diff --git a/inferno_template.gemspec b/inferno_template.gemspec index 71df468..1791090 100644 --- a/inferno_template.gemspec +++ b/inferno_template.gemspec @@ -1,21 +1,21 @@ Gem::Specification.new do |spec| spec.name = 'inferno_template' spec.version = '0.0.1' - spec.authors = ['Inferno Team'] - spec.email = ['inferno@groups.mitre.org'] + spec.authors = ["Inferno Template"] + # spec.email = ['TODO'] spec.date = Time.now.utc.strftime('%Y-%m-%d') - spec.summary = 'Inferno Test Kit Template' - spec.description = 'Inferno Test Kit Template' - spec.homepage = 'https://github.com/inferno-framework/inferno-template' + spec.summary = 'Inferno Template Test Kit' + spec.description = 'Inferno template Inferno test kit for FHIR' + # spec.homepage = 'TODO' spec.license = 'Apache-2.0' - spec.add_runtime_dependency 'inferno_core', '~> 0.3.0' + spec.add_runtime_dependency 'inferno_core', '~> 0.4.38' spec.add_development_dependency 'database_cleaner-sequel', '~> 1.8' spec.add_development_dependency 'factory_bot', '~> 6.1' spec.add_development_dependency 'rspec', '~> 3.10' spec.add_development_dependency 'webmock', '~> 3.11' - spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0') - spec.metadata['homepage_uri'] = spec.homepage - spec.metadata['source_code_uri'] = 'https://github.com/inferno-framework/inferno-template' + spec.required_ruby_version = Gem::Requirement.new('>= 3.1.2') + # spec.metadata['homepage_uri'] = spec.homepage + # spec.metadata['source_code_uri'] = 'TODO' spec.files = [ Dir['lib/**/*.rb'], Dir['lib/**/*.json'], diff --git a/lib/inferno_template.rb b/lib/inferno_template.rb index 779ed92..f287809 100644 --- a/lib/inferno_template.rb +++ b/lib/inferno_template.rb @@ -2,16 +2,33 @@ module InfernoTemplate class Suite < Inferno::TestSuite - id :test_suite_template - title 'Inferno Test Suite Template' - description 'A basic test suite template for Inferno' + id :inferno_template_test_suite + title 'Inferno Template Test Suite' + description 'Inferno template test suite.' - # This input will be available to all tests in this suite - input :url + # These inputs will be available to all tests in this suite + input :url, + title: 'FHIR Server Base Url' + + input :credentials, + title: 'OAuth Credentials', + type: :oauth_credentials, + optional: true # All FHIR requests in this suite will use this FHIR client fhir_client do url :url + oauth_credentials :credentials + end + + # All FHIR validation requsets will use this FHIR validator + fhir_resource_validator do + # igs 'identifier#version' # Use this method for published IGs/versions + # igs 'igs/filename.tgz' # Use this otherwise + + exclude_message do |message| + message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/) + end end # Tests and TestGroups can be defined inline diff --git a/lib/inferno_template/igs/.keep b/lib/inferno_template/igs/.keep new file mode 100644 index 0000000..e69de29 diff --git a/lib/inferno_template/igs/README.md b/lib/inferno_template/igs/README.md new file mode 100644 index 0000000..7ed8b27 --- /dev/null +++ b/lib/inferno_template/igs/README.md @@ -0,0 +1,21 @@ +# Note on this IGs folder + +There are three reasons why it would be necessary to put an IG package.tgz in this folder. If none of these apply, you do not need to put any files here, or can consider removing any existing files to make it clear they are unused. + +## 1. Generated Test Suites +Some test kits use a "generator" to automatically generate the contents of a test suite for an IG. The IG files are required every time the test suites need to be regenerated. Examples of test kits that use this approach are the US Core Test Kit and CARIN IG for Blue ButtonĀ® Test Kit. + + +## 2. Non-published IG +If your IG, or the specific version of the IG you want to test against, is not published, then the validator service needs to load the IG from file in order to be able to validate resources with it. The IG must be referenced in the `fhir_resource_validator` block in the test suite definition by filename, ie: + +```ruby + fhir_resource_validator do + igs 'igs/filename.tgz' + + ... + end +``` + +## 3. Inferno Validator UI +The Inferno Validator UI is configured to auto-load any IGs present in the igs folder and include them in all validations. In general, the Inferno team is currently leaving IGs in this folder even if not otherwise necessary to make it easy to re-enable the validator UI. \ No newline at end of file diff --git a/lib/inferno_template/patient_group.rb b/lib/inferno_template/patient_group.rb index 6a975da..6efbf4d 100644 --- a/lib/inferno_template/patient_group.rb +++ b/lib/inferno_template/patient_group.rb @@ -1,6 +1,6 @@ module InfernoTemplate class PatientGroup < Inferno::TestGroup - title 'Patient Tests' + title 'Patient Tests' description 'Verify that the server makes Patient resources available' id :patient_group @@ -10,7 +10,9 @@ class PatientGroup < Inferno::TestGroup Verify that Patient resources can be read from the server. ) - input :patient_id + input :patient_id, + title: 'Patient ID' + # Named requests can be used by other tests makes_request :patient diff --git a/run.sh b/run.sh index 9430385..fde0a7e 100755 --- a/run.sh +++ b/run.sh @@ -1,3 +1,3 @@ #!/bin/sh -docker-compose build -docker-compose up +docker compose build +docker compose up diff --git a/setup.sh b/setup.sh index 2e99e25..6089f58 100755 --- a/setup.sh +++ b/setup.sh @@ -1,4 +1,4 @@ #!/bin/sh -docker-compose pull -docker-compose build -docker-compose run inferno bundle exec inferno migrate +docker compose pull +docker compose build +docker compose run inferno bundle exec inferno migrate diff --git a/spec/inferno_template/patient_group_spec.rb b/spec/inferno_template/patient_group_spec.rb index 63c694c..1cbacbd 100644 --- a/spec/inferno_template/patient_group_spec.rb +++ b/spec/inferno_template/patient_group_spec.rb @@ -1,10 +1,29 @@ RSpec.describe InfernoTemplate::PatientGroup do - let(:suite) { Inferno::Repositories::TestSuites.new.find('test_suite_template') } + let(:suite) { Inferno::Repositories::TestSuites.new.find('inferno_template_test_suite') } let(:group) { suite.groups[1] } let(:session_data_repo) { Inferno::Repositories::SessionData.new } - let(:test_session) { repo_create(:test_session, test_suite_id: 'test_suite_template') } + let(:test_session) { repo_create(:test_session, test_suite_id: 'inferno_template_test_suite') } let(:url) { 'http://example.com/fhir' } - let(:error_outcome) { FHIR::OperationOutcome.new(issue: [{ severity: 'error' }]) } + let(:success_outcome) do + { + outcomes: [{ + issues: [] + }], + sessionId: '' + } + end + let(:error_outcome) do + { + outcomes: [{ + issues: [{ + location: 'Patient.identifier[0]', + message: 'Identifier.system must be an absolute reference, not a local reference', + level: 'ERROR' + }] + }], + sessionId: '' + } + end def run(runnable, inputs = {}) test_run_params = { test_session_id: test_session.id }.merge(runnable.reference_hash) @@ -67,9 +86,9 @@ def run(runnable, inputs = {}) let(:test) { group.tests.last } it 'passes if the resource is valid' do - stub_request(:post, "#{ENV.fetch('VALIDATOR_URL')}/validate") + stub_request(:post, "#{ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')}/validate") .with(query: hash_including({})) - .to_return(status: 200, body: FHIR::OperationOutcome.new.to_json) + .to_return(status: 200, body: success_outcome.to_json) resource = FHIR::Patient.new repo_create( @@ -79,13 +98,13 @@ def run(runnable, inputs = {}) response_body: resource.to_json ) - result = run(test) + result = run(test, url: url) expect(result.result).to eq('pass') end it 'fails if the resource is not valid' do - stub_request(:post, "#{ENV.fetch('VALIDATOR_URL')}/validate") + stub_request(:post, "#{ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')}/validate") .with(query: hash_including({})) .to_return(status: 200, body: error_outcome.to_json) @@ -97,7 +116,7 @@ def run(runnable, inputs = {}) response_body: resource.to_json ) - result = run(test) + result = run(test, url: url) expect(result.result).to eq('fail') end From 07bf9c5278429e61ec029e52a3f31ba115526d77 Mon Sep 17 00:00:00 2001 From: Elsa Date: Mon, 7 Oct 2024 11:47:36 -0400 Subject: [PATCH 02/10] Removed TODOs, commented out unnecessary things --- .env.test | 2 +- config/nginx.background.conf | 59 +++++++++++++++++------------------ config/nginx.conf | 59 +++++++++++++++++------------------ docker-compose.background.yml | 31 +++++++++--------- docker-compose.yml | 21 +++++++------ inferno_template.gemspec | 4 --- 6 files changed, 86 insertions(+), 90 deletions(-) diff --git a/.env.test b/.env.test index 1545bfc..325d504 100644 --- a/.env.test +++ b/.env.test @@ -1,2 +1,2 @@ -FHIR_RESOURCE_VALIDATOR_URL=https://example.com/validatorapi +FHIR_RESOURCE_VALIDATOR_URL=https://example.com/hl7validatorapi ASYNC_JOBS=false diff --git a/config/nginx.background.conf b/config/nginx.background.conf index 885866b..7b31f62 100644 --- a/config/nginx.background.conf +++ b/config/nginx.background.conf @@ -53,36 +53,35 @@ http { # the server will close connections after this time keepalive_timeout 600; - location /validator { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Port $server_port; - proxy_redirect off; - proxy_set_header Connection ''; - proxy_http_version 1.1; - chunked_transfer_encoding off; - proxy_buffering off; - proxy_cache off; - - proxy_pass http://fhir_validator_app; - } - - location /validatorapi/ { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Port $server_port; - proxy_redirect off; - proxy_set_header Connection ''; - proxy_http_version 1.1; - chunked_transfer_encoding off; - proxy_buffering off; - proxy_cache off; - - proxy_pass http://validator_service:4567/; - } - + # location /validator { + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # proxy_set_header Host $http_host; + # proxy_set_header X-Forwarded-Proto $scheme; + # proxy_set_header X-Forwarded-Port $server_port; + # proxy_redirect off; + # proxy_set_header Connection ''; + # proxy_http_version 1.1; + # chunked_transfer_encoding off; + # proxy_buffering off; + # proxy_cache off; + + # proxy_pass http://fhir_validator_app; + # } + + # location /validatorapi/ { + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # proxy_set_header Host $http_host; + # proxy_set_header X-Forwarded-Proto $scheme; + # proxy_set_header X-Forwarded-Port $server_port; + # proxy_redirect off; + # proxy_set_header Connection ''; + # proxy_http_version 1.1; + # chunked_transfer_encoding off; + # proxy_buffering off; + # proxy_cache off; + + # proxy_pass http://validator_service:4567/; + # } location /hl7validatorapi/ { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; diff --git a/config/nginx.conf b/config/nginx.conf index a0d6000..15abd8b 100644 --- a/config/nginx.conf +++ b/config/nginx.conf @@ -68,36 +68,35 @@ http { proxy_pass http://inferno:4567; } - location /validator { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Port $server_port; - proxy_redirect off; - proxy_set_header Connection ''; - proxy_http_version 1.1; - chunked_transfer_encoding off; - proxy_buffering off; - proxy_cache off; - - proxy_pass http://fhir_validator_app; - } - - location /validatorapi/ { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Port $server_port; - proxy_redirect off; - proxy_set_header Connection ''; - proxy_http_version 1.1; - chunked_transfer_encoding off; - proxy_buffering off; - proxy_cache off; - - proxy_pass http://validator_service:4567/; - } - + # location /validator { + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # proxy_set_header Host $http_host; + # proxy_set_header X-Forwarded-Proto $scheme; + # proxy_set_header X-Forwarded-Port $server_port; + # proxy_redirect off; + # proxy_set_header Connection ''; + # proxy_http_version 1.1; + # chunked_transfer_encoding off; + # proxy_buffering off; + # proxy_cache off; + + # proxy_pass http://fhir_validator_app; + # } + + # location /validatorapi/ { + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # proxy_set_header Host $http_host; + # proxy_set_header X-Forwarded-Proto $scheme; + # proxy_set_header X-Forwarded-Port $server_port; + # proxy_redirect off; + # proxy_set_header Connection ''; + # proxy_http_version 1.1; + # chunked_transfer_encoding off; + # proxy_buffering off; + # proxy_cache off; + + # proxy_pass http://validator_service:4567/; + # } location /hl7validatorapi/ { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; diff --git a/docker-compose.background.yml b/docker-compose.background.yml index 3d3591e..6b090bc 100644 --- a/docker-compose.background.yml +++ b/docker-compose.background.yml @@ -1,4 +1,4 @@ -version: '3' +version: "3" services: hl7_validator_service: image: infernocommunity/inferno-resource-validator @@ -11,27 +11,28 @@ services: # To let the service share your local FHIR package cache, # uncomment the below line # - ~/.fhir:/home/ktor/.fhir - validator_service: - image: infernocommunity/fhir-validator-service - # Update this path to match your directory structure - volumes: - - ./lib/inferno_template/igs:/home/igs - fhir_validator_app: - image: infernocommunity/fhir-validator-app - depends_on: - - validator_service - environment: - EXTERNAL_VALIDATOR_URL: http://localhost/validatorapi - VALIDATOR_BASE_PATH: /validator + # validator_service: + # image: infernocommunity/fhir-validator-service + # # Update this path to match your directory structure + # volumes: + # - ./lib/inferno_template/igs:/home/igs + # fhir_validator_app: + # image: infernocommunity/fhir-validator-app + # depends_on: + # - validator_service + # environment: + # EXTERNAL_VALIDATOR_URL: http://localhost/validatorapi + # VALIDATOR_BASE_PATH: /validator nginx: image: nginx volumes: - ./config/nginx.background.conf:/etc/nginx/nginx.conf ports: - "80:80" - command: [nginx, '-g', 'daemon off;'] + command: [nginx, "-g", "daemon off;"] depends_on: - - fhir_validator_app + - hl7_validator_service + # - fhir_validator_app redis: image: redis ports: diff --git a/docker-compose.yml b/docker-compose.yml index eaa6736..9944050 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3' +version: "3" services: inferno: build: @@ -6,7 +6,8 @@ services: volumes: - ./data:/opt/inferno/data depends_on: - - validator_service + # - validator_service + - hl7_validator_service worker: build: context: ./ @@ -19,14 +20,14 @@ services: extends: file: docker-compose.background.yml service: hl7_validator_service - validator_service: - extends: - file: docker-compose.background.yml - service: validator_service - fhir_validator_app: - extends: - file: docker-compose.background.yml - service: fhir_validator_app + # validator_service: + # extends: + # file: docker-compose.background.yml + # service: validator_service + # fhir_validator_app: + # extends: + # file: docker-compose.background.yml + # service: fhir_validator_app nginx: extends: file: docker-compose.background.yml diff --git a/inferno_template.gemspec b/inferno_template.gemspec index 1791090..c4ccbba 100644 --- a/inferno_template.gemspec +++ b/inferno_template.gemspec @@ -2,11 +2,9 @@ Gem::Specification.new do |spec| spec.name = 'inferno_template' spec.version = '0.0.1' spec.authors = ["Inferno Template"] - # spec.email = ['TODO'] spec.date = Time.now.utc.strftime('%Y-%m-%d') spec.summary = 'Inferno Template Test Kit' spec.description = 'Inferno template Inferno test kit for FHIR' - # spec.homepage = 'TODO' spec.license = 'Apache-2.0' spec.add_runtime_dependency 'inferno_core', '~> 0.4.38' spec.add_development_dependency 'database_cleaner-sequel', '~> 1.8' @@ -14,8 +12,6 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'rspec', '~> 3.10' spec.add_development_dependency 'webmock', '~> 3.11' spec.required_ruby_version = Gem::Requirement.new('>= 3.1.2') - # spec.metadata['homepage_uri'] = spec.homepage - # spec.metadata['source_code_uri'] = 'TODO' spec.files = [ Dir['lib/**/*.rb'], Dir['lib/**/*.json'], From d98ac7a980266414fbb3baf22081193d9fa06f9c Mon Sep 17 00:00:00 2001 From: Elsa Date: Wed, 25 Sep 2024 11:47:59 -0400 Subject: [PATCH 03/10] Upgrade inferno template with step 1 solution --- lib/inferno_template.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/inferno_template.rb b/lib/inferno_template.rb index f287809..70ea1e6 100644 --- a/lib/inferno_template.rb +++ b/lib/inferno_template.rb @@ -10,6 +10,8 @@ class Suite < Inferno::TestSuite input :url, title: 'FHIR Server Base Url' + input :access_token + input :credentials, title: 'OAuth Credentials', type: :oauth_credentials, @@ -19,6 +21,7 @@ class Suite < Inferno::TestSuite fhir_client do url :url oauth_credentials :credentials + bearer_token :access_token end # All FHIR validation requsets will use this FHIR validator From fd3c53b45d75b218a67116a7bd754711de6993c4 Mon Sep 17 00:00:00 2001 From: Elsa Date: Wed, 25 Sep 2024 16:11:35 -0400 Subject: [PATCH 04/10] Upgrade inferno template with step 2 solution --- lib/inferno_template.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/inferno_template.rb b/lib/inferno_template.rb index 70ea1e6..e95eb72 100644 --- a/lib/inferno_template.rb +++ b/lib/inferno_template.rb @@ -57,5 +57,24 @@ class Suite < Inferno::TestSuite # Tests and TestGroups can be written in separate files and then included # using their id group from: :patient_group + + group do + id :search_tests + title 'Search Tests' + + input :patient_id + + test do + title 'Condition Search by Patient' + + run do + fhir_search('Condition', params: { patient: patient_id }) + + assert_response_status(200) + assert_resource_type('Bundle') + assert_valid_bundle_entries + end + end + end end end From 9f59b072f419c6d3e060a97a5b00dcfb17787395 Mon Sep 17 00:00:00 2001 From: Elsa Date: Wed, 25 Sep 2024 16:39:25 -0400 Subject: [PATCH 05/10] Upgrade inferno template with step 3 solution --- lib/inferno_template.rb | 8 ++++++-- lib/inferno_template/patient_group.rb | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/inferno_template.rb b/lib/inferno_template.rb index e95eb72..3832cd0 100644 --- a/lib/inferno_template.rb +++ b/lib/inferno_template.rb @@ -26,7 +26,7 @@ class Suite < Inferno::TestSuite # All FHIR validation requsets will use this FHIR validator fhir_resource_validator do - # igs 'identifier#version' # Use this method for published IGs/versions + igs 'hl7.fhir.us.core#3.1.1' # Use this method for published IGs/versions # igs 'igs/filename.tgz' # Use this otherwise exclude_message do |message| @@ -72,7 +72,11 @@ class Suite < Inferno::TestSuite assert_response_status(200) assert_resource_type('Bundle') - assert_valid_bundle_entries + assert_valid_bundle_entries( + resource_types: { + 'Condition': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition' + } + ) end end end diff --git a/lib/inferno_template/patient_group.rb b/lib/inferno_template/patient_group.rb index 6efbf4d..9ae14e1 100644 --- a/lib/inferno_template/patient_group.rb +++ b/lib/inferno_template/patient_group.rb @@ -37,7 +37,7 @@ class PatientGroup < Inferno::TestGroup run do assert_resource_type(:patient) - assert_valid_resource + assert_valid_resource(profile_url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient') end end end From 7578759ae437da8240df30d04508caf19076e4a6 Mon Sep 17 00:00:00 2001 From: Elsa Date: Wed, 25 Sep 2024 17:03:01 -0400 Subject: [PATCH 06/10] Upgrade inferno template with step 4 solution --- lib/inferno_template.rb | 48 ++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/lib/inferno_template.rb b/lib/inferno_template.rb index 3832cd0..417fc04 100644 --- a/lib/inferno_template.rb +++ b/lib/inferno_template.rb @@ -58,25 +58,47 @@ class Suite < Inferno::TestSuite # using their id group from: :patient_group + group do id :search_tests title 'Search Tests' input :patient_id - test do - title 'Condition Search by Patient' - - run do - fhir_search('Condition', params: { patient: patient_id }) - - assert_response_status(200) - assert_resource_type('Bundle') - assert_valid_bundle_entries( - resource_types: { - 'Condition': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition' - } - ) + ['AllergyIntolerance', + 'CarePlan', + 'CareTeam', + 'Condition', + 'Device', + 'DiagnosticReport', + 'DocumentReference', + 'Encounter', + 'Goal', + 'Immunization', + 'MedicationRequest', + 'Observation', + 'Procedure'].each do |tested_resource| + + test do + title "#{tested_resource} Search by Patient" + + run do + fhir_search(tested_resource, params: { patient: patient_id }) + + assert_response_status(200) + assert_resource_type('Bundle') + + # There are not profiles for Observation, DocumentReference, or Device + # in US Core v3.1.1 + pass_if ['Observation', 'DiagnosticReport', 'Device'].include?(tested_resource), + "Note: no US Core Profile for #{tested_resource} resource type" + + assert_valid_bundle_entries( + resource_types: { + "#{tested_resource}": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-#{tested_resource.downcase}" + } + ) + end end end end From 0a7a5ffce568761006acfa8e6f52473dc518ef13 Mon Sep 17 00:00:00 2001 From: Elsa Date: Thu, 26 Sep 2024 10:07:08 -0400 Subject: [PATCH 07/10] Upgrade inferno template with step 5 solution --- lib/inferno_template.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/inferno_template.rb b/lib/inferno_template.rb index 417fc04..2d3c8be 100644 --- a/lib/inferno_template.rb +++ b/lib/inferno_template.rb @@ -88,6 +88,12 @@ class Suite < Inferno::TestSuite assert_response_status(200) assert_resource_type('Bundle') + # skip_if is a shortcut to wrapping `skip` statement in an `if` block + # it is a good idea to use the safe navigation operator `&.` to avoid runtime errors on nil + skip_if resource.entry&.empty?, 'No entries in bundle response.' + + info "Bundle contains #{resource.entry&.count} resources." + # There are not profiles for Observation, DocumentReference, or Device # in US Core v3.1.1 pass_if ['Observation', 'DiagnosticReport', 'Device'].include?(tested_resource), From 428318103c42d58cc986fd766aa6fd977a069b1a Mon Sep 17 00:00:00 2001 From: Elsa Date: Thu, 26 Sep 2024 12:47:28 -0400 Subject: [PATCH 08/10] Upgrade inferno template with step 6 solution --- .env | 2 +- inferno_template.gemspec | 1 + lib/inferno_template.rb | 147 +++++++++++++++++++++------------------ 3 files changed, 83 insertions(+), 67 deletions(-) diff --git a/.env b/.env index d3cc9c6..ae90efa 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -JS_HOST="" +INFERNO_HOST=http://localhost \ No newline at end of file diff --git a/inferno_template.gemspec b/inferno_template.gemspec index c4ccbba..8e11021 100644 --- a/inferno_template.gemspec +++ b/inferno_template.gemspec @@ -7,6 +7,7 @@ Gem::Specification.new do |spec| spec.description = 'Inferno template Inferno test kit for FHIR' spec.license = 'Apache-2.0' spec.add_runtime_dependency 'inferno_core', '~> 0.4.38' + spec.add_runtime_dependency 'smart_app_launch_test_kit', '~> 0.4.3' spec.add_development_dependency 'database_cleaner-sequel', '~> 1.8' spec.add_development_dependency 'factory_bot', '~> 6.1' spec.add_development_dependency 'rspec', '~> 3.10' diff --git a/lib/inferno_template.rb b/lib/inferno_template.rb index 2d3c8be..93d0881 100644 --- a/lib/inferno_template.rb +++ b/lib/inferno_template.rb @@ -1,4 +1,5 @@ require_relative 'inferno_template/patient_group' +require 'smart_app_launch_test_kit' module InfernoTemplate class Suite < Inferno::TestSuite @@ -10,20 +11,11 @@ class Suite < Inferno::TestSuite input :url, title: 'FHIR Server Base Url' - input :access_token - input :credentials, title: 'OAuth Credentials', type: :oauth_credentials, optional: true - # All FHIR requests in this suite will use this FHIR client - fhir_client do - url :url - oauth_credentials :credentials - bearer_token :access_token - end - # All FHIR validation requsets will use this FHIR validator fhir_resource_validator do igs 'hl7.fhir.us.core#3.1.1' # Use this method for published IGs/versions @@ -34,76 +26,99 @@ class Suite < Inferno::TestSuite end end - # Tests and TestGroups can be defined inline group do - id :capability_statement - title 'Capability Statement' - description 'Verify that the server has a CapabilityStatement' - - test do - id :capability_statement_read - title 'Read CapabilityStatement' - description 'Read CapabilityStatement from /metadata endpoint' + id :auth + title 'Auth' + optional + run_as_group - run do - fhir_get_capability_statement + output :access_token, :patient_id - assert_response_status(200) - assert_resource_type(:capability_statement) - end - end + group from: :smart_discovery + group from: :smart_standalone_launch end - # Tests and TestGroups can be written in separate files and then included - # using their id - group from: :patient_group - - group do - id :search_tests - title 'Search Tests' - - input :patient_id - - ['AllergyIntolerance', - 'CarePlan', - 'CareTeam', - 'Condition', - 'Device', - 'DiagnosticReport', - 'DocumentReference', - 'Encounter', - 'Goal', - 'Immunization', - 'MedicationRequest', - 'Observation', - 'Procedure'].each do |tested_resource| + id :api + title 'API' + input :access_token + + # All FHIR requests in this suite will use this FHIR client + fhir_client do + url :url + bearer_token :access_token + end + + # Tests and TestGroups can be defined inline + group do + id :capability_statement + title 'Capability Statement' + description 'Verify that the server has a CapabilityStatement' test do - title "#{tested_resource} Search by Patient" + id :capability_statement_read + title 'Read CapabilityStatement' + description 'Read CapabilityStatement from /metadata endpoint' run do - fhir_search(tested_resource, params: { patient: patient_id }) + fhir_get_capability_statement assert_response_status(200) - assert_resource_type('Bundle') - - # skip_if is a shortcut to wrapping `skip` statement in an `if` block - # it is a good idea to use the safe navigation operator `&.` to avoid runtime errors on nil - skip_if resource.entry&.empty?, 'No entries in bundle response.' - - info "Bundle contains #{resource.entry&.count} resources." - - # There are not profiles for Observation, DocumentReference, or Device - # in US Core v3.1.1 - pass_if ['Observation', 'DiagnosticReport', 'Device'].include?(tested_resource), - "Note: no US Core Profile for #{tested_resource} resource type" + assert_resource_type(:capability_statement) + end + end + end - assert_valid_bundle_entries( - resource_types: { - "#{tested_resource}": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-#{tested_resource.downcase}" - } - ) + # Tests and TestGroups can be written in separate files and then included + # using their id + group from: :patient_group + + group do + id :search_tests + title 'Search Tests' + + input :patient_id + + ['AllergyIntolerance', + 'CarePlan', + 'CareTeam', + 'Condition', + 'Device', + 'DiagnosticReport', + 'DocumentReference', + 'Encounter', + 'Goal', + 'Immunization', + 'MedicationRequest', + 'Observation', + 'Procedure'].each do |tested_resource| + + test do + title "#{tested_resource} Search by Patient" + + run do + fhir_search(tested_resource, params: { patient: patient_id }) + + assert_response_status(200) + assert_resource_type('Bundle') + + # skip_if is a shortcut to wrapping `skip` statement in an `if` block + # it is a good idea to use the safe navigation operator `&.` to avoid runtime errors on nil + skip_if resource.entry&.empty?, 'No entries in bundle response.' + + info "Bundle contains #{resource.entry&.count} resources." + + # There are not profiles for Observation, DocumentReference, or Device + # in US Core v3.1.1 + pass_if ['Observation', 'DiagnosticReport', 'Device'].include?(tested_resource), + "Note: no US Core Profile for #{tested_resource} resource type" + + assert_valid_bundle_entries( + resource_types: { + "#{tested_resource}": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-#{tested_resource.downcase}" + } + ) + end end end end From 86c3c51caa738b9457807d97eb7d205ce96329e9 Mon Sep 17 00:00:00 2001 From: Elsa Date: Wed, 9 Oct 2024 11:31:03 -0400 Subject: [PATCH 09/10] Remove TODO --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f6320b2..6001f51 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ your development environment and running your Test Kit](https://inferno-framewor More information about what is included in this repository can be [found here](https://inferno-framework.github.io/docs/getting-started/repo-layout-and-organization.html). ## Documentation + - [Inferno documentation](https://inferno-framework.github.io/docs/) - [Ruby API documentation](https://inferno-framework.github.io/inferno-core/docs/) - [JSON API documentation](https://inferno-framework.github.io/inferno-core/api-docs/) @@ -20,14 +21,17 @@ More information about what is included in this repository can be [found here](h A list of all Test Kits registered with the Inferno Team can be found on the [Test Kit Registry](https://inferno-framework.github.io/community/test-kits.html) page. ## License -Copyright 2024 TODO + +Copyright 2024 The MITRE Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + ``` http://www.apache.org/licenses/LICENSE-2.0 ``` + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the From da714517b3f2003e67c77afa6bc065c56b5a99d3 Mon Sep 17 00:00:00 2001 From: Elsa Date: Thu, 10 Oct 2024 10:43:06 -0400 Subject: [PATCH 10/10] Add access_token to rspec tests --- Gemfile.lock | 16 ++++++++++++++++ spec/inferno_template/patient_group_spec.rb | 15 ++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6802f3a..68c6de3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,6 +3,7 @@ PATH specs: inferno_template (0.0.1) inferno_core (~> 0.4.38) + smart_app_launch_test_kit (~> 0.4.3) GEM remote: https://rubygems.org/ @@ -15,11 +16,13 @@ GEM zeitwerk (~> 2.3) addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) + aes_key_wrap (1.1.0) base62-rb (0.3.1) base64 (0.2.0) bcp47 (0.3.3) i18n bigdecimal (3.1.8) + bindata (2.5.0) blueprinter (0.25.2) byebug (11.1.3) coderay (1.1.3) @@ -130,6 +133,7 @@ GEM http-accept (1.7.0) http-cookie (1.0.6) domain_name (~> 0.5) + httpclient (2.8.3) i18n (1.14.5) concurrent-ruby (~> 1.0) inferno_core (0.4.38) @@ -162,6 +166,11 @@ GEM irb (1.13.1) rdoc (>= 4.0.0) reline (>= 0.4.2) + json-jwt (1.15.3.1) + activesupport (>= 4.2) + aes_key_wrap + bindata + httpclient jwt (2.8.1) base64 kramdown (2.4.0) @@ -255,6 +264,11 @@ GEM connection_pool (>= 2.3.0) rack (>= 2.2.4) redis-client (>= 0.19.0) + smart_app_launch_test_kit (0.4.4) + inferno_core (>= 0.4.2) + json-jwt (~> 1.15.3) + jwt (~> 2.6) + tls_test_kit (~> 0.2.0) sqlite3 (1.7.3) mini_portile2 (~> 2.8.0) sqlite3 (1.7.3-aarch64-linux) @@ -272,6 +286,8 @@ GEM strscan (3.1.0) thor (1.2.2) tilt (2.3.0) + tls_test_kit (0.2.2) + inferno_core (>= 0.4.2) tty-color (0.6.0) tty-markdown (0.7.2) kramdown (>= 1.16.2, < 3.0) diff --git a/spec/inferno_template/patient_group_spec.rb b/spec/inferno_template/patient_group_spec.rb index 1cbacbd..416669a 100644 --- a/spec/inferno_template/patient_group_spec.rb +++ b/spec/inferno_template/patient_group_spec.rb @@ -1,9 +1,10 @@ RSpec.describe InfernoTemplate::PatientGroup do let(:suite) { Inferno::Repositories::TestSuites.new.find('inferno_template_test_suite') } - let(:group) { suite.groups[1] } + let(:group) { suite.groups[1].groups[1] } let(:session_data_repo) { Inferno::Repositories::SessionData.new } let(:test_session) { repo_create(:test_session, test_suite_id: 'inferno_template_test_suite') } let(:url) { 'http://example.com/fhir' } + let(:access_token) { 'SAMPLE_TOKEN' } let(:success_outcome) do { outcomes: [{ @@ -43,7 +44,7 @@ def run(runnable, inputs = {}) stub_request(:get, "#{url}/Patient/#{patient_id}") .to_return(status: 200, body: resource.to_json) - result = run(test, url: url, patient_id: patient_id) + result = run(test, url: url, patient_id: patient_id, access_token: access_token) expect(result.result).to eq('pass') end @@ -53,7 +54,7 @@ def run(runnable, inputs = {}) stub_request(:get, "#{url}/Patient/#{patient_id}") .to_return(status: 201, body: resource.to_json) - result = run(test, url: url, patient_id: patient_id) + result = run(test, url: url, patient_id: patient_id, access_token: access_token) expect(result.result).to eq('fail') expect(result.result_message).to match(/200/) @@ -64,7 +65,7 @@ def run(runnable, inputs = {}) stub_request(:get, "#{url}/Patient/#{patient_id}") .to_return(status: 200, body: resource.to_json) - result = run(test, url: url, patient_id: patient_id) + result = run(test, url: url, patient_id: patient_id, access_token: access_token) expect(result.result).to eq('fail') expect(result.result_message).to match(/Patient/) @@ -75,7 +76,7 @@ def run(runnable, inputs = {}) stub_request(:get, "#{url}/Patient/#{patient_id}") .to_return(status: 200, body: resource.to_json) - result = run(test, url: url, patient_id: patient_id) + result = run(test, url: url, patient_id: patient_id, access_token: access_token) expect(result.result).to eq('fail') expect(result.result_message).to match(/resource with id/) @@ -98,7 +99,7 @@ def run(runnable, inputs = {}) response_body: resource.to_json ) - result = run(test, url: url) + result = run(test, url: url, access_token: access_token) expect(result.result).to eq('pass') end @@ -116,7 +117,7 @@ def run(runnable, inputs = {}) response_body: resource.to_json ) - result = run(test, url: url) + result = run(test, url: url, access_token: access_token) expect(result.result).to eq('fail') end