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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +21 -0
- data/jat.gemspec +37 -0
- data/lib/jat/attribute.rb +85 -0
- data/lib/jat/config.rb +38 -0
- data/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads.rb +29 -0
- data/lib/jat/plugins/_activerecord_preloads/lib/preloader.rb +89 -0
- data/lib/jat/plugins/_json_api_activerecord/_json_api_activerecord.rb +22 -0
- data/lib/jat/plugins/_json_api_activerecord/lib/preloads.rb +84 -0
- data/lib/jat/plugins/_preloads/_preloads.rb +53 -0
- data/lib/jat/plugins/_preloads/lib/format_user_preloads.rb +52 -0
- data/lib/jat/plugins/_preloads/lib/preloads_with_path.rb +78 -0
- data/lib/jat/plugins/cache/cache.rb +39 -0
- data/lib/jat/plugins/camel_lower/camel_lower.rb +18 -0
- data/lib/jat/plugins/json_api/json_api.rb +207 -0
- data/lib/jat/plugins/json_api/lib/construct_traversal_map.rb +91 -0
- data/lib/jat/plugins/json_api/lib/map.rb +54 -0
- data/lib/jat/plugins/json_api/lib/params/fields/parse.rb +27 -0
- data/lib/jat/plugins/json_api/lib/params/fields/validate.rb +55 -0
- data/lib/jat/plugins/json_api/lib/params/fields.rb +23 -0
- data/lib/jat/plugins/json_api/lib/params/include/parse.rb +55 -0
- data/lib/jat/plugins/json_api/lib/params/include/validate.rb +29 -0
- data/lib/jat/plugins/json_api/lib/params/include.rb +49 -0
- data/lib/jat/plugins/json_api/lib/presenters/document_links_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/links_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/meta_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter.rb +53 -0
- data/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter.rb +53 -0
- data/lib/jat/plugins/json_api/lib/response.rb +239 -0
- data/lib/jat/plugins/json_api/lib/traversal_map.rb +34 -0
- data/lib/jat/plugins/simple_api/lib/construct_traversal_map.rb +45 -0
- data/lib/jat/plugins/simple_api/lib/map.rb +29 -0
- data/lib/jat/plugins/simple_api/lib/params/parse.rb +68 -0
- data/lib/jat/plugins/simple_api/lib/response.rb +134 -0
- data/lib/jat/plugins/simple_api/simple_api.rb +65 -0
- data/lib/jat/plugins/to_str/to_str.rb +44 -0
- data/lib/jat/plugins.rb +39 -0
- data/lib/jat/presenter.rb +51 -0
- data/lib/jat/utils/enum_deep_dup.rb +29 -0
- data/lib/jat/utils/enum_deep_freeze.rb +19 -0
- data/lib/jat.rb +66 -144
- data/test/lib/jat/attribute_test.rb +142 -0
- data/test/lib/jat/config_test.rb +57 -0
- data/test/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads_test.rb +40 -0
- data/test/lib/jat/plugins/_activerecord_preloads/lib/preloader_test.rb +98 -0
- data/test/lib/jat/plugins/_json_api_activerecord/_json_api_activerecord_test.rb +29 -0
- data/test/lib/jat/plugins/_json_api_activerecord/lib/preloads_test.rb +191 -0
- data/test/lib/jat/plugins/_preloads/_preloads_test.rb +68 -0
- data/test/lib/jat/plugins/_preloads/lib/format_user_preloads_test.rb +47 -0
- data/test/lib/jat/plugins/_preloads/lib/preloads_with_path_test.rb +33 -0
- data/test/lib/jat/plugins/cache/cache_test.rb +82 -0
- data/test/lib/jat/plugins/camel_lower/camel_lower_test.rb +78 -0
- data/test/lib/jat/plugins/json_api/json_api_test.rb +154 -0
- data/test/lib/jat/plugins/json_api/lib/construct_traversal_map_test.rb +119 -0
- data/test/lib/jat/plugins/json_api/lib/map_test.rb +117 -0
- data/test/lib/jat/plugins/json_api/lib/params/fields/parse_test.rb +24 -0
- data/test/lib/jat/plugins/json_api/lib/params/fields/validate_test.rb +47 -0
- data/test/lib/jat/plugins/json_api/lib/params/fields_test.rb +37 -0
- data/test/lib/jat/plugins/json_api/lib/params/include/parse_test.rb +46 -0
- data/test/lib/jat/plugins/json_api/lib/params/include/validate_test.rb +51 -0
- data/test/lib/jat/plugins/json_api/lib/params/include_test.rb +41 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/document_links_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/links_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/meta_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter_test.rb +75 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter_test.rb +75 -0
- data/test/lib/jat/plugins/json_api/lib/response_test.rb +489 -0
- data/test/lib/jat/plugins/json_api/lib/traversal_map_test.rb +58 -0
- data/test/lib/jat/plugins/simple_api/lib/construct_traversal_map_test.rb +100 -0
- data/test/lib/jat/plugins/simple_api/lib/map_test.rb +56 -0
- data/test/lib/jat/plugins/simple_api/lib/params/parse_test.rb +71 -0
- data/test/lib/jat/plugins/simple_api/lib/response_test.rb +342 -0
- data/test/lib/jat/plugins/simple_api/simple_api_test.rb +81 -0
- data/test/lib/jat/plugins/to_str/to_str_test.rb +52 -0
- data/test/lib/jat/presenter_test.rb +61 -0
- data/test/lib/jat/utils/enum_deep_dup_test.rb +31 -0
- data/test/lib/jat/utils/enum_deep_freeze_test.rb +28 -0
- data/test/lib/jat_test.rb +120 -0
- data/test/lib/plugin_test.rb +49 -0
- data/test/support/activerecord.rb +24 -0
- data/test/test_helper.rb +16 -0
- data/test/test_plugin.rb +59 -0
- 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
|