maestrano-connector-rails 1.2.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +7 -20
  3. data/VERSION +1 -1
  4. data/app/controllers/maestrano/synchronizations_controller.rb +3 -3
  5. data/app/models/maestrano/connector/rails/concerns/complex_entity.rb +50 -22
  6. data/app/models/maestrano/connector/rails/concerns/connec_helper.rb +157 -19
  7. data/app/models/maestrano/connector/rails/concerns/entity.rb +63 -42
  8. data/app/models/maestrano/connector/rails/concerns/external.rb +4 -0
  9. data/app/models/maestrano/connector/rails/concerns/sub_entity_base.rb +18 -5
  10. data/app/models/maestrano/connector/rails/organization.rb +1 -1
  11. data/lib/generators/connector/templates/complex_entity_example/contact_and_lead.rb +5 -5
  12. data/lib/generators/connector/templates/entity.rb +4 -5
  13. data/lib/generators/connector/templates/external.rb +6 -0
  14. data/lib/generators/connector/templates/home_index.haml +7 -4
  15. data/maestrano-connector-rails.gemspec +7 -4
  16. data/release_notes.md +5 -0
  17. data/spec/factories.rb +2 -2
  18. data/spec/integration/complex_id_references_spec.rb +248 -0
  19. data/spec/integration/complex_naming_spec.rb +191 -0
  20. data/spec/integration/{integration_complex_spec.rb → complex_spec.rb} +9 -9
  21. data/spec/integration/connec_to_external_spec.rb +7 -3
  22. data/spec/integration/id_references_spec.rb +581 -0
  23. data/spec/integration/singleton_spec.rb +3 -3
  24. data/spec/models/complex_entity_spec.rb +42 -27
  25. data/spec/models/connec_helper_spec.rb +399 -31
  26. data/spec/models/entity_spec.rb +76 -21
  27. data/spec/models/external_spec.rb +4 -0
  28. data/spec/models/sub_entity_base_spec.rb +11 -4
  29. metadata +6 -3
@@ -148,7 +148,7 @@ describe 'singleton workflow' do
148
148
  it 'does the mapping correctly' do
149
149
  idmap = Entities::SingletonIntegration.create_idmap(organization_id: organization.id, external_id: ext_comp_id, connec_id: 'some connec id')
150
150
  allow(Entities::SingletonIntegration).to receive(:create_idmap).and_return(idmap)
151
- expect_any_instance_of(Entities::SingletonIntegration).to receive(:push_entities_to_external).with([{entity: {name: 'My awesome company'}, idmap: idmap}])
151
+ expect_any_instance_of(Entities::SingletonIntegration).to receive(:push_entities_to_external).with([{entity: {name: 'My awesome company'}, idmap: idmap, id_refs_only_connec_entity: {}}])
152
152
  subject
153
153
  end
154
154
 
@@ -207,7 +207,7 @@ describe 'singleton workflow' do
207
207
  end
208
208
 
209
209
  it 'does the mapping correctly' do
210
- expect_any_instance_of(Entities::SingletonIntegration).to receive(:push_entities_to_external).with([{entity: mapped_connec_entity, idmap: idmap}])
210
+ expect_any_instance_of(Entities::SingletonIntegration).to receive(:push_entities_to_external).with([{entity: mapped_connec_entity, idmap: idmap, id_refs_only_connec_entity: {}}])
211
211
  subject
212
212
  end
213
213
 
@@ -263,7 +263,7 @@ describe 'singleton workflow' do
263
263
  end
264
264
 
265
265
  it 'does the mapping correctly' do
266
- expect_any_instance_of(Entities::SingletonIntegration).to receive(:push_entities_to_external).with([{entity: mapped_connec_entity, idmap: idmap}])
266
+ expect_any_instance_of(Entities::SingletonIntegration).to receive(:push_entities_to_external).with([{entity: mapped_connec_entity, idmap: idmap, id_refs_only_connec_entity: {}}])
267
267
  subject
268
268
  end
269
269
  end
@@ -81,8 +81,8 @@ describe Maestrano::Connector::Rails::ComplexEntity do
81
81
  }
82
82
 
83
83
  it 'calls get_external_entities on each connec sub complex entities' do
84
- expect_any_instance_of(Entities::SubEntities::ScE1).to receive(:get_external_entities_wrapper).with(nil)
85
- expect_any_instance_of(Entities::SubEntities::ScE2).to receive(:get_external_entities_wrapper).with(nil)
84
+ expect_any_instance_of(Entities::SubEntities::ScE1).to receive(:get_external_entities_wrapper).with(nil, 'sc_e1')
85
+ expect_any_instance_of(Entities::SubEntities::ScE2).to receive(:get_external_entities_wrapper).with(nil, 'ScE2')
86
86
  subject.get_external_entities_wrapper(nil)
87
87
  end
88
88
 
@@ -129,8 +129,10 @@ describe Maestrano::Connector::Rails::ComplexEntity do
129
129
  let(:id) { 'id' }
130
130
  let(:external_name) { 'sc_e1' }
131
131
  let(:connec_name) { 'connec1' }
132
- let(:modeled_external_entities) { {external_name => {connec_name => [entity]}} }
132
+ let(:modelled_external_entities) { {external_name => {connec_name => [entity]}} }
133
133
  before {
134
+ allow(subject.class).to receive(:connec_entities_names).and_return(['connec1'])
135
+ allow(subject.class).to receive(:external_entities_names).and_return(['sc_e1'])
134
136
  allow(Entities::SubEntities::ScE1).to receive(:external?).and_return(true)
135
137
  allow(Entities::SubEntities::ScE1).to receive(:entity_name).and_return(external_name)
136
138
  allow(Entities::SubEntities::ScE1).to receive(:id_from_external_entity_hash).and_return(id)
@@ -144,19 +146,19 @@ describe Maestrano::Connector::Rails::ComplexEntity do
144
146
 
145
147
  it 'does not create one' do
146
148
  expect{
147
- subject.consolidate_and_map_external_entities(modeled_external_entities)
149
+ subject.consolidate_and_map_external_entities(modelled_external_entities)
148
150
  }.to_not change{ Maestrano::Connector::Rails::IdMap.count }
149
151
  end
150
152
 
151
153
  it 'returns the mapped entity with the idmap' do
152
- expect(subject.consolidate_and_map_external_entities(modeled_external_entities)).to eql({external_name => {connec_name => [{entity: mapped_entity, idmap: idmap}]}})
154
+ expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => [{entity: mapped_entity, idmap: idmap}]}})
153
155
  end
154
156
 
155
157
  context 'when to_connec is false' do
156
158
  before { idmap.update(to_connec: false) }
157
159
 
158
160
  it 'discards the entity' do
159
- expect(subject.consolidate_and_map_external_entities(modeled_external_entities)).to eql({external_name => {connec_name => []}})
161
+ expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => []}})
160
162
  end
161
163
  end
162
164
 
@@ -166,11 +168,11 @@ describe Maestrano::Connector::Rails::ComplexEntity do
166
168
  }
167
169
 
168
170
  it 'discards the entity' do
169
- expect(subject.consolidate_and_map_external_entities(modeled_external_entities)).to eql({external_name => {connec_name => []}})
171
+ expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => []}})
170
172
  end
171
173
 
172
174
  it 'updates the idmaps' do
173
- subject.consolidate_and_map_external_entities(modeled_external_entities)
175
+ subject.consolidate_and_map_external_entities(modelled_external_entities)
174
176
  expect(idmap.reload.external_inactive).to be true
175
177
  end
176
178
  end
@@ -179,7 +181,7 @@ describe Maestrano::Connector::Rails::ComplexEntity do
179
181
  before { idmap.update(last_push_to_connec: 2.second.ago) }
180
182
 
181
183
  it 'discards the entity' do
182
- expect(subject.consolidate_and_map_external_entities(modeled_external_entities)).to eql({external_name => {connec_name => []}})
184
+ expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => []}})
183
185
  end
184
186
  end
185
187
 
@@ -190,22 +192,25 @@ describe Maestrano::Connector::Rails::ComplexEntity do
190
192
  let(:id) { 'external-unfolded-id' }
191
193
  let(:connec_id) { 'connec-id' }
192
194
  let(:entity) { {'id' => id, 'name' => 'John', 'updated_at' => date} }
193
- let(:modeled_connec_entities) { {connec_name => {external_name => [entity]}} }
194
- let(:modeled_external_entities) { {} }
195
+ let(:modelled_connec_entities) { {connec_name => {external_name => [entity]}} }
196
+ let(:modelled_external_entities) { {} }
195
197
  let(:connec_name) { 'sc_e1' }
196
198
  let(:external_name) { 'ext1' }
199
+ let(:id_refs_only_connec_entity) { {a: 1} }
197
200
  before{
201
+ allow(subject.class).to receive(:connec_entities_names).and_return(['sc_e1'])
202
+ allow(subject.class).to receive(:external_entities_names).and_return(['ext1'])
198
203
  allow(Entities::SubEntities::ScE1).to receive(:external?).and_return(false)
199
204
  allow(Entities::SubEntities::ScE1).to receive(:entity_name).and_return(connec_name)
200
205
  allow_any_instance_of(Entities::SubEntities::ScE1).to receive(:map_to).with(external_name, entity).and_return(mapped_entity)
201
206
  allow(Entities::SubEntities::ScE1).to receive(:object_name_from_connec_entity_hash).and_return(human_name)
202
- allow(Maestrano::Connector::Rails::ConnecHelper).to receive(:unfold_references).and_return(entity.merge(__connec_id: connec_id))
207
+ 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})
203
208
  }
204
209
 
205
210
  context 'when idmaps do not exist' do
206
211
  it 'creates the idmaps with a name and returns the mapped entities with their idmaps' do
207
212
  expect{
208
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, {})).to eql({connec_name => {external_name => [{entity: {mapped: 'entity'}, idmap: Maestrano::Connector::Rails::IdMap.first}]}})
213
+ 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}]}})
209
214
  }.to change{ Maestrano::Connector::Rails::IdMap.count }.by(1)
210
215
  expect(Maestrano::Connector::Rails::IdMap.last.name).to eql(human_name)
211
216
  end
@@ -216,38 +221,38 @@ describe Maestrano::Connector::Rails::ComplexEntity do
216
221
 
217
222
  it 'does not create an idmap' do
218
223
  expect{
219
- subject.consolidate_and_map_connec_entities(modeled_connec_entities, {})
224
+ subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})
220
225
  }.to_not change{ Maestrano::Connector::Rails::IdMap.count }
221
226
  end
222
227
 
223
228
  it 'returns the entity with its idmap' do
224
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, {})).to eql({connec_name => {external_name => [{entity: {mapped: 'entity'}, idmap: idmap1}]}})
229
+ 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}]}})
225
230
  end
226
231
 
227
232
  context 'when external inactive' do
228
233
  before { idmap1.update(external_inactive: true) }
229
234
  it 'discards the entity' do
230
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, {})).to eql({connec_name => {external_name => []}})
235
+ expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})).to eql({connec_name => {external_name => []}})
231
236
  end
232
237
  end
233
238
 
234
239
  context 'when to external flag is false' do
235
240
  before { idmap1.update(to_external: false) }
236
241
  it 'discards the entity' do
237
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, {})).to eql({connec_name => {external_name => []}})
242
+ expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})).to eql({connec_name => {external_name => []}})
238
243
  end
239
244
  end
240
245
 
241
246
  context 'when last_push_to_external is recent' do
242
247
  before { idmap1.update(last_push_to_external: 2.second.ago) }
243
248
  it 'discards the entity' do
244
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, {})).to eql({connec_name => {external_name => []}})
249
+ expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, {})).to eql({connec_name => {external_name => []}})
245
250
  end
246
251
  end
247
252
 
248
253
  context 'when conflict' do
249
254
  let(:external_entity_1) { {'id' => id} }
250
- let(:modeled_external_entities) { {external_name => {connec_name => [external_entity_1]}} }
255
+ let(:modelled_external_entities) { {external_name => {connec_name => [external_entity_1]}} }
251
256
  before {
252
257
  allow(Entities::SubEntities::ScE1).to receive(:id_from_external_entity_hash).and_return(id)
253
258
  }
@@ -256,16 +261,16 @@ describe Maestrano::Connector::Rails::ComplexEntity do
256
261
  context 'with connec preemption false' do
257
262
  it 'discards the entity and keep the external one' do
258
263
  subject.instance_variable_set(:@opts, {connec_preemption: false})
259
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, modeled_external_entities)).to eql({connec_name => {external_name => []}})
260
- expect(modeled_external_entities[external_name][connec_name]).to_not be_empty
264
+ expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, modelled_external_entities)).to eql({connec_name => {external_name => []}})
265
+ expect(modelled_external_entities[external_name][connec_name]).to_not be_empty
261
266
  end
262
267
  end
263
268
 
264
269
  context 'with connec preemption true' do
265
270
  it 'keeps the entity and discards the external one' do
266
271
  subject.instance_variable_set(:@opts, {connec_preemption: true})
267
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, modeled_external_entities)).to eql({connec_name => {external_name => [{entity: {mapped: 'entity'}, idmap: Maestrano::Connector::Rails::IdMap.first}]}})
268
- expect(modeled_external_entities[external_name][connec_name]).to be_empty
272
+ 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}]}})
273
+ expect(modelled_external_entities[external_name][connec_name]).to be_empty
269
274
  end
270
275
  end
271
276
  end
@@ -280,8 +285,8 @@ describe Maestrano::Connector::Rails::ComplexEntity do
280
285
  let(:date) { 1.day.ago }
281
286
 
282
287
  it 'keeps the entity and discards the external one' do
283
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, modeled_external_entities)).to eql({connec_name => {external_name => [{entity: {mapped: 'entity'}, idmap: Maestrano::Connector::Rails::IdMap.first}]}})
284
- expect(modeled_external_entities[external_name][connec_name]).to be_empty
288
+ 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}]}})
289
+ expect(modelled_external_entities[external_name][connec_name]).to be_empty
285
290
  end
286
291
  end
287
292
 
@@ -290,8 +295,8 @@ describe Maestrano::Connector::Rails::ComplexEntity do
290
295
  let(:date) { 1.year.ago }
291
296
 
292
297
  it 'discards the entity and keep the external one' do
293
- expect(subject.consolidate_and_map_connec_entities(modeled_connec_entities, modeled_external_entities)).to eql({connec_name => {external_name => []}})
294
- expect(modeled_external_entities[external_name][connec_name]).to_not be_empty
298
+ expect(subject.consolidate_and_map_connec_entities(modelled_connec_entities, modelled_external_entities)).to eql({connec_name => {external_name => []}})
299
+ expect(modelled_external_entities[external_name][connec_name]).to_not be_empty
295
300
  end
296
301
  end
297
302
  end
@@ -311,6 +316,11 @@ describe Maestrano::Connector::Rails::ComplexEntity do
311
316
  }
312
317
  }
313
318
 
319
+ before {
320
+ allow(subject.class).to receive(:external_entities_names).and_return(['sc_e1', 'ScE2'])
321
+ allow(subject.class).to receive(:connec_entities_names).and_return(['Connec1', 'connec2'])
322
+ }
323
+
314
324
  it 'calls push_entities_to_connec on each sub complex entity' do
315
325
  expect_any_instance_of(Entities::SubEntities::ScE1).to receive(:push_entities_to_connec_to).once.with([mapped_entity_with_idmap], 'Connec1')
316
326
  expect_any_instance_of(Entities::SubEntities::ScE2).to receive(:push_entities_to_connec_to).twice
@@ -343,6 +353,11 @@ describe Maestrano::Connector::Rails::ComplexEntity do
343
353
  }
344
354
  }
345
355
 
356
+ before {
357
+ allow(subject.class).to receive(:external_entities_names).and_return(['ext1', 'ext2'])
358
+ allow(subject.class).to receive(:connec_entities_names).and_return(['sc_e1', 'ScE2'])
359
+ }
360
+
346
361
  it 'calls push_entities_to_connec on each sub complex entity' do
347
362
  expect_any_instance_of(Entities::SubEntities::ScE1).to receive(:push_entities_to_external_to).once.with([mapped_entity_with_idmap], 'ext1')
348
363
  expect_any_instance_of(Entities::SubEntities::ScE2).to receive(:push_entities_to_external_to).twice
@@ -54,68 +54,71 @@ describe Maestrano::Connector::Rails::ConnecHelper do
54
54
 
55
55
  let(:output_hash) {
56
56
  {
57
- __connec_id: 'abcd',
58
- id: id_id,
59
- organization_id: org_id_id,
60
- lines: [
61
- {
62
- linked_transaction: {
63
- id: lt1_id_id
57
+ connec_id: connec_id,
58
+ entity: {
59
+ id: id_id,
60
+ organization_id: org_id_id,
61
+ lines: [
62
+ {
63
+ linked_transaction: {
64
+ id: lt1_id_id
65
+ }
66
+ },
67
+ {
68
+ linked_transaction: {
69
+ id: lt2_id_id
70
+ }
64
71
  }
65
- },
66
- {
67
- linked_transaction: {
68
- id: lt2_id_id
69
- }
70
- }
71
- ]
72
+ ]
73
+ }.with_indifferent_access,
74
+ id_refs_only_connec_entity: {}
72
75
  }
73
76
  }
74
77
  let(:lt1_id_id) { 'lt1_id' }
75
78
  let(:lt2_id_id) { 'lt2_id' }
76
79
  let(:lt1_id) { [subject.id_hash(lt1_id_id, organization)] }
77
80
  let(:lt2_id) { [subject.id_hash(lt2_id_id, organization)] }
81
+ let(:connec_id) { 'cid1' }
82
+ let(:connec_org_id) { 'cid2' }
83
+ let(:org_id_id) { 'org_id' }
78
84
 
79
85
  context 'when all ids are here' do
80
86
  let(:id_id) { 'id' }
81
- let(:org_id_id) { 'org_id' }
82
- let(:id) { [subject.id_hash(id_id, organization), {'provider' => 'connec', 'id' => 'abcd'}] }
83
- let(:org_id) { [subject.id_hash(org_id_id, organization), {'provider' => 'connec', 'id' => 'abcd'}] }
87
+ let(:id) { [subject.id_hash(id_id, organization), {'provider' => 'connec', 'id' => connec_id}] }
88
+ let(:org_id) { [subject.id_hash(org_id_id, organization), {'provider' => 'connec', 'id' => connec_org_id}] }
84
89
 
85
90
  it 'unfolds everything' do
86
- expect(subject.unfold_references(connec_hash, ['organization_id', 'lines/linked_transaction/id'], organization)).to eql(output_hash.with_indifferent_access)
91
+ expect(subject.unfold_references(connec_hash, ['organization_id', 'lines/linked_transaction/id'], organization)).to eql(output_hash)
87
92
  end
88
93
  end
89
94
 
90
95
  context 'when only id is missing' do
91
96
  let(:id_id) { nil }
92
- let(:org_id_id) { 'org_id' }
93
- let(:id) { [{'provider' => 'connec', 'realm' => 'some realm', 'id' => 'id'}] }
97
+ let(:id) { [{'provider' => 'connec', 'realm' => 'some realm', 'id' => connec_id}] }
94
98
  let(:org_id) { [subject.id_hash(org_id_id, organization)] }
95
99
 
96
100
  it 'unfolds the other refs and keep the connec_id' do
97
- expect(subject.unfold_references(connec_hash, ['organization_id', 'lines/linked_transaction/id'], organization)).to eql(output_hash.merge(__connec_id: 'id').with_indifferent_access)
101
+ expect(subject.unfold_references(connec_hash, ['organization_id', 'lines/linked_transaction/id'], organization)).to eql(output_hash.merge(connec_id: connec_id))
98
102
  end
99
103
  end
100
104
 
101
105
  context 'when at least one ref is missing and there is a connec id' do
102
106
  let(:id_id) { nil }
103
- let(:org_id_id) { 'org_id' }
104
- let(:id) { [{'provider' => 'connec', 'realm' => 'some realm', 'id' => 'id'}] }
105
- let(:org_id) { [{'provider' => 'connec', 'realm' => 'some realm', 'id' => org_id_id}] }
107
+ let(:id) { [{'provider' => 'connec', 'realm' => 'some realm', 'id' => connec_id}] }
108
+ let(:org_id) { [{'provider' => 'connec', 'realm' => 'some realm', 'id' => connec_org_id}] }
106
109
 
107
110
  it 'returns nil' do
108
- expect(subject.unfold_references(connec_hash, ['organization_id', 'lines/linked_transaction/id'], organization)).to be_nil
111
+ expect(subject.unfold_references(connec_hash, ['organization_id', 'lines/linked_transaction/id'], organization)).to eql(output_hash.merge(entity: nil))
109
112
  end
110
113
  end
111
114
  context 'when at least one ref is missing but there is no connec id' do
112
115
  let(:id_id) { 'id' }
113
- let(:id) { [subject.id_hash(id_id, organization), {'provider' => 'connec', 'id' => 'abcd'}] }
116
+ let(:id) { [subject.id_hash(id_id, organization), {'provider' => 'connec', 'id' => connec_id}] }
114
117
  let(:org_id_id) { nil }
115
118
  let(:org_id) { nil }
116
119
 
117
120
  it 'unfold the others refs' do
118
- expect(subject.unfold_references(connec_hash, ['organization_id', 'lines/linked_transaction/id'], organization)).to eql(output_hash.merge(organization_id: nil).with_indifferent_access)
121
+ expect(subject.unfold_references(connec_hash, ['organization_id', 'lines/linked_transaction/id'], organization)).to eql(output_hash)
119
122
  end
120
123
  end
121
124
 
@@ -129,13 +132,16 @@ describe Maestrano::Connector::Rails::ConnecHelper do
129
132
 
130
133
  let(:output_hash) {
131
134
  {
132
- __connec_id: 'abcd',
133
- id: '123'
135
+ connec_id: 'abcd',
136
+ entity: {
137
+ id: '123'
138
+ }.with_indifferent_access,
139
+ id_refs_only_connec_entity: {}
134
140
  }
135
141
  }
136
142
 
137
- it 'let the string as it is' do
138
- expect(subject.unfold_references(connec_hash, ['organization_id'], organization)).to eql(output_hash.with_indifferent_access)
143
+ it 'ignores the string' do
144
+ expect(subject.unfold_references(connec_hash, ['organization_id'], organization)).to eql(output_hash)
139
145
  end
140
146
  end
141
147
  end
@@ -188,6 +194,10 @@ describe Maestrano::Connector::Rails::ConnecHelper do
188
194
  expect(subject.fold_references(mapped_hash, ['organization_id', 'contact/id', 'lines/id', 'not_here_ref'], organization)).to eql(output_hash.with_indifferent_access)
189
195
  end
190
196
 
197
+ it 'folds the existing refs (both id and record refs)' do
198
+ expect(subject.fold_references(mapped_hash, {record_references: %w(organization_id contact/id), id_references: %w(lines/id not_here_ref)}, organization)).to eql(output_hash.with_indifferent_access)
199
+ end
200
+
191
201
  context 'when id is an integer' do
192
202
  let(:id) { 1234 }
193
203
 
@@ -196,4 +206,362 @@ describe Maestrano::Connector::Rails::ConnecHelper do
196
206
  end
197
207
  end
198
208
  end
209
+
210
+ describe 'build_id_references_tree' do
211
+ let(:id_references) { %w(lines/id lines/linked/id lines/linked/id2 linked/id) }
212
+ let(:tree) {
213
+ {
214
+ "lines"=>{
215
+ "id"=>{},
216
+ "linked"=>{
217
+ "id"=>{},
218
+ "id2"=>{}
219
+ }
220
+ },
221
+ "linked"=>{
222
+ "id"=>{}
223
+ }
224
+ }
225
+ }
226
+
227
+ it 'returns the tree' do
228
+ expect(subject.build_id_references_tree(id_references)).to eql(tree)
229
+ end
230
+ end
231
+
232
+ describe 'format_references' do
233
+ context 'when array' do
234
+ it 'transforms it to an hash' do
235
+ expect(subject.format_references([1])).to eql({record_references: [1], id_references: []})
236
+ end
237
+ end
238
+
239
+ context 'when hash with both keys' do
240
+ let(:hash) { {id_references: [1], record_references: [2]} }
241
+ it 'returns it' do
242
+ expect(subject.format_references(hash)).to eql(hash)
243
+ end
244
+ end
245
+
246
+ context 'when hash with only one key' do
247
+ context 'when missing id_references' do
248
+ it 'returns the completed hash' do
249
+ expect(subject.format_references(record_references: [1])).to eql({record_references: [1], id_references: []})
250
+ end
251
+ end
252
+
253
+ context 'when missing record_references' do
254
+ it 'returns the completed hash' do
255
+ expect(subject.format_references(id_references: [1])).to eql({id_references: [1], record_references: []})
256
+ end
257
+ end
258
+ end
259
+ end
260
+
261
+ describe 'filter_connec_entity_for_id_refs' do
262
+ let(:connec_entity) {
263
+ {
264
+ id: [{"id"=>"001", "provider"=>"this_app", "realm"=>"sfuiy765"}],
265
+ name: "Brewer Supplies Ltd",
266
+ description: "We supply all things brewed\n",
267
+ lines: [
268
+ {
269
+ id: [{"id"=>"002", "provider"=>"this_app", "realm"=>"sfuiy765"}],
270
+ amount: 12,
271
+ linked: {
272
+ linked_transactions: [
273
+ {
274
+ class: 'Invoice',
275
+ id: [{"id"=>"003", "provider"=>"this_app", "realm"=>"sfuiy765"}],
276
+ id2: [{"id"=>"013", "provider"=>"this_app", "realm"=>"sfuiy765"}],
277
+ },
278
+ {
279
+ class: 'Sales order',
280
+ id: [{"id"=>"004", "provider"=>"this_app", "realm"=>"sfuiy765"}],
281
+ id2: [{"id"=>"014", "provider"=>"this_app", "realm"=>"sfuiy765"}],
282
+ }
283
+ ]
284
+ }
285
+ }
286
+ ],
287
+ linked_transactions: [
288
+ {
289
+ class: 'Test',
290
+ id: [{"id"=>"005", "provider"=>"this_app", "realm"=>"sfuiy765"}],
291
+ }
292
+ ]
293
+ }
294
+ }
295
+
296
+ context 'with id_references' do
297
+ let(:id_references) { %w(lines/id lines/linked/linked_transactions/id lines/linked/linked_transactions/id2 linked_transactions/id) }
298
+ let(:filtered_connec_entity) {
299
+ {
300
+ lines: [
301
+ {
302
+ id: [{"id"=>"002", "provider"=>"this_app", "realm"=>"sfuiy765"}],
303
+ linked: {
304
+ linked_transactions: [
305
+ {
306
+ id: [{"id"=>"003", "provider"=>"this_app", "realm"=>"sfuiy765"}],
307
+ id2: [{"id"=>"013", "provider"=>"this_app", "realm"=>"sfuiy765"}],
308
+ },
309
+ {
310
+ id: [{"id"=>"004", "provider"=>"this_app", "realm"=>"sfuiy765"}],
311
+ id2: [{"id"=>"014", "provider"=>"this_app", "realm"=>"sfuiy765"}],
312
+ }
313
+ ]
314
+ }
315
+ }
316
+ ],
317
+ linked_transactions: [
318
+ {
319
+ id: [{"id"=>"005", "provider"=>"this_app", "realm"=>"sfuiy765"}],
320
+ }
321
+ ]
322
+ }.with_indifferent_access
323
+ }
324
+
325
+ it 'returns the connec_entity with only the relevant keys' do
326
+ expect(subject.filter_connec_entity_for_id_refs(connec_entity, id_references)).to eql(filtered_connec_entity)
327
+ end
328
+ end
329
+
330
+ context 'without id_references' do
331
+ it 'returns an empty hash' do
332
+ expect(subject.filter_connec_entity_for_id_refs(connec_entity, [])).to eql({})
333
+ end
334
+ end
335
+ end
336
+
337
+ describe 'value from hash' do
338
+ let(:hash) {
339
+ {
340
+ lines: [
341
+ {
342
+ linked: [
343
+ {
344
+ a: {
345
+ b: [1]
346
+ }
347
+ }
348
+ ]
349
+ },
350
+ {
351
+ linked: [
352
+ {
353
+ a: {
354
+ b: [2]
355
+ }
356
+ },
357
+ {
358
+ a: {
359
+ b: [3]
360
+ }
361
+ }
362
+ ]
363
+ },
364
+ ]
365
+ }
366
+ }
367
+
368
+ let(:path) { [:lines, 1,:linked, 0, :a, :b] }
369
+
370
+ it 'returns the value from the path' do
371
+ expect(subject.value_from_hash(hash, path)).to eql([2])
372
+ end
373
+
374
+ context 'when the path leads to nowhere' do
375
+ context 'with a wrong array' do
376
+ let(:hash) {
377
+ {
378
+ lines: [
379
+ {
380
+ linked: [
381
+ {
382
+ a: {
383
+ b: [1]
384
+ }
385
+ }
386
+ ]
387
+ },
388
+ ]
389
+ }
390
+ }
391
+
392
+ it 'returns nil' do
393
+ expect(subject.value_from_hash(hash, path)).to eql(nil)
394
+ end
395
+ end
396
+
397
+ context 'with a wrong hash' do
398
+ let(:hash) {
399
+ {
400
+ lines: [
401
+ {
402
+ },
403
+ {
404
+ linked: [
405
+ {
406
+ },
407
+ {
408
+ }
409
+ ]
410
+ },
411
+ ]
412
+ }
413
+ }
414
+
415
+ it 'returns nil' do
416
+ expect(subject.value_from_hash(hash, path)).to eql(nil)
417
+ end
418
+ end
419
+ end
420
+ end
421
+
422
+ describe 'merge_id_hashes' do
423
+ let(:dist) {
424
+ {
425
+ lines: [
426
+ {
427
+ id: [{"id"=>"002", "provider"=>"connec", "realm"=>"org-123"}],
428
+ linked: {
429
+ linked_transactions: [
430
+ {
431
+ id: [{"id"=>"003", "provider"=>"connec", "realm"=>"org-123"}],
432
+ id2: [{"id"=>"013", "provider"=>"connec", "realm"=>"org-123"}],
433
+ },
434
+ {
435
+ id: [{"id"=>"004", "provider"=>"connec", "realm"=>"org-123"}],
436
+ id2: [{"id"=>"014", "provider"=>"connec", "realm"=>"org-123"}],
437
+ }
438
+ ]
439
+ }
440
+ }
441
+ ],
442
+ linked_transactions: [
443
+ {
444
+ id: [{"id"=>"005", "provider"=>"connec", "realm"=>"org-123"}],
445
+ }
446
+ ]
447
+ }
448
+ }
449
+
450
+ let(:src) {
451
+ {
452
+ title: 'Title',
453
+ lines: [
454
+ {
455
+ amount: 123,
456
+ id: [{"id"=>"002", "provider"=>"this-app", "realm"=>"6543"}],
457
+ linked: {
458
+ linked_transactions: [
459
+ {
460
+ class: 'Invoice',
461
+ id: [{"id"=>"003", "provider"=>"this-app", "realm"=>"6543"}],
462
+ id2: [{"id"=>"013", "provider"=>"this-app", "realm"=>"6543"}],
463
+ },
464
+ {
465
+ class: 'Sales Order',
466
+ id: [{"id"=>"004", "provider"=>"this-app", "realm"=>"6543"}],
467
+ id2: [{"id"=>"014", "provider"=>"this-app", "realm"=>"6543"}],
468
+ }
469
+ ]
470
+ }
471
+ }
472
+ ],
473
+ linked_transactions: [
474
+ {
475
+ class: 'Payment',
476
+ id: [{"id"=>"005", "provider"=>"this-app", "realm"=>"6543"}],
477
+ }
478
+ ]
479
+ }
480
+ }
481
+
482
+ let(:id_references) {
483
+ %w(lines/id lines/linked/linked_transactions/id lines/linked/linked_transactions/id2 linked_transactions/id)
484
+ }
485
+
486
+ let(:output_hash) {
487
+ {
488
+ lines: [
489
+ {
490
+ id: [{"id"=>"002", "provider"=>"connec", "realm"=>"org-123"}, {"id"=>"002", "provider"=>"this-app", "realm"=>"6543"}],
491
+ linked: {
492
+ linked_transactions: [
493
+ {
494
+ id: [{"id"=>"003", "provider"=>"connec", "realm"=>"org-123"}, {"id"=>"003", "provider"=>"this-app", "realm"=>"6543"}],
495
+ id2: [{"id"=>"013", "provider"=>"connec", "realm"=>"org-123"}, {"id"=>"013", "provider"=>"this-app", "realm"=>"6543"}],
496
+ },
497
+ {
498
+ id: [{"id"=>"004", "provider"=>"connec", "realm"=>"org-123"}, {"id"=>"004", "provider"=>"this-app", "realm"=>"6543"}],
499
+ id2: [{"id"=>"014", "provider"=>"connec", "realm"=>"org-123"}, {"id"=>"014", "provider"=>"this-app", "realm"=>"6543"}],
500
+ }
501
+ ]
502
+ }
503
+ }
504
+ ],
505
+ linked_transactions: [
506
+ {
507
+ id: [{"id"=>"005", "provider"=>"connec", "realm"=>"org-123"}, {"id"=>"005", "provider"=>"this-app", "realm"=>"6543"}],
508
+ }
509
+ ]
510
+ }.with_indifferent_access
511
+ }
512
+
513
+ it 'merge the id from the src to the dist' do
514
+ expect(subject.merge_id_hashes(dist, src, id_references)).to eql(output_hash)
515
+ end
516
+
517
+ describe 'edge cases' do
518
+ context 'uncomplete src' do
519
+ describe 'when an id is missing in an array' do
520
+ before {
521
+ src[:linked_transactions] = []
522
+ output_hash[:linked_transactions].first.delete(:id)
523
+ }
524
+
525
+ it 'does not merge this id' do
526
+ expect(subject.merge_id_hashes(dist, src, id_references)).to eql(output_hash)
527
+ end
528
+ end
529
+
530
+ describe 'when an id is missing in a hash' do
531
+ before {
532
+ src[:lines].first.delete(:id)
533
+ output_hash[:lines].first.delete(:id)
534
+ }
535
+
536
+ it 'does not merge this id' do
537
+ expect(subject.merge_id_hashes(dist, src, id_references)).to eql(output_hash)
538
+ end
539
+ end
540
+ end
541
+
542
+ context 'uncomplete dist' do
543
+ describe 'when an id is missing in an array' do
544
+ before {
545
+ dist[:linked_transactions] = []
546
+ output_hash[:linked_transactions] = []
547
+ }
548
+
549
+ it 'does not merge this id' do
550
+ expect(subject.merge_id_hashes(dist, src, id_references)).to eql(output_hash)
551
+ end
552
+ end
553
+
554
+ describe 'when an id is missing in a hash' do
555
+ before {
556
+ dist[:lines].first.delete(:id)
557
+ output_hash[:lines].first.delete(:id)
558
+ }
559
+
560
+ it 'does not merge this id' do
561
+ expect(subject.merge_id_hashes(dist, src, id_references)).to eql(output_hash)
562
+ end
563
+ end
564
+ end
565
+ end
566
+ end
199
567
  end