jat 0.0.1 → 0.0.3

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +21 -0
  4. data/jat.gemspec +37 -0
  5. data/lib/jat/attribute.rb +85 -0
  6. data/lib/jat/config.rb +38 -0
  7. data/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads.rb +29 -0
  8. data/lib/jat/plugins/_activerecord_preloads/lib/preloader.rb +89 -0
  9. data/lib/jat/plugins/_json_api_activerecord/_json_api_activerecord.rb +22 -0
  10. data/lib/jat/plugins/_json_api_activerecord/lib/preloads.rb +84 -0
  11. data/lib/jat/plugins/_preloads/_preloads.rb +53 -0
  12. data/lib/jat/plugins/_preloads/lib/format_user_preloads.rb +52 -0
  13. data/lib/jat/plugins/_preloads/lib/preloads_with_path.rb +78 -0
  14. data/lib/jat/plugins/cache/cache.rb +39 -0
  15. data/lib/jat/plugins/camel_lower/camel_lower.rb +18 -0
  16. data/lib/jat/plugins/json_api/json_api.rb +207 -0
  17. data/lib/jat/plugins/json_api/lib/construct_traversal_map.rb +91 -0
  18. data/lib/jat/plugins/json_api/lib/map.rb +54 -0
  19. data/lib/jat/plugins/json_api/lib/params/fields/parse.rb +27 -0
  20. data/lib/jat/plugins/json_api/lib/params/fields/validate.rb +55 -0
  21. data/lib/jat/plugins/json_api/lib/params/fields.rb +23 -0
  22. data/lib/jat/plugins/json_api/lib/params/include/parse.rb +55 -0
  23. data/lib/jat/plugins/json_api/lib/params/include/validate.rb +29 -0
  24. data/lib/jat/plugins/json_api/lib/params/include.rb +49 -0
  25. data/lib/jat/plugins/json_api/lib/presenters/document_links_presenter.rb +48 -0
  26. data/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter.rb +48 -0
  27. data/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter.rb +48 -0
  28. data/lib/jat/plugins/json_api/lib/presenters/links_presenter.rb +48 -0
  29. data/lib/jat/plugins/json_api/lib/presenters/meta_presenter.rb +48 -0
  30. data/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter.rb +53 -0
  31. data/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter.rb +53 -0
  32. data/lib/jat/plugins/json_api/lib/response.rb +239 -0
  33. data/lib/jat/plugins/json_api/lib/traversal_map.rb +34 -0
  34. data/lib/jat/plugins/simple_api/lib/construct_traversal_map.rb +45 -0
  35. data/lib/jat/plugins/simple_api/lib/map.rb +29 -0
  36. data/lib/jat/plugins/simple_api/lib/params/parse.rb +68 -0
  37. data/lib/jat/plugins/simple_api/lib/response.rb +134 -0
  38. data/lib/jat/plugins/simple_api/simple_api.rb +65 -0
  39. data/lib/jat/plugins/to_str/to_str.rb +44 -0
  40. data/lib/jat/plugins.rb +39 -0
  41. data/lib/jat/presenter.rb +51 -0
  42. data/lib/jat/utils/enum_deep_dup.rb +29 -0
  43. data/lib/jat/utils/enum_deep_freeze.rb +19 -0
  44. data/lib/jat.rb +66 -144
  45. data/test/lib/jat/attribute_test.rb +142 -0
  46. data/test/lib/jat/config_test.rb +57 -0
  47. data/test/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads_test.rb +40 -0
  48. data/test/lib/jat/plugins/_activerecord_preloads/lib/preloader_test.rb +98 -0
  49. data/test/lib/jat/plugins/_json_api_activerecord/_json_api_activerecord_test.rb +29 -0
  50. data/test/lib/jat/plugins/_json_api_activerecord/lib/preloads_test.rb +191 -0
  51. data/test/lib/jat/plugins/_preloads/_preloads_test.rb +68 -0
  52. data/test/lib/jat/plugins/_preloads/lib/format_user_preloads_test.rb +47 -0
  53. data/test/lib/jat/plugins/_preloads/lib/preloads_with_path_test.rb +33 -0
  54. data/test/lib/jat/plugins/cache/cache_test.rb +82 -0
  55. data/test/lib/jat/plugins/camel_lower/camel_lower_test.rb +78 -0
  56. data/test/lib/jat/plugins/json_api/json_api_test.rb +154 -0
  57. data/test/lib/jat/plugins/json_api/lib/construct_traversal_map_test.rb +119 -0
  58. data/test/lib/jat/plugins/json_api/lib/map_test.rb +117 -0
  59. data/test/lib/jat/plugins/json_api/lib/params/fields/parse_test.rb +24 -0
  60. data/test/lib/jat/plugins/json_api/lib/params/fields/validate_test.rb +47 -0
  61. data/test/lib/jat/plugins/json_api/lib/params/fields_test.rb +37 -0
  62. data/test/lib/jat/plugins/json_api/lib/params/include/parse_test.rb +46 -0
  63. data/test/lib/jat/plugins/json_api/lib/params/include/validate_test.rb +51 -0
  64. data/test/lib/jat/plugins/json_api/lib/params/include_test.rb +41 -0
  65. data/test/lib/jat/plugins/json_api/lib/presenters/document_links_presenter_test.rb +69 -0
  66. data/test/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter_test.rb +69 -0
  67. data/test/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter_test.rb +69 -0
  68. data/test/lib/jat/plugins/json_api/lib/presenters/links_presenter_test.rb +69 -0
  69. data/test/lib/jat/plugins/json_api/lib/presenters/meta_presenter_test.rb +69 -0
  70. data/test/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter_test.rb +75 -0
  71. data/test/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter_test.rb +75 -0
  72. data/test/lib/jat/plugins/json_api/lib/response_test.rb +489 -0
  73. data/test/lib/jat/plugins/json_api/lib/traversal_map_test.rb +58 -0
  74. data/test/lib/jat/plugins/simple_api/lib/construct_traversal_map_test.rb +100 -0
  75. data/test/lib/jat/plugins/simple_api/lib/map_test.rb +56 -0
  76. data/test/lib/jat/plugins/simple_api/lib/params/parse_test.rb +71 -0
  77. data/test/lib/jat/plugins/simple_api/lib/response_test.rb +342 -0
  78. data/test/lib/jat/plugins/simple_api/simple_api_test.rb +81 -0
  79. data/test/lib/jat/plugins/to_str/to_str_test.rb +52 -0
  80. data/test/lib/jat/presenter_test.rb +61 -0
  81. data/test/lib/jat/utils/enum_deep_dup_test.rb +31 -0
  82. data/test/lib/jat/utils/enum_deep_freeze_test.rb +28 -0
  83. data/test/lib/jat_test.rb +120 -0
  84. data/test/lib/plugin_test.rb +49 -0
  85. data/test/support/activerecord.rb +24 -0
  86. data/test/test_helper.rb +16 -0
  87. data/test/test_plugin.rb +59 -0
  88. metadata +240 -11
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe "Jat::Plugins::SimpleApi::Params::Parse" do
6
+ before do
7
+ Jat::Plugins.load_plugin :simple_api
8
+ end
9
+
10
+ def parse(str)
11
+ Jat::Plugins::SimpleApi::Params::Parse.new(str).parse
12
+ end
13
+
14
+ it "returns empty hash when nil provided" do
15
+ assert_equal({}, parse(nil))
16
+ end
17
+
18
+ it "returns empty hash when empty string provided" do
19
+ assert_equal({}, parse(""))
20
+ end
21
+
22
+ it "parses single field" do
23
+ assert_equal({id: {}}, parse("id"))
24
+ end
25
+
26
+ it "parses multiple fields" do
27
+ assert_equal({id: {}, name: {}}, parse("id,name"))
28
+ end
29
+
30
+ it "parses single resource with single field" do
31
+ assert_equal({users: {id: {}}}, parse("users(id)"))
32
+ end
33
+
34
+ it "parses fields started with open PAREN" do
35
+ assert_equal({users: {id: {}}}, parse("(users(id))"))
36
+ end
37
+
38
+ it "parses single resource with multiple fields" do
39
+ assert_equal({users: {id: {}, name: {}}}, parse("users(id,name)"))
40
+ end
41
+
42
+ it "parses multiple resources with fields" do
43
+ fields = "id,posts(title,text),news(title,text)"
44
+ resp = {
45
+ id: {},
46
+ posts: {title: {}, text: {}},
47
+ news: {title: {}, text: {}}
48
+ }
49
+
50
+ assert_equal(resp, parse(fields))
51
+ end
52
+
53
+ it "parses included resources" do
54
+ fields = "id,posts(title,text,comments(author(name),comment))"
55
+ resp = {
56
+ id: {},
57
+ posts: {
58
+ title: {},
59
+ text: {},
60
+ comments: {
61
+ author: {
62
+ name: {}
63
+ },
64
+ comment: {}
65
+ }
66
+ }
67
+ }
68
+
69
+ assert_equal(resp, parse(fields))
70
+ end
71
+ end
@@ -0,0 +1,342 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe "Jat::Plugins::SimpleApi::Response" do
6
+ let(:base_class) { Class.new(Jat) { plugin :simple_api } }
7
+
8
+ it "returns empty hash when nothing to serialize" do
9
+ empty_serializer = Class.new(base_class)
10
+
11
+ assert_equal({}, empty_serializer.to_h(nil))
12
+ end
13
+
14
+ it "returns correct structure with meta" do
15
+ empty_serializer = Class.new(base_class)
16
+
17
+ assert_equal({meta: {any: :thing}}, empty_serializer.to_h(nil, meta: {any: :thing}))
18
+ end
19
+
20
+ it "returns correct structure with data" do
21
+ str_serializer = Class.new(base_class) do
22
+ attribute(:id) { |_| "STRING" }
23
+ end
24
+
25
+ assert_equal({id: "STRING"}, str_serializer.to_h("STRING"))
26
+ end
27
+
28
+ it "returns correct structure when parameter `many` defined manually" do
29
+ str_serializer = Class.new(base_class) do
30
+ attribute(:id) { |obj| obj[:foo] }
31
+ end
32
+
33
+ # By default hash is interpreted as `many: true` as it is Enumerable
34
+ obj = {foo: :bar}
35
+ context = {many: false}
36
+
37
+ assert_equal({id: :bar}, str_serializer.to_h(obj, context))
38
+ end
39
+
40
+ it "returns correct structure with array data" do
41
+ str_serializer = Class.new(base_class) do
42
+ attribute(:id) { |obj| obj }
43
+ end
44
+
45
+ assert_equal(
46
+ [{id: "1"}, {id: "2"}],
47
+ str_serializer.to_h(%w[1 2])
48
+ )
49
+ end
50
+
51
+ it "raises error when trying to add meta to response without root key" do
52
+ str_serializer = Class.new(base_class) do
53
+ attribute(:id) { |obj| obj }
54
+ end
55
+
56
+ error = assert_raises(Jat::Error) { str_serializer.to_h("1", meta: {foo: :bar}) }
57
+ assert_equal "Response must have a root key to add metadata", error.message
58
+
59
+ error = assert_raises(Jat::Error) { str_serializer.to_h(["1"], meta: {foo: :bar}) }
60
+ assert_equal "Response must have a root key to add metadata", error.message
61
+ end
62
+
63
+ it "returns correct structure with array data" do
64
+ str_serializer = Class.new(base_class) do
65
+ attribute(:id) { |obj| obj }
66
+ end
67
+
68
+ assert_equal(
69
+ [{id: "1"}, {id: "2"}],
70
+ str_serializer.to_h(%w[1 2])
71
+ )
72
+ end
73
+
74
+ it "returns correct structure with one object with root key" do
75
+ str_serializer = Class.new(base_class) do
76
+ root(:digit)
77
+ attribute(:id) { |obj| obj }
78
+ end
79
+
80
+ assert_equal({digit: {id: "1"}}, str_serializer.to_h("1"))
81
+ end
82
+
83
+ it "returns correct structure with list with root key" do
84
+ str_serializer = Class.new(base_class) do
85
+ root(:digits)
86
+ attribute(:id) { |obj| obj }
87
+ end
88
+
89
+ assert_equal(
90
+ {digits: [{id: "1"}, {id: "2"}]},
91
+ str_serializer.to_h(%w[1 2])
92
+ )
93
+ end
94
+
95
+ it "returns correct structures root_for_one and root_for_many keys" do
96
+ str_serializer = Class.new(base_class) do
97
+ root(:not_used)
98
+ root_for_one(:digit)
99
+ root_for_many(:digits)
100
+ attribute(:id) { |obj| obj }
101
+ end
102
+
103
+ assert_equal({digit: {id: "1"}}, str_serializer.to_h("1"))
104
+ assert_equal({digits: [{id: "1"}]}, str_serializer.to_h(["1"]))
105
+ end
106
+
107
+ it "returns correct structures when root is overwritten" do
108
+ str_serializer = Class.new(base_class) do
109
+ root(:root)
110
+ root_for_one(:root)
111
+ root_for_many(:root)
112
+ attribute(:id) { |obj| obj }
113
+ end
114
+
115
+ assert_equal({foo: {id: "1"}}, str_serializer.to_h("1", root: :foo))
116
+ assert_equal({foo: [{id: "1"}]}, str_serializer.to_h(["1"], root: :foo))
117
+ end
118
+
119
+ it "returns correct structure with data and meta" do
120
+ str_serializer = Class.new(base_class) do
121
+ root(:root)
122
+ config[:meta] = {version: "1.2.3"}
123
+
124
+ attribute(:id) { |obj| obj }
125
+ end
126
+
127
+ assert_equal(
128
+ {root: {id: "1"}, meta: {any: :thing, version: "1.2.3"}},
129
+ str_serializer.to_h("1", meta: {any: :thing})
130
+ )
131
+
132
+ assert_equal(
133
+ {root: [{id: "1"}], meta: {any: :thing, version: "1.2.3"}},
134
+ str_serializer.to_h(["1"], meta: {any: :thing})
135
+ )
136
+ end
137
+
138
+ it "returns correct structure with data multiple attributes" do
139
+ str_serializer = Class.new(base_class) do
140
+ attribute(:id) { |obj| obj }
141
+ attribute :length
142
+ end
143
+
144
+ assert_equal({id: "1", length: 1}, str_serializer.to_h("1"))
145
+ end
146
+
147
+ it "returns correct structure with has-one relationship" do
148
+ int_serializer = Class.new(base_class) do
149
+ attribute(:id) { |obj| obj }
150
+ end
151
+
152
+ str_serializer = Class.new(base_class) do
153
+ attribute(:id) { |obj| obj[0] }
154
+ attribute :length, serializer: int_serializer, exposed: true
155
+ end
156
+
157
+ assert_equal({id: "S", length: {id: 6}}, str_serializer.to_h("STRING"))
158
+ end
159
+
160
+ it "returns correct structure when children serializer defined as lambda" do
161
+ int_serializer = Class.new(base_class) do
162
+ attribute(:id) { |obj| obj }
163
+ end
164
+
165
+ str_serializer = Class.new(base_class) do
166
+ attribute(:id) { |obj| obj[0] }
167
+ attribute :length, serializer: -> { int_serializer }, exposed: true
168
+ end
169
+
170
+ assert_equal({id: "S", length: {id: 6}}, str_serializer.to_h("STRING"))
171
+ end
172
+
173
+ it "does not return has-one relationship when not exposed" do
174
+ int_serializer = Class.new(base_class) do
175
+ attribute(:id) { |obj| obj }
176
+ end
177
+
178
+ str_serializer = Class.new(base_class) do
179
+ attribute(:id) { |obj| obj[0] }
180
+ attribute :length, serializer: int_serializer, exposed: false
181
+ end
182
+
183
+ assert_equal({id: "S"}, str_serializer.to_h("STRING"))
184
+ end
185
+
186
+ it "returns nil as empty has-one relationship" do
187
+ int_serializer = Class.new(base_class)
188
+
189
+ str_serializer = Class.new(base_class) do
190
+ attribute(:id) { |obj| obj[0] }
191
+ attribute(:length, serializer: int_serializer, exposed: true) { |_obj| nil }
192
+ end
193
+
194
+ assert_equal(
195
+ {id: "S", length: nil},
196
+ str_serializer.to_h("STRING")
197
+ )
198
+ end
199
+
200
+ it "returns correct structure with has-one relationship with attributes" do
201
+ int_serializer = Class.new(base_class) do
202
+ attribute(:id) { |obj| obj }
203
+ attribute(:next) { |obj| obj + 1 }
204
+ end
205
+
206
+ str_serializer = Class.new(base_class) do
207
+ attribute(:id) { |obj| obj[0] }
208
+ attribute :length, serializer: int_serializer, exposed: true
209
+ end
210
+
211
+ assert_equal(
212
+ {id: "S", length: {id: 6, next: 7}},
213
+ str_serializer.to_h("STRING")
214
+ )
215
+ end
216
+
217
+ it "returns empty array as empty has-many relationship" do
218
+ chr_serializer = Class.new(base_class)
219
+ str_serializer = Class.new(base_class) do
220
+ attribute(:id) { |_obj| "id" }
221
+ attribute :chars, serializer: chr_serializer, many: true, exposed: true
222
+ end
223
+
224
+ assert_equal({id: "id", chars: []}, str_serializer.to_h(""))
225
+ end
226
+
227
+ it "returns correct structure with has-many relationship" do
228
+ chr_serializer = Class.new(base_class) do
229
+ attribute(:id) { |obj| obj }
230
+ end
231
+
232
+ str_serializer = Class.new(base_class) do
233
+ attribute(:id) { |obj| obj[0] }
234
+ attribute :chars, serializer: chr_serializer, many: true, exposed: true
235
+ end
236
+
237
+ assert_equal(
238
+ {id: "a", chars: [{id: "a"}, {id: "b"}]},
239
+ str_serializer.to_h("ab")
240
+ )
241
+ end
242
+
243
+ it "automatically checks if nested relationship is enumerable or single object" do
244
+ chr_serializer = Class.new(base_class) do
245
+ attribute(:id) { |obj| obj }
246
+ end
247
+
248
+ int_serializer = Class.new(base_class) do
249
+ attribute(:id) { |obj| obj }
250
+ end
251
+
252
+ str_serializer = Class.new(base_class) do
253
+ attribute(:id) { |obj| obj[0] }
254
+ attribute :chars, serializer: chr_serializer, exposed: true, many: true
255
+ attribute :length, serializer: int_serializer, exposed: true, many: false
256
+ end
257
+
258
+ assert_equal(
259
+ {id: "a", chars: [{id: "a"}, {id: "b"}], length: {id: 2}},
260
+ str_serializer.to_h("ab")
261
+ )
262
+ end
263
+
264
+ it "returns correct structure with has-many relationship with attributes" do
265
+ chr_serializer = Class.new(base_class) do
266
+ attribute(:id) { |obj| obj }
267
+ attribute :next
268
+ end
269
+
270
+ str_serializer = Class.new(base_class) do
271
+ attribute(:id) { |obj| obj[0] }
272
+ attribute :chars, serializer: chr_serializer, many: true, exposed: true
273
+ end
274
+
275
+ assert_equal(
276
+ {id: "a", chars: [{id: "a", next: "b"}, {id: "b", next: "c"}]},
277
+ str_serializer.to_h("ab")
278
+ )
279
+ end
280
+
281
+ it "accepts fields" do
282
+ # All fields are not exposed in this serializers,
283
+ # We will show only attributes provided in `fields` param
284
+ chr_serializer = Class.new(base_class) do
285
+ attribute(:id, exposed: false) { |obj| obj }
286
+ attribute :next, exposed: false
287
+ end
288
+
289
+ str_serializer = Class.new(base_class) do
290
+ attribute(:id, exposed: false) { |obj| obj }
291
+ attribute :chars, serializer: chr_serializer, many: true, exposed: false
292
+ end
293
+
294
+ assert_equal(
295
+ {chars: [{next: "b"}, {next: "c"}]},
296
+ str_serializer.to_h("ab", params: {fields: "chars(next)"})
297
+ )
298
+ end
299
+
300
+ it "does not overwrite manually added meta" do
301
+ str_serializer = Class.new(base_class) do
302
+ root(:root)
303
+ config[:meta] = {version: "1.2.3"}
304
+
305
+ attribute(:id) { |obj| obj }
306
+ end
307
+
308
+ assert_equal(
309
+ {root: {id: "1"}, meta: {version: "2.0.0"}},
310
+ str_serializer.to_h("1", meta: {version: "2.0.0"})
311
+ )
312
+ end
313
+
314
+ it "allows to provide lambda as meta key" do
315
+ str_serializer = Class.new(base_class) do
316
+ root(:root)
317
+ config[:meta] = {
318
+ obj: ->(obj, _context) { obj },
319
+ context: ->(_obj, context) { context },
320
+ time: ->(_obj, _context) { Time.new(2020, 1, 1) }
321
+ }
322
+
323
+ attribute(:id) { |obj| obj }
324
+ end
325
+
326
+ assert_equal(
327
+ {root: {id: "1"}, meta: {obj: "1", context: {foo: :bar}, time: Time.new(2020, 1, 1)}},
328
+ str_serializer.to_h("1", foo: :bar)
329
+ )
330
+ end
331
+
332
+ it "does not adds nil meta" do
333
+ str_serializer = Class.new(base_class) do
334
+ root(:root)
335
+ config[:meta] = {foo: nil, bar: proc {}}
336
+
337
+ attribute(:id) { |obj| obj }
338
+ end
339
+
340
+ assert_equal({root: {id: "1"}}, str_serializer.to_h("1", bazz: nil))
341
+ end
342
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe "Jat::Plugins::SimpleApi" do
6
+ before { @plugin = Jat::Plugins.load_plugin(:simple_api) }
7
+
8
+ let(:jat_class) do
9
+ new_class = Class.new(Jat)
10
+ new_class.plugin(plugin)
11
+ new_class.root :data
12
+ new_class.attribute :id, key: :itself
13
+ new_class
14
+ end
15
+
16
+ let(:plugin) { @plugin }
17
+
18
+ describe ".after_load" do
19
+ it "loads _json_api_activerecord plugin if activerecord option provided" do
20
+ jat_class = Class.new(Jat)
21
+ jat_class.expects(:plugin).with(:_json_api_activerecord, activerecord: true)
22
+
23
+ Jat::Plugins.after_load(plugin, jat_class, activerecord: true)
24
+ end
25
+ end
26
+
27
+ describe "InstanceMethods" do
28
+ let(:jat) { jat_class.new("JAT", {}) }
29
+
30
+ describe "#to_h" do
31
+ it "returns response in a simple-api format" do
32
+ expected_result = {data: {id: "JAT"}}
33
+ assert_equal expected_result, jat.to_h
34
+ end
35
+ end
36
+
37
+ describe "#traversal_map" do
38
+ it "returns memorized traversal_map hash" do
39
+ assert_equal jat.traversal_map.class, Hash
40
+ assert_same jat.traversal_map, jat.traversal_map
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "ClassMethods" do
46
+ describe ".inherited" do
47
+ it "inherits root" do
48
+ child = Class.new(jat_class)
49
+ assert_equal :data, child.root
50
+ end
51
+ end
52
+
53
+ describe ".root" do
54
+ it "saves and returns current root" do
55
+ assert_equal :data, jat_class.root
56
+ end
57
+
58
+ it "symbolizes root" do
59
+ jat_class.root "users"
60
+ assert_equal :users, jat_class.root
61
+ end
62
+ end
63
+
64
+ describe ".meta_key" do
65
+ it "returns default meta_key" do
66
+ assert_equal :meta, jat_class.meta_key
67
+ end
68
+
69
+ it "saves and returns meta key" do
70
+ jat_class.meta_key :metadata
71
+ assert_equal :metadata, jat_class.meta_key
72
+ assert_same jat_class.meta_key, jat_class.meta_key
73
+ end
74
+
75
+ it "symbolizes meta key" do
76
+ jat_class.meta_key "metadata"
77
+ assert_equal :metadata, jat_class.meta_key
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe "Jat::Plugins::ToStr" do
6
+ let(:jat_class) do
7
+ new_class = Class.new(Jat)
8
+ new_class.plugin(:to_str)
9
+ new_class.class_exec do
10
+ def to_h
11
+ {object => context}
12
+ end
13
+ end
14
+
15
+ new_class
16
+ end
17
+
18
+ describe "Jat" do
19
+ describe ".to_str" do
20
+ it "returns json string of to_h" do
21
+ assert_equal '{"obj":"ctx"}', jat_class.to_str("obj", "ctx")
22
+ end
23
+
24
+ it "returns json string of to_h with default empty hash context" do
25
+ assert_equal '{"obj":{}}', jat_class.to_str("obj")
26
+ end
27
+
28
+ it "returns result serialized with given in config serializer" do
29
+ jat_class.config[:to_str] = ->(data) { data.inspect }
30
+ assert_equal '{"obj"=>"ctx"}', jat_class.to_str("obj", "ctx")
31
+ end
32
+
33
+ it "accepts to_str config option when loading plugin" do
34
+ new_class = Class.new(Jat)
35
+ new_class.plugin(:to_str, to_str: ->(data) { data.inspect })
36
+ new_class.class_exec do
37
+ def to_h
38
+ {object => context}
39
+ end
40
+ end
41
+
42
+ assert_equal '{"obj"=>"ctx"}', new_class.to_str("obj", "ctx")
43
+ end
44
+ end
45
+
46
+ describe "#to_str" do
47
+ it "returns json string of to_h" do
48
+ assert_equal '{"obj":"ctx"}', jat_class.new("obj", "ctx").to_str
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe Jat::Presenter do
6
+ let(:jat_class) { Class.new(Jat) }
7
+ let(:presenter_class) { jat_class::Presenter }
8
+
9
+ describe ".jat_class=" do
10
+ it "assigns @jat_class" do
11
+ presenter_class.jat_class = :foo
12
+ assert_equal :foo, presenter_class.instance_variable_get(:@jat_class)
13
+ end
14
+ end
15
+
16
+ describe ".jat_class" do
17
+ it "returns self @jat_class" do
18
+ assert_same jat_class, presenter_class.instance_variable_get(:@jat_class)
19
+ assert_same jat_class, presenter_class.jat_class
20
+ end
21
+ end
22
+
23
+ describe ".inspect" do
24
+ it "returns self name" do
25
+ assert_equal "#{jat_class}::Presenter", presenter_class.inspect
26
+ end
27
+ end
28
+
29
+ describe ".add_method" do
30
+ let(:presenter) { presenter_class.new("OBJECT", "CONTEXT") }
31
+
32
+ it "adds method by providing block without variables" do
33
+ presenter_class.add_method(:foo, proc { [object, context] })
34
+ assert_equal %w[OBJECT CONTEXT], presenter.foo
35
+ end
36
+
37
+ it "adds method by providing block with one variables" do
38
+ presenter_class.add_method(:foo, proc { |obj| [obj, object, context] })
39
+ assert_equal %w[OBJECT OBJECT CONTEXT], presenter.foo
40
+ end
41
+
42
+ it "adds method by providing block with two variables" do
43
+ presenter_class.add_method(:foo, proc { |obj, ctx| [obj, ctx, object, context] })
44
+ assert_equal %w[OBJECT CONTEXT OBJECT CONTEXT], presenter.foo
45
+ end
46
+
47
+ it "raises error when block has more than two variables" do
48
+ error = assert_raises(Jat::Error) { presenter_class.add_method(:foo, proc { |_a, _b, _c| }) }
49
+ assert_equal "Invalid block arguments count", error.message
50
+ end
51
+ end
52
+
53
+ describe "#initialize" do
54
+ it "initializes object presenter with provided object and context" do
55
+ presenter = presenter_class.new("OBJ", "CTX")
56
+
57
+ assert_equal "OBJ", presenter.object
58
+ assert_equal "CTX", presenter.context
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe Jat::EnumDeepDup do
6
+ describe ".call" do
7
+ it "makes deep dup of hash" do
8
+ hash = {key1: {key11: {key111: :value111}}, key2: [{key22: {key222: :value222}}]}
9
+ dup = Jat::EnumDeepDup.call(hash)
10
+
11
+ assert_equal hash, dup
12
+
13
+ refute_same hash, dup
14
+ refute_same hash[:key1], dup[:key1]
15
+ refute_same hash[:key1][:key11], dup[:key1][:key11]
16
+
17
+ refute_same hash[:key2], dup[:key2]
18
+ refute_same hash[:key2][0], dup[:key2][0]
19
+ refute_same hash[:key2][0][:key22], dup[:key2][0][:key22]
20
+ end
21
+
22
+ it "does not duplicates non-enumerable objects" do
23
+ hash = {key1: Jat, key2: [-> {}]}
24
+ dup = Jat::EnumDeepDup.call(hash)
25
+
26
+ assert_equal hash, dup
27
+ assert_same hash[:key1], dup[:key1]
28
+ assert_same hash[:key2][0], dup[:key2][0]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe Jat::EnumDeepFreeze do
6
+ describe ".call" do
7
+ it "deeply freezes provided hash" do
8
+ hash = {key1: {key11: {key111: :value111}}, key2: [{key22: {key222: :value222}}]}
9
+ Jat::EnumDeepFreeze.call(hash)
10
+
11
+ assert hash.frozen?
12
+ assert hash[:key1].frozen?
13
+ assert hash[:key1][:key11].frozen?
14
+
15
+ assert hash[:key2].frozen?
16
+ assert hash[:key2][0].frozen?
17
+ assert hash[:key2][0][:key22].frozen?
18
+ end
19
+
20
+ it "does not freezes non-enumerable objects" do
21
+ hash = {key1: Jat, key2: [-> {}]}
22
+ Jat::EnumDeepFreeze.call(hash)
23
+
24
+ refute hash[:key1].frozen?
25
+ refute hash[:key2][0].frozen?
26
+ end
27
+ end
28
+ end