maestrano-connector-rails 2.0.2.pre.RC6 → 2.0.2.pre.RC7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -0
  3. data/DEVELOPER.md +1 -4
  4. data/Gemfile +2 -32
  5. data/Rakefile +6 -30
  6. data/app/models/maestrano/connector/rails/concerns/entity.rb +12 -0
  7. data/app/models/maestrano/connector/rails/concerns/sub_entity_base.rb +3 -2
  8. data/app/models/maestrano/connector/rails/id_map.rb +1 -0
  9. data/app/models/maestrano/connector/rails/services/data_consolidator.rb +4 -4
  10. data/db/migrate/20170315032224_add_metadata_to_id_map.rb +5 -0
  11. data/lib/maestrano/connector/rails/version.rb +7 -0
  12. data/lib/maestrano_connector_rails/factories.rb +1 -0
  13. data/maestrano-connector-rails.gemspec +44 -308
  14. metadata +13 -151
  15. data/VERSION +0 -1
  16. data/spec/controllers/connec_controller_spec.rb +0 -179
  17. data/spec/controllers/dependancies_controller_spec.rb +0 -31
  18. data/spec/controllers/group_users_controller_spec.rb +0 -39
  19. data/spec/controllers/groups_controller_spec.rb +0 -36
  20. data/spec/controllers/synchronizations_controller_spec.rb +0 -211
  21. data/spec/controllers/version_controller_spec.rb +0 -17
  22. data/spec/dummy/README.md +0 -1
  23. data/spec/dummy/Rakefile +0 -6
  24. data/spec/dummy/app/assets/images/.keep +0 -0
  25. data/spec/dummy/app/assets/javascripts/application.js +0 -13
  26. data/spec/dummy/app/assets/stylesheets/application.css +0 -15
  27. data/spec/dummy/app/controllers/application_controller.rb +0 -8
  28. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  29. data/spec/dummy/app/helpers/application_helper.rb +0 -2
  30. data/spec/dummy/app/mailers/.keep +0 -0
  31. data/spec/dummy/app/models/.keep +0 -0
  32. data/spec/dummy/app/models/concerns/.keep +0 -0
  33. data/spec/dummy/app/models/entities/.keep +0 -0
  34. data/spec/dummy/app/views/home/index.html.erb +0 -1
  35. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  36. data/spec/dummy/bin/bundle +0 -3
  37. data/spec/dummy/bin/rails +0 -4
  38. data/spec/dummy/bin/rake +0 -4
  39. data/spec/dummy/bin/setup +0 -29
  40. data/spec/dummy/config.ru +0 -4
  41. data/spec/dummy/config/application.rb +0 -26
  42. data/spec/dummy/config/boot.rb +0 -5
  43. data/spec/dummy/config/database.yml +0 -25
  44. data/spec/dummy/config/environment.rb +0 -5
  45. data/spec/dummy/config/environments/development.rb +0 -41
  46. data/spec/dummy/config/environments/production.rb +0 -79
  47. data/spec/dummy/config/environments/test.rb +0 -39
  48. data/spec/dummy/config/initializers/assets.rb +0 -11
  49. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  50. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -3
  51. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  52. data/spec/dummy/config/initializers/inflections.rb +0 -16
  53. data/spec/dummy/config/initializers/maestrano.rb +0 -2
  54. data/spec/dummy/config/initializers/mime_types.rb +0 -4
  55. data/spec/dummy/config/initializers/session_store.rb +0 -3
  56. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  57. data/spec/dummy/config/locales/en.yml +0 -23
  58. data/spec/dummy/config/routes.rb +0 -9
  59. data/spec/dummy/config/secrets.yml +0 -22
  60. data/spec/dummy/config/settings.yml +0 -2
  61. data/spec/dummy/config/settings/development.yml +0 -12
  62. data/spec/dummy/config/settings/production.yml +0 -1
  63. data/spec/dummy/config/settings/test.yml +0 -12
  64. data/spec/dummy/config/settings/uat.yml +0 -1
  65. data/spec/dummy/db/schema.rb +0 -102
  66. data/spec/dummy/lib/assets/.keep +0 -0
  67. data/spec/dummy/log/.keep +0 -0
  68. data/spec/dummy/public/404.html +0 -67
  69. data/spec/dummy/public/422.html +0 -67
  70. data/spec/dummy/public/500.html +0 -66
  71. data/spec/dummy/public/favicon.ico +0 -0
  72. data/spec/dummy/tmp/cache/.gitkeep +0 -0
  73. data/spec/integration/complex_id_references_spec.rb +0 -249
  74. data/spec/integration/complex_naming_spec.rb +0 -192
  75. data/spec/integration/complex_spec.rb +0 -578
  76. data/spec/integration/connec_to_external_spec.rb +0 -327
  77. data/spec/integration/external_to_connec_spec.rb +0 -159
  78. data/spec/integration/id_references_spec.rb +0 -584
  79. data/spec/integration/singleton_spec.rb +0 -297
  80. data/spec/jobs/all_synchronizations_job_spec.rb +0 -24
  81. data/spec/jobs/push_to_connec_job_spec.rb +0 -111
  82. data/spec/jobs/push_to_connec_worker_spec.rb +0 -37
  83. data/spec/jobs/synchronization_job_spec.rb +0 -216
  84. data/spec/models/complex_entity_spec.rb +0 -407
  85. data/spec/models/connec_helper_spec.rb +0 -588
  86. data/spec/models/connector_logger_spec.rb +0 -26
  87. data/spec/models/entity_base_spec.rb +0 -20
  88. data/spec/models/entity_spec.rb +0 -1078
  89. data/spec/models/external_spec.rb +0 -27
  90. data/spec/models/id_map_spec.rb +0 -12
  91. data/spec/models/organization_spec.rb +0 -243
  92. data/spec/models/sub_entity_base_spec.rb +0 -155
  93. data/spec/models/synchronization_spec.rb +0 -106
  94. data/spec/models/user_organization_rel_spec.rb +0 -14
  95. data/spec/models/user_spec.rb +0 -15
  96. data/spec/routing/connec_routing_spec.rb +0 -12
  97. data/spec/spec_helper.rb +0 -34
  98. data/template/Procfile +0 -2
  99. data/template/application-sample.yml +0 -13
  100. data/template/database.yml +0 -31
  101. data/template/gitignore +0 -23
  102. data/template/maestrano.rb +0 -2
  103. data/template/maestrano_connector_template.rb +0 -135
  104. data/template/routes.rb +0 -25
  105. data/template/rubocop.yml +0 -55
  106. data/template/settings/development.yml +0 -0
  107. data/template/settings/production.yml +0 -0
  108. data/template/settings/settings.yml +0 -2
  109. data/template/settings/test.yml +0 -0
  110. data/template/settings/uat.yml +0 -0
  111. data/template/sidekiq.rb +0 -9
  112. data/template/sidekiq.yml +0 -4
  113. data/template/spec_helper.rb +0 -24
@@ -1,216 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Maestrano::Connector::Rails::SynchronizationJob do
4
- let(:organization) { create(:organization) }
5
- let(:opts) { {} }
6
- subject { Maestrano::Connector::Rails::SynchronizationJob.perform_now(organization.id, opts) }
7
-
8
- def does_not_perform
9
- expect_any_instance_of(Maestrano::Connector::Rails::SynchronizationJob).to_not receive(:sync_entity)
10
- expect{ subject }.to change{ Maestrano::Connector::Rails::Synchronization.count }.by(0)
11
- end
12
-
13
- def performes
14
- expect{ subject }.to change{ Maestrano::Connector::Rails::Synchronization.count }.by(1)
15
- end
16
-
17
- describe 'perform' do
18
- context 'with sync_enabled set to false' do
19
- it { does_not_perform }
20
- end
21
-
22
- context 'with sync_enabled set to true' do
23
- before { organization.update(sync_enabled: true)}
24
-
25
- context 'with a sync still running for less than 30 minutes' do
26
- let!(:running_sync) { create(:synchronization, organization: organization, status: 'RUNNING', created_at: 29.minutes.ago) }
27
- it { does_not_perform }
28
- end
29
-
30
- context 'with a sync still running for more than 30 minutes' do
31
- let!(:running_sync) { create(:synchronization, organization: organization, status: 'RUNNING', created_at: 31.minutes.ago) }
32
- it { performes }
33
- end
34
-
35
- describe 'recovery mode' do
36
- context 'three last sync failed and last sync less than 24 hours ago' do
37
- before {
38
- 3.times do
39
- organization.synchronizations.create(status: 'ERROR', created_at: 2.hour.ago)
40
- end
41
- }
42
- it { does_not_perform }
43
-
44
- context 'synchronization is forced' do
45
- let(:opts) { {forced: true} }
46
- it { performes }
47
- end
48
- end
49
-
50
- context 'three last sync failed and last sync more than 24 hours ago' do
51
- before {
52
- 3.times do
53
- organization.synchronizations.create(status: 'ERROR', created_at: 2.day.ago, updated_at: 2.day.ago)
54
- end
55
- }
56
- it { performes }
57
- end
58
-
59
- context 'three sync failed but last sync is successfull' do
60
- before {
61
- 3.times do
62
- organization.synchronizations.create(status: 'ERROR', created_at: 2.hour.ago)
63
- end
64
- organization.synchronizations.create(status: 'SUCCESS', created_at: 1.hour.ago)
65
- }
66
- it { performes }
67
- end
68
- end
69
-
70
-
71
- context 'first sync' do
72
- it 'does two half syncs' do
73
- expect_any_instance_of(Maestrano::Connector::Rails::SynchronizationJob).to receive(:first_sync_entity).exactly(2 * organization.synchronized_entities.count).times
74
- subject
75
- end
76
- end
77
-
78
- context 'subsequent sync' do
79
- let!(:old_sync) { create(:synchronization, partial: false, status: 'SUCCESS', organization: organization) }
80
-
81
- it { performes }
82
-
83
- context 'with options' do
84
- context 'with only_entities' do
85
- let(:opts) { {only_entities: %w(people price)} }
86
-
87
- it 'calls sync entity on the specified entities' do
88
- expect_any_instance_of(Maestrano::Connector::Rails::SynchronizationJob).to receive(:sync_entity).twice
89
-
90
- subject
91
- end
92
-
93
- it 'set the current syncrhonization as partial' do
94
- subject
95
- expect(Maestrano::Connector::Rails::Synchronization.last.partial).to be(true)
96
- end
97
- end
98
- end
99
- end
100
-
101
- end
102
- end
103
-
104
- describe 'other methods' do
105
- subject { Maestrano::Connector::Rails::SynchronizationJob.new }
106
-
107
- describe 'sync_entity' do
108
-
109
- context 'non complex entity' do
110
- before {
111
- class Entities::Person < Maestrano::Connector::Rails::Entity
112
- end
113
- }
114
-
115
- it 'calls the seven methods' do
116
- expect_any_instance_of(Entities::Person).to receive(:before_sync)
117
- expect_any_instance_of(Entities::Person).to receive(:get_connec_entities).and_return([])
118
- expect_any_instance_of(Entities::Person).to receive(:get_external_entities_wrapper).and_return([])
119
- expect_any_instance_of(Entities::Person).to receive(:consolidate_and_map_data).and_return({})
120
- expect_any_instance_of(Entities::Person).to receive(:push_entities_to_external)
121
- expect_any_instance_of(Entities::Person).to receive(:push_entities_to_connec)
122
- expect_any_instance_of(Entities::Person).to receive(:after_sync)
123
- subject.sync_entity('person', organization, nil, nil, nil, {})
124
- end
125
- end
126
-
127
- context 'complex entity' do
128
- before {
129
- class Entities::SomeStuff < Maestrano::Connector::Rails::ComplexEntity
130
- end
131
- }
132
-
133
- it 'calls the seven methods' do
134
- expect_any_instance_of(Entities::SomeStuff).to receive(:before_sync)
135
- expect_any_instance_of(Entities::SomeStuff).to receive(:get_connec_entities).and_return({})
136
- expect_any_instance_of(Entities::SomeStuff).to receive(:get_external_entities_wrapper).and_return({})
137
- expect_any_instance_of(Entities::SomeStuff).to receive(:consolidate_and_map_data).and_return({})
138
- expect_any_instance_of(Entities::SomeStuff).to receive(:push_entities_to_external)
139
- expect_any_instance_of(Entities::SomeStuff).to receive(:push_entities_to_connec)
140
- expect_any_instance_of(Entities::SomeStuff).to receive(:after_sync)
141
- subject.sync_entity('some stuff', organization, nil, nil, nil, {})
142
- end
143
- end
144
- end
145
-
146
- describe 'first_sync_entity' do
147
- let(:batch_limit) { 50 }
148
-
149
- context 'non complex entity' do
150
- let(:external_entities1) { [] }
151
- let(:external_entities2) { [] }
152
- let(:connec_entities1) { [] }
153
- let(:connec_entities2) { [] }
154
- before {
155
- class Entities::Person < Maestrano::Connector::Rails::Entity
156
- end
157
- allow_any_instance_of(Entities::Person).to receive(:get_connec_entities).and_return(connec_entities1, connec_entities2)
158
- allow_any_instance_of(Entities::Person).to receive(:get_external_entities_wrapper).and_return(external_entities1, external_entities2)
159
- allow_any_instance_of(Entities::Person).to receive(:consolidate_and_map_data).and_return({})
160
- allow_any_instance_of(Entities::Person).to receive(:push_entities_to_external)
161
- allow_any_instance_of(Entities::Person).to receive(:push_entities_to_connec)
162
- }
163
-
164
- context 'with pagination' do
165
- context 'with more than 50 entities' do
166
- let(:external_entities1) { [*1..50] }
167
- let(:external_entities2) { [*51..60] }
168
-
169
- it 'calls perform_sync several time' do
170
- expect_any_instance_of(Entities::Person).to receive(:opts_merge!).twice
171
- expect(subject).to receive(:perform_sync).twice.and_call_original
172
-
173
- subject.first_sync_entity('person', organization, nil, nil, nil, {}, true)
174
- end
175
- end
176
-
177
- context 'with less than 50 entities' do
178
- let(:external_entities1) { [*1..40] }
179
-
180
- it 'calls perform_sync once' do
181
- expect_any_instance_of(Entities::Person).to receive(:opts_merge!).once.with({__skip: 0})
182
- expect(subject).to receive(:perform_sync).once.and_call_original
183
-
184
- subject.first_sync_entity('person', organization, nil, nil, nil, {}, true)
185
- end
186
- end
187
- end
188
-
189
- context 'without pagination' do
190
- context 'when more than 50 entities' do
191
- let(:external_entities1) { [*1..60] }
192
-
193
- it 'calls perform_sync once' do
194
- expect_any_instance_of(Entities::Person).to receive(:opts_merge!).once.with({__skip: 0})
195
- expect(subject).to receive(:perform_sync).once.and_call_original
196
-
197
- subject.first_sync_entity('person', organization, nil, nil, nil, {}, true)
198
- end
199
- end
200
-
201
- context 'when exactly 50 entities' do
202
- let(:external_entities1) { [*1..50] }
203
- let(:external_entities1) { [*1..50] }
204
-
205
- it 'calls perform_sync twice but no infinite loop' do
206
- expect_any_instance_of(Entities::Person).to receive(:opts_merge!).twice
207
- expect(subject).to receive(:perform_sync).twice.and_call_original
208
-
209
- subject.first_sync_entity('person', organization, nil, nil, nil, {}, true)
210
- end
211
- end
212
- end
213
- end
214
- end
215
- end
216
- end
@@ -1,407 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Maestrano::Connector::Rails::ComplexEntity do
4
-
5
- describe 'class methods' do
6
- subject { Maestrano::Connector::Rails::ComplexEntity }
7
-
8
- describe 'connec_entities_names' do
9
- it { expect{ subject.connec_entities_names }.to raise_error('Not implemented') }
10
- end
11
- describe 'external_entities_names' do
12
- it { expect{ subject.external_entities_names }.to raise_error('Not implemented') }
13
- end
14
-
15
- describe 'count_and_first' do
16
- it 'returns the biggest array size and the first element of the first non empty array' do
17
- entities = {
18
- 'items' => [],
19
- 'people' => [*1..27],
20
- 'organizations' => [*3..39]
21
- }
22
- expect(subject.count_and_first(entities)).to eql(count: 37, first: 1)
23
- end
24
- end
25
-
26
- describe 'public_connec_entity_name' do
27
- it 'calls public name' do
28
- allow(subject).to receive(:formatted_connec_entities_names).and_return(a: 2)
29
- expect(subject).to receive(:public_name).with(a: 2)
30
- subject.public_connec_entity_name
31
- end
32
- end
33
- describe 'public_external_entity_name' do
34
- it 'calls public name' do
35
- allow(subject).to receive(:formatted_external_entities_names).and_return(a: 2)
36
- expect(subject).to receive(:public_name).with(a: 2)
37
- subject.public_external_entity_name
38
- end
39
- end
40
-
41
-
42
- describe 'public_name' do
43
- context 'when one entity' do
44
- it 'returns the pluralized entity name' do
45
- expect(subject.public_name({'sales_order' => 'Sales order'})).to eql('Sales orders')
46
- end
47
- end
48
-
49
- context 'when two entities' do
50
- it 'returns the pluralized entity names separeted by a and' do
51
- expect(subject.public_name({'Sales order' => 'Sales order', 'Purchase order' => 'Purchase order'})).to eql('Sales orders and purchase orders')
52
- end
53
- end
54
-
55
- context 'when more than two' do
56
- it 'returns the pluralized entity names separeted by commas and a and' do
57
- expect(subject.public_name({'Sales order' => 'Sales order', 'Purchase order' => 'Purchase order', 'Order' => 'Order'})).to eql('Sales orders, purchase orders and orders')
58
- end
59
- end
60
- end
61
- end
62
-
63
- describe 'instance methods' do
64
- let!(:organization) { create(:organization, uid: 'cld-123') }
65
- let!(:connec_client) { Maestrano::Connec::Client[organization.tenant].new(organization.uid) }
66
- let!(:external_client) { Object.new }
67
- let(:opts) { {} }
68
- subject { Maestrano::Connector::Rails::ComplexEntity.new(organization, connec_client, external_client, opts) }
69
-
70
- #Complex specific methods
71
- describe 'complex specific methods' do
72
- describe 'connec_model_to_external_model' do
73
- it { expect{ subject.connec_model_to_external_model({}) }.to raise_error('Not implemented') }
74
- end
75
- describe 'external_model_to_connec_model' do
76
- it { expect{ subject.external_model_to_connec_model({}) }.to raise_error('Not implemented') }
77
- end
78
- end
79
-
80
- describe 'filter_connec_entities' do
81
- it { expect(subject.filter_connec_entities({'lead' => [{a: 2}]})).to eql({'lead' => [{a: 2}]}) }
82
- end
83
-
84
- describe 'methods with sub complex entities' do
85
- before {
86
- module Entities::SubEntities
87
- end
88
- class Entities::SubEntities::ScE1 < Maestrano::Connector::Rails::SubEntityBase
89
- end
90
- class Entities::SubEntities::ScE2 < Maestrano::Connector::Rails::SubEntityBase
91
- end
92
- }
93
-
94
- describe 'get_connec_entities' do
95
- before {
96
- allow(subject.class).to receive(:connec_entities_names).and_return(%w(sc_e1 ScE2))
97
- }
98
-
99
- it 'calls get_connec_entities on each connec sub complex entities' do
100
- expect_any_instance_of(Entities::SubEntities::ScE1).to receive(:get_connec_entities).with(nil)
101
- expect_any_instance_of(Entities::SubEntities::ScE2).to receive(:get_connec_entities).with(nil)
102
- subject.get_connec_entities(nil)
103
- end
104
-
105
- let(:arr1) { [{'name' => 'Water'}, {'name' => 'Sugar'}] }
106
- let(:arr2) { [{'price' => 92}, {'price' => 300}] }
107
- it 'returns an hash of the connec_entities keyed by connec_entity_name' do
108
- allow_any_instance_of(Entities::SubEntities::ScE1).to receive(:get_connec_entities).and_return(arr1)
109
- allow_any_instance_of(Entities::SubEntities::ScE2).to receive(:get_connec_entities).and_return(arr2)
110
- expect(subject.get_connec_entities(nil)).to eql({'sc_e1' => arr1, 'ScE2' => arr2})
111
- end
112
- end
113
-
114
- describe 'get_external_entities' do
115
- before {
116
- allow(subject.class).to receive(:external_entities_names).and_return(%w(sc_e1 ScE2))
117
- }
118
-
119
- it 'calls get_external_entities on each connec sub complex entities' do
120
- expect_any_instance_of(Entities::SubEntities::ScE1).to receive(:get_external_entities_wrapper).with(nil, 'sc_e1')
121
- expect_any_instance_of(Entities::SubEntities::ScE2).to receive(:get_external_entities_wrapper).with(nil, 'ScE2')
122
- subject.get_external_entities_wrapper(nil)
123
- end
124
-
125
- let(:arr1) { [{'name' => 'Water'}, {'name' => 'Sugar'}] }
126
- let(:arr2) { [{'price' => 92}, {'price' => 300}] }
127
- it 'returns an hash of the external_entities keyed by external_entity_name' do
128
- allow_any_instance_of(Entities::SubEntities::ScE1).to receive(:get_external_entities_wrapper).and_return(arr1)
129
- allow_any_instance_of(Entities::SubEntities::ScE2).to receive(:get_external_entities_wrapper).and_return(arr2)
130
- expect(subject.get_external_entities_wrapper(nil)).to eql({'sc_e1' => arr1, 'ScE2' => arr2})
131
- end
132
- end
133
-
134
-
135
- describe 'consolidate and map methods' do
136
- let(:human_name) { 'Jabba' }
137
- let(:mapped_entity) { {mapped: 'entity'} }
138
- let(:date) { 2.hour.ago }
139
-
140
- describe 'consolidate_and_map_data' do
141
- before{
142
- allow(subject).to receive(:external_model_to_connec_model).and_return({})
143
- allow(subject).to receive(:connec_model_to_external_model).and_return({})
144
- }
145
-
146
- it 'calls external_model_to_connec_model' do
147
- expect(subject).to receive(:external_model_to_connec_model).with({a: {}}).and_return({})
148
- subject.consolidate_and_map_data({}, {a: {}})
149
- end
150
-
151
- it 'calls connec_model_to_external_model' do
152
- expect(subject).to receive(:connec_model_to_external_model).with({a: {}}).and_return({})
153
- subject.consolidate_and_map_data({a: {}}, {})
154
- end
155
-
156
- it 'calls the consolidation on both connec and external and returns an hash with the results' do
157
- expect(subject).to receive(:consolidate_and_map_connec_entities).with({}, {}).and_return({connec_result: 1})
158
- expect(subject).to receive(:consolidate_and_map_external_entities).with({}).and_return({ext_result: 1})
159
- expect(subject.consolidate_and_map_data({}, {})).to eql({connec_entities: {connec_result: 1}, external_entities: {ext_result: 1}})
160
- end
161
- end
162
-
163
- describe 'consolidate_and_map_external_entities' do
164
- let(:entity) { {'id' => id, 'name' => 'Jane'} }
165
- let(:id) { 'id' }
166
- let(:external_name) { 'sc_e1' }
167
- let(:connec_name) { 'connec1' }
168
- let(:modelled_external_entities) { {external_name => {connec_name => [entity]}} }
169
- before do
170
- allow(subject.class).to receive(:connec_entities_names).and_return(['connec1'])
171
- allow(subject.class).to receive(:external_entities_names).and_return(['sc_e1'])
172
- allow(Entities::SubEntities::ScE1).to receive(:external?).and_return(true)
173
- allow(Entities::SubEntities::ScE1).to receive(:entity_name).and_return(external_name)
174
- allow(Entities::SubEntities::ScE1).to receive(:id_from_external_entity_hash).and_return(id)
175
- allow(Entities::SubEntities::ScE1).to receive(:object_name_from_external_entity_hash).and_return(human_name)
176
- allow(Entities::SubEntities::ScE1).to receive(:last_update_date_from_external_entity_hash).and_return(date)
177
- allow_any_instance_of(Entities::SubEntities::ScE1).to receive(:map_to).and_return(mapped_entity)
178
- end
179
-
180
- context 'when idmap exists' do
181
- let!(:idmap) { create(:idmap, organization: organization, connec_entity: connec_name.downcase, external_entity: external_name.downcase, external_id: id) }
182
-
183
- it 'does not create one' do
184
- expect{
185
- subject.consolidate_and_map_external_entities(modelled_external_entities)
186
- }.to_not change{ Maestrano::Connector::Rails::IdMap.count }
187
- end
188
-
189
- it 'returns the mapped entity with the idmap' do
190
- expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => [{entity: mapped_entity, idmap: idmap}]}})
191
- end
192
-
193
- context 'when to_connec is false' do
194
- before { idmap.update(to_connec: false) }
195
-
196
- it 'discards the entity' do
197
- expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => []}})
198
- end
199
- end
200
-
201
- context 'when entity is inactive' do
202
- before { allow(Entities::SubEntities::ScE1).to receive(:inactive_from_external_entity_hash?).and_return(true)}
203
-
204
- it 'discards the entity' do
205
- expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => []}})
206
- end
207
-
208
- it 'updates the idmaps' do
209
- subject.consolidate_and_map_external_entities(modelled_external_entities)
210
- expect(idmap.reload.external_inactive).to be true
211
- end
212
- end
213
-
214
- context 'when last_push_to_connec is recent' do
215
- before { idmap.update(last_push_to_connec: 2.second.ago) }
216
-
217
- it 'discards the entity' do
218
- expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => []}})
219
- end
220
- end
221
-
222
- end
223
- end
224
-
225
- describe 'consolidate_and_map_connec_entities' do
226
- let(:id) { 'external-unfolded-id' }
227
- let(:connec_id) { 'connec-id' }
228
- let(:entity) { {'id' => id, 'name' => 'John', 'updated_at' => date} }
229
- let(:modelled_connec_entities) { {connec_name => {external_name => [entity]}} }
230
- let(:modelled_external_entities) { {} }
231
- let(:connec_name) { 'sc_e1' }
232
- let(:external_name) { 'ext1' }
233
- let(:id_refs_only_connec_entity) { {a: 1} }
234
- before do
235
- allow(subject.class).to receive(:connec_entities_names).and_return(['sc_e1'])
236
- allow(subject.class).to receive(:external_entities_names).and_return(['ext1'])
237
- allow(Entities::SubEntities::ScE1).to receive(:external?).and_return(false)
238
- allow(Entities::SubEntities::ScE1).to receive(:entity_name).and_return(connec_name)
239
- allow_any_instance_of(Entities::SubEntities::ScE1).to receive(:map_to).with(external_name, entity, first_time_synch).and_return(mapped_entity)
240
- allow(Entities::SubEntities::ScE1).to receive(:object_name_from_connec_entity_hash).and_return(human_name)
241
- allow(Maestrano::Connector::Rails::ConnecHelper).to receive(:unfold_references).and_return({entity: entity, connec_id: connec_id, id_refs_only_connec_entity: id_refs_only_connec_entity})
242
- end
243
-
244
- context 'when idmaps do not exist' do
245
- let(:first_time_synch) { true }
246
- it 'creates the idmaps with a name and returns the mapped entities with their idmaps' do
247
- expect{
248
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})).to eql({connec_name => {external_name => [{entity: {mapped: 'entity'}, idmap: Maestrano::Connector::Rails::IdMap.first, id_refs_only_connec_entity: id_refs_only_connec_entity}]}})
249
- }.to change{ Maestrano::Connector::Rails::IdMap.count }.by(1)
250
- expect(Maestrano::Connector::Rails::IdMap.last.name).to eql(human_name)
251
- end
252
- end
253
-
254
- context 'when idmap exists' do
255
- let!(:first_time_synch) { false }
256
- let!(:idmap1) { create(:idmap, organization: organization, connec_entity: connec_name.downcase, external_entity: external_name.downcase, external_id: id, connec_id: connec_id) }
257
-
258
- it 'does not create an idmap' do
259
- expect{
260
- subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})
261
- }.to_not change{ Maestrano::Connector::Rails::IdMap.count }
262
- end
263
-
264
- it 'returns the entity with its idmap' do
265
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})).to eql({connec_name => {external_name => [{entity: {mapped: 'entity'}, idmap: idmap1, id_refs_only_connec_entity: id_refs_only_connec_entity}]}})
266
- end
267
-
268
- context 'when external inactive' do
269
- before { idmap1.update(external_inactive: true) }
270
- it 'discards the entity' do
271
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})).to eql({connec_name => {external_name => []}})
272
- end
273
- end
274
-
275
- context 'when to external flag is false' do
276
- before { idmap1.update(to_external: false) }
277
- it 'discards the entity' do
278
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})).to eql({connec_name => {external_name => []}})
279
- end
280
- end
281
-
282
- context 'when last_push_to_external is recent' do
283
- before do
284
- idmap1.update(last_push_to_external: 2.second.ago)
285
- end
286
- it 'discards the entity' do
287
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})).to eql({connec_name => {external_name => []}})
288
- end
289
- end
290
-
291
- context 'when conflict' do
292
- let(:external_entity_1) { {'id' => id} }
293
- let(:modelled_external_entities) { {external_name => {connec_name => [external_entity_1]}} }
294
- before {
295
- allow(Entities::SubEntities::ScE1).to receive(:id_from_external_entity_hash).and_return(id)
296
- }
297
-
298
- context 'with opts' do
299
- context 'with connec preemption false' do
300
- it 'discards the entity and keep the external one' do
301
- subject.instance_variable_set(:@opts, {connec_preemption: false})
302
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, modelled_external_entities)).to eql({connec_name => {external_name => []}})
303
- expect(modelled_external_entities[external_name][connec_name]).to_not be_empty
304
- end
305
- end
306
-
307
- context 'with connec preemption true' do
308
- it 'keeps the entity and discards the external one' do
309
- subject.instance_variable_set(:@opts, {connec_preemption: true})
310
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, modelled_external_entities)).to eql({connec_name => {external_name => [{entity: {mapped: 'entity'}, idmap: Maestrano::Connector::Rails::IdMap.first, id_refs_only_connec_entity: id_refs_only_connec_entity}]}})
311
- expect(modelled_external_entities[external_name][connec_name]).to be_empty
312
- end
313
- end
314
- end
315
-
316
- context 'without opts' do
317
- before {
318
- allow(Entities::SubEntities::ScE1).to receive(:last_update_date_from_external_entity_hash).and_return(external_date)
319
- }
320
-
321
- context 'with connec one more recent' do
322
- let(:external_date) { 1.year.ago }
323
- let(:date) { 1.day.ago }
324
-
325
- it 'keeps the entity and discards the external one' do
326
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, modelled_external_entities)).to eql({connec_name => {external_name => [{entity: {mapped: 'entity'}, idmap: Maestrano::Connector::Rails::IdMap.first, id_refs_only_connec_entity: id_refs_only_connec_entity}]}})
327
- expect(modelled_external_entities[external_name][connec_name]).to be_empty
328
- end
329
- end
330
-
331
- context 'with external one more recent' do
332
- let(:external_date) { 1.month.ago }
333
- let(:date) { 1.year.ago }
334
-
335
- it 'discards the entity and keep the external one' do
336
- expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, modelled_external_entities)).to eql({connec_name => {external_name => []}})
337
- expect(modelled_external_entities[external_name][connec_name]).to_not be_empty
338
- end
339
- end
340
- end
341
- end
342
- end
343
- end
344
- end
345
-
346
-
347
- describe 'push_entities_to_connec' do
348
- let(:idmap) { nil }
349
- let(:mapped_entity_with_idmap) { {entity: {}, idmap: idmap} }
350
- let(:external_hash) {
351
- {
352
- 'sc_e1' => {'Connec1' => [mapped_entity_with_idmap]},
353
- 'ScE2' => {'Connec1' => [mapped_entity_with_idmap, mapped_entity_with_idmap], 'connec2' => [mapped_entity_with_idmap]}
354
- }
355
- }
356
-
357
- before {
358
- allow(subject.class).to receive(:external_entities_names).and_return(['sc_e1', 'ScE2'])
359
- allow(subject.class).to receive(:connec_entities_names).and_return(['Connec1', 'connec2'])
360
- }
361
-
362
- it 'calls push_entities_to_connec on each sub complex entity' do
363
- expect_any_instance_of(Entities::SubEntities::ScE1).to receive(:push_entities_to_connec_to).once.with([mapped_entity_with_idmap], 'Connec1')
364
- expect_any_instance_of(Entities::SubEntities::ScE2).to receive(:push_entities_to_connec_to).twice
365
- subject.push_entities_to_connec(external_hash)
366
- end
367
-
368
- describe 'full call' do
369
- let(:idmap) { create(:idmap, organization: organization) }
370
- before {
371
- [Entities::SubEntities::ScE1, Entities::SubEntities::ScE2].each do |klass|
372
- allow(klass).to receive(:external?).and_return(true)
373
- allow(klass).to receive(:entity_name).and_return('n')
374
- end
375
- allow(connec_client).to receive(:batch).and_return(ActionDispatch::Response.new(200, {}, {results: [{status: 200, body: {connec1s: {id: [{provider: 'connec', id: 'connec-id'}]}}}]}.to_json, {}), ActionDispatch::Response.new(200, {}, {results: [{status: 200, body: {connec1s: {id: [{provider: 'connec', id: 'connec-id'}]}}}]}.to_json, {}), ActionDispatch::Response.new(200, {}, {results: [{status: 200, body: {connec2s: {id: [{provider: 'connec', id: 'connec-id'}]}}}]}.to_json, {}))
376
- }
377
- it 'is successful' do
378
- subject.push_entities_to_connec(external_hash)
379
- idmap.reload
380
- expect(idmap.message).to be nil
381
- end
382
- end
383
- end
384
-
385
- describe 'push_entities_to_external' do
386
- let(:mapped_entity_with_idmap) { {entity: {}, idmap: nil} }
387
- let(:connec_hash) {
388
- {
389
- 'sc_e1' => {'ext1' => [mapped_entity_with_idmap]},
390
- 'ScE2' => {'ext1' => [mapped_entity_with_idmap, mapped_entity_with_idmap], 'ext2' => [mapped_entity_with_idmap]}
391
- }
392
- }
393
-
394
- before {
395
- allow(subject.class).to receive(:external_entities_names).and_return(['ext1', 'ext2'])
396
- allow(subject.class).to receive(:connec_entities_names).and_return(['sc_e1', 'ScE2'])
397
- }
398
-
399
- it 'calls push_entities_to_connec on each sub complex entity' do
400
- expect_any_instance_of(Entities::SubEntities::ScE1).to receive(:push_entities_to_external_to).once.with([mapped_entity_with_idmap], 'ext1')
401
- expect_any_instance_of(Entities::SubEntities::ScE2).to receive(:push_entities_to_external_to).twice
402
- subject.push_entities_to_external(connec_hash)
403
- end
404
- end
405
- end
406
- end
407
- end