ruby_odata 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/.gitignore +3 -2
  2. data/.travis.yml +2 -1
  3. data/.yardopts +6 -0
  4. data/CHANGELOG.md +102 -0
  5. data/Guardfile +14 -0
  6. data/README.md +285 -0
  7. data/Rakefile +0 -7
  8. data/features/basic_auth.feature +3 -2
  9. data/features/batch_request.feature +7 -6
  10. data/features/cassettes/basic_auth_protected_resource.yml +57 -0
  11. data/features/cassettes/batch_request_additions.yml +69 -0
  12. data/features/cassettes/batch_request_deletes.yml +69 -0
  13. data/features/cassettes/batch_request_updates.yml +69 -0
  14. data/features/cassettes/clean_database_for_testing.yml +46 -0
  15. data/features/cassettes/cucumber_tags/basic_auth.yml +297 -0
  16. data/features/cassettes/cucumber_tags/batch_request.yml +1459 -0
  17. data/features/cassettes/cucumber_tags/complex_types.yml +326 -0
  18. data/features/cassettes/cucumber_tags/error_handling.yml +64 -0
  19. data/features/cassettes/cucumber_tags/query_builder.yml +2025 -0
  20. data/features/cassettes/cucumber_tags/service.yml +234 -0
  21. data/features/cassettes/cucumber_tags/service_manage.yml +937 -0
  22. data/features/cassettes/cucumber_tags/service_methods.yml +647 -0
  23. data/features/cassettes/cucumber_tags/ssl.yml +203 -0
  24. data/features/cassettes/cucumber_tags/type_conversion.yml +337 -0
  25. data/features/cassettes/service_manage_additions.yml +65 -0
  26. data/features/cassettes/service_manage_deletions.yml +58 -0
  27. data/features/cassettes/service_manage_deletions_2.yml +58 -0
  28. data/features/cassettes/unsecured_metadata.yml +89 -0
  29. data/features/complex_types.feature +4 -3
  30. data/features/error_handling.feature +14 -0
  31. data/features/query_builder.feature +30 -9
  32. data/features/service.feature +4 -3
  33. data/features/service_manage.feature +6 -5
  34. data/features/service_methods.feature +3 -2
  35. data/features/ssl.feature +8 -8
  36. data/features/step_definitions/service_steps.rb +38 -24
  37. data/features/support/env.rb +1 -3
  38. data/features/support/hooks.rb +3 -2
  39. data/features/support/pickle.rb +29 -18
  40. data/features/support/vcr.rb +24 -0
  41. data/features/type_conversion.feature +16 -17
  42. data/lib/ruby_odata/association.rb +7 -6
  43. data/lib/ruby_odata/class_builder.rb +6 -7
  44. data/lib/ruby_odata/exceptions.rb +4 -0
  45. data/lib/ruby_odata/helpers.rb +11 -0
  46. data/lib/ruby_odata/operation.rb +5 -6
  47. data/lib/ruby_odata/property_metadata.rb +4 -5
  48. data/lib/ruby_odata/query_builder.rb +98 -63
  49. data/lib/ruby_odata/service.rb +118 -103
  50. data/lib/ruby_odata/version.rb +3 -1
  51. data/lib/ruby_odata.rb +20 -18
  52. data/ruby_odata.gemspec +16 -12
  53. data/spec/query_builder_spec.rb +78 -14
  54. data/spec/service_spec.rb +83 -83
  55. data/spec/support/sample_service_matcher.rb +15 -0
  56. data/test/RubyODataService/RubyODataService/App_Data/.gitkeep +0 -0
  57. data/test/blueprints.rb +15 -9
  58. data/test/usage_samples/querying.rb +5 -1
  59. data/test/usage_samples/sample_data.rb +1 -3
  60. metadata +213 -39
  61. data/CHANGELOG.rdoc +0 -88
  62. data/README.rdoc +0 -259
@@ -0,0 +1,58 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://win7dev:8989/SampleService/RubyOData.svc/Products(1)
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*; q=0.5, application/xml'
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Cache-Control:
22
+ - no-cache
23
+ Content-Length:
24
+ - '1431'
25
+ Content-Type:
26
+ - application/atom+xml;type=entry;charset=utf-8
27
+ Server:
28
+ - Microsoft-IIS/7.5
29
+ Set-Cookie:
30
+ - ASP.NET_SessionId=pqd44q53aamnklanqbym2pcu; path=/; HttpOnly
31
+ X-Content-Type-Options:
32
+ - nosniff
33
+ Dataserviceversion:
34
+ - 1.0;
35
+ X-Aspnet-Version:
36
+ - 4.0.30319
37
+ X-Powered-By:
38
+ - ASP.NET
39
+ Date:
40
+ - Tue, 07 Aug 2012 21:47:37 GMT
41
+ body:
42
+ encoding: US-ASCII
43
+ string: <?xml version="1.0" encoding="utf-8"?><entry xml:base="http://win7dev:8989/SampleService/RubyOData.svc/"
44
+ xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
45
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss"
46
+ xmlns:gml="http://www.opengis.net/gml"><id>http://win7dev:8989/SampleService/RubyOData.svc/Products(1)</id><category
47
+ term="RubyODataService.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"
48
+ /><link rel="edit" title="Product" href="Products(1)" /><link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category"
49
+ type="application/atom+xml;type=entry" title="Category" href="Products(1)/Category"
50
+ /><title /><updated>2012-08-07T21:47:38Z</updated><author><name /></author><content
51
+ type="application/xml"><m:properties><d:Id m:type="Edm.Int32">1</d:Id><d:Name>Test
52
+ Product</d:Name><d:Description>Test Widget</d:Description><d:Price m:type="Edm.Decimal">10.25</d:Price><d:DiscontinuedDate
53
+ m:type="Edm.DateTime" m:null="true" /><d:CategoryId m:type="Edm.Int32">1</d:CategoryId><d:AuditFields
54
+ m:type="RubyODataService.AuditFields"><d:CreateDate m:type="Edm.DateTime">2012-08-07T21:47:38.157</d:CreateDate><d:ModifiedDate
55
+ m:type="Edm.DateTime">2012-08-07T21:47:38.157</d:ModifiedDate><d:CreatedBy>Machinist</d:CreatedBy></d:AuditFields></m:properties></content></entry>
56
+ http_version: !!null
57
+ recorded_at: Tue, 07 Aug 2012 21:47:38 GMT
58
+ recorded_with: VCR 2.2.4
@@ -0,0 +1,58 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://win7dev:8989/SampleService/RubyOData.svc/Products(1)
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*; q=0.5, application/xml'
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Cache-Control:
22
+ - no-cache
23
+ Content-Length:
24
+ - '1439'
25
+ Content-Type:
26
+ - application/atom+xml;type=entry;charset=utf-8
27
+ Server:
28
+ - Microsoft-IIS/7.5
29
+ Set-Cookie:
30
+ - ASP.NET_SessionId=1jtoo2ua0isload4ewywcbyh; path=/; HttpOnly
31
+ X-Content-Type-Options:
32
+ - nosniff
33
+ Dataserviceversion:
34
+ - 1.0;
35
+ X-Aspnet-Version:
36
+ - 4.0.30319
37
+ X-Powered-By:
38
+ - ASP.NET
39
+ Date:
40
+ - Tue, 07 Aug 2012 21:47:37 GMT
41
+ body:
42
+ encoding: US-ASCII
43
+ string: <?xml version="1.0" encoding="utf-8"?><entry xml:base="http://win7dev:8989/SampleService/RubyOData.svc/"
44
+ xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
45
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss"
46
+ xmlns:gml="http://www.opengis.net/gml"><id>http://win7dev:8989/SampleService/RubyOData.svc/Products(1)</id><category
47
+ term="RubyODataService.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"
48
+ /><link rel="edit" title="Product" href="Products(1)" /><link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category"
49
+ type="application/atom+xml;type=entry" title="Category" href="Products(1)/Category"
50
+ /><title /><updated>2012-08-07T21:47:38Z</updated><author><name /></author><content
51
+ type="application/xml"><m:properties><d:Id m:type="Edm.Int32">1</d:Id><d:Name>Changed
52
+ Test Product</d:Name><d:Description>Test Widget</d:Description><d:Price m:type="Edm.Decimal">10.25</d:Price><d:DiscontinuedDate
53
+ m:type="Edm.DateTime" m:null="true" /><d:CategoryId m:type="Edm.Int32">1</d:CategoryId><d:AuditFields
54
+ m:type="RubyODataService.AuditFields"><d:CreateDate m:type="Edm.DateTime">2012-08-07T21:47:38.157</d:CreateDate><d:ModifiedDate
55
+ m:type="Edm.DateTime">2012-08-07T21:47:38.157</d:ModifiedDate><d:CreatedBy>Machinist</d:CreatedBy></d:AuditFields></m:properties></content></entry>
56
+ http_version: !!null
57
+ recorded_at: Tue, 07 Aug 2012 21:47:38 GMT
58
+ recorded_with: VCR 2.2.4
@@ -0,0 +1,89 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://win7dev:8989/SampleService/RubyOData.svc/$metadata
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*; q=0.5, application/xml'
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Cache-Control:
22
+ - no-cache
23
+ Content-Length:
24
+ - '4055'
25
+ Content-Type:
26
+ - application/xml;charset=utf-8
27
+ Server:
28
+ - Microsoft-IIS/7.5
29
+ Set-Cookie:
30
+ - ASP.NET_SessionId=tvkikr3xqyy43kcx0mk1uwdr; path=/; HttpOnly
31
+ X-Content-Type-Options:
32
+ - nosniff
33
+ Dataserviceversion:
34
+ - 1.0;
35
+ X-Aspnet-Version:
36
+ - 4.0.30319
37
+ X-Powered-By:
38
+ - ASP.NET
39
+ Date:
40
+ - Tue, 07 Aug 2012 21:47:40 GMT
41
+ body:
42
+ encoding: US-ASCII
43
+ string: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"><edmx:DataServices
44
+ m:DataServiceVersion="1.0" m:MaxDataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><Schema
45
+ Namespace="RubyODataService" xmlns="http://schemas.microsoft.com/ado/2008/09/edm"><EntityType
46
+ Name="Product"><Key><PropertyRef Name="Id" /></Key><Property Name="Id" Type="Edm.Int32"
47
+ Nullable="false" p6:StoreGeneratedPattern="Identity" xmlns:p6="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
48
+ /><Property Name="Name" Type="Edm.String" MaxLength="4000" FixedLength="false"
49
+ Unicode="true" /><Property Name="Description" Type="Edm.String" MaxLength="4000"
50
+ FixedLength="false" Unicode="true" /><Property Name="Price" Type="Edm.Decimal"
51
+ Nullable="false" Precision="18" Scale="2" /><Property Name="DiscontinuedDate"
52
+ Type="Edm.DateTime" /><Property Name="CategoryId" Type="Edm.Int32" Nullable="false"
53
+ /><Property Name="AuditFields" Type="RubyODataService.AuditFields" Nullable="false"
54
+ /><NavigationProperty Name="Category" Relationship="RubyODataService.Category_Products"
55
+ ToRole="Category_Products_Source" FromRole="Category_Products_Target" /></EntityType><ComplexType
56
+ Name="AuditFields"><Property Name="CreateDate" Type="Edm.DateTime" Nullable="false"
57
+ /><Property Name="ModifiedDate" Type="Edm.DateTime" Nullable="false" /><Property
58
+ Name="CreatedBy" Type="Edm.String" MaxLength="4000" FixedLength="false" Unicode="true"
59
+ /></ComplexType><EntityType Name="Category"><Key><PropertyRef Name="Id" /></Key><Property
60
+ Name="Id" Type="Edm.Int32" Nullable="false" p6:StoreGeneratedPattern="Identity"
61
+ xmlns:p6="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /><Property
62
+ Name="Name" Type="Edm.String" MaxLength="4000" FixedLength="false" Unicode="true"
63
+ /><Property Name="AuditFields" Type="RubyODataService.AuditFields" Nullable="false"
64
+ /><NavigationProperty Name="Products" Relationship="RubyODataService.Category_Products"
65
+ ToRole="Category_Products_Target" FromRole="Category_Products_Source" /></EntityType><EntityType
66
+ Name="EdmMetadata"><Key><PropertyRef Name="Id" /></Key><Property Name="Id"
67
+ Type="Edm.Int32" Nullable="false" p6:StoreGeneratedPattern="Identity" xmlns:p6="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
68
+ /><Property Name="ModelHash" Type="Edm.String" MaxLength="4000" FixedLength="false"
69
+ Unicode="true" /></EntityType><Association Name="Category_Products"><End Type="RubyODataService.Product"
70
+ Role="Category_Products_Target" Multiplicity="*" /><End Type="RubyODataService.Category"
71
+ Role="Category_Products_Source" Multiplicity="1"><OnDelete Action="Cascade"
72
+ /></End><ReferentialConstraint><Principal Role="Category_Products_Source"><PropertyRef
73
+ Name="Id" /></Principal><Dependent Role="Category_Products_Target"><PropertyRef
74
+ Name="CategoryId" /></Dependent></ReferentialConstraint></Association><EntityContainer
75
+ Name="RubyODataContext" m:IsDefaultEntityContainer="true"><EntitySet Name="Products"
76
+ EntityType="RubyODataService.Product" /><EntitySet Name="Categories" EntityType="RubyODataService.Category"
77
+ /><EntitySet Name="EdmMetadatas" EntityType="RubyODataService.EdmMetadata"
78
+ /><AssociationSet Name="Category_Products" Association="RubyODataService.Category_Products"><End
79
+ Role="Category_Products_Target" EntitySet="Products" /><End Role="Category_Products_Source"
80
+ EntitySet="Categories" /></AssociationSet><FunctionImport Name="CleanDatabaseForTesting"
81
+ m:HttpMethod="POST" /><FunctionImport Name="EntityCategoryWebGet" ReturnType="Collection(RubyODataService.Category)"
82
+ EntitySet="Categories" m:HttpMethod="GET" /><FunctionImport Name="CategoryNames"
83
+ ReturnType="Collection(Edm.String)" m:HttpMethod="GET" /><FunctionImport Name="FirstCategoryId"
84
+ ReturnType="Edm.Int32" m:HttpMethod="GET" /><FunctionImport Name="EntitySingleCategoryWebGet"
85
+ ReturnType="RubyODataService.Category" EntitySet="Categories" m:HttpMethod="GET"><Parameter
86
+ Name="id" Type="Edm.Int32" /></FunctionImport></EntityContainer></Schema></edmx:DataServices></edmx:Edmx>
87
+ http_version: !!null
88
+ recorded_at: Tue, 07 Aug 2012 21:47:41 GMT
89
+ recorded_with: VCR 2.2.4
@@ -1,3 +1,4 @@
1
+ @complex_types
1
2
  Feature: Complex types
2
3
  In order to fully support OData services
3
4
  As a user of ruby_odata
@@ -12,7 +13,7 @@ Scenario: The proxy must generate classes for complex types if they exist
12
13
 
13
14
  Scenario: Complex properties on an entity must be the correct type
14
15
  Given I call "AddToProducts" on the service with a new "Product" object
15
- And I save changes
16
+ And I save changes
16
17
  And I call "Products" on the service with args: "1"
17
18
  When I run the query
18
19
  Then the first result should have a method: "AuditFields"
@@ -25,10 +26,10 @@ Scenario: Complex properties on an entity must be filled
25
26
  When I run the query
26
27
  Then the first result should have a method: "AuditFields"
27
28
  When I call "CreateDate" for "AuditFields" on the first result
28
- Then the operation should not be null
29
+ Then the operation should not be null
29
30
 
30
31
  # TODO: This scenario should have the AuditFields.CreatedBy field set in the Given
31
- # instead it is set by the blueprint
32
+ # instead it is set by the blueprint
32
33
  Scenario: Complex properties should be able to be added
33
34
  Given I call "AddToProducts" on the service with a new "Product" object
34
35
  And I save changes
@@ -0,0 +1,14 @@
1
+ @error_handling
2
+ Feature: Error handling
3
+ In order to assist debugging
4
+ As a user
5
+ I want more debug information when an error occurs communicating with the server
6
+
7
+ Background:
8
+ Given a HTTP ODataService exists
9
+ And blueprints exist for the service
10
+
11
+ Scenario: Violate a data type conversion (empty string to decimal)
12
+ Given I call "AddToProducts" on the service with a new "Product" object with Price: ""
13
+ When I save changes it should throw an exception with message containing "HTTP Error 400"
14
+
@@ -1,7 +1,8 @@
1
+ @query_builder
1
2
  Feature: Query Builder
2
3
  In order to query OData services
3
4
  As a user
4
- I want to be able to perform valid OData protocol operations
5
+ I want to be able to perform valid OData protocol operations
5
6
 
6
7
  Background:
7
8
  Given a HTTP ODataService exists
@@ -12,7 +13,7 @@ Scenario: Navigation Properties should be able to be eager loaded
12
13
  Given I call "AddToCategories" on the service with a new "Category" object with Name: "Test Category"
13
14
  And I save changes
14
15
  And I call "AddToProducts" on the service with a new "Product" object with Category: "@@LastSave.first"
15
- And I save changes
16
+ And I save changes
16
17
  And I call "Products" on the service with args: "1"
17
18
  And I expand the query to include "Category"
18
19
  When I run the query
@@ -99,14 +100,14 @@ Scenario: Skip should be allowed on the root level entity
99
100
  | Product 2 |
100
101
  | Product 3 |
101
102
  | Product 4 |
102
- | Product 5 |
103
+ | Product 5 |
103
104
  When I call "Products" on the service
104
105
  And I skip 3
105
106
  And I run the query
106
107
  Then the result should be:
107
108
  | Name |
108
109
  | Product 4 |
109
- | Product 5 |
110
+ | Product 5 |
110
111
 
111
112
 
112
113
  # Top
@@ -117,14 +118,14 @@ Scenario: Top should be allowed on the root level entity
117
118
  | Product 2 |
118
119
  | Product 3 |
119
120
  | Product 4 |
120
- | Product 5 |
121
+ | Product 5 |
121
122
  When I call "Products" on the service
122
123
  And I ask for the top 3
123
124
  And I run the query
124
125
  Then the result should be:
125
126
  | Name |
126
127
  | Product 1 |
127
- | Product 2 |
128
+ | Product 2 |
128
129
  | Product 3 |
129
130
 
130
131
  Scenario: Top should be able to be used along with skip for paging
@@ -134,8 +135,8 @@ Scenario: Top should be able to be used along with skip for paging
134
135
  | Product 2 |
135
136
  | Product 3 |
136
137
  | Product 4 |
137
- | Product 5 |
138
- | Product 6 |
138
+ | Product 5 |
139
+ | Product 6 |
139
140
  When I call "Products" on the service
140
141
  And I skip 2
141
142
  And I ask for the top 2
@@ -143,7 +144,7 @@ Scenario: Top should be able to be used along with skip for paging
143
144
  Then the result should be:
144
145
  | Name |
145
146
  | Product 3 |
146
- | Product 4 |
147
+ | Product 4 |
147
148
 
148
149
 
149
150
  # Links
@@ -160,3 +161,23 @@ Scenario: Navigation Properties should be able to represented as links
160
161
  And I run the query
161
162
  Then the result count should be 3
162
163
  Then the method "path" on the first result should equal: "/SampleService/RubyOData.svc/Products(1)"
164
+
165
+ # Count
166
+ Scenario: Count should be able to be used on a root collection
167
+ Given 4 products exist
168
+ When I call "Products" on the service
169
+ And I ask for the count
170
+ And I run the query
171
+ Then the integer result should be 4
172
+
173
+ Scenario: Count should be able to be used on with a filter
174
+ Given the following products exist:
175
+ | Name |
176
+ | Product 1 |
177
+ | Product 2 |
178
+ When I call "Products" on the service
179
+ And I filter the query with: "Name eq 'Product 2'"
180
+ And I ask for the count
181
+ And I run the query
182
+ Then the integer result should be 1
183
+
@@ -1,3 +1,4 @@
1
+ @service
1
2
  Feature: Service Should Generate a Proxy
2
3
  In order to consume the OData
3
4
  As a user
@@ -30,7 +31,7 @@ Scenario: Entity should have the correct accessors
30
31
  When I run the query
31
32
  Then the first result should have a method: "Id"
32
33
  And the first result should have a method: "Name"
33
-
34
+
34
35
  Scenario: Entity should fill values
35
36
  Given I call "AddToCategories" on the service with a new "Category" object with Name: "Test Category"
36
37
  And I save changes
@@ -39,9 +40,9 @@ Scenario: Entity should fill values
39
40
  Then the method "Id" on the first result should equal: "1"
40
41
  And the method "Name" on the first result should equal: "Test Category"
41
42
 
42
- Scenario: Navigation Properties should be included in results
43
+ Scenario: Navigation Properties should be included in results
43
44
  Given I call "AddToProducts" on the service with a new "Product" object
44
- And I save changes
45
+ And I save changes
45
46
  And I call "Products" on the service with args: "1"
46
47
  When I run the query
47
48
  Then the first result should have a method: "Category"
@@ -1,3 +1,4 @@
1
+ @service_manage
1
2
  Feature: Service management
2
3
  In order to manage entities
3
4
  As a admin
@@ -9,7 +10,7 @@ Background:
9
10
 
10
11
  Scenario: Service should respond to AddToEntityName for adding objects
11
12
  Given I call "AddToProducts" on the service with a new "Product" object with Name: "Sample Product"
12
- When I save changes
13
+ When I save changes within a cassette named "service_manage_additions"
13
14
  Then the first save result should be of type "Product"
14
15
  And the method "Name" on the first save result should equal: "Sample Product"
15
16
 
@@ -19,7 +20,7 @@ Scenario: Service should allow for deletes
19
20
  Then the first save result should be of type "Product"
20
21
  When I call "delete_object" on the service with the first last save result
21
22
  And I save changes
22
- Then the save result should equal: "true"
23
+ Then the save result should equal: "true"
23
24
  And no "Products" should exist
24
25
 
25
26
  Scenario: Untracked entities shouldn't be able to be deleted
@@ -29,7 +30,7 @@ Scenario: Entities should be able to be updated
29
30
  Given I call "AddToProducts" on the service with a new "Product" object with Name: "Test Product"
30
31
  When I save changes
31
32
  And I call "Products" on the service with args: "1"
32
- And I run the query
33
+ And I run the query within a cassette named "service_manage_deletions"
33
34
  Then the method "Name" on the first result should equal: "Test Product"
34
35
  When I set "Name" on the first result to "Changed Test Product"
35
36
  Then the method "Name" on the first result should equal: "Changed Test Product"
@@ -37,7 +38,7 @@ Scenario: Entities should be able to be updated
37
38
  And I save changes
38
39
  Then the save result should equal: "true"
39
40
  When I call "Products" on the service with args: "1"
40
- And I run the query
41
+ And I run the query within a cassette named "service_manage_deletions_2"
41
42
  Then the method "Name" on the first result should equal: "Changed Test Product"
42
43
 
43
44
  Scenario: Untracked entities shouldn't be able to be updated
@@ -47,7 +48,7 @@ Scenario: Related entities shouldn't be recreated on a child add
47
48
  Given I call "AddToCategories" on the service with a new "Category" object with Name: "Test Category"
48
49
  And I save changes
49
50
  And I call "AddToProducts" on the service with a new "Product" object with Category: "@@LastSave.first"
50
- And I save changes
51
+ And I save changes
51
52
  And I call "Products" on the service with args: "1"
52
53
  And I expand the query to include "Category"
53
54
  When I run the query
@@ -1,3 +1,4 @@
1
+ @service_methods
1
2
  Feature: Service methods
2
3
  In order to use a WCF Data Service more efficiently
3
4
  As a consumer
@@ -5,9 +6,9 @@ Feature: Service methods
5
6
 
6
7
  Background:
7
8
  Given a HTTP ODataService exists
8
- And blueprints exist for the service
9
+ And blueprints exist for the service
10
+
9
11
 
10
-
11
12
  Scenario: A custom web get (no parameters) that returns an entity
12
13
  Given a category exists
13
14
  And I call the service method "EntityCategoryWebGet"
data/features/ssl.feature CHANGED
@@ -1,13 +1,14 @@
1
+ @ssl
1
2
  Feature: Service Should Access Basic Resources via SSL using a self-signed certificate
2
-
3
- Background:
4
- Given a HTTPS BasicAuth ODataService exists using self-signed certificate and username "admin" and password "passwd"
5
- And blueprints exist for the service
6
3
 
7
4
  Scenario: Service should respond to valid collections
5
+ Given a HTTPS BasicAuth ODataService exists using self-signed certificate and username "admin" and password "passwd"
6
+ And blueprints exist for the service
8
7
  Then I should be able to call "Products" on the service
9
8
 
10
9
  Scenario: Entity should fill values on protected resource
10
+ Given a HTTPS BasicAuth ODataService exists using self-signed certificate and username "admin" and password "passwd"
11
+ And blueprints exist for the service
11
12
  Given I call "AddToCategories" on the service with a new "Category" object with Name: "Auth Test Category"
12
13
  And I save changes
13
14
  And I call "Categories" on the service with args: "1"
@@ -15,7 +16,6 @@ Scenario: Entity should fill values on protected resource
15
16
  Then the method "Id" on the first result should equal: "1"
16
17
  And the method "Name" on the first result should equal: "Auth Test Category"
17
18
 
18
- Scenario: Should get SSL failure if SSL used with self-signed certificate and not passing "false" as :verify_ssl option
19
- Given a HTTPS BasicAuth ODataService exists it should throw an exception with message containing "SSL Verification failed"
20
-
21
-
19
+ # TODO: Commented this scenario out because it requires the server to be online in order for the tests to run. Would like to move this to a mocked test that would accomplish the same thing...
20
+ # Scenario: Should get SSL failure if SSL used with self-signed certificate and not passing "false" as :verify_ssl option
21
+ # Given a HTTPS BasicAuth ODataService exists it should throw an exception with message containing "SSL Verification failed"
@@ -2,20 +2,22 @@ STANDARD_URL = "http://#{WEBSERVER}:#{HTTP_PORT_NUMBER}/SampleService/RubyOData.
2
2
  BASICAUTH_URL = "http://#{WEBSERVER}:#{HTTP_PORT_NUMBER}/SampleService/BasicAuth/RubyOData.svc"
3
3
  HTTPS_BASICAUTH_URL = "https://#{WEBSERVER}:#{HTTPS_PORT_NUMBER}/SampleService/BasicAuth/RubyOData.svc"
4
4
 
5
- When /^(.*) first (last query )?result('s)?(.*)$/ do |pre, last_query, apos, post|
6
- step = "#{pre} #{last_query}result#{apos}#{post}"
5
+ When /^(.*) first (last query )?result(\'s)?(.*)$/ do |pre, last_query, apos, post|
6
+ the_step = "#{pre} #{last_query}result#{apos}#{post}"
7
7
  first_result
8
- When step
8
+ step the_step
9
9
  end
10
10
 
11
11
  When /^(.*) first (last )?save result(.*)$/ do |pre, last, post|
12
- step = "#{pre} #{last}save result#{post}"
12
+ the_step = "#{pre} #{last}save result#{post}"
13
13
  first_save
14
- When step
14
+ step the_step
15
15
  end
16
16
 
17
17
  Given /^a HTTP ODataService exists$/ do
18
- @service = OData::Service.new(STANDARD_URL)
18
+ VCR.use_cassette("unsecured_metadata") do
19
+ @service = OData::Service.new(STANDARD_URL)
20
+ end
19
21
  end
20
22
 
21
23
  Given /^a HTTP BasicAuth ODataService exists$/ do
@@ -30,11 +32,11 @@ Given /^a HTTP BasicAuth ODataService exists using username "([^\"]*)" and passw
30
32
  @service = OData::Service.new(BASICAUTH_URL, { :username => username, :password => password })
31
33
  end
32
34
 
33
- Given /^a HTTP BasicAuth ODataService exists using username "([^\"]*)" and password "([^\"]*)" it should throw an exception with message "([^\"]*)"$/ do |username, password, msg|
35
+ Given /^a HTTP BasicAuth ODataService exists using username "([^\"]*)" and password "([^\"]*)" it should throw an exception with message "([^\"]*)"$/ do |username, password, msg|
34
36
  lambda { @service = OData::Service.new(BASICAUTH_URL, { :username => username, :password => password }) }.should raise_error(msg)
35
37
  end
36
38
 
37
- Given /^a HTTP BasicAuth ODataService exists it should throw an exception with message containing "([^\"]*)"$/ do |msg|
39
+ Given /^a HTTP BasicAuth ODataService exists it should throw an exception with message containing "([^\"]*)"$/ do |msg|
38
40
  lambda { @service = OData::Service.new(BASICAUTH_URL) }.should raise_error(/#{msg}.*/)
39
41
  end
40
42
 
@@ -42,7 +44,7 @@ Given /^a HTTPS BasicAuth ODataService exists it should throw an exception with
42
44
  lambda { @service = OData::Service.new(HTTPS_BASICAUTH_URL) }.should raise_error(/#{msg}.*/)
43
45
  end
44
46
 
45
- Given /^a HTTP BasicAuth ODataService exists it should throw an exception with message "([^\"]*)"$/ do |msg|
47
+ Given /^a HTTP BasicAuth ODataService exists it should throw an exception with message "([^\"]*)"$/ do |msg|
46
48
  lambda { @service = OData::Service.new(BASICAUTH_URL) }.should raise_error(msg)
47
49
  end
48
50
 
@@ -55,7 +57,7 @@ When /^I call "([^\"]*)" on the service$/ do |method|
55
57
  end
56
58
 
57
59
  Then /^the result should be "([^\"]*)"$/ do |result|
58
- @service_result.should eq result
60
+ @service_result.should eq result
59
61
  end
60
62
 
61
63
  Then /^the integer result should be ([^\"]*)$/ do |result|
@@ -122,18 +124,22 @@ When /^I ask for the top (\d+)$/ do |top|
122
124
  @service_query.top(top)
123
125
  end
124
126
 
127
+ When /^I ask for the count$/ do
128
+ @service_query.count
129
+ end
130
+
125
131
  When /^I ask for the links for "([^\"]*)"$/ do |nav_prop|
126
132
  @service_query.links(nav_prop)
127
133
  end
128
134
 
129
135
  Then /^the method "([^\"]*)" on the result should be of type "([^\"]*)"$/ do |method, type|
130
- result = @service_result.send(method.to_sym)
136
+ result = @service_result.send(method.to_sym)
131
137
  result.class.to_s.should eq type
132
138
  end
133
139
 
134
140
  Given /^I call "([^\"]*)" on the service with a new "([^\"]*)" object(?: with (.*))?$/ do |method, object, fields|
135
141
  fields_hash = parse_fields_string(fields)
136
-
142
+
137
143
  obj = object.constantize.send(:make, fields_hash)
138
144
  @service.send(method.to_sym, obj)
139
145
  end
@@ -172,6 +178,10 @@ Given /^I call "([^\"]*)" on the service with a new "([^\"]*)" object it should
172
178
  lambda { @service.send(method.to_sym, obj) }.should raise_error(msg)
173
179
  end
174
180
 
181
+ When /^I save changes it should throw an exception with message containing "([^"]*)"$/ do |msg|
182
+ lambda { @service.save_changes }.should raise_error(/#{msg}.*/)
183
+ end
184
+
175
185
  Then /^no "([^\"]*)" should exist$/ do |collection|
176
186
  @service.send(collection)
177
187
  results = @service.execute
@@ -180,19 +190,19 @@ end
180
190
 
181
191
  Then /^the primitive results should be:$/ do |table|
182
192
  # table is a Cucumber::Ast::Table
183
- values = table.hashes
193
+ values = table.hashes
184
194
  result_table = Cucumber::Ast::Table.new(values)
185
195
  table.diff!(result_table)
186
196
  end
187
197
 
188
198
  Then /^the result should be:$/ do |table|
189
199
  # table is a Cucumber::Ast::Table
190
-
200
+
191
201
  fields = table.hashes[0].keys
192
-
202
+
193
203
  # Build an array of hashes so that we can compare tables
194
204
  results = []
195
-
205
+
196
206
  @service_result.each do |result|
197
207
  obj_hash = Hash.new
198
208
  fields.each do |field|
@@ -200,20 +210,20 @@ Then /^the result should be:$/ do |table|
200
210
  end
201
211
  results << obj_hash
202
212
  end
203
-
213
+
204
214
  result_table = Cucumber::Ast::Table.new(results)
205
-
215
+
206
216
  table.diff!(result_table)
207
217
  end
208
218
 
209
219
  Then /^the save result should be:$/ do |table|
210
220
  # table is a Cucumber::Ast::Table
211
-
221
+
212
222
  fields = table.hashes[0].keys
213
-
223
+
214
224
  # Build an array of hashes so that we can compare tables
215
225
  results = []
216
-
226
+
217
227
  @saved_result.each do |result|
218
228
  obj_hash = Hash.new
219
229
  fields.each do |field|
@@ -221,10 +231,10 @@ Then /^the save result should be:$/ do |table|
221
231
  end
222
232
  results << obj_hash
223
233
  end
224
-
234
+
225
235
  result_table = Cucumber::Ast::Table.new(results)
226
-
227
- table.diff!(result_table)
236
+
237
+ table.diff!(result_table)
228
238
  end
229
239
 
230
240
  Then /^a class named "([^\"]*)" should exist$/ do |klass_name|
@@ -299,4 +309,8 @@ Given /^I call the service method "([^"]*)"(?: with (.*))?$/ do |method, args|
299
309
  else
300
310
  @service_result = @service.send(method)
301
311
  end
312
+ end
313
+
314
+ When /^(.*) within a cassette named "([^"]*)"$/ do |the_step, cassette_name|
315
+ VCR.use_cassette(cassette_name) { step the_step }
302
316
  end
@@ -1,6 +1,4 @@
1
1
  lib = File.expand_path(File.join(File.dirname(__FILE__), "../..", "lib"))
2
2
 
3
3
  require lib + '/ruby_odata'
4
- require 'machinist/object'
5
- require 'sham'
6
- require 'faker'
4
+ require "machinist"
@@ -1,4 +1,5 @@
1
1
  Before do
2
- Sham.reset
3
- RestClient.post "http://#{WEBSERVER}:#{HTTP_PORT_NUMBER}/SampleService/RubyOData.svc/CleanDatabaseForTesting", {}
2
+ VCR.use_cassette("clean_database_for_testing") do
3
+ RestClient.post "http://#{WEBSERVER}:#{HTTP_PORT_NUMBER}/SampleService/RubyOData.svc/CleanDatabaseForTesting", {}
4
+ end
4
5
  end