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,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Dor::Workflow::Response::Workflow do
6
+ subject(:instance) { described_class.new(xml: xml) }
7
+
8
+ describe '#pid' do
9
+ subject { instance.pid }
10
+
11
+ let(:xml) do
12
+ <<~XML
13
+ <workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
14
+ </workflow>
15
+ XML
16
+ end
17
+ it { is_expected.to eq 'druid:mw971zk1113' }
18
+ end
19
+
20
+ describe '#workflow_name' do
21
+ subject { instance.workflow_name }
22
+
23
+ let(:xml) do
24
+ <<~XML
25
+ <workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
26
+ </workflow>
27
+ XML
28
+ end
29
+ it { is_expected.to eq 'assemblyWF' }
30
+ end
31
+
32
+ describe '#active?' do
33
+ subject { instance.active_for?(version: 2) }
34
+
35
+ context 'when the workflow has not been instantiated for the given version' do
36
+ let(:xml) do
37
+ <<~XML
38
+ <workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
39
+ <process version="1" laneId="default" elapsed="0.0" attempts="1" datetime="2013-02-18T14:40:25-0800" status="completed" name="start-assembly"/>
40
+ <process version="1" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="completed" name="jp2-create"/>
41
+ </workflow>
42
+ XML
43
+ end
44
+ it { is_expected.to be false }
45
+ end
46
+
47
+ context 'when the workflow has been instantiated for the given version' do
48
+ let(:xml) do
49
+ <<~XML
50
+ <workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
51
+ <process version="1" laneId="default" elapsed="0.0" attempts="1" datetime="2013-02-18T14:40:25-0800" status="completed" name="start-assembly"/>
52
+ <process version="1" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="completed" name="jp2-create"/>
53
+ <process version="2" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="waiting" name="jp2-create"/>
54
+ </workflow>
55
+ XML
56
+ end
57
+ it { is_expected.to be true }
58
+ end
59
+ end
60
+
61
+ describe '#empty?' do
62
+ subject { instance.empty? }
63
+
64
+ context 'when there is xml' do
65
+ let(:xml) do
66
+ '<?xml version="1.0" encoding="UTF-8"?>
67
+ <workflow repository="dor" objectId="druid:oo201oo0001" id="accessionWF">
68
+ <process version="2" lifecycle="submitted" elapsed="0.0" archived="true" attempts="1"
69
+ datetime="2012-11-06T16:18:24-0800" status="completed" name="start-accession"/>
70
+ <process version="2" elapsed="0.0" archived="true" attempts="1"
71
+ datetime="2012-11-06T16:18:58-0800" status="completed" name="technical-metadata"/>
72
+ <process version="2" elapsed="0.0" archived="true" attempts="1"
73
+ datetime="2012-11-06T16:19:02-0800" status="completed" name="provenance-metadata"/>
74
+ <process version="2" elapsed="0.0" archived="true" attempts="1"
75
+ datetime="2012-11-06T16:19:05-0800" status="completed" name="remediate-object"/>
76
+ <process version="2" elapsed="0.0" archived="true" attempts="1"
77
+ datetime="2012-11-06T16:19:06-0800" status="completed" name="shelve"/>
78
+ <process version="2" lifecycle="published" elapsed="0.0" archived="true" attempts="1"
79
+ datetime="2012-11-06T16:19:07-0800" status="completed" name="publish"/>
80
+ <process version="2" elapsed="0.0" archived="true" attempts="1"
81
+ datetime="2012-11-06T16:19:09-0800" status="completed" name="sdr-ingest-transfer"/>
82
+ <process version="2" lifecycle="accessioned" elapsed="0.0" archived="true" attempts="1"
83
+ datetime="2012-11-06T16:19:10-0800" status="completed" name="cleanup"/>
84
+ <process version="2" elapsed="0.0" archived="true" attempts="1"
85
+ datetime="2012-11-06T16:19:13-0800" status="completed" name="rights-metadata"/>
86
+ <process version="2" lifecycle="described" elapsed="0.0" archived="true" attempts="1"
87
+ datetime="2012-11-06T16:19:15-0800" status="completed" name="descriptive-metadata"/>
88
+ <process version="2" elapsed="0.0" archived="true" attempts="2"
89
+ datetime="2012-11-06T16:19:16-0800" status="completed" name="content-metadata"/>
90
+ </workflow>'
91
+ end
92
+
93
+ it { is_expected.to be false }
94
+ end
95
+
96
+ context 'when the xml is empty' do
97
+ let(:xml) { '' }
98
+
99
+ it { is_expected.to be true }
100
+ end
101
+ end
102
+
103
+ describe '#process_for_recent_version' do
104
+ subject(:process) { instance.process_for_recent_version(name: 'jp2-create') }
105
+
106
+ context 'when the workflow has not been instantiated for the given version' do
107
+ let(:xml) do
108
+ <<~XML
109
+ <workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
110
+ <process version="1" laneId="default" elapsed="0.0" attempts="1" datetime="2013-02-18T14:40:25-0800" status="completed" name="start-assembly"/>
111
+ <process version="1" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="completed" name="jp2-create"/>
112
+ </workflow>
113
+ XML
114
+ end
115
+
116
+ it 'returns a process' do
117
+ expect(process).to be_kind_of Dor::Workflow::Response::Process
118
+ expect(process.status).to eq 'completed'
119
+ expect(process.name).to eq 'jp2-create'
120
+ end
121
+ end
122
+
123
+ context 'when the workflow has been instantiated for the given version' do
124
+ let(:xml) do
125
+ <<~XML
126
+ <workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
127
+ <process version="1" laneId="default" elapsed="0.0" attempts="1" datetime="2013-02-18T14:40:25-0800" status="completed" name="start-assembly"/>
128
+ <process version="1" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="completed" name="jp2-create"/>
129
+ <process version="2" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="error" name="jp2-create" errorMessage="it just broke"/>
130
+ </workflow>
131
+ XML
132
+ end
133
+
134
+ it 'returns a process' do
135
+ expect(process).to be_kind_of Dor::Workflow::Response::Process
136
+ expect(process.status).to eq 'error'
137
+ expect(process.error_message).to eq 'it just broke'
138
+ expect(process.name).to eq 'jp2-create'
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'simplecov'
7
+ SimpleCov.start do
8
+ add_filter 'spec'
9
+ end
10
+
11
+ require 'byebug'
12
+ require 'dor/workflow/client'
13
+ require 'equivalent-xml'
14
+ require 'equivalent-xml/rspec_matchers'
15
+ require 'webmock/rspec'
16
+
17
+ # RSpec.configure do |conf|
18
+ # end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ # This test can take up to 15s to run because it does retries with exponential backoff
6
+ RSpec.describe Dor::Workflow::Client::ConnectionFactory do
7
+ let(:mock_logger) { double('Logger', info: true, debug: true, warn: true) }
8
+
9
+ let(:repo) { 'dor' }
10
+ let(:druid) { 'druid:123' }
11
+ before do
12
+ stub_request(:put, "http://example.com/#{repo}/objects/#{druid}/workflows/httpException?create-ds=true")
13
+ .to_return(status: 500, body: 'Internal error', headers: {})
14
+ end
15
+
16
+ let(:client) { Dor::Workflow::Client.new url: 'http://example.com', logger: mock_logger }
17
+
18
+ describe '#create_workflow' do
19
+ it 'logs an error and retry upon a targeted Faraday exception' do
20
+ expect(mock_logger).to receive(:warn).with('retrying connection (1 remaining) to http://example.com/dor/objects/druid:123/workflows/httpException?create-ds=true: (Faraday::RetriableResponse) 500')
21
+ expect(mock_logger).to receive(:warn).with('retrying connection (0 remaining) to http://example.com/dor/objects/druid:123/workflows/httpException?create-ds=true: (Faraday::RetriableResponse) 500')
22
+ expect { client.create_workflow(repo, druid, 'httpException', '<xml>') }.to raise_error Dor::WorkflowException
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Dor::Workflow::Client::LifecycleRoutes do
6
+ let(:mock_requestor) { instance_double(Dor::Workflow::Client::Requestor) }
7
+
8
+ let(:routes) { described_class.new(requestor: mock_requestor) }
9
+
10
+ describe '#milestones' do
11
+ let(:ng_xml) { Nokogiri::XML(xml) }
12
+ let(:xml) do
13
+ '<?xml version="1.0" encoding="UTF-8"?><lifecycle objectId="druid:gv054hp4128"><milestone date="2012-01-26T21:06:54-0800" version="2">published</milestone></lifecycle>'
14
+ end
15
+
16
+ before do
17
+ allow(routes).to receive(:query_lifecycle).and_return(ng_xml)
18
+ end
19
+
20
+ subject(:milestones) { routes.milestones('dor', 'druid:gv054hp4128') }
21
+
22
+ it 'includes the version in with the milestones' do
23
+ expect(milestones.first[:milestone]).to eq('published')
24
+ expect(milestones.first[:version]).to eq('2')
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Dor::Workflow::Client::Requestor do
6
+ let(:mock_http_connection) do
7
+ Faraday.new(url: 'http://example.com/') do |builder|
8
+ builder.use Faraday::Response::RaiseError
9
+ builder.options.params_encoder = Faraday::FlatParamsEncoder
10
+
11
+ builder.adapter :test, stubs
12
+ end
13
+ end
14
+
15
+ let(:requestor) { described_class.new(connection: mock_http_connection) }
16
+
17
+ describe '.send_workflow_resource_request' do
18
+ let(:stubs) do
19
+ Faraday::Adapter::Test::Stubs.new do |stub|
20
+ stub.get('x?complete=a&complete=b') do |_env|
21
+ [200, {}, 'ab']
22
+ end
23
+ end
24
+ end
25
+
26
+ it 'uses the flat params encoder' do
27
+ response = requestor.send(:send_workflow_resource_request, 'x?complete=a&complete=b')
28
+
29
+ expect(response.body).to eq 'ab'
30
+ expect(response.env.url.query).to eq 'complete=a&complete=b'
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Dor::Workflow::Client::WorkflowRoutes do
6
+ let(:mock_requestor) { instance_double(Dor::Workflow::Client::Requestor) }
7
+
8
+ let(:routes) { described_class.new(requestor: mock_requestor) }
9
+
10
+ let(:wf_xml) do
11
+ <<-EOXML
12
+ <workflow id="etdSubmitWF">
13
+ <process name="register-object" status="completed" attempts="1" />
14
+ <process name="submit" status="waiting" />
15
+ <process name="reader-approval" status="waiting" />
16
+ <process name="registrar-approval" status="waiting" />
17
+ <process name="start-accession" status="waiting" />
18
+ </workflow>
19
+ EOXML
20
+ end
21
+
22
+ describe '#add_lane_id_to_workflow_xml' do
23
+ it 'adds laneId attributes to all process elements' do
24
+ expected = <<-XML
25
+ <workflow id="etdSubmitWF">
26
+ <process name="register-object" status="completed" attempts="1" laneId="lane1"/>
27
+ <process name="submit" status="waiting" laneId="lane1"/>
28
+ <process name="reader-approval" status="waiting" laneId="lane1"/>
29
+ <process name="registrar-approval" status="waiting" laneId="lane1"/>
30
+ <process name="start-accession" status="waiting" laneId="lane1"/>
31
+ </workflow>
32
+ XML
33
+ expect(routes.send(:add_lane_id_to_workflow_xml, 'lane1', wf_xml)).to be_equivalent_to(expected)
34
+ end
35
+ end
36
+
37
+ describe '#workflow' do
38
+ let(:xml) do
39
+ <<~XML
40
+ <workflow repository="dor" objectId="druid:mw971zk1113" id="accessionWF">
41
+ <process laneId="default" lifecycle="submitted" elapsed="0.0" attempts="1" datetime="2013-02-18T15:08:10-0800" status="completed" name="start-accession"/>
42
+ </workflow>
43
+ XML
44
+ end
45
+ before do
46
+ allow(routes).to receive(:workflow_xml) { xml }
47
+ end
48
+
49
+ it 'it returns a workflow' do
50
+ expect(routes.workflow(pid: 'druid:mw971zk1113', workflow_name: 'accessionWF')).to be_kind_of Dor::Workflow::Response::Workflow
51
+ end
52
+ end
53
+ end