orcid 0.0.4 → 0.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -0
  3. data/.hound.yml +793 -0
  4. data/.travis.yml +14 -0
  5. data/Gemfile +14 -0
  6. data/README.md +107 -6
  7. data/Rakefile +17 -9
  8. data/app/assets/images/orcid/.keep +0 -0
  9. data/app/controllers/orcid/application_controller.rb +13 -4
  10. data/app/controllers/orcid/profile_connections_controller.rb +34 -6
  11. data/app/controllers/orcid/profile_requests_controller.rb +18 -15
  12. data/app/models/orcid/profile.rb +15 -5
  13. data/app/models/orcid/profile_connection.rb +20 -20
  14. data/app/models/orcid/profile_request.rb +39 -20
  15. data/app/models/orcid/work.rb +45 -55
  16. data/app/models/orcid/work/xml_parser.rb +45 -0
  17. data/app/models/orcid/work/xml_renderer.rb +29 -0
  18. data/app/services/orcid/remote/profile_creation_service.rb +40 -32
  19. data/app/services/orcid/remote/profile_query_service.rb +82 -0
  20. data/app/services/orcid/remote/profile_query_service/query_parameter_builder.rb +43 -0
  21. data/app/services/orcid/remote/profile_query_service/search_response.rb +31 -0
  22. data/app/services/orcid/remote/service.rb +16 -13
  23. data/app/services/orcid/remote/work_service.rb +58 -43
  24. data/app/templates/orcid/work.template.v1.1.xml.erb +32 -1
  25. data/app/views/orcid/profile_connections/_orcid_connector.html.erb +14 -0
  26. data/app/views/orcid/profile_connections/new.html.erb +4 -4
  27. data/bin/rails +8 -0
  28. data/config/{application.yml → application.yml.example} +3 -13
  29. data/config/locales/orcid.en.yml +5 -1
  30. data/config/routes.rb +4 -2
  31. data/lib/generators/orcid/install/install_generator.rb +46 -7
  32. data/lib/orcid.rb +23 -11
  33. data/lib/orcid/configuration.rb +32 -13
  34. data/lib/orcid/configuration/provider.rb +27 -13
  35. data/lib/orcid/engine.rb +20 -4
  36. data/lib/orcid/exceptions.rb +33 -4
  37. data/lib/orcid/named_callbacks.rb +3 -1
  38. data/lib/orcid/spec_support.rb +19 -9
  39. data/lib/orcid/version.rb +1 -1
  40. data/lib/tasks/orcid_tasks.rake +3 -3
  41. data/orcid.gemspec +51 -0
  42. data/rubocop.txt +1164 -0
  43. data/script/fast_specs +22 -0
  44. data/spec/controllers/orcid/profile_connections_controller_spec.rb +101 -0
  45. data/spec/controllers/orcid/profile_requests_controller_spec.rb +116 -0
  46. data/spec/factories/orcid_profile_requests.rb +11 -0
  47. data/spec/factories/users.rb +9 -0
  48. data/spec/fast_helper.rb +12 -0
  49. data/spec/features/batch_profile_spec.rb +31 -0
  50. data/spec/features/non_ui_based_interactions_spec.rb +117 -0
  51. data/spec/features/profile_connection_feature_spec.rb +19 -0
  52. data/spec/features/public_api_query_spec.rb +36 -0
  53. data/spec/fixtures/orcid_works.xml +55 -0
  54. data/spec/lib/orcid/configuration/provider_spec.rb +40 -0
  55. data/spec/lib/orcid/configuration_spec.rb +38 -0
  56. data/spec/lib/orcid/named_callbacks_spec.rb +28 -0
  57. data/spec/lib/orcid_spec.rb +97 -0
  58. data/spec/models/orcid/profile_connection_spec.rb +81 -0
  59. data/spec/models/orcid/profile_request_spec.rb +131 -0
  60. data/spec/models/orcid/profile_spec.rb +76 -0
  61. data/spec/models/orcid/work/xml_parser_spec.rb +40 -0
  62. data/spec/models/orcid/work/xml_renderer_spec.rb +18 -0
  63. data/spec/models/orcid/work_spec.rb +53 -0
  64. data/spec/services/orcid/remote/profile_creation_service_spec.rb +40 -0
  65. data/spec/services/orcid/remote/profile_query_service/query_parameter_builder_spec.rb +44 -0
  66. data/spec/services/orcid/remote/profile_query_service/search_response_spec.rb +14 -0
  67. data/spec/services/orcid/remote/profile_query_service_spec.rb +118 -0
  68. data/spec/services/orcid/remote/service_spec.rb +26 -0
  69. data/spec/services/orcid/remote/work_service_spec.rb +44 -0
  70. data/spec/spec_helper.rb +99 -0
  71. data/spec/support/non_orcid_models.rb +11 -0
  72. data/spec/support/stub_callback.rb +25 -0
  73. data/spec/test_app_templates/Gemfile.extra +3 -0
  74. data/spec/test_app_templates/lib/generators/test_app_generator.rb +36 -0
  75. data/spec/views/orcid/profile_connections/new.html.erb_spec.rb +25 -0
  76. data/spec/views/orcid/profile_requests/new.html.erb_spec.rb +23 -0
  77. metadata +119 -29
  78. data/app/runners/orcid/profile_lookup_runner.rb +0 -33
  79. data/app/runners/orcid/runner.rb +0 -15
  80. data/app/services/orcid/remote/profile_lookup_service.rb +0 -56
  81. data/app/services/orcid/remote/profile_lookup_service/search_response.rb +0 -23
  82. data/lib/orcid/query_parameter_builder.rb +0 -38
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'public api query', requires_net_connect: true do
4
+ around(:each) do |example|
5
+ WebMock.allow_net_connect!
6
+ example.run
7
+ WebMock.disable_net_connect!
8
+ end
9
+
10
+ Given(:runner) {
11
+ Orcid::Remote::ProfileQueryService.new
12
+ }
13
+ context 'with simple query' do
14
+ Given(:parameters) { { email: 'jeremy.n.friesen@gmail.com' } }
15
+ When(:result) { runner.call(parameters) }
16
+ Then { expect(result.size).to eq(1) }
17
+ end
18
+
19
+ context 'with bad query' do
20
+ Given(:parameters) { { hobomancer: 'jeremy.n.friesen@gmail.com' } }
21
+ When(:result) { runner.call(parameters) }
22
+ Then { expect(result).to have_failed(OAuth2::Error) }
23
+ end
24
+
25
+ context 'with a text query' do
26
+ Given(:parameters) { { text: '"Jeremy Friesen"' } }
27
+ When(:result) { runner.call(parameters) }
28
+ Then { expect(result.size).to be > 0 }
29
+ end
30
+
31
+ context 'with a compound text query' do
32
+ Given(:parameters) { { email: "nobody@gmail.com", text: '"Jeremy+Friesen"' } }
33
+ When(:result) { runner.call(parameters) }
34
+ Then { expect(result.size).to eq 0 }
35
+ end
36
+ end
@@ -0,0 +1,55 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <orcid-message xmlns="http://www.orcid.org/ns/orcid">
3
+ <message-version>1.1</message-version>
4
+ <orcid-profile type="user">
5
+ <orcid-identifier>
6
+ <uri>http://sandbox.orcid.org/0000-0002-1117-8571</uri>
7
+ <path>0000-0002-1117-8571</path>
8
+ <host>sandbox.orcid.org</host>
9
+ </orcid-identifier>
10
+ <orcid-preferences>
11
+ <locale>en</locale>
12
+ </orcid-preferences>
13
+ <orcid-history>
14
+ <creation-method>API</creation-method>
15
+ <completion-date>2014-02-14T15:32:15.453Z</completion-date>
16
+ <submission-date>2014-02-14T15:31:12.816Z</submission-date>
17
+ <last-modified-date>2014-02-18T20:23:40.472Z</last-modified-date>
18
+ <claimed>true</claimed>
19
+ <source>
20
+ <source-orcid>
21
+ <uri>http://sandbox.orcid.org/0000-0002-6683-6607</uri>
22
+ <path>0000-0002-6683-6607</path>
23
+ <host>sandbox.orcid.org</host>
24
+ </source-orcid>
25
+ <source-name>Hydra ORCID Integrator</source-name>
26
+ </source>
27
+ </orcid-history>
28
+ <orcid-activities>
29
+ <orcid-works>
30
+ <orcid-work put-code="303475" visibility="public">
31
+ <work-title>
32
+ <title>Another Test Drive</title>
33
+ </work-title>
34
+ <work-type>test</work-type>
35
+ <work-source>
36
+ <uri>http://sandbox.orcid.org/0000-0002-6683-6607</uri>
37
+ <path>0000-0002-6683-6607</path>
38
+ <host>sandbox.orcid.org</host>
39
+ </work-source>
40
+ </orcid-work>
41
+ <orcid-work put-code="303474" visibility="public">
42
+ <work-title>
43
+ <title>Test Driven Orcid Integration</title>
44
+ </work-title>
45
+ <work-type>test</work-type>
46
+ <work-source>
47
+ <uri>http://sandbox.orcid.org/0000-0002-6683-6607</uri>
48
+ <path>0000-0002-6683-6607</path>
49
+ <host>sandbox.orcid.org</host>
50
+ </work-source>
51
+ </orcid-work>
52
+ </orcid-works>
53
+ </orcid-activities>
54
+ </orcid-profile>
55
+ </orcid-message>
@@ -0,0 +1,40 @@
1
+ require 'fast_helper'
2
+ require 'orcid/configuration/provider'
3
+
4
+ module Orcid
5
+ describe Configuration::Provider do
6
+
7
+ let(:storage) {
8
+ {
9
+ 'ORCID_APP_AUTHENTICATION_SCOPE' => '_APP_AUTHENTICATION_SCOPE',
10
+ 'ORCID_SITE_URL' => '_SITE_URL',
11
+ 'ORCID_TOKEN_URL' => '_TOKEN_URL',
12
+ 'ORCID_REMOTE_SIGNIN_URL' => '_REMOTE_SIGNIN_URL',
13
+ 'ORCID_AUTHORIZE_URL' => '_AUTHORIZE_URL',
14
+ 'ORCID_APP_ID' => '_APP_ID',
15
+ 'ORCID_APP_SECRET' => '_APP_SECRET',
16
+ }
17
+ }
18
+
19
+ subject { described_class.new(storage) }
20
+
21
+ its(:authentication_scope) { should eq storage.fetch('ORCID_APP_AUTHENTICATION_SCOPE') }
22
+ its(:site_url) { should eq storage.fetch('ORCID_SITE_URL') }
23
+ its(:token_url) { should eq storage.fetch('ORCID_TOKEN_URL') }
24
+ its(:signin_via_json_url) { should eq storage.fetch('ORCID_REMOTE_SIGNIN_URL') }
25
+ its(:authorize_url) { should eq storage.fetch('ORCID_AUTHORIZE_URL') }
26
+ its(:id) { should eq storage.fetch('ORCID_APP_ID') }
27
+ its(:secret) { should eq storage.fetch('ORCID_APP_SECRET') }
28
+
29
+ context 'with an empty ENV' do
30
+ Given(:provider) { described_class.new({}) }
31
+ Then { expect(provider.authentication_scope).to be_an_instance_of(String) }
32
+ And { expect(provider.site_url).to be_an_instance_of(String) }
33
+ And { expect(provider.token_url).to be_an_instance_of(String) }
34
+ And { expect(provider.signin_via_json_url).to be_an_instance_of(String) }
35
+ And { expect(provider.authorize_url).to be_an_instance_of(String) }
36
+ And { expect { provider.id }.to raise_error Orcid::ConfigurationError }
37
+ And { expect { provider.secret }.to raise_error Orcid::ConfigurationError }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ module Orcid
4
+ describe Configuration do
5
+
6
+ subject { described_class.new }
7
+
8
+ its(:parent_controller) { should be_an_instance_of String }
9
+ its(:provider) { should be_an_instance_of Configuration::Provider }
10
+ its(:authentication_model) { should eq Devise::MultiAuth::Authentication }
11
+
12
+ its(:mapper) { should respond_to :map }
13
+ its(:mapper) { should respond_to :configure }
14
+
15
+ context 'mapping to an Orcid::Work' do
16
+ let(:legend) {
17
+ [
18
+ [:title, :title],
19
+ [lambda{|*| 'spaghetti'}, :work_type]
20
+ ]
21
+ }
22
+ let(:title) { 'Hello World' }
23
+ let(:article) { NonOrcid::Article.new(title: title)}
24
+ before(:each) do
25
+ subject.register_mapping_to_orcid_work('non_orcid/article', legend)
26
+ end
27
+
28
+ it 'should configure the mapper' do
29
+ orcid_work = subject.mapper.map(article, target: 'orcid/work')
30
+ expect(orcid_work.work_type).to eq('spaghetti')
31
+ expect(orcid_work.title).to eq(title)
32
+ expect(orcid_work).to be_an_instance_of(Orcid::Work)
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ require 'fast_helper'
2
+ require './lib/orcid/named_callbacks'
3
+
4
+ module Orcid
5
+ describe NamedCallbacks do
6
+ Given(:named_callback) { NamedCallbacks.new }
7
+ Given(:context) { [ ] }
8
+ Given { named_callback.my_named_callback { |*a| context.replace(a) } }
9
+
10
+ describe "with a named callback" do
11
+ Given(:callback_name) { :my_named_callback }
12
+ When { named_callback.call(callback_name, 'a',:hello) }
13
+ Then { context == ['a', :hello] }
14
+ end
15
+
16
+ describe "with a named callback called by a string" do
17
+ Given(:callback_name) { 'my_named_callback' }
18
+ When { named_callback.call(callback_name, 'a',:hello) }
19
+ Then { context == ['a', :hello] }
20
+ end
21
+
22
+ describe "with a undeclared callback" do
23
+ When(:result) { named_callback.call(:undeclared_callback, 1, 2, 3) }
24
+ Then { result }
25
+ Then { context == [] }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe Orcid do
4
+ let(:user) { FactoryGirl.build_stubbed(:user) }
5
+ let(:orcid_profile_id) { '0001-0002-0003-0004' }
6
+ subject { described_class }
7
+ its(:provider) { should respond_to :id }
8
+ its(:provider) { should respond_to :secret }
9
+ its(:mapper) { should respond_to :map }
10
+ its(:use_relative_model_naming?) { should eq true }
11
+
12
+ context '.authentication_model' do
13
+ subject { Orcid.authentication_model }
14
+ it { should respond_to :to_access_token }
15
+ it { should respond_to :create! }
16
+ it { should respond_to :count }
17
+ it { should respond_to :where }
18
+ end
19
+
20
+ context '.oauth_client' do
21
+ subject { Orcid.oauth_client }
22
+ its(:client_credentials) { should respond_to :get_token }
23
+ end
24
+
25
+ context '.configure' do
26
+ it 'should yield a configuration' do
27
+ expect{|b| Orcid.configure(&b) }.to yield_with_args(Orcid::Configuration)
28
+ end
29
+ end
30
+
31
+ context '.profile_for' do
32
+ it 'should return nil if none is found' do
33
+ expect(Orcid.profile_for(user)).to eq(nil)
34
+ end
35
+
36
+ it 'should return an Orcid::Profile if the user has an orcid authentication' do
37
+ Orcid.connect_user_and_orcid_profile(user,orcid_profile_id)
38
+ expect(Orcid.profile_for(user).orcid_profile_id).to eq(orcid_profile_id)
39
+ end
40
+ end
41
+
42
+ context '.client_credentials_token' do
43
+ let(:tokenizer) { double('Tokenizer') }
44
+ let(:scope) { '/my-scope' }
45
+ let(:token) { double('Token') }
46
+
47
+ it 'should request the scoped token from the tokenizer' do
48
+ tokenizer.should_receive(:get_token).with(scope: scope).and_return(token)
49
+ expect(Orcid.client_credentials_token(scope, tokenizer: tokenizer)).to eq(token)
50
+ end
51
+ end
52
+
53
+ context '.connect_user_and_orcid_profile' do
54
+
55
+ it 'changes the authentication count' do
56
+ expect {
57
+ Orcid.connect_user_and_orcid_profile(user, orcid_profile_id)
58
+ }.to change(Orcid.authentication_model, :count).by(1)
59
+ end
60
+ end
61
+
62
+ context '.access_token_for' do
63
+ let(:client) { double("Client")}
64
+ let(:token) { double('Token') }
65
+ let(:tokenizer) { double("Tokenizer") }
66
+
67
+ it 'delegates to .authentication' do
68
+ tokenizer.should_receive(:to_access_token).with(provider: 'orcid', uid: orcid_profile_id, client: client).and_return(token)
69
+ expect(Orcid.access_token_for(orcid_profile_id, client: client, tokenizer: tokenizer)).to eq(token)
70
+ end
71
+ end
72
+
73
+ context '.enqueue' do
74
+ let(:object) { double }
75
+
76
+ it 'should #run the object' do
77
+ object.should_receive(:run)
78
+ Orcid.enqueue(object)
79
+ end
80
+ end
81
+
82
+ context '#authenticated_orcid' do
83
+ it 'should not be authenticated' do
84
+ Orcid.authenticated_orcid?(orcid_profile_id).should eq false
85
+ end
86
+ end
87
+
88
+ =begin
89
+ context '#authenticated_orcid' do
90
+ it 'should be authenticated' do
91
+ Orcid.should_receive(:authenticated_orcid).with(orcid_profile_id).and_return(true)
92
+ Orcid.authenticated_orcid?(orcid_profile_id).should eq true
93
+ end
94
+ end
95
+ =end
96
+
97
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ module Orcid
4
+ describe ProfileConnection do
5
+ let(:email) { 'test@hello.com'}
6
+ let(:user) { FactoryGirl.build_stubbed(:user) }
7
+ let(:profile_query_service) { double("Profile Lookup Service") }
8
+
9
+ subject {
10
+ Orcid::ProfileConnection.new(email: email, user: user).tap { |pc|
11
+ pc.profile_query_service = profile_query_service
12
+ }
13
+ }
14
+
15
+ its(:email) { should eq email }
16
+ its(:user) { should eq user }
17
+ its(:persisted?) { should eq false }
18
+ its(:orcid_profile_id) { should be_nil }
19
+
20
+ context '.available_query_attribute_names' do
21
+ subject { Orcid::ProfileConnection.new.available_query_attribute_names }
22
+ it { should include(:email) }
23
+ it { should include(:text) }
24
+ end
25
+
26
+ context '#query_attributes' do
27
+ subject { Orcid::ProfileConnection.new(email: email, user: user)}
28
+ its(:query_attributes) { should eq(email: email, text: nil) }
29
+ end
30
+
31
+ context '#query_requested?' do
32
+ context 'with no attributes' do
33
+ subject { Orcid::ProfileConnection.new }
34
+ its(:query_requested?) { should eq false }
35
+ end
36
+ context 'with attribute set' do
37
+ subject { Orcid::ProfileConnection.new(email: email, user: user)}
38
+ its(:query_requested?) { should eq true }
39
+ end
40
+ end
41
+
42
+ context '#save' do
43
+ let(:orcid_profile_id) { '1234-5678' }
44
+ let(:persister) { double("Persister") }
45
+
46
+ it 'should call the persister when valid' do
47
+ subject.orcid_profile_id = orcid_profile_id
48
+ persister.should_receive(:call).with(user, orcid_profile_id).and_return(:persisted)
49
+ expect(subject.save(persister: persister)).to eq(:persisted)
50
+ end
51
+
52
+ it 'should NOT call the persister and add errors when not valid' do
53
+ subject.user = nil
54
+ subject.orcid_profile_id = nil
55
+ expect {
56
+ subject.save(persister: persister)
57
+ }.to change { subject.errors.count }.by(2)
58
+ end
59
+ end
60
+
61
+ context '#with_orcid_profile_candidates' do
62
+ context 'with an email' do
63
+
64
+ it 'should yield the query response' do
65
+ subject.email = email
66
+ profile_query_service.should_receive(:call).with(subject.query_attributes).and_return(:query_response)
67
+ expect {|b| subject.with_orcid_profile_candidates(&b) }.to yield_with_args(:query_response)
68
+ end
69
+ end
70
+
71
+ context 'without an email' do
72
+ it 'should not yield' do
73
+ subject.email = nil
74
+ profile_query_service.stub(:call).and_return(:query_response)
75
+ expect {|b| subject.with_orcid_profile_candidates(&b) }.to_not yield_control
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ module Orcid
4
+ describe ProfileRequest do
5
+ let(:orcid_profile_id) { '0000-0001-8025-637X'}
6
+ let(:user) { mock_model('User') }
7
+ let(:attributes) {
8
+ {
9
+ user: user,
10
+ given_names: 'Daffy',
11
+ family_name: 'Duck',
12
+ primary_email: 'daffy@duck.com'
13
+ }
14
+ }
15
+ subject { described_class.new(attributes) }
16
+
17
+ context '#find_by_user' do
18
+ let!(:profile_request) { FactoryGirl.create(:orcid_profile_request) }
19
+ it 'returns the profile request' do
20
+ expect(described_class.find_by_user(profile_request.user)).to eq(profile_request)
21
+ end
22
+
23
+ it 'to return nil' do
24
+ other_user = FactoryGirl.build_stubbed(:user)
25
+ expect(described_class.find_by_user(other_user)).to be_nil
26
+ end
27
+
28
+ end
29
+
30
+ context '#handle_profile_creation_response' do
31
+ it 'should update local' do
32
+ # Don't want to hit the database
33
+ subject.should_receive(:update_column).with(:orcid_profile_id, orcid_profile_id)
34
+ Orcid.should_receive(:connect_user_and_orcid_profile).with(user, orcid_profile_id)
35
+
36
+ subject.handle_profile_creation_response(orcid_profile_id)
37
+ end
38
+ end
39
+
40
+ context '#xml_payload' do
41
+ it 'should be a parsable XML document' do
42
+ expect {
43
+ ActiveSupport::XmlMini.parse(subject.xml_payload)
44
+ }.to_not raise_error
45
+ end
46
+ end
47
+
48
+ context '#validate_before_run' do
49
+ let(:orcid_profile) { double('Orcid Profile', to_param: orcid_profile_id) }
50
+
51
+ context 'when no orcid profile has been assigned' do
52
+ before { Orcid.should_receive(:profile_for).with(user).and_return(nil) }
53
+ it 'should return true' do
54
+ expect(subject.validate_before_run).to eq(true)
55
+ end
56
+ end
57
+
58
+ context 'orcid_profile_id is set' do
59
+ before { subject.orcid_profile_id = orcid_profile_id }
60
+
61
+ it 'should return false' do
62
+ expect(subject.validate_before_run).to eq(false)
63
+ end
64
+
65
+ it 'should set an error' do
66
+ expect {
67
+ subject.validate_before_run
68
+ }.to change { subject.errors.full_messages.count }.by(1)
69
+ end
70
+
71
+ end
72
+
73
+ context 'user has an orcid_profile' do
74
+ before { Orcid.should_receive(:profile_for).with(user).and_return(orcid_profile) }
75
+
76
+ it 'should return false' do
77
+ expect(subject.validate_before_run).to eq(false)
78
+ end
79
+
80
+ it 'should set an error' do
81
+ expect {
82
+ subject.validate_before_run
83
+ }.to change { subject.errors.full_messages.count }.by(1)
84
+ end
85
+
86
+ end
87
+ end
88
+
89
+ context '#run' do
90
+ let(:profile_creation_service) { double('Profile Creation Service') }
91
+ let(:payload_xml_builder) { double('Payload Xml Builder') }
92
+ let(:validator) { double('Submission Guardian') }
93
+ let(:xml_payload) { double('Xml Payload') }
94
+
95
+ context 'with the submission guardian permitting the request' do
96
+ before(:each) do
97
+ validator.should_receive(:call).with(subject).
98
+ and_return(true)
99
+ payload_xml_builder.should_receive(:call).with(subject.attributes).
100
+ and_return(xml_payload)
101
+ profile_creation_service.should_receive(:call).with(xml_payload).
102
+ and_return(orcid_profile_id)
103
+ end
104
+
105
+ it 'should run a request and handle the response' do
106
+ subject.run(
107
+ payload_xml_builder: payload_xml_builder,
108
+ profile_creation_service: profile_creation_service,
109
+ validator: validator
110
+ )
111
+ end
112
+ end
113
+
114
+ context 'with the submission guardian returning false' do
115
+ before(:each) do
116
+ validator.should_receive(:call).with(subject).
117
+ and_return(false)
118
+ payload_xml_builder.should_not_receive(:call)
119
+ end
120
+
121
+ it 'should raise an exception' do
122
+ subject.run(
123
+ payload_xml_builder: payload_xml_builder,
124
+ profile_creation_service: profile_creation_service,
125
+ validator: validator
126
+ )
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end