lhs 24.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 (306) hide show
  1. checksums.yaml +7 -0
  2. data/.bundler-version +1 -0
  3. data/.gitignore +39 -0
  4. data/.rubocop.localch.yml +325 -0
  5. data/.rubocop.yml +52 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.activesupport4 +5 -0
  9. data/Gemfile.activesupport5 +4 -0
  10. data/LICENSE +674 -0
  11. data/README.md +2836 -0
  12. data/Rakefile +25 -0
  13. data/cider-ci.yml +6 -0
  14. data/cider-ci/bin/bundle +51 -0
  15. data/cider-ci/bin/ruby_install +8 -0
  16. data/cider-ci/bin/ruby_version +25 -0
  17. data/cider-ci/jobs/rspec-activesupport-4.yml +27 -0
  18. data/cider-ci/jobs/rspec-activesupport-5.yml +26 -0
  19. data/cider-ci/jobs/rspec-activesupport-latest.yml +24 -0
  20. data/cider-ci/jobs/rubocop.yml +18 -0
  21. data/cider-ci/task_components/bundle.yml +22 -0
  22. data/cider-ci/task_components/rspec.yml +37 -0
  23. data/cider-ci/task_components/rubocop.yml +29 -0
  24. data/cider-ci/task_components/ruby.yml +15 -0
  25. data/friday.yml +2 -0
  26. data/lhs.gemspec +43 -0
  27. data/lib/lhs.rb +100 -0
  28. data/lib/lhs/collection.rb +84 -0
  29. data/lib/lhs/complex.rb +158 -0
  30. data/lib/lhs/concerns/autoload_records.rb +55 -0
  31. data/lib/lhs/concerns/collection/handle_nested.rb +43 -0
  32. data/lib/lhs/concerns/collection/internal_collection.rb +49 -0
  33. data/lib/lhs/concerns/configuration.rb +20 -0
  34. data/lib/lhs/concerns/data/becomes.rb +18 -0
  35. data/lib/lhs/concerns/data/equality.rb +14 -0
  36. data/lib/lhs/concerns/data/json.rb +14 -0
  37. data/lib/lhs/concerns/data/to_hash.rb +14 -0
  38. data/lib/lhs/concerns/inspect.rb +70 -0
  39. data/lib/lhs/concerns/is_href.rb +15 -0
  40. data/lib/lhs/concerns/item/destroy.rb +38 -0
  41. data/lib/lhs/concerns/item/endpoint_lookup.rb +27 -0
  42. data/lib/lhs/concerns/item/save.rb +55 -0
  43. data/lib/lhs/concerns/item/update.rb +50 -0
  44. data/lib/lhs/concerns/item/validation.rb +61 -0
  45. data/lib/lhs/concerns/o_auth.rb +25 -0
  46. data/lib/lhs/concerns/option_blocks.rb +26 -0
  47. data/lib/lhs/concerns/proxy/accessors.rb +132 -0
  48. data/lib/lhs/concerns/proxy/create.rb +45 -0
  49. data/lib/lhs/concerns/proxy/link.rb +25 -0
  50. data/lib/lhs/concerns/proxy/problems.rb +27 -0
  51. data/lib/lhs/concerns/record/attribute_assignment.rb +25 -0
  52. data/lib/lhs/concerns/record/batch.rb +40 -0
  53. data/lib/lhs/concerns/record/chainable.rb +465 -0
  54. data/lib/lhs/concerns/record/configuration.rb +103 -0
  55. data/lib/lhs/concerns/record/create.rb +24 -0
  56. data/lib/lhs/concerns/record/custom_setters.rb +22 -0
  57. data/lib/lhs/concerns/record/destroy.rb +18 -0
  58. data/lib/lhs/concerns/record/endpoints.rb +108 -0
  59. data/lib/lhs/concerns/record/equality.rb +14 -0
  60. data/lib/lhs/concerns/record/find.rb +86 -0
  61. data/lib/lhs/concerns/record/find_by.rb +38 -0
  62. data/lib/lhs/concerns/record/first.rb +20 -0
  63. data/lib/lhs/concerns/record/href_for.rb +19 -0
  64. data/lib/lhs/concerns/record/last.rb +27 -0
  65. data/lib/lhs/concerns/record/mapping.rb +25 -0
  66. data/lib/lhs/concerns/record/merge.rb +26 -0
  67. data/lib/lhs/concerns/record/model.rb +23 -0
  68. data/lib/lhs/concerns/record/pagination.rb +47 -0
  69. data/lib/lhs/concerns/record/provider.rb +23 -0
  70. data/lib/lhs/concerns/record/relations.rb +26 -0
  71. data/lib/lhs/concerns/record/request.rb +620 -0
  72. data/lib/lhs/concerns/record/scope.rb +25 -0
  73. data/lib/lhs/concerns/record/tracing.rb +24 -0
  74. data/lib/lhs/concerns/record/update.rb +17 -0
  75. data/lib/lhs/config.rb +24 -0
  76. data/lib/lhs/data.rb +165 -0
  77. data/lib/lhs/endpoint.rb +12 -0
  78. data/lib/lhs/interceptors/auto_oauth/interceptor.rb +33 -0
  79. data/lib/lhs/interceptors/auto_oauth/thread_registry.rb +18 -0
  80. data/lib/lhs/interceptors/extended_rollbar/handler.rb +40 -0
  81. data/lib/lhs/interceptors/extended_rollbar/interceptor.rb +20 -0
  82. data/lib/lhs/interceptors/extended_rollbar/thread_registry.rb +19 -0
  83. data/lib/lhs/interceptors/request_cycle_cache/interceptor.rb +41 -0
  84. data/lib/lhs/interceptors/request_cycle_cache/thread_registry.rb +18 -0
  85. data/lib/lhs/item.rb +59 -0
  86. data/lib/lhs/pagination/base.rb +90 -0
  87. data/lib/lhs/pagination/link.rb +21 -0
  88. data/lib/lhs/pagination/offset.rb +22 -0
  89. data/lib/lhs/pagination/page.rb +18 -0
  90. data/lib/lhs/pagination/start.rb +22 -0
  91. data/lib/lhs/problems/base.rb +113 -0
  92. data/lib/lhs/problems/errors.rb +69 -0
  93. data/lib/lhs/problems/nested/base.rb +54 -0
  94. data/lib/lhs/problems/nested/errors.rb +16 -0
  95. data/lib/lhs/problems/nested/warnings.rb +15 -0
  96. data/lib/lhs/problems/warnings.rb +24 -0
  97. data/lib/lhs/proxy.rb +68 -0
  98. data/lib/lhs/railtie.rb +34 -0
  99. data/lib/lhs/record.rb +112 -0
  100. data/lib/lhs/rspec.rb +10 -0
  101. data/lib/lhs/test/stubbable_records.rb +34 -0
  102. data/lib/lhs/unprocessable.rb +6 -0
  103. data/lib/lhs/version.rb +5 -0
  104. data/script/ci/build.sh +18 -0
  105. data/spec/auto_oauth_spec.rb +169 -0
  106. data/spec/autoloading_spec.rb +48 -0
  107. data/spec/collection/accessors_spec.rb +31 -0
  108. data/spec/collection/collection_items_spec.rb +44 -0
  109. data/spec/collection/configurable_spec.rb +43 -0
  110. data/spec/collection/delegate_spec.rb +21 -0
  111. data/spec/collection/enumerable_spec.rb +27 -0
  112. data/spec/collection/href_spec.rb +17 -0
  113. data/spec/collection/meta_data_spec.rb +57 -0
  114. data/spec/collection/respond_to_spec.rb +20 -0
  115. data/spec/collection/to_a_spec.rb +34 -0
  116. data/spec/collection/to_ary_spec.rb +40 -0
  117. data/spec/collection/without_object_items_spec.rb +27 -0
  118. data/spec/complex/reduce_spec.rb +202 -0
  119. data/spec/concerns/record/request_spec.rb +78 -0
  120. data/spec/data/collection_spec.rb +56 -0
  121. data/spec/data/equality_spec.rb +23 -0
  122. data/spec/data/inspect_spec.rb +88 -0
  123. data/spec/data/is_item_or_collection_spec.rb +40 -0
  124. data/spec/data/item_spec.rb +106 -0
  125. data/spec/data/merge_spec.rb +27 -0
  126. data/spec/data/parent_spec.rb +39 -0
  127. data/spec/data/raw_spec.rb +48 -0
  128. data/spec/data/respond_to_spec.rb +26 -0
  129. data/spec/data/root_spec.rb +25 -0
  130. data/spec/data/select_spec.rb +27 -0
  131. data/spec/data/to_ary_spec.rb +28 -0
  132. data/spec/data/to_json_spec.rb +68 -0
  133. data/spec/dummy/Rakefile +8 -0
  134. data/spec/dummy/app/assets/images/.keep +0 -0
  135. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  136. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  137. data/spec/dummy/app/controllers/application_controller.rb +26 -0
  138. data/spec/dummy/app/controllers/automatic_authentication_controller.rb +29 -0
  139. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  140. data/spec/dummy/app/controllers/error_handling_with_chains_controller.rb +36 -0
  141. data/spec/dummy/app/controllers/extended_rollbar_controller.rb +10 -0
  142. data/spec/dummy/app/controllers/option_blocks_controller.rb +15 -0
  143. data/spec/dummy/app/controllers/request_cycle_cache_controller.rb +27 -0
  144. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  145. data/spec/dummy/app/mailers/.keep +0 -0
  146. data/spec/dummy/app/models/.keep +0 -0
  147. data/spec/dummy/app/models/concerns/.keep +0 -0
  148. data/spec/dummy/app/models/dummy_customer.rb +6 -0
  149. data/spec/dummy/app/models/dummy_record.rb +6 -0
  150. data/spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb +6 -0
  151. data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb +7 -0
  152. data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb +7 -0
  153. data/spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb +6 -0
  154. data/spec/dummy/app/models/dummy_record_with_oauth.rb +7 -0
  155. data/spec/dummy/app/models/dummy_user.rb +6 -0
  156. data/spec/dummy/app/models/providers/customer_system.rb +7 -0
  157. data/spec/dummy/app/models/providers/internal_services.rb +7 -0
  158. data/spec/dummy/app/views/error_handling_with_chains/error.html.erb +1 -0
  159. data/spec/dummy/app/views/error_handling_with_chains/show.html.erb +3 -0
  160. data/spec/dummy/app/views/form_for.html.erb +5 -0
  161. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  162. data/spec/dummy/bin/bundle +5 -0
  163. data/spec/dummy/bin/rails +6 -0
  164. data/spec/dummy/bin/rake +6 -0
  165. data/spec/dummy/config.ru +6 -0
  166. data/spec/dummy/config/application.rb +16 -0
  167. data/spec/dummy/config/boot.rb +7 -0
  168. data/spec/dummy/config/environment.rb +7 -0
  169. data/spec/dummy/config/environments/development.rb +36 -0
  170. data/spec/dummy/config/environments/production.rb +77 -0
  171. data/spec/dummy/config/environments/test.rb +40 -0
  172. data/spec/dummy/config/initializers/assets.rb +10 -0
  173. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  174. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  175. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  176. data/spec/dummy/config/initializers/inflections.rb +18 -0
  177. data/spec/dummy/config/initializers/mime_types.rb +6 -0
  178. data/spec/dummy/config/initializers/rollbar.rb +9 -0
  179. data/spec/dummy/config/initializers/session_store.rb +5 -0
  180. data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
  181. data/spec/dummy/config/locales/en.yml +23 -0
  182. data/spec/dummy/config/routes.rb +27 -0
  183. data/spec/dummy/config/secrets.yml +22 -0
  184. data/spec/dummy/lib/assets/.keep +0 -0
  185. data/spec/dummy/public/404.html +67 -0
  186. data/spec/dummy/public/422.html +67 -0
  187. data/spec/dummy/public/500.html +66 -0
  188. data/spec/dummy/public/favicon.ico +0 -0
  189. data/spec/endpoint/for_url_spec.rb +27 -0
  190. data/spec/extended_rollbar_spec.rb +67 -0
  191. data/spec/item/access_errors_spec.rb +33 -0
  192. data/spec/item/accessors_spec.rb +21 -0
  193. data/spec/item/add_error_spec.rb +21 -0
  194. data/spec/item/becomes_spec.rb +38 -0
  195. data/spec/item/blacklisted_keywords_spec.rb +30 -0
  196. data/spec/item/delegate_spec.rb +32 -0
  197. data/spec/item/destroy_spec.rb +113 -0
  198. data/spec/item/dig_spec.rb +29 -0
  199. data/spec/item/error_codes_spec.rb +55 -0
  200. data/spec/item/errors_spec.rb +324 -0
  201. data/spec/item/fetch_spec.rb +39 -0
  202. data/spec/item/getter_spec.rb +24 -0
  203. data/spec/item/internal_data_structure_spec.rb +37 -0
  204. data/spec/item/map_spec.rb +46 -0
  205. data/spec/item/nested_errors_spec.rb +28 -0
  206. data/spec/item/partial_update_spec.rb +170 -0
  207. data/spec/item/respond_to_spec.rb +31 -0
  208. data/spec/item/save_spec.rb +115 -0
  209. data/spec/item/setter_spec.rb +44 -0
  210. data/spec/item/translate_errors_spec.rb +257 -0
  211. data/spec/item/update_spec.rb +161 -0
  212. data/spec/item/validation_spec.rb +131 -0
  213. data/spec/item/warning_codes_spec.rb +55 -0
  214. data/spec/item/warnings_spec.rb +52 -0
  215. data/spec/option_blocks/ensure_reset_between_requests_spec.rb +23 -0
  216. data/spec/option_blocks/main_spec.rb +55 -0
  217. data/spec/pagination/link/current_page_spec.rb +19 -0
  218. data/spec/pagination/link/pages_left_spec.rb +36 -0
  219. data/spec/pagination/link/parallel_spec.rb +19 -0
  220. data/spec/pagination/link/total_spec.rb +46 -0
  221. data/spec/pagination/offset/pages_left_spec.rb +26 -0
  222. data/spec/pagination/parameters_spec.rb +61 -0
  223. data/spec/proxy/create_sub_resource_spec.rb +182 -0
  224. data/spec/proxy/load_spec.rb +75 -0
  225. data/spec/proxy/record_identification_spec.rb +35 -0
  226. data/spec/rails_helper.rb +13 -0
  227. data/spec/record/all_spec.rb +133 -0
  228. data/spec/record/attribute_assignment_spec.rb +28 -0
  229. data/spec/record/build_spec.rb +26 -0
  230. data/spec/record/cast_nested_data_spec.rb +78 -0
  231. data/spec/record/create_spec.rb +160 -0
  232. data/spec/record/creation_failed_spec.rb +55 -0
  233. data/spec/record/custom_setters_spec.rb +45 -0
  234. data/spec/record/definitions_spec.rb +29 -0
  235. data/spec/record/destroy_spec.rb +38 -0
  236. data/spec/record/dig_configuration_spec.rb +75 -0
  237. data/spec/record/dup_spec.rb +20 -0
  238. data/spec/record/endpoint_inheritance_spec.rb +65 -0
  239. data/spec/record/endpoint_options_spec.rb +52 -0
  240. data/spec/record/endpoint_priorities_spec.rb +26 -0
  241. data/spec/record/endpoints_spec.rb +96 -0
  242. data/spec/record/equality_spec.rb +27 -0
  243. data/spec/record/error_handling_integration_spec.rb +25 -0
  244. data/spec/record/error_handling_spec.rb +40 -0
  245. data/spec/record/expanded_spec.rb +69 -0
  246. data/spec/record/fetch_spec.rb +41 -0
  247. data/spec/record/find_by_chains_spec.rb +21 -0
  248. data/spec/record/find_by_spec.rb +76 -0
  249. data/spec/record/find_each_spec.rb +57 -0
  250. data/spec/record/find_in_batches_spec.rb +122 -0
  251. data/spec/record/find_in_parallel_spec.rb +67 -0
  252. data/spec/record/find_spec.rb +104 -0
  253. data/spec/record/first_spec.rb +39 -0
  254. data/spec/record/force_merge_spec.rb +56 -0
  255. data/spec/record/handle_includes_errors_spec.rb +32 -0
  256. data/spec/record/has_many_spec.rb +120 -0
  257. data/spec/record/has_one_spec.rb +116 -0
  258. data/spec/record/href_for_spec.rb +25 -0
  259. data/spec/record/ignore_errors_spec.rb +139 -0
  260. data/spec/record/immutable_chains_spec.rb +22 -0
  261. data/spec/record/includes_first_page_spec.rb +737 -0
  262. data/spec/record/includes_spec.rb +693 -0
  263. data/spec/record/includes_warning_spec.rb +46 -0
  264. data/spec/record/item_key_spec.rb +81 -0
  265. data/spec/record/items_created_key_configuration_spec.rb +37 -0
  266. data/spec/record/last_spec.rb +68 -0
  267. data/spec/record/loading_twice_spec.rb +19 -0
  268. data/spec/record/mapping_spec.rb +102 -0
  269. data/spec/record/model_name_spec.rb +17 -0
  270. data/spec/record/new_spec.rb +106 -0
  271. data/spec/record/options_getter_spec.rb +26 -0
  272. data/spec/record/options_spec.rb +164 -0
  273. data/spec/record/paginatable_collection_spec.rb +360 -0
  274. data/spec/record/pagination_chain_spec.rb +101 -0
  275. data/spec/record/pagination_links_spec.rb +72 -0
  276. data/spec/record/pagination_spec.rb +71 -0
  277. data/spec/record/persisted_spec.rb +52 -0
  278. data/spec/record/provider_spec.rb +41 -0
  279. data/spec/record/references_spec.rb +53 -0
  280. data/spec/record/relation_caching_spec.rb +121 -0
  281. data/spec/record/reload_by_id_spec.rb +43 -0
  282. data/spec/record/reload_spec.rb +65 -0
  283. data/spec/record/request_spec.rb +90 -0
  284. data/spec/record/save_spec.rb +40 -0
  285. data/spec/record/scope_chains_spec.rb +39 -0
  286. data/spec/record/select_spec.rb +17 -0
  287. data/spec/record/to_ary_spec.rb +65 -0
  288. data/spec/record/to_hash_spec.rb +22 -0
  289. data/spec/record/to_json_spec.rb +22 -0
  290. data/spec/record/tracing_spec.rb +154 -0
  291. data/spec/record/update_spec.rb +62 -0
  292. data/spec/record/where_chains_spec.rb +57 -0
  293. data/spec/record/where_spec.rb +62 -0
  294. data/spec/record/where_values_hash_spec.rb +32 -0
  295. data/spec/request_cycle_cache_spec.rb +106 -0
  296. data/spec/require_lhs_spec.rb +9 -0
  297. data/spec/spec_helper.rb +6 -0
  298. data/spec/stubs/all_spec.rb +72 -0
  299. data/spec/support/fixtures/json/feedback.json +11 -0
  300. data/spec/support/fixtures/json/feedbacks.json +174 -0
  301. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  302. data/spec/support/load_json.rb +5 -0
  303. data/spec/support/request_cycle_cache.rb +10 -0
  304. data/spec/support/reset.rb +67 -0
  305. data/spec/views/form_for_spec.rb +20 -0
  306. metadata +776 -0
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ describe LHS, type: :request do
6
+ context 'autoloading' do
7
+
8
+ let(:endpoints) { LHS::Record::Endpoints.all }
9
+
10
+ it "pre/re-loads all LHS classes initialy, because it's necessary for endpoint-to-record-class-discovery", reset_before: false do
11
+
12
+ expect(endpoints['http://datastore/v2/users']).to be_present
13
+ expect(endpoints['http://datastore/v2/users/{id}']).to be_present
14
+
15
+ expect(
16
+ DummyUser.endpoints.detect { |endpoint| endpoint.url == 'http://datastore/v2/users' }
17
+ ).to be_present
18
+ expect(
19
+ DummyUser.endpoints.detect { |endpoint| endpoint.url == 'http://datastore/v2/users/{id}' }
20
+ ).to be_present
21
+ end
22
+
23
+ it "also pre/re-loads all LHS classes that inherited from an LHS provider, because it's necessary for endpoint-to-record-class-discovery", reset_before: false do
24
+
25
+ expect(endpoints['http://customers']).to be_present
26
+ expect(endpoints['http://customers/{id}']).to be_present
27
+
28
+ expect(
29
+ DummyCustomer.endpoints.detect { |endpoint| endpoint.url == 'http://customers' }
30
+ ).to be_present
31
+ expect(
32
+ DummyCustomer.endpoints.detect { |endpoint| endpoint.url == 'http://customers/{id}' }
33
+ ).to be_present
34
+
35
+ customer_request = stub_request(:get, "http://customers/1")
36
+ .with(
37
+ headers: {
38
+ 'Authorization' => 'token123'
39
+ }
40
+ )
41
+ .to_return(body: { name: 'Steve' }.to_json)
42
+
43
+ DummyCustomer.find(1)
44
+
45
+ expect(customer_request).to have_been_requested
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:items) { [{ name: 'Steve' }] }
7
+ let(:extra) { 'extra' }
8
+ let(:collection) { Record.where }
9
+
10
+ context 'accessors' do
11
+ let(:response_data) do
12
+ {
13
+ items: items,
14
+ extra: extra,
15
+ total: 1
16
+ }
17
+ end
18
+
19
+ before do
20
+ class Record < LHS::Record
21
+ endpoint 'http://datastore/records`'
22
+ end
23
+ stub_request(:get, %r{http://datastore/records})
24
+ .to_return(body: response_data.to_json)
25
+ end
26
+
27
+ it 'allows access to extra data passed with collection' do
28
+ expect(collection.extra).to eq(extra)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:datastore) { 'http://local.ch/v2' }
7
+ let(:items) { [{ name: 'Steve' }] }
8
+ let(:collection) { Account.where }
9
+
10
+ before do
11
+ LHC.config.placeholder('datastore', datastore)
12
+ class Account < LHS::Record
13
+ endpoint '{+datastore}/accounts'
14
+ end
15
+ stub_request(:get, "http://local.ch/v2/accounts")
16
+ .to_return(body: response_data.to_json)
17
+ end
18
+
19
+ context 'plain array' do
20
+ let(:response_data) do
21
+ items
22
+ end
23
+
24
+ it 'initalises a collection' do
25
+ expect(collection.first.name).to eq 'Steve'
26
+ end
27
+
28
+ it 'casts items to be instance of defined LHS::Record' do
29
+ expect(collection.first).to be_kind_of Account
30
+ end
31
+ end
32
+
33
+ context 'items key' do
34
+ let(:response_data) do
35
+ {
36
+ items: items
37
+ }
38
+ end
39
+
40
+ it 'initalises a collection when reponse contains a key items containing an array of items' do
41
+ expect(collection.first.name).to eq 'Steve'
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:search) { 'http://local.ch/search' }
7
+ let(:limit) { 10 }
8
+ let(:total) { 20 }
9
+
10
+ before do
11
+ LHC.config.placeholder('search', search)
12
+ class Search < LHS::Record
13
+ configuration items_key: :docs, limit_key: :size, pagination_key: :start, pagination_strategy: :start, total_key: :totalResults
14
+ endpoint '{+search}/{type}'
15
+ end
16
+ stub_request(:get, "http://local.ch/search/phonebook?size=10").to_return(
17
+ body: {
18
+ docs: (1..10).to_a,
19
+ start: 1,
20
+ size: limit,
21
+ totalResults: total
22
+ }.to_json
23
+ )
24
+ stub_request(:get, "http://local.ch/search/phonebook?size=10&start=11").to_return(
25
+ body: {
26
+ docs: (11..20).to_a,
27
+ start: 11,
28
+ size: limit,
29
+ totalResults: total
30
+ }.to_json
31
+ )
32
+ end
33
+
34
+ context 'lets you configure how to deal with collections' do
35
+ it 'initalises and gives access to collections according to configuration' do
36
+ results = Search.all(type: :phonebook, size: 10)
37
+ expect(results.count).to eq total
38
+ expect(results.total).to eq total
39
+ expect(results.limit).to eq limit
40
+ expect(results.offset).to eq 11
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:data) do
7
+ ['ROLE_USER', 'ROLE_LOCALCH_ACCOUNT']
8
+ end
9
+
10
+ let(:collection) do
11
+ LHS::Collection.new(LHS::Data.new(data))
12
+ end
13
+
14
+ context 'delegates methods to raw' do
15
+ %w(length size last sample present? blank? empty? compact).each do |method|
16
+ it "delegates #{method} to raw" do
17
+ expect(collection.send(method.to_sym)).not_to be_nil
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:data) do
7
+ [1, 2, 3]
8
+ end
9
+
10
+ let(:collection) do
11
+ LHS::Collection.new(LHS::Data.new(data))
12
+ end
13
+
14
+ context 'enumerable' do
15
+ it 'works with map' do
16
+ expect(
17
+ collection.map { |x| x + 1 }
18
+ ).to eq [2, 3, 4]
19
+ end
20
+
21
+ it 'works with select' do
22
+ expect(
23
+ collection.select { |x| x == 2 }
24
+ ).to eq [2]
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:collection) do
7
+ LHS::Collection.new(LHS::Data.new([]))
8
+ end
9
+
10
+ context 'array misses href' do
11
+ it 'works with empty array' do
12
+ expect(
13
+ collection.href
14
+ ).to eq nil
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:total) { 0 }
7
+
8
+ let(:limit) { 50 }
9
+
10
+ let(:offset) { 0 }
11
+
12
+ let(:collection) do
13
+ {
14
+ href: "#{datastore}/feedbacks",
15
+ items: [],
16
+ total: total,
17
+ limit: limit,
18
+ offset: offset
19
+ }
20
+ end
21
+
22
+ let(:item) do
23
+ {
24
+ href: "#{datastore}/users/1",
25
+ feedbacks: collection
26
+ }
27
+ end
28
+
29
+ let(:datastore) { 'http://local.ch/v2' }
30
+
31
+ before do
32
+ LHC.config.placeholder('datastore', datastore)
33
+ class Feedback < LHS::Record
34
+ endpoint '{+datastore}/feedbacks'
35
+ endpoint '{+datastore}/feedbacks/{id}'
36
+ end
37
+ class User < LHS::Record
38
+ endpoint '{+datastore}/users'
39
+ endpoint '{+datastore}/users/{id}'
40
+ end
41
+ end
42
+
43
+ it 'provides meta data for collections' do
44
+ stub_request(:get, "#{datastore}/feedbacks").to_return(status: 200, body: collection.to_json)
45
+ feedbacks = Feedback.where
46
+ expect(feedbacks.total).to eq total
47
+ expect(feedbacks.limit).to eq limit
48
+ expect(feedbacks.offset).to eq offset
49
+ expect(feedbacks.href).to eq "#{datastore}/feedbacks"
50
+ end
51
+
52
+ it 'provides meta data also when navigating' do
53
+ stub_request(:get, "#{datastore}/users/1").to_return(status: 200, body: item.to_json)
54
+ user = User.find(1)
55
+ expect(user.feedbacks.href).to eq "#{datastore}/feedbacks"
56
+ end
57
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:data) do
7
+ ['ROLE_USER', 'ROLE_LOCALCH_ACCOUNT']
8
+ end
9
+
10
+ let(:collection) do
11
+ LHS::Data.new(LHS::Data.new(data))
12
+ end
13
+
14
+ context '#respond_to?' do
15
+ # In this case raw collection is an Array implementing first
16
+ it 'forwards calls to raw collection' do
17
+ expect(collection.respond_to?(:first)).to be(true)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:items) { [{ name: 'Steve' }] }
7
+ let(:extra) { 'extra' }
8
+ let(:collection) { Record.where }
9
+
10
+ context 'to_a' do
11
+ let(:response_data) do
12
+ {
13
+ items: items,
14
+ extra: extra,
15
+ total: 1
16
+ }
17
+ end
18
+
19
+ let(:subject) { collection.to_a }
20
+
21
+ before do
22
+ class Record < LHS::Record
23
+ endpoint 'http://datastore/records`'
24
+ end
25
+ stub_request(:get, %r{http://datastore/records})
26
+ .to_return(body: response_data.to_json)
27
+ end
28
+
29
+ it 'returns an array and not LHS::Data' do
30
+ expect(subject).to be_kind_of Array
31
+ expect(subject).not_to be_kind_of LHS::Data
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:items) { [{ name: 'Steve' }] }
7
+ let(:extra) { 'extra' }
8
+ let(:collection) { Record.where }
9
+
10
+ context 'to_ary' do
11
+ before do
12
+ class Record < LHS::Record
13
+ endpoint 'http://datastore/records`'
14
+ end
15
+ stub_request(:get, %r{http://datastore/records})
16
+ .to_return(body: response_data.to_json)
17
+ end
18
+
19
+ let(:response_data) do
20
+ {
21
+ items: items,
22
+ extra: extra,
23
+ total: 1
24
+ }
25
+ end
26
+
27
+ let(:subject) { collection.to_ary }
28
+
29
+ it 'returns an array' do
30
+ expect(subject).to be_present
31
+ expect(subject).to be_kind_of Array
32
+ expect(subject[0]).to be_kind_of Record
33
+ expect(subject[0].name).to eq 'Steve'
34
+ end
35
+
36
+ it 'responds to to_ary' do
37
+ expect(subject.respond_to?(:to_ary)).to eq true
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Collection do
6
+ let(:datastore) { 'http://local.ch/v2' }
7
+
8
+ before do
9
+ LHC.config.placeholder('datastore', datastore)
10
+ class Account < LHS::Record
11
+ endpoint '{+datastore}/accounts/{id}'
12
+ end
13
+ end
14
+
15
+ let(:data) {
16
+ {
17
+ 'authorities' => ['ROLE_USER', 'ROLE_LOCALCH_ACCOUNT']
18
+ }
19
+ }
20
+
21
+ it 'lets you access items of an array if they are not objects' do
22
+ stub_request(:get, "#{datastore}/accounts/1").to_return(status: 200, body: data.to_json)
23
+ feedback = Account.find(1)
24
+ expect(feedback.authorities.first).to eq 'ROLE_USER'
25
+ expect(feedback.authorities[1]).to eq 'ROLE_LOCALCH_ACCOUNT'
26
+ end
27
+ end
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Complex do
6
+ it 'returns nil when result is empty' do
7
+ expect(LHS::Complex.reduce([])).to be_nil
8
+ end
9
+
10
+ it 'forwards primitive types' do
11
+ expect(LHS::Complex.reduce(entry_id: 123)).to eq(entry_id: 123)
12
+ end
13
+
14
+ it 'fails when trying to merge primitive types' do
15
+ expect {
16
+ LHS::Complex.reduce([{ entry: true }, { entry: :content }])
17
+ }.to raise_error(ArgumentError)
18
+ end
19
+
20
+ it 'does not fail trying to merge primitive types when they are the same' do
21
+ expect {
22
+ LHS::Complex.reduce([{ entry: true }, { entry: true }])
23
+ }.not_to raise_error
24
+ end
25
+
26
+ context 'first level' do
27
+ context 'reduces symbols into/with X' do
28
+ it 'reduces symbols into hash' do
29
+ expect(LHS::Complex.reduce([
30
+ { entries: :contract },
31
+ :entries
32
+ ])).to eq(entries: :contract)
33
+ end
34
+
35
+ it 'reduces symbols into array' do
36
+ expect(LHS::Complex.reduce([
37
+ [:contracts],
38
+ :entries
39
+ ])).to eq([:contracts, :entries])
40
+ expect(LHS::Complex.reduce([
41
+ [:entries],
42
+ :entries
43
+ ])).to eq(:entries)
44
+ end
45
+
46
+ it 'reduces symbols with symbols' do
47
+ expect(LHS::Complex.reduce([
48
+ :contracts,
49
+ :entries
50
+ ])).to eq([:contracts, :entries])
51
+ expect(LHS::Complex.reduce([
52
+ :entries,
53
+ :entries
54
+ ])).to eq(:entries)
55
+ end
56
+ end
57
+
58
+ context 'reduces arrays into/with X' do
59
+ it 'reduces arrays into an hash' do
60
+ expect(LHS::Complex.reduce([
61
+ { entries: :contract },
62
+ [:entries]
63
+ ])).to eq(entries: :contract)
64
+ expect(LHS::Complex.reduce([
65
+ { entries: :contract },
66
+ [:products]
67
+ ])).to eq([{ entries: :contract }, :products])
68
+ end
69
+
70
+ it 'reduces arrays into an arrays' do
71
+ expect(LHS::Complex.reduce([
72
+ [:entries],
73
+ [:entries]
74
+ ])).to eq(:entries)
75
+ expect(LHS::Complex.reduce([
76
+ [:entries],
77
+ [:products]
78
+ ])).to eq([:entries, :products])
79
+ end
80
+
81
+ it 'reduces arrays into an symbols' do
82
+ expect(LHS::Complex.reduce([
83
+ :entries,
84
+ [:entries]
85
+ ])).to eq(:entries)
86
+ expect(LHS::Complex.reduce([
87
+ :entries,
88
+ [:products]
89
+ ])).to eq([:entries, :products])
90
+ end
91
+ end
92
+
93
+ context 'reduces hashes into/with X' do
94
+ it 'reduces hash into an hash' do
95
+ expect(LHS::Complex.reduce([
96
+ { entries: :contract },
97
+ { entries: :products }
98
+ ])).to eq(entries: [:contract, :products])
99
+ expect(LHS::Complex.reduce([
100
+ { entries: :contract },
101
+ { entries: :contract }
102
+ ])).to eq(entries: :contract)
103
+ end
104
+
105
+ it 'reduces hash into an array' do
106
+ expect(LHS::Complex.reduce([
107
+ [:entries],
108
+ { entries: :products }
109
+ ])).to eq(entries: :products)
110
+ expect(LHS::Complex.reduce([
111
+ [{ entries: :contract }],
112
+ { entries: :contract }
113
+ ])).to eq(entries: :contract)
114
+ end
115
+
116
+ it 'reduces hash into a symbol' do
117
+ expect(LHS::Complex.reduce([
118
+ :entries,
119
+ { entries: :products }
120
+ ])).to eq(entries: :products)
121
+ expect(LHS::Complex.reduce([
122
+ :products,
123
+ { entries: :contract }
124
+ ])).to eq([:products, { entries: :contract }])
125
+ end
126
+ end
127
+
128
+ context 'reduces array into/with X' do
129
+ it 'reduces array into hash' do
130
+ expect(LHS::Complex.reduce([
131
+ { entries: :contract },
132
+ [:entries, :products]
133
+ ])).to eq([{ entries: :contract }, :products])
134
+ end
135
+
136
+ it 'reduces array into array' do
137
+ expect(LHS::Complex.reduce([
138
+ [:contracts],
139
+ [:entries, :products, :contracts]
140
+ ])).to eq([:contracts, :entries, :products])
141
+ end
142
+
143
+ it 'reduces array with symbols' do
144
+ expect(LHS::Complex.reduce([
145
+ :contracts,
146
+ [:entries, :products]
147
+ ])).to eq([:contracts, :entries, :products])
148
+ end
149
+ end
150
+ end
151
+
152
+ context 'multi-level' do
153
+ it 'reduces a complex multi-level example' do
154
+ expect(LHS::Complex.reduce([
155
+ :contracts,
156
+ [:entries, products: { content_ads: :address }],
157
+ products: { content_ads: { place: :location } }
158
+ ])).to eq([
159
+ :contracts,
160
+ :entries,
161
+ products: { content_ads: [:address, { place: :location }] }
162
+ ])
163
+ end
164
+
165
+ it 'reduces another complex multi-level example' do
166
+ expect(LHS::Complex.reduce([
167
+ [entries: :content_ads, products: :price],
168
+ [:entries, products: { content_ads: :address }],
169
+ [entries: { content_ads: :owner }, products: [{ price: :region }, :image, { content_ads: :owner }]]
170
+ ])).to eq(
171
+ entries: { content_ads: :owner },
172
+ products: [{ content_ads: [:address, :owner], price: :region }, :image]
173
+ )
174
+ end
175
+
176
+ it 'reduces another complex multi-level example (single plus array)' do
177
+ expect(LHS::Complex.reduce([
178
+ { entries: :products },
179
+ { entries: [:customer, :contracts] }
180
+ ])).to eq(
181
+ entries: [:products, :customer, :contracts]
182
+ )
183
+ end
184
+
185
+ it 'reduces another complex multi-level example (single hash plus array)' do
186
+ expect(LHS::Complex.reduce([
187
+ { entries: { customer: :contracts } },
188
+ { entries: [:customer, :content_ads] }
189
+ ])).to eq(
190
+ entries: [{ customer: :contracts }, :content_ads]
191
+ )
192
+ end
193
+
194
+ it 'reduces properly' do
195
+ expect(LHS::Complex.reduce([
196
+ [:entries, :place, :content_ads], [{ place: :content_ads }], { content_ads: :place }
197
+ ])).to eq(
198
+ [:entries, { place: :content_ads, content_ads: :place }]
199
+ )
200
+ end
201
+ end
202
+ end