Class: AUCoreTestKit::Generator::SearchTestGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/au_core_test_kit/generator/search_test_generator.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(group_metadata, search_metadata, base_output_dir) ⇒ SearchTestGenerator

Returns a new instance of SearchTestGenerator.



22
23
24
25
26
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 22

def initialize(, , base_output_dir)
  self. = 
  self. = 
  self.base_output_dir = base_output_dir
end

Instance Attribute Details

#base_output_dirObject

Returns the value of attribute base_output_dir.



20
21
22
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 20

def base_output_dir
  @base_output_dir
end

#group_metadataObject

Returns the value of attribute group_metadata.



20
21
22
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 20

def 
  @group_metadata
end

#search_metadataObject

Returns the value of attribute search_metadata.



20
21
22
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 20

def 
  @search_metadata
end

Class Method Details

.generate(ig_metadata, base_output_dir) ⇒ Object



10
11
12
13
14
15
16
17
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 10

def generate(, base_output_dir)
  .groups
             .reject { |group| SpecialCases.exclude_group? group }
             .select { |group| group.searches.present? }
             .each do |group|
    group.searches.each { |search| new(group, search, base_output_dir).generate }
  end
end

Instance Method Details

#array_of_strings(array) ⇒ Object



222
223
224
225
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 222

def array_of_strings(array)
  quoted_strings = array.map { |element| "'#{element}'" }
  "[#{quoted_strings.join(', ')}]"
end

#base_output_file_nameObject



36
37
38
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 36

def base_output_file_name
  "#{class_name.underscore}.rb"
end

#class_nameObject



64
65
66
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 64

def class_name
  "#{Naming.upper_camel_case_for_profile()}#{search_title}SearchTest"
end

#conformance_expectationObject



76
77
78
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 76

def conformance_expectation
  [:expectation]
end

#descriptionObject



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 361

def description
  <<~DESCRIPTION.gsub(/\n{3,}/, "\n\n")
    A server #{conformance_expectation} support searching by
    #{search_param_name_string} on the #{resource_type} resource. This test
    will pass if resources are returned and match the search criteria. If
    none are returned, the test is skipped.

    #{medication_inclusion_description}
    #{reference_search_description}
    #{first_search_description}
    #{post_search_description}

    [AU Core Server CapabilityStatement](http://hl7.org.au/fhir/core/#{url_version}/CapabilityStatement-au-core-server.html)
  DESCRIPTION
end

#first_search?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 94

def first_search?
  .searches.first == 
end

#first_search_descriptionObject



331
332
333
334
335
336
337
338
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 331

def first_search_description
  return '' unless first_search?

  <<~FIRST_SEARCH_DESCRIPTION
    Because this is the first search of the sequence, resources in the
    response will be used for subsequent tests.
  FIRST_SEARCH_DESCRIPTION
end

#first_search_for_patient_by_patient_idObject



90
91
92
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 90

def first_search_for_patient_by_patient_id
  first_search? && resource_type == 'Patient' && [:names].first == '_id'
end

#fixed_value_search?Boolean

Returns:

  • (Boolean)


98
99
100
101
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 98

def fixed_value_search?
  first_search? && [:names] != ['patient'] &&
    !.delayed? && resource_type != 'Patient'
end

#fixed_value_search_param_nameObject



103
104
105
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 103

def fixed_value_search_param_name
  ([:names] - [:patient]).first
end

#generateObject



310
311
312
313
314
315
316
317
318
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 310

def generate
  FileUtils.mkdir_p(output_file_directory)
  File.open(output_file_name, 'w') { |f| f.write(output) }

  .add_test(
    id: test_id,
    file_name: base_output_file_name
  )
end

#includesObject



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 241

def includes
  # The medication SearchParameter does not exist for the MedicationStatement
  # and MedicationRequest resources in the current version of the IG,
  # we shall keep special cases to provide functionality for the "_include" tests.
  # https://jira.csiro.au/browse/ST-400
  special_cases = {
    'MedicationRequest:medication' => { 'parameter' => 'MedicationRequest:medication', 'target_resource' => 'Medication', 'paths' => ['medicationReference'] },
    'MedicationStatement:medication' => { 'parameter' => 'MedicationStatement:medication', 'target_resource' => 'Medication', 'paths' => ['medicationReference'] }
  }
  include_params_list = .include_params
  search_definitions = .search_definitions

  include_params_list.map do |include_param|
    if special_cases.key?(include_param)
      puts "Special case for include_param: #{include_param}"

      return [special_cases[include_param]]
    end

    target_resource = ''
    paths = ''
    search_definitions.each_key do |search_def_key|
      current_search_def_path = search_definitions[search_def_key]
      next unless current_search_def_path[:full_paths].first.split('.') == include_param.split(':')

      target_resource = current_search_def_path[:target_resource]
      paths = current_search_def_path[:paths]
      break
    end

    {
      'parameter' => include_param,
      'target_resource' => target_resource,
      'paths' => paths
    }
  end
end

#medication_inclusion_descriptionObject



340
341
342
343
344
345
346
347
348
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 340

def medication_inclusion_description
  return '' unless test_medication_inclusion?

  <<~MEDICATION_INCLUSION_DESCRIPTION
    If any #{resource_type} resources use external references to
    Medications, the search will be repeated with
    `_include=#{resource_type}:medication`.
  MEDICATION_INCLUSION_DESCRIPTION
end

#module_nameObject



68
69
70
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 68

def module_name
  "AUCore#{.reformatted_version.upcase}"
end

#needs_patient_id?Boolean

Returns:

  • (Boolean)


111
112
113
114
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 111

def needs_patient_id?
  [:names].include?('patient') ||
    (resource_type == 'Patient' && [:names].include?('_id'))
end

#optional?Boolean

Returns:

  • (Boolean)


140
141
142
143
144
145
146
147
148
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 140

def optional?
  # NOTE: Original behavior changed because we need a clear
  # expectation of the search parameters in tests. If in the
  # CapabilityStatement resource we have SHALL it should be
  # required in the tests.
  # https://github.com/hl7au/au-fhir-core-inferno/issues/47
  # conformance_expectation != 'SHALL' || !search_metadata[:must_support_or_mandatory]
  conformance_expectation != 'SHALL'
end

#optional_multiple_and_search_paramsObject



196
197
198
199
200
201
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 196

def optional_multiple_and_search_params
  @optional_multiple_and_search_params ||=
    search_param_names.select do |name|
      search_definition(name)[:multiple_and] == 'SHOULD'
    end
end

#optional_multiple_and_search_params_stringObject



210
211
212
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 210

def optional_multiple_and_search_params_string
  array_of_strings(optional_multiple_and_search_params)
end

#optional_multiple_or_search_paramsObject



181
182
183
184
185
186
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 181

def optional_multiple_or_search_params
  @optional_multiple_or_search_params ||=
    search_param_names.select do |name|
      search_definition(name)[:multiple_or] == 'SHOULD'
    end
end

#optional_multiple_or_search_params_stringObject



192
193
194
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 192

def optional_multiple_or_search_params_string
  array_of_strings(optional_multiple_or_search_params)
end

#outputObject



32
33
34
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 32

def output
  @output ||= ERB.new(template).result(binding)
end

#output_file_directoryObject



40
41
42
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 40

def output_file_directory
  File.join(base_output_dir, profile_identifier)
end

#output_file_nameObject



44
45
46
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 44

def output_file_name
  File.join(output_file_directory, base_output_file_name)
end

#path_for_value(path) ⇒ Object



124
125
126
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 124

def path_for_value(path)
  path == 'class' ? 'local_class' : path
end

#possible_status_search?Boolean

Returns:

  • (Boolean)


158
159
160
161
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 158

def possible_status_search?
  [:names].none? { |name| name.include? 'status' } &&
    .search_definitions.keys.any? { |key| key.to_s.include? 'status' }
end

#post_search_descriptionObject



350
351
352
353
354
355
356
357
358
359
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 350

def post_search_description
  return '' unless test_post_search?

  <<~POST_SEARCH_DESCRIPTION
    Additionally, this test will check that GET and POST search methods
    return the same number of results. Search by POST is required by the
    FHIR R4 specification, and these tests interpret search by GET as a
    requirement of AU Core #{.version}.
  POST_SEARCH_DESCRIPTION
end

#profile_identifierObject



48
49
50
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 48

def profile_identifier
  Naming.snake_case_for_profile()
end

#reference_search_descriptionObject



320
321
322
323
324
325
326
327
328
329
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 320

def reference_search_description
  return '' unless test_reference_variants?

  <<~REFERENCE_SEARCH_DESCRIPTION
    This test verifies that the server supports searching by reference using
    the form `#{search_param_names.first}=[id]` as well as `#{search_param_names.first}=#{search_param_names.first.capitalize}/[id]`. The two
    different forms are expected to return the same number of results. AU
    Core requires that both forms are supported by AU Core responders.
  REFERENCE_SEARCH_DESCRIPTION
end

#required_comparatorsObject



132
133
134
135
136
137
138
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 132

def required_comparators
  @required_comparators ||=
    search_param_names.each_with_object({}) do |name, comparators|
      required_comparators = required_comparators_for_param(name)
      comparators[name] = required_comparators if required_comparators.present?
    end
end

#required_comparators_for_param(name) ⇒ Object



128
129
130
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 128

def required_comparators_for_param(name)
  search_definition(name)[:comparators].select { |_comparator, expectation| expectation == 'SHALL' }
end

#required_comparators_stringObject



218
219
220
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 218

def required_comparators_string
  array_of_strings(required_comparators.keys)
end

#required_multiple_and_search_paramsObject



203
204
205
206
207
208
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 203

def required_multiple_and_search_params
  @required_multiple_and_search_params ||=
    search_param_names.select do |name|
      search_definition(name)[:multiple_and] == 'SHALL'
    end
end

#required_multiple_and_search_params_stringObject



214
215
216
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 214

def required_multiple_and_search_params_string
  array_of_strings(required_multiple_and_search_params)
end

#required_multiple_or_search_paramsObject



174
175
176
177
178
179
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 174

def required_multiple_or_search_params
  @required_multiple_or_search_params ||=
    search_param_names.select do |name|
      search_definition(name)[:multiple_or] == 'SHALL'
    end
end

#required_multiple_or_search_params_stringObject



188
189
190
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 188

def required_multiple_or_search_params_string
  array_of_strings(required_multiple_or_search_params)
end

#resource_typeObject



72
73
74
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 72

def resource_type
  .resource
end

#saves_delayed_references?Boolean

Returns:

  • (Boolean)


154
155
156
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 154

def saves_delayed_references?
  first_search? && .delayed_references.present?
end

#search_definition(name) ⇒ Object



150
151
152
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 150

def search_definition(name)
  .search_definitions[name.to_sym]
end

#search_identifierObject



56
57
58
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 56

def search_identifier
  [:names].join('_').tr('-', '_')
end

#search_methodObject



377
378
379
380
381
382
383
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 377

def search_method
  if [:names].first == 'identifier' && .name == 'au_core_patient'
    'run_search_test_with_system'
  else
    'run_search_test'
  end
end

#search_param_name_stringObject



107
108
109
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 107

def search_param_name_string
  [:names].join(' + ')
end

#search_param_namesObject



116
117
118
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 116

def search_param_names
  search_params.map { |param| param[:name] }
end

#search_param_names_arrayObject



120
121
122
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 120

def search_param_names_array
  array_of_strings(search_param_names)
end

#search_paramsObject



80
81
82
83
84
85
86
87
88
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 80

def search_params
  @search_params ||=
    [:names].map do |name|
      {
        name:,
        path: search_definition(name)[:path]
      }
    end
end

#search_propertiesObject



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 279

def search_properties
  {}.tap do |properties|
    properties[:first_search] = 'true' if first_search?
    properties[:fixed_value_search] = 'true' if fixed_value_search?
    properties[:resource_type] = "'#{resource_type}'"
    properties[:search_param_names] = search_param_names_array
    properties[:saves_delayed_references] = 'true' if saves_delayed_references?
    properties[:possible_status_search] = 'true' if possible_status_search?
    properties[:test_medication_inclusion] = 'true' if test_medication_inclusion?
    properties[:includes] = includes if .include_params.present?
    properties[:token_search_params] = token_search_params_string if token_search_params.present?
    properties[:test_reference_variants] = 'true' if test_reference_variants?
    properties[:params_with_comparators] = required_comparators_string if required_comparators.present?
    properties[:test_post_search] = 'true' if first_search?
    properties[:first_search_for_patient_by_patient_id] = 'true' if first_search_for_patient_by_patient_id
  end
end

#search_test_properties_stringObject



304
305
306
307
308
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 304

def search_test_properties_string
  search_properties
    .map { |key, value| "#{' ' * 8}#{key}: #{value}" }
    .join(",\n")
end

#search_titleObject



60
61
62
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 60

def search_title
  search_identifier.camelize
end

#templateObject



28
29
30
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 28

def template
  @template ||= File.read(File.join(__dir__, 'templates', 'search.rb.erb'))
end

#test_idObject



52
53
54
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 52

def test_id
  "au_core_#{.reformatted_version}_#{profile_identifier}_#{search_identifier}_search_test"
end

#test_medication_inclusion?Boolean

Returns:

  • (Boolean)


233
234
235
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 233

def test_medication_inclusion?
  %w[MedicationRequest MedicationDispense].include?(resource_type)
end

#test_post_search?Boolean

Returns:

  • (Boolean)


237
238
239
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 237

def test_post_search?
  first_search?
end

#test_reference_variants?Boolean

Returns:

  • (Boolean)


227
228
229
230
231
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 227

def test_reference_variants?
  return true if resource_type == 'PractitionerRole' && search_param_names.include?('practitioner')

  first_search? && search_param_names.include?('patient')
end

#token_search_paramsObject



163
164
165
166
167
168
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 163

def token_search_params
  @token_search_params ||=
    search_param_names.select do |name|
      %w[Identifier CodeableConcept Coding].include? .search_definitions[name.to_sym][:type]
    end
end

#token_search_params_stringObject



170
171
172
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 170

def token_search_params_string
  array_of_strings(token_search_params)
end

#url_versionObject



297
298
299
300
301
302
# File 'lib/au_core_test_kit/generator/search_test_generator.rb', line 297

def url_version
  case .version
  when 'v0.3.0-ballot'
    '0.3.0-ballot'
  end
end