yaks 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +158 -56
  3. data/Rakefile +1 -3
  4. data/ataru_setup.rb +72 -0
  5. data/find_missing_tests.rb +34 -0
  6. data/lib/yaks.rb +8 -10
  7. data/lib/yaks/breaking_changes.rb +4 -6
  8. data/lib/yaks/builder.rb +1 -1
  9. data/lib/yaks/changelog.rb +1 -1
  10. data/lib/yaks/collection_mapper.rb +8 -5
  11. data/lib/yaks/collection_resource.rb +0 -1
  12. data/lib/yaks/config.rb +17 -7
  13. data/lib/yaks/configurable.rb +20 -14
  14. data/lib/yaks/default_policy.rb +82 -33
  15. data/lib/yaks/format.rb +7 -3
  16. data/lib/yaks/format/collection_json.rb +4 -4
  17. data/lib/yaks/format/hal.rb +1 -2
  18. data/lib/yaks/format/halo.rb +2 -4
  19. data/lib/yaks/format/json_api.rb +46 -27
  20. data/lib/yaks/html5_forms.rb +0 -2
  21. data/lib/yaks/mapper.rb +5 -5
  22. data/lib/yaks/mapper/association.rb +7 -7
  23. data/lib/yaks/mapper/association_mapper.rb +2 -0
  24. data/lib/yaks/mapper/attribute.rb +10 -4
  25. data/lib/yaks/mapper/config.rb +2 -2
  26. data/lib/yaks/mapper/form.rb +4 -10
  27. data/lib/yaks/mapper/form/config.rb +16 -17
  28. data/lib/yaks/mapper/form/dynamic_field.rb +1 -1
  29. data/lib/yaks/mapper/form/field.rb +16 -7
  30. data/lib/yaks/mapper/form/field/option.rb +5 -4
  31. data/lib/yaks/mapper/form/fieldset.rb +1 -1
  32. data/lib/yaks/mapper/form/legend.rb +18 -0
  33. data/lib/yaks/mapper/has_many.rb +1 -0
  34. data/lib/yaks/mapper/link.rb +7 -4
  35. data/lib/yaks/null_resource.rb +4 -5
  36. data/lib/yaks/pipeline.rb +2 -2
  37. data/lib/yaks/primitivize.rb +3 -2
  38. data/lib/yaks/reader/hal.rb +12 -13
  39. data/lib/yaks/reader/json_api.rb +50 -33
  40. data/lib/yaks/resource.rb +6 -7
  41. data/lib/yaks/resource/form.rb +2 -12
  42. data/lib/yaks/resource/form/field.rb +4 -3
  43. data/lib/yaks/resource/form/field/option.rb +1 -1
  44. data/lib/yaks/resource/form/fieldset.rb +1 -1
  45. data/lib/yaks/resource/form/legend.rb +18 -0
  46. data/lib/yaks/resource/has_fields.rb +13 -7
  47. data/lib/yaks/resource/link.rb +1 -1
  48. data/lib/yaks/runner.rb +5 -2
  49. data/lib/yaks/serializer.rb +2 -3
  50. data/lib/yaks/util.rb +7 -8
  51. data/lib/yaks/version.rb +1 -1
  52. data/spec/acceptance/acceptance_spec.rb +53 -38
  53. data/spec/acceptance/json_shared_examples.rb +45 -12
  54. data/spec/acceptance/models.rb +1 -1
  55. data/spec/integration/dynamic_form_fields_spec.rb +0 -1
  56. data/spec/integration/fieldset_spec.rb +18 -20
  57. data/spec/integration/map_to_resource_spec.rb +6 -6
  58. data/spec/json/{confucius.collection.json → confucius.collection_json.json} +0 -0
  59. data/spec/json/confucius.json_api.json +43 -27
  60. data/spec/json/list_of_quotes.collection_json.json +43 -0
  61. data/spec/json/list_of_quotes.hal.json +18 -0
  62. data/spec/json/list_of_quotes.json_api.json +25 -0
  63. data/spec/json/youtypeitwepostit.collection_json.json +45 -0
  64. data/spec/spec_helper.rb +4 -3
  65. data/spec/support/classes_for_policy_testing.rb +38 -14
  66. data/spec/support/deep_eql.rb +21 -18
  67. data/spec/support/pet_mapper.rb +2 -0
  68. data/spec/support/shared_contexts.rb +9 -9
  69. data/spec/unit/yaks/builder_spec.rb +41 -18
  70. data/spec/unit/yaks/collection_mapper_spec.rb +22 -19
  71. data/spec/unit/yaks/collection_resource_spec.rb +16 -8
  72. data/spec/unit/yaks/config_spec.rb +215 -19
  73. data/spec/unit/yaks/configurable_spec.rb +66 -7
  74. data/spec/unit/yaks/default_policy/derive_mapper_from_collection_spec.rb +47 -0
  75. data/spec/unit/yaks/default_policy/derive_mapper_from_item_spec.rb +114 -0
  76. data/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +29 -71
  77. data/spec/unit/yaks/default_policy_spec.rb +4 -5
  78. data/spec/unit/yaks/format/collection_json_spec.rb +35 -36
  79. data/spec/unit/yaks/format/hal_spec.rb +3 -3
  80. data/spec/unit/yaks/format/json_api_spec.rb +109 -68
  81. data/spec/unit/yaks/format_spec.rb +34 -0
  82. data/spec/unit/yaks/fp/callable_spec.rb +5 -3
  83. data/spec/unit/yaks/mapper/association_mapper_spec.rb +22 -4
  84. data/spec/unit/yaks/mapper/association_spec.rb +23 -11
  85. data/spec/unit/yaks/mapper/attribute_spec.rb +46 -7
  86. data/spec/unit/yaks/mapper/config_spec.rb +2 -3
  87. data/spec/unit/yaks/mapper/form/config_spec.rb +95 -0
  88. data/spec/unit/yaks/mapper/form/dynamic_field_spec.rb +30 -0
  89. data/spec/unit/yaks/mapper/form/field/option_spec.rb +48 -4
  90. data/spec/unit/yaks/mapper/form/field_spec.rb +43 -2
  91. data/spec/unit/yaks/mapper/form/fieldset_spec.rb +67 -8
  92. data/spec/unit/yaks/mapper/form/legend_spec.rb +52 -0
  93. data/spec/unit/yaks/mapper/form_spec.rb +84 -23
  94. data/spec/unit/yaks/mapper/has_many_spec.rb +39 -36
  95. data/spec/unit/yaks/mapper/has_one_spec.rb +28 -20
  96. data/spec/unit/yaks/mapper/link_spec.rb +68 -16
  97. data/spec/unit/yaks/mapper_spec.rb +118 -30
  98. data/spec/unit/yaks/null_resource_spec.rb +83 -52
  99. data/spec/unit/yaks/pipeline_spec.rb +101 -74
  100. data/spec/unit/yaks/primitivize_spec.rb +25 -6
  101. data/spec/unit/yaks/resource/form/field_spec.rb +5 -5
  102. data/spec/unit/yaks/resource/form/fieldset_spec.rb +7 -0
  103. data/spec/unit/yaks/resource/form/legend_spec.rb +8 -0
  104. data/spec/unit/yaks/resource/form_spec.rb +17 -37
  105. data/spec/unit/yaks/resource/has_fields_spec.rb +44 -3
  106. data/spec/unit/yaks/resource/link_spec.rb +11 -6
  107. data/spec/unit/yaks/resource_spec.rb +87 -98
  108. data/spec/unit/yaks/runner_spec.rb +112 -28
  109. data/spec/unit/yaks/serializer_spec.rb +1 -1
  110. data/spec/unit/yaks/util_spec.rb +30 -10
  111. data/spec/yaml/list_of_quotes.yaml +13 -0
  112. data/yaks.gemspec +21 -13
  113. metadata +129 -41
  114. data/lib/yaks/attributes.rb +0 -86
  115. data/lib/yaks/fp.rb +0 -26
  116. data/lib/yaks/identifier/link_relation.rb +0 -17
  117. data/resources/iana-link-relations.csv +0 -152
  118. data/spec/json/youtypeitwepostit.collection.json +0 -45
  119. data/spec/unit/yaks/attributes_spec.rb +0 -178
  120. data/spec/unit/yaks/fp_spec.rb +0 -29
@@ -1,3 +1,5 @@
1
1
  class PetMapper < Yaks::Mapper
2
2
  attributes :id, :name, :species
3
3
  end
4
+ class GreatPetMapper < Yaks::Mapper; end
5
+ class GreatPetCollectionMapper < Yaks::Mapper; end
@@ -14,7 +14,7 @@ RSpec.shared_context 'yaks context' do
14
14
  let(:policy) { Yaks::DefaultPolicy.new }
15
15
  let(:rack_env) { {} }
16
16
  let(:mapper_stack) { [] }
17
- let(:yaks_context) { { policy: policy, env: rack_env, mapper_stack: mapper_stack } }
17
+ let(:yaks_context) { {policy: policy, env: rack_env, mapper_stack: mapper_stack} }
18
18
  end
19
19
 
20
20
  RSpec.shared_context 'plant collection resource' do
@@ -24,12 +24,12 @@ RSpec.shared_context 'plant collection resource' do
24
24
  let(:members) { [ plain_grass, oak, passiflora ] }
25
25
 
26
26
  [
27
- [ :plant , :profile , 'http://api.example.com/doc/plant' ],
28
- [ :plants , :profile , 'http://api.example.com/doc/plant_collection' ],
29
- [ :plants , :self , 'http://api.example.com/plants' ],
30
- [ :plain_grass , :self , 'http://api.example.com/plants/7/plain_grass' ],
31
- [ :oak , :self , 'http://api.example.com/plants/15/oak' ],
32
- [ :passiflora , :self , 'http://api.example.com/plants/33/passiflora' ],
27
+ [ :plant, :profile, 'http://api.example.com/doc/plant' ],
28
+ [ :plants, :profile, 'http://api.example.com/doc/plant_collection' ],
29
+ [ :plants, :self, 'http://api.example.com/plants' ],
30
+ [ :plain_grass, :self, 'http://api.example.com/plants/7/plain_grass' ],
31
+ [ :oak, :self, 'http://api.example.com/plants/15/oak' ],
32
+ [ :passiflora, :self, 'http://api.example.com/plants/33/passiflora' ]
33
33
  ].each do |name, type, uri|
34
34
  let(:"#{name}_#{type}_link") { Yaks::Resource::Link.new(rel: type, uri: uri) }
35
35
  end
@@ -44,14 +44,14 @@ RSpec.shared_context 'plant collection resource' do
44
44
  let(:oak) do
45
45
  Yaks::Resource.new(
46
46
  attributes: {name: "Oak", type: "tree"},
47
- links: [oak_self_link, plant_profile_link],
47
+ links: [oak_self_link, plant_profile_link]
48
48
  )
49
49
  end
50
50
 
51
51
  let(:passiflora) do
52
52
  Yaks::Resource.new(
53
53
  attributes: {name: "Passiflora", type: "flower"},
54
- links: [passiflora_self_link, plant_profile_link],
54
+ links: [passiflora_self_link, plant_profile_link]
55
55
  )
56
56
  end
57
57
  end
@@ -1,6 +1,6 @@
1
1
  RSpec.describe Yaks::Builder do
2
2
  class Buildable
3
- include Yaks::Attributes.new(:foo, :bar)
3
+ include Attribs.new(:foo, :bar)
4
4
 
5
5
  def self.create(foo, bar)
6
6
  new(foo: foo, bar: bar)
@@ -18,30 +18,54 @@ RSpec.describe Yaks::Builder do
18
18
  subject do
19
19
  Yaks::Builder.new(Buildable, [:finalize]) do
20
20
  def_set :foo, :bar
21
- def_forward :wrong_type, :update
21
+ def_forward :wrong_type, :with
22
22
  end
23
23
  end
24
24
 
25
- it 'should keep state' do
26
- expect(
27
- subject.create(3, 4) do
28
- foo 7
29
- update bar: 6
30
- end.to_h
31
- ).to eql(foo: 7, bar: 6)
32
- end
25
+ describe '#initialize' do
26
+ it 'should set the class to be instantiated' do
27
+ expect(subject.create(1, 2)).to be_instance_of Buildable
28
+ end
29
+
30
+ it 'should accept just a class' do
31
+ expect { Yaks::Builder.new(Buildable) }.to_not raise_error
32
+ end
33
+
34
+ it 'should define delegators for passed in method names' do
35
+ expect(subject).to respond_to(:finalize)
36
+ end
37
+
38
+ it 'should store the methods for inspection' do
39
+ expect(subject.inspect).to eql "#<Builder Buildable [:finalize]>"
40
+ end
33
41
 
34
- it 'should unwrap again' do
35
- expect( subject.create(3, 4) { finalize } ).to eql Buildable.new(foo: 7, bar: 8)
42
+ it 'should evaluate the passed in block' do
43
+ expect(subject).to respond_to(:foo)
44
+ end
36
45
  end
37
46
 
38
- context 'with no methods to forward' do
39
- subject do
40
- Yaks::Builder.new(Buildable)
47
+ describe '#create' do
48
+ it 'should keep state' do
49
+ expect(
50
+ subject.create(3, 4) do
51
+ foo 7
52
+ with bar: 6
53
+ end.to_h
54
+ ).to eql(foo: 7, bar: 6)
41
55
  end
42
56
 
43
- it 'should still work' do
44
- expect(subject.create(3,4)).to eql Buildable.new(foo: 3, bar: 4)
57
+ it 'should unwrap again' do
58
+ expect(subject.create(3, 4) { finalize }).to eql Buildable.new(foo: 7, bar: 8)
59
+ end
60
+
61
+ context 'with no methods to forward' do
62
+ subject do
63
+ Yaks::Builder.new(Buildable)
64
+ end
65
+
66
+ it 'should still work' do
67
+ expect(subject.create(3, 4)).to eql Buildable.new(foo: 3, bar: 4)
68
+ end
45
69
  end
46
70
  end
47
71
 
@@ -66,5 +90,4 @@ RSpec.describe Yaks::Builder do
66
90
  expect(subject.inspect).to eql '#<Builder Buildable [:foo, :bar]>'
67
91
  end
68
92
  end
69
-
70
93
  end
@@ -1,4 +1,4 @@
1
- RSpec.describe Yaks::CollectionMapper do
1
+ RSpec.describe Yaks::CollectionMapper, '#call' do
2
2
  include_context 'fixtures'
3
3
 
4
4
  subject(:mapper) { mapper_class.new(context) }
@@ -6,10 +6,10 @@ RSpec.describe Yaks::CollectionMapper do
6
6
  let(:mapper_stack) { [] }
7
7
 
8
8
  let(:context) {
9
- { item_mapper: item_mapper,
10
- policy: policy,
11
- env: {},
12
- mapper_stack: mapper_stack }
9
+ {item_mapper: item_mapper,
10
+ policy: policy,
11
+ env: {},
12
+ mapper_stack: mapper_stack}
13
13
  }
14
14
 
15
15
  let(:collection) { [] }
@@ -32,7 +32,7 @@ RSpec.describe Yaks::CollectionMapper do
32
32
 
33
33
  context 'when at the top of the stack' do
34
34
  it 'should have a "collection" rel derived from the type' do
35
- expect(mapper.call(collection).rels).to eql ['rel:the_types']
35
+ expect(mapper.call(collection).rels).to eql ['rel:the_types']
36
36
  end
37
37
  end
38
38
 
@@ -58,8 +58,8 @@ RSpec.describe Yaks::CollectionMapper do
58
58
  links: [],
59
59
  attributes: {},
60
60
  members: [
61
- Yaks::Resource.new(type: 'pet', attributes: {:id => 2, :species => "dog", :name => "boingboing"}),
62
- Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
61
+ Yaks::Resource.new(type: 'pet', attributes: {id: 2, species: "dog", name: "boingboing"}),
62
+ Yaks::Resource.new(type: 'pet', attributes: {id: 3, species: "cat", name: "wassup"})
63
63
  ],
64
64
  rels: ['rel:pets']
65
65
  )
@@ -82,8 +82,8 @@ RSpec.describe Yaks::CollectionMapper do
82
82
  links: [],
83
83
  attributes: {},
84
84
  members: [
85
- Yaks::Resource.new(type: 'pet', attributes: {:id => 2, :species => "dog", :name => "boingboing"}),
86
- Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
85
+ Yaks::Resource.new(type: 'pet', attributes: {id: 2, species: "dog", name: "boingboing"}),
86
+ Yaks::Resource.new(type: 'pet', attributes: {id: 3, species: "cat", name: "wassup"})
87
87
  ],
88
88
  rels: ['rel:pets']
89
89
  )
@@ -99,8 +99,13 @@ RSpec.describe Yaks::CollectionMapper do
99
99
 
100
100
  let(:collection) {
101
101
  Class.new(SimpleDelegator) do
102
- def foo ; 123 ; end
103
- def bar ; 'pi la~~~' ; end
102
+ def foo
103
+ 123
104
+ end
105
+
106
+ def bar
107
+ 'pi la~~~'
108
+ end
104
109
  end.new([])
105
110
  }
106
111
 
@@ -108,7 +113,7 @@ RSpec.describe Yaks::CollectionMapper do
108
113
  expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
109
114
  type: 'the_type',
110
115
  links: [],
111
- attributes: { foo: 123, bar: 'pi la~~~' },
116
+ attributes: {foo: 123, bar: 'pi la~~~'},
112
117
  members: [],
113
118
  rels: ['rel:the_types']
114
119
  )
@@ -126,7 +131,7 @@ RSpec.describe Yaks::CollectionMapper do
126
131
  expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
127
132
  type: 'the_type',
128
133
  links: [ Yaks::Resource::Link.new(rel: :self, uri: 'http://api.example.com/orders') ],
129
- attributes: { },
134
+ attributes: {},
130
135
  members: [],
131
136
  rels: ['rel:the_types']
132
137
  )
@@ -153,7 +158,7 @@ RSpec.describe Yaks::CollectionMapper do
153
158
  links: [],
154
159
  attributes: {},
155
160
  members: [
156
- Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
161
+ Yaks::Resource.new(type: 'pet', attributes: {id: 3, species: "cat", name: "wassup"})
157
162
  ],
158
163
  rels: ['rel:pets']
159
164
  )
@@ -161,12 +166,11 @@ RSpec.describe Yaks::CollectionMapper do
161
166
  end
162
167
 
163
168
  context 'with an empty collection' do
164
-
165
169
  context 'without an item_mapper specified' do
166
170
  let(:context) { Yaks::Util.slice_hash(super(), :policy, :env, :mapper_stack) }
167
171
 
168
172
  it 'should use a rel of "collection"' do
169
- expect(mapper.([]).rels).to eq ['collection']
173
+ expect(mapper.call([]).rels).to eq ['collection']
170
174
  end
171
175
  end
172
176
 
@@ -174,9 +178,8 @@ RSpec.describe Yaks::CollectionMapper do
174
178
  let(:context) { Yaks::Util.slice_hash(super(), :policy, :env, :mapper_stack, :item_mapper) }
175
179
 
176
180
  it 'should derive the collection rel from the item mapper' do
177
- expect(mapper.([]).rels).to eq ['rel:the_types']
181
+ expect(mapper.call([]).rels).to eq ['rel:the_types']
178
182
  end
179
183
  end
180
-
181
184
  end
182
185
  end
@@ -22,12 +22,12 @@ RSpec.describe Yaks::CollectionResource do
22
22
  Yaks::Resource::Link.new(rel: 'http://rels/summary', uri: 'http://order/10/summary'),
23
23
  Yaks::Resource::Link.new(rel: :profile, uri: 'http://rels/collection')
24
24
  ],
25
- attributes: { total: 10.00 },
25
+ attributes: {total: 10.00},
26
26
  members: [
27
27
  Yaks::Resource.new(
28
28
  type: 'order',
29
29
  links: [Yaks::Resource::Link.new(rel: :self, uri: 'http://order/10')],
30
- attributes: { customer: 'John Doe', price: 10.00 }
30
+ attributes: {customer: 'John Doe', price: 10.00}
31
31
  )
32
32
  ],
33
33
  rels: ['http://api.example.org/rels/orders']
@@ -35,17 +35,19 @@ RSpec.describe Yaks::CollectionResource do
35
35
  }
36
36
 
37
37
  its(:type) { should eql 'order' }
38
- its(:links) { should eql [
38
+ its(:links) {
39
+ should eql [
39
40
  Yaks::Resource::Link.new(rel: 'http://rels/summary', uri: 'http://order/10/summary'),
40
41
  Yaks::Resource::Link.new(rel: :profile, uri: 'http://rels/collection')
41
42
  ]
42
43
  }
43
- its(:attributes) { should eql( total: 10.00 ) }
44
- its(:members) { should eql [
44
+ its(:attributes) { should eql(total: 10.00) }
45
+ its(:members) {
46
+ should eql [
45
47
  Yaks::Resource.new(
46
48
  type: 'order',
47
49
  links: [Yaks::Resource::Link.new(rel: :self, uri: 'http://order/10')],
48
- attributes: { customer: 'John Doe', price: 10.00 }
50
+ attributes: {customer: 'John Doe', price: 10.00}
49
51
  )
50
52
  ]
51
53
  }
@@ -55,10 +57,16 @@ RSpec.describe Yaks::CollectionResource do
55
57
  end
56
58
 
57
59
  describe '#seq' do
58
- let(:init_opts) { { members: [1,2,3] } }
60
+ let(:init_opts) { {members: [1, 2, 3]} }
59
61
 
60
62
  it 'iterates over the members' do
61
- expect(subject.seq.map(&:next)).to eql [2,3,4]
63
+ expect(subject.seq.map(&:next)).to eql [2, 3, 4]
64
+ end
65
+ end
66
+
67
+ describe '#collection?' do
68
+ it 'should always be true' do
69
+ expect(subject.collection?).to be true
62
70
  end
63
71
  end
64
72
  end
@@ -16,42 +16,176 @@ RSpec.describe Yaks::Config do
16
16
  its(:hooks) { should eql([]) }
17
17
  its(:format_options_hash) { should eql({})}
18
18
  end
19
+ end
20
+
21
+ describe '#default_format' do
22
+ configure do
23
+ default_format :json_api
24
+ end
25
+
26
+ its(:default_format) { should equal :json_api }
27
+ end
28
+
29
+ describe '#policy_class' do
30
+ MyPolicy = Struct.new(:options)
31
+ configure do
32
+ policy_class MyPolicy
33
+ end
34
+
35
+ its(:policy_class) { should equal MyPolicy }
36
+ its(:policy) { should be_a MyPolicy }
37
+ end
38
+
39
+ describe '#rel_template' do
40
+ configure do
41
+ mapper_namespace Object
42
+ rel_template 'http://rel/foo'
43
+ end
44
+
45
+ its(:policy_options) { should eql(namespace: Object, rel_template: 'http://rel/foo') }
46
+ end
47
+
48
+ describe '#mapper_for' do
49
+ let(:expected_options) do
50
+ {
51
+ namespace: Object,
52
+ mapper_rules: {
53
+ home: HomeMapper,
54
+ Soy => MyMappers::WheatMapper
55
+ }
56
+ }
57
+ end
58
+ configure do
59
+ mapper_namespace Object
60
+ mapper_for Soy, MyMappers::WheatMapper
61
+ mapper_for :home, HomeMapper
62
+ end
63
+
64
+ its(:policy_options) { should eql(expected_options) }
65
+ end
19
66
 
20
- context 'with a default format' do
21
- configure do
22
- default_format :json_api
67
+ describe '#format_options' do
68
+ configure do
69
+ format_options :hal, plural_links: [:self, :profile]
70
+ format_options :collection_json, template: :template_form_name
71
+ end
72
+
73
+ it 'should set format options' do
74
+ expect(config.format_options_hash[:hal]).to eql(plural_links: [:self, :profile])
75
+ end
76
+ end
77
+
78
+ describe '#json_serializer' do
79
+ configure do
80
+ json_serializer(&:upcase)
81
+ end
82
+
83
+ specify do
84
+ expect(config.serializers[:json].call('foo')).to eql "FOO"
85
+ end
86
+ end
87
+
88
+ describe '#map_to_primitive' do
89
+ configure do
90
+ map_to_primitive Date do |date|
91
+ date.strftime("%Y-%m")
23
92
  end
93
+ end
24
94
 
25
- its(:default_format) { should equal :json_api }
95
+ it 'registers how to handle a primitive type' do
96
+ expect(config.primitivize.call(Date.new(2015, 10))).to eql "2015-10"
26
97
  end
27
98
 
28
- context 'with a custom policy class' do
29
- MyPolicy = Struct.new(:options)
30
- configure do
31
- policy_class MyPolicy
99
+ it 'should not change the existing primitize instance' do
100
+ old_prim = config.primitivize
101
+ config.map_to_primitive Date do |date|
102
+ date.strftime("%m-%Y")
32
103
  end
104
+ expect(old_prim.call(Date.new(2015, 10))).to eql "2015-10"
105
+ end
106
+ end
33
107
 
34
- its(:policy_class) { should equal MyPolicy }
35
- its(:policy) { should be_a MyPolicy }
108
+ describe '#mapper_namespace' do
109
+ configure do
110
+ rel_template '/foo/{rel}'
111
+ mapper_namespace Yaks::Mapper
112
+ end
113
+
114
+ it 'configures the policy to look in the given namespace' do
115
+ expect(config.policy.options[:namespace]).to eql Yaks::Mapper
36
116
  end
37
117
 
38
- context 'with a rel template' do
39
- configure do
40
- rel_template 'http://rel/foo'
118
+ it 'should not overwrite other options' do
119
+ expect(config.policy.options[:rel_template]).to eql '/foo/{rel}'
120
+ end
121
+ end
122
+
123
+ describe '#policy' do
124
+ PolicyClass = Class.new do
125
+ include Attribs.new(:namespace)
126
+ end
127
+
128
+ configure do
129
+ policy_class PolicyClass
130
+ mapper_namespace Yaks::Mapper
131
+ end
132
+
133
+ it 'returns an instantiated policy' do
134
+ expect(config.policy).to eql PolicyClass.new(namespace: Yaks::Mapper)
135
+ end
136
+ end
137
+
138
+ describe '#derive_mapper_from_object' do
139
+ configure { }
140
+ let(:object) { Pet.new(id: 7, name: 'fifi', species: 'cat') }
141
+ subject do
142
+ config.derive_mapper_from_object do |object|
143
+ mapper_class = super(object)
144
+ Object.const_get("Great#{mapper_class.name}")
41
145
  end
146
+ end
147
+
148
+ its(:policy_class) { should <= Yaks::DefaultPolicy }
42
149
 
43
- its(:policy_options) { should eql(rel_template: 'http://rel/foo') }
150
+ it 'should override the policy method' do
151
+ expect(subject.policy.derive_mapper_from_object(object)).to be GreatPetMapper
44
152
  end
153
+ end
45
154
 
46
- context 'with format options' do
47
- configure do
48
- format_options :hal, plural_links: [:self, :profile]
155
+ describe '#derive_mapper_from_item' do
156
+ configure { }
157
+ let(:object) { Pet.new(id: 7, name: 'fifi', species: 'cat') }
158
+ subject do
159
+ config.derive_mapper_from_item do |object|
160
+ mapper_class = super(object)
161
+ Object.const_get("Great#{mapper_class.name}")
49
162
  end
163
+ end
164
+
165
+ its(:policy_class) { should <= Yaks::DefaultPolicy }
166
+
167
+ it 'should override the policy method' do
168
+ expect(subject.policy.derive_mapper_from_item(object)).to be GreatPetMapper
169
+ expect(subject.policy.derive_mapper_from_object(object)).to be GreatPetMapper
170
+ end
171
+ end
50
172
 
51
- specify do
52
- expect(config.format_options_hash[:hal]).to eql(plural_links: [:self, :profile])
173
+ describe '#derive_mapper_from_collection' do
174
+ configure { }
175
+ let(:object) { [Pet.new(id: 7, name: 'fifi', species: 'cat')] }
176
+ subject do
177
+ config.derive_mapper_from_collection do |object|
178
+ mapper_class_name = super(object).name.split('::').last
179
+ Object.const_get("GreatPet#{mapper_class_name}")
53
180
  end
54
181
  end
182
+
183
+ its(:policy_class) { should <= Yaks::DefaultPolicy }
184
+
185
+ it 'should override the policy method' do
186
+ expect(subject.policy.derive_mapper_from_collection(object)).to be GreatPetCollectionMapper
187
+ expect(subject.policy.derive_mapper_from_object(object)).to be GreatPetCollectionMapper
188
+ end
55
189
  end
56
190
 
57
191
  describe '#call' do
@@ -66,4 +200,66 @@ RSpec.describe Yaks::Config do
66
200
  end
67
201
  end
68
202
 
203
+ describe '#map' do
204
+ configure {}
205
+
206
+ it 'only performs the mapping stage' do
207
+ expect(config.map(wassup))
208
+ .to eql Yaks::Resource.new(
209
+ type: "pet",
210
+ attributes: {id: 3, name: "wassup", species: "cat"}
211
+ )
212
+ end
213
+ end
214
+
215
+ describe '#read' do
216
+ configure {
217
+ default_format :json_api
218
+ }
219
+
220
+ it 'invokes the reader for the given format' do
221
+ expect(config.read('{"data": [{"type": "pets",
222
+ "id": 3,
223
+ "name": "wassup",
224
+ "species": "cat"}]}').members.first)
225
+ .to eql Yaks::Resource.new(
226
+ type: "pet",
227
+ attributes: {id: 3, name: "wassup", species: "cat"}
228
+ )
229
+ end
230
+ end
231
+
232
+ describe '#format' do
233
+ configure {
234
+ default_format :hal
235
+ }
236
+
237
+ it 'invokes the formatter on a resource' do
238
+ expect(config.format(Yaks::Resource.new(attributes: {shape: "round"})))
239
+ .to eql("shape" => "round")
240
+ end
241
+ end
242
+
243
+ describe '#runner' do
244
+ configure {}
245
+
246
+ it 'provides a Yaks::Runner' do
247
+ expect(config.runner(:foo, bar: 1))
248
+ .to eql Yaks::Runner.new(config: config, object: :foo, options: {bar: 1})
249
+ end
250
+ end
251
+
252
+ describe '#serializer' do
253
+ configure do
254
+ serializer(:foo) {|x| x.upcase.reverse }
255
+ end
256
+
257
+ it 'registers a serializer for a given type' do
258
+ expect(config.serializers[:foo].call('bar')).to eql 'RAB'
259
+ end
260
+
261
+ it 'should keep existing serializers' do
262
+ expect(config.serializers[:json].call([:foo, :bar], {})).to eql %{[\n "foo",\n "bar"\n]}
263
+ end
264
+ end
69
265
  end