soaspec 0.0.19 → 0.0.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,64 +1,64 @@
1
-
2
- require 'xmlsimple'
3
- require 'yaml'
4
- require 'fileutils'
5
-
6
- default_output_file = 'output.yml'
7
-
8
- # Create file if not present. If present but different give warning
9
- def create_file(options)
10
- filename = options[:filename]
11
- raise 'Need to pass filename' unless filename
12
- content = options[:content]
13
- raise 'Need to pass contents to insert into file' unless content
14
- if File.exist? filename
15
- old_content = File.read(filename)
16
- if old_content != content
17
- warn "!! #{filename} already exists and differs from template"
18
- end
19
- else
20
- File.open(filename, 'w') do |f|
21
- f.puts content
22
- end
23
- puts 'Created: ' + filename
24
- end
25
- end
26
-
27
- # Convert key in camelcase to underscore separated (snakecase)
28
- def underscore_key(key)
29
- key.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
30
- .gsub(/([a-z\d])([A-Z])/,'\1_\2')
31
- .tr('-', '_')
32
- .gsub(/\s/, '_')
33
- .gsub(/__+/, '_')
34
- .downcase
35
- end
36
-
37
- # For all keys in a Hash, convert Camelcase to underscore separated
38
- def convert_hash_keys(value)
39
- case value
40
- when Array
41
- value.map { |v| convert_hash_keys(v) }
42
- when Hash
43
- Hash[value.map { |k, v| [underscore_key(k), convert_hash_keys(v)] }]
44
- else
45
- value
46
- end
47
- end
48
-
49
- # Remove arrays created as another string
50
- def clean_up_yaml(yaml_string)
51
- yaml_string = yaml_string.gsub(/\R+(\s*)-/, '').gsub(/{}/, "''") # Remove arrays, {} -> ''
52
- # Insert new line where there are 2 ':' on 1 line. Issue from first gsub
53
- yaml_string.gsub(/:(\s)(\w*):/){|s| s.insert(1, "\n")}
54
- end
55
-
56
- if ARGV[0]
57
- warn "Using '#{default_output_file}' as default output file since no 2nd argument passed" unless ARGV[1]
58
- hash = XmlSimple.xml_in(ARGV[0])
59
- converted = convert_hash_keys hash
60
- yaml_file = clean_up_yaml(converted.to_yaml)
61
- create_file(filename: ARGV[1] || default_output_file, content: yaml_file)
62
- else
63
- puts 'usage: xml_to_yaml_file [input.xml] [output.yml] '
1
+
2
+ require 'xmlsimple'
3
+ require 'yaml'
4
+ require 'fileutils'
5
+
6
+ default_output_file = 'output.yml'
7
+
8
+ # Create file if not present. If present but different give warning
9
+ def create_file(options)
10
+ filename = options[:filename]
11
+ raise 'Need to pass filename' unless filename
12
+ content = options[:content]
13
+ raise 'Need to pass contents to insert into file' unless content
14
+ if File.exist? filename
15
+ old_content = File.read(filename)
16
+ if old_content != content
17
+ warn "!! #{filename} already exists and differs from template"
18
+ end
19
+ else
20
+ File.open(filename, 'w') do |f|
21
+ f.puts content
22
+ end
23
+ puts 'Created: ' + filename
24
+ end
25
+ end
26
+
27
+ # Convert key in camelcase to underscore separated (snakecase)
28
+ def underscore_key(key)
29
+ key.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
30
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2')
31
+ .tr('-', '_')
32
+ .gsub(/\s/, '_')
33
+ .gsub(/__+/, '_')
34
+ .downcase
35
+ end
36
+
37
+ # For all keys in a Hash, convert Camelcase to underscore separated
38
+ def convert_hash_keys(value)
39
+ case value
40
+ when Array
41
+ value.map { |v| convert_hash_keys(v) }
42
+ when Hash
43
+ Hash[value.map { |k, v| [underscore_key(k), convert_hash_keys(v)] }]
44
+ else
45
+ value
46
+ end
47
+ end
48
+
49
+ # Remove arrays created as another string
50
+ def clean_up_yaml(yaml_string)
51
+ yaml_string = yaml_string.gsub(/\R+(\s*)-/, '').gsub(/{}/, "''") # Remove arrays, {} -> ''
52
+ # Insert new line where there are 2 ':' on 1 line. Issue from first gsub
53
+ yaml_string.gsub(/:(\s)(\w*):/){|s| s.insert(1, "\n")}
54
+ end
55
+
56
+ if ARGV[0]
57
+ warn "Using '#{default_output_file}' as default output file since no 2nd argument passed" unless ARGV[1]
58
+ hash = XmlSimple.xml_in(ARGV[0])
59
+ converted = convert_hash_keys hash
60
+ yaml_file = clean_up_yaml(converted.to_yaml)
61
+ create_file(filename: ARGV[1] || default_output_file, content: yaml_file)
62
+ else
63
+ puts 'usage: xml_to_yaml_file [input.xml] [output.yml] '
64
64
  end
@@ -1,48 +1,61 @@
1
- require 'rest-client' # REST
2
- require 'erb' # Embedded ruby
3
- require 'yaml' # Reading yaml
4
- require 'rspec' # Testing framework
5
- require 'rspec/its'
6
- require 'savon' # SOAP
7
- require 'nokogiri' # XPath
8
- require 'date'
9
-
10
- require 'soaspec/version'
11
- require 'soaspec/basic_soap_handler'
12
- require 'soaspec/tester'
13
- require 'soaspec/exchange'
14
- require 'soaspec/matchers'
15
- require 'soaspec/soaspec_shared_examples'
16
- require 'soaspec/hash_methods'
17
- require 'soaspec/spec_logger'
18
-
19
- # Gem for handling SOAP and REST api tests
20
- module Soaspec
21
-
22
- def self.hi
23
- puts 'Hello world!'
24
- end
25
-
26
- # Represents Environment parameters used in Soaspec tests
27
- module Environment
28
-
29
- # Used so that exchange class knows what context it's in
30
- def self.api_handler=(handler)
31
- @api_handler = handler
32
- end
33
-
34
- def self.api_handler
35
- @api_handler
36
- end
37
-
38
- # Whether to transform strings to keys automatically
39
- def self.always_use_keys=(use_keys)
40
- @always_use_keys = use_keys
41
- end
42
-
43
- def self.always_use_keys?
44
- @always_use_keys || true
45
- end
46
-
47
- end
48
- end
1
+ require 'rest-client' # REST
2
+ require 'erb' # Embedded ruby
3
+ require 'yaml' # Reading yaml
4
+ require 'rspec' # Testing framework
5
+ require 'rspec/its'
6
+ require 'savon' # SOAP
7
+ require 'nokogiri' # XPath
8
+ require 'date'
9
+
10
+ require 'soaspec/version'
11
+ require 'soaspec/basic_soap_handler'
12
+ require 'soaspec/tester'
13
+ require 'soaspec/exchange'
14
+ require 'soaspec/matchers'
15
+ require 'soaspec/soaspec_shared_examples'
16
+ require 'soaspec/hash_methods'
17
+ require 'soaspec/spec_logger'
18
+
19
+ # Gem for handling SOAP and REST api tests
20
+ module Soaspec
21
+
22
+ def self.hi
23
+ puts 'Hello world!'
24
+ end
25
+
26
+ # Represents Environment parameters used in Soaspec tests
27
+ module Environment
28
+
29
+ # Used so that exchange class knows what context it's in
30
+ def self.api_handler=(handler)
31
+ @api_handler = handler
32
+ end
33
+
34
+ def self.api_handler
35
+ @api_handler
36
+ end
37
+
38
+ # Whether to transform strings to keys automatically
39
+ def self.always_use_keys=(use_keys)
40
+ @always_use_keys = use_keys
41
+ end
42
+
43
+ def self.always_use_keys?
44
+ @always_use_keys || true
45
+ end
46
+
47
+ # Whether to remove namespaces from response in Xpath assertion automatically
48
+ # For why this may not be a good thing in general see
49
+ # http://tenderlovemaking.com/2009/04/23/namespaces-in-xml.html
50
+ # This will be overridden if xpath has a ':' in it
51
+ def self.strip_namespaces=(remove_namespaces_from_response)
52
+ @strip_namespaces = remove_namespaces_from_response
53
+ end
54
+
55
+ # Whether to remove namespaces in xpath assertion automatically
56
+ def self.strip_namespaces?
57
+ @strip_namespaces || false
58
+ end
59
+
60
+ end
61
+ end
@@ -1,123 +1,133 @@
1
-
2
- require_relative 'tester'
3
- require_relative 'hash_methods'
4
-
5
- module Soaspec
6
- # Wraps around Savon client defining default values dependent on the soap request
7
- class BasicSoapHandler < Tester
8
- # Savon client used to make SOAP calls
9
- attr_accessor :client
10
- # SOAP Operation to use by default
11
- attr_accessor :operation
12
-
13
- # Options to log xml request and response
14
- def logging_options
15
- {
16
- log: true, # See request and response. (Put this in traffic file)
17
- log_level: :debug,
18
- logger: Soaspec::SpecLogger.create,
19
- pretty_print_xml: true # Prints XML pretty
20
- }
21
- end
22
-
23
- # Default Savon options. See http://savonrb.com/version2/globals.html for details
24
- # @return [Hash] Default Savon options for all BasicSoapHandler
25
- def default_options
26
- {
27
- ssl_verify_mode: :none, # Easier for testing. Not so secure
28
- follow_redirects: true, # Necessary for many API calls
29
- soap_version: 2, # use SOAP 1.2. You will get 415 error if this is incorrect
30
- raise_errors: false # HTTP errors not cause failure as often negative test scenarios expect not 200 response
31
- # Things could go wrong if not set properly
32
- # env_namespace: :soap, # Change environment namespace
33
- # namespace_identifier: :tst, # Change namespace element
34
- # element_form_default: :qualified # Populate each element with namespace
35
- # namespace: 'http://Extended_namespace.xsd' change root namespace
36
- # basic_auth: 'user', 'password'
37
- }
38
- end
39
-
40
- # Add values to here when extending this class to have default Savon options.
41
- # See http://savonrb.com/version2/globals.html for details
42
- # @return [Hash] Savon options adding to & overriding defaults
43
- def savon_options
44
- {
45
- }
46
- end
47
-
48
- # Setup object to handle communicating with a particular SOAP WSDL
49
- # @param [Hash] specific_options Options defining SOAP request. WSDL, authentication, see http://savonrb.com/version2/globals.html for list of options
50
- def initialize(name, specific_options = {})
51
- options = default_options.merge logging_options
52
- options.merge! savon_options
53
- options.merge!(specific_options)
54
- @client = Savon.client(options)
55
- super
56
- end
57
-
58
- def name(name)
59
- @test_values = {}
60
- @test_name = name
61
- self
62
- end
63
-
64
- def override(request_parameters)
65
- @test_values = request_parameters
66
- self
67
- end
68
-
69
- # Used in together with Exchange request that passes such override parameters
70
- def make_request(override_parameters)
71
- test_values = override_parameters # Used in Erb
72
- # Erb parses template file, executing Ruby code in `<% %>` blocks to work out final request
73
- test_values = test_values.transform_keys_to_symbols if Soaspec::Environment.always_use_keys?
74
- if @request_option == :template
75
- request_body = File.read('template/' + template_name + '.xml')
76
- render_body = ERB.new(request_body).result(binding)
77
- @client.call(operation, xml: render_body) # Call the SOAP operation with the request XML provided
78
- elsif @request_option == :hash
79
- @client.call(operation, message: @default_hash.merge(test_values), attributes: root_attributes)
80
- end
81
- end
82
-
83
- def default_hash=(hash)
84
- @request_option = :hash
85
- @default_hash = Soaspec::Environment.always_use_keys? ? hash.transform_keys_to_symbols : hash
86
- end
87
-
88
- def status_code_for(response)
89
- response.http.code
90
- end
91
-
92
- # Override this to specify elements that must be present in the response
93
- # Will be used in 'success_scenarios' shared examples
94
- # @return [Array] Array of symbols specifying element names
95
- def mandatory_elements
96
- []
97
- end
98
-
99
- # Override this to specify xpath results that must be present in the response
100
- # Will be used in 'success_scenarios' shared examples
101
- # @return [Hash] Hash of 'xpath' => 'expected value' pairs
102
- def mandatory_xpath_values
103
- {}
104
- end
105
-
106
- # Attributes set at the root XML element of SOAP request
107
- def root_attributes
108
- nil
109
- end
110
-
111
- def xpath_value_for(param)
112
- result = param[:exchange].response.xpath(param[:xpath]).first
113
- raise 'No value at Xpath' unless result
114
- result.inner_text
115
- end
116
-
117
- def value_from_path(exchange, path)
118
- path = '//' + path if path[0] != '/'
119
- xpath_value_for(exchange: exchange, xpath: path)
120
- end
121
-
122
- end
1
+
2
+ require_relative 'tester'
3
+ require_relative 'hash_methods'
4
+ require_relative 'xpath_not_found'
5
+
6
+ module Soaspec
7
+ # Wraps around Savon client defining default values dependent on the soap request
8
+ class BasicSoapHandler < Tester
9
+ # Savon client used to make SOAP calls
10
+ attr_accessor :client
11
+ # SOAP Operation to use by default
12
+ attr_accessor :operation
13
+
14
+ # Options to log xml request and response
15
+ def logging_options
16
+ {
17
+ log: true, # See request and response. (Put this in traffic file)
18
+ log_level: :debug,
19
+ logger: Soaspec::SpecLogger.create,
20
+ pretty_print_xml: true # Prints XML pretty
21
+ }
22
+ end
23
+
24
+ # Default Savon options. See http://savonrb.com/version2/globals.html for details
25
+ # @return [Hash] Default Savon options for all BasicSoapHandler
26
+ def default_options
27
+ {
28
+ ssl_verify_mode: :none, # Easier for testing. Not so secure
29
+ follow_redirects: true, # Necessary for many API calls
30
+ soap_version: 2, # use SOAP 1.2. You will get 415 error if this is incorrect
31
+ raise_errors: false # HTTP errors not cause failure as often negative test scenarios expect not 200 response
32
+ # Things could go wrong if not set properly
33
+ # env_namespace: :soap, # Change environment namespace
34
+ # namespace_identifier: :tst, # Change namespace element
35
+ # element_form_default: :qualified # Populate each element with namespace
36
+ # namespace: 'http://Extended_namespace.xsd' change root namespace
37
+ # basic_auth: 'user', 'password'
38
+ }
39
+ end
40
+
41
+ # Add values to here when extending this class to have default Savon options.
42
+ # See http://savonrb.com/version2/globals.html for details
43
+ # @return [Hash] Savon options adding to & overriding defaults
44
+ def savon_options
45
+ {
46
+ }
47
+ end
48
+
49
+ # Setup object to handle communicating with a particular SOAP WSDL
50
+ # @param [Hash] specific_options Options defining SOAP request. WSDL, authentication, see http://savonrb.com/version2/globals.html for list of options
51
+ def initialize(name, specific_options = {})
52
+ options = default_options.merge logging_options
53
+ options.merge! savon_options
54
+ options.merge!(specific_options)
55
+ @client = Savon.client(options)
56
+ super
57
+ end
58
+
59
+ def name(name)
60
+ @test_values = {}
61
+ @test_name = name
62
+ self
63
+ end
64
+
65
+ def override(request_parameters)
66
+ @test_values = request_parameters
67
+ self
68
+ end
69
+
70
+ # Used in together with Exchange request that passes such override parameters
71
+ def make_request(override_parameters)
72
+ test_values = override_parameters # Used in Erb
73
+ # Erb parses template file, executing Ruby code in `<% %>` blocks to work out final request
74
+ test_values = test_values.transform_keys_to_symbols if Soaspec::Environment.always_use_keys?
75
+ if @request_option == :template
76
+ request_body = File.read('template/' + template_name + '.xml')
77
+ render_body = ERB.new(request_body).result(binding)
78
+ @client.call(operation, xml: render_body) # Call the SOAP operation with the request XML provided
79
+ elsif @request_option == :hash
80
+ @client.call(operation, message: @default_hash.merge(test_values), attributes: root_attributes)
81
+ end
82
+ end
83
+
84
+ def default_hash=(hash)
85
+ @request_option = :hash
86
+ @default_hash = Soaspec::Environment.always_use_keys? ? hash.transform_keys_to_symbols : hash
87
+ end
88
+
89
+ def status_code_for(response)
90
+ response.http.code
91
+ end
92
+
93
+ # Override this to specify elements that must be present in the response
94
+ # Will be used in 'success_scenarios' shared examples
95
+ # @return [Array] Array of symbols specifying element names
96
+ def mandatory_elements
97
+ []
98
+ end
99
+
100
+ # Override this to specify xpath results that must be present in the response
101
+ # Will be used in 'success_scenarios' shared examples
102
+ # @return [Hash] Hash of 'xpath' => 'expected value' pairs
103
+ def mandatory_xpath_values
104
+ {}
105
+ end
106
+
107
+ # Attributes set at the root XML element of SOAP request
108
+ def root_attributes
109
+ nil
110
+ end
111
+
112
+ # Returns the value at the provided xpath
113
+ def xpath_value_for(param)
114
+ result =
115
+ if Soaspec::Environment.strip_namespaces? && !param[:xpath].include?(':')
116
+ temp_doc = param[:exchange].response.doc
117
+ temp_doc.remove_namespaces!
118
+ temp_doc.xpath(param[:xpath]).first
119
+ else
120
+ puts 'no strip' + param[:xpath]
121
+ param[:exchange].response.xpath(param[:xpath]).first
122
+ end
123
+ raise NoElementAtXpath, "No value at Xpath '#{param[:xpath]}'" unless result
124
+ result.inner_text
125
+ end
126
+
127
+ def value_from_path(exchange, path)
128
+ path = '//' + path if path[0] != '/'
129
+ xpath_value_for(exchange: exchange, xpath: path)
130
+ end
131
+
132
+ end
123
133
  end