soaspec 0.2.33 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +15 -15
- data/.gitlab-ci.yml +62 -62
- data/.rspec +3 -3
- data/.rubocop.yml +2 -2
- data/CODE_OF_CONDUCT.md +74 -74
- data/ChangeLog +643 -632
- data/Dockerfile +7 -7
- data/Gemfile +8 -8
- data/LICENSE.txt +21 -21
- data/README.md +253 -231
- data/Rakefile +52 -52
- data/Todo.md +16 -16
- data/exe/soaspec +140 -138
- data/exe/xml_to_yaml_file +43 -43
- data/lib/soaspec.rb +118 -106
- data/lib/soaspec/baseline.rb +82 -22
- data/lib/soaspec/core_ext/hash.rb +44 -44
- data/lib/soaspec/cucumber/generic_steps.rb +94 -94
- data/lib/soaspec/demo.rb +6 -6
- data/lib/soaspec/errors.rb +24 -24
- data/lib/soaspec/exchange/exchange.rb +131 -129
- data/lib/soaspec/exchange/exchange_extractor.rb +105 -90
- data/lib/soaspec/exchange/exchange_properties.rb +28 -28
- data/lib/soaspec/exchange/exchange_repeater.rb +21 -21
- data/lib/soaspec/exchange/request_builder.rb +108 -70
- data/lib/soaspec/exchange/variable_storer.rb +24 -24
- data/lib/soaspec/exchange_handlers/exchange_handler.rb +98 -98
- data/lib/soaspec/exchange_handlers/exchange_handler_defaults.rb +61 -61
- data/lib/soaspec/exchange_handlers/handler_accessors.rb +132 -132
- data/lib/soaspec/exchange_handlers/request/rest_request.rb +77 -59
- data/lib/soaspec/exchange_handlers/request/soap_request.rb +41 -41
- data/lib/soaspec/exchange_handlers/response_extractor.rb +84 -84
- data/lib/soaspec/exchange_handlers/rest_exchanger_factory.rb +111 -111
- data/lib/soaspec/exchange_handlers/rest_handler.rb +307 -307
- data/lib/soaspec/exchange_handlers/rest_methods.rb +65 -65
- data/lib/soaspec/exchange_handlers/rest_parameters.rb +112 -112
- data/lib/soaspec/exchange_handlers/rest_parameters_defaults.rb +42 -42
- data/lib/soaspec/exchange_handlers/soap_handler.rb +241 -241
- data/lib/soaspec/exe_helpers.rb +94 -94
- data/lib/soaspec/generate_server.rb +48 -48
- data/lib/soaspec/generator/.rspec.erb +5 -5
- data/lib/soaspec/generator/.travis.yml.erb +5 -5
- data/lib/soaspec/generator/Gemfile.erb +8 -8
- data/lib/soaspec/generator/README.md.erb +29 -29
- data/lib/soaspec/generator/Rakefile.erb +20 -19
- data/lib/soaspec/generator/config/data/default.yml.erb +2 -2
- data/lib/soaspec/generator/css/bootstrap.css +6833 -6833
- data/lib/soaspec/generator/features/support/env.rb.erb +3 -3
- data/lib/soaspec/generator/generate_exchange.html.erb +47 -47
- data/lib/soaspec/generator/lib/blz_service.rb.erb +26 -26
- data/lib/soaspec/generator/lib/dynamic_class_content.rb.erb +12 -12
- data/lib/soaspec/generator/lib/new_rest_service.rb.erb +56 -56
- data/lib/soaspec/generator/lib/new_soap_service.rb.erb +29 -29
- data/lib/soaspec/generator/lib/package_service.rb.erb +2 -2
- data/lib/soaspec/generator/lib/shared_example.rb.erb +8 -8
- data/lib/soaspec/generator/spec/dynamic_soap_spec.rb.erb +12 -12
- data/lib/soaspec/generator/spec/rest_spec.rb.erb +9 -9
- data/lib/soaspec/generator/spec/soap_spec.rb.erb +51 -51
- data/lib/soaspec/generator/spec/spec_helper.rb.erb +23 -23
- data/lib/soaspec/generator/template/soap_template.xml +6 -6
- data/lib/soaspec/indifferent_hash.rb +9 -9
- data/lib/soaspec/interpreter.rb +70 -70
- data/lib/soaspec/matchers.rb +136 -140
- data/lib/soaspec/o_auth2.rb +142 -142
- data/lib/soaspec/soaspec_shared_examples.rb +26 -26
- data/lib/soaspec/spec_logger.rb +143 -143
- data/lib/soaspec/template_reader.rb +30 -30
- data/lib/soaspec/test_server/bank.wsdl +90 -90
- data/lib/soaspec/test_server/get_bank.rb +166 -166
- data/lib/soaspec/test_server/id_manager.rb +41 -41
- data/lib/soaspec/test_server/invoices.rb +29 -29
- data/lib/soaspec/test_server/namespace.xml +14 -14
- data/lib/soaspec/test_server/note.xml +5 -5
- data/lib/soaspec/test_server/puppy_service.rb +21 -21
- data/lib/soaspec/test_server/test_attribute.rb +14 -14
- data/lib/soaspec/test_server/test_namespace.rb +14 -14
- data/lib/soaspec/version.rb +6 -6
- data/lib/soaspec/virtual_server.rb +193 -190
- data/lib/soaspec/wait.rb +43 -43
- data/lib/soaspec/wsdl_generator.rb +215 -215
- data/soaspec.gemspec +58 -58
- data/test.wsdl +116 -116
- data/test.xml +10 -10
- data/test_wsdl.rb +43 -43
- metadata +3 -3
data/lib/soaspec/o_auth2.rb
CHANGED
@@ -1,142 +1,142 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'erb'
|
4
|
-
|
5
|
-
module Soaspec
|
6
|
-
# Handles working with OAuth2
|
7
|
-
class OAuth2
|
8
|
-
# How often to refresh access token
|
9
|
-
@refresh_token = :always
|
10
|
-
# List of access tokens. They are mapped according to the OAuth parameters used
|
11
|
-
@access_tokens = {}
|
12
|
-
# List of instance URLs. They are mapped according to the OAuth parameters used
|
13
|
-
@instance_urls = {}
|
14
|
-
# Whether to see params sent to & received from oauth URL
|
15
|
-
@request_message = true
|
16
|
-
# How many times to attempt to authenticate before raising exception
|
17
|
-
@retry_limit = 2
|
18
|
-
class << self
|
19
|
-
# Default token url used across entire suite
|
20
|
-
attr_accessor :token_url
|
21
|
-
# @attr [Symbol] refresh_token How often to refresh access token
|
22
|
-
# Values are:
|
23
|
-
# * :always - (Default) Request token from token url every time it is needed
|
24
|
-
# * :once - Request token once for the entire execution of the suite
|
25
|
-
attr_accessor :refresh_token
|
26
|
-
# @attr [Hash] access_tokens List of access tokens. They are mapped according to the OAuth parameters used
|
27
|
-
attr_accessor :access_tokens
|
28
|
-
# List of URLs to that define the instance of an application
|
29
|
-
attr_accessor :instance_urls
|
30
|
-
# Specify whether to see params sent to and retrieved from oauth. This will put password in log file, only recommended for debugging
|
31
|
-
attr_writer :debug_oauth
|
32
|
-
# @return [Boolean] Whether to include request message describing OAuth (either full or simplified)
|
33
|
-
attr_writer :request_message
|
34
|
-
# @return [Integer] How many times to attempt to authenticate before raising exception
|
35
|
-
attr_accessor :retry_limit
|
36
|
-
# @return [Boolean] Whether to see params sent to & received from oauth URL
|
37
|
-
def debug_oauth?
|
38
|
-
@debug_oauth || false
|
39
|
-
end
|
40
|
-
|
41
|
-
# @return [Boolean] Whether to include request message describing OAuth (either full or simplified)
|
42
|
-
def request_message?
|
43
|
-
@request_message
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# @attr [Hash] OAuth parameters
|
48
|
-
attr_accessor :params
|
49
|
-
# @attr [Integer] Count of tries to obtain access token
|
50
|
-
attr_accessor :retry_count
|
51
|
-
|
52
|
-
# @param [Hash] params_sent Parameters to make OAuth request
|
53
|
-
# @option params_sent [token_url] URL to retrieve OAuth token from. @Note this can be set globally instead of here
|
54
|
-
# @option params_sent [client_id] Client ID
|
55
|
-
# @option params_sent [client_secret] Client Secret
|
56
|
-
# @option params_sent [username] Username used in password grant
|
57
|
-
# @option params_sent [password] Password used in password grant
|
58
|
-
# @option params_sent [security_token] Security Token used in password grant
|
59
|
-
# @param [String] api_username Username to use which can be set by Soaspec::ExchangeHandler
|
60
|
-
def initialize(params_sent, api_username = nil)
|
61
|
-
self.retry_count = 0 # No initial tries at getting access token
|
62
|
-
params = params_sent.transform_keys_to_symbols
|
63
|
-
params[:token_url] ||= Soaspec::OAuth2.token_url
|
64
|
-
raise ArgumentError, 'client_id and client_secret not set' unless params[:client_id] && params[:client_secret]
|
65
|
-
raise ArgumentError, 'token_url mandatory' unless params[:token_url]
|
66
|
-
|
67
|
-
self.params = params
|
68
|
-
params[:username] = api_username || ERB.new(params[:username]).result(binding) if params[:username]
|
69
|
-
params[:security_token] = ERB.new(params[:security_token]).result(binding) if params[:security_token]
|
70
|
-
params[:token_url] = ERB.new(params[:token_url]).result(binding) if params[:token_url]
|
71
|
-
params[:password] = ERB.new(params[:password]).result(binding) if params[:password]
|
72
|
-
end
|
73
|
-
|
74
|
-
# Retrieve whether to debug oauth parameters based on global settings
|
75
|
-
# @return [Boolean] Whether to see params sent to & received from oauth URL
|
76
|
-
def debug_oauth?
|
77
|
-
self.class.debug_oauth?
|
78
|
-
end
|
79
|
-
|
80
|
-
# Retrieve instance_url according to access token response.
|
81
|
-
# Some applications have a different instance
|
82
|
-
# It's assumed this will be constant for a set of oauth parameters
|
83
|
-
# @return [String] Instance url
|
84
|
-
def instance_url
|
85
|
-
Soaspec::OAuth2.instance_urls[params] ||= response['instance_url']
|
86
|
-
end
|
87
|
-
|
88
|
-
# @return [String] Existing or new access token, dependent on refresh_token attribute
|
89
|
-
def access_token
|
90
|
-
Soaspec::SpecLogger.info request_message if self.class.request_message?
|
91
|
-
case Soaspec::OAuth2.refresh_token
|
92
|
-
when :once
|
93
|
-
Soaspec::OAuth2.access_tokens[params] ||= response['access_token']
|
94
|
-
else # Default is :always
|
95
|
-
response['access_token']
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# @return [Hash] Hash containing access token parameters
|
100
|
-
def response
|
101
|
-
Soaspec::SpecLogger.info "using oauth_params: #{params}" if debug_oauth?
|
102
|
-
response = RestClient.post(params[:token_url], payload, cache_control: 'no_cache', verify_ssl: false)
|
103
|
-
rescue RestClient::Exception => e
|
104
|
-
Soaspec::SpecLogger.info(["oauth_error: #{e.message}", "oauth_response: #{e.response}"])
|
105
|
-
self.retry_count += 1
|
106
|
-
sleep 0.1 # Wait if a bit before retying obtaining access token
|
107
|
-
retry if retry_count < self.class.retry_limit
|
108
|
-
raise e
|
109
|
-
else
|
110
|
-
Soaspec::SpecLogger.info(["response: \n headers: #{response&.headers}\n body: #{response}\n"]) if debug_oauth?
|
111
|
-
JSON.parse(response)
|
112
|
-
end
|
113
|
-
|
114
|
-
# @return [String] String to represent OAuth for logging logs
|
115
|
-
def request_message
|
116
|
-
if debug_oauth?
|
117
|
-
"request_params: #{payload}"
|
118
|
-
else
|
119
|
-
params[:username] ? "User '#{params[:username]}'" : 'client_credentials'
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# @return [String] Password to use in OAuth request
|
124
|
-
def password
|
125
|
-
params[:security_token] ? (params[:password] + params[:security_token]) : params[:password]
|
126
|
-
end
|
127
|
-
|
128
|
-
# Payload to add to o-auth request dependent on params provided
|
129
|
-
# @return [Hash] Payload for retrieving OAuth access token
|
130
|
-
def payload
|
131
|
-
payload = { client_id: params[:client_id], client_secret: params[:client_secret] }
|
132
|
-
payload.merge(if params[:password] && params[:username]
|
133
|
-
{
|
134
|
-
grant_type: 'password', username: params[:username],
|
135
|
-
password: password, multipart: true
|
136
|
-
}
|
137
|
-
else
|
138
|
-
{ grant_type: 'client_credentials' }
|
139
|
-
end)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Soaspec
|
6
|
+
# Handles working with OAuth2
|
7
|
+
class OAuth2
|
8
|
+
# How often to refresh access token
|
9
|
+
@refresh_token = :always
|
10
|
+
# List of access tokens. They are mapped according to the OAuth parameters used
|
11
|
+
@access_tokens = {}
|
12
|
+
# List of instance URLs. They are mapped according to the OAuth parameters used
|
13
|
+
@instance_urls = {}
|
14
|
+
# Whether to see params sent to & received from oauth URL
|
15
|
+
@request_message = true
|
16
|
+
# How many times to attempt to authenticate before raising exception
|
17
|
+
@retry_limit = 2
|
18
|
+
class << self
|
19
|
+
# Default token url used across entire suite
|
20
|
+
attr_accessor :token_url
|
21
|
+
# @attr [Symbol] refresh_token How often to refresh access token
|
22
|
+
# Values are:
|
23
|
+
# * :always - (Default) Request token from token url every time it is needed
|
24
|
+
# * :once - Request token once for the entire execution of the suite
|
25
|
+
attr_accessor :refresh_token
|
26
|
+
# @attr [Hash] access_tokens List of access tokens. They are mapped according to the OAuth parameters used
|
27
|
+
attr_accessor :access_tokens
|
28
|
+
# List of URLs to that define the instance of an application
|
29
|
+
attr_accessor :instance_urls
|
30
|
+
# Specify whether to see params sent to and retrieved from oauth. This will put password in log file, only recommended for debugging
|
31
|
+
attr_writer :debug_oauth
|
32
|
+
# @return [Boolean] Whether to include request message describing OAuth (either full or simplified)
|
33
|
+
attr_writer :request_message
|
34
|
+
# @return [Integer] How many times to attempt to authenticate before raising exception
|
35
|
+
attr_accessor :retry_limit
|
36
|
+
# @return [Boolean] Whether to see params sent to & received from oauth URL
|
37
|
+
def debug_oauth?
|
38
|
+
@debug_oauth || false
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Boolean] Whether to include request message describing OAuth (either full or simplified)
|
42
|
+
def request_message?
|
43
|
+
@request_message
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @attr [Hash] OAuth parameters
|
48
|
+
attr_accessor :params
|
49
|
+
# @attr [Integer] Count of tries to obtain access token
|
50
|
+
attr_accessor :retry_count
|
51
|
+
|
52
|
+
# @param [Hash] params_sent Parameters to make OAuth request
|
53
|
+
# @option params_sent [token_url] URL to retrieve OAuth token from. @Note this can be set globally instead of here
|
54
|
+
# @option params_sent [client_id] Client ID
|
55
|
+
# @option params_sent [client_secret] Client Secret
|
56
|
+
# @option params_sent [username] Username used in password grant
|
57
|
+
# @option params_sent [password] Password used in password grant
|
58
|
+
# @option params_sent [security_token] Security Token used in password grant
|
59
|
+
# @param [String] api_username Username to use which can be set by Soaspec::ExchangeHandler
|
60
|
+
def initialize(params_sent, api_username = nil)
|
61
|
+
self.retry_count = 0 # No initial tries at getting access token
|
62
|
+
params = params_sent.transform_keys_to_symbols
|
63
|
+
params[:token_url] ||= Soaspec::OAuth2.token_url
|
64
|
+
raise ArgumentError, 'client_id and client_secret not set' unless params[:client_id] && params[:client_secret]
|
65
|
+
raise ArgumentError, 'token_url mandatory' unless params[:token_url]
|
66
|
+
|
67
|
+
self.params = params
|
68
|
+
params[:username] = api_username || ERB.new(params[:username]).result(binding) if params[:username]
|
69
|
+
params[:security_token] = ERB.new(params[:security_token]).result(binding) if params[:security_token]
|
70
|
+
params[:token_url] = ERB.new(params[:token_url]).result(binding) if params[:token_url]
|
71
|
+
params[:password] = ERB.new(params[:password]).result(binding) if params[:password]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Retrieve whether to debug oauth parameters based on global settings
|
75
|
+
# @return [Boolean] Whether to see params sent to & received from oauth URL
|
76
|
+
def debug_oauth?
|
77
|
+
self.class.debug_oauth?
|
78
|
+
end
|
79
|
+
|
80
|
+
# Retrieve instance_url according to access token response.
|
81
|
+
# Some applications have a different instance
|
82
|
+
# It's assumed this will be constant for a set of oauth parameters
|
83
|
+
# @return [String] Instance url
|
84
|
+
def instance_url
|
85
|
+
Soaspec::OAuth2.instance_urls[params] ||= response['instance_url']
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [String] Existing or new access token, dependent on refresh_token attribute
|
89
|
+
def access_token
|
90
|
+
Soaspec::SpecLogger.info request_message if self.class.request_message?
|
91
|
+
case Soaspec::OAuth2.refresh_token
|
92
|
+
when :once
|
93
|
+
Soaspec::OAuth2.access_tokens[params] ||= response['access_token']
|
94
|
+
else # Default is :always
|
95
|
+
response['access_token']
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# @return [Hash] Hash containing access token parameters
|
100
|
+
def response
|
101
|
+
Soaspec::SpecLogger.info "using oauth_params: #{params}" if debug_oauth?
|
102
|
+
response = RestClient.post(params[:token_url], payload, cache_control: 'no_cache', verify_ssl: false)
|
103
|
+
rescue RestClient::Exception => e
|
104
|
+
Soaspec::SpecLogger.info(["oauth_error: #{e.message}", "oauth_response: #{e.response}"])
|
105
|
+
self.retry_count += 1
|
106
|
+
sleep 0.1 # Wait if a bit before retying obtaining access token
|
107
|
+
retry if retry_count < self.class.retry_limit
|
108
|
+
raise e
|
109
|
+
else
|
110
|
+
Soaspec::SpecLogger.info(["response: \n headers: #{response&.headers}\n body: #{response}\n"]) if debug_oauth?
|
111
|
+
JSON.parse(response)
|
112
|
+
end
|
113
|
+
|
114
|
+
# @return [String] String to represent OAuth for logging logs
|
115
|
+
def request_message
|
116
|
+
if debug_oauth?
|
117
|
+
"request_params: #{payload}"
|
118
|
+
else
|
119
|
+
params[:username] ? "User '#{params[:username]}'" : 'client_credentials'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# @return [String] Password to use in OAuth request
|
124
|
+
def password
|
125
|
+
params[:security_token] ? (params[:password] + params[:security_token]) : params[:password]
|
126
|
+
end
|
127
|
+
|
128
|
+
# Payload to add to o-auth request dependent on params provided
|
129
|
+
# @return [Hash] Payload for retrieving OAuth access token
|
130
|
+
def payload
|
131
|
+
payload = { client_id: params[:client_id], client_secret: params[:client_secret] }
|
132
|
+
payload.merge(if params[:password] && params[:username]
|
133
|
+
{
|
134
|
+
grant_type: 'password', username: params[:username],
|
135
|
+
password: password, multipart: true
|
136
|
+
}
|
137
|
+
else
|
138
|
+
{ grant_type: 'client_credentials' }
|
139
|
+
end)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -1,26 +1,26 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rspec'
|
4
|
-
|
5
|
-
RSpec.shared_examples_for 'success scenario' do
|
6
|
-
it 'has successful status code' do
|
7
|
-
expect(described_class.successful_status_code?).to be true
|
8
|
-
end
|
9
|
-
context 'has expected mandatory elements' do
|
10
|
-
described_class.exchange_handler.expected_mandatory_elements.each do |mandatory_element|
|
11
|
-
it mandatory_element do
|
12
|
-
expect(described_class).to contain_key mandatory_element
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
described_class.exchange_handler.expected_mandatory_xpath_values.each do |xpath, value|
|
17
|
-
it "has xpath '#{xpath}' equal to '#{value}'" do
|
18
|
-
expect(described_class).to have_xpath_value(xpath => value)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
described_class.exchange_handler.expected_mandatory_json_values.each do |xpath, value|
|
22
|
-
it "has json '#{xpath}' equal to '#{value}'" do
|
23
|
-
expect(described_class).to have_xpath_value(xpath => value)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
|
5
|
+
RSpec.shared_examples_for 'success scenario' do
|
6
|
+
it 'has successful status code' do
|
7
|
+
expect(described_class.successful_status_code?).to be true
|
8
|
+
end
|
9
|
+
context 'has expected mandatory elements' do
|
10
|
+
described_class.exchange_handler.expected_mandatory_elements.each do |mandatory_element|
|
11
|
+
it mandatory_element do
|
12
|
+
expect(described_class).to contain_key mandatory_element
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
described_class.exchange_handler.expected_mandatory_xpath_values.each do |xpath, value|
|
17
|
+
it "has xpath '#{xpath}' equal to '#{value}'" do
|
18
|
+
expect(described_class).to have_xpath_value(xpath => value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
described_class.exchange_handler.expected_mandatory_json_values.each do |xpath, value|
|
22
|
+
it "has json '#{xpath}' equal to '#{value}'" do
|
23
|
+
expect(described_class).to have_xpath_value(xpath => value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/soaspec/spec_logger.rb
CHANGED
@@ -1,143 +1,143 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'logger'
|
4
|
-
require 'fileutils'
|
5
|
-
require 'colorize'
|
6
|
-
|
7
|
-
module Soaspec
|
8
|
-
# Custom class for logging API traffic
|
9
|
-
class ApiLogger < Logger
|
10
|
-
#
|
11
|
-
# Rewrite << to use info logger with formatting
|
12
|
-
#
|
13
|
-
def <<(msg)
|
14
|
-
info msg
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# Handles logs of API requests and responses
|
19
|
-
class SpecLogger
|
20
|
-
# Folder to put API traffic logs
|
21
|
-
@traffic_folder = 'logs'
|
22
|
-
# Whether to output api traffic to terminal
|
23
|
-
@output_to_terminal = false
|
24
|
-
# Color shown when displaying in terminal
|
25
|
-
@terminal_color = :light_blue
|
26
|
-
# Whether to output API traffic to log file
|
27
|
-
@output_to_file = true
|
28
|
-
# Time test run. Will only be calculated once once called
|
29
|
-
@time_test_run = Time.now.strftime('%Y-%m-%d_%H_%M_%S')
|
30
|
-
# By default file is based on time
|
31
|
-
@traffic_file = nil
|
32
|
-
# Name of program to include in logs
|
33
|
-
@progname
|
34
|
-
class << self
|
35
|
-
# Folder to put API traffic logs
|
36
|
-
attr_accessor :traffic_folder
|
37
|
-
# Color shown when displaying in terminal
|
38
|
-
attr_accessor :terminal_color
|
39
|
-
# Readers for log parameters
|
40
|
-
attr_reader :output_to_terminal, :output_to_file, :time_test_run
|
41
|
-
# @return [String] Name of program to include in logs
|
42
|
-
attr_accessor :progname
|
43
|
-
# @return [String] String representing date format to use for traffic
|
44
|
-
attr_writer :time_format
|
45
|
-
# Logger used to log API requests
|
46
|
-
attr_accessor :logger
|
47
|
-
|
48
|
-
# String representing date format to use for traffic
|
49
|
-
def time_format
|
50
|
-
@time_format || '%H:%M:%S'
|
51
|
-
end
|
52
|
-
|
53
|
-
# Set file to log traffic to
|
54
|
-
# @param [String] file Path to traffic file to use
|
55
|
-
def traffic_file=(file)
|
56
|
-
@traffic_file = file
|
57
|
-
reset_log
|
58
|
-
end
|
59
|
-
|
60
|
-
# @return [String] Traffic file to create logs at
|
61
|
-
def traffic_file
|
62
|
-
return File.join(traffic_folder, @traffic_file) if @traffic_file
|
63
|
-
|
64
|
-
filename = "traffic_#{time_test_run}.log"
|
65
|
-
File.join(traffic_folder, filename)
|
66
|
-
end
|
67
|
-
|
68
|
-
# Unset Logger object. It will be recreated on next time 'info' is called
|
69
|
-
def reset_log
|
70
|
-
@logger = nil
|
71
|
-
RestClient.log = nil
|
72
|
-
end
|
73
|
-
|
74
|
-
# Whether to log all API traffic
|
75
|
-
def log_api_traffic=(set)
|
76
|
-
@log_api_traffic = set
|
77
|
-
reset_log
|
78
|
-
end
|
79
|
-
|
80
|
-
# @return [Boolean] Whether to log all API traffic
|
81
|
-
def log_api_traffic?
|
82
|
-
@log_api_traffic.nil? ? true : @log_api_traffic
|
83
|
-
end
|
84
|
-
|
85
|
-
# @param [Symbol, Boolean] value # Whether to output API traffic to log file
|
86
|
-
def output_to_file=(value)
|
87
|
-
@output_to_file = value
|
88
|
-
reset_log
|
89
|
-
end
|
90
|
-
|
91
|
-
# @param [Symbol, Boolean] value # Whether to output API traffic to STDOUT
|
92
|
-
def output_to_terminal=(value)
|
93
|
-
@output_to_terminal = value
|
94
|
-
reset_log
|
95
|
-
end
|
96
|
-
|
97
|
-
# Create new log file if necessary and setup logging level
|
98
|
-
# @return [Logger] Logger class to record API traffic
|
99
|
-
def create
|
100
|
-
create_log_file
|
101
|
-
@logger = ApiLogger.new(traffic_file) # Where request and responses of APIs are stored
|
102
|
-
@logger.progname = progname || 'SpecLog'
|
103
|
-
@logger.formatter = proc do |_severity, datetime, progname, msg|
|
104
|
-
message = "#{progname}, [#{datetime.strftime(time_format)}] : #{msg}\n"
|
105
|
-
print message.colorize(terminal_color) if @output_to_terminal
|
106
|
-
message if @output_to_file
|
107
|
-
end
|
108
|
-
RestClient.log = @logger
|
109
|
-
@logger
|
110
|
-
end
|
111
|
-
|
112
|
-
# Log a message using Soaspec logger
|
113
|
-
# Logger (and it's file) will be created if it's not already set
|
114
|
-
# @param [String, Array] message The message to add to the logger or list of messages
|
115
|
-
def info(message)
|
116
|
-
return unless log_api_traffic?
|
117
|
-
|
118
|
-
create unless @logger
|
119
|
-
if message.respond_to? :each
|
120
|
-
message.each do |message_item|
|
121
|
-
info(message_item)
|
122
|
-
end
|
123
|
-
else
|
124
|
-
if block_given?
|
125
|
-
@logger.info(message) { yield }
|
126
|
-
else
|
127
|
-
@logger.info(message)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
private
|
133
|
-
|
134
|
-
# Create folder and file to store logs
|
135
|
-
def create_log_file
|
136
|
-
return if File.exist?(traffic_file)
|
137
|
-
|
138
|
-
FileUtils.mkdir_p traffic_folder
|
139
|
-
FileUtils.touch traffic_file
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'colorize'
|
6
|
+
|
7
|
+
module Soaspec
|
8
|
+
# Custom class for logging API traffic
|
9
|
+
class ApiLogger < Logger
|
10
|
+
#
|
11
|
+
# Rewrite << to use info logger with formatting
|
12
|
+
#
|
13
|
+
def <<(msg)
|
14
|
+
info msg
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Handles logs of API requests and responses
|
19
|
+
class SpecLogger
|
20
|
+
# Folder to put API traffic logs
|
21
|
+
@traffic_folder = 'logs'
|
22
|
+
# Whether to output api traffic to terminal
|
23
|
+
@output_to_terminal = false
|
24
|
+
# Color shown when displaying in terminal
|
25
|
+
@terminal_color = :light_blue
|
26
|
+
# Whether to output API traffic to log file
|
27
|
+
@output_to_file = true
|
28
|
+
# Time test run. Will only be calculated once once called
|
29
|
+
@time_test_run = Time.now.strftime('%Y-%m-%d_%H_%M_%S')
|
30
|
+
# By default file is based on time
|
31
|
+
@traffic_file = nil
|
32
|
+
# Name of program to include in logs
|
33
|
+
@progname
|
34
|
+
class << self
|
35
|
+
# Folder to put API traffic logs
|
36
|
+
attr_accessor :traffic_folder
|
37
|
+
# Color shown when displaying in terminal
|
38
|
+
attr_accessor :terminal_color
|
39
|
+
# Readers for log parameters
|
40
|
+
attr_reader :output_to_terminal, :output_to_file, :time_test_run
|
41
|
+
# @return [String] Name of program to include in logs
|
42
|
+
attr_accessor :progname
|
43
|
+
# @return [String] String representing date format to use for traffic
|
44
|
+
attr_writer :time_format
|
45
|
+
# Logger used to log API requests
|
46
|
+
attr_accessor :logger
|
47
|
+
|
48
|
+
# String representing date format to use for traffic
|
49
|
+
def time_format
|
50
|
+
@time_format || '%H:%M:%S'
|
51
|
+
end
|
52
|
+
|
53
|
+
# Set file to log traffic to
|
54
|
+
# @param [String] file Path to traffic file to use
|
55
|
+
def traffic_file=(file)
|
56
|
+
@traffic_file = file
|
57
|
+
reset_log
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [String] Traffic file to create logs at
|
61
|
+
def traffic_file
|
62
|
+
return File.join(traffic_folder, @traffic_file) if @traffic_file
|
63
|
+
|
64
|
+
filename = "traffic_#{time_test_run}.log"
|
65
|
+
File.join(traffic_folder, filename)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Unset Logger object. It will be recreated on next time 'info' is called
|
69
|
+
def reset_log
|
70
|
+
@logger = nil
|
71
|
+
RestClient.log = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
# Whether to log all API traffic
|
75
|
+
def log_api_traffic=(set)
|
76
|
+
@log_api_traffic = set
|
77
|
+
reset_log
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Boolean] Whether to log all API traffic
|
81
|
+
def log_api_traffic?
|
82
|
+
@log_api_traffic.nil? ? true : @log_api_traffic
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param [Symbol, Boolean] value # Whether to output API traffic to log file
|
86
|
+
def output_to_file=(value)
|
87
|
+
@output_to_file = value
|
88
|
+
reset_log
|
89
|
+
end
|
90
|
+
|
91
|
+
# @param [Symbol, Boolean] value # Whether to output API traffic to STDOUT
|
92
|
+
def output_to_terminal=(value)
|
93
|
+
@output_to_terminal = value
|
94
|
+
reset_log
|
95
|
+
end
|
96
|
+
|
97
|
+
# Create new log file if necessary and setup logging level
|
98
|
+
# @return [Logger] Logger class to record API traffic
|
99
|
+
def create
|
100
|
+
create_log_file
|
101
|
+
@logger = ApiLogger.new(traffic_file) # Where request and responses of APIs are stored
|
102
|
+
@logger.progname = progname || 'SpecLog'
|
103
|
+
@logger.formatter = proc do |_severity, datetime, progname, msg|
|
104
|
+
message = "#{progname}, [#{datetime.strftime(time_format)}] : #{msg}\n"
|
105
|
+
print message.colorize(terminal_color) if @output_to_terminal
|
106
|
+
message if @output_to_file
|
107
|
+
end
|
108
|
+
RestClient.log = @logger
|
109
|
+
@logger
|
110
|
+
end
|
111
|
+
|
112
|
+
# Log a message using Soaspec logger
|
113
|
+
# Logger (and it's file) will be created if it's not already set
|
114
|
+
# @param [String, Array] message The message to add to the logger or list of messages
|
115
|
+
def info(message)
|
116
|
+
return unless log_api_traffic?
|
117
|
+
|
118
|
+
create unless @logger
|
119
|
+
if message.respond_to? :each
|
120
|
+
message.each do |message_item|
|
121
|
+
info(message_item)
|
122
|
+
end
|
123
|
+
else
|
124
|
+
if block_given?
|
125
|
+
@logger.info(message) { yield }
|
126
|
+
else
|
127
|
+
@logger.info(message)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
# Create folder and file to store logs
|
135
|
+
def create_log_file
|
136
|
+
return if File.exist?(traffic_file)
|
137
|
+
|
138
|
+
FileUtils.mkdir_p traffic_folder
|
139
|
+
FileUtils.touch traffic_file
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|