dor-workflow-client 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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