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,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::Preloads::PreloadsWithPath" do
|
|
6
|
+
before { Jat::Plugins.load_plugin(:_preloads) }
|
|
7
|
+
|
|
8
|
+
let(:described_class) { Jat::Plugins::Preloads::PreloadsWithPath }
|
|
9
|
+
|
|
10
|
+
it "returns provided preloads and path to last value" do
|
|
11
|
+
preloads = {a: {b: {c: {}}, d: {}}, e: {}}
|
|
12
|
+
new_preloads, path = described_class.call(preloads)
|
|
13
|
+
|
|
14
|
+
assert_equal({a: {b: {c: {}}, d: {}}, e: {}}, new_preloads)
|
|
15
|
+
assert_equal(%i[e], path)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "returns provided preloads and path to marked with `!` value" do
|
|
19
|
+
preloads = {a: {b!: {c: {}}, d: {}}, e: {}}
|
|
20
|
+
new_preloads, path = described_class.call(preloads)
|
|
21
|
+
|
|
22
|
+
assert_equal({a: {b: {c: {}}, d: {}}, e: {}}, new_preloads)
|
|
23
|
+
assert_equal(%i[a b], path)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "returns empty preloads and path when empty hash provided" do
|
|
27
|
+
preloads = {}
|
|
28
|
+
new_preloads, path = described_class.call(preloads)
|
|
29
|
+
|
|
30
|
+
assert_equal({}, new_preloads)
|
|
31
|
+
assert_equal([], path)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::Cache" do
|
|
6
|
+
let(:jat_class) do
|
|
7
|
+
new_class = Class.new(Jat)
|
|
8
|
+
to_h_mod = Module.new do
|
|
9
|
+
def to_h
|
|
10
|
+
"RES_#{object}"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
new_class.include(to_h_mod)
|
|
14
|
+
new_class.plugin(:cache)
|
|
15
|
+
new_class
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
let(:context) { {cache: hash_cache} }
|
|
19
|
+
let(:hash_storage) { {} }
|
|
20
|
+
let(:hash_cache) do
|
|
21
|
+
hash_storage
|
|
22
|
+
lambda do |object, context, &block|
|
|
23
|
+
key = [object, context[:foo], context[:_format]].join(".").freeze
|
|
24
|
+
hash_storage[key] ||= block.call
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "InstanceMethods" do
|
|
29
|
+
describe "#to_h" do
|
|
30
|
+
it "takes result from cache" do
|
|
31
|
+
result1 = jat_class.new("OBJECT", context).to_h
|
|
32
|
+
result2 = jat_class.new("OBJECT", context).to_h
|
|
33
|
+
|
|
34
|
+
assert_equal "RES_OBJECT", result1
|
|
35
|
+
assert_equal "RES_OBJECT", result2
|
|
36
|
+
assert_same result1, result2
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "does not take cached result when cache keys are different" do
|
|
40
|
+
result1 = jat_class.new("OBJECT", context).to_h
|
|
41
|
+
result2 = jat_class.new("OBJECT", context.merge(foo: :bazz)).to_h
|
|
42
|
+
|
|
43
|
+
assert_equal "RES_OBJECT", result1
|
|
44
|
+
assert_equal "RES_OBJECT", result2
|
|
45
|
+
refute_same result1, result2
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "does not saves cache when no context[:cache] provided" do
|
|
49
|
+
jat_class.new("OBJECT", {}).to_str
|
|
50
|
+
|
|
51
|
+
assert_equal [], hash_storage.keys
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "#to_str" do
|
|
56
|
+
it "takes result from cache" do
|
|
57
|
+
result1 = jat_class.new("OBJECT", context).to_str
|
|
58
|
+
result2 = jat_class.new("OBJECT", context).to_str
|
|
59
|
+
|
|
60
|
+
assert_equal '"RES_OBJECT"', result1
|
|
61
|
+
assert_equal '"RES_OBJECT"', result2
|
|
62
|
+
assert_same result1, result2
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "does not take cached result when cache keys are different" do
|
|
66
|
+
result1 = jat_class.new("OBJECT", context).to_str
|
|
67
|
+
result2 = jat_class.new("OBJECT", context.merge(foo: :bazz)).to_str
|
|
68
|
+
|
|
69
|
+
assert_equal '"RES_OBJECT"', result1
|
|
70
|
+
assert_equal '"RES_OBJECT"', result2
|
|
71
|
+
refute_same result1, result2
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "does not saves cache for #to_h" do
|
|
75
|
+
context[:foo] = :bar
|
|
76
|
+
jat_class.new("OBJECT", context).to_str
|
|
77
|
+
|
|
78
|
+
assert_equal ["OBJECT.bar.to_str"], hash_storage.keys
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::CamelLower" do
|
|
6
|
+
let(:jat_class) do
|
|
7
|
+
new_class = Class.new(Jat)
|
|
8
|
+
new_class.plugin(:camel_lower)
|
|
9
|
+
new_class
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "Attribute" do
|
|
13
|
+
describe "#name" do
|
|
14
|
+
it "returns name in camel_lower case" do
|
|
15
|
+
attribute = jat_class.attribute(:foo)
|
|
16
|
+
assert :foo, attribute.name
|
|
17
|
+
|
|
18
|
+
attribute = jat_class.attribute(:foo_bar)
|
|
19
|
+
assert :fooBar, attribute.name
|
|
20
|
+
|
|
21
|
+
attribute = jat_class.attribute(:foo_bar_bazz)
|
|
22
|
+
assert :fooBarBazz, attribute.name
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "Test responses with simple_api plugin" do
|
|
28
|
+
before { jat_class.plugin(:simple_api) }
|
|
29
|
+
|
|
30
|
+
it "returns attributes in camelLower case" do
|
|
31
|
+
jat_class.attribute(:foo_bar) { 1 }
|
|
32
|
+
|
|
33
|
+
response = jat_class.to_h(true)
|
|
34
|
+
assert_equal({fooBar: 1}, response)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "accepts fields in camelLower format" do
|
|
38
|
+
jat_class.attribute(:foo_bar, exposed: false) { 1 }
|
|
39
|
+
|
|
40
|
+
response = jat_class.to_h(true, params: {fields: "fooBar"})
|
|
41
|
+
assert_equal({fooBar: 1}, response)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "Test responses with json_api plugin" do
|
|
46
|
+
before do
|
|
47
|
+
jat_class.plugin(:json_api)
|
|
48
|
+
jat_class.type :foo
|
|
49
|
+
jat_class.attribute(:id) { object }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "returns attributes in camelLower case" do
|
|
53
|
+
jat_class.attribute(:foo_bar) { 1 }
|
|
54
|
+
|
|
55
|
+
assert_equal({fooBar: 1}, jat_class.to_h(true).dig(:data, :attributes))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "accepts `fields` in camelLower format" do
|
|
59
|
+
jat_class.attribute(:foo_bar, exposed: false) { 1 }
|
|
60
|
+
|
|
61
|
+
response = jat_class.to_h(true, params: {fields: {foo: "fooBar"}})
|
|
62
|
+
assert_equal({fooBar: 1}, response.dig(:data, :attributes))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "accepts `include` in camelLower format" do
|
|
66
|
+
new_serializer = Class.new(Jat)
|
|
67
|
+
new_serializer.plugin(:json_api)
|
|
68
|
+
new_serializer.type :new
|
|
69
|
+
new_serializer.attribute(:id) { object }
|
|
70
|
+
|
|
71
|
+
jat_class.relationship(:foo_bar, serializer: new_serializer) { 1 }
|
|
72
|
+
|
|
73
|
+
response = jat_class.to_h(true, params: {include: "fooBar"})
|
|
74
|
+
response_relationships = response.dig(:data, :relationships).keys
|
|
75
|
+
assert_includes(response_relationships, :fooBar)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::JsonApi" do
|
|
6
|
+
let(:jat_class) do
|
|
7
|
+
new_class = Class.new(Jat)
|
|
8
|
+
new_class.plugin(plugin)
|
|
9
|
+
new_class.type :jat
|
|
10
|
+
new_class.attribute :id, key: :itself
|
|
11
|
+
new_class
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
let(:plugin) { Jat::Plugins.load_plugin(:json_api) }
|
|
15
|
+
|
|
16
|
+
describe ".after_load" do
|
|
17
|
+
it "loads _json_api_activerecord plugin if activerecord option provided" do
|
|
18
|
+
jat_class = Class.new(Jat)
|
|
19
|
+
jat_class.expects(:plugin).with(:_json_api_activerecord, activerecord: true)
|
|
20
|
+
|
|
21
|
+
Jat::Plugins.after_load(plugin, jat_class, activerecord: true)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "registers Presenters constants" do
|
|
25
|
+
jat_class = Class.new(Jat)
|
|
26
|
+
Jat::Plugins.after_load(plugin, jat_class, activerecord: true)
|
|
27
|
+
|
|
28
|
+
assert_equal jat_class::JsonapiPresenter.jat_class, jat_class
|
|
29
|
+
assert_equal jat_class::LinksPresenter.jat_class, jat_class
|
|
30
|
+
assert_equal jat_class::DocumentLinksPresenter.jat_class, jat_class
|
|
31
|
+
assert_equal jat_class::RelationshipLinksPresenter.jat_class, jat_class
|
|
32
|
+
assert_equal jat_class::MetaPresenter.jat_class, jat_class
|
|
33
|
+
assert_equal jat_class::DocumentMetaPresenter.jat_class, jat_class
|
|
34
|
+
assert_equal jat_class::RelationshipMetaPresenter.jat_class, jat_class
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "InstanceMethods" do
|
|
39
|
+
let(:jat) do
|
|
40
|
+
jat_class.new("JAT", {})
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#to_h" do
|
|
44
|
+
it "returns response in json-api format" do
|
|
45
|
+
expected_result = {data: {type: :jat, id: "JAT"}}
|
|
46
|
+
assert_equal expected_result, jat.to_h
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "#traversal_map" do
|
|
51
|
+
it "returns memorized traversal_map object" do
|
|
52
|
+
assert_equal jat.traversal_map.class, Jat::Plugins::JsonApi::TraversalMap
|
|
53
|
+
assert_same jat.traversal_map, jat.traversal_map
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "ClassMethods" do
|
|
59
|
+
describe ".relationship" do
|
|
60
|
+
it "adds new attribute with required serializer" do
|
|
61
|
+
jat_class.relationship(:foo, serializer: jat_class, exposed: true) { "block" }
|
|
62
|
+
|
|
63
|
+
atribute = jat_class.attributes[:foo]
|
|
64
|
+
assert_equal jat_class, atribute.serializer
|
|
65
|
+
assert_equal true, atribute.exposed?
|
|
66
|
+
assert_equal "block", jat_class::Presenter.new(nil, nil).foo
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe ".inherited" do
|
|
71
|
+
it "inherits type" do
|
|
72
|
+
child = Class.new(jat_class)
|
|
73
|
+
assert_equal :jat, child.type
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "inherits `jsonapi` data" do
|
|
77
|
+
jat_class.jsonapi(:version) { "1.0" }
|
|
78
|
+
|
|
79
|
+
child = Class.new(jat_class)
|
|
80
|
+
assert_equal("1.0", child.jsonapi_data[:version].call)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "inherits `object_links`, `relationship_links`, `document_links`" do
|
|
84
|
+
jat_class.object_link(:self) { "/articles/1" }
|
|
85
|
+
jat_class.relationship_link(:related) { "/articles/2" }
|
|
86
|
+
jat_class.document_link(:last) { "/articles/3" }
|
|
87
|
+
child = Class.new(jat_class)
|
|
88
|
+
|
|
89
|
+
assert_equal("/articles/1", child.object_links[:self].call)
|
|
90
|
+
assert_equal("/articles/2", child.relationship_links[:related].call)
|
|
91
|
+
assert_equal("/articles/3", child.document_links[:last].call)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "does not change parents links when children links are changed" do
|
|
95
|
+
jat_class.object_link(:self) { "/articles/1" }
|
|
96
|
+
jat_class.relationship_link(:related) { "/articles/2" }
|
|
97
|
+
jat_class.document_link(:last) { "/articles/3" }
|
|
98
|
+
|
|
99
|
+
child = Class.new(jat_class)
|
|
100
|
+
child.object_links.delete(:self)
|
|
101
|
+
child.relationship_links.delete(:related)
|
|
102
|
+
child.document_links.delete(:last)
|
|
103
|
+
|
|
104
|
+
assert_equal("/articles/1", jat_class.object_links[:self].call)
|
|
105
|
+
assert_equal("/articles/2", jat_class.relationship_links[:related].call)
|
|
106
|
+
assert_equal("/articles/3", jat_class.document_links[:last].call)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "inherits `object_meta`, `relationship_meta`, `document_meta`" do
|
|
110
|
+
jat_class.object_meta(:self) { "foo/1" }
|
|
111
|
+
jat_class.relationship_meta(:related) { "foo/2" }
|
|
112
|
+
jat_class.document_meta(:last) { "foo/3" }
|
|
113
|
+
child = Class.new(jat_class)
|
|
114
|
+
|
|
115
|
+
assert_equal("foo/1", child.added_object_meta[:self].call)
|
|
116
|
+
assert_equal("foo/2", child.added_relationship_meta[:related].call)
|
|
117
|
+
assert_equal("foo/3", child.added_document_meta[:last].call)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "does not change parents meta when children meta changed" do
|
|
121
|
+
jat_class.object_meta(:self) { "foo/1" }
|
|
122
|
+
jat_class.relationship_meta(:related) { "foo/2" }
|
|
123
|
+
jat_class.document_meta(:last) { "foo/3" }
|
|
124
|
+
|
|
125
|
+
child = Class.new(jat_class)
|
|
126
|
+
child.added_object_meta.delete(:self)
|
|
127
|
+
child.added_relationship_meta.delete(:related)
|
|
128
|
+
child.added_document_meta.delete(:last)
|
|
129
|
+
|
|
130
|
+
assert_equal("foo/1", jat_class.added_object_meta[:self].call)
|
|
131
|
+
assert_equal("foo/2", jat_class.added_relationship_meta[:related].call)
|
|
132
|
+
assert_equal("foo/3", jat_class.added_document_meta[:last].call)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
describe ".type" do
|
|
137
|
+
it "does not allows to ask for type before type is defined" do
|
|
138
|
+
new_class = Class.new(Jat) { plugin(:json_api) }
|
|
139
|
+
|
|
140
|
+
error = assert_raises(Jat::Error) { new_class.type }
|
|
141
|
+
assert_equal "#{new_class} has no defined type", error.message
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "saves and returns current type" do
|
|
145
|
+
assert_equal :jat, jat_class.type
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "symbolizes type" do
|
|
149
|
+
jat_class.type "users"
|
|
150
|
+
assert_equal :users, jat_class.type
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::JsonApi::ConstructTraversalMap" do
|
|
6
|
+
before { Jat::Plugins.load_plugin(:json_api) }
|
|
7
|
+
|
|
8
|
+
let(:described_class) { Jat::Plugins::JsonApi::ConstructTraversalMap }
|
|
9
|
+
let(:base_class) { Class.new(Jat) { plugin :json_api } }
|
|
10
|
+
|
|
11
|
+
let(:a) do
|
|
12
|
+
ser = Class.new(base_class)
|
|
13
|
+
ser.type :a
|
|
14
|
+
|
|
15
|
+
ser.attribute :a1
|
|
16
|
+
ser.attribute :a2
|
|
17
|
+
ser.attribute :a3, exposed: false
|
|
18
|
+
|
|
19
|
+
ser.relationship :b, serializer: b
|
|
20
|
+
ser.relationship :c, serializer: c
|
|
21
|
+
ser.relationship :d, serializer: d, exposed: true
|
|
22
|
+
ser
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
let(:b) do
|
|
26
|
+
ser = Class.new(base_class)
|
|
27
|
+
ser.type :b
|
|
28
|
+
ser.attribute :b1
|
|
29
|
+
ser.attribute :b2
|
|
30
|
+
ser.attribute :b3, exposed: false
|
|
31
|
+
ser
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
let(:c) do
|
|
35
|
+
ser = Class.new(base_class)
|
|
36
|
+
ser.type :c
|
|
37
|
+
ser.attribute :c1
|
|
38
|
+
ser.attribute :c2
|
|
39
|
+
ser.attribute :c3, exposed: false
|
|
40
|
+
ser
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
let(:d) do
|
|
44
|
+
ser = Class.new(base_class)
|
|
45
|
+
ser.type :d
|
|
46
|
+
ser.attribute :d1
|
|
47
|
+
ser.attribute :d2
|
|
48
|
+
ser.attribute :d3, exposed: false
|
|
49
|
+
ser
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "returns all attributes" do
|
|
53
|
+
result = described_class.new(a, :all).to_h
|
|
54
|
+
expected_result = {
|
|
55
|
+
a: {serializer: a, attributes: %i[a1 a2 a3], relationships: %i[b c d]},
|
|
56
|
+
b: {serializer: b, attributes: %i[b1 b2 b3], relationships: []},
|
|
57
|
+
c: {serializer: c, attributes: %i[c1 c2 c3], relationships: []},
|
|
58
|
+
d: {serializer: d, attributes: %i[d1 d2 d3], relationships: []}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
assert_equal expected_result, result
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "returns exposed attributes" do
|
|
65
|
+
result = described_class.new(a, :exposed).to_h
|
|
66
|
+
expected_result = {
|
|
67
|
+
a: {serializer: a, attributes: %i[a1 a2], relationships: %i[d]},
|
|
68
|
+
d: {serializer: d, attributes: %i[d1 d2], relationships: []}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
assert_equal expected_result, result
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "returns only manually exposed per-type attributes or exposed by default when no manual type provided" do
|
|
75
|
+
exposed = {
|
|
76
|
+
a: %i[a2 a3 c d],
|
|
77
|
+
c: %i[c2 c3],
|
|
78
|
+
d: %i[d2 d3]
|
|
79
|
+
}
|
|
80
|
+
result = described_class.new(a, :manual, manually_exposed: exposed).to_h
|
|
81
|
+
expected_result = {
|
|
82
|
+
a: {serializer: a, attributes: %i[a2 a3], relationships: %i[c d]},
|
|
83
|
+
c: {serializer: c, attributes: %i[c2 c3], relationships: []},
|
|
84
|
+
d: {serializer: d, attributes: %i[d2 d3], relationships: []}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
assert_equal expected_result, result
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "returns manually exposed per-type attributes or exposed by default when no manual type provided" do
|
|
91
|
+
exposed = {
|
|
92
|
+
a: %i[a2 a3 b c],
|
|
93
|
+
c: %i[c2 c3]
|
|
94
|
+
}
|
|
95
|
+
result = described_class.new(a, :manual, manually_exposed: exposed).to_h
|
|
96
|
+
expected_result = {
|
|
97
|
+
a: {serializer: a, attributes: %i[a2 a3], relationships: %i[b c]},
|
|
98
|
+
b: {serializer: b, attributes: %i[b1 b2], relationships: []},
|
|
99
|
+
c: {serializer: c, attributes: %i[c2 c3], relationships: []}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
assert_equal expected_result, result
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "returns combined auto-exposed and manualy exposed attributes" do
|
|
106
|
+
exposed = {
|
|
107
|
+
a: %i[c],
|
|
108
|
+
c: %i[c3]
|
|
109
|
+
}
|
|
110
|
+
result = described_class.new(a, :exposed, manually_exposed: exposed).to_h
|
|
111
|
+
expected_result = {
|
|
112
|
+
a: {serializer: a, attributes: %i[a1 a2], relationships: %i[c d]},
|
|
113
|
+
c: {serializer: c, attributes: %i[c1 c2 c3], relationships: []},
|
|
114
|
+
d: {serializer: d, attributes: %i[d1 d2], relationships: []}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
assert_equal expected_result, result
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::JsonApi::Map" do
|
|
6
|
+
subject { Jat::Plugins::JsonApi::Map.call(jat) }
|
|
7
|
+
|
|
8
|
+
let(:jat_class) do
|
|
9
|
+
Class.new(Jat) do
|
|
10
|
+
plugin :json_api
|
|
11
|
+
type :jat
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
let(:jat) { jat_class.new(nil, params: {fields: param_fields, include: param_includes}) }
|
|
15
|
+
|
|
16
|
+
let(:default_map) { {a: :a1, b: :b1, c: :c1} }
|
|
17
|
+
let(:includes_map) { {b: :b2, c: :c2} }
|
|
18
|
+
let(:fields_map) { {c: :c3} }
|
|
19
|
+
|
|
20
|
+
before do
|
|
21
|
+
jat.traversal_map.expects(:exposed).returns(default_map)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "when no params given" do
|
|
25
|
+
let(:param_includes) { nil }
|
|
26
|
+
let(:param_fields) { nil }
|
|
27
|
+
|
|
28
|
+
it "returns map of exposed by default fields" do
|
|
29
|
+
assert_equal default_map, subject
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "when fields given" do
|
|
34
|
+
let(:param_includes) { nil }
|
|
35
|
+
let(:param_fields) { "FIELDS" }
|
|
36
|
+
|
|
37
|
+
before do
|
|
38
|
+
constructor = Jat::Plugins::JsonApi::ConstructTraversalMap.allocate
|
|
39
|
+
constructor.expects(:to_h).returns(fields_map)
|
|
40
|
+
|
|
41
|
+
Jat::Plugins::JsonApi::Params::Fields
|
|
42
|
+
.expects(:call)
|
|
43
|
+
.with(jat, "FIELDS")
|
|
44
|
+
.returns("PARSED_FIELDS")
|
|
45
|
+
|
|
46
|
+
Jat::Plugins::JsonApi::ConstructTraversalMap
|
|
47
|
+
.expects(:new)
|
|
48
|
+
.with(jat_class, :manual, manually_exposed: "PARSED_FIELDS")
|
|
49
|
+
.returns(constructor)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "constructs map with default and provided fields" do
|
|
53
|
+
assert_equal({a: :a1, b: :b1, c: :c3}, subject)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "when includes given" do
|
|
58
|
+
let(:param_includes) { "INCLUDES" }
|
|
59
|
+
let(:param_fields) { nil }
|
|
60
|
+
|
|
61
|
+
before do
|
|
62
|
+
constructor = Jat::Plugins::JsonApi::ConstructTraversalMap.allocate
|
|
63
|
+
constructor.expects(:to_h).returns(includes_map)
|
|
64
|
+
|
|
65
|
+
Jat::Plugins::JsonApi::Params::Include
|
|
66
|
+
.expects(:call)
|
|
67
|
+
.with(jat, "INCLUDES")
|
|
68
|
+
.returns("PARSED_INCLUDES")
|
|
69
|
+
|
|
70
|
+
Jat::Plugins::JsonApi::ConstructTraversalMap
|
|
71
|
+
.expects(:new)
|
|
72
|
+
.with(jat_class, :exposed, manually_exposed: "PARSED_INCLUDES")
|
|
73
|
+
.returns(constructor)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "constructs map with default and included fields" do
|
|
77
|
+
assert_equal({a: :a1, b: :b2, c: :c2}, subject)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe "when fields and includes given" do
|
|
82
|
+
let(:param_fields) { "FIELDS" }
|
|
83
|
+
let(:param_includes) { "INCLUDES" }
|
|
84
|
+
|
|
85
|
+
before do
|
|
86
|
+
constructor1 = Jat::Plugins::JsonApi::ConstructTraversalMap.allocate
|
|
87
|
+
constructor1.expects(:to_h).returns(fields_map)
|
|
88
|
+
|
|
89
|
+
Jat::Plugins::JsonApi::Params::Fields
|
|
90
|
+
.expects(:call)
|
|
91
|
+
.with(jat, "FIELDS")
|
|
92
|
+
.returns("PARSED_FIELDS")
|
|
93
|
+
|
|
94
|
+
Jat::Plugins::JsonApi::ConstructTraversalMap
|
|
95
|
+
.expects(:new)
|
|
96
|
+
.with(jat_class, :manual, manually_exposed: "PARSED_FIELDS")
|
|
97
|
+
.returns(constructor1)
|
|
98
|
+
|
|
99
|
+
constructor2 = Jat::Plugins::JsonApi::ConstructTraversalMap.allocate
|
|
100
|
+
constructor2.expects(:to_h).returns(includes_map)
|
|
101
|
+
|
|
102
|
+
Jat::Plugins::JsonApi::Params::Include
|
|
103
|
+
.expects(:call)
|
|
104
|
+
.with(jat, "INCLUDES")
|
|
105
|
+
.returns("PARSED_INCLUDES")
|
|
106
|
+
|
|
107
|
+
Jat::Plugins::JsonApi::ConstructTraversalMap
|
|
108
|
+
.expects(:new)
|
|
109
|
+
.with(jat_class, :exposed, manually_exposed: "PARSED_INCLUDES")
|
|
110
|
+
.returns(constructor2)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "constructs map with using everything: defaults, includes, fields" do
|
|
114
|
+
assert_equal({a: :a1, b: :b2, c: :c3}, subject)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::JsonApi::Params::Fields::Parse" do
|
|
6
|
+
before { Jat::Plugins.load_plugin(:json_api) }
|
|
7
|
+
|
|
8
|
+
let(:described_class) { Jat::Plugins::JsonApi::Params::Fields::Parse }
|
|
9
|
+
|
|
10
|
+
it "returns empty hash when param not provided" do
|
|
11
|
+
result = described_class.call(nil)
|
|
12
|
+
assert_equal({}, result)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "returns hash with parsed keys" do
|
|
16
|
+
result = described_class.call(a: "a1,a2", b: "b1")
|
|
17
|
+
assert_equal({a: %i[a1 a2], b: %i[b1]}, result)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "symbolizes types" do
|
|
21
|
+
result = described_class.call("a" => "a1,a2", "b" => "b1")
|
|
22
|
+
assert_equal({a: %i[a1 a2], b: %i[b1]}, result)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::JsonApi::Params::Fields::Validate" do
|
|
6
|
+
before { Jat::Plugins.load_plugin(:json_api) }
|
|
7
|
+
|
|
8
|
+
let(:described_class) { Jat::Plugins::JsonApi::Params::Fields::Validate }
|
|
9
|
+
let(:base_class) { Class.new(Jat) { plugin :json_api } }
|
|
10
|
+
let(:a_serializer) { Class.new(base_class) }
|
|
11
|
+
let(:b_serializer) { Class.new(base_class) }
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
ser = a_serializer
|
|
15
|
+
ser.type :a
|
|
16
|
+
ser.attribute :a1
|
|
17
|
+
ser.relationship :a2, serializer: b_serializer
|
|
18
|
+
|
|
19
|
+
ser = b_serializer
|
|
20
|
+
ser.type :b
|
|
21
|
+
ser.attribute :b1
|
|
22
|
+
ser.relationship :b2, serializer: a_serializer
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "does not raises when serializer has all requested keys" do
|
|
26
|
+
assert described_class.call(a_serializer.allocate, a: %i[a1 a2], b: %i[b1 b2])
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "does not raises when requested only fields for nested serializer" do
|
|
30
|
+
assert described_class.call(a_serializer.allocate, b: %i[b1 b2])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "raises error when some type can not be in response" do
|
|
34
|
+
error = assert_raises(Jat::Error) { described_class.call(a_serializer.allocate, a: %i[a1 a2], foo: %i[b1 b2]) }
|
|
35
|
+
assert_equal "#{a_serializer} and its children have no requested type `foo`", error.message
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "raises error when some key is not present in main serializer" do
|
|
39
|
+
error = assert_raises(Jat::Error) { described_class.call(a_serializer.allocate, a: %i[b1]) }
|
|
40
|
+
assert_equal "#{a_serializer} has no requested attribute or relationship `b1`", error.message
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "raises error when some key is not present in nested serializer" do
|
|
44
|
+
error = assert_raises(Jat::Error) { described_class.call(a_serializer.allocate, a: %i[a1], b: %i[a1]) }
|
|
45
|
+
assert_equal "#{b_serializer} has no requested attribute or relationship `a1`", error.message
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::JsonApi::Params::Fields" do
|
|
6
|
+
before { Jat::Plugins.load_plugin(:json_api) }
|
|
7
|
+
|
|
8
|
+
let(:jat_class) do
|
|
9
|
+
Class.new(Jat) do
|
|
10
|
+
plugin :json_api
|
|
11
|
+
type :a
|
|
12
|
+
|
|
13
|
+
attribute :a1
|
|
14
|
+
attribute :a2
|
|
15
|
+
attribute :a3
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:described_class) { Jat::Plugins::JsonApi::Params::Fields }
|
|
20
|
+
|
|
21
|
+
it "returns empty hash when parameters not provided" do
|
|
22
|
+
result = described_class.call(jat_class.allocate, nil)
|
|
23
|
+
|
|
24
|
+
assert_equal({}, result)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "returns parsed attributes" do
|
|
28
|
+
result = described_class.call(jat_class.allocate, a: "a1,a2")
|
|
29
|
+
|
|
30
|
+
assert_equal({a: %i[a1 a2]}, result)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "validates provided attributes" do
|
|
34
|
+
error = assert_raises(Jat::Error) { described_class.call(jat_class.allocate, a: "a1,a2,a3,a4") }
|
|
35
|
+
assert_match(/a4/, error.message)
|
|
36
|
+
end
|
|
37
|
+
end
|