dhs 1.0.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 (301) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rubocop.yml +27 -0
  3. data/.github/workflows/test.yml +27 -0
  4. data/.gitignore +39 -0
  5. data/.rubocop.yml +186 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +674 -0
  9. data/README.md +2807 -0
  10. data/Rakefile +26 -0
  11. data/dhs.gemspec +44 -0
  12. data/docs/accessing-data.png +0 -0
  13. data/lib/dhs.rb +67 -0
  14. data/lib/dhs/collection.rb +84 -0
  15. data/lib/dhs/complex.rb +158 -0
  16. data/lib/dhs/concerns/autoload_records.rb +57 -0
  17. data/lib/dhs/concerns/collection/handle_nested.rb +43 -0
  18. data/lib/dhs/concerns/collection/internal_collection.rb +74 -0
  19. data/lib/dhs/concerns/configuration.rb +20 -0
  20. data/lib/dhs/concerns/data/becomes.rb +18 -0
  21. data/lib/dhs/concerns/data/equality.rb +14 -0
  22. data/lib/dhs/concerns/data/extend.rb +87 -0
  23. data/lib/dhs/concerns/data/json.rb +14 -0
  24. data/lib/dhs/concerns/data/to_hash.rb +14 -0
  25. data/lib/dhs/concerns/inspect.rb +70 -0
  26. data/lib/dhs/concerns/is_href.rb +15 -0
  27. data/lib/dhs/concerns/item/destroy.rb +38 -0
  28. data/lib/dhs/concerns/item/endpoint_lookup.rb +27 -0
  29. data/lib/dhs/concerns/item/save.rb +55 -0
  30. data/lib/dhs/concerns/item/update.rb +50 -0
  31. data/lib/dhs/concerns/item/validation.rb +61 -0
  32. data/lib/dhs/concerns/o_auth.rb +25 -0
  33. data/lib/dhs/concerns/option_blocks.rb +26 -0
  34. data/lib/dhs/concerns/proxy/accessors.rb +132 -0
  35. data/lib/dhs/concerns/proxy/create.rb +45 -0
  36. data/lib/dhs/concerns/proxy/link.rb +25 -0
  37. data/lib/dhs/concerns/proxy/problems.rb +27 -0
  38. data/lib/dhs/concerns/record/attribute_assignment.rb +25 -0
  39. data/lib/dhs/concerns/record/batch.rb +40 -0
  40. data/lib/dhs/concerns/record/chainable.rb +465 -0
  41. data/lib/dhs/concerns/record/configuration.rb +103 -0
  42. data/lib/dhs/concerns/record/create.rb +24 -0
  43. data/lib/dhs/concerns/record/custom_setters.rb +22 -0
  44. data/lib/dhs/concerns/record/destroy.rb +18 -0
  45. data/lib/dhs/concerns/record/endpoints.rb +108 -0
  46. data/lib/dhs/concerns/record/equality.rb +14 -0
  47. data/lib/dhs/concerns/record/find.rb +86 -0
  48. data/lib/dhs/concerns/record/find_by.rb +38 -0
  49. data/lib/dhs/concerns/record/first.rb +20 -0
  50. data/lib/dhs/concerns/record/href_for.rb +19 -0
  51. data/lib/dhs/concerns/record/last.rb +27 -0
  52. data/lib/dhs/concerns/record/mapping.rb +25 -0
  53. data/lib/dhs/concerns/record/merge.rb +26 -0
  54. data/lib/dhs/concerns/record/model.rb +23 -0
  55. data/lib/dhs/concerns/record/pagination.rb +49 -0
  56. data/lib/dhs/concerns/record/provider.rb +23 -0
  57. data/lib/dhs/concerns/record/relations.rb +26 -0
  58. data/lib/dhs/concerns/record/request.rb +581 -0
  59. data/lib/dhs/concerns/record/scope.rb +25 -0
  60. data/lib/dhs/concerns/record/tracing.rb +24 -0
  61. data/lib/dhs/concerns/record/update.rb +17 -0
  62. data/lib/dhs/config.rb +24 -0
  63. data/lib/dhs/data.rb +180 -0
  64. data/lib/dhs/endpoint.rb +12 -0
  65. data/lib/dhs/interceptors/auto_oauth/interceptor.rb +33 -0
  66. data/lib/dhs/interceptors/auto_oauth/thread_registry.rb +18 -0
  67. data/lib/dhs/interceptors/extended_rollbar/handler.rb +40 -0
  68. data/lib/dhs/interceptors/extended_rollbar/interceptor.rb +20 -0
  69. data/lib/dhs/interceptors/extended_rollbar/thread_registry.rb +19 -0
  70. data/lib/dhs/interceptors/request_cycle_cache/interceptor.rb +41 -0
  71. data/lib/dhs/interceptors/request_cycle_cache/thread_registry.rb +18 -0
  72. data/lib/dhs/item.rb +59 -0
  73. data/lib/dhs/pagination/base.rb +90 -0
  74. data/lib/dhs/pagination/link.rb +21 -0
  75. data/lib/dhs/pagination/offset.rb +22 -0
  76. data/lib/dhs/pagination/page.rb +18 -0
  77. data/lib/dhs/pagination/start.rb +22 -0
  78. data/lib/dhs/pagination/total_pages.rb +9 -0
  79. data/lib/dhs/problems/base.rb +113 -0
  80. data/lib/dhs/problems/errors.rb +69 -0
  81. data/lib/dhs/problems/nested/base.rb +54 -0
  82. data/lib/dhs/problems/nested/errors.rb +16 -0
  83. data/lib/dhs/problems/nested/warnings.rb +15 -0
  84. data/lib/dhs/problems/warnings.rb +24 -0
  85. data/lib/dhs/proxy.rb +69 -0
  86. data/lib/dhs/railtie.rb +34 -0
  87. data/lib/dhs/record.rb +112 -0
  88. data/lib/dhs/rspec.rb +10 -0
  89. data/lib/dhs/test/stubbable_records.rb +34 -0
  90. data/lib/dhs/unprocessable.rb +6 -0
  91. data/lib/dhs/version.rb +5 -0
  92. data/script/ci/build.sh +18 -0
  93. data/spec/auto_oauth_spec.rb +163 -0
  94. data/spec/autoloading_spec.rb +45 -0
  95. data/spec/collection/accessors_spec.rb +31 -0
  96. data/spec/collection/collection_items_spec.rb +44 -0
  97. data/spec/collection/configurable_spec.rb +43 -0
  98. data/spec/collection/delegate_spec.rb +21 -0
  99. data/spec/collection/enumerable_spec.rb +27 -0
  100. data/spec/collection/href_spec.rb +17 -0
  101. data/spec/collection/meta_data_spec.rb +58 -0
  102. data/spec/collection/respond_to_spec.rb +20 -0
  103. data/spec/collection/to_a_spec.rb +34 -0
  104. data/spec/collection/to_ary_spec.rb +40 -0
  105. data/spec/collection/without_object_items_spec.rb +27 -0
  106. data/spec/complex/reduce_spec.rb +202 -0
  107. data/spec/concerns/record/request_spec.rb +78 -0
  108. data/spec/data/collection_spec.rb +56 -0
  109. data/spec/data/equality_spec.rb +23 -0
  110. data/spec/data/inspect_spec.rb +88 -0
  111. data/spec/data/is_item_or_collection_spec.rb +40 -0
  112. data/spec/data/item_spec.rb +106 -0
  113. data/spec/data/merge_spec.rb +27 -0
  114. data/spec/data/parent_spec.rb +39 -0
  115. data/spec/data/raw_spec.rb +48 -0
  116. data/spec/data/respond_to_spec.rb +26 -0
  117. data/spec/data/root_spec.rb +25 -0
  118. data/spec/data/select_spec.rb +27 -0
  119. data/spec/data/to_ary_spec.rb +28 -0
  120. data/spec/data/to_json_spec.rb +68 -0
  121. data/spec/dummy/Rakefile +8 -0
  122. data/spec/dummy/app/assets/images/.keep +0 -0
  123. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  124. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  125. data/spec/dummy/app/controllers/application_controller.rb +26 -0
  126. data/spec/dummy/app/controllers/automatic_authentication_controller.rb +29 -0
  127. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  128. data/spec/dummy/app/controllers/error_handling_with_chains_controller.rb +36 -0
  129. data/spec/dummy/app/controllers/extended_rollbar_controller.rb +10 -0
  130. data/spec/dummy/app/controllers/option_blocks_controller.rb +15 -0
  131. data/spec/dummy/app/controllers/request_cycle_cache_controller.rb +27 -0
  132. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  133. data/spec/dummy/app/mailers/.keep +0 -0
  134. data/spec/dummy/app/models/.keep +0 -0
  135. data/spec/dummy/app/models/concerns/.keep +0 -0
  136. data/spec/dummy/app/models/concerns/dummy_customer/some_concern.rb +9 -0
  137. data/spec/dummy/app/models/dummy_customer.rb +7 -0
  138. data/spec/dummy/app/models/dummy_record.rb +6 -0
  139. data/spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb +6 -0
  140. data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb +7 -0
  141. data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb +7 -0
  142. data/spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb +6 -0
  143. data/spec/dummy/app/models/dummy_record_with_oauth.rb +7 -0
  144. data/spec/dummy/app/models/dummy_user.rb +6 -0
  145. data/spec/dummy/app/models/providers/customer_system.rb +7 -0
  146. data/spec/dummy/app/models/providers/internal_services.rb +7 -0
  147. data/spec/dummy/app/views/error_handling_with_chains/error.html.erb +1 -0
  148. data/spec/dummy/app/views/error_handling_with_chains/show.html.erb +3 -0
  149. data/spec/dummy/app/views/form_for.html.erb +5 -0
  150. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  151. data/spec/dummy/bin/bundle +5 -0
  152. data/spec/dummy/bin/rails +6 -0
  153. data/spec/dummy/bin/rake +6 -0
  154. data/spec/dummy/config.ru +6 -0
  155. data/spec/dummy/config/application.rb +16 -0
  156. data/spec/dummy/config/boot.rb +7 -0
  157. data/spec/dummy/config/environment.rb +7 -0
  158. data/spec/dummy/config/environments/development.rb +36 -0
  159. data/spec/dummy/config/environments/production.rb +77 -0
  160. data/spec/dummy/config/environments/test.rb +40 -0
  161. data/spec/dummy/config/initializers/assets.rb +10 -0
  162. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  163. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  164. data/spec/dummy/config/initializers/dhs.rb +5 -0
  165. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  166. data/spec/dummy/config/initializers/inflections.rb +18 -0
  167. data/spec/dummy/config/initializers/mime_types.rb +6 -0
  168. data/spec/dummy/config/initializers/rollbar.rb +9 -0
  169. data/spec/dummy/config/initializers/session_store.rb +5 -0
  170. data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
  171. data/spec/dummy/config/locales/en.yml +23 -0
  172. data/spec/dummy/config/routes.rb +27 -0
  173. data/spec/dummy/config/secrets.yml +22 -0
  174. data/spec/dummy/lib/assets/.keep +0 -0
  175. data/spec/dummy/public/404.html +67 -0
  176. data/spec/dummy/public/422.html +67 -0
  177. data/spec/dummy/public/500.html +66 -0
  178. data/spec/dummy/public/favicon.ico +0 -0
  179. data/spec/endpoint/for_url_spec.rb +27 -0
  180. data/spec/extended_rollbar_spec.rb +67 -0
  181. data/spec/item/access_errors_spec.rb +31 -0
  182. data/spec/item/accessors_spec.rb +21 -0
  183. data/spec/item/add_error_spec.rb +21 -0
  184. data/spec/item/becomes_spec.rb +38 -0
  185. data/spec/item/blacklisted_keywords_spec.rb +28 -0
  186. data/spec/item/delegate_spec.rb +32 -0
  187. data/spec/item/destroy_spec.rb +113 -0
  188. data/spec/item/dig_spec.rb +29 -0
  189. data/spec/item/error_codes_spec.rb +55 -0
  190. data/spec/item/errors_spec.rb +324 -0
  191. data/spec/item/fetch_spec.rb +39 -0
  192. data/spec/item/getter_spec.rb +24 -0
  193. data/spec/item/internal_data_structure_spec.rb +37 -0
  194. data/spec/item/map_spec.rb +46 -0
  195. data/spec/item/nested_errors_spec.rb +27 -0
  196. data/spec/item/partial_update_spec.rb +168 -0
  197. data/spec/item/respond_to_spec.rb +31 -0
  198. data/spec/item/save_spec.rb +115 -0
  199. data/spec/item/setter_spec.rb +44 -0
  200. data/spec/item/translate_errors_spec.rb +257 -0
  201. data/spec/item/update_spec.rb +161 -0
  202. data/spec/item/validation_spec.rb +131 -0
  203. data/spec/item/warning_codes_spec.rb +55 -0
  204. data/spec/item/warnings_spec.rb +51 -0
  205. data/spec/option_blocks/ensure_reset_between_requests_spec.rb +23 -0
  206. data/spec/option_blocks/main_spec.rb +54 -0
  207. data/spec/pagination/link/current_page_spec.rb +19 -0
  208. data/spec/pagination/link/pages_left_spec.rb +36 -0
  209. data/spec/pagination/link/parallel_spec.rb +19 -0
  210. data/spec/pagination/link/total_spec.rb +45 -0
  211. data/spec/pagination/offset/pages_left_spec.rb +26 -0
  212. data/spec/pagination/parameters_spec.rb +59 -0
  213. data/spec/pagination/total_pages_spec.rb +51 -0
  214. data/spec/proxy/create_sub_resource_spec.rb +182 -0
  215. data/spec/proxy/load_spec.rb +75 -0
  216. data/spec/proxy/record_identification_spec.rb +35 -0
  217. data/spec/rails_helper.rb +13 -0
  218. data/spec/record/all_spec.rb +133 -0
  219. data/spec/record/attribute_assignment_spec.rb +28 -0
  220. data/spec/record/build_spec.rb +26 -0
  221. data/spec/record/cast_nested_data_spec.rb +80 -0
  222. data/spec/record/compact_spec.rb +93 -0
  223. data/spec/record/create_spec.rb +160 -0
  224. data/spec/record/creation_failed_spec.rb +55 -0
  225. data/spec/record/custom_setters_spec.rb +42 -0
  226. data/spec/record/definitions_spec.rb +29 -0
  227. data/spec/record/destroy_spec.rb +38 -0
  228. data/spec/record/dig_configuration_spec.rb +75 -0
  229. data/spec/record/dup_spec.rb +20 -0
  230. data/spec/record/endpoint_inheritance_spec.rb +65 -0
  231. data/spec/record/endpoint_options_spec.rb +51 -0
  232. data/spec/record/endpoint_priorities_spec.rb +24 -0
  233. data/spec/record/endpoints_spec.rb +96 -0
  234. data/spec/record/equality_spec.rb +27 -0
  235. data/spec/record/error_handling_integration_spec.rb +25 -0
  236. data/spec/record/error_handling_spec.rb +40 -0
  237. data/spec/record/expanded_spec.rb +69 -0
  238. data/spec/record/fetch_spec.rb +40 -0
  239. data/spec/record/find_by_chains_spec.rb +21 -0
  240. data/spec/record/find_by_spec.rb +76 -0
  241. data/spec/record/find_each_spec.rb +57 -0
  242. data/spec/record/find_in_batches_spec.rb +122 -0
  243. data/spec/record/find_in_parallel_spec.rb +67 -0
  244. data/spec/record/find_spec.rb +103 -0
  245. data/spec/record/first_spec.rb +39 -0
  246. data/spec/record/force_merge_spec.rb +55 -0
  247. data/spec/record/handle_includes_errors_spec.rb +33 -0
  248. data/spec/record/has_many_spec.rb +118 -0
  249. data/spec/record/has_one_spec.rb +114 -0
  250. data/spec/record/href_for_spec.rb +24 -0
  251. data/spec/record/ignore_errors_spec.rb +137 -0
  252. data/spec/record/immutable_chains_spec.rb +22 -0
  253. data/spec/record/includes_after_expansion_spec.rb +70 -0
  254. data/spec/record/includes_expanded_spec.rb +37 -0
  255. data/spec/record/includes_first_page_spec.rb +738 -0
  256. data/spec/record/includes_missing_spec.rb +57 -0
  257. data/spec/record/includes_spec.rb +690 -0
  258. data/spec/record/includes_warning_spec.rb +46 -0
  259. data/spec/record/item_key_spec.rb +81 -0
  260. data/spec/record/items_created_key_configuration_spec.rb +37 -0
  261. data/spec/record/last_spec.rb +64 -0
  262. data/spec/record/loading_twice_spec.rb +19 -0
  263. data/spec/record/mapping_spec.rb +103 -0
  264. data/spec/record/model_name_spec.rb +17 -0
  265. data/spec/record/new_spec.rb +106 -0
  266. data/spec/record/options_getter_spec.rb +25 -0
  267. data/spec/record/options_spec.rb +164 -0
  268. data/spec/record/paginatable_collection_spec.rb +360 -0
  269. data/spec/record/pagination_chain_spec.rb +101 -0
  270. data/spec/record/pagination_links_spec.rb +72 -0
  271. data/spec/record/pagination_spec.rb +71 -0
  272. data/spec/record/persisted_spec.rb +52 -0
  273. data/spec/record/provider_spec.rb +40 -0
  274. data/spec/record/references_spec.rb +95 -0
  275. data/spec/record/relation_caching_spec.rb +120 -0
  276. data/spec/record/reload_by_id_spec.rb +43 -0
  277. data/spec/record/reload_spec.rb +64 -0
  278. data/spec/record/request_spec.rb +90 -0
  279. data/spec/record/save_spec.rb +40 -0
  280. data/spec/record/scope_chains_spec.rb +39 -0
  281. data/spec/record/select_spec.rb +17 -0
  282. data/spec/record/to_ary_spec.rb +65 -0
  283. data/spec/record/to_hash_spec.rb +22 -0
  284. data/spec/record/to_json_spec.rb +22 -0
  285. data/spec/record/tracing_spec.rb +149 -0
  286. data/spec/record/update_spec.rb +61 -0
  287. data/spec/record/where_chains_spec.rb +57 -0
  288. data/spec/record/where_spec.rb +62 -0
  289. data/spec/record/where_values_hash_spec.rb +32 -0
  290. data/spec/request_cycle_cache_spec.rb +106 -0
  291. data/spec/require_dhs_spec.rb +9 -0
  292. data/spec/spec_helper.rb +6 -0
  293. data/spec/stubs/all_spec.rb +69 -0
  294. data/spec/support/fixtures/json/feedback.json +11 -0
  295. data/spec/support/fixtures/json/feedbacks.json +174 -0
  296. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  297. data/spec/support/load_json.rb +5 -0
  298. data/spec/support/request_cycle_cache.rb +10 -0
  299. data/spec/support/reset.rb +67 -0
  300. data/spec/views/form_for_spec.rb +20 -0
  301. metadata +783 -0
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Item do
6
+ before do
7
+ class Record < DHS::Record
8
+ endpoint '{+datastore}/records'
9
+ end
10
+ end
11
+
12
+ let(:json) do
13
+ {
14
+ local_entry_id: 'ABC123'
15
+ }
16
+ end
17
+
18
+ let(:item) do
19
+ DHS::Data.new(json, nil, Record)
20
+ end
21
+
22
+ it 'is possible to fetch data' do
23
+ expect(
24
+ item.fetch(:local_entry_id)
25
+ ).to eq 'ABC123'
26
+ end
27
+
28
+ context 'empty data' do
29
+ let(:json) do
30
+ {}
31
+ end
32
+
33
+ it 'is possible to get a default when fetched data is nil' do
34
+ expect(
35
+ item.fetch(:local_entry_id, 'DEFAULT')
36
+ ).to eq 'DEFAULT'
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Item do
6
+ before do
7
+ class Record < DHS::Record
8
+ endpoint '{+datastore}/v2/{campaign_id}/feedbacks'
9
+ endpoint '{+datastore}/v2/feedbacks'
10
+ end
11
+ end
12
+
13
+ let(:data) do
14
+ DHS::Data.new({ addresses: [{ business: { identities: [{ name: 'Löwenzorn' }] } }] }, nil, Record)
15
+ end
16
+
17
+ context 'item getter' do
18
+ it 'returns a collection if you access an array' do
19
+ expect(data.addresses).to be_kind_of(DHS::Data)
20
+ expect(data.addresses._proxy).to be_kind_of(DHS::Collection)
21
+ expect(data.addresses.first.business.identities.first.name).to eq 'Löwenzorn'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Item do
6
+ before do
7
+ class Feedback < DHS::Record
8
+ endpoint '{+datastore}/v2/feedbacks'
9
+ endpoint '{+datastore}/v2/feedbacks/{id}'
10
+ end
11
+ end
12
+
13
+ let(:hash) do
14
+ { 'addresses' => [{ 'businesses' => { 'identities' => [{ 'name' => 'Löwenzorn' }] } }] }
15
+ end
16
+
17
+ let(:data) do
18
+ DHS::Data.new(hash, nil, Feedback)
19
+ end
20
+
21
+ it 'deep symbolizes keys internaly when new data is initalized' do
22
+ expect(data._raw[:addresses].first[:businesses][:identities].first[:name]).to eq 'Löwenzorn'
23
+ data.id = 'YZ12'
24
+ expect(data._raw.keys).to include(:id)
25
+ end
26
+
27
+ it 'deep symbolizes internal data' do
28
+ feedback = Feedback.build(hash)
29
+ expect(feedback._raw.keys).to include(:addresses)
30
+ expect(feedback._raw[:addresses].first[:businesses][:identities].first[:name]).to eq 'Löwenzorn'
31
+ end
32
+
33
+ it 'deep symbolizes internal data when building new objects' do
34
+ feedback = Feedback.build('name' => 'BB8')
35
+ expect(feedback._data._raw.keys).to include(:name)
36
+ end
37
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Item do
6
+ before do
7
+ class Record < DHS::Record
8
+ endpoint '{+datastore}/records'
9
+ end
10
+ end
11
+
12
+ let(:json) do
13
+ {
14
+ key: 'value'
15
+ }
16
+ end
17
+
18
+ let(:item) do
19
+ DHS::Data.new(json, nil, Record)
20
+ end
21
+
22
+ it 'is possible to map' do
23
+ mapped_data = item.map do |key, value|
24
+ { value => key }
25
+ end
26
+ expect(mapped_data).to eq([{ 'value' => :key }])
27
+ end
28
+
29
+ context 'nested' do
30
+ let(:json) do
31
+ {
32
+ languages: {
33
+ de: { key: 'german value' },
34
+ en: { key: 'english value' }
35
+ }
36
+ }
37
+ end
38
+
39
+ it 'also maps nested data' do
40
+ mapped_data = item.languages.map do |_language, value|
41
+ value[:key]
42
+ end
43
+ expect(mapped_data).to eq(['german value', 'english value'])
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Item do
6
+ context 'nested data' do
7
+ before do
8
+ class Presence < DHS::Record
9
+ endpoint 'http://opm/presences'
10
+ end
11
+ stub_request(:post, 'http://opm/presences')
12
+ .to_return(
13
+ body: {
14
+ listings: [{ status: 'CONNECTED' }],
15
+ field_errors: []
16
+ }.to_json
17
+ )
18
+ end
19
+
20
+ it 'does not raise when accessing nested data' do
21
+ presence = Presence.create
22
+ expect(lambda {
23
+ presence.listings.first
24
+ }).not_to raise_error NoMethodError
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Item do
6
+ before do
7
+ class Record < DHS::Record
8
+ endpoint '{+datastore}/v2/{campaign_id}/feedbacks'
9
+ endpoint '{+datastore}/v2/feedbacks'
10
+ end
11
+ end
12
+
13
+ let(:json) do
14
+ load_json(:feedbacks)
15
+ end
16
+
17
+ let(:data) do
18
+ DHS::Data.new(json, nil, Record)
19
+ end
20
+
21
+ let(:item) do
22
+ data[0]
23
+ end
24
+
25
+ context 'update' do
26
+ it 'persists changes on the backend' do
27
+ stub_request(:post, item.href)
28
+ .with(body: { name: 'Steve' }.to_json)
29
+ result = item.partial_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.partial_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.partial_update(name: 'Steve')
43
+ expect(item.name).to eq 'Steve'
44
+ expect(item.likes).to eq 'Banana'
45
+ end
46
+
47
+ it 'updates local version of an object even if BE request fails' do
48
+ stub_request(:post, item.href)
49
+ .to_return(status: 400, body: item._raw.merge(likes: 'Banana').to_json)
50
+ item.update(name: 'Andrea')
51
+ expect(item.name).to eq 'Andrea'
52
+ expect(item.likes).not_to eq 'Banana'
53
+ end
54
+ end
55
+
56
+ context 'with many placeholders' do
57
+ before do
58
+ class GrandChild < DHS::Record
59
+ endpoint 'http://host/v2/parents/{parent_id}/children/{child_id}/grand_children'
60
+ endpoint 'http://host/v2/parents/{parent_id}/children/{child_id}/grand_children/{id}'
61
+ end
62
+ end
63
+
64
+ let(:data) do
65
+ {
66
+ id: 'aaa',
67
+ parent_id: 'bbb',
68
+ child_id: 'ccc',
69
+ name: 'Lorem'
70
+ }
71
+ end
72
+
73
+ let(:item) do
74
+ GrandChild.new(data)
75
+ end
76
+
77
+ it 'persists changes on the backend' do
78
+ stub_request(:get, 'http://host/v2/parents/bbb/children/ccc/grand_children/aaa')
79
+ .to_return(status: 200, body: data.to_json)
80
+ stub_request(:post, 'http://host/v2/parents/bbb/children/ccc/grand_children/aaa')
81
+ .with(body: { name: 'Steve' }.to_json)
82
+
83
+ grand_child = GrandChild.find(parent_id: 'bbb', child_id: 'ccc', id: 'aaa')
84
+ expect(grand_child.name).to eq('Lorem')
85
+ result = grand_child.partial_update(name: 'Steve')
86
+ expect(result).to eq true
87
+ end
88
+
89
+ it 'persists changes on the backend removing placeholder from body' do
90
+ stub_request(:post, 'http://host/v2/parents/bbb/children/ccc/grand_children/kkkk')
91
+ .with(body: { name: 'Steve' }.to_json)
92
+
93
+ result = item.partial_update(name: 'Steve', id: 'kkkk')
94
+ expect(result).to eq true
95
+ end
96
+ end
97
+
98
+ context 'update!' do
99
+ it 'raises if something goes wrong' do
100
+ stub_request(:post, item.href)
101
+ .with(body: { name: 'Steve' }.to_json)
102
+ .to_return(status: 500)
103
+ expect(-> { item.partial_update!(name: 'Steve') }).to raise_error DHC::ServerError
104
+ end
105
+ end
106
+
107
+ context 'records without hrefs and nested items' do
108
+ before do
109
+ class Location < DHS::Record
110
+ endpoint 'http://uberall/locations'
111
+ endpoint 'http://uberall/locations/{id}'
112
+ end
113
+ end
114
+
115
+ it 'finds and compiles existing endpoints to determine update url' do
116
+ stub_request(:get, 'http://uberall/locations/1').to_return(body: { id: 1 }.to_json)
117
+ stub_request(:post, 'http://uberall/locations/1').to_return(body: { id: 1, listings: [{ directory: 'facebook' }] }.to_json)
118
+ location = Location.find(1)
119
+ location.partial_update(autoSync: true)
120
+ expect(location.autoSync).to eq true
121
+ expect(location.listings.first.directory).to eq 'facebook'
122
+ end
123
+
124
+ context 'records with nested items' do
125
+ before do
126
+ class Location < DHS::Record
127
+ endpoint 'http://uberall/locations'
128
+ endpoint 'http://uberall/locations/{id}'
129
+ configuration item_created_key: %i[response location], item_key: %i[response location]
130
+ end
131
+ end
132
+
133
+ it 'finds and compiles existing endpoints to determine update url' do
134
+ stub_request(:get, 'http://uberall/locations/1').to_return(body: { response: { location: { id: 1 } } }.to_json)
135
+ stub_request(:post, 'http://uberall/locations/1').to_return(body: { response: { location: { id: 1, listings: [{ directory: 'facebook' }] } } }.to_json)
136
+ location = Location.find(1)
137
+ location.partial_update(autoSync: true)
138
+ expect(location.autoSync).to eq true
139
+ expect(location.listings.first.directory).to eq 'facebook'
140
+ end
141
+
142
+ it 'use given update http method' do
143
+ stub_request(:get, 'http://uberall/locations/1').to_return(body: { response: { location: { id: 1 } } }.to_json)
144
+ stub_request(:patch, 'http://uberall/locations/1').to_return(body: { response: { location: { id: 1, listings: [{ directory: 'facebook' }] } } }.to_json)
145
+ location = Location.find(1)
146
+ location.partial_update({ autoSync: true }, { method: :patch })
147
+ expect(location.autoSync).to eq true
148
+ expect(location.listings.first.directory).to eq 'facebook'
149
+ end
150
+ end
151
+ end
152
+
153
+ context 'chainable' do
154
+ it 'allows to chain partial_update with options' do
155
+ stub_request(:put, item.href)
156
+ .with(body: { name: 'Steve' }.to_json)
157
+ result = item.options(method: :put).partial_update(name: 'Steve')
158
+ expect(result).to eq true
159
+ end
160
+
161
+ it 'allows to chain partial_update! with options' do
162
+ stub_request(:put, item.href)
163
+ .with(body: { name: 'Steve' }.to_json)
164
+ result = item.options(method: :put).partial_update!(name: 'Steve')
165
+ expect(result).to eq true
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Item do
6
+ let(:item) do
7
+ DHS::Item.new(id: 1234)
8
+ end
9
+
10
+ context '#respond_to?' do
11
+ it 'is true for setters' do
12
+ expect(item.respond_to?(:id=)).to be(true)
13
+ end
14
+
15
+ it 'is true for getters' do
16
+ expect(item.respond_to?(:id)).to be(true)
17
+ end
18
+
19
+ it 'is true for brackets' do
20
+ expect(item.respond_to?(:[])).to be(true)
21
+ end
22
+
23
+ it 'is false for new' do
24
+ expect(item.respond_to?(:new)).to be(false)
25
+ end
26
+
27
+ it 'is false for proxy_association' do
28
+ expect(item.respond_to?(:proxy_association)).to be(false)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Item do
6
+ before do
7
+ class Record < DHS::Record
8
+ endpoint '{+datastore}/v2/{campaign_id}/feedbacks'
9
+ endpoint '{+datastore}/v2/feedbacks'
10
+ end
11
+ end
12
+
13
+ let(:json) do
14
+ load_json(:feedbacks)
15
+ end
16
+
17
+ let(:data) do
18
+ DHS::Data.new(json, nil, Record)
19
+ end
20
+
21
+ let(:item) do
22
+ data[0]
23
+ end
24
+
25
+ context 'endpoint options' do
26
+ let(:headers) { { 'X-Header' => 'VALUE' } }
27
+
28
+ before do
29
+ class RecordWithOptions < DHS::Record
30
+ endpoint 'http://datastore/records', headers: { 'X-Header' => 'VALUE' }
31
+ end
32
+ end
33
+
34
+ it 'considers end point options when saving' do
35
+ data = { name: 'Steve' }
36
+ stub_request(:post, 'http://datastore/records')
37
+ .with(body: data.to_json, headers: headers)
38
+ .to_return(body: data.to_json)
39
+ RecordWithOptions.create!(data)
40
+ end
41
+ end
42
+
43
+ context 'save' do
44
+ it 'persists changes on the backend' do
45
+ stub_request(:post, item.href).with(body: item._raw.merge(name: 'Steve').to_json)
46
+ item.name = 'Steve'
47
+ expect(item.save).to eq true
48
+ end
49
+
50
+ it 'returns false if persting goes wrong' do
51
+ stub_request(:post, item.href)
52
+ .with(body: item._raw.to_json)
53
+ .to_return(status: 500)
54
+ expect(item.save).to eq false
55
+ end
56
+
57
+ it 'merges reponse data with object' do
58
+ stub_request(:post, item.href)
59
+ .with(body: item._raw.to_json)
60
+ .to_return(status: 200, body: item._raw.merge(name: 'Steve').to_json)
61
+ item.save
62
+ expect(item.name).to eq 'Steve'
63
+ end
64
+ end
65
+
66
+ context 'with many placeholders' do
67
+ before do
68
+ class GrandChild < DHS::Record
69
+ endpoint 'http://host/v2/parents/{parent_id}/children/{child_id}/grand_children'
70
+ endpoint 'http://host/v2/parents/{parent_id}/children/{child_id}/grand_children/{id}'
71
+ end
72
+ end
73
+
74
+ let(:data) do
75
+ {
76
+ parent_id: 'bbb',
77
+ child_id: 'ccc',
78
+ name: 'Lorem'
79
+ }
80
+ end
81
+
82
+ let(:item) do
83
+ GrandChild.new(data)
84
+ end
85
+
86
+ it 'persists changes on the backend' do
87
+ stub_request(:post, 'http://host/v2/parents/bbb/children/ccc/grand_children')
88
+ .with(body: { name: 'Lorem' }.to_json)
89
+
90
+ expect(item.save).to eq true
91
+ end
92
+ end
93
+
94
+ context 'save!' do
95
+ it 'raises if something goes wrong' do
96
+ stub_request(:post, item.href)
97
+ .with(body: item._raw.to_json)
98
+ .to_return(status: 500)
99
+ expect(-> { item.save! }).to raise_error DHC::ServerError
100
+ end
101
+
102
+ it 'keeps header psassed in the options' do
103
+ headers = { 'Stats' => 'first-access' }
104
+ request = stub_request(:post, item.href)
105
+ .with(
106
+ body: item._raw.to_json,
107
+ headers: headers
108
+ )
109
+ .to_return(status: 200, body: item._raw.to_json)
110
+
111
+ item.save!(headers: headers)
112
+ expect(request).to have_been_requested
113
+ end
114
+ end
115
+ end