lhs 0.3.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 (122) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +38 -0
  3. data/Gemfile +11 -0
  4. data/README.md +67 -0
  5. data/Rakefile +26 -0
  6. data/docs/collections.md +28 -0
  7. data/docs/data.md +39 -0
  8. data/docs/examples/claim_no_include.json +16 -0
  9. data/docs/examples/claim_with_include.json +47 -0
  10. data/docs/items.md +55 -0
  11. data/docs/service.jpg +0 -0
  12. data/docs/service.pdf +649 -3
  13. data/docs/services.md +191 -0
  14. data/lhs.gemspec +31 -0
  15. data/lib/lhs.rb +6 -0
  16. data/lib/lhs/collection.rb +78 -0
  17. data/lib/lhs/concerns/data/json.rb +12 -0
  18. data/lib/lhs/concerns/item/destroy.rb +15 -0
  19. data/lib/lhs/concerns/item/save.rb +29 -0
  20. data/lib/lhs/concerns/item/update.rb +24 -0
  21. data/lib/lhs/concerns/service/all.rb +24 -0
  22. data/lib/lhs/concerns/service/batch.rb +37 -0
  23. data/lib/lhs/concerns/service/build.rb +17 -0
  24. data/lib/lhs/concerns/service/create.rb +26 -0
  25. data/lib/lhs/concerns/service/endpoints.rb +82 -0
  26. data/lib/lhs/concerns/service/find.rb +36 -0
  27. data/lib/lhs/concerns/service/find_by.rb +35 -0
  28. data/lib/lhs/concerns/service/first.rb +19 -0
  29. data/lib/lhs/concerns/service/includes.rb +21 -0
  30. data/lib/lhs/concerns/service/mapping.rb +23 -0
  31. data/lib/lhs/concerns/service/model.rb +16 -0
  32. data/lib/lhs/concerns/service/request.rb +96 -0
  33. data/lib/lhs/concerns/service/where.rb +16 -0
  34. data/lib/lhs/data.rb +103 -0
  35. data/lib/lhs/errors.rb +86 -0
  36. data/lib/lhs/item.rb +83 -0
  37. data/lib/lhs/proxy.rb +26 -0
  38. data/lib/lhs/service.rb +20 -0
  39. data/lib/lhs/version.rb +3 -0
  40. data/script/ci/build.sh +19 -0
  41. data/spec/collection/meta_data_spec.rb +54 -0
  42. data/spec/collection/respond_to_spec.rb +19 -0
  43. data/spec/collection/without_object_items_spec.rb +26 -0
  44. data/spec/data/collection_spec.rb +36 -0
  45. data/spec/data/item_spec.rb +44 -0
  46. data/spec/data/merge_spec.rb +32 -0
  47. data/spec/data/raw_spec.rb +39 -0
  48. data/spec/data/respond_to_spec.rb +26 -0
  49. data/spec/data/root_spec.rb +25 -0
  50. data/spec/data/to_json_spec.rb +39 -0
  51. data/spec/dummy/README.rdoc +28 -0
  52. data/spec/dummy/Rakefile +6 -0
  53. data/spec/dummy/app/assets/images/.keep +0 -0
  54. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  55. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  56. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  57. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  58. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  59. data/spec/dummy/app/mailers/.keep +0 -0
  60. data/spec/dummy/app/models/.keep +0 -0
  61. data/spec/dummy/app/models/concerns/.keep +0 -0
  62. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  63. data/spec/dummy/bin/bundle +3 -0
  64. data/spec/dummy/bin/rails +4 -0
  65. data/spec/dummy/bin/rake +4 -0
  66. data/spec/dummy/config.ru +4 -0
  67. data/spec/dummy/config/application.rb +14 -0
  68. data/spec/dummy/config/boot.rb +5 -0
  69. data/spec/dummy/config/environment.rb +5 -0
  70. data/spec/dummy/config/environments/development.rb +34 -0
  71. data/spec/dummy/config/environments/production.rb +75 -0
  72. data/spec/dummy/config/environments/test.rb +39 -0
  73. data/spec/dummy/config/initializers/assets.rb +8 -0
  74. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  75. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  76. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  77. data/spec/dummy/config/initializers/inflections.rb +16 -0
  78. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  79. data/spec/dummy/config/initializers/session_store.rb +3 -0
  80. data/spec/dummy/config/initializers/wrap_parameters.rb +9 -0
  81. data/spec/dummy/config/locales/en.yml +23 -0
  82. data/spec/dummy/config/routes.rb +56 -0
  83. data/spec/dummy/config/secrets.yml +22 -0
  84. data/spec/dummy/lib/assets/.keep +0 -0
  85. data/spec/dummy/public/404.html +67 -0
  86. data/spec/dummy/public/422.html +67 -0
  87. data/spec/dummy/public/500.html +66 -0
  88. data/spec/dummy/public/favicon.ico +0 -0
  89. data/spec/item/destroy_spec.rb +39 -0
  90. data/spec/item/getter_spec.rb +24 -0
  91. data/spec/item/respond_to_spec.rb +29 -0
  92. data/spec/item/save_errors_spec.rb +48 -0
  93. data/spec/item/save_spec.rb +58 -0
  94. data/spec/item/setter_spec.rb +38 -0
  95. data/spec/item/update_spec.rb +56 -0
  96. data/spec/proxy/load_spec.rb +47 -0
  97. data/spec/rails_helper.rb +9 -0
  98. data/spec/service/all_spec.rb +31 -0
  99. data/spec/service/build_spec.rb +25 -0
  100. data/spec/service/create_spec.rb +81 -0
  101. data/spec/service/creation_failed_spec.rb +54 -0
  102. data/spec/service/endpoint_misconfiguration_spec.rb +26 -0
  103. data/spec/service/endpoint_options_spec.rb +23 -0
  104. data/spec/service/endpoints_spec.rb +57 -0
  105. data/spec/service/find_by_spec.rb +49 -0
  106. data/spec/service/find_each_spec.rb +47 -0
  107. data/spec/service/find_in_batches_spec.rb +68 -0
  108. data/spec/service/find_spec.rb +71 -0
  109. data/spec/service/first_spec.rb +39 -0
  110. data/spec/service/includes_spec.rb +61 -0
  111. data/spec/service/mapping_spec.rb +72 -0
  112. data/spec/service/model_name_spec.rb +17 -0
  113. data/spec/service/request_spec.rb +22 -0
  114. data/spec/service/where_spec.rb +33 -0
  115. data/spec/spec_helper.rb +4 -0
  116. data/spec/support/cleanup_configuration.rb +17 -0
  117. data/spec/support/cleanup_services.rb +20 -0
  118. data/spec/support/fixtures/json/feedback.json +11 -0
  119. data/spec/support/fixtures/json/feedbacks.json +174 -0
  120. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  121. data/spec/support/load_json.rb +3 -0
  122. metadata +346 -0
@@ -0,0 +1,48 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Item do
4
+
5
+ context 'save failed' do
6
+
7
+ let(:datastore) { 'http://datastore-stg.lb-service.sunrise.intra.local.ch/v2' }
8
+
9
+ before(:each) do
10
+ LHC.config.placeholder(:datastore, datastore)
11
+ class SomeService < LHS::Service
12
+ endpoint ':datastore/:campaign_id/feedbacks'
13
+ endpoint ':datastore/feedbacks'
14
+ end
15
+ end
16
+
17
+ let(:save_error) do
18
+ {
19
+ "status" => 400,
20
+ "message" => "ratings must be set when review or name or review_title is set | The property value is required; it cannot be null, empty, or blank.",
21
+ "fields" => [
22
+ {
23
+ "name" => "ratings",
24
+ "details" => [{ "code" => "REQUIRED_PROPERTY_VALUE" }]
25
+ },{
26
+ "name" => "recommended",
27
+ "details" => [{"code" => "REQUIRED_PROPERTY_VALUE"}]
28
+ }
29
+ ]
30
+ }
31
+ end
32
+
33
+ it 'provides errors when creation failed' do
34
+ stub_request(:post, "#{datastore}/feedbacks")
35
+ .to_return(status: 400, body: save_error.to_json)
36
+ record = SomeService.build
37
+ record.name = 'Steve'
38
+ result = record.save
39
+ expect(result).to eq false
40
+ expect(record.errors).to be
41
+ expect(record.name).to eq 'Steve'
42
+ expect(record.errors.include?(:ratings)).to eq true
43
+ expect(record.errors.include?(:recommended)).to eq true
44
+ expect(record.errors[:ratings]).to eq ['REQUIRED_PROPERTY_VALUE']
45
+ expect(record.errors[:recommended]).to eq ['REQUIRED_PROPERTY_VALUE']
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,58 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Item do
4
+
5
+ before(:each) do
6
+ class SomeService < LHS::Service
7
+ endpoint ':datastore/v2/:campaign_id/feedbacks'
8
+ endpoint ':datastore/v2/feedbacks'
9
+ end
10
+ end
11
+
12
+ let(:json) do
13
+ load_json(:feedbacks)
14
+ end
15
+
16
+ let(:data) do
17
+ LHS::Data.new(json, nil, SomeService)
18
+ end
19
+
20
+ let(:item) do
21
+ data[0]
22
+ end
23
+
24
+ context 'save' do
25
+
26
+ it 'persists changes on the backend' do
27
+ stub_request(:post, item.href)
28
+ .with(body: item._raw.merge(name: 'Steve').to_json)
29
+ item.name = 'Steve'
30
+ expect(item.save).to eq true
31
+ end
32
+
33
+ it 'returns false if persting goes wrong' do
34
+ stub_request(:post, item.href)
35
+ .with(body: item._raw.to_json)
36
+ .to_return(status: 500)
37
+ expect(item.save).to eq false
38
+ end
39
+
40
+ it 'merges reponse data with object' do
41
+ stub_request(:post, item.href)
42
+ .with(body: item._raw.to_json)
43
+ .to_return(status: 200, body: item._raw.merge(name: 'Steve').to_json)
44
+ item.save
45
+ expect(item.name).to eq 'Steve'
46
+ end
47
+ end
48
+
49
+ context 'save!' do
50
+
51
+ it 'raises if something goes wrong' do
52
+ stub_request(:post, item.href)
53
+ .with(body: item._raw.to_json)
54
+ .to_return(status: 500)
55
+ expect(->{ item.save! }).to raise_error LHC::ServerError
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,38 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Item do
4
+
5
+ before(:each) do
6
+ class SomeService < LHS::Service
7
+ endpoint ':datastore/v2/:campaign_id/feedbacks'
8
+ endpoint ':datastore/v2/feedbacks'
9
+ end
10
+ end
11
+
12
+ let(:json) do
13
+ load_json(:feedbacks)
14
+ end
15
+
16
+ let(:data) do
17
+ LHS::Data.new(json, nil, SomeService)
18
+ end
19
+
20
+ let(:item) do
21
+ data[0]
22
+ end
23
+
24
+ context 'item setter' do
25
+
26
+ it 'sets the value for an existing attribute' do
27
+ expect(item.name = 'Steve').to eq 'Steve'
28
+ expect(item.name).to eq 'Steve'
29
+ expect(item._raw['name']).to eq 'Steve'
30
+ end
31
+
32
+ it 'sets things to nil' do
33
+ item.name = 'Steve'
34
+ expect(item.name = nil).to eq nil
35
+ expect(item.name).to eq nil
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,56 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Item do
4
+
5
+ before(:each) do
6
+ class SomeService < LHS::Service
7
+ endpoint ':datastore/v2/:campaign_id/feedbacks'
8
+ endpoint ':datastore/v2/feedbacks'
9
+ end
10
+ end
11
+
12
+ let(:json) do
13
+ load_json(:feedbacks)
14
+ end
15
+
16
+ let(:data) do
17
+ LHS::Data.new(json, nil, SomeService)
18
+ end
19
+
20
+ let(:item) do
21
+ data[0]
22
+ end
23
+
24
+ context 'update' do
25
+
26
+ it 'persists changes on the backend' do
27
+ stub_request(:post, item.href)
28
+ .with(body: item._raw.merge(name: 'Steve').to_json)
29
+ result = item.update(name: 'Steve')
30
+ expect(result).to eq true
31
+ end
32
+
33
+ it 'returns false if persisting went wrong' do
34
+ stub_request(:post, item.href).to_return(status: 500)
35
+ result = item.update(name: 'Steve')
36
+ expect(result).to eq false
37
+ end
38
+
39
+ it 'merges reponse data with object' do
40
+ stub_request(:post, item.href)
41
+ .to_return(status: 200, body: item._raw.merge(likes: 'Banana').to_json)
42
+ item.update(name: 'Steve')
43
+ expect(item.likes).to eq 'Banana'
44
+ end
45
+ end
46
+
47
+ context 'update!' do
48
+
49
+ it 'raises if something goes wrong' do
50
+ stub_request(:post, item.href)
51
+ .with(body: item._raw.merge(name: 'Steve').to_json)
52
+ .to_return(status: 500)
53
+ expect(->{ item.update!(name: 'Steve') }).to raise_error LHC::ServerError
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,47 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Proxy do
4
+
5
+ before(:each) do
6
+ class SomeService < LHS::Service
7
+ endpoint ':datastore/v2/feedbacks'
8
+ end
9
+ end
10
+
11
+ let(:json) do
12
+ load_json(:feedbacks)
13
+ end
14
+
15
+ let(:data) do
16
+ LHS::Data.new(json, nil, SomeService)
17
+ end
18
+
19
+ let(:item) do
20
+ data[0]
21
+ end
22
+
23
+ let(:link) do
24
+ item.campaign
25
+ end
26
+
27
+ before(:each) do
28
+ stub_request(:get, 'http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc5690cf271c375c5a12d')
29
+ .to_return(status: 200, body: load_json(:localina_content_ad))
30
+ end
31
+
32
+ context 'load' do
33
+
34
+ it 'is loading data remotely when not present yet' do
35
+ link.load!.id
36
+ end
37
+
38
+ it 'can be reloaded' do
39
+ link.load!.id
40
+ stub_request(:get, 'http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/content-ads/51dfc5690cf271c375c5a12d')
41
+ .to_return(status: 404)
42
+ link.load!.id
43
+ expect(-> { link.reload!.id })
44
+ .to raise_error LHC::NotFound
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ require File.expand_path("../dummy/config/environment", __FILE__)
3
+ require 'rspec/rails'
4
+
5
+ ENV["RAILS_ENV"] ||= 'test'
6
+
7
+ RSpec.configure do |config|
8
+ config.infer_spec_type_from_file_location!
9
+ end
@@ -0,0 +1,31 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Collection do
4
+
5
+ let(:datastore) { 'http://datastore-stg.lb-service.sunrise.intra.local.ch/v2' }
6
+
7
+ before(:each) do
8
+ LHC.config.placeholder('datastore', datastore)
9
+ class SomeService < LHS::Service
10
+ endpoint ':datastore/:campaign_id/feedbacks'
11
+ endpoint ':datastore/feedbacks'
12
+ end
13
+ end
14
+
15
+ context 'all' do
16
+
17
+ it 'fetches all records from the backend' do
18
+ stub_request(:get, "#{datastore}/feedbacks?limit=100")
19
+ .to_return(status: 200, body: {items: (1..100).to_a, total: 300, limit: 100, offset: 0}.to_json)
20
+ stub_request(:get, "#{datastore}/feedbacks?limit=100&offset=101")
21
+ .to_return(status: 200, body: {items: (101..200).to_a, total: 300, limit: 100, offset: 101}.to_json)
22
+ stub_request(:get, "#{datastore}/feedbacks?limit=100&offset=201")
23
+ .to_return(status: 200, body: {items: (201..300).to_a, total: 300, limit: 100, offset: 201}.to_json)
24
+ all = SomeService.all
25
+ expect(all).to be_kind_of LHS::Data
26
+ expect(all._proxy).to be_kind_of LHS::Collection
27
+ expect(all.count).to eq 300
28
+ expect(all[299]).to eq 300
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Service do
4
+
5
+ context 'new' do
6
+
7
+ let(:datastore) { 'http://datastore-stg.lb-service.sunrise.intra.local.ch/v2' }
8
+
9
+ before(:each) do
10
+ LHC.config.placeholder('datastore', datastore)
11
+ class Feedback < LHS::Service
12
+ endpoint ':datastore/content-ads/:campaign_id/feedbacks'
13
+ endpoint ':datastore/feedbacks'
14
+ end
15
+ end
16
+
17
+ it 'builds a new item from scratch' do
18
+ feedback = Feedback.build recommended: true
19
+ expect(feedback.recommended).to eq true
20
+ stub_request(:post, "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks")
21
+ .with(body: "{\"recommended\":true}")
22
+ feedback.save
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,81 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Service do
4
+
5
+ context 'create' do
6
+
7
+ let(:datastore) { 'http://datastore-stg.lb-service.sunrise.intra.local.ch/v2' }
8
+
9
+ before(:each) do
10
+ LHC.config.placeholder('datastore', datastore)
11
+ class Feedback < LHS::Service
12
+ endpoint ':datastore/content-ads/:campaign_id/feedbacks'
13
+ endpoint ':datastore/feedbacks'
14
+ end
15
+ end
16
+
17
+ let(:object) do
18
+ {
19
+ recommended: true,
20
+ source_id: 'aaa'
21
+ }
22
+ end
23
+
24
+ it 'creates new record on the backend' do
25
+ stub_request(:post, "#{datastore}/feedbacks")
26
+ .with(body: object.to_json)
27
+ .to_return(status: 200, body: object.to_json)
28
+ record = Feedback.create(object)
29
+ expect(record.recommended).to eq true
30
+ expect(record.errors).to eq nil
31
+ end
32
+
33
+ it 'uses proper endpoint when creating data' do
34
+ stub_request(:post, "#{datastore}/content-ads/12345/feedbacks")
35
+ .with(body: object.to_json)
36
+ .to_return(status: 200, body: object.to_json)
37
+ Feedback.create(object.merge(campaign_id: '12345'))
38
+ end
39
+
40
+ it 'merges backend response object with object' do
41
+ body = object.merge(additional_key: 1)
42
+ stub_request(:post, "#{datastore}/content-ads/12345/feedbacks")
43
+ .with(body: object.to_json)
44
+ .to_return(status: 200, body: body.to_json)
45
+ data = Feedback.create(object.merge(campaign_id: '12345'))
46
+ expect(data.additional_key).to eq 1
47
+ end
48
+
49
+ context 'creation errors' do
50
+ let(:creation_error) do
51
+ {
52
+ "status" => 400,
53
+ "fields" => [
54
+ {
55
+ "name" => "ratings",
56
+ "details" => [{ "code" => "REQUIRED_PROPERTY_VALUE" }]
57
+ },{
58
+ "name" => "recommended",
59
+ "details" => [{"code" => "REQUIRED_PROPERTY_VALUE"}]
60
+ }
61
+ ]
62
+ }
63
+ end
64
+
65
+ it 'provides errors accessor on the record when creation failed using create' do
66
+ stub_request(:post, "#{datastore}/content-ads/12345/feedbacks")
67
+ .to_return(status: 400, body: creation_error.to_json)
68
+ feedback = Feedback.create(object.merge(campaign_id: '12345'))
69
+ expect(feedback.errors).to be_kind_of LHS::Errors
70
+ end
71
+
72
+ it 'raises an exception when creation failed using create!' do
73
+ stub_request(:post, "#{datastore}/content-ads/12345/feedbacks")
74
+ .to_return(status: 400, body: creation_error.to_json)
75
+ expect(->{
76
+ Feedback.create!(object.merge(campaign_id: '12345'))
77
+ }).to raise_error
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,54 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Service do
4
+
5
+ context 'creation failed' do
6
+
7
+ let(:datastore) { 'http://datastore-stg.lb-service.sunrise.intra.local.ch/v2' }
8
+
9
+ before(:each) do
10
+ LHC.config.placeholder(:datastore, datastore)
11
+ class SomeService < LHS::Service
12
+ endpoint ':datastore/:campaign_id/feedbacks'
13
+ endpoint ':datastore/feedbacks'
14
+ end
15
+ end
16
+
17
+ let(:error_message) { "ratings must be set when review or name or review_title is set | The property value is required; it cannot be null, empty, or blank." }
18
+
19
+ let(:creation_error) do
20
+ {
21
+ "status" => 400,
22
+ "message" => error_message,
23
+ "fields" => [
24
+ {
25
+ "name" => "ratings",
26
+ "details" => [{ "code" => "REQUIRED_PROPERTY_VALUE" }]
27
+ },{
28
+ "name" => "recommended",
29
+ "details" => [{"code" => "REQUIRED_PROPERTY_VALUE"}]
30
+ }
31
+ ]
32
+ }
33
+ end
34
+
35
+ it 'provides errors when creation failed' do
36
+ stub_request(:post, "#{datastore}/feedbacks")
37
+ .to_return(status: 400, body: creation_error.to_json)
38
+ record = SomeService.create(name: 'Steve')
39
+ expect(record.errors).to be
40
+ expect(record.name).to eq 'Steve'
41
+ expect(record.errors.include?(:ratings)).to eq true
42
+ expect(record.errors.include?(:recommended)).to eq true
43
+ expect(record.errors[:ratings]).to eq ['REQUIRED_PROPERTY_VALUE']
44
+ expect(record.errors.messages).to eq({:ratings=>["REQUIRED_PROPERTY_VALUE"], :recommended=>["REQUIRED_PROPERTY_VALUE"]})
45
+ expect(record.errors.message).to eq error_message
46
+ end
47
+
48
+ it 'doesnt fail when no fields are provided by the backend' do
49
+ stub_request(:post, "#{datastore}/feedbacks")
50
+ .to_return(status: 400, body: {}.to_json)
51
+ SomeService.create(name: 'Steve')
52
+ end
53
+ end
54
+ end