soaspec 0.0.89 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0fbb853656c1ac3fa5e3f8cf9deb35d3ffd2094b
4
- data.tar.gz: 4af040f838d170b0248adcddbee6adffee89d978
3
+ metadata.gz: 47048ecb768673e682744c8ed3064450530ed0de
4
+ data.tar.gz: 4f4137848f7a656914205ad76a3ae800a065c969
5
5
  SHA512:
6
- metadata.gz: 72d6dcbf54043591c26c8e0951e68a56c331a26f7d8d05bc9acd76ae512bda463bddc5be2d96de322e4041c64c51b972f879aaf227f1e3465c436821bba2692a
7
- data.tar.gz: d25a4e7f6ab09ed7657a886fcf2b24aefd15da539fc9ad18fa1ed70a17c278a750a098e771603dd7e571d5cb6a9bfc2749525ae37e96dd3eff34ddb01d2a81e8
6
+ metadata.gz: dd35e76ceae861c08bcad153b0e124643c83b856071e486116f40d1a7c210f92b4d0854172bcf14a5d1a462e42f5ad197fd8853bdd8a252bbfc469948c52a1d9
7
+ data.tar.gz: 167dbbf4db1b4a61def28a6c4bfea8810c192a922f03495ae727fc754b9086a0658e8e5b1c4a0265a7d5c2ae322207f65889d65d4096a3061b7a7cb20e6886fb
data/ChangeLog CHANGED
@@ -1,3 +1,9 @@
1
+ Version 0.1.0
2
+ * Enhancements
3
+ * Cleaned up unit tests for WSDL generator. Won't bother for SOAP ComplexType for now as I'm not needing this and it looks like Savon 3 will create example requests anyway
4
+ * Put SOAP Basic Auth in Example
5
+ * Added template handling for REST handler
6
+
1
7
  Version 0.0.89
2
8
  * Enhancements
3
9
  * Move more functionality out of soaspec exe and into WsdlGenerator. Started unit tests for it
data/README.md CHANGED
@@ -31,7 +31,7 @@ Example:
31
31
  ```
32
32
  mkdir 'api_test'
33
33
  cd 'api_test'
34
- soaspec-init
34
+ soaspec new
35
35
  bundle install
36
36
  ```
37
37
 
@@ -41,7 +41,7 @@ Then you can run the tests with:
41
41
  rake spec
42
42
  ```
43
43
 
44
- You can also use `soaspec-generate` to generate a set of tests from a WSDL. This is still in trial period
44
+ You can also use `soaspec generate` to generate a set of tests from a WSDL. This is still in trial period and will be finished probably after Savon 3 is more stable.
45
45
 
46
46
  ## Usage
47
47
 
data/Todo.md CHANGED
@@ -1,7 +1,6 @@
1
1
  * Give examples and convenience methods for building classes for each SOAP or REST operation
2
2
  * For SOAP give example of basic_auth
3
- * Handle REST template (similar way to SOAP)
4
- * Get wsdl generator working for non complex gems
5
3
  * Potentially have in built use of 'vcr' and 'http_stub' gems
6
4
  * Handle proxies to record traffic for MiddleWare testing
7
- * Much more - please raise an issue for suggestion
5
+ * Get wsdl generator working for non complex gems (Put on hold til new Savon version)
6
+ * Much more - please raise an issue for suggestion
@@ -26,14 +26,9 @@ class SoaspecVirtualServer < Sinatra::Application
26
26
  Soaspec::TestServer::TestNamespace.food
27
27
  end
28
28
 
29
- # This is the one being hit by SOAP actions
30
- post '/BLZService' do
31
- Soaspec::TestServer::GetBank.response_for request
32
- end
33
-
34
- # This is returned when a query for the WSDL is made
35
- get '/BLZService' do
36
- [200, { 'Content-Type' => 'text/xml' }, Soaspec::TestServer::GetBank.test_wsdl]
29
+ # Used for simple testing of posing
30
+ post '/echoer' do
31
+ request.body
37
32
  end
38
33
 
39
34
  # Simulate retrieving an ouath token. Passed to '/invoices'
@@ -46,6 +41,11 @@ class SoaspecVirtualServer < Sinatra::Application
46
41
  JSON.generate(customer_id: id, oauth: request.env['HTTP_AUTHORIZATION'], user: Soaspec::TestServer::Invoices.user_used)
47
42
  end
48
43
 
44
+ # This is returned when a query for the WSDL is made
45
+ get '/BLZService' do
46
+ [200, { 'Content-Type' => 'text/xml' }, Soaspec::TestServer::GetBank.test_wsdl]
47
+ end
48
+
49
49
  authorize do |username, password|
50
50
  username == 'admin' && password == 'secret'
51
51
  end
@@ -54,6 +54,11 @@ class SoaspecVirtualServer < Sinatra::Application
54
54
  get '/basic_secrets' do
55
55
  'Secret data'
56
56
  end
57
+
58
+ # This is the one being hit by SOAP actions
59
+ post '/BLZService' do
60
+ Soaspec::TestServer::GetBank.response_for request
61
+ end
57
62
  end
58
63
 
59
64
  # Used for testing storage of data
@@ -55,6 +55,7 @@ module Soaspec
55
55
  super
56
56
  set_remove_key(options, :api_username)
57
57
  set_remove_key(options, :default_hash)
58
+ set_remove_key(options, :template_name)
58
59
  @init_options = options
59
60
  end
60
61
 
@@ -71,16 +72,6 @@ module Soaspec
71
72
  false
72
73
  end
73
74
 
74
- # @return [Hash]
75
- def hash_used_in_request(override_hash)
76
- request = @default_hash.merge(override_hash)
77
- if pascal_keys?
78
- request.map { |k, v| [convert_to_pascal_case(k.to_s), v] }.to_h
79
- else
80
- request
81
- end
82
- end
83
-
84
75
  # Initialize value of merged options
85
76
  def init_merge_options
86
77
  options = rest_resource_options
@@ -93,6 +84,7 @@ module Soaspec
93
84
  # @param [Hash] override_parameters Params to characterize REST request
94
85
  # @param_value [params] Extra parameters (E.g. headers)
95
86
  # @param_value [suburl] URL appended to base_url of class
87
+ # @param_value [q] Query for REST
96
88
  # @param_value [method] REST method (:get, :post, etc)
97
89
  def make_request(override_parameters)
98
90
  @merged_options ||= init_merge_options
@@ -101,7 +93,6 @@ module Soaspec
101
93
  test_values[:method] ||= :post
102
94
  test_values[:suburl] = test_values[:suburl].to_s if test_values[:suburl]
103
95
  test_values[:params][:params] = test_values[:q] if test_values[:q] # Use q for query parameters. Nested :params is ugly and long
104
-
105
96
  # In order for ERB to be calculated at correct time, the first time request is made, the resource should be created
106
97
  @resource ||= RestClient::Resource.new(ERB.new(base_url_value).result(binding), @merged_options)
107
98
 
@@ -110,11 +101,9 @@ module Soaspec
110
101
  begin
111
102
  response = case test_values[:method]
112
103
  when :post, :patch, :put
113
- unless test_values[:payload]
114
- test_values[:payload] = JSON.generate(hash_used_in_request(test_values[:body])).to_s if test_values[:body]
115
- end
116
- @resource_used.send(test_values[:method].to_s, test_values[:payload], test_values[:params])
117
- else
104
+ Soaspec::SpecLogger.info("request body: #{post_data(test_values)}")
105
+ @resource_used.send(test_values[:method].to_s, post_data(test_values), test_values[:params])
106
+ else # :get, :delete
118
107
  @resource_used.send(test_values[:method].to_s, test_values[:params])
119
108
  end
120
109
  rescue RestClient::ExceptionWithResponse => e
@@ -131,11 +120,12 @@ module Soaspec
131
120
  extract_hash response
132
121
  end
133
122
 
123
+ # @return [Boolean] Whether response body includes String
134
124
  def include_in_body?(response, expected)
135
125
  response.body.include? expected
136
126
  end
137
127
 
138
- # Whether the request found the desired value or not
128
+ # @@return [Boolean] Whether the request found the desired value or not
139
129
  def found?(response)
140
130
  status_code_for(response) != 404
141
131
  end
@@ -275,6 +265,31 @@ module Soaspec
275
265
  end
276
266
  end
277
267
 
268
+ private
269
+
270
+ # Work out data to send based upon payload, template_name
271
+ # @return [String] Payload to send in REST request
272
+ def post_data(test_values)
273
+ if test_values[:body]
274
+ test_values[:payload] = JSON.generate(hash_used_in_request(test_values[:body])).to_s
275
+ elsif @request_option == :template
276
+ request_body = File.read('template/' + template_name)
277
+ ERB.new(request_body).result(binding)
278
+ else
279
+ test_values[:payload]
280
+ end
281
+ end
282
+
283
+ # @return [Hash] Hash used in REST request based on data conversion
284
+ def hash_used_in_request(override_hash)
285
+ request = @default_hash.merge(override_hash)
286
+ if pascal_keys?
287
+ request.map { |k, v| [convert_to_pascal_case(k.to_s), v] }.to_h
288
+ else
289
+ request
290
+ end
291
+ end
292
+
278
293
  # Convenience methods for once off usage of a REST request
279
294
  class << self
280
295
 
@@ -101,11 +101,11 @@ module Soaspec
101
101
  test_values = request_body_params request_parameters
102
102
  begin
103
103
  if @request_option == :template
104
- request_body = File.read('template/' + template_name + '.xml')
104
+ request_body = File.read('template/' + template_name)
105
105
  render_body = ERB.new(request_body).result(binding)
106
- @client.call(operation, xml: render_body) # Call the SOAP operation with the request XML provided
106
+ client.call(operation, xml: render_body) # Call the SOAP operation with the request XML provided
107
107
  elsif @request_option == :hash
108
- @client.call(operation, message: @default_hash.merge(test_values), attributes: request_root_attributes)
108
+ client.call(operation, message: @default_hash.merge(test_values), attributes: request_root_attributes)
109
109
  end
110
110
  rescue Savon::HTTPError => e
111
111
  e
@@ -1,3 +1,3 @@
1
1
  module Soaspec
2
- VERSION = '0.0.89'.freeze
2
+ VERSION = '0.1.0'.freeze
3
3
  end
@@ -5,7 +5,7 @@ module Soaspec
5
5
  def try_enum_for(type)
6
6
  raise "'@wsdl_schemas' must be defined" if @wsdl_schemas.nil?
7
7
  custom_type = @wsdl_schemas.xpath("//*[@name='#{type}']")
8
- if custom_type.first
8
+ if enumeration? custom_type
9
9
  prefix = custom_type.first.namespace.prefix
10
10
  enumerations = custom_type.xpath("//#{prefix}:enumeration")
11
11
  return 'Custom Type' if enumerations.empty?
@@ -17,6 +17,13 @@ module Soaspec
17
17
  end
18
18
  end
19
19
 
20
+ # @param [Nokogiri::XML::NodeSet]
21
+ # @return [Boolean] Whether WSDL type is an enumeration
22
+ def enumeration?(type)
23
+ return false unless type.first
24
+ !type.xpath("*/#{type.first.namespace.prefix}:enumeration").empty?
25
+ end
26
+
20
27
  # Return value of string after a namespace
21
28
  # @param [String] string String to parse for part after namespace
22
29
  def value_after_namespace(string)
@@ -40,6 +47,12 @@ module Soaspec
40
47
  end
41
48
  end
42
49
 
50
+ # @param [Nokogiri::XML::Element]
51
+ # @return [Boolean] True if nokogori element is a complex type, that is, has a complexType element underneath itself
52
+ def complex_type?(element)
53
+ element.children.any? { |child| child.name == 'complexType' }
54
+ end
55
+
43
56
  # @param [String, Symbol] underscore_separated Snakecase value to be converted to camel case
44
57
  def camel_case(underscore_separated)
45
58
  underscore_separated.to_s.split('_').collect(&:capitalize).join
@@ -52,27 +65,43 @@ module Soaspec
52
65
  root_element = @wsdl_schemas.at_xpath("//*[@name='#{op_details[:input]}']")
53
66
  raise 'Operation has no input defined' if root_element.nil?
54
67
  schema_namespace = root_element.namespace.prefix
55
-
56
68
  root_type = root_element['type']
57
69
  if root_type
58
70
  @wsdl_schemas.xpath("//*[@name='#{root_type.split(':').last}']//#{schema_namespace}:element")
59
71
  else
60
- return [] unless root_element.children.any? { |child| child.name == 'complexType' } # Empty Array if there are no root elements
61
- root_element.xpath("//#{schema_namespace}:element")
72
+ return [] unless complex_type? root_element # Empty Array if there are no root elements
73
+ complex_type = root_element.children.find { |c| c.name == 'complexType' }
74
+ sequence = complex_type.children.find { |c| c.name == 'sequence' }
75
+ sequence.xpath("#{schema_namespace}:element")
62
76
  end
63
77
  end
64
78
 
65
- # @param [Nokogiri::NodeSet] list List
66
- def wsdl_to_yaml_for(list)
67
- raise "'@content' string must be set" if @content.nil?
68
- puts list
69
- list.each do |element|
79
+ # @param [Nokogiri::XML::Element]
80
+ def document_type_for(element, depth = 1)
81
+ # raise "Too far deep for #{element}" unless depth < 6
82
+ return unless depth < 6
83
+ if complex_type? element
84
+ complex_type = element.children.find { |c| c.name == 'complexType' }
85
+ sequence = complex_type.children.find { |c| c.name == 'sequence' }
86
+ sequence.children.select { |node| node.class == Nokogiri::XML::Element }.each do |sub_element|
87
+ document_type_for sub_element, depth += 1
88
+ end
89
+ else
90
+ return "No type seen for #{element}, #{element.class}" unless element['type']
70
91
  name = element['name']
71
92
  type = value_after_namespace(element['type'])
72
- puts 'Name ' + name + ' type ' + type
73
93
  @use_camel_case = true if (/[[:upper:]]/.match(name[0]) != nil)
74
- @content += " #{name.snakecase}: #{fill_in_field_from_type(type)} # #{type} \n"
75
- # TODO: If it is nested need to loop again
94
+ spaces = ' ' * depth
95
+ @content += "#{spaces}#{name.snakecase}: #{fill_in_field_from_type(type)} # #{type} \n"
96
+ end
97
+ end
98
+
99
+ # Makes a yaml string in a '@content' instance variable
100
+ # @param [Nokogiri::XML::NodeSet] list List
101
+ def wsdl_to_yaml_for(list)
102
+ raise "'@content' string must be set" if @content.nil?
103
+ list.each do |element|
104
+ document_type_for element
76
105
  end
77
106
  end
78
107
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soaspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.89
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SamuelGarrattIQA
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-06 00:00:00.000000000 Z
11
+ date: 2018-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler