roar 0.0.1.alpha1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +8 -0
- data/README.textile +297 -0
- data/Rakefile +16 -0
- data/lib/roar/client/entity_proxy.rb +58 -0
- data/lib/roar/client/proxy.rb +14 -0
- data/lib/roar/client/transport.rb +29 -0
- data/lib/roar/model.rb +36 -0
- data/lib/roar/model/representable.rb +31 -0
- data/lib/roar/rails.rb +21 -0
- data/lib/roar/rails/controller_methods.rb +71 -0
- data/lib/roar/rails/representer_methods.rb +52 -0
- data/lib/roar/rails/test_case.rb +43 -0
- data/lib/roar/representer.rb +72 -0
- data/lib/roar/representer/feature/http_verbs.rb +63 -0
- data/lib/roar/representer/feature/hypermedia.rb +43 -0
- data/lib/roar/representer/feature/model_representing.rb +88 -0
- data/lib/roar/representer/json.rb +32 -0
- data/lib/roar/representer/xml.rb +43 -0
- data/lib/roar/version.rb +1 -1
- data/roar.gemspec +10 -1
- data/test/Gemfile +6 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/controllers/albums_controller.rb +27 -0
- data/test/dummy/app/controllers/application_controller.rb +4 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/album.rb +6 -0
- data/test/dummy/app/models/song.rb +2 -0
- data/test/dummy/app/representers/representer/xml/album.rb +19 -0
- data/test/dummy/app/representers/representer/xml/song.rb +9 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/musician/featured.html.erb +1 -0
- data/test/dummy/app/views/musician/featured_with_block.html.erb +4 -0
- data/test/dummy/app/views/musician/hamlet.html.haml +1 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +20 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +22 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +16 -0
- data/test/dummy/config/environments/production.rb +46 -0
- data/test/dummy/config/environments/test.rb +32 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +7 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20110514114753_create_albums.rb +14 -0
- data/test/dummy/db/migrate/20110514121228_create_songs.rb +14 -0
- data/test/dummy/db/schema.rb +29 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/module - (2011-05-14 15:26:19) +5 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/tmp/app/cells/blog/post/latest.html.erb +7 -0
- data/test/dummy/tmp/app/cells/blog/post_cell.rb +7 -0
- data/test/fake_server.rb +80 -0
- data/test/http_verbs_test.rb +46 -0
- data/test/hypermedia_test.rb +35 -0
- data/test/integration_test.rb +122 -0
- data/test/json_representer_test.rb +101 -0
- data/test/model_representing_test.rb +121 -0
- data/test/model_test.rb +50 -0
- data/test/order_representers.rb +34 -0
- data/test/proxy_test.rb +89 -0
- data/test/rails/controller_methods_test.rb +147 -0
- data/test/rails/rails_representer_methods_test.rb +32 -0
- data/test/representable_test.rb +49 -0
- data/test/representer_test.rb +25 -0
- data/test/ruby_representation_test.rb +144 -0
- data/test/test_helper.rb +45 -0
- data/test/test_helper_test.rb +59 -0
- data/test/transport_test.rb +34 -0
- data/test/xml_hypermedia_test.rb +47 -0
- data/test/xml_representer_test.rb +238 -0
- metadata +181 -13
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'roar/representer/feature/model_representing'
|
3
|
+
|
4
|
+
class ModelRepresentingTest < MiniTest::Spec
|
5
|
+
describe "ModelRepresenting" do
|
6
|
+
class ItemRepresenter < Roar::Representer::XML
|
7
|
+
include Roar::Representer::Feature::ModelRepresenting # TODO: move to abstract!
|
8
|
+
self.representation_name= :item
|
9
|
+
representable_property :value
|
10
|
+
end
|
11
|
+
|
12
|
+
class PositionRepresenter < Roar::Representer::XML
|
13
|
+
include Roar::Representer::Feature::ModelRepresenting # TODO: move to abstract!
|
14
|
+
self.representation_name= :position
|
15
|
+
representable_property :id
|
16
|
+
representable_property :item, :as => ItemRepresenter
|
17
|
+
end
|
18
|
+
|
19
|
+
class OrderRepresenter < Roar::Representer::XML
|
20
|
+
include Roar::Representer::Feature::ModelRepresenting # TODO: move to abstract!
|
21
|
+
self.representation_name= :order
|
22
|
+
representable_property :id
|
23
|
+
representable_property :items, :as => [ItemRepresenter]
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#definition_class" do
|
27
|
+
it "returns ModelDefinition" do
|
28
|
+
assert_equal Roar::Representer::Feature::ModelRepresenting::ModelDefinition, OrderRepresenter.send(:definition_class)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#for_model" do
|
34
|
+
it "copies represented model attributes, nothing more" do
|
35
|
+
@o = Position.new("id" => 1, "item" => Item.new("value" => "Beer"))
|
36
|
+
|
37
|
+
@r = PositionRepresenter.for_model(@o)
|
38
|
+
assert_kind_of PositionRepresenter, @r
|
39
|
+
assert_equal 1, @r.id
|
40
|
+
|
41
|
+
@i = @r.item
|
42
|
+
assert_kind_of ItemRepresenter, @i
|
43
|
+
assert_equal "Beer", @i.value
|
44
|
+
end
|
45
|
+
|
46
|
+
it "copies the model to @represented" do
|
47
|
+
@o = Position.new("id" => 1, "item" => @i = Item.new("value" => "Beer"))
|
48
|
+
|
49
|
+
@r = PositionRepresenter.for_model(@o)
|
50
|
+
assert_equal @o, @r.represented
|
51
|
+
assert_equal @i, @r.item.represented
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
it "works with Hyperlink attributes" do
|
56
|
+
@c = Class.new(ItemRepresenter) do
|
57
|
+
link :self do "http://self" end
|
58
|
+
end
|
59
|
+
|
60
|
+
assert_equal({"value"=>"Beer", "links"=>[{"rel"=>:self, "href"=>"http://self"}]}, @c.for_model(Item.new("value" => "Beer")).to_attributes)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#serialize_model" do
|
66
|
+
it "skips empty :item" do
|
67
|
+
@o = Position.new("id" => 1)
|
68
|
+
assert_xml_equal "<position><id>1</id></position>", PositionRepresenter.serialize_model(@o)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "skips empty [:items]" do
|
72
|
+
assert_xml_equal "<order><id>1</id></order>", OrderRepresenter.serialize_model(Order.new("id" => 1))
|
73
|
+
end
|
74
|
+
|
75
|
+
it "serializes the model" do
|
76
|
+
@o = Order.new("id" => 1, "items" => [Item.new("value" => "Beer")])
|
77
|
+
assert_xml_equal %{
|
78
|
+
<order>
|
79
|
+
<id>1</id>
|
80
|
+
<item>
|
81
|
+
<value>Beer</value>
|
82
|
+
</item>
|
83
|
+
</order>}"", OrderRepresenter.serialize_model(@o)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#to_nested_attributes" do
|
89
|
+
it "provides a AR-compatible hash" do
|
90
|
+
@o = Order.new("id" => 1, "items" => [Item.new("value" => "Beer")])
|
91
|
+
@r = OrderRepresenter.for_model(@o)
|
92
|
+
|
93
|
+
OrderRepresenter.class_eval do
|
94
|
+
include Roar::Representer::Feature::ActiveRecordMethods
|
95
|
+
end
|
96
|
+
assert_equal({"id" => 1, "items_attributes" => [{"value" => "Beer"}]}, @r.to_nested_attributes) # DISCUSS: overwrite #to_attributes.
|
97
|
+
end
|
98
|
+
|
99
|
+
it "doesn't include :links" do
|
100
|
+
@o = Order.new("id" => 1, "items" => [Item.new("value" => "Beer")])
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
OrderRepresenter.class_eval do
|
105
|
+
include Roar::Representer::Feature::ActiveRecordMethods
|
106
|
+
link :self do
|
107
|
+
# "bla"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
ItemRepresenter.class_eval do
|
111
|
+
link :self do
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
@r = OrderRepresenter.for_model(@o)
|
116
|
+
|
117
|
+
assert_equal({"id" => 1, "items_attributes" => [{"value" => "Beer"}]}, @r.to_nested_attributes) # DISCUSS: overwrite #to_attributes.
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/test/model_test.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ModelTest < MiniTest::Spec
|
4
|
+
describe "HttpVerbs" do
|
5
|
+
before do
|
6
|
+
@klass = Class.new(TestModel) do
|
7
|
+
include Roar::Model::HttpVerbs
|
8
|
+
|
9
|
+
self.resource_base = "http://localhost:9999/test/"
|
10
|
+
end
|
11
|
+
@o = @klass.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it "has resource_base* accessors for setting the uri base path" do
|
15
|
+
assert_equal "http://localhost:9999/test/", @klass.resource_base
|
16
|
+
end
|
17
|
+
|
18
|
+
it ".get returns deserialized object from " do
|
19
|
+
assert_equal({"id" => "4711"}, @klass.get(4711).attributes)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
describe "The Model API" do
|
25
|
+
class Dog
|
26
|
+
include Roar::Model
|
27
|
+
|
28
|
+
accessors :name
|
29
|
+
end
|
30
|
+
|
31
|
+
before do
|
32
|
+
@klass = Dog
|
33
|
+
end
|
34
|
+
|
35
|
+
it "the constructor accepts attributes" do
|
36
|
+
assert_equal({"id" => "4711"}, @klass.new({"id" => "4711"}).attributes)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "responds to .model_name" do
|
40
|
+
assert_equal "model_test/dog", @klass.model_name
|
41
|
+
end
|
42
|
+
|
43
|
+
it "lets .accessors create accessors" do
|
44
|
+
@o = @klass.new({"name" => "Joe"})
|
45
|
+
assert_equal "Joe", @o.name
|
46
|
+
@o.name= "Noe"
|
47
|
+
assert_equal "Noe", @o.name
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'roar/representer/json'
|
2
|
+
require 'roar/representer/feature/http_verbs'
|
3
|
+
require 'roar/representer/feature/hypermedia'
|
4
|
+
|
5
|
+
module JSON
|
6
|
+
|
7
|
+
class Item < Roar::Representer::JSON
|
8
|
+
property :article_id
|
9
|
+
property :amount
|
10
|
+
|
11
|
+
include Roar::Representer::Feature::HttpVerbs
|
12
|
+
include Roar::Representer::Feature::Hypermedia
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class Order < Roar::Representer::JSON
|
17
|
+
property :client_id
|
18
|
+
collection :items, :as => Item
|
19
|
+
|
20
|
+
|
21
|
+
include Roar::Representer::Feature::HttpVerbs
|
22
|
+
include Roar::Representer::Feature::Hypermedia
|
23
|
+
|
24
|
+
|
25
|
+
link :items do
|
26
|
+
items_url
|
27
|
+
end
|
28
|
+
|
29
|
+
link :self do
|
30
|
+
order_url(represented)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/test/proxy_test.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ProxyTest < MiniTest::Spec
|
4
|
+
describe "Transport" do
|
5
|
+
before do
|
6
|
+
@klass = Class.new(Object) do
|
7
|
+
include Roar::Client::Transport
|
8
|
+
end
|
9
|
+
@o = @klass.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it "#get_uri returns Restfulie response" do
|
13
|
+
assert_equal "<test><id>4711</id></test>", @o.get_uri("http://localhost:9999/test/4711").body
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
describe "The public Proxy API" do
|
19
|
+
before do
|
20
|
+
@klass = Class.new(TestModel) do
|
21
|
+
extend Roar::Client::Proxy
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "responds to .get_model" do
|
26
|
+
@o = @klass.get_model("http://localhost:9999/test/1", TestModel)
|
27
|
+
assert_kind_of TestModel, @o
|
28
|
+
assert_equal({"id" => "1"}, @o.attributes)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "EntityProxy" do
|
33
|
+
before do
|
34
|
+
Proxy = Roar::Client::EntityProxy
|
35
|
+
@proxy_class = Proxy.class_for(:class => TestModel)
|
36
|
+
end
|
37
|
+
|
38
|
+
it ".class_for returns an EntityProxy subclass" do
|
39
|
+
@proxy = @proxy_class.new
|
40
|
+
assert_kind_of Proxy, @proxy
|
41
|
+
end
|
42
|
+
|
43
|
+
it "responds to .options" do
|
44
|
+
assert_equal({:class => TestModel}, @proxy_class.send(:options))
|
45
|
+
end
|
46
|
+
|
47
|
+
it "doesn't override superclass options" do
|
48
|
+
assert_equal nil, Proxy.options
|
49
|
+
end
|
50
|
+
|
51
|
+
it "responds to .from_attributes and responds to #original_attributes" do
|
52
|
+
assert_equal({:urn => "urn:item"}, @proxy_class.from_attributes(:urn => "urn:item").send(:original_attributes))
|
53
|
+
end
|
54
|
+
|
55
|
+
it "responds to .model_name with the proxied name" do
|
56
|
+
assert_equal "test", @proxy_class.model_name
|
57
|
+
end
|
58
|
+
|
59
|
+
# finalize!
|
60
|
+
describe "#finalize!" do
|
61
|
+
before do
|
62
|
+
@o = @proxy_class.from_attributes("uri" => "http://localhost:9999/test/1")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "responds to #proxied_resource" do
|
66
|
+
assert_nil @o.send(:proxied_resource)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "#finalize! retrieves proxied resource" do
|
70
|
+
@o.finalize!
|
71
|
+
assert_kind_of TestModel, @o.send(:proxied_resource)
|
72
|
+
end
|
73
|
+
|
74
|
+
# delegation:
|
75
|
+
it "#attributes are delegated" do
|
76
|
+
@o.finalize!
|
77
|
+
assert_equal({"id" => "1"}, @o.attributes)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "#to_xml renders the unproxied entity" do
|
81
|
+
assert_equal "<test>\n <uri>http://localhost:9999/test/1</uri>\n</test>\n", @o.to_xml
|
82
|
+
end
|
83
|
+
|
84
|
+
it "#attributes_for_xml returns the unfinalized EntityProxy#attributes hash" do
|
85
|
+
assert_equal({"uri"=>"http://localhost:9999/test/1"}, @o.attributes_for_xml)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'roar/rails/test_case'
|
3
|
+
require "dummy/config/environment"
|
4
|
+
require "rails/test_help" # adds stuff like @routes, etc.
|
5
|
+
|
6
|
+
module Representer
|
7
|
+
module BMP
|
8
|
+
class Album; end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ControllerMethodsTest < ActionController::TestCase
|
13
|
+
tests AlbumsController
|
14
|
+
|
15
|
+
test "responds to #responder" do
|
16
|
+
assert_equal Roar::Rails::ControllerMethods::Responder, @controller.class.responder
|
17
|
+
end
|
18
|
+
|
19
|
+
test "responds to #represents" do
|
20
|
+
@controller = Class.new(AlbumsController)
|
21
|
+
assert_equal Album, @controller.represented_class
|
22
|
+
@controller.represents Song
|
23
|
+
assert_equal Song, @controller.represented_class
|
24
|
+
end
|
25
|
+
|
26
|
+
test "responds to #representer_class_for" do
|
27
|
+
assert_equal Representer::BMP::Album, @controller.representer_class_for(Album, :bmp)
|
28
|
+
end
|
29
|
+
|
30
|
+
test "responds to #representation" do
|
31
|
+
post :create, %{<album>
|
32
|
+
<year>2011</year>
|
33
|
+
<song>
|
34
|
+
<title>Walking In Your Footsteps</title>
|
35
|
+
</song>
|
36
|
+
</album>}, :format => :xml
|
37
|
+
|
38
|
+
|
39
|
+
assert_equal({"id"=>"", "year"=>"2011",
|
40
|
+
"songs_attributes"=>[{"title"=>"Walking In Your Footsteps"}]}, @controller.representation)
|
41
|
+
end
|
42
|
+
|
43
|
+
test "responds to #incoming" do
|
44
|
+
post :create, %{<album>
|
45
|
+
<year>2011</year>
|
46
|
+
<song>
|
47
|
+
<title>Walking In Your Footsteps</title>
|
48
|
+
</song>
|
49
|
+
</album>}, :format => :xml
|
50
|
+
|
51
|
+
|
52
|
+
assert_equal({"id"=>"", "year"=>"2011",
|
53
|
+
"songs"=>[{"title"=>"Walking In Your Footsteps"}], "links"=>[]}, @controller.incoming.to_attributes)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
class ControllerFunctionalTest < ActionController::TestCase
|
59
|
+
tests AlbumsController
|
60
|
+
|
61
|
+
test "GET: returns a xml representation" do
|
62
|
+
get :show, :id => 1, :format => :xml
|
63
|
+
|
64
|
+
assert_response 200
|
65
|
+
assert_body %{
|
66
|
+
<album>
|
67
|
+
<id>1</id>
|
68
|
+
<year>2011</year>
|
69
|
+
<song>
|
70
|
+
<title>Alltax</title>
|
71
|
+
</song>
|
72
|
+
<song>
|
73
|
+
<title>Bali</title>
|
74
|
+
</song>
|
75
|
+
|
76
|
+
<link rel="self" href="http://test.host/albums/1" />
|
77
|
+
<link rel="album-search" href="http://test.host/articles/starts_with/{query}" />
|
78
|
+
</album>}, :format => :xml
|
79
|
+
end
|
80
|
+
|
81
|
+
test "POST: creates a new album and returns the xml representation" do
|
82
|
+
post :create, %{<album>
|
83
|
+
<year>1997</year>
|
84
|
+
<song>
|
85
|
+
<title>Cooler Than You</title>
|
86
|
+
</song>
|
87
|
+
</album>}, :format => :xml
|
88
|
+
|
89
|
+
assert @album = Album.find(:last)
|
90
|
+
assert_equal "1997", @album.year
|
91
|
+
assert_equal "Cooler Than You", @album.songs.first.title
|
92
|
+
|
93
|
+
assert_response 201, "Location" => album_url(@album) # Created
|
94
|
+
assert_body %{
|
95
|
+
<album>
|
96
|
+
<id>2</id>
|
97
|
+
<year>1997</year>
|
98
|
+
<song>
|
99
|
+
<title>Cooler Than You</title>
|
100
|
+
</song>
|
101
|
+
|
102
|
+
<link rel="self" href="http://test.host/albums/2" />
|
103
|
+
<link rel="album-search" href="http://test.host/articles/starts_with/{query}" />
|
104
|
+
</album>}, :format => :xml
|
105
|
+
end
|
106
|
+
|
107
|
+
test "POST: invalid incoming representations yields to 422" do
|
108
|
+
post :create, :format => :xml
|
109
|
+
|
110
|
+
assert_response 422 # Unprocessable Entity
|
111
|
+
end
|
112
|
+
|
113
|
+
test "PUT: updates album and returns the xml representation" do
|
114
|
+
put :update, %{
|
115
|
+
<album>
|
116
|
+
<year>1997</year>
|
117
|
+
<song>
|
118
|
+
<title>Cooler Than You</title>
|
119
|
+
</song>
|
120
|
+
<song>
|
121
|
+
<title>Rubbing The Elf</title>
|
122
|
+
</song>
|
123
|
+
</album>}, :id => 1, :format => :xml
|
124
|
+
|
125
|
+
assert @album = Album.find(1)
|
126
|
+
assert_equal "1997", @album.year
|
127
|
+
assert_equal 2, @album.songs.size
|
128
|
+
assert_equal "Cooler Than You", @album.songs.first.title
|
129
|
+
assert_equal "Rubbing The Elf", @album.songs.last.title
|
130
|
+
|
131
|
+
assert_response 200
|
132
|
+
assert_body %{
|
133
|
+
<album>
|
134
|
+
<id>1</id>
|
135
|
+
<year>1997</year>
|
136
|
+
<song>
|
137
|
+
<title>Cooler Than You</title>
|
138
|
+
</song>
|
139
|
+
<song>
|
140
|
+
<title>Rubbing The Elf</title>
|
141
|
+
</song>
|
142
|
+
|
143
|
+
<link rel="self" href="http://test.host/albums/1" />
|
144
|
+
<link rel="album-search" href="http://test.host/articles/starts_with/{query}" />
|
145
|
+
</album>}, :format => :xml
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require "dummy/config/environment"
|
3
|
+
require 'roar/rails'
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
module JPG
|
7
|
+
class Song; end
|
8
|
+
class Album < Roar::Representer::XML; end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
class RailsRepresenterMethodsTest < MiniTest::Spec
|
15
|
+
describe "Rails::RepresenterMethods" do
|
16
|
+
before do
|
17
|
+
@c = Representer::JPG::Album # TODO: mix Rails into Base, not XML only.
|
18
|
+
end
|
19
|
+
|
20
|
+
it "provides conventions for #collection" do
|
21
|
+
@c.collection :songs
|
22
|
+
|
23
|
+
@d = @c.representable_attrs.first
|
24
|
+
assert_equal Representer::JPG::Song, @d.sought_type
|
25
|
+
assert @d.array?
|
26
|
+
end
|
27
|
+
|
28
|
+
it "provides conventions for #representation_name" do
|
29
|
+
assert_equal "album", @c.representation_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|