zeebe_bpmn_rspec 0.2.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ee557a1aed97212da2a198eafd8238859e12499f32e8ddf24d97d5240c83c36
4
- data.tar.gz: 0105ee8a65e00fbab192cf6f76710e43973bec36324b3defcc4f83882db833ca
3
+ metadata.gz: dbc8b0a3a6bf05f4ef29f2a5285b452afa1e733f2e166a521ba28e48dc2f94d1
4
+ data.tar.gz: 5ef538eea22fce15ba4356ea06204891b69ec51170706cc804d005f1639107f6
5
5
  SHA512:
6
- metadata.gz: 978a61f885179d519ede6340a283b93f9c36e1d712c1279629500732afe01a9f9ac7483a484c17d99356bcebb0258fb04f65771492a6d2b6774cd9be64454f1b
7
- data.tar.gz: 6f235e5995f75fd04b7996708bb8a23d81cbb1b7bf1ecd8ebea46a5fba78fa1e5c60f8ab1e305e263d0e16e7ac2005dad78dfdf5e684528ff3cdf3343a2f9c2e
6
+ metadata.gz: 89756e04128e43c7386cc13f785dc3146568b76a7ed5b841c9ec71851f243f043c5d91e1709dd6a44ec41dc05f6e8c2c2414e20fb4227eb3a896b1ee12efad5f
7
+ data.tar.gz: 3e2f49b5e1ad94878f83ac4b6efb69028a77728e3f53b8f46b2fa134cc6ea63b19f7f3c9e88717ab9942cc0daf97d103ebdfdb12492e937c5f59361b1ec069dd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # zeebe_bpmn_rspec
2
2
 
3
+ ## v1.0.0
4
+ - Support Zeebe 1.0.0. Method names now use `process` instead of `workflow`
5
+ to match the renaming in Zeebe. Previous methods are deprecated and will be
6
+ removed in a future release.
7
+
8
+ ## v0.5.0 (unreleased)
9
+ - Require Ruby 2.6 or later.
10
+ - Require `worker` to be specified when activating a job. This argument is
11
+ defaulted but can no longer be specified as blank.
12
+
13
+ ## v0.4.1
14
+ - Allow `with_workflow_instance` to be called without a block.
15
+ - Allow `worker` to be specified when activating a job.
16
+ - Expose `workflow_instance_key` for activated jobs.
17
+
18
+ ## v0.4.0
19
+ - Add `ttl_ms` option for `publish_message`.
20
+ - Add `update_retries` method to `ActivatedJob` class.
21
+ - Add `set_variables` helper.
22
+ - Add support for `:fetch_variables` option when activating jobs.
23
+
24
+ ## v0.3.1
25
+ - Use consistent activate request timeout.
26
+ - Provide a better error when a job is not activated.
27
+
28
+ ## v0.3.0
29
+ - Add custom matchers, `have_variables`, `have_headers`, and `have_activated`.
30
+
3
31
  ## v0.2.0
4
32
  - Add `retries` option to `ActivatedJob#and_fail`.
5
33
  - Add method aliases: `and_complete` (`complete`), `and_fail` (`fail`), `and_throw_error` (`throw_error`).
data/README.md CHANGED
@@ -39,24 +39,26 @@ end
39
39
 
40
40
  The gem adds the following helper methods to RSpec.
41
41
 
42
- ### Deploy Workflow
42
+ The gem also defines [Custom Matchers](#custom-matchers).
43
43
 
44
- The `deploy_workflow` method requires a path to a BPMN file and deploys it to Zeebe. There is no support for
44
+ ### Deploy Process
45
+
46
+ The `deploy_process` (previously `deploy_workflow`) method requires a path to a BPMN file and deploys it to Zeebe. There is no support for
45
47
  removing a BPMN file once deployed, so this can be done once before the examples that use it.
46
48
 
47
49
  ```ruby
48
- before(:all) { deploy_workflow(filepath) }
50
+ before(:all) { deploy_process(filepath) }
49
51
  ```
50
52
 
51
- A custom name can also be specified for the workflow:
53
+ A custom name can also be specified for the process:
52
54
 
53
55
  ```ruby
54
- before(:all) { deploy_workflow(filepath, "custom_name") }
56
+ before(:all) { deploy_process(filepath, "custom_name") }
55
57
  ```
56
58
 
57
- ### With Workflow Instance
59
+ ### With Process Instance
58
60
 
59
- The `with_workflow_instance` method is used to create an instance for the specified workflow
61
+ The `with_process_instance` (previously `with_workflow_instance`) method is used to create an instance for the specified process
60
62
  and then yields a block that can interact with the instance.
61
63
 
62
64
  This method ensures that an active instance is cancelled at the end of the block.
@@ -65,14 +67,14 @@ For testing BPMN files it is expected that most of the test definition will be w
65
67
  call to this method.
66
68
 
67
69
  ```ruby
68
- with_workflow_instance("file_basename") do
70
+ with_process_instance("file_basename") do
69
71
  ...
70
72
  end
71
73
  ```
72
74
 
73
75
  ### Processing Jobs
74
76
 
75
- A single job can be processed for a workflow by calling `activate_job` (previously `process_job`).
77
+ A single job can be processed for a process by calling `activate_job` (previously `process_job`).
76
78
  `activate_job` is called with a job type:
77
79
 
78
80
  ```ruby
@@ -127,8 +129,8 @@ activate_job("my_job").
127
129
  expect_input(user_id: 123).
128
130
  and_complete
129
131
 
130
- # Jobs can be completed with data that is merged with variables in the workflow
131
- project_job("my_job").
132
+ # Jobs can be completed with data that is merged with variables in the process
133
+ activate_job("my_job").
132
134
  and_complete(status: "ACTIVATED")
133
135
  ```
134
136
 
@@ -155,6 +157,16 @@ job = activate_job("my_job")
155
157
  job.fail(retries: 1)
156
158
  ```
157
159
 
160
+ #### Update Retries
161
+
162
+ The retries for a job can also be modified using the `update_retries` method:
163
+
164
+ ```ruby
165
+ job = activate_job("my_job")
166
+
167
+ job.update_retries(3)
168
+ ```
169
+
158
170
  #### Throw Error
159
171
 
160
172
  The `and_throw_error` (also aliased as `throw_error`) method can be used to throw an error for a job. The error code is required and an
@@ -186,17 +198,17 @@ The maximum number of jobs to return can be specified:
186
198
  jobs = activate_jobs("my_job", max_jobs: 2).to_a
187
199
  ```
188
200
 
189
- ### Workflow Complete
201
+ ### Process Complete
190
202
 
191
- The `workflow_complete!` method can be used to assert that the current workflow is complete at the end of a
192
- test. This is implemented by cancelling the workflow and checking for an error that it is already
203
+ The `process_complete!` (previously `workflow_complete!`) method can be used to assert that the current process is complete at the end of a
204
+ test. This is implemented by cancelling the process and checking for an error that it is already
193
205
  complete.
194
206
 
195
207
  ```ruby
196
- with_workflow_instance("file_basename") do
208
+ with_process_instance("file_basename") do
197
209
  ...
198
210
 
199
- workflow_complete!
211
+ process_complete!
200
212
  end
201
213
  ```
202
214
 
@@ -217,6 +229,131 @@ publish_message("message_name", correlation_key: expected_value,
217
229
  variables: { foo: "bar" })
218
230
  ```
219
231
 
232
+ The time-to-live (in milliseconds) cna also be specified for a message.
233
+ It defaults to 5000 milliseconds if unspecified.
234
+
235
+ ```ruby
236
+ publish_message("message_name", correlation_key: expected_value, ttl_ms: 1000)
237
+ ```
238
+
239
+ ### Set Variables
240
+
241
+ The `set_variables` method can be used to set variables for a specified
242
+ scope in Zeebe:
243
+
244
+ ```ruby
245
+ # process_instance_key is a method that returns the key for the current process instance
246
+ set_variables(process_instance_key, { foo: "bar" })
247
+ ```
248
+
249
+ An activated job can be used to determine the key for the task that it is associated with:
250
+
251
+ ```ruby
252
+ job = job_with_type("my_type")
253
+ set_variables(job.task_key, { foo: "baz"})
254
+ ```
255
+
256
+ Variables default to being local to the scope on which they are set. This
257
+ can be overridden by specifying the `:local` option:
258
+
259
+ ```ruby
260
+ set_variables(job.task_key, { foo: "baz"}, local: false)
261
+ ```
262
+
263
+ ### Custom Matchers
264
+
265
+ In addition to the helpers documented above, this gem defines custom RSpec matchers to provide a more typical
266
+ experience of expectations and matchers.
267
+
268
+ #### expect_job_of_type
269
+
270
+ The `expect_job_of_type` helper is a convenient wrapper to activate a job and set an expectation target.
271
+
272
+ ```ruby
273
+ expect_job_of_type("my_type")
274
+ ```
275
+
276
+ Similar to the `activate_job` helper, it activates a job and wraps the result in an `ActivatedJob` object.
277
+ That object is then passed to `expect()`. Unlike `activate_job`, this helper does not raise if there is no job activated.
278
+
279
+ This is equivalent to `expect(job_with_type("my_type")` or `expect(activate_job("my_type", validate: false))`.
280
+
281
+ `expect_job_of_type` is expected to be used with the matchers below.
282
+
283
+ #### have_activated
284
+
285
+ The `have_activated` matcher checks that the target represents an activated job. It will raise an error if no job
286
+ was activated.
287
+
288
+ ```ruby
289
+ expect_job_of_type("my_type").to have_activated
290
+ ```
291
+
292
+ Various additional methods can be chained on the `have_activated` matcher.
293
+
294
+ The `with_variables` method can be used to check the input variables that the job was activated with:
295
+
296
+ ```ruby
297
+ expect_job_of_type("my_type").to have_activated.with_variables(user_id: 123)
298
+ ```
299
+
300
+ The `with_headers` method can be used to check the headers that the job was activated with:
301
+
302
+ ```ruby
303
+ expect_job_of_type("my_type").to have_activated.with_headers(id_type: "user")
304
+ ```
305
+
306
+ The `with_variables` and `with_headers` methods can be chained on the same expectation:
307
+
308
+ ```ruby
309
+ expect_job_of_type("my_type").to have_activated.
310
+ with_variables(user_id: 123).
311
+ with_headers(id_type: "user")
312
+ ```
313
+
314
+ The matcher also supports methods to complete, fail, or throw an error for a job:
315
+
316
+ ```ruby
317
+ # Complete
318
+ expect_job_of_type("my_type").to have_activated.and_complete
319
+
320
+ # Complete with new variables
321
+ expect_job_of_type("my_type").to have_activated.and_complete(result_code: 456)
322
+
323
+ # Fail (sets retries to 0 by default)
324
+ expect_job_of_type("my_type").to have_activated.and_fail
325
+
326
+ # Fail and specify retries
327
+ expect_job_of_type("my_type").to have_activated.and_fail(retries: 1)
328
+
329
+ # Fail with an error message
330
+ expect_job_of_type("my_type").to have_activated.and_fail("boom!")
331
+
332
+ # Fail with an error message and specify retries
333
+ expect_job_of_type("my_type").to have_activated.and_fail("boom!", retries: 2)
334
+
335
+ # Throw an error (error code is required)
336
+ expect_job_of_type("my_type").to have_activated.and_throw_error("MY_ERROR")
337
+
338
+ # Throw an error with an error message
339
+ expect_job_of_type("my_type").to have_activated.and_throw_error("MY_ERROR", "went horribly wrong")
340
+ ```
341
+
342
+ Only one of `and_complete`, `and_fail`, or `and_throw_error` can be specified for a single expectation.
343
+
344
+ #### have_variables and have_headers
345
+
346
+ In addition to the `with_variables` and `with_headers` methods that can be chained onto the `have_activated`
347
+ matcher, there are matchers that can be used directly to set expectations on the variables or
348
+ headers for an `ActivatedJob`.
349
+
350
+ ```ruby
351
+ job = activate_job("my_type")
352
+
353
+ expect(job).to have_variables(user: 123)
354
+ expect(job).to have_headers(id_type: "user")
355
+ ```
356
+
220
357
  ## Tips & Tricks
221
358
 
222
359
  ### Enumerator for Multiple Jobs
@@ -233,7 +370,7 @@ to specify a short duration.
233
370
 
234
371
  The current gem and approach have some limitations:
235
372
 
236
- 1. You can interact with only one workflow at a time.
373
+ 1. You can interact with only one process at a time.
237
374
 
238
375
  ## Development
239
376
 
@@ -0,0 +1,17 @@
1
+ version: "3.4"
2
+
3
+ services:
4
+ zeebe:
5
+ volumes:
6
+ - ./compose/zeebe-hazelcast-exporter.jar:/usr/local/zeebe/exporters/zeebe-hazelcast-exporter.jar
7
+ - ./compose/application.yml:/usr/local/zeebe/config/application.yaml
8
+
9
+ monitor:
10
+ image: camunda/zeebe-simple-monitor:0.19.1
11
+ environment:
12
+ - zeebe.client.broker.contactPoint=zeebe:26500
13
+ - zeebe.client.worker.hazelcast.connection=zeebe:5701
14
+ ports:
15
+ - "8082:8082"
16
+ depends_on:
17
+ - zeebe
data/docker-compose.yml CHANGED
@@ -8,7 +8,7 @@ x-environment: &default-environment
8
8
  BUNDLE_DISABLE_SHARED_GEMS: "true"
9
9
  ZEEBE_ADDRESS: zeebe:26500
10
10
  x-service: &default-service
11
- image: ruby:2.6.6
11
+ image: ruby:2.7.3
12
12
  volumes:
13
13
  - .:/usr/src/gem
14
14
  - ./compose/entrypoint.sh:/tmp/entrypoint.sh
@@ -18,22 +18,9 @@ x-service: &default-service
18
18
  stdin_open: true
19
19
  services:
20
20
  zeebe:
21
- image: camunda/zeebe:0.23.4
21
+ image: camunda/zeebe:${ZEEBE_VERSION:-1.0.0}
22
22
  environment:
23
23
  ZEEBE_LOG_LEVEL: debug
24
- volumes:
25
- - ./compose/zeebe-hazelcast-exporter.jar:/usr/local/zeebe/exporters/zeebe-hazelcast-exporter.jar
26
- - ./compose/application.yml:/usr/local/zeebe/config/application.yaml
27
-
28
- monitor:
29
- image: camunda/zeebe-simple-monitor:0.19.0
30
- environment:
31
- - zeebe.client.broker.contactPoint=zeebe:26500
32
- - zeebe.client.worker.hazelcast.connection=zeebe:5701
33
- ports:
34
- - "8082:8082"
35
- depends_on:
36
- - zeebe
37
24
 
38
25
  console:
39
26
  <<: *default-service
@@ -1,14 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support"
3
4
  require "rspec"
4
5
  require "zeebe/client"
6
+ require "zeebe_bpmn_rspec/deprecate_workflow_alias"
5
7
  require "zeebe_bpmn_rspec/helpers"
6
8
  require "zeebe_bpmn_rspec/version"
9
+ require "zeebe_bpmn_rspec/matchers/have_activated"
7
10
 
8
11
  # Top-level gem module
9
12
  module ZeebeBpmnRspec
10
13
  class << self
11
- attr_writer :client, :zeebe_address
14
+ attr_writer :client, :zeebe_address, :activate_request_timeout
12
15
 
13
16
  def configure
14
17
  yield(self)
@@ -23,6 +26,10 @@ module ZeebeBpmnRspec
23
26
  def zeebe_address
24
27
  @zeebe_address || ENV["ZEEBE_ADDRESS"] || (raise "zeebe_address must be set")
25
28
  end
29
+
30
+ def activate_request_timeout
31
+ @activate_request_timeout || 1000
32
+ end
26
33
  end
27
34
  end
28
35
 
@@ -1,34 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support"
4
3
  require "active_support/core_ext/hash/keys"
5
4
  require "json"
6
5
 
7
6
  module ZeebeBpmnRspec
8
7
  class ActivatedJob
9
8
  include ::Zeebe::Client::GatewayProtocol # for direct reference of request classes
9
+ extend DeprecateWorkflowAlias
10
10
 
11
- attr_reader :job, :type, :workflow_instance_key
11
+ attr_reader :job, :type
12
12
 
13
- def initialize(job, type:, workflow_instance_key:, client:, context:)
13
+ def initialize(job, type:, process_instance_key:, client:, context:, validate:) # rubocop:disable Metrics/ParameterLists
14
14
  @job = job
15
15
  @type = type
16
- @workflow_instance_key = workflow_instance_key
16
+ @process_instance_key = process_instance_key
17
17
  @client = client
18
18
  @context = context
19
19
 
20
- context.instance_eval do
21
- aggregate_failures do
22
- expect(job.workflowInstanceKey).to eq(workflow_instance_key)
23
- expect(job.type).to eq(type)
20
+ if validate
21
+ context.instance_eval do
22
+ expect(job).not_to be_nil, "expected to receive job of type '#{type}' but received none"
23
+ aggregate_failures do
24
+ expect(job.processInstanceKey).to eq(process_instance_key)
25
+ expect(job.type).to eq(type)
26
+ end
24
27
  end
25
28
  end
26
29
  end
27
30
 
31
+ def raw
32
+ job
33
+ end
34
+
28
35
  def key
29
36
  job.key
30
37
  end
31
38
 
39
+ def process_instance_key
40
+ job.processInstanceKey
41
+ end
42
+ deprecate_workflow_alias :workflow_instance_key, :process_instance_key
43
+
44
+ def retries
45
+ job.retries
46
+ end
47
+
48
+ def task_key
49
+ job.elementInstanceKey
50
+ end
51
+
52
+ def to_s
53
+ raw.to_s
54
+ end
55
+
32
56
  def variables
33
57
  @_variables ||= JSON.parse(job.variables)
34
58
  end
@@ -87,6 +111,13 @@ module ZeebeBpmnRspec
87
111
  end
88
112
  alias complete and_complete
89
113
 
114
+ def update_retries(retries = 1)
115
+ client.update_job_retries(UpdateJobRetriesRequest.new(
116
+ jobKey: job.key,
117
+ retries: retries
118
+ ))
119
+ end
120
+
90
121
  private
91
122
 
92
123
  attr_reader :client, :context
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/deprecation"
4
+
5
+ module ZeebeBpmnRspec
6
+ module DeprecateWorkflowAlias
7
+ WorkflowDeprecation = ActiveSupport::Deprecation.new("v2.0", "ZeebeBpmnRspec")
8
+
9
+ def deprecate_workflow_alias(deprecated_name, new_name)
10
+ alias_method deprecated_name, new_name
11
+ deprecate deprecated_name => new_name, deprecator: WorkflowDeprecation
12
+ end
13
+ end
14
+ end
@@ -1,42 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/object/blank"
3
4
  require "zeebe_bpmn_rspec/activated_job"
4
5
 
5
6
  module ZeebeBpmnRspec
6
7
  module Helpers # rubocop:disable Metrics/ModuleLength
7
8
  include ::Zeebe::Client::GatewayProtocol # for direct reference of request classes
8
-
9
- def deploy_workflow(path, name = nil)
10
- _zeebe_client.deploy_workflow(DeployWorkflowRequest.new(
11
- workflows: [WorkflowRequestObject.new(
12
- name: (name && "#{name}.bpmn") || File.basename(path),
13
- type: WorkflowRequestObject::ResourceType::FILE,
14
- definition: File.read(path)
15
- )]
16
- ))
9
+ extend DeprecateWorkflowAlias
10
+
11
+ def deploy_process(path, name = nil)
12
+ _zeebe_client.deploy_process(DeployProcessRequest.new(
13
+ processes: [ProcessRequestObject.new(
14
+ name: (name && "#{name}.bpmn") || File.basename(path),
15
+ definition: File.read(path)
16
+ )]
17
+ ))
17
18
  rescue StandardError => e
18
- raise "Failed to deploy workflow: #{e}"
19
+ raise "Failed to deploy precess: #{e}"
19
20
  end
21
+ deprecate_workflow_alias :deploy_workflow, :deploy_process
20
22
 
21
- def with_workflow_instance(name, variables = {})
23
+ def with_process_instance(name, variables = {})
22
24
  system_error = nil
23
- workflow = _zeebe_client.create_workflow_instance(CreateWorkflowInstanceRequest.new(
24
- bpmnProcessId: name,
25
- version: -1, # always latest
26
- variables: variables.to_json
27
- ))
28
- @__workflow_instance_key = workflow.workflowInstanceKey
29
- yield(workflow.workflowInstanceKey)
25
+ process = _zeebe_client.create_process_instance(CreateProcessInstanceRequest.new(
26
+ bpmnProcessId: name,
27
+ version: -1, # always latest
28
+ variables: variables.to_json
29
+ ))
30
+ @__process_instance_key = process.processInstanceKey
31
+ yield(process.processInstanceKey) if block_given?
30
32
  rescue Exception => e # rubocop:disable Lint/RescueException
31
33
  # exceptions are rescued to ensure that instances are cancelled
32
34
  # any error is re-raised below
33
35
  system_error = e
34
36
  ensure
35
- if workflow&.workflowInstanceKey
37
+ if process&.processInstanceKey
36
38
  begin
37
- _zeebe_client.cancel_workflow_instance(CancelWorkflowInstanceRequest.new(
38
- workflowInstanceKey: workflow.workflowInstanceKey
39
- ))
39
+ _zeebe_client.cancel_process_instance(CancelProcessInstanceRequest.new(
40
+ processInstanceKey: process.processInstanceKey
41
+ ))
40
42
  rescue GRPC::NotFound => _e
41
43
  # expected
42
44
  rescue StandardError => _e
@@ -45,56 +47,70 @@ module ZeebeBpmnRspec
45
47
  end
46
48
  raise system_error if system_error
47
49
  end
50
+ deprecate_workflow_alias :with_workflow_instance, :with_process_instance
48
51
 
49
- def workflow_complete!
52
+ def process_complete!(wait_seconds: 0.25)
50
53
  error = nil
51
- sleep 0.25 # TODO: configurable?
54
+ sleep(wait_seconds)
52
55
  begin
53
- _zeebe_client.cancel_workflow_instance(CancelWorkflowInstanceRequest.new(
54
- workflowInstanceKey: workflow_instance_key
55
- ))
56
+ _zeebe_client.cancel_process_instance(CancelProcessInstanceRequest.new(
57
+ processInstanceKey: process_instance_key
58
+ ))
56
59
  rescue GRPC::NotFound => e
57
60
  error = e
58
61
  end
59
62
 
60
- raise "Expected workflow instance #{workflow_instance_key} to be complete" if error.nil?
63
+ raise "Expected process instance #{process_instance_key} to be complete" if error.nil?
61
64
  end
65
+ deprecate_workflow_alias :workflow_complete!, :process_complete!
62
66
 
63
- def workflow_instance_key
64
- @__workflow_instance_key
67
+ def process_instance_key
68
+ @__process_instance_key
65
69
  end
70
+ deprecate_workflow_alias :workflow_instance_key, :process_instance_key
66
71
 
67
- def activate_job(type)
68
- stream = _zeebe_client.activate_jobs(ActivateJobsRequest.new(
69
- type: type,
70
- worker: "#{type}-#{SecureRandom.hex}",
71
- maxJobsToActivate: 1,
72
- timeout: 5000, # TODO: configure
73
- requestTimeout: 5000
74
- ))
72
+ def activate_job(type, fetch_variables: nil, validate: true, worker: "#{type}-#{SecureRandom.hex}")
73
+ raise ArgumentError.new("'worker' cannot be blank") if worker.blank?
74
+
75
+ stream = _zeebe_client.activate_jobs(ActivateJobsRequest.new({
76
+ type: type,
77
+ worker: worker,
78
+ maxJobsToActivate: 1,
79
+ timeout: 1000,
80
+ fetchVariable: fetch_variables&.then { |v| Array(v) },
81
+ requestTimeout: ZeebeBpmnRspec.activate_request_timeout,
82
+ }.compact))
75
83
 
76
84
  job = nil
77
85
  stream.find { |response| job = response.jobs.first }
78
- raise "No job with type #{type.inspect} found" if job.nil?
79
-
80
86
  # puts job.inspect # support debug logging?
81
87
 
82
88
  ActivatedJob.new(job,
83
89
  type: type,
84
- workflow_instance_key: workflow_instance_key,
90
+ process_instance_key: process_instance_key,
85
91
  client: _zeebe_client,
86
- context: self)
92
+ context: self,
93
+ validate: validate)
87
94
  end
88
95
  alias process_job activate_job
89
- # TODO: deprecate process_job
96
+ deprecate process_job: :activate_job
90
97
 
91
- def activate_jobs(type, max_jobs: nil)
98
+ def job_with_type(type, fetch_variables: nil)
99
+ activate_job(type, fetch_variables: fetch_variables, validate: false)
100
+ end
101
+
102
+ def expect_job_of_type(type, fetch_variables: nil)
103
+ expect(job_with_type(type, fetch_variables: fetch_variables))
104
+ end
105
+
106
+ def activate_jobs(type, max_jobs: nil, fetch_variables: nil)
92
107
  stream = _zeebe_client.activate_jobs(ActivateJobsRequest.new({
93
108
  type: type,
94
109
  worker: "#{type}-#{SecureRandom.hex}",
95
110
  maxJobsToActivate: max_jobs,
96
- timeout: 5000, # TODO: configure
97
- requestTimeout: 5000,
111
+ timeout: 1000,
112
+ fetchVariable: fetch_variables&.then { |v| Array(v) },
113
+ requestTimeout: ZeebeBpmnRspec.activate_request_timeout,
98
114
  }.compact))
99
115
 
100
116
  Enumerator.new do |yielder|
@@ -102,27 +118,36 @@ module ZeebeBpmnRspec
102
118
  response.jobs.each do |job|
103
119
  yielder << ActivatedJob.new(job,
104
120
  type: type,
105
- workflow_instance_key: workflow_instance_key,
121
+ process_instance_key: process_instance_key,
106
122
  client: _zeebe_client,
107
- context: self)
123
+ context: self,
124
+ validate: true)
108
125
  end
109
126
  end
110
127
  end
111
128
  end
112
129
 
113
- def publish_message(name, correlation_key:, variables: nil)
130
+ def publish_message(name, correlation_key:, variables: nil, ttl_ms: 5000)
114
131
  _zeebe_client.publish_message(PublishMessageRequest.new(
115
132
  {
116
133
  name: name,
117
134
  correlationKey: correlation_key,
118
- timeToLive: 5000,
135
+ timeToLive: ttl_ms,
119
136
  variables: variables&.to_json,
120
137
  }.compact
121
138
  ))
122
139
  end
123
140
 
141
+ def set_variables(key, variables, local: true)
142
+ _zeebe_client.set_variables(SetVariablesRequest.new(
143
+ elementInstanceKey: key,
144
+ variables: variables.to_json,
145
+ local: local
146
+ ))
147
+ end
148
+
124
149
  def reset_zeebe!
125
- @__workflow_instance_key = nil
150
+ @__process_instance_key = nil
126
151
  end
127
152
 
128
153
  private
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zeebe_bpmn_rspec/matchers/have_variables"
4
+ require "zeebe_bpmn_rspec/matchers/have_headers"
5
+
6
+ module ZeebeBpmnRspec
7
+ class HaveActivatedMatcherError < StandardError
8
+ def initialize
9
+ super("Only one of complete, fail, and throw error can be specified")
10
+ end
11
+ end
12
+ end
13
+
14
+ # rubocop:disable Metrics/BlockLength
15
+ RSpec::Matchers.define :have_activated do
16
+ match do |job|
17
+ @job = job
18
+
19
+ @matcher_error = nil
20
+ begin
21
+ aggregate_failures "activated job#{of_type(job)}" do
22
+ unless job.is_a?(ZeebeBpmnRspec::ActivatedJob)
23
+ raise ArgumentError.new("expectation target must be a "\
24
+ "#{ZeebeBpmnRspec::ActivatedJob.name}, got #{job.inspect}")
25
+ end
26
+
27
+ if job.raw.nil?
28
+ raise RSpec::Expectations::ExpectationNotMetError.new("expected activated job#{of_type(job)}, got nil")
29
+ end
30
+
31
+ expect(job).to have_variables(@variables) if @variables
32
+ expect(job).to have_headers(@headers) if @headers
33
+ end
34
+ rescue Exception => e # rubocop:disable Lint/RescueException
35
+ @matcher_error = e
36
+ end
37
+ return false if @matcher_error
38
+
39
+ if @complete
40
+ job.complete(@output || {})
41
+ elsif @fail
42
+ job.fail(@fail_message, retries: @retries)
43
+ elsif @throw
44
+ job.throw_error(@error_code, @throw_message)
45
+ end
46
+
47
+ true
48
+ end
49
+
50
+ def of_type(job)
51
+ job.respond_to?(:type) ? " of type #{job.type}" : nil
52
+ end
53
+
54
+ failure_message do |_job|
55
+ raise matcher_error
56
+ end
57
+
58
+ attr_reader :job, :matcher_error
59
+
60
+ def predestined?
61
+ @complete || @fail || @throw
62
+ end
63
+
64
+ def check_predestined!
65
+ raise ZeebeBpmnRspec::HaveActivatedMatcherError.new if predestined?
66
+ end
67
+
68
+ chain :with_variables do |variables|
69
+ @variables = variables.is_a?(Hash) ? variables.stringify_keys : variables
70
+ end
71
+
72
+ chain :with_headers do |headers|
73
+ @headers = headers.is_a?(Hash) ? headers.stringify_keys : headers
74
+ end
75
+
76
+ chain :and_complete do |output = nil|
77
+ check_predestined!
78
+
79
+ @output = output
80
+ @complete = true
81
+ end
82
+
83
+ chain :and_fail do |message = nil, retries: 0|
84
+ check_predestined!
85
+
86
+ @fail_message = message
87
+ @retries = retries
88
+ @fail = true
89
+ end
90
+
91
+ chain :and_throw_error do |error_code, message = nil|
92
+ check_predestined!
93
+
94
+ @error_code = error_code
95
+ @throw_message = message
96
+ @throw = true
97
+ end
98
+ end
99
+ # rubocop:enable Metrics/BlockLength
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec::Matchers.define :have_headers do
4
+ match do |actual|
5
+ @job = actual
6
+ @actual = @job.headers
7
+ values_match?(expected, @actual)
8
+ end
9
+
10
+ failure_message do |_actual|
11
+ "expected that job:\n #{@job}\n\nwould have headers #{expected}"
12
+ end
13
+
14
+ diffable
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec::Matchers.define :have_variables do |expected|
4
+ match do |actual|
5
+ @job = actual
6
+ @actual = @job.variables
7
+ values_match?(expected, @actual)
8
+ end
9
+
10
+ failure_message do |_actual|
11
+ "expected that job:\n #{@job}\n\nwould have variables #{expected}"
12
+ end
13
+
14
+ diffable
15
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ZeebeBpmnRspec
4
- VERSION = "0.2.0"
4
+ VERSION = "1.0.0"
5
5
  end
@@ -41,7 +41,9 @@ Gem::Specification.new do |spec|
41
41
  spec.executables = []
42
42
  spec.require_paths = ["lib"]
43
43
 
44
- spec.add_development_dependency "bundler", "~> 1.12"
44
+ spec.required_ruby_version = ">= 2.6"
45
+
46
+ spec.add_development_dependency "bundler", "~> 2.1"
45
47
  spec.add_development_dependency "ezcater_rubocop", "2.0.0"
46
48
  spec.add_development_dependency "overcommit"
47
49
  spec.add_development_dependency "rake", "~> 10.0"
@@ -50,5 +52,5 @@ Gem::Specification.new do |spec|
50
52
 
51
53
  spec.add_runtime_dependency "activesupport"
52
54
  spec.add_runtime_dependency "rspec", "~> 3.4"
53
- spec.add_runtime_dependency "zeebe-client"
55
+ spec.add_runtime_dependency "zeebe-client", "~> 0.14.0"
54
56
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zeebe_bpmn_rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ezCater, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-29 00:00:00.000000000 Z
11
+ date: 2021-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.12'
19
+ version: '2.1'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.12'
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ezcater_rubocop
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -126,16 +126,16 @@ dependencies:
126
126
  name: zeebe-client
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: 0.14.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ">="
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: 0.14.0
139
139
  description: Zeebe BPMN testing using RSpec
140
140
  email:
141
141
  - engineering@ezcater.com
@@ -148,10 +148,15 @@ files:
148
148
  - Gemfile
149
149
  - LICENSE.txt
150
150
  - README.md
151
+ - docker-compose.simple-monitor.yml
151
152
  - docker-compose.yml
152
153
  - lib/zeebe_bpmn_rspec.rb
153
154
  - lib/zeebe_bpmn_rspec/activated_job.rb
155
+ - lib/zeebe_bpmn_rspec/deprecate_workflow_alias.rb
154
156
  - lib/zeebe_bpmn_rspec/helpers.rb
157
+ - lib/zeebe_bpmn_rspec/matchers/have_activated.rb
158
+ - lib/zeebe_bpmn_rspec/matchers/have_headers.rb
159
+ - lib/zeebe_bpmn_rspec/matchers/have_variables.rb
155
160
  - lib/zeebe_bpmn_rspec/version.rb
156
161
  - zeebe_bpmn_rspec.gemspec
157
162
  homepage: https://github.com/ezcater/zeebe_bpmn_rspec
@@ -167,14 +172,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
167
172
  requirements:
168
173
  - - ">="
169
174
  - !ruby/object:Gem::Version
170
- version: '0'
175
+ version: '2.6'
171
176
  required_rubygems_version: !ruby/object:Gem::Requirement
172
177
  requirements:
173
178
  - - ">="
174
179
  - !ruby/object:Gem::Version
175
180
  version: '0'
176
181
  requirements: []
177
- rubygems_version: 3.0.3
182
+ rubygems_version: 3.1.4
178
183
  signing_key:
179
184
  specification_version: 4
180
185
  summary: Zeebe BPMN testing using RSpec