ruby_odata 0.1.0 → 0.1.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.
- data/.gitignore +3 -2
- data/.travis.yml +2 -1
- data/.yardopts +6 -0
- data/CHANGELOG.md +102 -0
- data/Guardfile +14 -0
- data/README.md +285 -0
- data/Rakefile +0 -7
- data/features/basic_auth.feature +3 -2
- data/features/batch_request.feature +7 -6
- data/features/cassettes/basic_auth_protected_resource.yml +57 -0
- data/features/cassettes/batch_request_additions.yml +69 -0
- data/features/cassettes/batch_request_deletes.yml +69 -0
- data/features/cassettes/batch_request_updates.yml +69 -0
- data/features/cassettes/clean_database_for_testing.yml +46 -0
- data/features/cassettes/cucumber_tags/basic_auth.yml +297 -0
- data/features/cassettes/cucumber_tags/batch_request.yml +1459 -0
- data/features/cassettes/cucumber_tags/complex_types.yml +326 -0
- data/features/cassettes/cucumber_tags/error_handling.yml +64 -0
- data/features/cassettes/cucumber_tags/query_builder.yml +2025 -0
- data/features/cassettes/cucumber_tags/service.yml +234 -0
- data/features/cassettes/cucumber_tags/service_manage.yml +937 -0
- data/features/cassettes/cucumber_tags/service_methods.yml +647 -0
- data/features/cassettes/cucumber_tags/ssl.yml +203 -0
- data/features/cassettes/cucumber_tags/type_conversion.yml +337 -0
- data/features/cassettes/service_manage_additions.yml +65 -0
- data/features/cassettes/service_manage_deletions.yml +58 -0
- data/features/cassettes/service_manage_deletions_2.yml +58 -0
- data/features/cassettes/unsecured_metadata.yml +89 -0
- data/features/complex_types.feature +4 -3
- data/features/error_handling.feature +14 -0
- data/features/query_builder.feature +30 -9
- data/features/service.feature +4 -3
- data/features/service_manage.feature +6 -5
- data/features/service_methods.feature +3 -2
- data/features/ssl.feature +8 -8
- data/features/step_definitions/service_steps.rb +38 -24
- data/features/support/env.rb +1 -3
- data/features/support/hooks.rb +3 -2
- data/features/support/pickle.rb +29 -18
- data/features/support/vcr.rb +24 -0
- data/features/type_conversion.feature +16 -17
- data/lib/ruby_odata/association.rb +7 -6
- data/lib/ruby_odata/class_builder.rb +6 -7
- data/lib/ruby_odata/exceptions.rb +4 -0
- data/lib/ruby_odata/helpers.rb +11 -0
- data/lib/ruby_odata/operation.rb +5 -6
- data/lib/ruby_odata/property_metadata.rb +4 -5
- data/lib/ruby_odata/query_builder.rb +98 -63
- data/lib/ruby_odata/service.rb +118 -103
- data/lib/ruby_odata/version.rb +3 -1
- data/lib/ruby_odata.rb +20 -18
- data/ruby_odata.gemspec +16 -12
- data/spec/query_builder_spec.rb +78 -14
- data/spec/service_spec.rb +83 -83
- data/spec/support/sample_service_matcher.rb +15 -0
- data/test/RubyODataService/RubyODataService/App_Data/.gitkeep +0 -0
- data/test/blueprints.rb +15 -9
- data/test/usage_samples/querying.rb +5 -1
- data/test/usage_samples/sample_data.rb +1 -3
- metadata +213 -39
- data/CHANGELOG.rdoc +0 -88
- 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
|
+
|
data/features/service.feature
CHANGED
@@ -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
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
8
|
+
step the_step
|
9
9
|
end
|
10
10
|
|
11
11
|
When /^(.*) first (last )?save result(.*)$/ do |pre, last, post|
|
12
|
-
|
12
|
+
the_step = "#{pre} #{last}save result#{post}"
|
13
13
|
first_save
|
14
|
-
|
14
|
+
step the_step
|
15
15
|
end
|
16
16
|
|
17
17
|
Given /^a HTTP ODataService exists$/ do
|
18
|
-
|
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
|
data/features/support/env.rb
CHANGED
data/features/support/hooks.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
Before do
|
2
|
-
|
3
|
-
|
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
|