au_ps_inferno 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/au_ps_inferno/generator/constants.rb +61 -0
  4. data/lib/au_ps_inferno/generator/generator.rb +76 -0
  5. data/lib/au_ps_inferno/generator/generator_group_based_metadata_module.rb +113 -0
  6. data/lib/au_ps_inferno/generator/ig_resources_extractor.rb +149 -0
  7. data/lib/au_ps_inferno/generator/metadata_manager.rb +608 -0
  8. data/lib/au_ps_inferno/generator/naming.rb +52 -0
  9. data/lib/au_ps_inferno/generator/sections_validation_group_generator.rb +182 -0
  10. data/lib/au_ps_inferno/generator/test_file_generator.rb +77 -0
  11. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_bundle_instance.rb +56 -0
  12. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_bundle_must_support_conformance/suite_au_ps_bundle_instance_au_ps_bundle_must_support_conformance_bundle_must_support_populated.rb +21 -0
  13. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_bundle_must_support_conformance.rb +16 -0
  14. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_attester/suite_au_ps_bundle_instance_au_ps_composition_attester_attester_party_ms_elements.rb +21 -0
  15. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_attester/suite_au_ps_bundle_instance_au_ps_composition_attester_attester_party_ms_identifier_slices.rb +21 -0
  16. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_attester/suite_au_ps_bundle_instance_au_ps_composition_attester_attester_party_ms_subelements.rb +21 -0
  17. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_attester.rb +26 -0
  18. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_author/suite_au_ps_bundle_instance_au_ps_composition_author_author_ms_elements.rb +21 -0
  19. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_author/suite_au_ps_bundle_instance_au_ps_composition_author_author_ms_identifier_slices.rb +21 -0
  20. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_author/suite_au_ps_bundle_instance_au_ps_composition_author_author_ms_subelements.rb +21 -0
  21. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_author/suite_au_ps_bundle_instance_au_ps_composition_author_author_resource_type_is_valid.rb +21 -0
  22. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_author.rb +28 -0
  23. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_custodian/suite_au_ps_bundle_instance_au_ps_composition_custodian_custodian_ms_elements.rb +21 -0
  24. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_custodian/suite_au_ps_bundle_instance_au_ps_composition_custodian_custodian_ms_identifier_slices.rb +21 -0
  25. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_custodian/suite_au_ps_bundle_instance_au_ps_composition_custodian_custodian_ms_subelements.rb +21 -0
  26. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_custodian.rb +26 -0
  27. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_mandatory_sections/composition_mandatory_sections_mandatory_sections_entry_profiles.rb +21 -0
  28. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_mandatory_sections/suite_au_ps_bundle_instance_au_ps_composition_mandatory_sections_sections_shall_populated.rb +21 -0
  29. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_mandatory_sections.rb +20 -0
  30. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_mandatory_ms_populated.rb +21 -0
  31. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_ms_subelements_populated.rb +22 -0
  32. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_optional_ms_populated.rb +22 -0
  33. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_optional_ms_slices.rb +22 -0
  34. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_must_support_conformance.rb +28 -0
  35. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_optional_sections/suite_au_ps_bundle_instance_au_ps_composition_optional_sections_optional_sections_entry_profiles.rb +22 -0
  36. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_optional_sections/suite_au_ps_bundle_instance_au_ps_composition_optional_sections_sections_may_populated.rb +24 -0
  37. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_optional_sections.rb +20 -0
  38. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_recommended_sections/composition_recommended_sections_recommended_sections_entry_profiles.rb +21 -0
  39. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_recommended_sections/suite_au_ps_bundle_instance_au_ps_composition_recommended_sections_sections_should_populated.rb +22 -0
  40. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_recommended_sections.rb +20 -0
  41. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_subject/suite_au_ps_bundle_instance_au_ps_composition_subject_subject_ms_elements.rb +21 -0
  42. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_subject/suite_au_ps_bundle_instance_au_ps_composition_subject_subject_ms_identifier_slices.rb +21 -0
  43. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_subject/suite_au_ps_bundle_instance_au_ps_composition_subject_subject_ms_subelements_populated.rb +21 -0
  44. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_subject/suite_au_ps_bundle_instance_au_ps_composition_subject_subject_resource_type_is_valid.rb +21 -0
  45. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_subject.rb +28 -0
  46. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_undefined_sections/suite_au_ps_bundle_instance_au_ps_composition_undefined_sections_sections_may_undefined.rb +24 -0
  47. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/au_ps_composition_undefined_sections.rb +18 -0
  48. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/bundle_validation/suite_au_ps_bundle_instance_bundle_validation_bundle_valid.rb +21 -0
  49. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/bundle_validation/suite_au_ps_bundle_instance_bundle_validation_bundle_valid_ips.rb +21 -0
  50. data/lib/au_ps_inferno/suite/au_ps_bundle_instance/bundle_validation.rb +20 -0
  51. data/lib/au_ps_inferno/suite/au_ps_retrieve_cs_group/au_ps_cs_is_valid_test.rb +21 -0
  52. data/lib/au_ps_inferno/suite/au_ps_retrieve_cs_group/au_ps_cs_supports_au_ps_profiles.rb +40 -0
  53. data/lib/au_ps_inferno/suite/au_ps_retrieve_cs_group/au_ps_cs_supports_ips_recommended_ops.rb +19 -0
  54. data/lib/au_ps_inferno/suite/au_ps_retrieve_cs_group/au_ps_retrieve_cs_group.rb +47 -0
  55. data/lib/au_ps_inferno/suite/au_ps_v100.rb +39 -0
  56. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_bundle_must_support_conformance/bundle_must_support_conformance_bundle_must_support_populated.rb +21 -0
  57. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_bundle_must_support_conformance.rb +16 -0
  58. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_attester/composition_attester_attester_party_ms_elements.rb +21 -0
  59. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_attester/composition_attester_attester_party_ms_identifier_slices.rb +21 -0
  60. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_attester/composition_attester_attester_party_ms_subelements.rb +21 -0
  61. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_attester.rb +26 -0
  62. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_author/composition_author_author_ms_elements.rb +21 -0
  63. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_author/composition_author_author_ms_identifier_slices.rb +21 -0
  64. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_author/composition_author_author_ms_subelements.rb +21 -0
  65. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_author/composition_author_author_resource_type_is_valid.rb +21 -0
  66. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_author.rb +28 -0
  67. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_custodian/composition_custodian_custodian_ms_elements.rb +21 -0
  68. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_custodian/composition_custodian_custodian_ms_identifier_slices.rb +21 -0
  69. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_custodian/composition_custodian_custodian_ms_subelements.rb +21 -0
  70. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_custodian.rb +26 -0
  71. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_mandatory_sections/composition_mandatory_sections_mandatory_sections_entry_profiles.rb +21 -0
  72. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_mandatory_sections/composition_mandatory_sections_sections_shall_populated.rb +21 -0
  73. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_mandatory_sections.rb +20 -0
  74. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_mandatory_ms_populated.rb +21 -0
  75. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_ms_subelements_populated.rb +22 -0
  76. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_optional_ms_populated.rb +22 -0
  77. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_optional_ms_slices.rb +22 -0
  78. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_must_support_conformance.rb +28 -0
  79. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_optional_sections/composition_optional_sections_optional_sections_entry_profiles.rb +22 -0
  80. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_optional_sections/composition_optional_sections_sections_may_populated.rb +24 -0
  81. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_optional_sections.rb +20 -0
  82. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_recommended_sections/composition_recommended_sections_recommended_sections_entry_profiles.rb +21 -0
  83. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_recommended_sections/composition_recommended_sections_sections_should_populated.rb +22 -0
  84. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_recommended_sections.rb +20 -0
  85. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_subject/composition_subject_subject_ms_elements.rb +21 -0
  86. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_subject/composition_subject_subject_ms_identifier_slices.rb +21 -0
  87. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_subject/composition_subject_subject_ms_subelements_populated.rb +21 -0
  88. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_subject/composition_subject_subject_resource_type_is_valid.rb +21 -0
  89. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_subject.rb +28 -0
  90. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_undefined_sections/composition_undefined_sections_sections_may_undefined.rb +24 -0
  91. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/au_ps_composition_undefined_sections.rb +18 -0
  92. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/bundle_validation/suite_generate_au_ps_using_ips_summary_validation_tests_bundle_validation_bundle_valid.rb +21 -0
  93. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/bundle_validation/suite_generate_au_ps_using_ips_summary_validation_tests_bundle_validation_bundle_valid_ips.rb +21 -0
  94. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/bundle_validation.rb +20 -0
  95. data/lib/au_ps_inferno/suite/generate_au_ps_using_ips_summary_validation_tests/generate_au_ps_using_ips_summary_validation_tests.rb +56 -0
  96. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_bundle_must_support_conformance/bundle_must_support_conformance_bundle_must_support_populated.rb +21 -0
  97. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_bundle_must_support_conformance.rb +16 -0
  98. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_attester/composition_attester_attester_party_ms_elements.rb +21 -0
  99. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_attester/composition_attester_attester_party_ms_identifier_slices.rb +21 -0
  100. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_attester/composition_attester_attester_party_ms_subelements.rb +21 -0
  101. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_attester.rb +26 -0
  102. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_author/composition_author_author_ms_identifier_slices.rb +21 -0
  103. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_author/composition_author_author_resource_type_is_valid.rb +21 -0
  104. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_author/suite_retrieve_au_ps_bundle_validation_tests_au_ps_composition_author_author_ms_elements.rb +21 -0
  105. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_author/suite_retrieve_au_ps_bundle_validation_tests_au_ps_composition_author_author_ms_subelements.rb +21 -0
  106. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_author.rb +28 -0
  107. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_custodian/composition_custodian_custodian_ms_identifier_slices.rb +21 -0
  108. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_custodian/composition_custodian_custodian_ms_subelements.rb +21 -0
  109. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_custodian/suite_retrieve_au_ps_bundle_validation_tests_au_ps_composition_custodian_custodian_ms_elements.rb +21 -0
  110. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_custodian.rb +26 -0
  111. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_mandatory_sections/composition_mandatory_sections_mandatory_sections_entry_profiles.rb +21 -0
  112. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_mandatory_sections/composition_mandatory_sections_sections_shall_populated.rb +21 -0
  113. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_mandatory_sections.rb +20 -0
  114. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_mandatory_ms_populated.rb +21 -0
  115. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_ms_subelements_populated.rb +22 -0
  116. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_optional_ms_populated.rb +22 -0
  117. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_must_support_conformance/composition_must_support_conformance_composition_optional_ms_slices.rb +22 -0
  118. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_must_support_conformance.rb +28 -0
  119. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_optional_sections/composition_optional_sections_optional_sections_entry_profiles.rb +22 -0
  120. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_optional_sections/composition_optional_sections_sections_may_populated.rb +24 -0
  121. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_optional_sections.rb +20 -0
  122. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_recommended_sections/composition_recommended_sections_recommended_sections_entry_profiles.rb +21 -0
  123. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_recommended_sections/composition_recommended_sections_sections_should_populated.rb +22 -0
  124. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_recommended_sections.rb +20 -0
  125. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_subject/composition_subject_subject_ms_identifier_slices.rb +21 -0
  126. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_subject/composition_subject_subject_ms_subelements_populated.rb +21 -0
  127. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_subject/composition_subject_subject_resource_type_is_valid.rb +21 -0
  128. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_subject/suite_retrieve_au_ps_bundle_validation_tests_au_ps_composition_subject_subject_ms_elements.rb +21 -0
  129. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_subject.rb +28 -0
  130. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_undefined_sections/composition_undefined_sections_sections_may_undefined.rb +24 -0
  131. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/au_ps_composition_undefined_sections.rb +18 -0
  132. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/bundle_validation/suite_retrieve_au_ps_bundle_validation_tests_bundle_validation_bundle_valid.rb +21 -0
  133. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/bundle_validation/suite_retrieve_au_ps_bundle_validation_tests_bundle_validation_bundle_valid_ips.rb +21 -0
  134. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/bundle_validation.rb +20 -0
  135. data/lib/au_ps_inferno/suite/retrieve_au_ps_bundle_validation_tests/retrieve_au_ps_bundle_validation_tests.rb +56 -0
  136. data/lib/au_ps_inferno/utils/attester/basic_test_attester_identifier_slices.rb +74 -0
  137. data/lib/au_ps_inferno/utils/attester/basic_test_attester_message_helpers.rb +16 -0
  138. data/lib/au_ps_inferno/utils/attester/basic_test_attester_module.rb +14 -0
  139. data/lib/au_ps_inferno/utils/attester/basic_test_attester_resource.rb +54 -0
  140. data/lib/au_ps_inferno/utils/author/basic_test_author_module.rb +12 -0
  141. data/lib/au_ps_inferno/utils/author/basic_test_author_resource.rb +32 -0
  142. data/lib/au_ps_inferno/utils/author/basic_test_author_tests.rb +24 -0
  143. data/lib/au_ps_inferno/utils/basic_test/bundle_module.rb +87 -0
  144. data/lib/au_ps_inferno/utils/basic_test/capability_operations_module.rb +37 -0
  145. data/lib/au_ps_inferno/utils/basic_test/composition_elements_and_slices_module.rb +98 -0
  146. data/lib/au_ps_inferno/utils/basic_test/composition_section_check_resources_ms_elements_module.rb +197 -0
  147. data/lib/au_ps_inferno/utils/basic_test/composition_section_read_issues_helpers_module.rb +66 -0
  148. data/lib/au_ps_inferno/utils/basic_test/composition_section_read_module.rb +127 -0
  149. data/lib/au_ps_inferno/utils/basic_test/composition_subelements_module.rb +84 -0
  150. data/lib/au_ps_inferno/utils/basic_test/ms_elements_populated_helpers_module.rb +38 -0
  151. data/lib/au_ps_inferno/utils/basic_test/ms_elements_populated_module.rb +71 -0
  152. data/lib/au_ps_inferno/utils/basic_test/ms_identifier_slices_module.rb +61 -0
  153. data/lib/au_ps_inferno/utils/basic_test/ms_sub_elements_populated_module.rb +128 -0
  154. data/lib/au_ps_inferno/utils/basic_test/paths_module.rb +26 -0
  155. data/lib/au_ps_inferno/utils/basic_test/resolve_path_debug_module.rb +45 -0
  156. data/lib/au_ps_inferno/utils/basic_test/resolve_resource_type_module.rb +52 -0
  157. data/lib/au_ps_inferno/utils/basic_test/resource_helpers_module.rb +129 -0
  158. data/lib/au_ps_inferno/utils/basic_test/scratch_bundle_entries_module.rb +30 -0
  159. data/lib/au_ps_inferno/utils/basic_test/section_bundle_validation_module.rb +70 -0
  160. data/lib/au_ps_inferno/utils/basic_test_class.rb +56 -0
  161. data/lib/au_ps_inferno/utils/basic_test_contants_module.rb +32 -0
  162. data/lib/au_ps_inferno/utils/basic_test_with_url.rb +8 -0
  163. data/lib/au_ps_inferno/utils/basic_validate_bundle_test.rb +43 -0
  164. data/lib/au_ps_inferno/utils/bundle_decorator.rb +81 -0
  165. data/lib/au_ps_inferno/utils/bundle_entry_decorator.rb +19 -0
  166. data/lib/au_ps_inferno/utils/bundle_is_valid_class.rb +31 -0
  167. data/lib/au_ps_inferno/utils/capability_statement_decorator.rb +20 -0
  168. data/lib/au_ps_inferno/utils/composition_decorator.rb +56 -0
  169. data/lib/au_ps_inferno/utils/composition_utils/boolean_and_stats.rb +28 -0
  170. data/lib/au_ps_inferno/utils/composition_utils.rb +29 -0
  171. data/lib/au_ps_inferno/utils/custodian/basic_test_custodian_identifier_slices.rb +47 -0
  172. data/lib/au_ps_inferno/utils/custodian/basic_test_custodian_module.rb +14 -0
  173. data/lib/au_ps_inferno/utils/custodian/basic_test_custodian_resource.rb +32 -0
  174. data/lib/au_ps_inferno/utils/custodian/basic_test_custodian_tests.rb +19 -0
  175. data/lib/au_ps_inferno/utils/inferno_suite_generator_compat.rb +7 -0
  176. data/lib/au_ps_inferno/utils/ips_bundle_is_valid_class.rb +15 -0
  177. data/lib/au_ps_inferno/utils/ips_retrieve_bundle_test_class.rb +17 -0
  178. data/lib/au_ps_inferno/utils/ips_summary_valid_bundle_class.rb +15 -0
  179. data/lib/au_ps_inferno/utils/metadata_manager.rb +58 -0
  180. data/lib/au_ps_inferno/utils/retrieve_bundle_test_class.rb +81 -0
  181. data/lib/au_ps_inferno/utils/rich_message_class.rb +23 -0
  182. data/lib/au_ps_inferno/utils/rich_validation_message.rb +42 -0
  183. data/lib/au_ps_inferno/utils/section_decorator.rb +23 -0
  184. data/lib/au_ps_inferno/utils/section_names_mapping.rb +31 -0
  185. data/lib/au_ps_inferno/utils/section_test_class.rb +18 -0
  186. data/lib/au_ps_inferno/utils/section_test_module.rb +16 -0
  187. data/lib/au_ps_inferno/utils/structure_definition_decorator.rb +28 -0
  188. data/lib/au_ps_inferno/utils/subject/basic_test_subject_module.rb +12 -0
  189. data/lib/au_ps_inferno/utils/subject/basic_test_subject_patient_ms_other_tests.rb +15 -0
  190. data/lib/au_ps_inferno/utils/subject/basic_test_subject_resource.rb +21 -0
  191. data/lib/au_ps_inferno/utils/summary_valid_bundle_class.rb +84 -0
  192. data/lib/au_ps_inferno/utils/validator_helpers.rb +92 -0
  193. data/lib/au_ps_inferno/version.rb +6 -0
  194. data/lib/au_ps_inferno.rb +3 -0
  195. metadata +310 -0
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../inferno_suite_generator_compat'
4
+ require 'inferno_suite_generator/test_utils/ms_checker'
5
+ module AUPSTestKit
6
+ module BasicTestCompositionSectionReadModule
7
+ # Composition Must Support elements in sections.
8
+ module BasicTestCompositionSectionCheckResourcesMSElementsModule # rubocop:disable Metrics/ModuleLength
9
+ AU_PS_PROFILE_BASE_URL = 'http://hl7.org.au/fhir/ps/StructureDefinition/'
10
+
11
+ def check_ms_elements_populated(profile_url, resources, all_present: false)
12
+ profile_metadata = group_metadata_for(profile_url)
13
+ collapsed_elements_statuses(ms_checker_for(profile_metadata).elements_present_statuses(resources, all_present:))
14
+ end
15
+
16
+ private
17
+
18
+ def collapsed_elements_statuses(elements_statuses)
19
+ to_collapse = parent_paths_to_collapse(elements_statuses)
20
+ elements_statuses.filter do |element|
21
+ next true unless element[:path].include?('.')
22
+
23
+ to_collapse.none? do |to_collapse_path|
24
+ element[:path].start_with?("#{to_collapse_path}.")
25
+ end
26
+ end
27
+ end
28
+
29
+ def parent_paths_to_collapse(elements_statuses)
30
+ optional_missing_parent_elements(elements_statuses).map { |element| element[:path] }.uniq
31
+ end
32
+
33
+ def complex_elements(elements_statuses)
34
+ elements_statuses.filter { |element| element[:path].include?('.') }.map { |element| element[:path] }
35
+ end
36
+
37
+ def optional_missing_parent_elements(elements_statuses)
38
+ complex_elements_paths = complex_elements(elements_statuses)
39
+ elements_statuses.filter do |element|
40
+ element[:present] == false &&
41
+ element[:mandatory] == false &&
42
+ !element[:path].include?('.') &&
43
+ complex_elements_paths.any? { |complex_element| complex_element.start_with?(element[:path]) }
44
+ end
45
+ end
46
+
47
+ def raw_sections_profiles(sections_codes)
48
+ sections_metadata = metadata_manager.sections_metadata_by_codes(sections_codes)
49
+ sections_metadata.flat_map do |section_metadata|
50
+ section_short = section_metadata[:short]
51
+ section_code = section_metadata[:code]
52
+ section_metadata[:entries].flat_map do |entry_metadata|
53
+ entry_metadata[:profiles].map do |profile|
54
+ {
55
+ profile: profile,
56
+ section_short: section_short,
57
+ section_code: section_code
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ def sections_profiles(sections_codes)
65
+ uniq_profiles = Set.new
66
+ raw_sections_profiles(sections_codes).filter do |profile|
67
+ _, profile_url = profile[:profile].split('|', 2)
68
+ next false unless profile_url.present? && profile_url.start_with?(AU_PS_PROFILE_BASE_URL)
69
+ next false if uniq_profiles.include?(profile_url)
70
+
71
+ uniq_profiles.add(profile_url)
72
+ true
73
+ end
74
+ end
75
+
76
+ def resources_to_check_ms(sections_codes:, bundle_resource:)
77
+ composition_resource = bundle_resource.composition_resource
78
+
79
+ entry_references = composition_resource.entry_references_by_codes(sections_codes)
80
+ bundle_resource.resources_by_references(entry_references)
81
+ end
82
+
83
+ def result_has?(results, result_type)
84
+ results.any? { |result| result == result_type }
85
+ end
86
+
87
+ def results_error?(results)
88
+ result_has?(results, 'error')
89
+ end
90
+
91
+ def check_ms_elements_populated_against_profiles(sections_profiles, resources_to_check_ms, all_present: false)
92
+ sections_profiles.map { |profile| process_profile(profile, resources_to_check_ms, all_present:) }
93
+ end
94
+
95
+ def normalize_resource_type_and_profile(profile)
96
+ parts = profile.split('|')
97
+ raise StandardError, 'Profile is not in the correct format' if parts.length < 2
98
+
99
+ {
100
+ resource_type: parts[0],
101
+ profile_url: parts[1]
102
+ }
103
+ end
104
+
105
+ def msg_line(title, text)
106
+ "**#{title}**: #{text}"
107
+ end
108
+
109
+ def ms_checker_for(profile_metadata, section_context = nil)
110
+ InfernoSuiteGenerator::MSChecker.new(profile_metadata, ms_checker_message_config(section_context))
111
+ end
112
+
113
+ def build_ms_outcome(profile_metadata, resources, section_context = nil, all_present: false)
114
+ ms_helper = ms_checker_for(profile_metadata, section_context)
115
+ ms_checks_results = check_ms_elements_populated(profile_metadata.profile_url, resources, all_present:)
116
+
117
+ {
118
+ status: ms_helper.calculate_elements_status_message_level(ms_checks_results),
119
+ message: ms_helper.build_report_message(profile_metadata, ms_checks_results)
120
+ }
121
+ end
122
+
123
+ def process_profile(section_profile, resources_to_check_ms, all_present: false)
124
+ profile_info_str, filtered_resources, _, profile_url =
125
+ build_profile_context(section_profile, resources_to_check_ms)
126
+ return report_missing_resources(profile_info_str) if filtered_resources.blank?
127
+
128
+ profile_metadata = group_metadata_for(profile_url)
129
+ outcome = build_ms_outcome(profile_metadata, filtered_resources, section_profile, all_present:)
130
+ add_message(outcome[:status], outcome[:message].join("\n\n"))
131
+
132
+ outcome[:status]
133
+ end
134
+
135
+ def build_profile_context(section_profile, resources_to_check_ms)
136
+ resource_type_and_profile = normalize_resource_type_and_profile(section_profile[:profile])
137
+ resource_type, profile_url = resource_type_and_profile.values_at(:resource_type, :profile_url)
138
+ profile_info_str = msg_line('Profile', "#{resource_type} — #{profile_url}")
139
+ filtered_resources = resources_by_type(resources_to_check_ms, resource_type)
140
+
141
+ [profile_info_str, filtered_resources, resource_type, profile_url]
142
+ end
143
+
144
+ def resources_by_type(resources, resource_type)
145
+ resources.filter { |resource| resource.resourceType == resource_type }
146
+ end
147
+
148
+ def group_metadata_for(profile_url)
149
+ resource_metadata_raw = metadata_manager.group_metadata_by_profile_url(profile_url)
150
+ InfernoSuiteGenerator::Generator::GroupMetadata.new(resource_metadata_raw)
151
+ end
152
+
153
+ def report_missing_resources(profile_info_str)
154
+ full_message_data = [
155
+ 'No resources found',
156
+ profile_info_str
157
+ ]
158
+ add_message('warning', full_message_data.join("\n\n"))
159
+ nil
160
+ end
161
+
162
+ def section_context_label(section_context)
163
+ short = section_context[:section_short]
164
+ code = section_context[:section_code]
165
+ short.present? ? "#{short} (#{code})" : code.to_s
166
+ end
167
+
168
+ def ms_checker_message_config(section_context)
169
+ return {} if section_context.blank?
170
+
171
+ section_label = section_context_label(section_context)
172
+
173
+ {
174
+ 'mandatory_error_message' =>
175
+ inject_section_into_ms_message(InfernoSuiteGenerator::MSChecker::MANDATORY_ERROR_MS_MESSAGE, section_label),
176
+ 'optional_warning_message' =>
177
+ inject_section_into_ms_message(InfernoSuiteGenerator::MSChecker::OPTIONAL_MS_WARNING_MESSAGE,
178
+ section_label),
179
+ 'okay_message' =>
180
+ inject_section_into_ms_message(InfernoSuiteGenerator::MSChecker::MS_OKAY_MESSAGE, section_label)
181
+ }
182
+ end
183
+
184
+ def inject_section_into_ms_message(message, section_label)
185
+ message.sub('.', " in the #{section_label} section.")
186
+ end
187
+
188
+ def composition_section_check_ms_pass?(sections_codes:, bundle_resource:, all_present: false)
189
+ results = check_ms_elements_populated_against_profiles(sections_profiles(sections_codes),
190
+ resources_to_check_ms(sections_codes: sections_codes,
191
+ bundle_resource: bundle_resource),
192
+ all_present:)
193
+ !results_error?(results)
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AUPSTestKit
4
+ # Helpers for reading composition section issues.
5
+ module BasicTestCompositionSectionReadIssuesHelpersModule
6
+ def references_resolution_report(section_metadata, bundle_resource)
7
+ section_code = section_metadata[:code]
8
+ composition_resource = bundle_resource.composition_resource
9
+ section = composition_resource.section_by_code(section_code)
10
+ entries_resource_types = permitted_resource_types(section_metadata)
11
+
12
+ section.entry_references.map do |ref|
13
+ issues = composition_section_ref_read_issues(ref, bundle_resource, entries_resource_types)
14
+ build_reference_resolution_report(ref, issues)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def read_composition_section_issues(section_metadata, bundle_resource)
21
+ section_code = section_metadata[:code]
22
+ if bundle_resource.composition_resource.section_by_code(section_code).blank?
23
+ return ["No composition section found for code: #{section_code}"]
24
+ end
25
+
26
+ references_resolution_report(section_metadata, bundle_resource).map do |ref_report|
27
+ ref_report[:issues]
28
+ end.flatten.compact
29
+ end
30
+
31
+ def build_reference_resolution_report(ref, issues)
32
+ {
33
+ reference: ref,
34
+ resolved: issues.empty?,
35
+ issues: issues
36
+ }
37
+ end
38
+
39
+ def composition_section_ref_read_issues(ref, bundle_resource, entries_resource_types)
40
+ resource = bundle_resource.resource_by_reference(ref)
41
+ issues = []
42
+ issues << "Resource not found for reference: #{ref}" if resource.blank?
43
+ if resource.present? && !entries_resource_types.include?(resource.resourceType)
44
+ issues << "Resource type: #{resource.resourceType} is not in the list " \
45
+ "of expected resource types: #{entries_resource_types}"
46
+ end
47
+ issues
48
+ end
49
+
50
+ def permitted_resource_types(section_metadata)
51
+ section_metadata[:entries].map do |entry|
52
+ entry[:profiles].map do |profile|
53
+ profile.split('|').first
54
+ end
55
+ end.flatten.uniq
56
+ end
57
+
58
+ def empty_section_entry_reason_line(section)
59
+ if section.empty_reason_str.present?
60
+ "emptyReason: #{section.empty_reason_str}"
61
+ else
62
+ 'No entries; no emptyReason.'
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../inferno_suite_generator_compat'
4
+ require_relative 'composition_section_check_resources_ms_elements_module'
5
+ require_relative 'composition_section_read_issues_helpers_module'
6
+ module AUPSTestKit
7
+ # Reading composition section rows: profile/entry matching and list outcomes.
8
+ module BasicTestCompositionSectionReadModule
9
+ # !!!!!!!!!!
10
+ # TODO: Remove generator and replace with runtime
11
+ MANDATORY_SECTIONS_CODES = %w[11450-4 48765-2 10160-0].freeze
12
+ RECOMMENDED_SECTIONS_CODES = %w[11369-6 30954-2 47519-4 46264-8].freeze
13
+ OPTIONAL_SECTIONS_CODES = %w[42348-3 104605-1 47420-5 11348-0 10162-6 81338-6 18776-5 29762-2 8716-3].freeze
14
+
15
+ include BasicTestCompositionSectionCheckResourcesMSElementsModule
16
+ include BasicTestCompositionSectionReadIssuesHelpersModule
17
+
18
+ private
19
+
20
+ def test_composition_mandatory_sections
21
+ check_bundle_exists_in_scratch
22
+ test_composition_sections_data(sections_codes: MANDATORY_SECTIONS_CODES, bundle_data: scratch_bundle,
23
+ mandatory: true)
24
+ end
25
+
26
+ def test_composition_recommended_sections
27
+ check_bundle_exists_in_scratch
28
+ test_composition_sections_data(sections_codes: RECOMMENDED_SECTIONS_CODES, bundle_data: scratch_bundle)
29
+ end
30
+
31
+ def test_composition_optional_sections
32
+ check_bundle_exists_in_scratch
33
+ test_composition_sections_data(sections_codes: OPTIONAL_SECTIONS_CODES, bundle_data: scratch_bundle)
34
+ end
35
+
36
+ def test_composition_sections_data(sections_codes:, bundle_data:, mandatory: false)
37
+ # Mandatory: true - FN should fail if any mandatory section is not populated correctly.
38
+ # Unresolved references always fail regardless of mandatory status.
39
+ bundle_resource = BundleDecorator.new(bundle_data)
40
+ refs_test_pass = composition_sections_references_resolution_pass?(sections_codes: sections_codes,
41
+ bundle_resource: bundle_resource,
42
+ mandatory: mandatory)
43
+ ms_test_pass = composition_section_check_ms_pass?(sections_codes: sections_codes,
44
+ bundle_resource: bundle_resource,
45
+ all_present: true)
46
+
47
+ assert refs_test_pass, 'Some section entry references cannot be resolved.'
48
+ assert ms_test_pass,
49
+ 'Some of the sections are not populated with the correct Must Support elements.'
50
+ end
51
+
52
+ def composition_sections_references_resolution_pass?(sections_codes:, bundle_resource:, mandatory: false)
53
+ composition_resource = bundle_resource.composition_resource
54
+ sections_metadata = metadata_manager.sections_metadata_by_codes(sections_codes)
55
+ sections_metadata.map do |section_metadata|
56
+ composition_section_references_resolution_issues?(section_metadata: section_metadata,
57
+ composition_resource: composition_resource,
58
+ bundle_resource: bundle_resource,
59
+ mandatory: mandatory)
60
+ end.all?
61
+ end
62
+
63
+ def section_reference_message_level(mandatory:, has_unresolved:)
64
+ mandatory || has_unresolved ? 'error' : 'warning'
65
+ end
66
+
67
+ def composition_section_references_resolution_issues?(section_metadata:, composition_resource:, bundle_resource:,
68
+ mandatory:)
69
+ section_code = section_metadata[:code]
70
+ section = composition_resource.section_by_code(section_code)
71
+ issues = read_composition_section_issues(section_metadata, bundle_resource)
72
+ text = composition_section_read_report_message(section_metadata, section, bundle_resource, section_code)
73
+ has_unresolved = issues.any? { |issue| issue.start_with?('Resource not found for reference:') }
74
+ level = section_reference_message_level(mandatory:, has_unresolved:)
75
+ add_message(issues.empty? ? 'info' : level, text)
76
+ issues.empty? || (!mandatory && !has_unresolved)
77
+ end
78
+
79
+ def composition_section_read_report_message(section_metadata, section, bundle_resource, section_code)
80
+ short = section_metadata[:short]
81
+ header = short.present? ? "#{short} (#{section_code})" : section_code.to_s
82
+ body = composition_section_read_list_body(section, bundle_resource, section_code, section_metadata)
83
+ "#{header}\n\n#{body}"
84
+ end
85
+
86
+ def composition_section_read_list_body(section, bundle_resource, section_code, section_metadata)
87
+ return "No composition section found for code: #{section_code}" if section.blank?
88
+ return empty_section_entry_reason_line(section) if section.entry_references.empty?
89
+
90
+ section.entry_references.each.map do |ref|
91
+ format_composition_section_entry_line(ref, bundle_resource, section_metadata)
92
+ end.join("\n\n")
93
+ end
94
+
95
+ def format_composition_section_entry_line(ref, bundle_resource, section_metadata)
96
+ resource = bundle_resource.resource_by_reference(ref)
97
+ index = get_section_entry_index(section_metadata, bundle_resource, ref)
98
+ return composition_section_entry_line_unresolved(ref) if resource.blank?
99
+ unless permitted_resource_types(section_metadata).include?(resource.resourceType)
100
+ return composition_section_entry_line_bad_type(index, ref, resource.resourceType)
101
+ end
102
+
103
+ composition_section_entry_line_resolved(index, ref, resource)
104
+ end
105
+
106
+ def get_section_entry_index(section_metadata, bundle_resource, ref)
107
+ section = bundle_resource.composition_resource.section_by_code(section_metadata[:code])
108
+ return nil if section.blank?
109
+
110
+ section.get_entry_index_by_reference(ref)
111
+ end
112
+
113
+ def composition_section_entry_line_unresolved(ref)
114
+ "**#{ref}** -> ❌ Reference does not resolve"
115
+ end
116
+
117
+ def composition_section_entry_line_bad_type(index, ref, resource_type)
118
+ "entry[#{index}]: **#{ref}** -> ❌ Invalid resource type: #{resource_type}"
119
+ end
120
+
121
+ def composition_section_entry_line_resolved(index, ref, resource)
122
+ profiles = resource.meta&.profile || []
123
+ suffix = profiles.any? ? "(meta.profile: #{profiles.join(', ')})" : '(no meta.profile)'
124
+ "entry[#{index}]: **#{ref}** -> #{resource.resourceType} #{suffix}"
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AUPSTestKit
4
+ # Composition Must Support sub-elements (grouped paths) and parent-group validation on arbitrary resources.
5
+ module BasicTestCompositionSubelementsModule
6
+ private
7
+
8
+ def validate_populated_sub_elements_in_composition(mandatory_ms, optional_ms)
9
+ composition_resource = composition_resource_from_scratch
10
+ return false unless composition_resource.present?
11
+
12
+ grouped_elements = (mandatory_ms + optional_ms).group_by { |element| element.split('.').first }
13
+ run_composition_subelements_assertions(composition_resource, grouped_elements, mandatory_ms)
14
+ end
15
+
16
+ def composition_resource_from_scratch
17
+ return nil unless scratch_bundle.present?
18
+
19
+ BundleDecorator.new(scratch_bundle).composition_resource
20
+ end
21
+
22
+ def run_composition_subelements_assertions(composition_resource, grouped_elements, mandatory_ms)
23
+ any_parent = composition_any_subelement_parent_populated?(composition_resource, grouped_elements)
24
+ mandatory_ok = composition_mandatory_subelements_ok?(composition_resource, grouped_elements, mandatory_ms)
25
+
26
+ # Error: when any mandatory Must Support sub-elements are missing (i.e. subject.reference and attester.mode).
27
+ # Warning: when any optional Must Support sub-elements are missing (i.e. attester.time and attester.party)
28
+ # Info: when all optional Must Support sub-elements are populated
29
+ # One message for each complex element with Must Support sub-elements, i.e. subject and attester
30
+ # Include list of Must Support sub-elements populated and missing.
31
+
32
+ grouped_elements.each do |parent_path, sub_elements|
33
+ add_composition_subelements_messages(composition_resource, parent_path, sub_elements, mandatory_ms)
34
+ end
35
+
36
+ skip_if !any_parent, 'No complex element with Must Support sub-elements is populated'
37
+ msg = 'Some of the mandatory Must Support sub-elements are not populated. ' \
38
+ 'See the list of populated sub-elements in messages tab.'
39
+ assert mandatory_ok, msg
40
+ end
41
+
42
+ def composition_any_subelement_parent_populated?(composition_resource, grouped_elements)
43
+ grouped_elements.any? do |parent_path, _|
44
+ resolve_path_with_dar(composition_resource, parent_path).first.present?
45
+ end
46
+ end
47
+
48
+ def composition_mandatory_subelements_ok?(composition_resource, grouped_elements, mandatory_ms)
49
+ grouped_elements.all? do |parent_path, sub_elements|
50
+ next true unless resolve_path_with_dar(composition_resource, parent_path).first.present?
51
+
52
+ (mandatory_ms & sub_elements).all? { |el| resolve_path_with_dar(composition_resource, el).first.present? }
53
+ end
54
+ end
55
+
56
+ def add_composition_subelements_messages(composition_resource, parent_path, sub_elements, mandatory_ms)
57
+ unless resolve_path_with_dar(composition_resource, parent_path).first.present?
58
+ add_message('warning', composition_subelement_parent_unpopulated_message(parent_path, sub_elements))
59
+ return
60
+ end
61
+
62
+ level = composition_subelements_worst_level(composition_resource, sub_elements, mandatory_ms)
63
+ add_message(level, populated_paths_info(composition_resource, sub_elements, mandatory_array: mandatory_ms))
64
+ end
65
+
66
+ def composition_subelement_parent_unpopulated_message(parent_path, sub_elements)
67
+ detail = "**Complex element #{parent_path}** is not populated. " \
68
+ "Must Support sub-elements that would be validated: #{sub_elements.join(', ')}."
69
+ ['Must Support sub-elements correctly populated', 'Composition', detail].join("\n\n")
70
+ end
71
+
72
+ def composition_subelements_worst_level(composition_resource, sub_elements, mandatory_ms)
73
+ levels = sub_elements.map do |sub_element|
74
+ present = resolve_path_with_dar(composition_resource, sub_element).first.present?
75
+ next 'info' if present
76
+
77
+ mandatory_ms.include?(sub_element) ? 'error' : 'warning'
78
+ end
79
+ return 'error' if levels.include?('error')
80
+
81
+ levels.include?('warning') ? 'warning' : 'info'
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AUPSTestKit
4
+ # Internal helpers to keep the populated-message module concise.
5
+ module BasicTestMsElementsPopulatedHelpersModule
6
+ private
7
+
8
+ def assert_message
9
+ 'When any mandatory Must Support element is missing. See the list in messages tab.'
10
+ end
11
+
12
+ def get_target_metadata_by_container_type(container_type)
13
+ case container_type
14
+ when 'subject'
15
+ metadata_manager.subject_metadata
16
+ when 'author'
17
+ metadata_manager.author_metadata
18
+ when 'custodian'
19
+ metadata_manager.custodian_metadata
20
+ when 'attester'
21
+ metadata_manager.attester_metadata
22
+ end
23
+ end
24
+
25
+ def get_resource_by_container_type(container_type)
26
+ case container_type
27
+ when 'subject'
28
+ subject_resource
29
+ when 'author'
30
+ author_resource
31
+ when 'custodian'
32
+ custodian_resource
33
+ when 'attester'
34
+ attester_party_resource
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ms_elements_populated_helpers_module'
4
+
5
+ module AUPSTestKit
6
+ # Must Support elements populated or missing message.
7
+ module BasicTestMsElementsPopulatedModule
8
+ include BasicTestMsElementsPopulatedHelpersModule
9
+
10
+ def ms_elements_populated_message(container_type)
11
+ guard_populated_resource(container_type)
12
+
13
+ resource = get_resource_by_container_type(container_type)
14
+
15
+ author_and_device_resource?(container_type, resource)
16
+
17
+ resource_metadata_raw = metadata_manager.group_metadata_by_resource_type(resource.resourceType)
18
+ return unless resource_metadata_raw.present?
19
+
20
+ profile_metadata = InfernoSuiteGenerator::Generator::GroupMetadata.new(resource_metadata_raw)
21
+
22
+ assert all_ms_mandatory_elements_populated?(resource, profile_metadata), assert_message
23
+ end
24
+
25
+ private
26
+
27
+ def all_ms_mandatory_elements_populated?(resource, profile_metadata)
28
+ ms_checker = InfernoSuiteGenerator::MSChecker.new(profile_metadata)
29
+ ms_checks_results = elements(ms_checker, [resource])
30
+ ms_slices_results = slices(ms_checker, [resource])
31
+ ms_extension_results = extensions(ms_checker, [resource])
32
+ all_check_results = [*ms_checks_results, *ms_slices_results, *ms_extension_results]
33
+
34
+ status = ms_checker.calculate_elements_status_message_level(all_check_results)
35
+ message = ms_checker.build_report_message(profile_metadata, all_check_results)
36
+ add_message(status, message.join("\n\n"))
37
+
38
+ all_check_results.none? { |result| !result[:present] && result[:mandatory] }
39
+ end
40
+
41
+ def elements(checker, resources)
42
+ elements_statuses = checker.elements_present_statuses(resources, all_present: false)
43
+ elements_statuses.filter { |result| element_simple?(result[:path]) }
44
+ end
45
+
46
+ def slices(checker, resources)
47
+ slices_statuses = checker.slices_present_statuses(resources, all_present: false)
48
+ slices_statuses.filter { |result| element_simple?(result[:path]) }
49
+ end
50
+
51
+ def extensions(checker, resources)
52
+ ms_extension_results = checker.extensions_present_statuses(resources, all_present: false)
53
+ normalized_ms_extension_results(ms_extension_results)
54
+ end
55
+
56
+ def normalized_ms_extension_results(ms_extension_results)
57
+ ms_extension_results.map do |result|
58
+ {
59
+ definition: result[:definition],
60
+ path: result[:definition][:id].split(':')[-1],
61
+ present: result[:present],
62
+ mandatory: false
63
+ }
64
+ end
65
+ end
66
+
67
+ def element_simple?(path)
68
+ !path.include?('.')
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AUPSTestKit
4
+ # Must Support identifier slices (IHI, DVA, Medicare) on a resource (e.g. Patient).
5
+ module BasicTestMsIdentifierSlicesModule
6
+ private
7
+
8
+ # Validates Must Support identifier slices (IHI, DVA, Medicare) on a resource (e.g. Patient).
9
+ # Two messages: (1) Must support identifier slices correctly populated; (2) At least one slice populated.
10
+ # Pass: all messages info or warning. No error level used.
11
+ #
12
+ # @param resource [Hash, FHIR::Model] The resource with identifier array (e.g. Patient)
13
+ # @param slices [Array<Hash>] Each hash has :name (String) and :system (String URL)
14
+ def validate_ms_identifier_slices_in_resource(resource, slices)
15
+ return unless resource.present?
16
+
17
+ slice_results = build_ms_identifier_slice_results(identifiers_from_resource(resource) || [], slices)
18
+ add_ms_identifier_slices_populated_message(slice_results)
19
+ add_ms_identifier_slices_at_least_one_message(slice_results)
20
+ end
21
+
22
+ def add_ms_identifier_slices_populated_message(slice_results)
23
+ lines = slice_results.map { |r| ms_identifier_slice_line_with_type(r) }
24
+ heading = '## List of Must Support identifier slices populated or missing'
25
+ body = ['Must support identifier slices correctly populated', heading, lines.join("\n\n")].join("\n\n")
26
+ add_message(slice_results.all? { |r| r[:identifier].present? } ? 'info' : 'warning', body)
27
+ end
28
+
29
+ def add_ms_identifier_slices_at_least_one_message(slice_results)
30
+ lines = slice_results.map { |r| ms_identifier_slice_line_system_only(r) }
31
+ heading = '## List of Must Support identifier slices populated or missing (system when populated)'
32
+ intro = 'At least one Must Support identifier slices is populated'
33
+ body = [intro, heading, lines.join("\n\n")].join("\n\n")
34
+ add_message(slice_results.any? { |r| r[:identifier].present? } ? 'info' : 'warning', body)
35
+ end
36
+
37
+ def build_ms_identifier_slice_results(identifiers, slices)
38
+ slices.map do |slice|
39
+ ident = find_identifier_by_system(identifiers, slice[:system])
40
+ { slice: slice, identifier: ident }
41
+ end
42
+ end
43
+
44
+ def ms_identifier_slice_line_with_type(result)
45
+ if result[:identifier].present?
46
+ type_str = identifier_type_display(result[:identifier])
47
+ "✅ Populated: **#{result[:slice][:name]}** — system: #{result[:slice][:system]}#{type_str}"
48
+ else
49
+ "⚠️ Missing: **#{result[:slice][:name]}**"
50
+ end
51
+ end
52
+
53
+ def ms_identifier_slice_line_system_only(result)
54
+ if result[:identifier].present?
55
+ "✅ Populated: **#{result[:slice][:name]}** — system: #{result[:slice][:system]}"
56
+ else
57
+ "⚠️ Missing: **#{result[:slice][:name]}**"
58
+ end
59
+ end
60
+ end
61
+ end