soaspec 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +0 -17
- data/ChangeLog +6 -0
- data/Gemfile +2 -2
- data/README.md +42 -9
- data/Rakefile +1 -1
- data/exe/soaspec +9 -14
- data/exe/xml_to_yaml_file +3 -3
- data/images/basic_demo.gif +0 -0
- data/lib/soaspec.rb +9 -19
- data/lib/soaspec/core_ext/hash.rb +10 -12
- data/lib/soaspec/cucumber/generic_steps.rb +1 -1
- data/lib/soaspec/exchange.rb +4 -1
- data/lib/soaspec/exchange_handlers/exchange_handler.rb +5 -4
- data/lib/soaspec/exchange_handlers/handler_accessors.rb +7 -3
- data/lib/soaspec/exchange_handlers/response_extractor.rb +55 -0
- data/lib/soaspec/exchange_handlers/rest_exchanger_factory.rb +1 -1
- data/lib/soaspec/exchange_handlers/rest_handler.rb +16 -43
- data/lib/soaspec/exchange_handlers/rest_methods.rb +1 -2
- data/lib/soaspec/exchange_handlers/rest_parameters.rb +6 -2
- data/lib/soaspec/exchange_handlers/rest_parameters_defaults.rb +1 -1
- data/lib/soaspec/exchange_handlers/soap_handler.rb +6 -10
- data/lib/soaspec/exchange_properties.rb +1 -2
- data/lib/soaspec/exe_helpers.rb +7 -9
- data/lib/soaspec/indifferent_hash.rb +1 -1
- data/lib/soaspec/interpreter.rb +1 -3
- data/lib/soaspec/matchers.rb +1 -2
- data/lib/soaspec/o_auth2.rb +2 -1
- data/lib/soaspec/spec_logger.rb +54 -12
- data/lib/soaspec/template_reader.rb +2 -1
- data/lib/soaspec/test_server/get_bank.rb +5 -5
- data/lib/soaspec/test_server/id_manager.rb +1 -3
- data/lib/soaspec/test_server/invoices.rb +0 -1
- data/lib/soaspec/test_server/puppy_service.rb +0 -1
- data/lib/soaspec/test_server/test_attribute.rb +0 -1
- data/lib/soaspec/version.rb +2 -2
- data/lib/soaspec/virtual_server.rb +1 -1
- data/lib/soaspec/wait.rb +1 -1
- data/lib/soaspec/wsdl_generator.rb +11 -3
- data/soaspec.gemspec +7 -2
- data/test_wsdl.rb +4 -7
- metadata +54 -10
@@ -0,0 +1,55 @@
|
|
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
|
+
# @return [Hash] Hash representing response body
|
24
|
+
def to_hash(response)
|
25
|
+
case Interpreter.response_type_for(response)
|
26
|
+
when :xml then parse_xml(response.body.to_s)
|
27
|
+
when :json
|
28
|
+
JSON.parse(response.body.to_s)
|
29
|
+
else
|
30
|
+
raise "Unable to interpret type of #{response.body}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# @param [String] xml XML to convert
|
37
|
+
# @return [Hash] Hash representing XML
|
38
|
+
def parse_xml(xml)
|
39
|
+
parser = Nori.new(strip_namespaces: strip_namespaces?, convert_tags_to: ->(tag) { tag.snakecase.to_sym })
|
40
|
+
parser.parse(xml)
|
41
|
+
end
|
42
|
+
|
43
|
+
# This enables shortcut xpaths to be used. If no '/' is given, one is appended to the start of the path
|
44
|
+
# If attribute value is set then this is also adjusted
|
45
|
+
# @return [String] New Xpath adjusted according to any add ons
|
46
|
+
def prefix_xpath(xpath, attribute)
|
47
|
+
xpath = "//*[@#{attribute}]" unless attribute.nil?
|
48
|
+
if xpath[0] != '/'
|
49
|
+
xpath = convert_to_pascal_case(xpath) if pascal_keys?
|
50
|
+
xpath = '//' + xpath
|
51
|
+
end
|
52
|
+
xpath
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -6,6 +6,7 @@ require_relative '../core_ext/hash'
|
|
6
6
|
require_relative '../not_found_errors'
|
7
7
|
require_relative 'handler_accessors'
|
8
8
|
require_relative '../interpreter'
|
9
|
+
require_relative 'response_extractor'
|
9
10
|
require 'json'
|
10
11
|
require 'jsonpath'
|
11
12
|
require 'nori'
|
@@ -14,6 +15,7 @@ require 'erb'
|
|
14
15
|
module Soaspec
|
15
16
|
# Wraps around Savon client defining default values dependent on the soap request
|
16
17
|
class RestHandler < ExchangeHandler
|
18
|
+
include ResponseExtractor
|
17
19
|
extend Soaspec::RestParameters
|
18
20
|
include Soaspec::RestParametersDefaults
|
19
21
|
extend Soaspec::RestExchangeFactory
|
@@ -25,6 +27,7 @@ module Soaspec
|
|
25
27
|
# @param [Hash] options Options defining REST request. base_url, default_hash
|
26
28
|
def initialize(name = self.class.to_s, options = {})
|
27
29
|
raise "Base URL not set! Please set in class with 'base_url' method" unless base_url_value
|
30
|
+
|
28
31
|
if name.is_a?(Hash) && options == {} # If name is not set, use first parameter as the options hash
|
29
32
|
options = name
|
30
33
|
name = self.class.to_s
|
@@ -87,6 +90,7 @@ module Soaspec
|
|
87
90
|
def parse_headers
|
88
91
|
Hash[rest_client_headers.map do |header_name, header_value|
|
89
92
|
raise ArgumentError, "Header '#{header_name}' is null. Headers are #{rest_client_headers}" if header_value.nil?
|
93
|
+
|
90
94
|
[header_name, ERB.new(header_value).result(binding)]
|
91
95
|
end]
|
92
96
|
end
|
@@ -94,6 +98,7 @@ module Soaspec
|
|
94
98
|
# Convert snakecase to PascalCase
|
95
99
|
def convert_to_pascal_case(key)
|
96
100
|
return key if /[[:upper:]]/ =~ key[0] # If first character already capital, don't do conversion
|
101
|
+
|
97
102
|
key.split('_').map(&:capitalize).join
|
98
103
|
end
|
99
104
|
|
@@ -104,9 +109,7 @@ module Soaspec
|
|
104
109
|
options.merge! basic_auth_params if respond_to? :basic_auth_params
|
105
110
|
options[:headers] ||= {}
|
106
111
|
options[:headers].merge! parse_headers
|
107
|
-
if Soaspec.auto_oauth && respond_to?(:access_token)
|
108
|
-
options[:headers][:authorization] ||= ERB.new('Bearer <%= access_token %>').result(binding)
|
109
|
-
end
|
112
|
+
options[:headers][:authorization] ||= ERB.new('Bearer <%= access_token %>').result(binding) if Soaspec.auto_oauth && respond_to?(:access_token)
|
110
113
|
options.merge(@init_options)
|
111
114
|
end
|
112
115
|
|
@@ -143,16 +146,14 @@ module Soaspec
|
|
143
146
|
|
144
147
|
# Returns the value at the provided xpath
|
145
148
|
# @param [RestClient::Response] response
|
146
|
-
# @param [String] xpath
|
149
|
+
# @param [String] xpath Path to find elements from
|
150
|
+
# @param [String] attribute Attribute to find path for
|
147
151
|
# @return [Enumerable] Value inside element found through Xpath
|
148
152
|
def xpath_elements_for(response: nil, xpath: nil, attribute: nil)
|
149
153
|
raise ArgumentError unless response && xpath
|
150
154
|
raise "Can't perform XPATH if response is not XML" unless Interpreter.response_type_for(response) == :xml
|
151
|
-
|
152
|
-
|
153
|
-
xpath = convert_to_pascal_case(xpath) if pascal_keys?
|
154
|
-
xpath = '//' + xpath
|
155
|
-
end
|
155
|
+
|
156
|
+
xpath = prefix_xpath(xpath, attribute)
|
156
157
|
temp_doc = Nokogiri.parse(response.body).dup
|
157
158
|
if strip_namespaces? && !xpath.include?(':')
|
158
159
|
temp_doc.remove_namespaces!
|
@@ -165,6 +166,7 @@ module Soaspec
|
|
165
166
|
# @return [Enumerable] List of values matching JSON path
|
166
167
|
def json_path_values_for(response, path, attribute: nil)
|
167
168
|
raise 'JSON does not support attributes' if attribute
|
169
|
+
|
168
170
|
if path[0] != '$'
|
169
171
|
path = convert_to_pascal_case(path) if pascal_keys?
|
170
172
|
path = '$..' + path
|
@@ -183,8 +185,9 @@ module Soaspec
|
|
183
185
|
case Interpreter.response_type_for(response)
|
184
186
|
when :xml
|
185
187
|
result = xpath_elements_for(response: response, xpath: path, attribute: attribute).first
|
186
|
-
raise NoElementAtPath, "No value at Xpath '#{path}'" unless result
|
188
|
+
raise NoElementAtPath, "No value at Xpath '#{prefix_xpath(path, attribute)}'" unless result
|
187
189
|
return result.inner_text if attribute.nil?
|
190
|
+
|
188
191
|
return result.attributes[attribute].inner_text
|
189
192
|
when :json
|
190
193
|
paths_to_check = path.split(',')
|
@@ -192,11 +195,13 @@ module Soaspec
|
|
192
195
|
json_path_values_for(response, path_to_check, attribute: attribute)
|
193
196
|
end.reject(&:empty?)
|
194
197
|
raise NoElementAtPath, "Path '#{path}' not found in '#{response.body}'" if matching_values.empty?
|
198
|
+
|
195
199
|
matching_values.first.first
|
196
200
|
when :hash
|
197
201
|
response.dig(path.split('.')) # Use path as Hash dig expression separating params via '.' TODO: Unit test
|
198
202
|
else
|
199
203
|
raise NoElementAtPath, 'Response is empty' if response.to_s.empty?
|
204
|
+
|
200
205
|
response.to_s[/path/] # Perform regular expression using path if not XML nor JSON TODO: Unit test
|
201
206
|
end
|
202
207
|
end
|
@@ -214,42 +219,10 @@ module Soaspec
|
|
214
219
|
end
|
215
220
|
end
|
216
221
|
|
217
|
-
# TODO: This and 'to_hash' method should be merged
|
218
|
-
# Convert XML or JSON response into a Hash
|
219
|
-
# @param [String] response Response as a String (either in XML or JSON)
|
220
|
-
# @return [Hash]
|
221
|
-
def extract_hash(response)
|
222
|
-
raise NoElementAtPath, "Empty Body. Can't assert on it" if response.body.empty?
|
223
|
-
case Interpreter.response_type_for response
|
224
|
-
when :json
|
225
|
-
converted = JSON.parse(response.body)
|
226
|
-
return converted.transform_keys_to_symbols if converted.is_a? Hash
|
227
|
-
return converted.map!(&:transform_keys_to_symbols) if converted.is_a? Array
|
228
|
-
raise 'Incorrect Type produced ' + converted.class
|
229
|
-
when :xml
|
230
|
-
parser = Nori.new(convert_tags_to: lambda { |tag| tag.snakecase.to_sym })
|
231
|
-
parser.parse(response.body)
|
232
|
-
else
|
233
|
-
raise "Neither XML nor JSON detected. It is #{type}. Don't know how to parse It is #{response.body}"
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
# @return [Hash] Hash representing response body
|
238
|
-
def to_hash(response)
|
239
|
-
case Interpreter.response_type_for(response)
|
240
|
-
when :xml
|
241
|
-
parser = Nori.new(strip_namespaces: strip_namespaces?, convert_tags_to: ->(tag) { tag.snakecase.to_sym })
|
242
|
-
parser.parse(response.body.to_s)
|
243
|
-
when :json
|
244
|
-
JSON.parse(response.body.to_s)
|
245
|
-
else
|
246
|
-
raise "Unable to interpret type of #{response.body}"
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
222
|
# @response [RestClient::Request] Request of API call. Either intended request or actual request
|
251
223
|
def request(response)
|
252
224
|
return 'Request not yet sent' if response.nil?
|
225
|
+
|
253
226
|
response.request
|
254
227
|
end
|
255
228
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Soaspec
|
2
2
|
# Methods to define parameters specific to REST handler
|
3
3
|
module RestParameters
|
4
|
-
|
5
4
|
# Defines method 'base_url_value' containing base URL used in REST requests
|
6
5
|
# @param [String] url Base Url to use in REST requests. Suburl is appended to this
|
7
6
|
def base_url(url)
|
8
7
|
raise ArgumentError, "Base Url passed must be a String for #{self} but was #{url.class}" unless url.is_a?(String)
|
8
|
+
|
9
9
|
define_method('base_url_value') { ERB.new(url).result(binding) }
|
10
10
|
end
|
11
11
|
|
@@ -37,6 +37,7 @@ module Soaspec
|
|
37
37
|
# @return [String] Client id obtained from credentials file
|
38
38
|
def client_id
|
39
39
|
raise '@client_id is not set. Set by specifying credentials file with "oauth2_file FILENAME" before this is called' unless @client_id
|
40
|
+
|
40
41
|
@client_id
|
41
42
|
end
|
42
43
|
|
@@ -45,6 +46,7 @@ module Soaspec
|
|
45
46
|
# @param [String] password Password to use
|
46
47
|
def basic_auth(user: nil, password: nil)
|
47
48
|
raise ArgumentError, "Must pass both 'user' and 'password' for #{self}" unless user && password
|
49
|
+
|
48
50
|
define_method('basic_auth_params') do
|
49
51
|
{ user: user, password: password }
|
50
52
|
end
|
@@ -72,11 +74,13 @@ module Soaspec
|
|
72
74
|
# @return [Hash] Hash with credentials in it
|
73
75
|
def load_credentials_hash(filename)
|
74
76
|
raise ArgumentError, "Filename passed must be a String for #{self} but was #{filename.class}" unless filename.is_a?(String)
|
77
|
+
|
75
78
|
full_path = Soaspec.credentials_folder ? File.join(Soaspec.credentials_folder, filename) : filename
|
76
79
|
full_path += '.yml' unless full_path.end_with?('.yml') # Automatically add 'yml' extension
|
77
80
|
file_hash = YAML.load_file(full_path)
|
78
81
|
raise "File at #{full_path} is not a hash" unless file_hash.is_a? Hash
|
82
|
+
|
79
83
|
file_hash.transform_keys_to_symbols
|
80
84
|
end
|
81
85
|
end
|
82
|
-
end
|
86
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
require_relative 'exchange_handler'
|
3
2
|
require_relative '../core_ext/hash'
|
4
3
|
require_relative '../not_found_errors'
|
@@ -7,7 +6,6 @@ require_relative '../interpreter'
|
|
7
6
|
require 'forwardable'
|
8
7
|
|
9
8
|
module Soaspec
|
10
|
-
|
11
9
|
# Accessors specific to SOAP handler
|
12
10
|
module SoapAccessors
|
13
11
|
# Define attributes set on root SOAP element
|
@@ -78,10 +76,8 @@ module Soaspec
|
|
78
76
|
name = self.class.to_s
|
79
77
|
end
|
80
78
|
super
|
81
|
-
|
82
|
-
|
83
|
-
set_remove_key(options, :template_name)
|
84
|
-
merged_options = Soaspec.log_api_traffic? ? default_options.merge(logging_options) : default_options
|
79
|
+
set_remove_keys(options, %i[operation default_hash template_name])
|
80
|
+
merged_options = Soaspec::SpecLogger.log_api_traffic? ? default_options.merge(logging_options) : default_options
|
85
81
|
merged_options.merge! savon_options
|
86
82
|
merged_options.merge!(options)
|
87
83
|
self.client = Savon.client(merged_options)
|
@@ -152,7 +148,7 @@ module Soaspec
|
|
152
148
|
# @param [Nokogiri::XML::Document]
|
153
149
|
def convert_to_lower_case(xml_doc)
|
154
150
|
xml_doc.traverse do |node|
|
155
|
-
node.name = node.name.downcase if node.
|
151
|
+
node.name = node.name.downcase if node.is_a?(Nokogiri::XML::Element)
|
156
152
|
end
|
157
153
|
end
|
158
154
|
|
@@ -162,6 +158,7 @@ module Soaspec
|
|
162
158
|
# @return [Enumerable] Elements found through Xpath
|
163
159
|
def xpath_elements_for(response: nil, xpath: nil, attribute: nil)
|
164
160
|
raise ArgumentError('response and xpath must be passed to method') unless response && xpath
|
161
|
+
|
165
162
|
xpath = "//*[@#{attribute}]" unless attribute.nil?
|
166
163
|
xpath = '//' + xpath if xpath[0] != '/'
|
167
164
|
temp_doc = response.doc.dup
|
@@ -184,6 +181,7 @@ module Soaspec
|
|
184
181
|
results = xpath_elements_for(response: response, xpath: path, attribute: attribute)
|
185
182
|
raise NoElementAtPath, "No value at Xpath '#{path}' in XML #{response.doc}" if results.empty?
|
186
183
|
return results.first.inner_text if attribute.nil?
|
184
|
+
|
187
185
|
results.first.attributes[attribute].inner_text
|
188
186
|
end
|
189
187
|
|
@@ -206,7 +204,6 @@ module Soaspec
|
|
206
204
|
|
207
205
|
# Convenience methods for once off usage of a SOAP request
|
208
206
|
class << self
|
209
|
-
|
210
207
|
# Implement undefined setter with []= for FactoryBot to use without needing to define params to set
|
211
208
|
# @param [Object] method_name Name of method not defined
|
212
209
|
# @param [Object] args Arguments passed to method
|
@@ -231,6 +228,5 @@ module Soaspec
|
|
231
228
|
operations.include?(method_name) || super
|
232
229
|
end
|
233
230
|
end
|
234
|
-
|
235
231
|
end
|
236
|
-
end
|
232
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# Convenience methods to set Exchange specific properties
|
2
2
|
# Will be used when creating a subclass of Exchange
|
3
3
|
module ExchangeProperties
|
4
|
-
|
5
4
|
# Set default exchange handler for this exchange
|
6
5
|
# This is helpful for when you need a new exchange handler created for each exchange
|
7
6
|
# @param [Class] handler_class Class of ExchangeHandler to set Exchange to use
|
@@ -25,4 +24,4 @@ module ExchangeProperties
|
|
25
24
|
true
|
26
25
|
end
|
27
26
|
end
|
28
|
-
end
|
27
|
+
end
|
data/lib/soaspec/exe_helpers.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
|
2
1
|
require 'fileutils'
|
3
2
|
module Soaspec
|
4
3
|
# Help with tasks common to soaspec executables
|
5
4
|
module ExeHelpers
|
6
|
-
|
7
5
|
# Create files in project depending on type of project
|
8
6
|
# @param [String] type Type of project to create, e.g., 'soap', 'rest'
|
9
7
|
def create_files_for(type)
|
@@ -19,9 +17,10 @@ module Soaspec
|
|
19
17
|
end
|
20
18
|
|
21
19
|
# @param [Array] filenames List of files to create
|
22
|
-
def create_files(filenames)
|
20
|
+
def create_files(filenames, ignore_if_present: false)
|
23
21
|
raise ArgumentError, 'Expected filenames to be an Array' unless filenames.is_a? Array
|
24
|
-
|
22
|
+
|
23
|
+
filenames.each { |name| create_file filename: name, ignore_if_present: ignore_if_present }
|
25
24
|
end
|
26
25
|
|
27
26
|
# Spec task string depending upon whether virtual is used
|
@@ -45,15 +44,15 @@ module Soaspec
|
|
45
44
|
|
46
45
|
# @param [String] filename Name of the file to create
|
47
46
|
# @param [String] content Content to place inside file
|
47
|
+
# @param [Boolean] ignore_if_present Don't complain if file is present
|
48
48
|
def create_file(filename: nil, content: nil, ignore_if_present: false, erb: true)
|
49
49
|
raise 'Need to pass filename' unless filename
|
50
|
+
|
50
51
|
content ||= retrieve_contents(filename, erb)
|
51
52
|
create_folder File.split(filename).first
|
52
53
|
if File.exist? filename
|
53
54
|
old_content = File.read(filename)
|
54
|
-
if old_content != content && !ignore_if_present
|
55
|
-
warn "!! #{filename} already exists and differs from template"
|
56
|
-
end
|
55
|
+
warn "!! #{filename} already exists and differs from template" if old_content != content && !ignore_if_present
|
57
56
|
else
|
58
57
|
File.open(filename, 'w') { |f| f.puts content }
|
59
58
|
puts 'Created: ' + filename
|
@@ -82,6 +81,5 @@ module Soaspec
|
|
82
81
|
def generated_soap_spec_for(operation)
|
83
82
|
ERB.new(File.read(File.join(File.dirname(__FILE__), 'generator', 'spec/dynamic_soap_spec.rb.erb'))).result(binding)
|
84
83
|
end
|
85
|
-
|
86
84
|
end
|
87
|
-
end
|
85
|
+
end
|
data/lib/soaspec/interpreter.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
|
2
1
|
# Help interpret the general type of a particular object
|
3
2
|
class Interpreter
|
4
|
-
|
5
3
|
class << self
|
6
4
|
# @param [Object] response API response
|
7
5
|
# @return [Symbol] Type of provided response
|
@@ -38,4 +36,4 @@ class Interpreter
|
|
38
36
|
false
|
39
37
|
end
|
40
38
|
end
|
41
|
-
end
|
39
|
+
end
|
data/lib/soaspec/matchers.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
require_relative 'core_ext/hash'
|
3
2
|
require_relative 'not_found_errors'
|
4
3
|
|
@@ -61,7 +60,6 @@ end
|
|
61
60
|
RSpec::Matchers.alias_matcher :have_jsonpath_value, :have_xpath_value
|
62
61
|
|
63
62
|
RSpec::Matchers.define :be_found do
|
64
|
-
|
65
63
|
match do |exchange|
|
66
64
|
expect(exchange.exchange_handler.found?(exchange.response)).to be true
|
67
65
|
end
|
@@ -91,6 +89,7 @@ RSpec::Matchers.define :be_successful do
|
|
91
89
|
failure_list << "Expected value at json '#{path}' to be '#{value}' but was '#{exchange[path]}'" unless exchange[path] == value
|
92
90
|
end
|
93
91
|
raise failure_list.to_s unless failure_list.empty?
|
92
|
+
|
94
93
|
true
|
95
94
|
end
|
96
95
|
end
|
data/lib/soaspec/o_auth2.rb
CHANGED
@@ -38,6 +38,7 @@ module Soaspec
|
|
38
38
|
params[:token_url] ||= Soaspec::OAuth2.token_url
|
39
39
|
raise ArgumentError, 'client_id and client_secret not set' unless params[:client_id] && params[:client_secret]
|
40
40
|
raise ArgumentError, 'token_url mandatory' unless params[:token_url]
|
41
|
+
|
41
42
|
self.params = params
|
42
43
|
params[:username] = api_username || ERB.new(params[:username]).result(binding) if params[:username]
|
43
44
|
params[:security_token] = ERB.new(params[:security_token]).result(binding) if params[:security_token]
|
@@ -99,4 +100,4 @@ module Soaspec
|
|
99
100
|
end)
|
100
101
|
end
|
101
102
|
end
|
102
|
-
end
|
103
|
+
end
|