roar 0.11.4 → 0.11.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.markdown +5 -1
- data/Gemfile +1 -1
- data/README.textile +22 -21
- data/lib/roar/representer.rb +1 -1
- data/lib/roar/representer/feature/client.rb +3 -3
- data/lib/roar/representer/feature/coercion.rb +1 -1
- data/lib/roar/representer/feature/http_verbs.rb +8 -9
- data/lib/roar/representer/feature/hypermedia.rb +83 -63
- data/lib/roar/representer/json.rb +12 -12
- data/lib/roar/representer/json/hal.rb +98 -25
- data/lib/roar/representer/transport/faraday.rb +5 -11
- data/lib/roar/representer/transport/net_http.rb +5 -5
- data/lib/roar/representer/xml.rb +11 -11
- data/lib/roar/version.rb +1 -1
- data/roar.gemspec +2 -2
- data/test/client_test.rb +2 -2
- data/test/coercion_feature_test.rb +2 -2
- data/test/dummy/app/controllers/albums_controller.rb +6 -6
- data/test/dummy/app/models/album.rb +1 -1
- data/test/dummy/app/representers/representer/xml/album.rb +3 -3
- data/test/dummy/app/representers/representer/xml/song.rb +1 -1
- data/test/dummy/config/boot.rb +1 -1
- data/test/fake_server.rb +14 -15
- data/test/faraday_http_transport_test.rb +25 -10
- data/test/hal_json_test.rb +73 -31
- data/test/http_verbs_feature_test.rb +12 -12
- data/test/hypermedia_feature_test.rb +38 -145
- data/test/hypermedia_test.rb +100 -0
- data/test/integration_test.rb +22 -22
- data/test/json_representer_test.rb +31 -31
- data/test/net_http_transport_test.rb +24 -10
- data/test/order_representers.rb +11 -11
- data/test/rails/controller_methods_test.rb +25 -25
- data/test/rails/rails_representer_methods_test.rb +3 -3
- data/test/representer_test.rb +6 -6
- data/test/test_helper.rb +33 -4
- data/test/xml_representer_test.rb +47 -47
- metadata +3 -3
- data/lib/roar/rails.rb +0 -21
@@ -8,25 +8,25 @@ module Representer
|
|
8
8
|
class Album; end
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
class ControllerMethodsTest < ActionController::TestCase
|
13
13
|
tests AlbumsController
|
14
|
-
|
14
|
+
|
15
15
|
test "responds to #responder" do
|
16
16
|
assert_equal Roar::Rails::ControllerMethods::Responder, @controller.class.responder
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
test "responds to #represents" do
|
20
20
|
@controller = Class.new(AlbumsController)
|
21
21
|
assert_equal Album, @controller.represented_class
|
22
22
|
@controller.represents Song
|
23
23
|
assert_equal Song, @controller.represented_class
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
test "responds to #representer_class_for" do
|
27
27
|
assert_equal Representer::BMP::Album, @controller.representer_class_for(Album, :bmp)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
test "responds to #representation" do
|
31
31
|
post :create, %{<album>
|
32
32
|
<year>2011</year>
|
@@ -34,12 +34,12 @@ class ControllerMethodsTest < ActionController::TestCase
|
|
34
34
|
<title>Walking In Your Footsteps</title>
|
35
35
|
</song>
|
36
36
|
</album>}, :format => :xml
|
37
|
-
|
38
|
-
|
37
|
+
|
38
|
+
|
39
39
|
assert_equal({"id"=>"", "year"=>"2011",
|
40
40
|
"songs_attributes"=>[{"title"=>"Walking In Your Footsteps"}]}, @controller.representation)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
test "responds to #incoming" do
|
44
44
|
post :create, %{<album>
|
45
45
|
<year>2011</year>
|
@@ -47,8 +47,8 @@ class ControllerMethodsTest < ActionController::TestCase
|
|
47
47
|
<title>Walking In Your Footsteps</title>
|
48
48
|
</song>
|
49
49
|
</album>}, :format => :xml
|
50
|
-
|
51
|
-
|
50
|
+
|
51
|
+
|
52
52
|
assert_equal({"id"=>"", "year"=>"2011",
|
53
53
|
"songs"=>[{"title"=>"Walking In Your Footsteps"}], "links"=>[]}, @controller.incoming.to_attributes)
|
54
54
|
end
|
@@ -57,14 +57,14 @@ end
|
|
57
57
|
|
58
58
|
class ControllerFunctionalTest < ActionController::TestCase
|
59
59
|
tests AlbumsController
|
60
|
-
|
60
|
+
|
61
61
|
test "GET: returns a xml representation" do
|
62
62
|
get :show, :id => 1, :format => :xml
|
63
|
-
|
63
|
+
|
64
64
|
assert_response 200
|
65
65
|
assert_body %{
|
66
66
|
<album>
|
67
|
-
<id>1</id>
|
67
|
+
<id>1</id>
|
68
68
|
<year>2011</year>
|
69
69
|
<song>
|
70
70
|
<title>Alltax</title>
|
@@ -72,12 +72,12 @@ class ControllerFunctionalTest < ActionController::TestCase
|
|
72
72
|
<song>
|
73
73
|
<title>Bali</title>
|
74
74
|
</song>
|
75
|
-
|
75
|
+
|
76
76
|
<link rel="self" href="http://test.host/albums/1" />
|
77
77
|
<link rel="album-search" href="http://test.host/articles/starts_with/{query}" />
|
78
78
|
</album>}, :format => :xml
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
test "POST: creates a new album and returns the xml representation" do
|
82
82
|
post :create, %{<album>
|
83
83
|
<year>1997</year>
|
@@ -85,31 +85,31 @@ class ControllerFunctionalTest < ActionController::TestCase
|
|
85
85
|
<title>Cooler Than You</title>
|
86
86
|
</song>
|
87
87
|
</album>}, :format => :xml
|
88
|
-
|
88
|
+
|
89
89
|
assert @album = Album.find(:last)
|
90
90
|
assert_equal "1997", @album.year
|
91
91
|
assert_equal "Cooler Than You", @album.songs.first.title
|
92
|
-
|
92
|
+
|
93
93
|
assert_response 201, "Location" => album_url(@album) # Created
|
94
94
|
assert_body %{
|
95
95
|
<album>
|
96
|
-
<id>2</id>
|
96
|
+
<id>2</id>
|
97
97
|
<year>1997</year>
|
98
98
|
<song>
|
99
99
|
<title>Cooler Than You</title>
|
100
100
|
</song>
|
101
|
-
|
101
|
+
|
102
102
|
<link rel="self" href="http://test.host/albums/2" />
|
103
103
|
<link rel="album-search" href="http://test.host/articles/starts_with/{query}" />
|
104
104
|
</album>}, :format => :xml
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
test "POST: invalid incoming representations yields to 422" do
|
108
108
|
post :create, :format => :xml
|
109
|
-
|
109
|
+
|
110
110
|
assert_response 422 # Unprocessable Entity
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
test "PUT: updates album and returns the xml representation" do
|
114
114
|
put :update, %{
|
115
115
|
<album>
|
@@ -121,13 +121,13 @@ class ControllerFunctionalTest < ActionController::TestCase
|
|
121
121
|
<title>Rubbing The Elf</title>
|
122
122
|
</song>
|
123
123
|
</album>}, :id => 1, :format => :xml
|
124
|
-
|
124
|
+
|
125
125
|
assert @album = Album.find(1)
|
126
126
|
assert_equal "1997", @album.year
|
127
127
|
assert_equal 2, @album.songs.size
|
128
128
|
assert_equal "Cooler Than You", @album.songs.first.title
|
129
129
|
assert_equal "Rubbing The Elf", @album.songs.last.title
|
130
|
-
|
130
|
+
|
131
131
|
assert_response 200
|
132
132
|
assert_body %{
|
133
133
|
<album>
|
@@ -139,7 +139,7 @@ class ControllerFunctionalTest < ActionController::TestCase
|
|
139
139
|
<song>
|
140
140
|
<title>Rubbing The Elf</title>
|
141
141
|
</song>
|
142
|
-
|
142
|
+
|
143
143
|
<link rel="self" href="http://test.host/albums/1" />
|
144
144
|
<link rel="album-search" href="http://test.host/articles/starts_with/{query}" />
|
145
145
|
</album>}, :format => :xml
|
@@ -16,15 +16,15 @@ class RailsRepresenterMethodsTest < MiniTest::Spec
|
|
16
16
|
before do
|
17
17
|
@c = Representer::JPG::Album # TODO: mix Rails into Base, not XML only.
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
it "provides conventions for #collection" do
|
21
21
|
@c.collection :songs
|
22
|
-
|
22
|
+
|
23
23
|
@d = @c.representable_attrs.first
|
24
24
|
assert_equal Representer::JPG::Song, @d.sought_type
|
25
25
|
assert @d.array?
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it "provides conventions for #representation_name" do
|
29
29
|
assert_equal "album", @c.representation_name
|
30
30
|
end
|
data/test/representer_test.rb
CHANGED
@@ -7,32 +7,32 @@ class RepresenterTest < MiniTest::Spec
|
|
7
7
|
include Roar::Representer
|
8
8
|
end
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
it "aliases #representable_property to #property" do
|
12
12
|
@c.property :title
|
13
13
|
assert_equal "title", @c.representable_attrs.first.name
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
it "aliases #representable_collection to #collection" do
|
17
17
|
@c.collection :songs
|
18
18
|
assert_equal "songs", @c.representable_attrs.first.name
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
describe "Inheritance" do
|
23
23
|
it "properly inherits properties from modules" do
|
24
24
|
module PersonRepresentation
|
25
25
|
include Roar::Representer::JSON
|
26
26
|
property :name
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
class Person
|
30
|
-
include
|
30
|
+
include AttributesConstructor
|
31
31
|
include Roar::Representer::JSON
|
32
32
|
include PersonRepresentation
|
33
33
|
attr_accessor :name
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
assert_equal "{\"name\":\"Paulo\"}", Person.new(:name => "Paulo").to_json
|
37
37
|
end
|
38
38
|
end
|
data/test/test_helper.rb
CHANGED
@@ -17,7 +17,7 @@ begin
|
|
17
17
|
rescue LoadError
|
18
18
|
end
|
19
19
|
|
20
|
-
module
|
20
|
+
module AttributesConstructor
|
21
21
|
def initialize(attrs={})
|
22
22
|
attrs.each do |k,v|
|
23
23
|
instance_variable_set("@#{k}", v)
|
@@ -26,17 +26,17 @@ module AttributesContructor
|
|
26
26
|
end
|
27
27
|
|
28
28
|
class Item
|
29
|
-
include
|
29
|
+
include AttributesConstructor
|
30
30
|
attr_accessor :value
|
31
31
|
end
|
32
32
|
|
33
33
|
class Position
|
34
|
-
include
|
34
|
+
include AttributesConstructor
|
35
35
|
attr_accessor :id, :item
|
36
36
|
end
|
37
37
|
|
38
38
|
class Order
|
39
|
-
include
|
39
|
+
include AttributesConstructor
|
40
40
|
attr_accessor :id, :items
|
41
41
|
end
|
42
42
|
|
@@ -49,3 +49,32 @@ require './test/fake_server'
|
|
49
49
|
ShamRack.at('roar.example.com').rackup do
|
50
50
|
run FakeServer
|
51
51
|
end
|
52
|
+
|
53
|
+
MiniTest::Spec.class_eval do
|
54
|
+
def link(options)
|
55
|
+
Roar::Representer::Feature::Hypermedia::Hyperlink.new(options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.representer_for(&block) # FIXME: move to test_helper.
|
59
|
+
let (:rpr) do
|
60
|
+
Module.new do
|
61
|
+
include Roar::Representer::JSON
|
62
|
+
include Roar::Representer::Feature::Hypermedia
|
63
|
+
|
64
|
+
instance_exec(&block)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
Roar::Representer::Feature::Hypermedia::Hyperlink.class_eval do
|
71
|
+
def ==(other)
|
72
|
+
stringify_hash(table) == stringify_hash(other.table)
|
73
|
+
end
|
74
|
+
|
75
|
+
def stringify_hash(hash)
|
76
|
+
hash.collect do |k,v|
|
77
|
+
[k.to_s, v.to_s]
|
78
|
+
end.sort
|
79
|
+
end
|
80
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ItemRepresenter
|
4
|
-
include
|
4
|
+
include AttributesConstructor
|
5
5
|
include Roar::Representer::XML
|
6
6
|
self.representation_wrap= :item
|
7
7
|
property :value
|
@@ -9,7 +9,7 @@ class ItemRepresenter
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class PositionRepresenter
|
12
|
-
include
|
12
|
+
include AttributesConstructor
|
13
13
|
include Roar::Representer::XML
|
14
14
|
self.representation_wrap= :position
|
15
15
|
property :id
|
@@ -20,69 +20,69 @@ end
|
|
20
20
|
|
21
21
|
class XMLRepresenterFunctionalTest < MiniTest::Spec
|
22
22
|
class Order
|
23
|
-
include
|
23
|
+
include AttributesConstructor
|
24
24
|
attr_accessor :id, :items
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
class GreedyOrder < Order
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
class TestXmlRepresenter
|
31
31
|
include Roar::Representer::XML
|
32
32
|
self.representation_wrap= :order
|
33
33
|
property :id
|
34
34
|
attr_accessor :id
|
35
35
|
end
|
36
|
-
|
37
|
-
|
36
|
+
|
37
|
+
|
38
38
|
describe "XMLRepresenter" do
|
39
39
|
before do
|
40
40
|
@m = {"id" => "1"}
|
41
41
|
@o = Order.new(@m)
|
42
|
-
|
42
|
+
|
43
43
|
@r = TestXmlRepresenter.new
|
44
44
|
@i = ItemRepresenter.new
|
45
45
|
@i.value = "Beer"
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
describe "#to_xml" do
|
49
49
|
it "serializes the model" do
|
50
50
|
assert_xml_equal "<order/>", @r.to_xml
|
51
|
-
|
51
|
+
|
52
52
|
@r.id = 1
|
53
53
|
assert_xml_equal "<order><id>1</id></order>", @r.to_xml
|
54
|
-
|
54
|
+
|
55
55
|
@r.id = 2
|
56
56
|
assert_xml_equal "<rap><id>2</id></rap>", @r.to_xml(:wrap => :rap)
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
it "is aliased by #serialize" do
|
60
60
|
assert_equal @r.to_xml, @r.serialize
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
it "accepts :include and :exclude" do
|
64
64
|
assert_equal '<order/>', @r.to_xml(:exclude => [:id])
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
describe "#from_xml" do
|
69
69
|
it "deserializes object" do
|
70
70
|
@order = Order.new.from_xml("<order><id>1</id></order>")
|
71
71
|
assert_equal "1", @order.id
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
it "is aliased by #deserialize" do
|
75
75
|
@order = Order.new.deserialize("<order><id>1</id></order>")
|
76
76
|
assert_equal "1", @order.id
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
it "accepts :include and :exclude" do
|
80
80
|
@order = Order.new.deserialize("<order><id>1</id></order>", :exclude => [:id])
|
81
81
|
assert_equal nil, @order.id
|
82
82
|
end
|
83
83
|
end
|
84
|
-
|
85
|
-
|
84
|
+
|
85
|
+
|
86
86
|
describe "XML.from_xml" do
|
87
87
|
class Order
|
88
88
|
include Roar::Representer::XML
|
@@ -90,96 +90,96 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
|
|
90
90
|
property :pending
|
91
91
|
attr_accessor :id, :pending
|
92
92
|
end
|
93
|
-
|
93
|
+
|
94
94
|
it "is aliased to #deserialize" do
|
95
95
|
assert_equal TestXmlRepresenter.from_xml("<order/>").id, TestXmlRepresenter.deserialize("<order/>").id
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
it "accepts :exclude option" do
|
99
99
|
order = Order.from_xml(%{<order><id>1</id><pending>1</pending></order>}, :exclude => [:id])
|
100
100
|
assert_equal nil, order.id
|
101
101
|
assert_equal "1", order.pending
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
it "accepts :include option" do
|
105
105
|
order = Order.from_xml(%{<order><id>1</id><pending>1</pending></order>}, :include => [:id])
|
106
106
|
assert_equal "1", order.id
|
107
107
|
assert_equal nil, order.pending
|
108
108
|
end
|
109
109
|
end
|
110
|
-
|
111
|
-
|
110
|
+
|
111
|
+
|
112
112
|
describe "without options" do
|
113
113
|
it ".from_xml returns the deserialized model" do
|
114
114
|
@m = TestXmlRepresenter.from_xml("<order><id>1</id></order>")
|
115
115
|
assert_equal "1", @m.id
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
#it ".from_xml still works with nil" do
|
119
119
|
# assert TestXmlRepresenter.from_xml(nil)
|
120
120
|
#end
|
121
|
-
|
121
|
+
|
122
122
|
end
|
123
|
-
|
124
|
-
|
123
|
+
|
124
|
+
|
125
125
|
describe "with a typed attribute" do
|
126
126
|
before do
|
127
127
|
@r = PositionRepresenter.new("id" => "1")
|
128
128
|
end
|
129
|
-
|
129
|
+
|
130
130
|
it "#serialize skips empty :item" do
|
131
131
|
assert_xml_equal "<position><id>1</id></position>", @r.to_xml
|
132
132
|
end
|
133
|
-
|
133
|
+
|
134
134
|
it "#to_xml delegates to ItemRepresenter#to_xml" do
|
135
135
|
@r.item = @i
|
136
136
|
assert_xml_equal "<position><id>1</id><item><value>Beer</value></item></position>", @r.to_xml
|
137
137
|
end
|
138
|
-
|
138
|
+
|
139
139
|
it ".from_xml typecasts :item" do
|
140
140
|
@m = PositionRepresenter.from_xml("<position><id>1</id><item><value>beer</value></item>\n</position>")
|
141
|
-
|
141
|
+
|
142
142
|
assert_equal "1", @m.id
|
143
143
|
assert_equal "beer", @m.item.value
|
144
144
|
end
|
145
145
|
end
|
146
|
-
|
147
|
-
|
146
|
+
|
147
|
+
|
148
148
|
describe "with a typed list" do
|
149
149
|
before do
|
150
150
|
@c = Class.new do
|
151
|
-
include
|
151
|
+
include AttributesConstructor
|
152
152
|
include Roar::Representer::XML
|
153
|
-
|
153
|
+
|
154
154
|
self.representation_wrap= :order
|
155
155
|
property :id
|
156
156
|
collection :items, :class => ItemRepresenter, :from => :item
|
157
157
|
attr_accessor :id, :items
|
158
158
|
end
|
159
|
-
|
159
|
+
|
160
160
|
@r = @c.new("id" => 1)
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
it "#serialize_model skips empty :item" do
|
164
164
|
assert_xml_equal "<order><id>1</id></order>", @r.to_xml
|
165
165
|
end
|
166
|
-
|
166
|
+
|
167
167
|
it "#serialize delegates to ItemXmlRepresenter#to_xml in list" do
|
168
168
|
@r.items = [ItemRepresenter.new("value" => "Bier")]
|
169
|
-
|
170
|
-
assert_xml_equal "<order><id>1</id><item><value>Bier</value></item></order>",
|
169
|
+
|
170
|
+
assert_xml_equal "<order><id>1</id><item><value>Bier</value></item></order>",
|
171
171
|
@r.to_xml
|
172
172
|
end
|
173
|
-
|
173
|
+
|
174
174
|
it ".from_xml typecasts list" do
|
175
175
|
@m = @c.from_xml("<order><id>1</id><item><value>beer</value></item>\n</order>")
|
176
|
-
|
176
|
+
|
177
177
|
assert_equal "1", @m.id
|
178
178
|
assert_equal 1, @m.items.size
|
179
179
|
assert_equal "beer", @m.items.first.value
|
180
180
|
end
|
181
181
|
end
|
182
|
-
|
182
|
+
|
183
183
|
end
|
184
184
|
end
|
185
185
|
|
@@ -188,19 +188,19 @@ class XmlHyperlinkRepresenterTest < MiniTest::Spec
|
|
188
188
|
before do
|
189
189
|
@link = Roar::Representer::Feature::Hypermedia::Hyperlink.new.extend(Roar::Representer::XML::HyperlinkRepresenter).from_xml(%{<link rel="self" href="http://roar.apotomo.de" media="web"/>})
|
190
190
|
end
|
191
|
-
|
191
|
+
|
192
192
|
it "responds to #rel" do
|
193
193
|
assert_equal "self", @link.rel
|
194
194
|
end
|
195
|
-
|
195
|
+
|
196
196
|
it "responds to #href" do
|
197
197
|
assert_equal "http://roar.apotomo.de", @link.href
|
198
198
|
end
|
199
|
-
|
199
|
+
|
200
200
|
it "responds to #media" do
|
201
201
|
assert_equal "web", @link.media
|
202
202
|
end
|
203
|
-
|
203
|
+
|
204
204
|
it "responds to #to_xml" do
|
205
205
|
assert_xml_equal %{<link rel=\"self\" href=\"http://roar.apotomo.de\" media="web"/>}, @link.to_xml
|
206
206
|
end
|