orcid 0.0.4 → 0.1.0

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