soaspec 0.0.89 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|