mockserver-client 1.0.8.pre → 6.0.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 +5 -5
- data/Gemfile +2 -1
- data/README.md +79 -227
- data/lib/mockserver/client.rb +518 -0
- data/lib/mockserver/errors.rb +18 -0
- data/lib/mockserver/forward_chain_expectation.rb +117 -0
- data/lib/mockserver/models.rb +1507 -0
- data/lib/mockserver/version.rb +3 -3
- data/lib/mockserver/websocket_client.rb +353 -0
- data/lib/mockserver-client.rb +7 -16
- data/mockserver-client.gemspec +26 -27
- metadata +54 -206
- data/.gitignore +0 -21
- data/.rubocop.yml +0 -7
- data/Rakefile +0 -10
- data/bin/mockserver +0 -9
- data/lib/cli.rb +0 -146
- data/lib/mockserver/abstract_client.rb +0 -111
- data/lib/mockserver/mock_server_client.rb +0 -46
- data/lib/mockserver/model/array_of.rb +0 -85
- data/lib/mockserver/model/body.rb +0 -56
- data/lib/mockserver/model/cookie.rb +0 -36
- data/lib/mockserver/model/delay.rb +0 -34
- data/lib/mockserver/model/enum.rb +0 -47
- data/lib/mockserver/model/expectation.rb +0 -139
- data/lib/mockserver/model/forward.rb +0 -41
- data/lib/mockserver/model/header.rb +0 -43
- data/lib/mockserver/model/parameter.rb +0 -43
- data/lib/mockserver/model/request.rb +0 -81
- data/lib/mockserver/model/response.rb +0 -45
- data/lib/mockserver/model/times.rb +0 -61
- data/lib/mockserver/proxy_client.rb +0 -9
- data/lib/mockserver/utility_methods.rb +0 -59
- data/pom.xml +0 -118
- data/spec/fixtures/forward_mockserver.json +0 -7
- data/spec/fixtures/incorrect_login_response.json +0 -20
- data/spec/fixtures/post_login_request.json +0 -22
- data/spec/fixtures/register_expectation.json +0 -50
- data/spec/fixtures/retrieved_request.json +0 -22
- data/spec/fixtures/search_request.json +0 -6
- data/spec/fixtures/times_once.json +0 -6
- data/spec/integration/mock_client_integration_spec.rb +0 -82
- data/spec/mockserver/builder_spec.rb +0 -90
- data/spec/mockserver/mock_client_spec.rb +0 -80
- data/spec/mockserver/proxy_client_spec.rb +0 -38
- data/spec/spec_helper.rb +0 -61
data/lib/mockserver/version.rb
CHANGED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'securerandom'
|
|
5
|
+
require 'logger'
|
|
6
|
+
require 'openssl'
|
|
7
|
+
require 'timeout'
|
|
8
|
+
|
|
9
|
+
module MockServer
|
|
10
|
+
WEB_SOCKET_CORRELATION_ID_HEADER_NAME = 'WebSocketCorrelationId'
|
|
11
|
+
CLIENT_REGISTRATION_ID_HEADER = 'X-CLIENT-REGISTRATION-ID'
|
|
12
|
+
|
|
13
|
+
WEBSOCKET_PATH = '/_mockserver_callback_websocket'
|
|
14
|
+
|
|
15
|
+
TYPE_HTTP_REQUEST = 'org.mockserver.model.HttpRequest'
|
|
16
|
+
TYPE_HTTP_RESPONSE = 'org.mockserver.model.HttpResponse'
|
|
17
|
+
TYPE_HTTP_REQUEST_AND_RESPONSE = 'org.mockserver.model.HttpRequestAndHttpResponse'
|
|
18
|
+
TYPE_CLIENT_ID_DTO = 'org.mockserver.serialization.model.WebSocketClientIdDTO'
|
|
19
|
+
TYPE_ERROR_DTO = 'org.mockserver.serialization.model.WebSocketErrorDTO'
|
|
20
|
+
|
|
21
|
+
MAX_RECONNECT_ATTEMPTS = 3
|
|
22
|
+
REGISTRATION_TIMEOUT = 10
|
|
23
|
+
|
|
24
|
+
def self.extract_correlation_id(request)
|
|
25
|
+
return nil if request.headers.nil?
|
|
26
|
+
|
|
27
|
+
request.headers.each do |header|
|
|
28
|
+
if header.name == WEB_SOCKET_CORRELATION_ID_HEADER_NAME
|
|
29
|
+
return header.values.first if header.values && !header.values.empty?
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.add_correlation_id_header(message, correlation_id)
|
|
36
|
+
message.headers ||= []
|
|
37
|
+
message.headers.each do |header|
|
|
38
|
+
if header.name == WEB_SOCKET_CORRELATION_ID_HEADER_NAME
|
|
39
|
+
header.values = [correlation_id]
|
|
40
|
+
return message
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
message.headers << KeyToMultiValue.new(
|
|
44
|
+
name: WEB_SOCKET_CORRELATION_ID_HEADER_NAME,
|
|
45
|
+
values: [correlation_id]
|
|
46
|
+
)
|
|
47
|
+
message
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.build_ws_message(type_name, value_dict)
|
|
51
|
+
JSON.generate({
|
|
52
|
+
'type' => type_name,
|
|
53
|
+
'value' => JSON.generate(value_dict)
|
|
54
|
+
})
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.build_error_message(error_msg, correlation_id)
|
|
58
|
+
JSON.generate({
|
|
59
|
+
'type' => TYPE_ERROR_DTO,
|
|
60
|
+
'value' => JSON.generate({
|
|
61
|
+
'message' => error_msg,
|
|
62
|
+
'webSocketCorrelationId' => correlation_id
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @api private
|
|
68
|
+
def self.clean_context_path(context_path)
|
|
69
|
+
return '' if context_path.nil? || context_path.empty?
|
|
70
|
+
return "/#{context_path}" unless context_path.start_with?('/')
|
|
71
|
+
|
|
72
|
+
context_path
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class WebSocketClient
|
|
76
|
+
attr_reader :client_id
|
|
77
|
+
|
|
78
|
+
def initialize
|
|
79
|
+
@ws = nil
|
|
80
|
+
@client_id = nil
|
|
81
|
+
@response_callback = nil
|
|
82
|
+
@forward_callback = nil
|
|
83
|
+
@forward_response_callback = nil
|
|
84
|
+
@stopped = false
|
|
85
|
+
@connected = false
|
|
86
|
+
@listen_thread = nil
|
|
87
|
+
@host = ''
|
|
88
|
+
@port = 0
|
|
89
|
+
@context_path = ''
|
|
90
|
+
@secure = false
|
|
91
|
+
@ca_cert_path = nil
|
|
92
|
+
@tls_verify = true
|
|
93
|
+
@logger = Logger.new($stdout)
|
|
94
|
+
@logger.progname = 'MockServer::WebSocketClient'
|
|
95
|
+
@logger.level = Logger::WARN
|
|
96
|
+
@registration_queue = nil
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def connected?
|
|
100
|
+
@connected && !@stopped
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def connect(host, port, context_path: '', secure: false,
|
|
104
|
+
ca_cert_path: nil, client_id: nil, tls_verify: true)
|
|
105
|
+
@host = host
|
|
106
|
+
@port = port
|
|
107
|
+
@context_path = context_path
|
|
108
|
+
@secure = secure
|
|
109
|
+
@ca_cert_path = ca_cert_path
|
|
110
|
+
@tls_verify = tls_verify
|
|
111
|
+
|
|
112
|
+
registration_id = client_id || SecureRandom.uuid
|
|
113
|
+
|
|
114
|
+
do_connect(registration_id)
|
|
115
|
+
@client_id
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def register_response_callback(callback_fn)
|
|
119
|
+
@response_callback = callback_fn
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def register_forward_callback(forward_fn, response_fn = nil)
|
|
123
|
+
@forward_callback = forward_fn
|
|
124
|
+
@forward_response_callback = response_fn
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def listen
|
|
128
|
+
@listen_thread = Thread.new { listen_loop }
|
|
129
|
+
@listen_thread.abort_on_exception = false
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def close
|
|
133
|
+
@stopped = true
|
|
134
|
+
@connected = false
|
|
135
|
+
@ws&.close if @ws
|
|
136
|
+
rescue StandardError
|
|
137
|
+
# ignore close errors
|
|
138
|
+
ensure
|
|
139
|
+
@ws = nil
|
|
140
|
+
@listen_thread&.join(5) if @listen_thread && @listen_thread != Thread.current
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
|
|
145
|
+
def do_connect(registration_id)
|
|
146
|
+
require 'websocket-client-simple'
|
|
147
|
+
|
|
148
|
+
scheme = @secure ? 'wss' : 'ws'
|
|
149
|
+
path = MockServer.clean_context_path(@context_path) + WEBSOCKET_PATH
|
|
150
|
+
uri = "#{scheme}://#{@host}:#{@port}#{path}"
|
|
151
|
+
|
|
152
|
+
headers = { CLIENT_REGISTRATION_ID_HEADER => registration_id }
|
|
153
|
+
|
|
154
|
+
@registration_queue = Queue.new
|
|
155
|
+
@connected = false
|
|
156
|
+
ws_client = self
|
|
157
|
+
|
|
158
|
+
opts = { headers: headers }
|
|
159
|
+
|
|
160
|
+
if @secure
|
|
161
|
+
if @ca_cert_path
|
|
162
|
+
cert_store = OpenSSL::X509::Store.new
|
|
163
|
+
cert_store.set_default_paths
|
|
164
|
+
cert_store.add_file(@ca_cert_path)
|
|
165
|
+
opts[:cert_store] = cert_store
|
|
166
|
+
opts[:verify_mode] = OpenSSL::SSL::VERIFY_PEER
|
|
167
|
+
elsif !@tls_verify
|
|
168
|
+
opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
|
|
169
|
+
else
|
|
170
|
+
opts[:verify_mode] = OpenSSL::SSL::VERIFY_PEER
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
@ws = ::WebSocket::Client::Simple.connect(uri, **opts) do |ws|
|
|
175
|
+
ws.on :message do |msg|
|
|
176
|
+
ws_client.send(:handle_raw_message, msg.data)
|
|
177
|
+
end
|
|
178
|
+
ws.on :error do |e|
|
|
179
|
+
ws_client.send(:handle_ws_error, e)
|
|
180
|
+
end
|
|
181
|
+
ws.on :close do |_e|
|
|
182
|
+
ws_client.send(:handle_ws_close)
|
|
183
|
+
end
|
|
184
|
+
ws.on :open do
|
|
185
|
+
ws_client.send(:handle_ws_open)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
result = nil
|
|
190
|
+
begin
|
|
191
|
+
Timeout.timeout(REGISTRATION_TIMEOUT) do
|
|
192
|
+
result = @registration_queue.pop
|
|
193
|
+
end
|
|
194
|
+
rescue Timeout::Error
|
|
195
|
+
@ws&.close rescue nil
|
|
196
|
+
@ws = nil
|
|
197
|
+
@connected = false
|
|
198
|
+
raise WebSocketError,
|
|
199
|
+
"WebSocket registration timed out after #{REGISTRATION_TIMEOUT}s " \
|
|
200
|
+
"connecting to #{@host}:#{@port}"
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
if result.is_a?(Exception)
|
|
204
|
+
raise result
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
@client_id = result
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def handle_ws_open
|
|
211
|
+
@connected = true
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def handle_ws_close
|
|
215
|
+
@connected = false
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def handle_ws_error(error)
|
|
219
|
+
@connected = false
|
|
220
|
+
if @registration_queue
|
|
221
|
+
ws_error = WebSocketError.new(
|
|
222
|
+
"WebSocket connection error to #{@host}:#{@port}: #{error.message}"
|
|
223
|
+
)
|
|
224
|
+
@registration_queue.push(ws_error)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def listen_loop
|
|
229
|
+
reconnect_attempts = 0
|
|
230
|
+
until @stopped
|
|
231
|
+
sleep 0.1
|
|
232
|
+
next if connected?
|
|
233
|
+
|
|
234
|
+
break if @stopped
|
|
235
|
+
|
|
236
|
+
reconnect_attempts += 1
|
|
237
|
+
if reconnect_attempts > MAX_RECONNECT_ATTEMPTS
|
|
238
|
+
@logger.error('Max reconnect attempts reached, giving up')
|
|
239
|
+
break
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
@logger.warn("WebSocket disconnected, reconnecting (attempt #{reconnect_attempts}/#{MAX_RECONNECT_ATTEMPTS})")
|
|
243
|
+
begin
|
|
244
|
+
do_connect(@client_id || SecureRandom.uuid)
|
|
245
|
+
reconnect_attempts = 0
|
|
246
|
+
rescue StandardError => e
|
|
247
|
+
@logger.error("Reconnection failed: #{e.message}")
|
|
248
|
+
sleep [2**reconnect_attempts, 8].min
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def handle_raw_message(raw_message)
|
|
254
|
+
begin
|
|
255
|
+
parsed = JSON.parse(raw_message)
|
|
256
|
+
rescue JSON::ParserError => e
|
|
257
|
+
@logger.warn("Received unparseable WebSocket message: #{e.message}")
|
|
258
|
+
return
|
|
259
|
+
end
|
|
260
|
+
msg_type = parsed['type']
|
|
261
|
+
msg_value = parsed['value']
|
|
262
|
+
|
|
263
|
+
if msg_type == TYPE_CLIENT_ID_DTO
|
|
264
|
+
value = JSON.parse(msg_value)
|
|
265
|
+
@client_id = value['clientId']
|
|
266
|
+
@registration_queue&.push(@client_id)
|
|
267
|
+
return
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
if msg_type == TYPE_HTTP_REQUEST
|
|
271
|
+
request = HttpRequest.from_hash(JSON.parse(msg_value))
|
|
272
|
+
correlation_id = MockServer.extract_correlation_id(request)
|
|
273
|
+
|
|
274
|
+
if @forward_callback
|
|
275
|
+
handle_forward_request(request, correlation_id)
|
|
276
|
+
elsif @response_callback
|
|
277
|
+
handle_response_request(request, correlation_id)
|
|
278
|
+
else
|
|
279
|
+
@logger.warn("Received HttpRequest callback but no callback registered")
|
|
280
|
+
end
|
|
281
|
+
return
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
if msg_type == TYPE_HTTP_REQUEST_AND_RESPONSE
|
|
285
|
+
req_and_resp = HttpRequestAndHttpResponse.from_hash(JSON.parse(msg_value))
|
|
286
|
+
correlation_id = MockServer.extract_correlation_id(req_and_resp.http_request)
|
|
287
|
+
|
|
288
|
+
if @forward_response_callback
|
|
289
|
+
handle_forward_response(req_and_resp, correlation_id)
|
|
290
|
+
else
|
|
291
|
+
@logger.warn("Received HttpRequestAndHttpResponse callback but no forward_response_callback registered")
|
|
292
|
+
end
|
|
293
|
+
return
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
@logger.warn("Received unhandled WebSocket message type: #{msg_type}")
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def handle_response_request(request, correlation_id)
|
|
300
|
+
result = @response_callback.call(request)
|
|
301
|
+
unless result.is_a?(HttpResponse)
|
|
302
|
+
raise CallbackError, "Response callback must return HttpResponse, got #{result.class}"
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
MockServer.add_correlation_id_header(result, correlation_id) if correlation_id
|
|
306
|
+
msg = MockServer.build_ws_message(TYPE_HTTP_RESPONSE, result.to_h)
|
|
307
|
+
@ws.send(msg)
|
|
308
|
+
rescue StandardError => exc
|
|
309
|
+
@logger.error("Error in response callback: #{exc.message}")
|
|
310
|
+
if correlation_id
|
|
311
|
+
error_msg = MockServer.build_error_message(exc.message, correlation_id)
|
|
312
|
+
@ws.send(error_msg)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def handle_forward_request(request, correlation_id)
|
|
317
|
+
result = @forward_callback.call(request)
|
|
318
|
+
unless result.is_a?(HttpRequest)
|
|
319
|
+
raise CallbackError, "Forward callback must return HttpRequest, got #{result.class}"
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
MockServer.add_correlation_id_header(result, correlation_id) if correlation_id
|
|
323
|
+
msg = MockServer.build_ws_message(TYPE_HTTP_REQUEST, result.to_h)
|
|
324
|
+
@ws.send(msg)
|
|
325
|
+
rescue StandardError => exc
|
|
326
|
+
@logger.error("Error in forward callback: #{exc.message}")
|
|
327
|
+
if correlation_id
|
|
328
|
+
error_msg = MockServer.build_error_message(exc.message, correlation_id)
|
|
329
|
+
@ws.send(error_msg)
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def handle_forward_response(req_and_resp, correlation_id)
|
|
334
|
+
result = @forward_response_callback.call(
|
|
335
|
+
req_and_resp.http_request,
|
|
336
|
+
req_and_resp.http_response
|
|
337
|
+
)
|
|
338
|
+
unless result.is_a?(HttpResponse)
|
|
339
|
+
raise CallbackError, "Forward response callback must return HttpResponse, got #{result.class}"
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
MockServer.add_correlation_id_header(result, correlation_id) if correlation_id
|
|
343
|
+
msg = MockServer.build_ws_message(TYPE_HTTP_RESPONSE, result.to_h)
|
|
344
|
+
@ws.send(msg)
|
|
345
|
+
rescue StandardError => exc
|
|
346
|
+
@logger.error("Error in forward response callback: #{exc.message}")
|
|
347
|
+
if correlation_id
|
|
348
|
+
error_msg = MockServer.build_error_message(exc.message, correlation_id)
|
|
349
|
+
@ws.send(error_msg)
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
end
|
data/lib/mockserver-client.rb
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
#
|
|
2
|
-
require_relative './mockserver/version'
|
|
3
|
-
require_relative './mockserver/mock_server_client'
|
|
4
|
-
require_relative './mockserver/proxy_client'
|
|
1
|
+
# frozen_string_literal: true
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
to_s
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
require 'multi_json'
|
|
17
|
-
MultiJson.use(:json_pure)
|
|
3
|
+
require_relative 'mockserver/version'
|
|
4
|
+
require_relative 'mockserver/errors'
|
|
5
|
+
require_relative 'mockserver/models'
|
|
6
|
+
require_relative 'mockserver/websocket_client'
|
|
7
|
+
require_relative 'mockserver/forward_chain_expectation'
|
|
8
|
+
require_relative 'mockserver/client'
|
data/mockserver-client.gemspec
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
5
|
require 'mockserver/version'
|
|
5
6
|
|
|
6
7
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name
|
|
8
|
-
spec.version
|
|
9
|
-
spec.authors
|
|
10
|
-
spec.email
|
|
11
|
-
spec.
|
|
12
|
-
spec.
|
|
13
|
-
|
|
8
|
+
spec.name = 'mockserver-client'
|
|
9
|
+
spec.version = MockServer::VERSION
|
|
10
|
+
spec.authors = ['James Bloom']
|
|
11
|
+
spec.email = ['jamesdbloom@gmail.com']
|
|
12
|
+
spec.summary = 'Official Ruby client for MockServer'
|
|
13
|
+
spec.description = 'Official Ruby client for MockServer — create expectations, verify requests, ' \
|
|
14
|
+
'and register dynamic callbacks via WebSocket. Includes a fluent builder DSL.'
|
|
15
|
+
spec.homepage = 'https://www.mock-server.com'
|
|
16
|
+
spec.license = 'Apache-2.0'
|
|
17
|
+
|
|
18
|
+
spec.required_ruby_version = '>= 3.0'
|
|
14
19
|
|
|
15
|
-
spec.
|
|
16
|
-
|
|
20
|
+
spec.metadata = {
|
|
21
|
+
'source_code_uri' => 'https://github.com/mock-server/mockserver-monorepo',
|
|
22
|
+
'changelog_uri' => 'https://www.mock-server.com/mock_server/changelog.html',
|
|
23
|
+
'bug_tracker_uri' => 'https://github.com/mock-server/mockserver-monorepo/issues',
|
|
24
|
+
'documentation_uri' => 'https://www.mock-server.com/mock_server/getting_started.html',
|
|
25
|
+
}
|
|
17
26
|
|
|
18
|
-
spec.files =
|
|
19
|
-
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
|
20
|
-
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
|
27
|
+
spec.files = Dir['lib/**/*.rb'] + %w[README.md Gemfile mockserver-client.gemspec]
|
|
21
28
|
spec.require_paths = ['lib']
|
|
22
29
|
|
|
23
|
-
spec.
|
|
24
|
-
spec.
|
|
25
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
26
|
-
spec.add_development_dependency 'simplecov', '~> 0.8'
|
|
27
|
-
spec.add_development_dependency 'webmock', '~> 1.18'
|
|
28
|
-
spec.add_development_dependency 'rubocop', '~> 0.23'
|
|
30
|
+
spec.add_dependency 'logger', '>= 1.0'
|
|
31
|
+
spec.add_dependency 'websocket-client-simple', '~> 0.8'
|
|
29
32
|
|
|
30
|
-
spec.
|
|
31
|
-
spec.
|
|
32
|
-
spec.
|
|
33
|
-
spec.add_dependency 'rest-client', '~> 1.7'
|
|
34
|
-
spec.add_dependency 'logging_factory', '~> 0.0.2'
|
|
35
|
-
spec.add_dependency 'thor', '~> 0.19'
|
|
36
|
-
spec.add_dependency 'colorize', '~> 0.7'
|
|
33
|
+
spec.add_development_dependency 'rspec', '~> 3.12'
|
|
34
|
+
spec.add_development_dependency 'rspec_junit_formatter', '~> 0.6'
|
|
35
|
+
spec.add_development_dependency 'webmock', '~> 3.19'
|
|
37
36
|
end
|