global-registry-bindings 0.0.6 → 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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +79 -35
  3. data/lib/global_registry_bindings/entity/entity_type_methods.rb +35 -33
  4. data/lib/global_registry_bindings/entity/mdm_methods.rb +9 -19
  5. data/lib/global_registry_bindings/entity/push_entity_methods.rb +31 -38
  6. data/lib/global_registry_bindings/entity/push_relationship_methods.rb +61 -47
  7. data/lib/global_registry_bindings/entity/relationship_type_methods.rb +48 -37
  8. data/lib/global_registry_bindings/exceptions.rb +1 -0
  9. data/lib/global_registry_bindings/global_registry_bindings.rb +129 -46
  10. data/lib/global_registry_bindings/{entity/delete_entity_methods.rb → model/delete_entity.rb} +5 -5
  11. data/lib/global_registry_bindings/model/entity.rb +64 -0
  12. data/lib/global_registry_bindings/model/pull_mdm.rb +23 -0
  13. data/lib/global_registry_bindings/model/push_entity.rb +21 -0
  14. data/lib/global_registry_bindings/model/push_relationship.rb +79 -0
  15. data/lib/global_registry_bindings/model/relationship.rb +68 -0
  16. data/lib/global_registry_bindings/options.rb +26 -59
  17. data/lib/global_registry_bindings/options/entity_class_options.rb +34 -0
  18. data/lib/global_registry_bindings/options/entity_instance_options.rb +90 -0
  19. data/lib/global_registry_bindings/options/entity_options_parser.rb +76 -0
  20. data/lib/global_registry_bindings/options/relationship_class_options.rb +37 -0
  21. data/lib/global_registry_bindings/options/relationship_instance_options.rb +131 -0
  22. data/lib/global_registry_bindings/options/relationship_options_parser.rb +98 -0
  23. data/lib/global_registry_bindings/railtie.rb +2 -1
  24. data/lib/global_registry_bindings/version.rb +1 -1
  25. data/lib/global_registry_bindings/worker.rb +25 -0
  26. data/lib/global_registry_bindings/workers/{delete_gr_entity_worker.rb → delete_entity_worker.rb} +1 -6
  27. data/lib/global_registry_bindings/workers/pull_mdm_id_worker.rb +12 -13
  28. data/lib/global_registry_bindings/workers/push_entity_worker.rb +24 -0
  29. data/lib/global_registry_bindings/workers/push_relationship_worker.rb +17 -7
  30. data/spec/acceptance/global_registry_bindings_spec.rb +50 -40
  31. data/spec/factories/factories.rb +24 -0
  32. data/spec/fixtures/get_entity_types_area.json +44 -0
  33. data/spec/fixtures/post_entities_community.json +8 -0
  34. data/spec/fixtures/post_relationship_types_fancy_org_area.json +16 -0
  35. data/spec/fixtures/put_entities_community_relationship.json +16 -0
  36. data/spec/fixtures/put_entities_fancy_org_area_relationship.json +8 -0
  37. data/spec/fixtures/put_entities_fancy_org_relationship.json +17 -0
  38. data/spec/fixtures/put_entities_person_country_relationship.json +23 -0
  39. data/spec/fixtures/put_entities_relationship_400.json +3 -0
  40. data/spec/fixtures/put_relationship_types_fields_fancy_org_area.json +25 -0
  41. data/spec/helpers/sidekiq_helpers.rb +14 -0
  42. data/spec/internal/app/models/address.rb +7 -2
  43. data/spec/internal/app/models/area.rb +7 -0
  44. data/spec/internal/app/models/assignment.rb +5 -4
  45. data/spec/internal/app/models/community.rb +19 -0
  46. data/spec/internal/app/models/country.rb +8 -0
  47. data/spec/internal/app/models/namespaced/person.rb +48 -2
  48. data/spec/internal/app/models/organization.rb +26 -3
  49. data/spec/internal/db/schema.rb +28 -0
  50. data/spec/internal/log/test.log +71023 -0
  51. data/spec/models/address_spec.rb +6 -204
  52. data/spec/models/assignment_spec.rb +40 -186
  53. data/spec/models/organization_spec.rb +106 -92
  54. data/spec/models/person_spec.rb +158 -214
  55. data/spec/models/user_edited_person_spec.rb +2 -2
  56. data/spec/spec_helper.rb +5 -6
  57. data/spec/workers/delete_gr_entity_worker_spec.rb +4 -4
  58. data/spec/workers/pull_mdm_id_worker_spec.rb +94 -32
  59. data/spec/workers/push_entity_worker_spec.rb +476 -0
  60. data/spec/workers/push_relationship_worker_spec.rb +344 -15
  61. metadata +45 -10
  62. data/lib/global_registry_bindings/entity/entity_methods.rb +0 -62
  63. data/lib/global_registry_bindings/options/class_options.rb +0 -62
  64. data/lib/global_registry_bindings/options/instance_options.rb +0 -63
  65. data/lib/global_registry_bindings/workers/push_gr_entity_worker.rb +0 -22
  66. data/spec/workers/push_gr_entity_worker_spec.rb +0 -27
@@ -2,8 +2,8 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe 'Namespaced::Person::UserEdited' do
6
- describe ':pull_mdm_id_from_global_registry_async' do
5
+ RSpec.describe Namespaced::Person::UserEdited do
6
+ describe '#pull_mdm_id_from_global_registry_async' do
7
7
  it 'should enqueue sidekiq job' do
8
8
  user_edited = build(:user_edited)
9
9
  expect do
data/spec/spec_helper.rb CHANGED
@@ -26,6 +26,8 @@ MOCK_REDIS = MockRedis.new
26
26
 
27
27
  ActionController::Base.cache_store = :memory_store
28
28
 
29
+ require 'helpers/sidekiq_helpers'
30
+
29
31
  RSpec.configure do |config|
30
32
  config.use_transactional_fixtures = true
31
33
  config.file_fixture_path = 'spec/fixtures'
@@ -33,23 +35,20 @@ RSpec.configure do |config|
33
35
  config.run_all_when_everything_filtered = true
34
36
  config.include ActiveSupport::Testing::TimeHelpers
35
37
  config.include FactoryGirl::Syntax::Methods
38
+ config.include SidekiqHelpers
36
39
 
37
40
  config.before(:suite) do
38
41
  FactoryGirl.find_definitions
39
42
  end
40
43
 
41
44
  config.before(:each) do
42
- MOCK_REDIS.keys.each do |key|
43
- MOCK_REDIS.del(key)
44
- end
45
-
46
45
  SidekiqUniqueJobs.configure do |c|
47
46
  c.redis_test_mode = :mock
48
47
  end
49
48
  allow(Sidekiq).to receive(:redis).and_yield(MOCK_REDIS)
50
49
 
51
- Sidekiq::Queues.clear_all
52
- Sidekiq::Worker.clear_all
50
+ clear_sidekiq_jobs_and_locks
51
+
53
52
  Rails.cache.clear
54
53
  end
55
54
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe 'GlobalRegistry::Bindings::Workers' do
6
- describe 'DeleteGrEntityWorker' do
5
+ RSpec.describe GlobalRegistry::Bindings::Workers::DeleteEntityWorker do
6
+ context 'entity 22527d88-3cba-11e7-b876-129bd0521531' do
7
7
  context 'valid global_registry_id' do
8
8
  let!(:request) do
9
9
  stub_request(:delete, 'https://backend.global-registry.org/entities/22527d88-3cba-11e7-b876-129bd0521531')
@@ -11,7 +11,7 @@ RSpec.describe 'GlobalRegistry::Bindings::Workers' do
11
11
  end
12
12
 
13
13
  it 'should delete the entity' do
14
- worker = GlobalRegistry::Bindings::Workers::DeleteGrEntityWorker.new
14
+ worker = GlobalRegistry::Bindings::Workers::DeleteEntityWorker.new
15
15
  worker.perform('22527d88-3cba-11e7-b876-129bd0521531')
16
16
  expect(request).to have_been_requested.once
17
17
  end
@@ -24,7 +24,7 @@ RSpec.describe 'GlobalRegistry::Bindings::Workers' do
24
24
  end
25
25
 
26
26
  it 'should delete the entity' do
27
- worker = GlobalRegistry::Bindings::Workers::DeleteGrEntityWorker.new
27
+ worker = GlobalRegistry::Bindings::Workers::DeleteEntityWorker.new
28
28
  worker.perform('22527d88-3cba-11e7-b876-129bd0521531')
29
29
  expect(request).to have_been_requested.once
30
30
  end
@@ -2,48 +2,110 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe 'GlobalRegistry::Bindings::Workers' do
6
- describe 'PullMdmIdWorker' do
7
- let(:user) { create(:person) }
8
-
9
- it 'sends :pull_mdm_id_from_global_registry to the model instance' do
10
- allow(Namespaced::Person).to receive(:pull_mdm_id_from_global_registry)
11
- expect(Namespaced::Person).to receive(:find).with(user.id).and_return(user)
12
- expect(user).to receive(:pull_mdm_id_from_global_registry)
13
-
14
- worker_name = "GlobalRegistry::Bindings::Workers::#{Namespaced::Person.global_registry.mdm_worker_class_name}"
15
- worker = worker_name.constantize.new
16
- worker.perform(Namespaced::Person, user.id)
5
+ RSpec.describe GlobalRegistry::Bindings::Workers::PullMdmIdWorker do
6
+ context Namespaced::Person do
7
+ let(:person) { create(:person) }
8
+
9
+ context 'with valid id' do
10
+ it 'should call #pull_mdm_id_from_global_registry' do
11
+ expect(Namespaced::Person).to receive(:find).with(person.id).and_return(person)
12
+
13
+ worker_name =
14
+ "GlobalRegistry::Bindings::Workers::#{Namespaced::Person.global_registry_entity.mdm_worker_class_name}"
15
+ worker = worker_name.constantize.new
16
+ expect(worker).to receive(:pull_mdm_id_from_global_registry)
17
+ worker.perform('Namespaced::Person', person.id)
18
+ expect(worker.model).to be person
19
+ end
20
+ end
21
+
22
+ context ActiveRecord::RecordNotFound do
23
+ it 'should fail silently' do
24
+ expect(Namespaced::Person).to receive(:find).with(person.id).and_raise(ActiveRecord::RecordNotFound)
25
+ expect(GlobalRegistry::Bindings::Workers::PullMdmIdWorker).not_to receive(:pull_mdm_id_from_global_registry)
26
+
27
+ worker_name =
28
+ "GlobalRegistry::Bindings::Workers::#{Namespaced::Person.global_registry_entity.mdm_worker_class_name}"
29
+ worker = worker_name.constantize.new
30
+ worker.perform(Namespaced::Person, person.id)
31
+ expect(worker.model).to be nil
32
+ end
17
33
  end
18
34
 
19
- it 'fails silently on ActiveRecord::RecordNotFound' do
20
- allow(Namespaced::Person).to receive(:pull_mdm_id_from_global_registry)
21
- expect(Namespaced::Person).to receive(:find).with(user.id).and_raise(ActiveRecord::RecordNotFound)
22
- expect(user).not_to receive(:pull_mdm_id_from_global_registry)
35
+ context RestClient::ResourceNotFound do
36
+ it 'should log a message' do
37
+ expect(Namespaced::Person).to receive(:find).with(person.id).and_raise(RestClient::ResourceNotFound)
38
+ expect(GlobalRegistry::Bindings::Workers::PullMdmIdWorker).not_to receive(:pull_mdm_id_from_global_registry)
39
+ expect(Rails.logger).to receive(:info).with('GR entity for GlobalRegistry::Bindings::Workers::PullNamespaced' \
40
+ 'PersonMdmIdWorker 1 does not exist; will _not_ retry')
23
41
 
24
- worker_name = "GlobalRegistry::Bindings::Workers::#{Namespaced::Person.global_registry.mdm_worker_class_name}"
25
- worker = worker_name.constantize.new
26
- worker.perform(Namespaced::Person, user.id)
42
+ worker_name =
43
+ "GlobalRegistry::Bindings::Workers::#{Namespaced::Person.global_registry_entity.mdm_worker_class_name}"
44
+ worker = worker_name.constantize.new
45
+ worker.perform(Namespaced::Person, person.id)
46
+ expect(worker.model).to be nil
47
+ end
27
48
  end
49
+ end
28
50
 
29
- it 'logs a message on RestClient::ResourceNotFound' do
30
- allow(Namespaced::Person).to receive(:pull_mdm_id_from_global_registry)
31
- expect(Namespaced::Person).to receive(:find).with(user.id).and_raise(RestClient::ResourceNotFound)
32
- expect(user).not_to receive(:pull_mdm_id_from_global_registry)
33
- expect(Rails.logger).to receive(:info).with('GR entity for GlobalRegistry::Bindings::Workers::PullNamespaced' \
34
- 'PersonMdmIdWorker 1 does not exist; will _not_ retry')
51
+ describe '#pull_mdm_id_from_global_registry' do
52
+ context Namespaced::Person do
53
+ let(:worker) { GlobalRegistry::Bindings::Workers::PullNamespacedPersonMdmIdWorker.new }
54
+ before do
55
+ worker.model = person
56
+ end
57
+
58
+ context 'model missing global_registry_id' do
59
+ let(:person) { create(:person) }
35
60
 
36
- worker_name = "GlobalRegistry::Bindings::Workers::#{Namespaced::Person.global_registry.mdm_worker_class_name}"
37
- worker = worker_name.constantize.new
38
- worker.perform('Namespaced::Person', user.id)
61
+ it 'should raise an exception' do
62
+ expect do
63
+ worker.pull_mdm_id_from_global_registry
64
+ end.to raise_error GlobalRegistry::Bindings::RecordMissingGlobalRegistryId,
65
+ "Namespaced::Person(#{person.id}) has no global_registry_id; will retry"
66
+ end
67
+ end
68
+
69
+ context 'entity missing mdm id' do
70
+ let(:person) { create(:person, global_registry_id: '22527d88-3cba-11e7-b876-129bd0521531') }
71
+ let!(:request) do
72
+ stub_request(:get, 'https://backend.global-registry.org/entities/22527d88-3cba-11e7-b876-129bd0521531')
73
+ .with(query: { 'filters[owned_by]' => 'mdm' })
74
+ .to_return(body: file_fixture('get_entities_person.json'), status: 200)
75
+ end
76
+
77
+ it 'should raise an exception' do
78
+ expect do
79
+ worker.pull_mdm_id_from_global_registry
80
+ end.to raise_error GlobalRegistry::Bindings::EntityMissingMdmId,
81
+ "GR entity #{person.global_registry_id} for Namespaced::Person(#{person.id}) has " \
82
+ 'no mdm id; will retry'
83
+ end
84
+ end
85
+
86
+ context 'entity missing mdm id' do
87
+ let(:person) { create(:person, global_registry_id: '22527d88-3cba-11e7-b876-129bd0521531') }
88
+ let!(:request) do
89
+ stub_request(:get, 'https://backend.global-registry.org/entities/22527d88-3cba-11e7-b876-129bd0521531')
90
+ .with(query: { 'filters[owned_by]' => 'mdm' })
91
+ .to_return(body: file_fixture('get_entities_person_mdm.json'), status: 200)
92
+ end
93
+
94
+ it 'should raise an exception' do
95
+ expect do
96
+ worker.pull_mdm_id_from_global_registry
97
+ expect(person.global_registry_mdm_id).to eq 'c81340b2-7e57-4978-b6b9-396f21bb0bb2'
98
+ end.not_to raise_error
99
+ end
100
+ end
39
101
  end
40
102
  end
41
103
 
42
- describe 'mdm_worker_class' do
104
+ describe '#mdm_worker_class' do
43
105
  before do
44
106
  module MdmTest
45
107
  class Klass
46
- def self.global_registry
108
+ def self.global_registry_entity
47
109
  @gr ||= Object.new
48
110
  end
49
111
  end
@@ -55,10 +117,10 @@ RSpec.describe 'GlobalRegistry::Bindings::Workers' do
55
117
  end
56
118
 
57
119
  it 'generates worker class with mdm timeout set' do
58
- expect(MdmTest::Klass.global_registry).to(
120
+ expect(MdmTest::Klass.global_registry_entity).to(
59
121
  receive(:mdm_worker_class_name).and_return('PullMdmTestKlassMdmIdWorker')
60
122
  )
61
- expect(MdmTest::Klass.global_registry).to(
123
+ expect(MdmTest::Klass.global_registry_entity).to(
62
124
  receive(:mdm_timeout).and_return(33.minutes)
63
125
  )
64
126
 
@@ -0,0 +1,476 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe GlobalRegistry::Bindings::Workers::PushEntityWorker do
6
+ around { |example| travel_to Time.utc(2001, 2, 3), &example }
7
+ describe '#perform(model_class, id)' do
8
+ context Namespaced::Person do
9
+ let(:person) { create(:person) }
10
+ context 'with valid id' do
11
+ it 'should call #push_entity_to_global_registry' do
12
+ expect(Namespaced::Person).to receive(:find).with(person.id).and_return(person)
13
+
14
+ worker = GlobalRegistry::Bindings::Workers::PushEntityWorker.new
15
+ expect(worker).to receive(:push_entity_to_global_registry)
16
+ worker.perform('Namespaced::Person', person.id)
17
+ expect(worker.model).to be person
18
+ end
19
+ end
20
+
21
+ context 'with invalid id' do
22
+ it 'should fail silently' do
23
+ expect(Namespaced::Person).to receive(:find).with(person.id).and_raise(ActiveRecord::RecordNotFound)
24
+ expect(GlobalRegistry::Bindings::Workers::PushEntityWorker).not_to receive(:push_entity_to_global_registry)
25
+
26
+ worker = GlobalRegistry::Bindings::Workers::PushEntityWorker.new
27
+ worker.perform(Namespaced::Person, person.id)
28
+ expect(worker.model).to be nil
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ describe '#push_entity_to_global_registry' do
35
+ describe Organization do
36
+ let(:worker) { GlobalRegistry::Bindings::Workers::PushEntityWorker.new organization }
37
+ context 'and unknown \'fancy_org\' entity_type' do
38
+ let!(:requests) do
39
+ [stub_request(:get, 'https://backend.global-registry.org/entity_types')
40
+ .with(query: { 'filters[name]' => 'fancy_org', 'filters[parent_id]' => nil })
41
+ .to_return(body: file_fixture('get_entity_types.json'), status: 200),
42
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
43
+ .with(body: { entity_type: { name: 'fancy_org', parent_id: nil, field_type: 'entity' } })
44
+ .to_return(body: file_fixture('post_entity_types_fancy_org.json'), status: 200),
45
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
46
+ .with(body: { entity_type: { name: 'name', parent_id: '025a1128-3f33-11e7-b876-129bd0521531',
47
+ field_type: 'string' } })
48
+ .to_return(status: 200),
49
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
50
+ .with(body: { entity_type: { name: 'description', parent_id: '025a1128-3f33-11e7-b876-129bd0521531',
51
+ field_type: 'string' } })
52
+ .to_return(status: 200),
53
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
54
+ .with(body: { entity_type: { name: 'start_date', parent_id: '025a1128-3f33-11e7-b876-129bd0521531',
55
+ field_type: 'date' } })
56
+ .to_return(status: 200)]
57
+ end
58
+
59
+ context 'with root level organization' do
60
+ let(:organization) { create(:organization) }
61
+ let!(:sub_requests) do
62
+ [stub_request(:post, 'https://backend.global-registry.org/entities')
63
+ .with(body: { entity: { fancy_org: { name: 'Organization', description: 'Fancy Organization',
64
+ start_date: '2001-02-03', parent_id: nil,
65
+ client_integration_id: organization.id,
66
+ client_updated_at: '2001-02-03 00:00:00' } } })
67
+ .to_return(body: file_fixture('post_entities_fancy_org.json'), status: 200)]
68
+ end
69
+
70
+ it 'should create \'fancy_org\' entity_type and push entity to Global Registry' do
71
+ worker.push_entity_to_global_registry
72
+ (requests + sub_requests).each { |r| expect(r).to have_been_requested.once }
73
+ expect(organization.gr_id).to eq 'aebb4170-3f34-11e7-bba6-129bd0521531'
74
+ end
75
+ end
76
+
77
+ context 'with organization with parent missing global_registry_id' do
78
+ let(:parent) { create(:organization, name: 'Parent', description: 'Parent Fancy Organization') }
79
+ let(:organization) { create(:organization, parent: parent) }
80
+
81
+ it 'should create \'fancy_org\' entity_type raise an exception' do
82
+ expect do
83
+ worker.push_entity_to_global_registry
84
+ requests.each { |r| expect(r).to have_been_requested.once }
85
+ end.to raise_error GlobalRegistry::Bindings::ParentEntityMissingGlobalRegistryId,
86
+ "Organization(#{organization.id}) has parent entity Organization(#{parent.id}) " \
87
+ 'missing global_registry_id; will retry.'
88
+ end
89
+ end
90
+
91
+ context 'organization with an existing parent' do
92
+ let(:parent) do
93
+ create :organization, name: 'Parent', description: 'Parent Fancy Organization',
94
+ gr_id: 'cd5da38a-c336-46a7-b818-dcdd51c4acde'
95
+ end
96
+ let(:organization) { create(:organization, parent: parent) }
97
+ let!(:sub_requests) do
98
+ [stub_request(:post, 'https://backend.global-registry.org/entities')
99
+ .with(body: { entity: { fancy_org: { name: 'Organization', description: 'Fancy Organization',
100
+ start_date: '2001-02-03',
101
+ parent_id: 'cd5da38a-c336-46a7-b818-dcdd51c4acde',
102
+ client_integration_id: organization.id,
103
+ client_updated_at: '2001-02-03 00:00:00' } } })
104
+ .to_return(body: file_fixture('post_entities_fancy_org.json'), status: 200)]
105
+ end
106
+
107
+ it 'should create \'fancy_org\' entity_type and push both entities' do
108
+ worker.push_entity_to_global_registry
109
+ (requests + sub_requests).each { |r| expect(r).to have_been_requested.once }
110
+ expect(parent.gr_id).to eq 'cd5da38a-c336-46a7-b818-dcdd51c4acde'
111
+ expect(organization.gr_id).to eq 'aebb4170-3f34-11e7-bba6-129bd0521531'
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ describe Namespaced::Person do
118
+ let(:worker) { GlobalRegistry::Bindings::Workers::PushEntityWorker.new person }
119
+ context 'as create' do
120
+ let(:person) { create(:person) }
121
+
122
+ context '\'person\' entity_type does not exist' do
123
+ let!(:requests) do
124
+ [stub_request(:get, 'https://backend.global-registry.org/entity_types')
125
+ .with(query: { 'filters[name]' => 'person', 'filters[parent_id]' => nil })
126
+ .to_return(body: file_fixture('get_entity_types.json'), status: 200),
127
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
128
+ .with(body: { entity_type: { name: 'person', parent_id: nil, field_type: 'entity' } })
129
+ .to_return(body: file_fixture('post_entity_types_person.json'), status: 200),
130
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
131
+ .with(body: { entity_type: { name: 'first_name', parent_id: 'ee13a693-3ce7-4c19-b59a-30c8f137acd8',
132
+ field_type: 'string' } })
133
+ .to_return(status: 200),
134
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
135
+ .with(body: { entity_type: { name: 'last_name', parent_id: 'ee13a693-3ce7-4c19-b59a-30c8f137acd8',
136
+ field_type: 'string' } })
137
+ .to_return(status: 200),
138
+ stub_request(:post, 'https://backend.global-registry.org/entities')
139
+ .with(body: { entity: { person: { first_name: 'Tony', last_name: 'Stark',
140
+ client_integration_id: person.id,
141
+ client_updated_at: '2001-02-03 00:00:00',
142
+ authentication: {
143
+ key_guid: '98711710-acb5-4a41-ba51-e0fc56644b53'
144
+ } } } })
145
+ .to_return(body: file_fixture('post_entities_person.json'), status: 200)]
146
+ end
147
+
148
+ it 'should create \'person\' entity_type and push entity' do
149
+ worker.push_entity_to_global_registry
150
+ requests.each { |r| expect(r).to have_been_requested.once }
151
+ expect(person.global_registry_id).to eq '22527d88-3cba-11e7-b876-129bd0521531'
152
+ end
153
+ end
154
+
155
+ context '\'person\' entity_type exists' do
156
+ let!(:requests) do
157
+ [stub_request(:get, 'https://backend.global-registry.org/entity_types')
158
+ .with(query: { 'filters[name]' => 'person', 'filters[parent_id]' => nil })
159
+ .to_return(body: file_fixture('get_entity_types_person.json'), status: 200),
160
+ stub_request(:post, 'https://backend.global-registry.org/entities')
161
+ .with(body: { entity: { person: { first_name: 'Tony', last_name: 'Stark',
162
+ client_integration_id: person.id,
163
+ client_updated_at: '2001-02-03 00:00:00',
164
+ authentication: {
165
+ key_guid: '98711710-acb5-4a41-ba51-e0fc56644b53'
166
+ } } } })
167
+ .to_return(body: file_fixture('post_entities_person.json'), status: 200)]
168
+ end
169
+
170
+ it 'should skip creating entity_type and push the entity' do
171
+ worker.push_entity_to_global_registry
172
+ requests.each { |r| expect(r).to have_been_requested.once }
173
+ expect(person.global_registry_id).to eq '22527d88-3cba-11e7-b876-129bd0521531'
174
+ end
175
+ end
176
+
177
+ context 'partial \'person\' entity_type exists' do
178
+ let!(:requests) do
179
+ [stub_request(:get, 'https://backend.global-registry.org/entity_types')
180
+ .with(query: { 'filters[name]' => 'person', 'filters[parent_id]' => nil })
181
+ .to_return(body: file_fixture('get_entity_types_person_partial.json'), status: 200),
182
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
183
+ .with(body: { entity_type: { name: 'first_name', parent_id: 'ee13a693-3ce7-4c19-b59a-30c8f137acd8',
184
+ field_type: 'string' } })
185
+ .to_return(status: 200),
186
+ stub_request(:post, 'https://backend.global-registry.org/entities')
187
+ .with(body: { entity: { person: { first_name: 'Tony', last_name: 'Stark',
188
+ client_integration_id: person.id,
189
+ client_updated_at: '2001-02-03 00:00:00',
190
+ authentication: {
191
+ key_guid: '98711710-acb5-4a41-ba51-e0fc56644b53'
192
+ } } } })
193
+ .to_return(body: file_fixture('post_entities_person.json'), status: 200)]
194
+ end
195
+
196
+ it 'should skip creating entity_type and push the entity' do
197
+ worker.push_entity_to_global_registry
198
+ requests.each { |r| expect(r).to have_been_requested.once }
199
+ expect(person.global_registry_id).to eq '22527d88-3cba-11e7-b876-129bd0521531'
200
+ end
201
+ end
202
+
203
+ context '\'person\' entity_type is cached' do
204
+ before :each do
205
+ person_entity_types = JSON.parse(file_fixture('get_entity_types_person.json').read)
206
+ Rails.cache.write('GlobalRegistry::Bindings::EntityType::person', person_entity_types['entity_types'].first)
207
+ end
208
+
209
+ it 'should skip creating entity_type and push the entity' do
210
+ request = stub_request(:post, 'https://backend.global-registry.org/entities')
211
+ .with(body: { entity: { person: { first_name: 'Tony', last_name: 'Stark',
212
+ client_integration_id: person.id,
213
+ client_updated_at: '2001-02-03 00:00:00',
214
+ authentication: {
215
+ key_guid: '98711710-acb5-4a41-ba51-e0fc56644b53'
216
+ } } } })
217
+ .to_return(body: file_fixture('post_entities_person.json'), status: 200)
218
+ worker.push_entity_to_global_registry
219
+ expect(request).to have_been_requested.once
220
+ expect(person.global_registry_id).to eq '22527d88-3cba-11e7-b876-129bd0521531'
221
+ end
222
+ end
223
+ end
224
+
225
+ context 'as an update' do
226
+ let(:person) { create(:person, global_registry_id: 'f8d20318-2ff2-4a98-a5eb-e9d840508bf1') }
227
+ context '\'person\' entity_type is cached' do
228
+ before :each do
229
+ person_entity_types = JSON.parse(file_fixture('get_entity_types_person.json').read)
230
+ Rails.cache.write('GlobalRegistry::Bindings::EntityType::person', person_entity_types['entity_types'].first)
231
+ end
232
+
233
+ it 'should skip creating entity_type and update the entity' do
234
+ request = stub_request(:put,
235
+ 'https://backend.global-registry.org/entities/f8d20318-2ff2-4a98-a5eb-e9d840508bf1')
236
+ .with(body: { entity: { person: { first_name: 'Tony', last_name: 'Stark',
237
+ client_integration_id: person.id,
238
+ client_updated_at: '2001-02-03 00:00:00',
239
+ authentication: {
240
+ key_guid: '98711710-acb5-4a41-ba51-e0fc56644b53'
241
+ } } } })
242
+ .to_return(body: file_fixture('post_entities_person.json'), status: 200)
243
+ worker.push_entity_to_global_registry
244
+ expect(request).to have_been_requested.once
245
+ end
246
+
247
+ context 'invalid entity id' do
248
+ let!(:requests) do
249
+ [stub_request(:put,
250
+ 'https://backend.global-registry.org/entities/f8d20318-2ff2-4a98-a5eb-e9d840508bf1')
251
+ .with(body: { entity: { person: { first_name: 'Tony', last_name: 'Stark',
252
+ client_integration_id: person.id,
253
+ client_updated_at: '2001-02-03 00:00:00',
254
+ authentication: {
255
+ key_guid: '98711710-acb5-4a41-ba51-e0fc56644b53'
256
+ } } } })
257
+ .to_return(status: 404),
258
+ stub_request(:post, 'https://backend.global-registry.org/entities')
259
+ .with(body: { entity: { person: { first_name: 'Tony', last_name: 'Stark',
260
+ client_integration_id: person.id,
261
+ client_updated_at: '2001-02-03 00:00:00',
262
+ authentication: {
263
+ key_guid: '98711710-acb5-4a41-ba51-e0fc56644b53'
264
+ } } } })
265
+ .to_return(body: file_fixture('post_entities_person.json'), status: 200)]
266
+ end
267
+
268
+ it 'should push entity as create' do
269
+ worker.push_entity_to_global_registry
270
+ requests.each { |r| expect(r).to have_been_requested.once }
271
+ expect(person.global_registry_id).to eq '22527d88-3cba-11e7-b876-129bd0521531'
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ describe Address do
279
+ let(:worker) { GlobalRegistry::Bindings::Workers::PushEntityWorker.new address }
280
+ context 'as create' do
281
+ context '\'address\' record does not belong to a person' do
282
+ let(:address) { create(:address) }
283
+
284
+ it 'should not create \'address\' entity_type and skip push of entity' do
285
+ worker.push_entity_to_global_registry
286
+ end
287
+ end
288
+
289
+ context '\'address\' entity_type does not exist' do
290
+ let!(:requests) do
291
+ [stub_request(:get, 'https://backend.global-registry.org/entity_types')
292
+ .with(query: { 'filters[name]' => 'person', 'filters[parent_id]' => nil })
293
+ .to_return(body: file_fixture('get_entity_types_person.json'), status: 200),
294
+ stub_request(:get, 'https://backend.global-registry.org/entity_types')
295
+ .with(query: { 'filters[name]' => 'address',
296
+ 'filters[parent_id]' => 'ee13a693-3ce7-4c19-b59a-30c8f137acd8' })
297
+ .to_return(body: file_fixture('get_entity_types.json'), status: 200),
298
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
299
+ .with(body: { entity_type: { name: 'address', parent_id: 'ee13a693-3ce7-4c19-b59a-30c8f137acd8',
300
+ field_type: 'entity' } })
301
+ .to_return(body: file_fixture('post_entity_types_address.json'), status: 200),
302
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
303
+ .with(body: { entity_type: { name: 'zip', parent_id: 'f5331684-3ca8-11e7-b937-129bd0521531',
304
+ field_type: 'string' } })
305
+ .to_return(status: 200),
306
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
307
+ .with(body: { entity_type: { name: 'line1', parent_id: 'f5331684-3ca8-11e7-b937-129bd0521531',
308
+ field_type: 'string' } })
309
+ .to_return(status: 200),
310
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
311
+ .with(body: { entity_type: { name: 'line2', parent_id: 'f5331684-3ca8-11e7-b937-129bd0521531',
312
+ field_type: 'string' } })
313
+ .to_return(status: 200),
314
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
315
+ .with(body: { entity_type: { name: 'primary', parent_id: 'f5331684-3ca8-11e7-b937-129bd0521531',
316
+ field_type: 'boolean' } })
317
+ .to_return(status: 200),
318
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
319
+ .with(body: { entity_type: { name: 'postal_code', parent_id: 'f5331684-3ca8-11e7-b937-129bd0521531',
320
+ field_type: 'string' } })
321
+ .to_return(status: 200)]
322
+ end
323
+
324
+ context '\'address\' record belongs to a person without global registry id' do
325
+ let(:person) { create(:person) }
326
+ let(:address) { create(:address, person: person) }
327
+
328
+ it 'should create \'address\' entity_type and raise an error' do
329
+ expect do
330
+ worker.push_entity_to_global_registry
331
+ end.to raise_error GlobalRegistry::Bindings::ParentEntityMissingGlobalRegistryId,
332
+ "Address(#{address.id}) has parent entity Namespaced::Person(#{person.id}) " \
333
+ 'missing global_registry_id; will retry.'
334
+ requests.each { |r| expect(r).to have_been_requested.once }
335
+ expect(person.global_registry_id).to be nil
336
+ expect(address.global_registry_id).to be nil
337
+ end
338
+ end
339
+
340
+ context '\'address\' record belongs to an existing person entity' do
341
+ let(:person) { create(:person, global_registry_id: '22527d88-3cba-11e7-b876-129bd0521531') }
342
+ let(:address) { create(:address, person: person) }
343
+ let!(:sub_requests) do
344
+ [stub_request(:put,
345
+ 'https://backend.global-registry.org/entities/22527d88-3cba-11e7-b876-129bd0521531')
346
+ .with(body: { entity: { person: { client_integration_id: person.id,
347
+ address: {
348
+ zip: '90265', primary: 'true',
349
+ line1: '10880 Malibu Point', postal_code: '90265',
350
+ client_integration_id: address.id,
351
+ client_updated_at: '2001-02-03 00:00:00'
352
+ } } } })
353
+ .to_return(body: file_fixture('put_entities_address.json'), status: 200)]
354
+ end
355
+
356
+ it 'should create \'address\' entity_type and push address entity' do
357
+ worker.push_entity_to_global_registry
358
+ (requests + sub_requests).each { |r| expect(r).to have_been_requested.once }
359
+ expect(address.global_registry_id).to eq '0a594356-3f1c-11e7-bba6-129bd0521531'
360
+ end
361
+ end
362
+ end
363
+
364
+ context '\'address\' and \'person\' entity_types exist' do
365
+ let(:person) { create(:person, global_registry_id: '22527d88-3cba-11e7-b876-129bd0521531') }
366
+ let(:address) { create(:address, person: person) }
367
+ let!(:requests) do
368
+ [stub_request(:get, 'https://backend.global-registry.org/entity_types')
369
+ .with(query: { 'filters[name]' => 'person', 'filters[parent_id]' => nil })
370
+ .to_return(body: file_fixture('get_entity_types_person.json'), status: 200),
371
+ stub_request(:put,
372
+ 'https://backend.global-registry.org/entities/22527d88-3cba-11e7-b876-129bd0521531')
373
+ .with(body: { entity: { person: { client_integration_id: person.id,
374
+ address: {
375
+ zip: '90265', primary: 'true',
376
+ line1: '10880 Malibu Point', postal_code: '90265',
377
+ client_integration_id: address.id,
378
+ client_updated_at: '2001-02-03 00:00:00'
379
+ } } } })
380
+ .to_return(body: file_fixture('put_entities_address.json'), status: 200)]
381
+ end
382
+
383
+ context '\'address\' entity_type has partial fields' do
384
+ let!(:sub_requests) do
385
+ [stub_request(:get, 'https://backend.global-registry.org/entity_types')
386
+ .with(query: { 'filters[name]' => 'address',
387
+ 'filters[parent_id]' => 'ee13a693-3ce7-4c19-b59a-30c8f137acd8' })
388
+ .to_return(body: file_fixture('get_entity_types_address_partial.json'), status: 200),
389
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
390
+ .with(body: { entity_type: { name: 'line2', parent_id: 'f5331684-3ca8-11e7-b937-129bd0521531',
391
+ field_type: 'string' } })
392
+ .to_return(status: 200),
393
+ stub_request(:post, 'https://backend.global-registry.org/entity_types')
394
+ .with(body: { entity_type: { name: 'primary', parent_id: 'f5331684-3ca8-11e7-b937-129bd0521531',
395
+ field_type: 'boolean' } })
396
+ .to_return(status: 200)]
397
+ end
398
+
399
+ it 'should add missing fields and push address entity' do
400
+ worker.push_entity_to_global_registry
401
+ (requests + sub_requests).each { |r| expect(r).to have_been_requested.once }
402
+ expect(address.global_registry_id).to eq '0a594356-3f1c-11e7-bba6-129bd0521531'
403
+ end
404
+ end
405
+
406
+ context '\'address\' entity_type has all fields' do
407
+ let!(:sub_requests) do
408
+ [stub_request(:get, 'https://backend.global-registry.org/entity_types')
409
+ .with(query: { 'filters[name]' => 'address',
410
+ 'filters[parent_id]' => 'ee13a693-3ce7-4c19-b59a-30c8f137acd8' })
411
+ .to_return(body: file_fixture('get_entity_types_address.json'), status: 200)]
412
+ end
413
+
414
+ it 'should push address entity' do
415
+ worker.push_entity_to_global_registry
416
+ (requests + sub_requests).each { |r| expect(r).to have_been_requested.once }
417
+ expect(address.global_registry_id).to eq '0a594356-3f1c-11e7-bba6-129bd0521531'
418
+ end
419
+ end
420
+ end
421
+ end
422
+
423
+ context 'as an update' do
424
+ before :each do
425
+ person_entity_types = JSON.parse(file_fixture('get_entity_types_person.json').read)
426
+ Rails.cache.write('GlobalRegistry::Bindings::EntityType::person', person_entity_types['entity_types'].first)
427
+ address_entity_types = JSON.parse(file_fixture('get_entity_types_address.json').read)
428
+ Rails.cache.write('GlobalRegistry::Bindings::EntityType::address',
429
+ address_entity_types['entity_types'].first)
430
+ end
431
+ let(:person) { create(:person, global_registry_id: '22527d88-3cba-11e7-b876-129bd0521531') }
432
+ let(:address) do
433
+ create(:address, person: person, global_registry_id: '0a594356-3f1c-11e7-bba6-129bd0521531')
434
+ end
435
+ let!(:request) do
436
+ stub_request(:put,
437
+ 'https://backend.global-registry.org/entities/22527d88-3cba-11e7-b876-129bd0521531')
438
+ .with(body: { entity: { person: { client_integration_id: person.id,
439
+ address: {
440
+ zip: '90265', primary: 'false',
441
+ line1: '100 Sesame Street', postal_code: '90265',
442
+ client_integration_id: address.id,
443
+ client_updated_at: '2001-02-03 00:00:00'
444
+ } } } })
445
+ .to_return(body: file_fixture('put_entities_address.json'), status: 200)
446
+ end
447
+
448
+ it 'should push address entity' do
449
+ address.address1 = '100 Sesame Street'
450
+ address.primary = false
451
+ expect do
452
+ worker.push_entity_to_global_registry
453
+ end.to_not(change { address.global_registry_id })
454
+ expect(request).to have_been_requested.once
455
+ end
456
+ end
457
+ end
458
+
459
+ describe Community do
460
+ let(:worker) { GlobalRegistry::Bindings::Workers::PushEntityWorker.new community }
461
+ let(:community) { create(:community, infobase_id: 234) }
462
+ let!(:request) do
463
+ stub_request(:post, 'https://backend.global-registry.org/entities')
464
+ .with(body: { entity: { community: { name: 'Community', client_integration_id: community.id,
465
+ client_updated_at: '2001-02-03 00:00:00' } } })
466
+ .to_return(body: file_fixture('post_entities_community.json'), status: 200)
467
+ end
468
+
469
+ it 'should push community entity' do
470
+ worker.push_entity_to_global_registry
471
+ expect(request).to have_been_requested.once
472
+ expect(community.global_registry_id).to eq '6133f6fe-c63a-425a-bb46-68917c689723'
473
+ end
474
+ end
475
+ end
476
+ end