dor-workflow-client 3.0.0.rc1

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.
@@ -0,0 +1,633 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Dor::Workflow::Client do
6
+ let(:wf_xml) do
7
+ <<-EOXML
8
+ <workflow id="etdSubmitWF">
9
+ <process name="register-object" status="completed" attempts="1" />
10
+ <process name="submit" status="waiting" />
11
+ <process name="reader-approval" status="waiting" />
12
+ <process name="registrar-approval" status="waiting" />
13
+ <process name="start-accession" status="waiting" />
14
+ </workflow>
15
+ EOXML
16
+ end
17
+
18
+ let(:wf_xml_label) do
19
+ <<~EOXML
20
+ <?xml version="1.0"?>
21
+ <workflow id="etdSubmitWF">
22
+ <process name="register-object" status="completed" attempts="1" laneId="default"/>
23
+ <process name="submit" status="waiting" laneId="default"/>
24
+ <process name="reader-approval" status="waiting" laneId="default"/>
25
+ <process name="registrar-approval" status="waiting" laneId="default"/>
26
+ <process name="start-accession" status="waiting" laneId="default"/>
27
+ </workflow>
28
+ EOXML
29
+ end
30
+
31
+ let(:stubs) do
32
+ Faraday::Adapter::Test::Stubs.new
33
+ end
34
+
35
+ let(:mock_http_connection) do
36
+ Faraday.new(url: 'http://example.com/') do |builder|
37
+ builder.use Faraday::Response::RaiseError
38
+ builder.options.params_encoder = Faraday::FlatParamsEncoder
39
+
40
+ builder.adapter :test, stubs
41
+ end
42
+ end
43
+
44
+ let(:mock_logger) { double('Logger', info: true, debug: true, warn: true) }
45
+
46
+ before do
47
+ @repo = 'dor'
48
+ @druid = 'druid:123'
49
+ end
50
+
51
+ let(:client) { described_class.new connection: mock_http_connection, logger: mock_logger }
52
+
53
+ describe '#connection' do
54
+ subject(:conn) { client.requestor.connection }
55
+ let(:client) { described_class.new url: 'http://example.com', timeout: 99, logger: mock_logger }
56
+
57
+ it 'has a timeout' do
58
+ expect(conn).to be_a(Faraday::Connection)
59
+ expect(conn.options.timeout).to eq(99)
60
+ expect(conn.options.open_timeout).to eq(99)
61
+ end
62
+
63
+ it 'has a user_agent' do
64
+ expect(conn.headers).to include('User-Agent' => /dor-workflow-service \d+\.\d+\.\d+/)
65
+ end
66
+
67
+ it 'defaults to using the flat params encoder' do
68
+ expect(conn.options.params_encoder).to eq Faraday::FlatParamsEncoder
69
+ end
70
+ end
71
+
72
+ describe '#create_workflow' do
73
+ let(:stubs) do
74
+ Faraday::Adapter::Test::Stubs.new do |stub|
75
+ stub.put("#{@repo}/objects/#{@druid}/workflows/etdSubmitWF") { |_env| [201, {}, ''] }
76
+ stub.put("#{@repo}/objects/#{@druid}/workflows/noCreateDsWF?create-ds=false") { |_env| [201, {}, ''] }
77
+ stub.put("#{@repo}/objects/#{@druid}/workflows/raiseException") { |_env| raise 'broken' }
78
+ end
79
+ end
80
+
81
+ it 'should pass workflow xml to the DOR workflow service and return the URL to the workflow' do
82
+ client.create_workflow(@repo, @druid, 'etdSubmitWF', wf_xml)
83
+ end
84
+
85
+ it 'should raise on an unexpected Exception' do
86
+ expect { client.create_workflow(@repo, @druid, 'raiseException', wf_xml) }.to raise_error(Exception, 'broken')
87
+ end
88
+
89
+ it 'sets the create-ds param to the value of the passed in options hash' do
90
+ client.create_workflow(@repo, @druid, 'noCreateDsWF', wf_xml, create_ds: false)
91
+ end
92
+
93
+ it 'adds lane_id attributes to all steps if passed in as an option' do
94
+ skip 'test not implemented'
95
+ end
96
+ end
97
+
98
+ describe '#update_workflow_status' do
99
+ let(:stubs) do
100
+ Faraday::Adapter::Test::Stubs.new do |stub|
101
+ stub.put("#{@repo}/objects/#{@druid}/workflows/etdSubmitWF/registrar-approval?current-status=queued") do |_env|
102
+ [201, {}, '{"next_steps":["submit-marc"]}']
103
+ end
104
+
105
+ stub.put("#{@repo}/objects/#{@druid}/workflows/etdSubmitWF/registrar-approval") do |env|
106
+ expect(env.body).to eq "<?xml version=\"1.0\"?>\n<process name=\"registrar-approval\" status=\"completed\" elapsed=\"0\" note=\"annotation\" version=\"2\" laneId=\"lane2\"/>\n"
107
+ [201, {}, '{"next_steps":["submit-marc"]}']
108
+ end
109
+
110
+ stub.put("#{@repo}/objects/#{@druid}/workflows/errorWF/registrar-approval") do |_env|
111
+ [400, {}, '']
112
+ end
113
+ end
114
+ end
115
+
116
+ it 'should update workflow status and return true if successful' do
117
+ expect(client.update_workflow_status(@repo, @druid, 'etdSubmitWF', 'registrar-approval', 'completed', version: 2, note: 'annotation', lane_id: 'lane2')).to be_kind_of Dor::Workflow::Response::Update
118
+ end
119
+
120
+ it 'should return false if the PUT to the DOR workflow service throws an exception' do
121
+ expect { client.update_workflow_status(@repo, @druid, 'errorWF', 'registrar-approval', 'completed') }.to raise_error(Dor::WorkflowException, /status 400/)
122
+ end
123
+
124
+ it 'performs a conditional update when current-status is passed as a parameter' do
125
+ expect(mock_http_connection).to receive(:put).with("#{@repo}/objects/#{@druid}/workflows/etdSubmitWF/registrar-approval?current-status=queued").and_call_original
126
+
127
+ expect(client.update_workflow_status(@repo, @druid, 'etdSubmitWF', 'registrar-approval', 'completed', version: 2, note: 'annotation', lane_id: 'lane1', current_status: 'queued')).to be_kind_of Dor::Workflow::Response::Update
128
+ end
129
+
130
+ it 'should throw exception if invalid status provided' do
131
+ expect { client.update_workflow_status(@repo, @druid, 'accessionWF', 'publish', 'NOT_VALID_STATUS') }.to raise_error(ArgumentError)
132
+ end
133
+ end
134
+
135
+ describe '#update_workflow_error_status' do
136
+ let(:stubs) do
137
+ Faraday::Adapter::Test::Stubs.new do |stub|
138
+ stub.put("#{@repo}/objects/#{@druid}/workflows/etdSubmitWF/reader-approval") do |env|
139
+ expect(env.body).to match(/status="error" errorMessage="Some exception" errorText="The optional stacktrace"/)
140
+ [201, {}, '']
141
+ end
142
+
143
+ stub.put("#{@repo}/objects/#{@druid}/workflows/errorWF/reader-approval") do |_env|
144
+ [400, {}, '']
145
+ end
146
+ end
147
+ end
148
+
149
+ it 'should update workflow status to error and return true if successful' do
150
+ client.update_workflow_error_status(@repo, @druid, 'etdSubmitWF', 'reader-approval', 'Some exception', error_text: 'The optional stacktrace')
151
+ end
152
+ it 'should return false if the PUT to the DOR workflow service throws an exception' do
153
+ expect { client.update_workflow_status(@repo, @druid, 'errorWF', 'reader-approval', 'completed') }.to raise_error(Dor::WorkflowException, /status 400/)
154
+ end
155
+ end
156
+
157
+ describe '#workflow_status' do
158
+ let(:repo) { @repo }
159
+ let(:druid) { @druid }
160
+ let(:stubs) do
161
+ Faraday::Adapter::Test::Stubs.new do |stub|
162
+ stub.get("#{repo}/objects/#{druid}/workflows/#{workflow_name}") do |_env|
163
+ response
164
+ end
165
+ end
166
+ end
167
+
168
+ subject { client.workflow_status(repo, druid, workflow_name, step_name) }
169
+ let(:step_name) { 'registrar-approval' }
170
+ let(:workflow_name) { 'etdSubmitWF' }
171
+ let(:status) { 200 }
172
+ let(:response) do
173
+ [status, {}, xml]
174
+ end
175
+ let(:xml) { '' }
176
+
177
+ context 'when a single result is returned' do
178
+ let(:xml) do
179
+ '<workflow><process name="registrar-approval" status="completed" /></workflow>'
180
+ end
181
+
182
+ it 'returns status as a string' do
183
+ expect(subject).to eq('completed')
184
+ end
185
+ end
186
+
187
+ context 'when a multiple versions are returned' do
188
+ let(:xml) do
189
+ '<workflow><process name="registrar-approval" version="1" status="completed" />
190
+ <process name="registrar-approval" version="2" status="waiting" /></workflow>'
191
+ end
192
+
193
+ it 'returns the status for the highest version' do
194
+ expect(subject).to eq('waiting')
195
+ end
196
+ end
197
+
198
+ context 'when it fails for any reason' do
199
+ let(:status) { 404 }
200
+
201
+ it 'throws an exception' do
202
+ expect { subject }.to raise_error Dor::WorkflowException
203
+ end
204
+ end
205
+
206
+ context 'when it cannot parse the response' do
207
+ let(:xml) do
208
+ 'something not xml'
209
+ end
210
+
211
+ it 'throws an exception' do
212
+ expect { subject }.to raise_error Dor::WorkflowException, "Unable to parse response:\nsomething not xml"
213
+ end
214
+ end
215
+
216
+ context 'when the workflow/process combination doesnt exist' do
217
+ let(:xml) do
218
+ '<workflow><process name="registrar-approval" status="completed" /></workflow>'
219
+ end
220
+ let(:step_name) { 'publish' }
221
+
222
+ it 'returns nil' do
223
+ expect(subject).to be_nil
224
+ end
225
+ end
226
+ end
227
+
228
+ describe '#workflow_xml' do
229
+ subject(:workflow_xml) { client.workflow_xml('dor', 'druid:123', workflow) }
230
+
231
+ context 'when a workflow name is provided' do
232
+ let(:workflow) { 'etdSubmitWF' }
233
+ let(:xml) { '<workflow id="etdSubmitWF"><process name="registrar-approval" status="completed" /></workflow>' }
234
+ let(:stubs) do
235
+ Faraday::Adapter::Test::Stubs.new do |stub|
236
+ stub.get('dor/objects/druid:123/workflows/etdSubmitWF') do |_env|
237
+ [200, {}, xml]
238
+ end
239
+ end
240
+ end
241
+
242
+ it 'returns the xml for a given repository, druid, and workflow' do
243
+ expect(workflow_xml).to eq(xml)
244
+ end
245
+ end
246
+
247
+ context 'when no workflow name is provided' do
248
+ let(:workflow) { nil }
249
+
250
+ it 'raises an error' do
251
+ expect { workflow_xml }.to raise_error ArgumentError
252
+ end
253
+ end
254
+ end
255
+
256
+ describe '#all_workflows_xml' do
257
+ subject(:all_workflows_xml) { client.all_workflows_xml('druid:123') }
258
+
259
+ let(:workflow) { 'etdSubmitWF' }
260
+ let(:xml) do
261
+ <<~XML
262
+ <workflows>
263
+ <workflow id="etdSubmitWF"><process name="registrar-approval" status="completed" /></workflow>
264
+ <workflow id="etdSubmitWF"><process name="registrar-approval" status="completed" /></workflow>
265
+ </workflows>
266
+ XML
267
+ end
268
+ let(:stubs) do
269
+ Faraday::Adapter::Test::Stubs.new do |stub|
270
+ stub.get('objects/druid:123/workflows') do |_env|
271
+ [200, {}, xml]
272
+ end
273
+ end
274
+ end
275
+
276
+ it 'returns the xml for a given druid' do
277
+ expect(all_workflows_xml).to eq(xml)
278
+ end
279
+ end
280
+
281
+ describe '#workflows' do
282
+ let(:xml) { '<workflow id="accessionWF"><process name="publish" status="completed" /></workflow>' }
283
+ let(:stubs) do
284
+ Faraday::Adapter::Test::Stubs.new do |stub|
285
+ stub.get("dor/objects/#{@druid}/workflows/") do |_env|
286
+ [200, {}, xml]
287
+ end
288
+ end
289
+ end
290
+
291
+ it 'returns the workflows associated with druid' do
292
+ expect(client.workflows(@druid)).to eq(['accessionWF'])
293
+ end
294
+ end
295
+
296
+ describe '#lifecycle' do
297
+ let(:stubs) do
298
+ Faraday::Adapter::Test::Stubs.new do |stub|
299
+ stub.get('dor/objects/druid:123/lifecycle') do |_env|
300
+ [200, {}, <<-EOXML]
301
+ <lifecycle objectId="druid:ct011cv6501">
302
+ <milestone date="2010-04-27T11:34:17-0700">registered</milestone>
303
+ <milestone date="2010-04-29T10:12:51-0700">inprocess</milestone>
304
+ <milestone date="2010-06-15T16:08:58-0700">released</milestone>
305
+ </lifecycle>
306
+ EOXML
307
+ end
308
+
309
+ stub.get('dor/objects/druid:abc/lifecycle') do |_env|
310
+ [200, {}, <<-EOXML]
311
+ <lifecycle />
312
+ EOXML
313
+ end
314
+ end
315
+ end
316
+
317
+ it 'returns a Time object reprenting when the milestone was reached' do
318
+ expect(client.lifecycle('dor', 'druid:123', 'released').beginning_of_day).to eq(Time.parse('2010-06-15T16:08:58-0700').beginning_of_day)
319
+ end
320
+
321
+ it "returns nil if the milestone hasn't been reached yet" do
322
+ expect(client.lifecycle('dor', 'druid:abc', 'inprocess')).to be_nil
323
+ end
324
+ end
325
+
326
+ describe '#active_lifecycle' do
327
+ let(:stubs) do
328
+ Faraday::Adapter::Test::Stubs.new do |stub|
329
+ stub.get("dor/objects/#{@druid}/lifecycle") do |_env|
330
+ [200, {}, <<-EOXML]
331
+ <lifecycle objectId="#{@druid}">
332
+ <milestone date="2010-04-27T11:34:17-0700">registered</milestone>
333
+ <milestone date="2010-04-29T10:12:51-0700">inprocess</milestone>
334
+ <milestone date="2010-06-15T16:08:58-0700">released</milestone>
335
+ </lifecycle>
336
+ EOXML
337
+ end
338
+
339
+ stub.get("dor/objects/#{@druid}/lifecycle") do |_env|
340
+ [200, {}, <<-EOXML]
341
+ <lifecycle />
342
+ EOXML
343
+ end
344
+ end
345
+ end
346
+
347
+ it 'parses out the active lifecycle' do
348
+ expect(client.active_lifecycle('dor', @druid, 'released').beginning_of_day).to eq(Time.parse('2010-06-15T16:08:58-0700').beginning_of_day)
349
+ end
350
+
351
+ it 'handles missing lifecycle' do
352
+ expect(client.active_lifecycle('dor', @druid, 'NOT_FOUND')).to be_nil
353
+ end
354
+ end
355
+
356
+ context '#objects_for_workstep' do
357
+ before(:all) do
358
+ @repository = 'dor'
359
+ @workflow = 'googleScannedBookWF'
360
+ @completed = 'google-download'
361
+ @waiting = 'process-content'
362
+ end
363
+
364
+ let(:stubs) do
365
+ Faraday::Adapter::Test::Stubs.new do |stub|
366
+ stub.get("workflow_queue?waiting=#{@repository}:#{@workflow}:#{@waiting}&completed=#{@repository}:#{@workflow}:#{@completed}&lane-id=default") do |_env|
367
+ [200, {}, '<objects count="1"><object id="druid:ab123de4567"/><object id="druid:ab123de9012"/></objects>']
368
+ end
369
+ end
370
+ end
371
+
372
+ describe 'a query with one step completed and one waiting' do
373
+ it 'creates the URI string with only the one completed step' do
374
+ expect(client.objects_for_workstep(@completed, @waiting, 'default', default_repository: @repository, default_workflow: @workflow)).to eq(['druid:ab123de4567', 'druid:ab123de9012'])
375
+ end
376
+ end
377
+
378
+ describe 'a query with TWO steps completed and one waiting' do
379
+ it 'creates the URI string with the two completed steps correctly' do
380
+ second_completed = 'google-convert'
381
+ xml = %(<objects count="1"><object id="druid:ab123de4567"/><object id="druid:ab123de9012"/></objects>)
382
+ allow(mock_http_connection).to receive(:get).with("workflow_queue?waiting=#{@repository}:#{@workflow}:#{@waiting}&completed=#{@repository}:#{@workflow}:#{@completed}&completed=#{@repository}:#{@workflow}:#{second_completed}&lane-id=default").and_return(double(Faraday::Response, body: xml))
383
+ expect(client.objects_for_workstep([@completed, second_completed], @waiting, 'default', default_repository: @repository, default_workflow: @workflow)).to eq(['druid:ab123de4567', 'druid:ab123de9012'])
384
+ end
385
+ end
386
+
387
+ context 'a query using qualified workflow names for completed and waiting' do
388
+ before :each do
389
+ @qualified_waiting = "#{@repository}:#{@workflow}:#{@waiting}"
390
+ @qualified_completed = "#{@repository}:#{@workflow}:#{@completed}"
391
+ end
392
+
393
+ RSpec.shared_examples 'lane-aware' do
394
+ it 'creates the URI string with the two completed steps across repositories correctly' do
395
+ qualified_completed2 = 'sdr:sdrIngestWF:complete-deposit'
396
+ qualified_completed3 = 'sdr:sdrIngestWF:ingest-transfer'
397
+ xml = %(<objects count="2"><object id="druid:ab123de4567"/><object id="druid:ab123de9012"/></objects>)
398
+ allow(mock_http_connection).to receive(:get).with("workflow_queue?waiting=#{@qualified_waiting}&completed=#{@qualified_completed}&completed=#{qualified_completed2}&completed=#{qualified_completed3}&lane-id=#{laneid}").and_return(double(Faraday::Response, body: xml))
399
+ args = [[@qualified_completed, qualified_completed2, qualified_completed3], @qualified_waiting]
400
+ args << laneid if laneid != 'default'
401
+ expect(client.objects_for_workstep(*args)).to eq(['druid:ab123de4567', 'druid:ab123de9012'])
402
+ end
403
+ end
404
+
405
+ describe 'default lane_id' do
406
+ it_behaves_like 'lane-aware' do
407
+ let(:laneid) { 'default' }
408
+ end
409
+ end
410
+ describe 'explicit lane_id' do
411
+ it_behaves_like 'lane-aware' do
412
+ let(:laneid) { 'lane1' }
413
+ end
414
+ end
415
+
416
+ context 'URI string creation' do
417
+ before :each do
418
+ @xml = %(<objects count="1"><object id="druid:ab123de4567"/></objects>)
419
+ end
420
+ it 'with only one completed step passed in as a String' do
421
+ allow(mock_http_connection).to receive(:get).with("workflow_queue?waiting=#{@qualified_waiting}&completed=#{@qualified_completed}&lane-id=default").and_return(double(Faraday::Response, body: @xml))
422
+ expect(client.objects_for_workstep(@qualified_completed, @qualified_waiting)).to eq(['druid:ab123de4567'])
423
+ end
424
+ it 'without any completed steps, only waiting' do
425
+ allow(mock_http_connection).to receive(:get).with("workflow_queue?waiting=#{@qualified_waiting}&lane-id=default").and_return(double(Faraday::Response, body: @xml))
426
+ expect(client.objects_for_workstep(nil, @qualified_waiting)).to eq(['druid:ab123de4567'])
427
+ end
428
+ it 'same but with lane_id' do
429
+ allow(mock_http_connection).to receive(:get).with("workflow_queue?waiting=#{@qualified_waiting}&lane-id=lane1").and_return(double(Faraday::Response, body: @xml))
430
+ expect(client.objects_for_workstep(nil, @qualified_waiting, 'lane1')).to eq(['druid:ab123de4567'])
431
+ end
432
+ end
433
+ end
434
+ end
435
+
436
+ context 'get empty workflow queue' do
437
+ before(:all) do
438
+ @repository = 'dor'
439
+ @workflow = 'googleScannedBookWF'
440
+ @completed = 'google-download'
441
+ @waiting = 'process-content'
442
+ end
443
+
444
+ let(:stubs) do
445
+ Faraday::Adapter::Test::Stubs.new do |stub|
446
+ stub.get("workflow_queue?waiting=#{@repository}:#{@workflow}:#{@waiting}&completed=#{@repository}:#{@workflow}:#{@completed}&lane-id=default") do |_env|
447
+ [200, {}, '<objects count="0"/>']
448
+ end
449
+ end
450
+ end
451
+
452
+ it 'returns an empty list if it encounters an empty workflow queue' do
453
+ expect(client.objects_for_workstep(@completed, @waiting, 'default', default_repository: @repository, default_workflow: @workflow)).to eq([])
454
+ end
455
+ end
456
+
457
+ context 'get errored workflow steps' do
458
+ before(:all) do
459
+ @repository = 'dor'
460
+ @workflow = 'accessionWF'
461
+ @step = 'publish'
462
+ end
463
+
464
+ let(:stubs) do
465
+ Faraday::Adapter::Test::Stubs.new do |stub|
466
+ stub.get("/workflow_queue?error=#{@step}&repository=#{@repository}&workflow=#{@workflow}") do |_env|
467
+ [200, {}, <<-EOXML]
468
+ <objects count="1">
469
+ <object id="druid:ab123cd4567" errorMessage="This is an error message"/>
470
+ </objects>
471
+ EOXML
472
+ end
473
+ end
474
+ end
475
+
476
+ describe 'errored_objects_for_workstep' do
477
+ it 'returns error messages for errored objects' do
478
+ expect(client.errored_objects_for_workstep(@workflow, @step, @repository)).to eq('druid:ab123cd4567' => 'This is an error message')
479
+ end
480
+ end
481
+
482
+ describe 'count_errored_for_workstep' do
483
+ it 'counts how many steps are errored out' do
484
+ expect(client.count_errored_for_workstep(@workflow, @step, @repository)).to eq(1)
485
+ end
486
+ end
487
+ end
488
+
489
+ describe '#count_queued_for_workstep' do
490
+ before(:all) do
491
+ @repository = 'dor'
492
+ @workflow = 'accessionWF'
493
+ @step = 'publish'
494
+ end
495
+
496
+ let(:stubs) do
497
+ Faraday::Adapter::Test::Stubs.new do |stub|
498
+ stub.get("/workflow_queue?queued=#{@step}&repository=#{@repository}&workflow=#{@workflow}") do |_env|
499
+ [200, {}, <<-EOXML]
500
+ <objects count="1">
501
+ <object id="druid:ab123cd4567"/>
502
+ </objects>
503
+ EOXML
504
+ end
505
+ end
506
+ end
507
+
508
+ it 'counts how many steps are errored out' do
509
+ expect(client.count_queued_for_workstep(@workflow, @step, @repository)).to eq(1)
510
+ end
511
+ end
512
+
513
+ describe '#count_objects_in_step' do
514
+ before(:all) do
515
+ @workflow = 'sdrIngestWF'
516
+ @step = 'start-ingest'
517
+ @type = 'waiting'
518
+ @repository = 'sdr'
519
+ end
520
+
521
+ let(:stubs) do
522
+ Faraday::Adapter::Test::Stubs.new do |stub|
523
+ stub.get("/workflow_queue?repository=#{@repository}&workflow=#{@workflow}&#{@type}=#{@step}") do |_env|
524
+ [200, {}, <<-EOXML]
525
+ <objects count="1">
526
+ <object id="druid:oo000ra0001" url="null/fedora/objects/druid:oo000ra0001"/>
527
+ </objects>
528
+ EOXML
529
+ end
530
+ end
531
+ end
532
+
533
+ it 'counts how many objects are at the type of step' do
534
+ expect(client.count_objects_in_step(@workflow, @step, @type, @repository)).to eq(1)
535
+ end
536
+ end
537
+
538
+ describe '#delete_workflow' do
539
+ let(:url) { "#{@repo}/objects/#{@druid}/workflows/accessionWF" }
540
+
541
+ let(:stubs) do
542
+ Faraday::Adapter::Test::Stubs.new do |stub|
543
+ stub.delete(url) { |_env| [202, {}, ''] }
544
+ end
545
+ end
546
+
547
+ it 'sends a delete request to the workflow service' do
548
+ expect(mock_http_connection).to receive(:delete).with(url).and_call_original
549
+ client.delete_workflow(@repo, @druid, 'accessionWF')
550
+ end
551
+ end
552
+
553
+ describe '#close_version' do
554
+ let(:stubs) do
555
+ Faraday::Adapter::Test::Stubs.new do |stub|
556
+ stub.post('dor/objects/druid:123/versionClose?create-accession=false') do |_env|
557
+ [202, {}, '']
558
+ end
559
+
560
+ stub.post('dor/objects/druid:123/versionClose') do |_env|
561
+ [202, {}, '']
562
+ end
563
+ end
564
+ end
565
+
566
+ let(:url) { 'dor/objects/druid:123/versionClose' }
567
+ it 'calls the versionClose endpoint with druid' do
568
+ client.close_version(@repo, @druid)
569
+ end
570
+
571
+ it 'optionally prevents creation of accessionWF' do
572
+ expect(mock_http_connection).to receive(:post).with('dor/objects/druid:123/versionClose?create-accession=false').and_call_original
573
+ client.close_version(@repo, @druid, false)
574
+ end
575
+ end
576
+
577
+ describe '.stale_queued_workflows' do
578
+ let(:stubs) do
579
+ Faraday::Adapter::Test::Stubs.new do |stub|
580
+ stub.get('workflow_queue/all_queued?repository=dor&hours-ago=24&limit=100') do |_env|
581
+ [200, {}, <<-XML]
582
+ <workflows>
583
+ <workflow laneId="lane1" note="annotation" lifecycle="in-process" errorText="stacktrace" errorMessage="NullPointerException" elapsed="1.173" repository="dor" attempts="0" datetime="2008-11-15T13:30:00-0800" status="waiting" process="content-metadata" name="accessionWF" druid="dr:123"/>
584
+ <workflow laneId="lane2" note="annotation" lifecycle="in-process" errorText="stacktrace" errorMessage="NullPointerException" elapsed="1.173" repository="dor" attempts="0" datetime="2008-11-15T13:30:00-0800" status="waiting" process="jp2-create" name="assemblyWF" druid="dr:456"/>
585
+ </workflows>
586
+ XML
587
+ end
588
+ end
589
+ end
590
+
591
+ it 'returns an Array of Hashes containing each workflow step' do
592
+ ah = client.stale_queued_workflows 'dor', hours_ago: 24, limit: 100
593
+ expected = [
594
+ { workflow: 'accessionWF', step: 'content-metadata', druid: 'dr:123', lane_id: 'lane1' },
595
+ { workflow: 'assemblyWF', step: 'jp2-create', druid: 'dr:456', lane_id: 'lane2' }
596
+ ]
597
+ expect(ah).to eql(expected)
598
+ end
599
+ end
600
+
601
+ describe '.count_stale_queued_workflows' do
602
+ let(:stubs) do
603
+ Faraday::Adapter::Test::Stubs.new do |stub|
604
+ stub.get('workflow_queue/all_queued?repository=dor&hours-ago=48&count-only=true') do |_env|
605
+ [200, {}, '<objects count="10"/>']
606
+ end
607
+ end
608
+ end
609
+
610
+ it 'returns the number of queued workflow steps' do
611
+ expect(client.count_stale_queued_workflows('dor', hours_ago: 48)).to eq(10)
612
+ end
613
+ end
614
+
615
+ describe '.lane_ids' do
616
+ let(:stubs) do
617
+ Faraday::Adapter::Test::Stubs.new do |stub|
618
+ stub.get('workflow_queue/lane_ids?lane_ids?step=dor:accessionWF:shelve') do |_env|
619
+ [200, {}, <<-XML]
620
+ <lanes>
621
+ <lane id="lane1"/>
622
+ <lane id="lane2"/>
623
+ </lanes>
624
+ XML
625
+ end
626
+ end
627
+ end
628
+
629
+ it 'returns the lane ids for a given workflow step' do
630
+ expect(client.lane_ids('dor', 'accessionWF', 'shelve')).to eq(%w[lane1 lane2])
631
+ end
632
+ end
633
+ end