rod-rest 0.0.1

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.
@@ -0,0 +1,109 @@
1
+ require 'bundler/setup'
2
+ require_relative 'test_helper'
3
+ require 'rod/rest/collection_proxy'
4
+
5
+ module Rod
6
+ module Rest
7
+ describe CollectionProxy do
8
+ let(:collection) { CollectionProxy.new(mercedes_proxy,association_name,size,client) }
9
+ let(:mercedes_proxy) { Object.new }
10
+ let(:association_name) { "drivers" }
11
+ let(:size) { 0 }
12
+ let(:client) { Object.new }
13
+
14
+ describe "#empty?" do
15
+ describe "with 0 elements" do
16
+ it "is empty" do
17
+ collection.empty?.should == true
18
+ end
19
+ end
20
+
21
+ describe "with 1 element" do
22
+ let(:size) { 1 }
23
+
24
+ it "is not empty" do
25
+ collection.empty?.should == false
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "#size" do
31
+ describe "with 5 elements" do
32
+ let(:size) { 5 }
33
+
34
+ it "has size of 5" do
35
+ collection.size.should == size
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "with car proxy" do
41
+ let(:car_type) { "Car" }
42
+ let(:mercedes_300_id) { 1 }
43
+
44
+ describe "with 3 drivers" do
45
+ let(:size) { 3 }
46
+ let(:schumaher) { Object.new }
47
+ let(:kubica) { Object.new }
48
+ let(:alonzo) { Object.new }
49
+
50
+ describe "#[index]" do
51
+ before do
52
+ stub(client).fetch_related_object(mercedes_proxy,association_name,1) { kubica }
53
+ stub(client).fetch_related_object(mercedes_proxy,association_name,5) { raise MissingResource.new("/cars/#{mercedes_300_id}/drivers/5") }
54
+ end
55
+
56
+ it "returns drivers by index" do
57
+ collection[1].should == kubica
58
+ end
59
+
60
+ it "returns nil in case of out of bounds driver" do
61
+ collection[5].should == nil
62
+ end
63
+ end
64
+
65
+ describe "#first" do
66
+ before do
67
+ stub(client).fetch_related_object(mercedes_proxy,association_name,0) { schumaher }
68
+ end
69
+
70
+ it "returns the first driver" do
71
+ collection.first.should == schumaher
72
+ end
73
+ end
74
+
75
+ describe "#last" do
76
+ before do
77
+ stub(client).fetch_related_object(mercedes_proxy,association_name,2) { alonzo }
78
+ end
79
+
80
+ it "returns the last driver" do
81
+ collection.last.should == alonzo
82
+ end
83
+ end
84
+
85
+ describe "#each" do
86
+ before do
87
+ stub(client).fetch_related_object(mercedes_proxy,association_name,0) { schumaher }
88
+ stub(client).fetch_related_object(mercedes_proxy,association_name,1) { kubica }
89
+ stub(client).fetch_related_object(mercedes_proxy,association_name,2) { alonzo }
90
+ end
91
+
92
+ it "iterates over the drivers" do
93
+ drivers = [schumaher,kubica,alonzo]
94
+ collection.each do |driver|
95
+ driver.should == drivers.shift
96
+ end
97
+ drivers.size.should == 0
98
+ end
99
+
100
+ it "allows to chain the calls" do
101
+ drivers = [schumaher,kubica,alonzo]
102
+ collection.each.map{|e| e }.should == drivers
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,108 @@
1
+ require 'bundler/setup'
2
+ require_relative 'test_helper'
3
+ require 'rod/rest/json_serializer'
4
+
5
+ stub_class 'Rod::Model'
6
+
7
+ module Rod
8
+ module Rest
9
+ describe JsonSerializer do
10
+ let(:serializer) { JsonSerializer.new }
11
+ let(:object) { object = stub!.class { resource }.subject
12
+ stub(object).rod_id { rod_id }
13
+ stub(object).is_a?(Rod::Model) { true }
14
+ object
15
+ }
16
+ let(:rod_id) { 1 }
17
+ let(:type) { "Car" }
18
+ let(:resource) { resource = stub!.fields { fields }.subject
19
+ stub(resource).singular_associations { singular_associations }
20
+ stub(resource).plural_associations { plural_associations }
21
+ stub(resource).to_s { type }
22
+ resource
23
+ }
24
+ let(:fields) { [] }
25
+ let(:singular_associations) { [] }
26
+ let(:plural_associations) { [] }
27
+ let(:result) { JSON.parse(serializer.serialize(object),symbolize_names: true) }
28
+
29
+
30
+ describe "resource without properties" do
31
+ it "serializes its rod_id" do
32
+ result[:rod_id].should == rod_id
33
+ end
34
+
35
+ it "serializes its type" do
36
+ result[:type].should == type
37
+ end
38
+ end
39
+
40
+ describe "resource with name field" do
41
+ let(:fields) { [name_field] }
42
+ let(:name_field) { stub!.name { field_name }.subject }
43
+ let(:field_name) { "brand" }
44
+ let(:brand) { "Mercedes" }
45
+
46
+ before do
47
+ stub(object).brand { brand }
48
+ end
49
+
50
+ it "serializes its name field" do
51
+ result[:brand].should == brand
52
+ end
53
+ end
54
+
55
+ describe "resource with 'owner' singular association" do
56
+ let(:singular_associations) { [owner_association] }
57
+ let(:owner_association) { stub!.name { owner_association_name }.subject }
58
+ let(:owner_association_name){ "owner" }
59
+ let(:owner) { owner = stub!.rod_id { owner_rod_id }.subject
60
+ stub(owner).class { owner_type }.subject
61
+ owner
62
+ }
63
+ let(:owner_rod_id) { 10 }
64
+ let(:owner_type) { "Person" }
65
+
66
+ describe "with existing owner" do
67
+ before do
68
+ stub(object).owner { owner }
69
+ end
70
+
71
+ it "serializes rod_id of the owner" do
72
+ result[:owner][:rod_id] == owner_rod_id
73
+ end
74
+
75
+ it "serializes type of the owner" do
76
+ result[:owner][:type] == owner_type
77
+ end
78
+ end
79
+
80
+ describe "without owner" do
81
+ before do
82
+ stub(object).owner { nil }
83
+ end
84
+
85
+ it "serializes the owner as nil" do
86
+ result[:owner].should == nil
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "resource with 'drivers' plural association" do
92
+ let(:plural_associations) { [drivers_association] }
93
+ let(:drivers_association) { stub!.name { driver_association_name }.subject }
94
+ let(:driver_association_name) { "drivers" }
95
+ let(:drivers) { stub!.size { drivers_count }.subject }
96
+ let(:drivers_count) { 1 }
97
+
98
+ before do
99
+ stub(object).drivers { drivers }
100
+ end
101
+
102
+ it "serializes the number of associated objects" do
103
+ result[:drivers][:count].should == drivers_count
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,37 @@
1
+ require 'bundler/setup'
2
+ require_relative 'test_helper'
3
+ require 'rod/rest/metadata'
4
+
5
+ module Rod
6
+ module Rest
7
+ describe Metadata do
8
+ let(:metadata) { Metadata.new(description: description, parser: parser, resource_metadata_factory: resource_metadata_factory) }
9
+ let(:parser) { stub!.parse(description,is_a(Hash)) { hash_description }.subject }
10
+ let(:description) { Object.new }
11
+ let(:hash_description) { { resource_name => resource_description, "Rod" => rod_description } }
12
+ let(:resource_description) { Object.new }
13
+ let(:rod_description) { Object.new }
14
+ let(:resource_metadata_factory) { stub!.new(resource_name,resource_description) { resource_metadata }.subject }
15
+ let(:resource_metadata) { Object.new }
16
+ let(:resource_name) { "Resource" }
17
+
18
+ it "creates the metadata from the description" do
19
+ metadata.resources
20
+ expect(parser).to have_received.parse(description,is_a(Hash))
21
+ end
22
+
23
+ it "returns collection of resource descriptions" do
24
+ metadata.resources.should respond_to(:each)
25
+ end
26
+
27
+ it "skips Rod pseudo-resource description" do
28
+ metadata.resources.size.should == hash_description.size - 1
29
+ end
30
+
31
+ it "creates the metadata description using the metadata factory" do
32
+ metadata.resources.first
33
+ expect(resource_metadata_factory).to have_received.new(resource_name,resource_description)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,63 @@
1
+ require 'bundler/setup'
2
+ require_relative 'test_helper'
3
+ require 'rod/rest/property_metadata'
4
+
5
+ module Rod
6
+ module Rest
7
+ describe PropertyMetadata do
8
+ let(:property_metadata) { PropertyMetadata.new(name,options) }
9
+
10
+ describe "constructor" do
11
+ it "forbids to create property without name" do
12
+ lambda { PropertyMetadata.new(nil,{}) }.should raise_error(ArgumentError)
13
+ end
14
+ end
15
+
16
+ describe "#name" do
17
+ let(:options) { { type: :integer } }
18
+ let(:name) { :age }
19
+
20
+ it "converts its name to string" do
21
+ property_metadata.name.should be_a(String)
22
+ end
23
+
24
+ it "returns the name of the poperty" do
25
+ property_metadata.name.should == name.to_s
26
+ end
27
+ end
28
+
29
+ describe "#symbolic_name" do
30
+ let(:options) { { type: :string } }
31
+ let(:name) { :name }
32
+
33
+ it "converts its symbolic name to string" do
34
+ property_metadata.symbolic_name.should be_a(Symbol)
35
+ end
36
+
37
+ it "returns the symbolic name of the poperty" do
38
+ property_metadata.symbolic_name.should == name.to_sym
39
+ end
40
+ end
41
+
42
+ describe "#indexed?" do
43
+ let(:options) { { type: :string, index: index } }
44
+ let(:name) { :brand }
45
+
46
+ describe "with index" do
47
+ let(:index) { :hash }
48
+
49
+ it "returns true" do
50
+ property_metadata.should be_indexed
51
+ end
52
+ end
53
+
54
+ describe "without index" do
55
+ let(:index) { nil }
56
+ it "returns false" do
57
+ property_metadata.should_not be_indexed
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,87 @@
1
+ require 'bundler/setup'
2
+ require_relative 'test_helper'
3
+ require 'rod/rest/proxy'
4
+
5
+ module Rod
6
+ module Rest
7
+ describe Proxy do
8
+ let(:proxy) { Proxy.new(metadata,client,collection_proxy_factory: collection_proxy_factory) }
9
+ let(:metadata) { metadata = stub!.fields { [id_field,name_field] }.subject
10
+ stub(metadata).singular_associations { [owner_association] }
11
+ stub(metadata).plural_associations { [drivers_association] }
12
+ stub(metadata).name { car_type }
13
+ metadata
14
+ }
15
+ let(:client) { client = stub!.fetch_object(schumaher_hash) { schumaher_object }.subject }
16
+ let(:collection_proxy_factory) { stub!.new(anything,drivers_association_name,drivers_count,client) { collection_proxy }.subject }
17
+ let(:collection_proxy) { Object.new }
18
+ let(:id_field) { property = stub!.symbolic_name { :rod_id }.subject
19
+ stub(property).name { "rod_id" }
20
+ property
21
+ }
22
+ let(:name_field) { property = stub!.symbolic_name { :name }.subject
23
+ stub(property).name { "name" }
24
+ property
25
+ }
26
+ let(:owner_association) { property = stub!.symbolic_name { :owner }.subject
27
+ stub(property).name { "owner" }
28
+ property
29
+ }
30
+ let(:drivers_association) { property = stub!.symbolic_name { drivers_association_name.to_sym }.subject
31
+ stub(property).name { drivers_association_name }
32
+ property
33
+ }
34
+ let(:drivers_association_name) { "drivers"}
35
+
36
+ let(:car_type) { "Test::Car" }
37
+ let(:mercedes_300_hash) { { rod_id: mercedes_300_id, name: mercedes_300_name, type: car_type,
38
+ owner: { rod_id: schumaher_id, type: person_type}, drivers: { count: drivers_count } } }
39
+ let(:mercedes_300_id) { 1 }
40
+ let(:mercedes_300_name) { "Mercedes 300" }
41
+
42
+ let(:person_type) { "Test::Person" }
43
+ let(:drivers_count) { 1 }
44
+ let(:schumaher_hash) { { rod_id: schumaher_id, type: person_type } }
45
+ let(:schumaher_id) { 2 }
46
+ let(:schumaher_object) { Object.new }
47
+ let(:owner_object) { schumaher_object }
48
+ let(:first_driver_object) { schumaher_object }
49
+
50
+ it "creates new instances" do
51
+ proxy.new(mercedes_300_hash).should_not == nil
52
+ end
53
+
54
+ it "refuses to create instances with missing rod_id" do
55
+ lambda { proxy.new({}) }.should raise_error(InvalidData)
56
+ end
57
+
58
+ it "refuses to create instances with missing type" do
59
+ lambda { proxy.new({rod_id: mercedes_300_id}) }.should raise_error(InvalidData)
60
+ end
61
+
62
+ describe "created instance" do
63
+ let(:mercedes_300) { proxy.new(mercedes_300_hash) }
64
+
65
+ it "has a type" do
66
+ mercedes_300.type.should == car_type
67
+ end
68
+
69
+ it "has an id" do
70
+ mercedes_300.rod_id.should == mercedes_300_id
71
+ end
72
+
73
+ it "has a valid 'name' field" do
74
+ mercedes_300.name.should == mercedes_300_name
75
+ end
76
+
77
+ it "has an valid 'owner' singular association" do
78
+ mercedes_300.owner.should == owner_object
79
+ end
80
+
81
+ it "has a valid 'drivers' plural association" do
82
+ mercedes_300.drivers.should == collection_proxy
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,44 @@
1
+ require 'bundler/setup'
2
+ require_relative 'test_helper'
3
+ require 'rod/rest/proxy_factory'
4
+
5
+ module Rod
6
+ module Rest
7
+ describe ProxyFactory do
8
+ let(:factory) { ProxyFactory.new(metadata,client,proxy_class: proxy_class) }
9
+ let(:metadata) { [car_metadata,person_metadata] }
10
+ let(:car_metadata) { stub!.name { car_type }.subject }
11
+ let(:person_metadata) { stub!.name { person_type }.subject }
12
+ let(:client) { Object.new }
13
+ let(:car_type) { "Car" }
14
+ let(:person_type) { "Person" }
15
+ let(:unknown_type) { "Unknown" }
16
+ let(:proxy_class) { klass = stub!.new(car_metadata,client) { car_proxy_factory }.subject
17
+ stub(klass).new(person_metadata,client) { person_proxy_factory }
18
+ klass
19
+ }
20
+ let(:car_proxy_factory) { stub!.new(mercedes_300_hash) { mercedes_300 }.subject }
21
+ let(:person_proxy_factory) { stub!.new(schumaher_hash) { schumaher }.subject }
22
+ let(:mercedes_300_hash) { { rod_id: mercedes_300_id, type: car_type } }
23
+ let(:schumaher_hash) { { rod_id: schumaher_id, type: person_type } }
24
+ let(:unknown_hash) { { rod_id: unknown_id, type: unknown_type } }
25
+ let(:mercedes_300_id) { 1 }
26
+ let(:schumaher_id) { 2 }
27
+ let(:unknown_id) { 3 }
28
+ let(:mercedes_300) { Object.new }
29
+ let(:schumaher) { Object.new }
30
+
31
+ it "builds new car from hash" do
32
+ factory.build(mercedes_300_hash).should == mercedes_300
33
+ end
34
+
35
+ it "builds new person proxy from hash" do
36
+ factory.build(schumaher_hash).should == schumaher
37
+ end
38
+
39
+ it "raises UnknownResource for unknown resource type" do
40
+ lambda { factory.build(unknown_hash) }.should raise_error(UnknownResource)
41
+ end
42
+ end
43
+ end
44
+ end