wsdirector-core 1.0.3 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d062f547a78c242ffc0b863fc7cd0e9405fc8b4621791ca2bb30f077a6778885
4
- data.tar.gz: c75f03818f180eb0ee202402272189ec23a2d53ad2dd28cc9657971b9abde523
3
+ metadata.gz: e8f7c80b878147f8ceba30cff3c94398e7cf8196794d3b4b857ade3702b8a97f
4
+ data.tar.gz: dc767a46dc089ee5cbe7ff90227ddaa2bb23eee835264a436084dd5cf910e77a
5
5
  SHA512:
6
- metadata.gz: a276cdde656fd94d4e019aa398d1bbce8509e57561bc318e9af681871d3647137f367db714c70eaaeea1b1722c81f19881c6fccb57db123885b4b6c04618ebe7
7
- data.tar.gz: d735cf99e4c64f826ce23cf82bd66fbb2469066c3c660d05e30ed4c31610cff3498ea5d58b98558ce60ef007c34a1717326677f2457ac132a8bb43a7af401bc1
6
+ metadata.gz: c2a1d4aa0e1134344f2e4d94fb132153d90f071e48a541bef57e4ab26bf9d49227a9b646a6e3a226ff86d84995e54297933c9aa755db6374c5a8b107d741d4b8
7
+ data.tar.gz: cd9e6f0d9f2804fca5c3fff3dbccbcd6cc7cc3f1f4eafb9eba7846bf4c8b81cc96246ed1c0fc9be4721267406a97e6bb3e3173d6f7b0b8995f88a30b21dcb4ee
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.1.0 (2024-10-04)
6
+
7
+ - Support `stream_id`, `offset`, and `epoch` fields in Action Cable `receive`. ([@palkan][])
8
+
9
+ - Add `print` option to `receive` action to print the received message. ([@palkan][])
10
+
5
11
  ## 1.0.3 (2023-10-03)
6
12
 
7
13
  - Add `timeout` option to receive to limit the amount of time we wait for the expected message. ([@palkan][])
@@ -94,7 +94,7 @@ module WSDirector
94
94
  "an object including #{obj.inspect}"
95
95
  end
96
96
 
97
- def truncate(*__rest__, &__block__) ; obj.truncate(*__rest__, &__block__); end
97
+ def truncate(*__rest__, &__block__) ; obj.truncate(*__rest__, &__block__); end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :truncate)
98
98
  end
99
99
 
100
100
  # Base protocol describes basic actions
@@ -118,7 +118,7 @@ module WSDirector
118
118
  @client = build_client(*__rest__, &__block__)
119
119
 
120
120
  log(:done) { "Connected" }
121
- end
121
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :init_client)
122
122
 
123
123
  def handle_step(step)
124
124
  type = step.delete("type")
@@ -160,7 +160,7 @@ module WSDirector
160
160
  ordered = step["ordered"]
161
161
  timeout = step.fetch("timeout", 5).to_f
162
162
 
163
- log { "Receive a message in #{timeout}s: #{expected.truncate(100)}" }
163
+ log { "Receive a message in #{timeout}s: #{expected.inspect.truncate(100)}" }
164
164
 
165
165
  start = Time.now.to_f
166
166
  received = nil
@@ -181,12 +181,16 @@ module WSDirector
181
181
  end
182
182
  end
183
183
 
184
+ if step["print"]
185
+ debug({"message" => received})
186
+ end
187
+
184
188
  log(:done) { "Received a message: #{received&.truncate(100)}" }
185
189
  rescue ThreadError, ReceiveTimeoutError
186
190
  if received
187
191
  raise UnmatchedExpectationError, prepare_receive_error(expected, received)
188
192
  else
189
- raise NoMessageError, "Expected to receive #{expected} but nothing has been received"
193
+ raise NoMessageError, "Expected to receive #{expected.inspect} but nothing has been received"
190
194
  end
191
195
  end
192
196
 
@@ -253,7 +257,7 @@ module WSDirector
253
257
 
254
258
  def build_client(*__rest__, &__block__)
255
259
  Client.new(*__rest__, &__block__)
256
- end
260
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :build_client)
257
261
 
258
262
  def prepare_receive_error(expected, received)
259
263
  <<~MSG
@@ -14,14 +14,14 @@ module WSDirector
14
14
  @refs_counter = 3
15
15
  @join_refs_counter = 3
16
16
  @topics_to_join_ref = {}
17
- end
17
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :initialize)
18
18
 
19
19
  def init_client(**options)
20
20
  options[:query] ||= {}
21
21
  # Make sure we use the v2 of the protocol
22
22
  options[:query][:vsn] = "2.0.0"
23
23
 
24
- super(**options)
24
+ super
25
25
  end
26
26
 
27
27
  def join(step)
@@ -5,7 +5,7 @@ module WSDirector
5
5
  # Extend Object through refinements
6
6
  module Formatting
7
7
  refine ::Object do
8
- def truncate(*) ; itself; end
8
+ def truncate(*__rest__) ; itself; end
9
9
  end
10
10
 
11
11
  refine ::String do
@@ -94,7 +94,7 @@ module WSDirector
94
94
  "an object including #{obj.inspect}"
95
95
  end
96
96
 
97
- def truncate(...) ; obj.truncate(...); end
97
+ def truncate(...) ; obj.truncate(...); end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :truncate)
98
98
  end
99
99
 
100
100
  # Base protocol describes basic actions
@@ -118,7 +118,7 @@ module WSDirector
118
118
  @client = build_client(...)
119
119
 
120
120
  log(:done) { "Connected" }
121
- end
121
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :init_client)
122
122
 
123
123
  def handle_step(step)
124
124
  type = step.delete("type")
@@ -160,7 +160,7 @@ module WSDirector
160
160
  ordered = step["ordered"]
161
161
  timeout = step.fetch("timeout", 5).to_f
162
162
 
163
- log { "Receive a message in #{timeout}s: #{expected.truncate(100)}" }
163
+ log { "Receive a message in #{timeout}s: #{expected.inspect.truncate(100)}" }
164
164
 
165
165
  start = Time.now.to_f
166
166
  received = nil
@@ -181,12 +181,16 @@ module WSDirector
181
181
  end
182
182
  end
183
183
 
184
+ if step["print"]
185
+ debug({"message" => received})
186
+ end
187
+
184
188
  log(:done) { "Received a message: #{received&.truncate(100)}" }
185
189
  rescue ThreadError, ReceiveTimeoutError
186
190
  if received
187
191
  raise UnmatchedExpectationError, prepare_receive_error(expected, received)
188
192
  else
189
- raise NoMessageError, "Expected to receive #{expected} but nothing has been received"
193
+ raise NoMessageError, "Expected to receive #{expected.inspect} but nothing has been received"
190
194
  end
191
195
  end
192
196
 
@@ -253,7 +257,7 @@ module WSDirector
253
257
 
254
258
  def build_client(...)
255
259
  Client.new(...)
256
- end
260
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :build_client)
257
261
 
258
262
  def prepare_receive_error(expected, received)
259
263
  <<~MSG
@@ -11,7 +11,7 @@ module WSDirector
11
11
  options[:ignore] ||= [PING_IGNORE]
12
12
  options[:subprotocol] ||= "actioncable-v1-json"
13
13
 
14
- super(**options)
14
+ super
15
15
 
16
16
  receive("data>" => {"type" => "welcome"})
17
17
  log(:done) { "Welcomed" }
@@ -64,7 +64,11 @@ module WSDirector
64
64
  key = step.key?("data") ? "data" : "data>"
65
65
 
66
66
  message = step.fetch(key, {})
67
- super(key => {"identifier" => identifier, "message" => message})
67
+
68
+ # Move all protocol-level fields to data
69
+ step[key] = {"identifier" => identifier, "message" => message}.merge(step.slice("offset", "stream_id", "epoch"))
70
+
71
+ super
68
72
  end
69
73
 
70
74
  def receive_all(step)
@@ -78,7 +82,7 @@ module WSDirector
78
82
 
79
83
  key = msg.key?("data") ? "data" : "data>"
80
84
 
81
- msg[key] = {"identifier" => identifier, "message" => msg[key]}
85
+ msg[key] = {"identifier" => identifier, "message" => msg[key]}.merge(step.slice("offset", "stream_id", "epoch"))
82
86
  end
83
87
 
84
88
  super
@@ -88,7 +92,7 @@ module WSDirector
88
92
 
89
93
  def extract_identifier(step)
90
94
  channel = step.delete("channel")
91
- step.fetch("params", {}).merge(channel: channel).to_json
95
+ (step.delete("params") || {}).merge(channel: channel).to_json
92
96
  end
93
97
  end
94
98
  end
@@ -14,14 +14,14 @@ module WSDirector
14
14
  @refs_counter = 3
15
15
  @join_refs_counter = 3
16
16
  @topics_to_join_ref = {}
17
- end
17
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :initialize)
18
18
 
19
19
  def init_client(**options)
20
20
  options[:query] ||= {}
21
21
  # Make sure we use the v2 of the protocol
22
22
  options[:query][:vsn] = "2.0.0"
23
23
 
24
- super(**options)
24
+ super
25
25
  end
26
26
 
27
27
  def join(step)
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WSDirector
4
+ module Ext
5
+ # Extend Object through refinements
6
+ module Formatting
7
+ refine ::Object do
8
+ def truncate(*__rest__) = itself
9
+ end
10
+
11
+ refine ::String do
12
+ def truncate(limit)
13
+ return self if size <= limit
14
+
15
+ "#{self[0..(limit - 3)]}..."
16
+ end
17
+ end
18
+
19
+ refine ::Hash do
20
+ def truncate(limit)
21
+ str = to_json
22
+
23
+ str.truncate(limit)
24
+ end
25
+ end
26
+
27
+ refine ::Float do
28
+ def duration
29
+ if self > 1
30
+ "#{truncate(2)}s"
31
+ else
32
+ "#{(self * 1000).to_i}ms"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -11,7 +11,7 @@ module WSDirector
11
11
  options[:ignore] ||= [PING_IGNORE]
12
12
  options[:subprotocol] ||= "actioncable-v1-json"
13
13
 
14
- super(**options)
14
+ super
15
15
 
16
16
  receive("data>" => {"type" => "welcome"})
17
17
  log(:done) { "Welcomed" }
@@ -64,7 +64,11 @@ module WSDirector
64
64
  key = step.key?("data") ? "data" : "data>"
65
65
 
66
66
  message = step.fetch(key, {})
67
- super(key => {"identifier" => identifier, "message" => message})
67
+
68
+ # Move all protocol-level fields to data
69
+ step[key] = {"identifier" => identifier, "message" => message}.merge(step.slice("offset", "stream_id", "epoch"))
70
+
71
+ super
68
72
  end
69
73
 
70
74
  def receive_all(step)
@@ -78,7 +82,7 @@ module WSDirector
78
82
 
79
83
  key = msg.key?("data") ? "data" : "data>"
80
84
 
81
- msg[key] = {"identifier" => identifier, "message" => msg[key]}
85
+ msg[key] = {"identifier" => identifier, "message" => msg[key]}.merge(step.slice("offset", "stream_id", "epoch"))
82
86
  end
83
87
 
84
88
  super
@@ -88,7 +92,7 @@ module WSDirector
88
92
 
89
93
  def extract_identifier(step)
90
94
  channel = step.delete("channel")
91
- step.fetch("params", {}).merge(channel: channel).to_json
95
+ (step.delete("params") || {}).merge(channel: channel).to_json
92
96
  end
93
97
  end
94
98
  end
@@ -160,7 +160,7 @@ module WSDirector
160
160
  ordered = step["ordered"]
161
161
  timeout = step.fetch("timeout", 5).to_f
162
162
 
163
- log { "Receive a message in #{timeout}s: #{expected.truncate(100)}" }
163
+ log { "Receive a message in #{timeout}s: #{expected.inspect.truncate(100)}" }
164
164
 
165
165
  start = Time.now.to_f
166
166
  received = nil
@@ -181,12 +181,16 @@ module WSDirector
181
181
  end
182
182
  end
183
183
 
184
+ if step["print"]
185
+ debug({"message" => received})
186
+ end
187
+
184
188
  log(:done) { "Received a message: #{received&.truncate(100)}" }
185
189
  rescue ThreadError, ReceiveTimeoutError
186
190
  if received
187
191
  raise UnmatchedExpectationError, prepare_receive_error(expected, received)
188
192
  else
189
- raise NoMessageError, "Expected to receive #{expected} but nothing has been received"
193
+ raise NoMessageError, "Expected to receive #{expected.inspect} but nothing has been received"
190
194
  end
191
195
  end
192
196
 
@@ -21,7 +21,7 @@ module WSDirector
21
21
  # Make sure we use the v2 of the protocol
22
22
  options[:query][:vsn] = "2.0.0"
23
23
 
24
- super(**options)
24
+ super
25
25
  end
26
26
 
27
27
  def join(step)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WSDirector
4
- VERSION = "1.0.3"
4
+ VERSION = "1.1.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wsdirector-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-10-03 00:00:00.000000000 Z
13
+ date: 2024-10-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: websocket-client-simple
@@ -207,6 +207,7 @@ files:
207
207
  - lib/.rbnext/3.1/wsdirector/runner.rb
208
208
  - lib/.rbnext/3.1/wsdirector/scenario_reader.rb
209
209
  - lib/.rbnext/3.1/wsdirector/task.rb
210
+ - lib/.rbnext/3.2/wsdirector/ext/formatting.rb
210
211
  - lib/wsdirector-cli.rb
211
212
  - lib/wsdirector.rb
212
213
  - lib/wsdirector/cli.rb
@@ -245,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
246
  - !ruby/object:Gem::Version
246
247
  version: '0'
247
248
  requirements: []
248
- rubygems_version: 3.4.8
249
+ rubygems_version: 3.5.18
249
250
  signing_key:
250
251
  specification_version: 4
251
252
  summary: Scenario-based WebSocket black-box testing