soaspec 0.2.24 → 0.2.25

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 (83) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +15 -15
  3. data/.gitlab-ci.yml +51 -33
  4. data/.rspec +3 -3
  5. data/.rubocop.yml +2 -2
  6. data/CODE_OF_CONDUCT.md +74 -74
  7. data/ChangeLog +588 -577
  8. data/Gemfile +6 -6
  9. data/LICENSE.txt +21 -21
  10. data/README.md +230 -230
  11. data/Rakefile +50 -42
  12. data/Todo.md +15 -15
  13. data/exe/soaspec +137 -123
  14. data/exe/xml_to_yaml_file +42 -42
  15. data/lib/soaspec.rb +103 -101
  16. data/lib/soaspec/core_ext/hash.rb +42 -35
  17. data/lib/soaspec/cucumber/generic_steps.rb +85 -85
  18. data/lib/soaspec/demo.rb +4 -4
  19. data/lib/soaspec/exchange/exchange.rb +117 -111
  20. data/lib/soaspec/exchange/exchange_extractor.rb +83 -83
  21. data/lib/soaspec/exchange/exchange_properties.rb +26 -26
  22. data/lib/soaspec/exchange/exchange_repeater.rb +19 -19
  23. data/lib/soaspec/exchange/request_builder.rb +68 -68
  24. data/lib/soaspec/exchange/variable_storer.rb +22 -22
  25. data/lib/soaspec/exchange_handlers/exchange_handler.rb +130 -126
  26. data/lib/soaspec/exchange_handlers/handler_accessors.rb +130 -130
  27. data/lib/soaspec/exchange_handlers/request/rest_request.rb +49 -0
  28. data/lib/soaspec/exchange_handlers/request/soap_request.rb +39 -0
  29. data/lib/soaspec/exchange_handlers/response_extractor.rb +82 -82
  30. data/lib/soaspec/exchange_handlers/rest_exchanger_factory.rb +109 -109
  31. data/lib/soaspec/exchange_handlers/rest_handler.rb +287 -259
  32. data/lib/soaspec/exchange_handlers/rest_methods.rb +63 -44
  33. data/lib/soaspec/exchange_handlers/rest_parameters.rb +90 -86
  34. data/lib/soaspec/exchange_handlers/rest_parameters_defaults.rb +40 -21
  35. data/lib/soaspec/exchange_handlers/soap_handler.rb +239 -235
  36. data/lib/soaspec/exe_helpers.rb +92 -92
  37. data/lib/soaspec/generate_server.rb +46 -37
  38. data/lib/soaspec/generator/.rspec.erb +5 -5
  39. data/lib/soaspec/generator/.travis.yml.erb +5 -5
  40. data/lib/soaspec/generator/Gemfile.erb +8 -8
  41. data/lib/soaspec/generator/README.md.erb +29 -29
  42. data/lib/soaspec/generator/Rakefile.erb +19 -19
  43. data/lib/soaspec/generator/config/data/default.yml.erb +2 -2
  44. data/lib/soaspec/generator/css/bootstrap.css +6833 -6833
  45. data/lib/soaspec/generator/features/support/env.rb.erb +3 -0
  46. data/lib/soaspec/generator/generate_exchange.html.erb +47 -35
  47. data/lib/soaspec/generator/lib/blz_service.rb.erb +26 -26
  48. data/lib/soaspec/generator/lib/dynamic_class_content.rb.erb +12 -12
  49. data/lib/soaspec/generator/lib/new_rest_service.rb.erb +56 -51
  50. data/lib/soaspec/generator/lib/new_soap_service.rb.erb +29 -29
  51. data/lib/soaspec/generator/lib/package_service.rb.erb +2 -2
  52. data/lib/soaspec/generator/lib/shared_example.rb.erb +8 -8
  53. data/lib/soaspec/generator/spec/dynamic_soap_spec.rb.erb +12 -12
  54. data/lib/soaspec/generator/spec/rest_spec.rb.erb +9 -9
  55. data/lib/soaspec/generator/spec/soap_spec.rb.erb +51 -51
  56. data/lib/soaspec/generator/spec/spec_helper.rb.erb +23 -23
  57. data/lib/soaspec/generator/template/soap_template.xml +6 -6
  58. data/lib/soaspec/indifferent_hash.rb +7 -7
  59. data/lib/soaspec/interpreter.rb +39 -39
  60. data/lib/soaspec/matchers.rb +114 -114
  61. data/lib/soaspec/not_found_errors.rb +13 -13
  62. data/lib/soaspec/o_auth2.rb +128 -128
  63. data/lib/soaspec/soaspec_shared_examples.rb +24 -24
  64. data/lib/soaspec/spec_logger.rb +122 -121
  65. data/lib/soaspec/template_reader.rb +28 -28
  66. data/lib/soaspec/test_server/bank.wsdl +90 -90
  67. data/lib/soaspec/test_server/get_bank.rb +164 -164
  68. data/lib/soaspec/test_server/id_manager.rb +39 -39
  69. data/lib/soaspec/test_server/invoices.rb +27 -27
  70. data/lib/soaspec/test_server/namespace.xml +14 -14
  71. data/lib/soaspec/test_server/note.xml +5 -5
  72. data/lib/soaspec/test_server/puppy_service.rb +19 -19
  73. data/lib/soaspec/test_server/test_attribute.rb +12 -12
  74. data/lib/soaspec/test_server/test_namespace.rb +12 -12
  75. data/lib/soaspec/version.rb +4 -4
  76. data/lib/soaspec/virtual_server.rb +174 -174
  77. data/lib/soaspec/wait.rb +41 -41
  78. data/lib/soaspec/wsdl_generator.rb +215 -215
  79. data/soaspec.gemspec +56 -53
  80. data/test.wsdl +116 -116
  81. data/test.xml +10 -10
  82. data/test_wsdl.rb +41 -41
  83. metadata +38 -6
@@ -1,130 +1,130 @@
1
- module Soaspec
2
- # Describes methods test handlers use to easily set attributes
3
- # Some are included in 'success scenarios' and to configure the request sent
4
- module HandlerAccessors
5
- # Defines expected_mandatory_elements method used in 'success_scenario' shared examples
6
- # to indicate certain elements must be present
7
- # @param [Array] elements Array of symbols specifying expected element names for 'success scenario' in snakecase
8
- #
9
- # @example Inside class
10
- # mandatory_elements :GetWeatherResult
11
- #
12
- # Or for a list
13
- #
14
- # @example Inside class
15
- # mandatory_elements [:GetWeatherResult, :GetResultStatus]
16
- #
17
- # In test
18
- # describe Exchange(:name) do
19
- # it_behaves_like 'success scenario' # Includes checks for mandatory elements
20
- # end
21
- def mandatory_elements(elements)
22
- define_method('expected_mandatory_elements') do
23
- return [elements] if elements.is_a?(String) || elements.is_a?(Symbol)
24
-
25
- elements
26
- end
27
- end
28
-
29
- # Defines mandatory xpaths value pairs to be included in 'success scenario' shared example
30
- #
31
- # @example Inside class
32
- # mandatory_xpath_values '//xmlns:GetWeatherResult' => 'Data Not Found'
33
- #
34
- # @example In test
35
- # describe Exchange(:name) do
36
- # it_behaves_like 'success scenario' # Includes xpath pair validation
37
- # end
38
- #
39
- # @param [Hash] xpath_value_pairs Hash of element => expected value that must appear
40
- # in a successful response body
41
- def mandatory_xpath_values(xpath_value_pairs)
42
- raise ArgumentError('Hash of {xpath => expected values} expected ') unless xpath_value_pairs.is_a? Hash
43
-
44
- define_method('expected_mandatory_xpath_values') { xpath_value_pairs }
45
- end
46
-
47
- # Defines mandatory json path value pairs to be included in 'success scenario' shared example
48
- #
49
- # @example Inside class
50
- # mandatory_json_values '$..GetWeatherResult' => 'Found'
51
- #
52
- # @example In test
53
- # describe Exchange(:name) do
54
- # it_behaves_like 'success scenario' # Includes json pair validation
55
- # end
56
- #
57
- # @param [Hash] json_value_pairs Hash of element => expected value that must appear
58
- # in a successful response body
59
- def mandatory_json_values(json_value_pairs)
60
- raise ArgumentError("Hash of {'jsonpath' => expected values} expected") unless json_value_pairs.is_a? Hash
61
-
62
- define_method('expected_mandatory_json_values') { json_value_pairs }
63
- end
64
-
65
- # Links a particular path to a meaningful method that can be accessed from Exchange class.
66
- # This will use the 'value_from_path' method which
67
- # should be implemented by each ExchangeHandler
68
- # @param [String, Symbol] name Method name used to access element
69
- # @param [String, Symbol] path Path to find object (e.g, XPath, JSONPath).
70
- # For JSONPath a ',' can be put to get an element either path
71
- def element(name, path)
72
- define_method("__custom_path_#{name}") do |response|
73
- value_from_path(response, path.to_s)
74
- end
75
- end
76
-
77
- # Links an attribute to a meaningful method that can be accessed from Exchange class.
78
- # This will use the 'value_from_path' method which
79
- # should be implemented by each ExchangeHandler
80
- # @param [String, Symbol] name Method name used to access attribute
81
- # @param [String, nil, Hash] attribute Attribute name to extract from xml. If not set, this will default to @name
82
- def attribute(name, attribute = nil)
83
- attribute_used = attribute || name.to_s
84
- define_method("__custom_path_#{name}") do |response|
85
- value_from_path(response, 'implicit', attribute: attribute_used)
86
- end
87
- end
88
-
89
- # All xpath will be done with XML that is converted to lower case
90
- # You must then use lower case in the xpath's to obtain the desired values
91
- # @param [Boolean] set Whether to convert all xml in response to lower case before performing XPath
92
- def convert_to_lower(set)
93
- return unless set
94
-
95
- define_method('convert_to_lower?') { true }
96
- end
97
-
98
- # Whether to remove namespaces from response in Xpath assertion automatically
99
- # For why this may not be a good thing in general see
100
- # http://tenderlovemaking.com/2009/04/23/namespaces-in-xml.html
101
- # This will be overridden if xpath has a ':' in it
102
- # @param [Boolean] set Whether to strip namespaces form XML response
103
- def strip_namespaces(set)
104
- return unless set
105
-
106
- # Whether to remove namespaces in xpath assertion automatically
107
- define_method('strip_namespaces?') { true }
108
- end
109
-
110
- # Set the default hash representing data to be used in making a request
111
- # This will set the @request_option instance variable too
112
- # @param [Hash] hash Default hash of request
113
- def default_hash(hash)
114
- define_method('default_hash_value') do
115
- @request_option = :hash
116
- Soaspec.always_use_keys? ? hash.transform_keys_to_symbols : hash
117
- end
118
- end
119
-
120
- # Set the request option type and the template name
121
- # Erb is used to parse the template file, executing Ruby code in `<%= %>` blocks to work out the final request
122
- # @param [String] name Name of file inside 'template' folder excluding extension
123
- def template_name(name)
124
- define_method('template_name_value') do
125
- @request_option = :template
126
- name
127
- end
128
- end
129
- end
130
- end
1
+ module Soaspec
2
+ # Describes methods test handlers use to easily set attributes
3
+ # Some are included in 'success scenarios' and to configure the request sent
4
+ module HandlerAccessors
5
+ # Defines expected_mandatory_elements method used in 'success_scenario' shared examples
6
+ # to indicate certain elements must be present
7
+ # @param [Array] elements Array of symbols specifying expected element names for 'success scenario' in snakecase
8
+ #
9
+ # @example Inside class
10
+ # mandatory_elements :GetWeatherResult
11
+ #
12
+ # Or for a list
13
+ #
14
+ # @example Inside class
15
+ # mandatory_elements [:GetWeatherResult, :GetResultStatus]
16
+ #
17
+ # In test
18
+ # describe Exchange(:name) do
19
+ # it_behaves_like 'success scenario' # Includes checks for mandatory elements
20
+ # end
21
+ def mandatory_elements(elements)
22
+ define_method('expected_mandatory_elements') do
23
+ return [elements] if elements.is_a?(String) || elements.is_a?(Symbol)
24
+
25
+ elements
26
+ end
27
+ end
28
+
29
+ # Defines mandatory xpaths value pairs to be included in 'success scenario' shared example
30
+ #
31
+ # @example Inside class
32
+ # mandatory_xpath_values '//xmlns:GetWeatherResult' => 'Data Not Found'
33
+ #
34
+ # @example In test
35
+ # describe Exchange(:name) do
36
+ # it_behaves_like 'success scenario' # Includes xpath pair validation
37
+ # end
38
+ #
39
+ # @param [Hash] xpath_value_pairs Hash of element => expected value that must appear
40
+ # in a successful response body
41
+ def mandatory_xpath_values(xpath_value_pairs)
42
+ raise ArgumentError('Hash of {xpath => expected values} expected ') unless xpath_value_pairs.is_a? Hash
43
+
44
+ define_method('expected_mandatory_xpath_values') { xpath_value_pairs }
45
+ end
46
+
47
+ # Defines mandatory json path value pairs to be included in 'success scenario' shared example
48
+ #
49
+ # @example Inside class
50
+ # mandatory_json_values '$..GetWeatherResult' => 'Found'
51
+ #
52
+ # @example In test
53
+ # describe Exchange(:name) do
54
+ # it_behaves_like 'success scenario' # Includes json pair validation
55
+ # end
56
+ #
57
+ # @param [Hash] json_value_pairs Hash of element => expected value that must appear
58
+ # in a successful response body
59
+ def mandatory_json_values(json_value_pairs)
60
+ raise ArgumentError("Hash of {'jsonpath' => expected values} expected") unless json_value_pairs.is_a? Hash
61
+
62
+ define_method('expected_mandatory_json_values') { json_value_pairs }
63
+ end
64
+
65
+ # Links a particular path to a meaningful method that can be accessed from Exchange class.
66
+ # This will use the 'value_from_path' method which
67
+ # should be implemented by each ExchangeHandler
68
+ # @param [String, Symbol] name Method name used to access element
69
+ # @param [String, Symbol] path Path to find object (e.g, XPath, JSONPath).
70
+ # For JSONPath a ',' can be put to get an element either path
71
+ def element(name, path)
72
+ define_method("__custom_path_#{name}") do |response|
73
+ value_from_path(response, path.to_s)
74
+ end
75
+ end
76
+
77
+ # Links an attribute to a meaningful method that can be accessed from Exchange class.
78
+ # This will use the 'value_from_path' method which
79
+ # should be implemented by each ExchangeHandler
80
+ # @param [String, Symbol] name Method name used to access attribute
81
+ # @param [String, nil, Hash] attribute Attribute name to extract from xml. If not set, this will default to @name
82
+ def attribute(name, attribute = nil)
83
+ attribute_used = attribute || name.to_s
84
+ define_method("__custom_path_#{name}") do |response|
85
+ value_from_path(response, 'implicit', attribute: attribute_used)
86
+ end
87
+ end
88
+
89
+ # All xpath will be done with XML that is converted to lower case
90
+ # You must then use lower case in the xpath's to obtain the desired values
91
+ # @param [Boolean] set Whether to convert all xml in response to lower case before performing XPath
92
+ def convert_to_lower(set)
93
+ return unless set
94
+
95
+ define_method('convert_to_lower?') { true }
96
+ end
97
+
98
+ # Whether to remove namespaces from response in Xpath assertion automatically
99
+ # For why this may not be a good thing in general see
100
+ # http://tenderlovemaking.com/2009/04/23/namespaces-in-xml.html
101
+ # This will be overridden if xpath has a ':' in it
102
+ # @param [Boolean] set Whether to strip namespaces form XML response
103
+ def strip_namespaces(set)
104
+ return unless set
105
+
106
+ # Whether to remove namespaces in xpath assertion automatically
107
+ define_method('strip_namespaces?') { true }
108
+ end
109
+
110
+ # Set the default hash representing data to be used in making a request
111
+ # This will set the @request_option instance variable too
112
+ # @param [Hash] hash Default hash of request
113
+ def default_hash(hash)
114
+ define_method('default_hash_value') do
115
+ @request_option = :hash
116
+ Soaspec.always_use_keys? ? hash.transform_keys_to_symbols : hash
117
+ end
118
+ end
119
+
120
+ # Set the request option type and the template name
121
+ # Erb is used to parse the template file, executing Ruby code in `<%= %>` blocks to work out the final request
122
+ # @param [String] name Name of file inside 'template' folder excluding extension
123
+ def template_name(name)
124
+ define_method('template_name_value') do
125
+ @request_option = :template
126
+ name
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,49 @@
1
+ module Soaspec
2
+ # Models a request made to a REST API
3
+ class RestRequest
4
+ # @example GET method
5
+ # :get
6
+ # @return [Symbol] REST method used
7
+ attr_accessor :method
8
+ # @example JSON body
9
+ # {"test":5}
10
+ # @return [String] Body of request sent
11
+ attr_accessor :body
12
+ # @return [String] Name given to test to describe it
13
+ attr_accessor :test_name
14
+ # @return [String] User used in basic auth
15
+ attr_accessor :basic_auth_user
16
+ # @return [String] Password used in basic auth
17
+ attr_accessor :basic_auth_password
18
+ # @return [String] Url appended to base_url
19
+ attr_accessor :suburl
20
+ # @return [Hash] Miscellaneous parameters
21
+ attr_accessor :other_params
22
+ # Headers. Keys that are `symbols` will be converted from `snake_case` to `Word-Word2`
23
+ # @return [Hash] Headers sent as part of request
24
+ attr_accessor :headers
25
+
26
+ def initialize(overall, options, body)
27
+ overall_params = overall.dup # Must duplicate hash as deletion occurring
28
+ self.body = body
29
+ self.method = overall_params.delete(:method)
30
+ self.suburl = overall_params.delete(:suburl)
31
+ self.test_name = overall_params.delete(:name)
32
+ self.other_params = overall_params
33
+ self.basic_auth_user = options[:user]
34
+ self.basic_auth_password = options[:password]
35
+ self.headers = options[:headers]
36
+ end
37
+
38
+ # @param [String, Symbol] value Message to send to object retrieving a value
39
+ # @return [Object] Result of retrieving value
40
+ def [](value)
41
+ self.send(value)
42
+ end
43
+
44
+ # @return [String] Show inspection of all parameters
45
+ def to_s
46
+ inspect
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ module Soaspec
2
+ # Models a request made to a SOAP API
3
+ class SoapRequest
4
+ # @example SOAP operation
5
+ # :login
6
+ # @return [Symbol] SOAP operation used
7
+ attr_accessor :operation
8
+ # Hash representing what will be sent to Savon. Either the exact xml (if using a template)
9
+ # or a message Hash that will be converted to XML by Savon
10
+ # @example
11
+ # { xml: "<env:Envelope xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ...</env:Body>\n</env:Envelope> " }
12
+ # @return [Hash] Body of request sent
13
+ attr_accessor :body
14
+ # @return [Symbol] Method of building the request (:hash, :template)
15
+ attr_accessor :request_option
16
+ # @return [String] Name given to test to describe it
17
+ attr_accessor :test_name
18
+
19
+ # @param [Symbol] operation Soap operation used
20
+ # @param [Hash] body Hash with method of SOAP generated contained
21
+ # @param [Symbol] request_option Method of building the request (:hash, :template)
22
+ def initialize(operation, body, request_option)
23
+ self.body = body
24
+ self.operation = operation
25
+ self.request_option = request_option
26
+ end
27
+
28
+ # @param [String, Symbol] value Message to send to object retrieving a value
29
+ # @return [Object] Result of retrieving value
30
+ def [](value)
31
+ self.send(value)
32
+ end
33
+
34
+ # @return [String] Show inspection of all parameters
35
+ def to_s
36
+ inspect
37
+ end
38
+ end
39
+ end
@@ -1,82 +1,82 @@
1
- module Soaspec
2
- # Enables extracting a response according to type / path
3
- module ResponseExtractor
4
- # Convert XML or JSON response into a Hash. Doesn't accept empty body
5
- # @param [String] response Response as a String (either in XML or JSON)
6
- # @return [Hash] Extracted Hash from response
7
- def extract_hash(response)
8
- raise NoElementAtPath, "Empty Body. Can't assert on it" if response.body.empty?
9
-
10
- case Interpreter.response_type_for response
11
- when :xml then parse_xml(response.body.to_s)
12
- when :json
13
- converted = JSON.parse(response.body)
14
- return converted.transform_keys_to_symbols if converted.is_a? Hash
15
- return converted.map!(&:transform_keys_to_symbols) if converted.is_a? Array
16
-
17
- raise 'Incorrect Type produced ' + converted.class
18
- else
19
- raise "Neither XML nor JSON detected. It is #{type}. Don't know how to parse It is #{response.body}"
20
- end
21
- end
22
-
23
- # @param [Object] response Response object
24
- # @return [Hash] Hash representing response body
25
- def to_hash(response)
26
- case Interpreter.response_type_for(response)
27
- when :xml then IndifferentHash.new(parse_xml(response.body.to_s))
28
- when :json
29
- IndifferentHash.new(JSON.parse(response.body.to_s))
30
- else
31
- raise "Unable to interpret type of #{response.body}"
32
- end
33
- end
34
-
35
- private
36
-
37
- # @param [String] xml XML to convert
38
- # @return [Hash] Hash representing XML
39
- def parse_xml(xml)
40
- parser = Nori.new(strip_namespaces: strip_namespaces?, convert_tags_to: ->(tag) { tag.snakecase.to_sym })
41
- parser.parse(xml)
42
- end
43
-
44
- # This enables shortcut xpaths to be used. If no '/' is given, one is appended to the start of the path
45
- # If attribute value is set then this is also adjusted
46
- # @return [String] New Xpath adjusted according to any add ons
47
- def prefix_xpath(xpath, attribute)
48
- xpath = "//*[@#{attribute}]" unless attribute.nil?
49
- if xpath[0] != '/'
50
- xpath = convert_to_pascal_case(xpath) if pascal_keys?
51
- xpath = '//' + xpath
52
- end
53
- xpath
54
- end
55
-
56
- # Convert snakecase to PascalCase
57
- # @return [String] PascalCase converted path
58
- def convert_to_pascal_case(key)
59
- return key if /[[:upper:]]/ =~ key[0] # If first character already capital, don't do conversion
60
-
61
- key.split('_').map(&:capitalize).join
62
- end
63
-
64
- # Find element with name specified or pascal case equivalent
65
- # @return [String] String to find paths with pascal converted or given path
66
- def add_pascal_path(json_path)
67
- return json_path unless pascal_keys?
68
-
69
- json_path.split(',').collect do |sub_path|
70
- "#{sub_path},#{convert_to_pascal_case(sub_path)}"
71
- end.join(',')
72
- end
73
-
74
- # @param [String] json_path Path set from Exchange
75
- # @return [String] JSON Path
76
- def prefix_json_path(json_path)
77
- return json_path if json_path[0] == '$'
78
-
79
- "$..#{json_path}"
80
- end
81
- end
82
- end
1
+ module Soaspec
2
+ # Enables extracting a response according to type / path
3
+ module ResponseExtractor
4
+ # Convert XML or JSON response into a Hash. Doesn't accept empty body
5
+ # @param [String] response Response as a String (either in XML or JSON)
6
+ # @return [Hash] Extracted Hash from response
7
+ def extract_hash(response)
8
+ raise NoElementAtPath, "Empty Body. Can't assert on it" if response.body.empty?
9
+
10
+ case Interpreter.response_type_for response
11
+ when :xml then parse_xml(response.body.to_s)
12
+ when :json
13
+ converted = JSON.parse(response.body)
14
+ return converted.transform_keys_to_symbols if converted.is_a? Hash
15
+ return converted.map!(&:transform_keys_to_symbols) if converted.is_a? Array
16
+
17
+ raise 'Incorrect Type produced ' + converted.class
18
+ else
19
+ raise "Neither XML nor JSON detected. It is #{type}. Don't know how to parse It is #{response.body}"
20
+ end
21
+ end
22
+
23
+ # @param [Object] response Response object
24
+ # @return [Hash] Hash representing response body
25
+ def to_hash(response)
26
+ case Interpreter.response_type_for(response)
27
+ when :xml then IndifferentHash.new(parse_xml(response.body.to_s))
28
+ when :json
29
+ IndifferentHash.new(JSON.parse(response.body.to_s))
30
+ else
31
+ raise "Unable to interpret type of #{response.body}"
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ # @param [String] xml XML to convert
38
+ # @return [Hash] Hash representing XML
39
+ def parse_xml(xml)
40
+ parser = Nori.new(strip_namespaces: strip_namespaces?, convert_tags_to: ->(tag) { tag.snakecase.to_sym })
41
+ parser.parse(xml)
42
+ end
43
+
44
+ # This enables shortcut xpaths to be used. If no '/' is given, one is appended to the start of the path
45
+ # If attribute value is set then this is also adjusted
46
+ # @return [String] New Xpath adjusted according to any add ons
47
+ def prefix_xpath(xpath, attribute)
48
+ xpath = "//*[@#{attribute}]" unless attribute.nil?
49
+ if xpath[0] != '/'
50
+ xpath = convert_to_pascal_case(xpath) if pascal_keys?
51
+ xpath = '//' + xpath
52
+ end
53
+ xpath
54
+ end
55
+
56
+ # Convert snakecase to PascalCase
57
+ # @return [String] PascalCase converted path
58
+ def convert_to_pascal_case(key)
59
+ return key if /[[:upper:]]/ =~ key[0] # If first character already capital, don't do conversion
60
+
61
+ key.split('_').map(&:capitalize).join
62
+ end
63
+
64
+ # Find element with name specified or pascal case equivalent
65
+ # @return [String] String to find paths with pascal converted or given path
66
+ def add_pascal_path(json_path)
67
+ return json_path unless pascal_keys?
68
+
69
+ json_path.split(',').collect do |sub_path|
70
+ "#{sub_path},#{convert_to_pascal_case(sub_path)}"
71
+ end.join(',')
72
+ end
73
+
74
+ # @param [String] json_path Path set from Exchange
75
+ # @return [String] JSON Path
76
+ def prefix_json_path(json_path)
77
+ return json_path if json_path[0] == '$'
78
+
79
+ "$..#{json_path}"
80
+ end
81
+ end
82
+ end