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 +4 -4
- data/ChangeLog +6 -0
- data/README.md +2 -2
- data/Todo.md +2 -3
- data/exe/soaspec-virtual-server +13 -8
- data/lib/soaspec/exchange_handlers/rest_handler.rb +32 -17
- data/lib/soaspec/exchange_handlers/soap_handler.rb +3 -3
- data/lib/soaspec/version.rb +1 -1
- data/lib/soaspec/wsdl_generator.rb +41 -12
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47048ecb768673e682744c8ed3064450530ed0de
|
4
|
+
data.tar.gz: 4f4137848f7a656914205ad76a3ae800a065c969
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
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
|
-
*
|
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
|
data/exe/soaspec-virtual-server
CHANGED
@@ -26,14 +26,9 @@ class SoaspecVirtualServer < Sinatra::Application
|
|
26
26
|
Soaspec::TestServer::TestNamespace.food
|
27
27
|
end
|
28
28
|
|
29
|
-
#
|
30
|
-
post '/
|
31
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
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
|
104
|
+
request_body = File.read('template/' + template_name)
|
105
105
|
render_body = ERB.new(request_body).result(binding)
|
106
|
-
|
106
|
+
client.call(operation, xml: render_body) # Call the SOAP operation with the request XML provided
|
107
107
|
elsif @request_option == :hash
|
108
|
-
|
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
|
data/lib/soaspec/version.rb
CHANGED
@@ -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
|
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
|
61
|
-
root_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::
|
66
|
-
def
|
67
|
-
raise "
|
68
|
-
|
69
|
-
|
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
|
-
|
75
|
-
#
|
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
|
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-
|
11
|
+
date: 2018-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|