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,6 +1,12 @@
1
1
  RSpec.describe Yaks::Primitivize do
2
2
  subject(:primitivizer) { described_class.create }
3
3
 
4
+ describe "#initialize" do
5
+ it "should not create any mappings" do
6
+ expect(described_class.new.mappings).to eql Hash[]
7
+ end
8
+ end
9
+
4
10
  describe '.create' do
5
11
  it 'should map String, true, false, nil, numbers to themselves' do
6
12
  [
@@ -22,14 +28,17 @@ RSpec.describe Yaks::Primitivize do
22
28
 
23
29
  it 'should recursively handle hashes' do
24
30
  expect(primitivizer.call(
25
- :foo => {:wassup => :friends, 123 => '456'}
31
+ foo: {:wassup => :friends, 123 => '456'}
26
32
  )).to eql('foo' => {'wassup' => 'friends', 123 => '456'})
27
33
  end
28
34
 
29
35
  it 'should handle arrays recursively' do
30
- expect(primitivizer.call(
31
- [:foo, [:wassup, :friends], 123, '456']
32
- )).to eql( ['foo', ['wassup', 'friends'], 123, '456'] )
36
+ expect(primitivizer.call([:foo, [:wassup, :friends], 123, '456']))
37
+ .to eql(['foo', %w[wassup friends], 123, '456'])
38
+ end
39
+
40
+ it "should handle URIs by turning them to strings" do
41
+ expect(primitivizer.call(URI("http://foo.bar/baz"))).to eql "http://foo.bar/baz"
33
42
  end
34
43
  end
35
44
 
@@ -45,7 +54,8 @@ RSpec.describe Yaks::Primitivize do
45
54
  "I am funny"
46
55
  end
47
56
 
48
- expect { primitivizer.call(funny_object) }.to raise_error "don't know how to turn OpenStruct (I am funny) into a primitive"
57
+ expect { primitivizer.call(funny_object) }
58
+ .to raise_error Yaks::PrimitivizeError, "don't know how to turn OpenStruct (I am funny) into a primitive"
49
59
  end
50
60
 
51
61
  context 'with custom mapping' do
@@ -66,10 +76,19 @@ RSpec.describe Yaks::Primitivize do
66
76
  end
67
77
 
68
78
  it 'should evaluate in the context of primitivize' do
69
- expect( primitivizer.call( Vector[:foo, :baxxx, :bazz] ) ).to eql( [3, 5, 4] )
79
+ expect(primitivizer.call(Vector[:foo, :baxxx, :bazz])).to eql([3, 5, 4])
70
80
  end
71
81
  end
82
+ end
72
83
 
84
+ describe "#map" do
85
+ let(:primitivizer) { described_class.new }
73
86
 
87
+ it "should add new mappings" do
88
+ primitivizer.map(String) {|s| s.upcase }
89
+ primitivizer.map(Numeric) {|n| n.next }
90
+
91
+ expect(primitivizer.call("foo")).to eql "FOO"
92
+ end
74
93
  end
75
94
  end
@@ -11,12 +11,12 @@ RSpec.describe Yaks::Resource::Form::Field do
11
11
  described_class.new(name: 'foo', type: :select, options: [
12
12
  Yaks::Resource::Form::Field::Option.new(label: 'foo', selected: false, value: 1),
13
13
  Yaks::Resource::Form::Field::Option.new(label: 'foo', selected: true, value: 2),
14
- Yaks::Resource::Form::Field::Option.new(label: 'foo', selected: false, value: 3),
14
+ Yaks::Resource::Form::Field::Option.new(label: 'foo', selected: false, value: 3)
15
15
  ])
16
16
  end
17
17
 
18
18
  it 'should return the selected value' do
19
- expect( subject.value ).to eql 2
19
+ expect(subject.value).to eql 2
20
20
  end
21
21
  end
22
22
 
@@ -25,12 +25,12 @@ RSpec.describe Yaks::Resource::Form::Field do
25
25
  described_class.new(name: 'foo', type: :select, options: [
26
26
  Yaks::Resource::Form::Field::Option.new(label: 'foo', selected: false, value: 1),
27
27
  Yaks::Resource::Form::Field::Option.new(label: 'foo', selected: false, value: 2),
28
- Yaks::Resource::Form::Field::Option.new(label: 'foo', selected: false, value: 3),
28
+ Yaks::Resource::Form::Field::Option.new(label: 'foo', selected: false, value: 3)
29
29
  ])
30
30
  end
31
31
 
32
32
  it 'should return nothing' do
33
- expect( subject.value ).to be nil
33
+ expect(subject.value).to be nil
34
34
  end
35
35
  end
36
36
  end
@@ -48,7 +48,7 @@ RSpec.describe Yaks::Resource::Form::Field do
48
48
  Yaks::Resource::Form::Field::Option.new(label: 'f', selected: true, value: "1"),
49
49
  Yaks::Resource::Form::Field::Option.new(label: 'f', selected: false, value: "2"),
50
50
  Yaks::Resource::Form::Field::Option.new(label: 'f', selected: true, value: "3"),
51
- Yaks::Resource::Form::Field::Option.new(label: 'f', selected: false, value: "4"),
51
+ Yaks::Resource::Form::Field::Option.new(label: 'f', selected: false, value: "4")
52
52
  ])
53
53
  end
54
54
 
@@ -0,0 +1,7 @@
1
+ RSpec.describe Yaks::Resource::Form::Fieldset do
2
+ subject(:fieldset) { described_class.new(fields: []) }
3
+
4
+ describe '#type' do
5
+ its(:type) { should equal :fieldset }
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ RSpec.describe Yaks::Resource::Form::Legend do
2
+ subject(:legend) { described_class.new(label: 'a legend') }
3
+
4
+ describe '#initialize' do
5
+ its(:type) { should equal :legend }
6
+ its(:label) { should eql 'a legend' }
7
+ end
8
+ end
@@ -23,65 +23,45 @@ RSpec.describe Yaks::Resource::Form do
23
23
  end
24
24
  end
25
25
 
26
- describe '#fields_flat' do
27
- let(:fields) do
28
- [
29
- Yaks::Resource::Form::Fieldset.new(fields: [
30
- Yaks::Resource::Form::Field.new(name: :foo, value: '123', type: 'text'),
31
- Yaks::Resource::Form::Field.new(name: :bar, value: '+32 477 123 123', type: 'tel')
32
- ]),
33
- Yaks::Resource::Form::Fieldset.new(fields: [
34
- Yaks::Resource::Form::Fieldset.new(fields: [
35
- Yaks::Resource::Form::Field.new(name: :qux, value: '777', type: 'text'),
36
- ]),
37
- Yaks::Resource::Form::Field.new(name: :quux, value: '999', type: 'tel')
38
- ])
39
- ]
40
- end
41
-
42
- it 'should flatten fieldsets' do
43
- expect(subject.fields_flat).to eql [
44
- Yaks::Resource::Form::Field.new(name: :foo, value: '123', type: 'text'),
45
- Yaks::Resource::Form::Field.new(name: :bar, value: '+32 477 123 123', type: 'tel'),
46
- Yaks::Resource::Form::Field.new(name: :qux, value: '777', type: 'text'),
47
- Yaks::Resource::Form::Field.new(name: :quux, value: '999', type: 'tel')
48
- ]
49
- end
50
- end
51
-
52
26
  describe "#method?" do
53
27
  it 'should return true if method matches' do
54
28
  form_sym = Yaks::Resource::Form.new(name: :foo, method: :get)
55
29
  form_str = Yaks::Resource::Form.new(name: :foo, method: 'GET')
56
30
 
57
- expect(form_sym.method?(:get)).to eq(true)
58
- expect(form_sym.method?('get')).to eq(true)
59
- expect(form_str.method?(:get)).to eq(true)
60
- expect(form_str.method?('GET')).to eq(true)
31
+ expect(form_sym.method?(:get)).to be true
32
+ expect(form_sym.method?('get')).to be true
33
+ expect(form_str.method?(:get)).to be true
34
+ expect(form_str.method?('GET')).to be true
61
35
  end
62
36
 
63
37
  it 'should return false if method does not match' do
64
38
  form_sym = Yaks::Resource::Form.new(name: :foo, method: :get)
65
39
  form_str = Yaks::Resource::Form.new(name: :foo, method: 'GET')
66
40
 
67
- expect(form_sym.method?(:post)).to eq(false)
68
- expect(form_sym.method?('patch')).to eq(false)
69
- expect(form_str.method?(:delete)).to eq(false)
70
- expect(form_str.method?('PUT')).to eq(false)
41
+ expect(form_sym.method?(:post)).to be false
42
+ expect(form_sym.method?('patch')).to be false
43
+ expect(form_str.method?(:delete)).to be false
44
+ expect(form_str.method?('PUT')).to be false
45
+ end
46
+
47
+ it 'should always be false when method is not specified' do
48
+ form = Yaks::Resource::Form.new(name: :foo)
49
+
50
+ expect(form.method?(:post)).to be false
71
51
  end
72
52
  end
73
53
 
74
54
  describe "#has_action?" do
75
- it 'should return true if form has an action url' do
55
+ it 'should return true if form has an action url' do
76
56
  form = Yaks::Resource::Form.new(name: :foo, action: "/my-action")
77
57
 
78
- expect(form.has_action?).to eq(true)
58
+ expect(form.has_action?).to be true
79
59
  end
80
60
 
81
61
  it 'should return false if form has not an action url' do
82
62
  form = Yaks::Resource::Form.new(name: :foo)
83
63
 
84
- expect(form.has_action?).to eq(false)
64
+ expect(form.has_action?).to be false
85
65
  end
86
66
  end
87
67
  end
@@ -2,7 +2,7 @@ RSpec.describe Yaks::Resource::HasFields do
2
2
  let(:class_with_fields) do
3
3
  Class.new do
4
4
  include Yaks::Resource::HasFields
5
- include Yaks::Attributes.new(:fields)
5
+ include Attribs.new(:fields)
6
6
  end
7
7
  end
8
8
 
@@ -24,10 +24,9 @@ RSpec.describe Yaks::Resource::HasFields do
24
24
  subject(:with_fields) { class_with_fields.new(fields: fields) }
25
25
 
26
26
  describe '#map_fields' do
27
-
28
27
  let(:update_fields) do
29
28
  ->(field) do
30
- field.with({ value: "updated" })
29
+ field.with(value: "updated")
31
30
  end
32
31
  end
33
32
 
@@ -47,4 +46,46 @@ RSpec.describe Yaks::Resource::HasFields do
47
46
  end
48
47
  end
49
48
 
49
+ describe '#fields_flat' do
50
+ let(:fields) do
51
+ [
52
+ Yaks::Resource::Form::Fieldset.new(fields: [
53
+ Yaks::Resource::Form::Legend.new(label: 'a legend'),
54
+ Yaks::Resource::Form::Field.new(name: :foo, value: '123', type: 'text'),
55
+ Yaks::Resource::Form::Field.new(name: :bar, value: '+32 477 123 123', type: 'tel')
56
+ ]),
57
+ Yaks::Resource::Form::Fieldset.new(fields: [
58
+ Yaks::Resource::Form::Fieldset.new(fields: [
59
+ Yaks::Resource::Form::Field.new(name: :qux, value: '777', type: 'text')
60
+ ]),
61
+ Yaks::Resource::Form::Field.new(name: :quux, value: '999', type: 'tel')
62
+ ])
63
+ ]
64
+ end
65
+
66
+ it 'should flatten fieldsets, skipping legends' do
67
+ expect(subject.fields_flat.to_a).to eql [
68
+ Yaks::Resource::Form::Field.new(name: :foo, value: '123', type: 'text'),
69
+ Yaks::Resource::Form::Field.new(name: :bar, value: '+32 477 123 123', type: 'tel'),
70
+ Yaks::Resource::Form::Field.new(name: :qux, value: '777', type: 'text'),
71
+ Yaks::Resource::Form::Field.new(name: :quux, value: '999', type: 'tel')
72
+ ]
73
+ end
74
+
75
+ it 'should work like #map, collecting block return values, maintaining nesting' do
76
+ expect(subject.fields_flat {|f| f.with(required: true) }).to eql [
77
+ Yaks::Resource::Form::Fieldset.new(fields: [
78
+ Yaks::Resource::Form::Legend.new(label: 'a legend'),
79
+ Yaks::Resource::Form::Field.new(name: :foo, value: '123', type: 'text', required: true),
80
+ Yaks::Resource::Form::Field.new(name: :bar, value: '+32 477 123 123', type: 'tel', required: true)
81
+ ]),
82
+ Yaks::Resource::Form::Fieldset.new(fields: [
83
+ Yaks::Resource::Form::Fieldset.new(fields: [
84
+ Yaks::Resource::Form::Field.new(name: :qux, value: '777', type: 'text', required: true)
85
+ ]),
86
+ Yaks::Resource::Form::Field.new(name: :quux, value: '999', type: 'tel', required: true)
87
+ ])
88
+ ]
89
+ end
90
+ end
50
91
  end
@@ -3,18 +3,23 @@ RSpec.describe Yaks::Resource::Link do
3
3
 
4
4
  let(:rel) { :foo_rel }
5
5
  let(:uri) { 'http://api.example.org/rel/foo' }
6
- let(:options) { { title: 'mr. spectacular' } }
6
+ let(:options) { {title: 'mr. spectacular'} }
7
7
 
8
8
  its(:rel) { should eql :foo_rel }
9
9
  its(:uri) { should eql 'http://api.example.org/rel/foo' }
10
10
  its(:options) { should eql(title: 'mr. spectacular') }
11
11
 
12
- its(:title) { should eql('mr. spectacular') }
13
- its(:templated?) { should be false }
12
+ describe '#title' do
13
+ its(:title) { should eql('mr. spectacular') }
14
+ end
15
+
16
+ describe '#templated?' do
17
+ its(:templated?) { should be false }
14
18
 
15
- context 'with explicit templated option' do
16
- let(:options) { super().merge(templated: true) }
17
- its(:templated?) { should be true }
19
+ context 'with explicit templated option' do
20
+ let(:options) { super().merge(templated: true) }
21
+ its(:templated?) { should be true }
22
+ end
18
23
  end
19
24
 
20
25
  describe '#rel?' do
@@ -2,95 +2,20 @@ RSpec.describe Yaks::Resource do
2
2
  subject(:resource) { described_class.new(init_opts) }
3
3
  let(:init_opts) { {} }
4
4
 
5
- context 'with a zero-arg constructor' do
6
- subject(:resource) { described_class.new }
7
-
8
- its(:type) { should be_nil }
9
- its(:attributes) { should eql({}) }
10
- its(:links) { should eql [] }
11
- its(:subresources) { should eql [] }
12
- its(:self_link) { should be_nil }
13
- its(:null_resource?) { should be false }
14
- its(:collection?) { should be false }
15
- end
16
-
17
- context 'with a type' do
18
- let(:init_opts) { { type: 'post' } }
19
- its(:type) { should eql 'post' }
20
- end
21
-
22
- context 'with attributes' do
23
- let(:init_opts) { { attributes: {name: 'Arne', age: 31} } }
24
-
25
- it 'should delegate [] to attribute access' do
26
- expect(resource[:name]).to eql 'Arne'
27
- end
28
- end
29
-
30
- context 'with links' do
31
- let(:init_opts) {
32
- {
33
- links: [
34
- Yaks::Resource::Link.new(rel: :profile, uri: '/foo/bar/profile'),
35
- Yaks::Resource::Link.new(rel: :self, uri: '/foo/bar')
36
- ]
37
- }
38
- }
39
- its(:links) { should eql [
40
- Yaks::Resource::Link.new(rel: :profile, uri: '/foo/bar/profile'),
41
- Yaks::Resource::Link.new(rel: :self, uri: '/foo/bar')
42
- ]
43
- }
44
-
45
- its(:self_link) { should eql Yaks::Resource::Link.new(rel: :self, uri: '/foo/bar') }
46
- end
47
-
48
- context 'with subresources' do
49
- let(:init_opts) { { subresources: [ Yaks::Resource.new(type: 'comment', rels: ['comments']) ] } }
50
- its(:subresources) { should eql [Yaks::Resource.new(type: 'comment', rels: ['comments'])] }
51
-
52
- it 'should return an enumerable for #seq' do
53
- expect(resource.seq.each.with_index.to_a).to eq [ [resource, 0] ]
54
- end
55
- end
56
-
57
- it 'should act as a collection of one' do
58
- expect(resource.seq.each.to_a).to eql [resource]
59
- end
60
-
61
- describe 'persistent updates' do
62
- let(:resource) {
63
- Yaks::Resource.new(
64
- attributes: {x: :y},
65
- links: [:one],
66
- subresources: [ :subres ]
67
- )
68
- }
69
-
70
- it 'should do updates without modifying the original' do
71
- expect(
72
- resource
73
- .merge_attributes(foo: :bar)
74
- .add_link(:a_link)
75
- .add_subresource(:a_subresource)
76
- .merge_attributes(foo: :baz)
77
- ).to eq Yaks::Resource.new(
78
- attributes: {x: :y, foo: :baz},
79
- links: [:one, :a_link],
80
- subresources: [:subres, :a_subresource]
81
- )
82
-
83
- expect(resource).to eq Yaks::Resource.new(
84
- attributes: {x: :y},
85
- links: [:one],
86
- subresources: [:subres]
87
- )
5
+ describe '#initialize' do
6
+ context 'with a zero-arg constructor' do
7
+ subject(:resource) { described_class.new }
8
+
9
+ its(:type) { should be_nil }
10
+ its(:attributes) { should eql({}) }
11
+ its(:links) { should eql [] }
12
+ its(:subresources) { should eql [] }
13
+ its(:self_link) { should be_nil }
14
+ its(:null_resource?) { should be false }
88
15
  end
89
- end
90
16
 
91
- describe '#initialize' do
92
17
  it 'should verify subresources is an array' do
93
- expect { Yaks::Resource.new(subresources: { '/rel/comments' => []}) }
18
+ expect { Yaks::Resource.new(subresources: {'/rel/comments' => []}) }
94
19
  .to raise_exception /comments/
95
20
  end
96
21
 
@@ -100,17 +25,39 @@ RSpec.describe Yaks::Resource do
100
25
  end
101
26
 
102
27
  it 'should work without args' do
103
- expect( Yaks::Resource.new ).to be_a Yaks::Resource
28
+ expect(Yaks::Resource.new).to be_a Yaks::Resource
104
29
  end
105
30
 
106
31
  it 'should take defaults when no args are passed' do
107
- expect( Yaks::Resource.new.rels ).to eq []
32
+ expect(Yaks::Resource.new.rels).to eq []
33
+ end
34
+ end
35
+
36
+ describe "#[]" do
37
+ it "should access attributes" do
38
+ expect(described_class.new(attributes: {foo: :bar})[:foo]).to eql :bar
39
+ end
40
+ end
41
+
42
+ describe '#find_form' do
43
+ it 'should find a form by name' do
44
+ expect(resource
45
+ .add_form(Yaks::Resource::Form.new(name: :a_form))
46
+ .add_form(Yaks::Resource::Form.new(name: :b_form))
47
+ .find_form(:b_form))
48
+ .to eq Yaks::Resource::Form.new(name: :b_form)
49
+ end
50
+ end
51
+
52
+ describe "#seq" do
53
+ it "should provide an enumerable that yields this resource once" do
54
+ expect(resource.seq.each.to_a).to eql [resource]
108
55
  end
109
56
  end
110
57
 
111
58
  describe '#self_link' do
112
59
  let(:init_opts) {
113
- { links:
60
+ {links:
114
61
  [
115
62
  Yaks::Resource::Link.new(rel: :self, uri: 'foo'),
116
63
  Yaks::Resource::Link.new(rel: :self, uri: 'bar'),
@@ -123,6 +70,18 @@ RSpec.describe Yaks::Resource do
123
70
  end
124
71
  end
125
72
 
73
+ describe "#collection?" do
74
+ it "should be false" do
75
+ expect(resource.collection?).to be false
76
+ end
77
+ end
78
+
79
+ describe "#null_resource?" do
80
+ it "should be false" do
81
+ expect(resource.null_resource?).to be false
82
+ end
83
+ end
84
+
126
85
  describe '#add_rel' do
127
86
  it 'should add to the rels' do
128
87
  expect(resource.add_rel(:foo).add_rel(:bar))
@@ -130,6 +89,22 @@ RSpec.describe Yaks::Resource do
130
89
  end
131
90
  end
132
91
 
92
+ describe "#add_link" do
93
+ let(:init_opts) {
94
+ {
95
+ links: [Yaks::Resource::Link.new(rel: :next, uri: '/next')]
96
+ }
97
+ }
98
+
99
+ it "should append to the links list" do
100
+ expect(resource.add_link(Yaks::Resource::Link.new(rel: :previous, uri: '/previous')))
101
+ .to eql Yaks::Resource.new(links: [
102
+ Yaks::Resource::Link.new(rel: :next, uri: '/next'),
103
+ Yaks::Resource::Link.new(rel: :previous, uri: '/previous')
104
+ ])
105
+ end
106
+ end
107
+
133
108
  describe '#add_form' do
134
109
  it 'should append to the forms' do
135
110
  expect(resource.add_form(Yaks::Resource::Form.new(name: :a_form)))
@@ -137,13 +112,20 @@ RSpec.describe Yaks::Resource do
137
112
  end
138
113
  end
139
114
 
140
- describe '#find_form' do
141
- it 'should find a form by name' do
142
- expect(resource
143
- .add_form(Yaks::Resource::Form.new(name: :a_form))
144
- .add_form(Yaks::Resource::Form.new(name: :b_form))
145
- .find_form(:b_form))
146
- .to eq Yaks::Resource::Form.new(name: :b_form)
115
+ describe "#add_subresource" do
116
+ let(:init_opts) {
117
+ {
118
+ subresources: [Yaks::Resource.new(attributes: {foo: 1})]
119
+ }
120
+ }
121
+ it "should append to the subresources list" do
122
+ expect(resource.add_subresource(Yaks::Resource.new(attributes: {bar: 2})))
123
+ .to eql Yaks::Resource.new(
124
+ subresources: [
125
+ Yaks::Resource.new(attributes: {foo: 1}),
126
+ Yaks::Resource.new(attributes: {bar: 2})
127
+ ]
128
+ )
147
129
  end
148
130
  end
149
131
 
@@ -155,10 +137,17 @@ RSpec.describe Yaks::Resource do
155
137
  end
156
138
  end
157
139
 
140
+ describe "#merge_attributes" do
141
+ let(:init_opts) {{attributes: {foo: 1, bar: 2}}}
142
+ it "should merge attributes into any existing attributes" do
143
+ expect(resource.merge_attributes(bar: 3, baz: 4))
144
+ .to eql Yaks::Resource.new(attributes: {foo: 1, bar: 3, baz: 4})
145
+ end
146
+ end
147
+
158
148
  describe '#with_collection' do
159
149
  it 'should be a no-op' do
160
- expect(Yaks::Resource.new.with_collection([:foo])).to eql Yaks::Resource.new
150
+ expect(described_class.new.with_collection([:foo])).to eql Yaks::Resource.new
161
151
  end
162
152
  end
163
-
164
153
  end