ruby_odata 0.1.0 → 0.1.6
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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +7 -2
- data/.simplecov +10 -0
- data/.travis.yml +10 -4
- data/.yardopts +6 -0
- data/CHANGELOG.md +157 -0
- data/Guardfile +14 -0
- data/LICENSE +20 -22
- data/README.md +289 -0
- data/Rakefile +19 -9
- 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 +13 -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 +32 -74
- data/features/support/env.rb +6 -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/gemfiles/Gemfile.ruby187 +6 -0
- data/lib/ruby_odata.rb +20 -18
- data/lib/ruby_odata/association.rb +7 -6
- data/lib/ruby_odata/class_builder.rb +31 -14
- data/lib/ruby_odata/exceptions.rb +11 -0
- data/lib/ruby_odata/helpers.rb +17 -0
- data/lib/ruby_odata/operation.rb +5 -6
- data/lib/ruby_odata/property_metadata.rb +9 -7
- data/lib/ruby_odata/query_builder.rb +127 -63
- data/lib/ruby_odata/service.rb +265 -147
- data/lib/ruby_odata/version.rb +3 -1
- data/ruby_odata.gemspec +22 -13
- data/spec/fixtures/error_without_message.xml +5 -0
- data/spec/fixtures/int64_ids/edmx_boat_service.xml +19 -0
- data/spec/fixtures/int64_ids/edmx_car_service.xml +21 -0
- data/spec/fixtures/int64_ids/result_boats.xml +26 -0
- data/spec/fixtures/int64_ids/result_cars.xml +28 -0
- data/spec/fixtures/ms_system_center/edmx_ms_system_center.xml +1645 -0
- data/spec/fixtures/ms_system_center/edmx_ms_system_center_v2.xml +2120 -0
- data/spec/fixtures/ms_system_center/hardware_profiles.xml +61 -0
- data/spec/fixtures/ms_system_center/virtual_machines.xml +175 -0
- data/spec/fixtures/ms_system_center/vm_templates.xml +1193 -0
- data/spec/fixtures/nested_expands/edmx_northwind.xml +557 -0
- data/spec/fixtures/nested_expands/northwind_products_category_expands.xml +774 -0
- data/spec/fixtures/sample_service/result_select_categories_expand.xml +268 -0
- data/spec/fixtures/sample_service/result_select_categories_no_property.xml +6 -0
- data/spec/fixtures/sample_service/result_select_categories_travsing_no_expand.xml +6 -0
- data/spec/fixtures/sample_service/result_select_products_name_price.xml +92 -0
- data/spec/property_metadata_spec.rb +10 -10
- data/spec/query_builder_spec.rb +153 -14
- data/spec/revised_service_spec.rb +111 -6
- data/spec/service_spec.rb +389 -85
- data/spec/spec_helper.rb +3 -0
- 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 +276 -76
- data/CHANGELOG.rdoc +0 -88
- data/README.rdoc +0 -259
| @@ -10,7 +10,7 @@ module OData | |
| 10 10 | 
             
                  @cat_prod_service = OData::Service.new "http://test.com/test.svc"
         | 
| 11 11 | 
             
                end
         | 
| 12 12 | 
             
                subject { @cat_prod_service }
         | 
| 13 | 
            -
             | 
| 13 | 
            +
             | 
| 14 14 | 
             
                context "methods" do
         | 
| 15 15 | 
             
                  it { should respond_to :update_object }
         | 
| 16 16 | 
             
                  it { should respond_to :delete_object }
         | 
| @@ -25,7 +25,7 @@ module OData | |
| 25 25 | 
             
                  it { should respond_to :collections }
         | 
| 26 26 | 
             
                  it { should respond_to :options }
         | 
| 27 27 | 
             
                  it { should respond_to :function_imports }
         | 
| 28 | 
            -
             | 
| 28 | 
            +
             | 
| 29 29 | 
             
                  context "after parsing metadata" do
         | 
| 30 30 | 
             
                    it { should respond_to :Products }
         | 
| 31 31 | 
             
                    it { should respond_to :Categories }
         | 
| @@ -43,7 +43,7 @@ module OData | |
| 43 43 | 
             
                  end
         | 
| 44 44 | 
             
                  it "should expose the local model type" do
         | 
| 45 45 | 
             
                    subject['Products'][:type].should eq Product
         | 
| 46 | 
            -
                    subject['Categories'][:type].should eq Category | 
| 46 | 
            +
                    subject['Categories'][:type].should eq Category
         | 
| 47 47 | 
             
                  end
         | 
| 48 48 | 
             
                end
         | 
| 49 49 | 
             
                context "class metadata" do
         | 
| @@ -51,6 +51,7 @@ module OData | |
| 51 51 | 
             
                  it { should_not be_empty}
         | 
| 52 52 | 
             
                  it { should have_key 'Product' }
         | 
| 53 53 | 
             
                  it { should have_key 'Category' }
         | 
| 54 | 
            +
             | 
| 54 55 | 
             
                  context "should have keys for each property" do
         | 
| 55 56 | 
             
                    subject { @cat_prod_service.class_metadata['Category'] }
         | 
| 56 57 | 
             
                    it { should have_key 'Id' }
         | 
| @@ -69,6 +70,7 @@ module OData | |
| 69 70 | 
             
                      meta.fc_target_path.should be_nil
         | 
| 70 71 | 
             
                      meta.fc_keep_in_content.should be_nil
         | 
| 71 72 | 
             
                      meta.nav_prop.should eq false
         | 
| 73 | 
            +
                      meta.is_key.should eq true
         | 
| 72 74 | 
             
                    end
         | 
| 73 75 | 
             
                    it "should have correct PropertyMetadata for Category.Name" do
         | 
| 74 76 | 
             
                      meta = subject['Name']
         | 
| @@ -78,6 +80,7 @@ module OData | |
| 78 80 | 
             
                      meta.fc_target_path.should be_nil
         | 
| 79 81 | 
             
                      meta.fc_keep_in_content.should be_nil
         | 
| 80 82 | 
             
                      meta.nav_prop.should eq false
         | 
| 83 | 
            +
                      meta.is_key.should eq false
         | 
| 81 84 | 
             
                    end
         | 
| 82 85 | 
             
                    it "should have correct PropertyMetadata for Category.Products" do
         | 
| 83 86 | 
             
                      meta = subject['Products']
         | 
| @@ -88,6 +91,7 @@ module OData | |
| 88 91 | 
             
                      meta.fc_keep_in_content.should be_nil
         | 
| 89 92 | 
             
                      meta.nav_prop.should eq true
         | 
| 90 93 | 
             
                      meta.association.should_not be_nil
         | 
| 94 | 
            +
                      meta.is_key.should eq false
         | 
| 91 95 | 
             
                    end
         | 
| 92 96 | 
             
                  end
         | 
| 93 97 | 
             
                end
         | 
| @@ -115,7 +119,7 @@ module OData | |
| 115 119 | 
             
                    subject['EntityCategoryWebGet'][:parameters].should be_nil
         | 
| 116 120 | 
             
                    subject['EntitySingleCategoryWebGet'][:parameters].should be_a Hash
         | 
| 117 121 | 
             
                    subject['EntitySingleCategoryWebGet'][:parameters]['id'].should eq 'Edm.Int32'
         | 
| 118 | 
            -
                  end | 
| 122 | 
            +
                  end
         | 
| 119 123 | 
             
                  context "after parsing function imports" do
         | 
| 120 124 | 
             
                    subject { @cat_prod_service }
         | 
| 121 125 | 
             
                    it { should respond_to :CleanDatabaseForTesting }
         | 
| @@ -152,10 +156,10 @@ module OData | |
| 152 156 | 
             
                    subject { @cat_prod_service }
         | 
| 153 157 | 
             
                    before(:each) do
         | 
| 154 158 | 
             
                      stub_request(:post, "http://test.com/test.svc/CleanDatabaseForTesting").to_return(:status => 204)
         | 
| 155 | 
            -
             | 
| 159 | 
            +
             | 
| 156 160 | 
             
                      stub_request(:get, "http://test.com/test.svc/EntityCategoryWebGet").
         | 
| 157 161 | 
             
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_entity_category_web_get.xml", __FILE__)), :headers => {})
         | 
| 158 | 
            -
             | 
| 162 | 
            +
             | 
| 159 163 | 
             
                      stub_request(:get, "http://test.com/test.svc/EntitySingleCategoryWebGet?id=1").
         | 
| 160 164 | 
             
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_entity_single_category_web_get.xml", __FILE__)), :headers => {})
         | 
| 161 165 |  | 
| @@ -194,4 +198,105 @@ module OData | |
| 194 198 | 
             
                  end
         | 
| 195 199 | 
             
                end
         | 
| 196 200 | 
             
              end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
              describe "Keys" do
         | 
| 203 | 
            +
                describe "Collection with an int64 key Named 'id'" do
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                  before(:all) do
         | 
| 206 | 
            +
                    stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 207 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 208 | 
            +
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/int64_ids/edmx_car_service.xml", __FILE__)), :headers => {})
         | 
| 209 | 
            +
                    @svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 210 | 
            +
                  end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                  context "has the correct metadata" do
         | 
| 213 | 
            +
                    before(:all) do
         | 
| 214 | 
            +
                      @id_meta = @svc.class_metadata['Car']['id']
         | 
| 215 | 
            +
                    end
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                    subject { @id_meta }
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                    its(:name)                { should eq('id') }
         | 
| 220 | 
            +
                    its(:type)                { should eq('Edm.Int64') }
         | 
| 221 | 
            +
                    its(:nullable)            { should be_false }
         | 
| 222 | 
            +
                    its(:fc_target_path)      { should be_nil }
         | 
| 223 | 
            +
                    its(:fc_keep_in_content)  { should be_nil }
         | 
| 224 | 
            +
                  end
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                  context "can parse Id correctly" do
         | 
| 227 | 
            +
                    before(:each) do
         | 
| 228 | 
            +
                      stub_request(:get, "http://test.com/test.svc/Cars(213L)").
         | 
| 229 | 
            +
                        with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 230 | 
            +
                        to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/int64_ids/result_cars.xml", __FILE__)), :headers => {})
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                      @svc.Cars(213)
         | 
| 233 | 
            +
                      results = @svc.execute
         | 
| 234 | 
            +
                      @car = results.first
         | 
| 235 | 
            +
                    end
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                    subject { @car }
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                    its(:id)      { should eq(213) }
         | 
| 240 | 
            +
                    its(:color)   { should eq('peach') }
         | 
| 241 | 
            +
                  end
         | 
| 242 | 
            +
                end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                describe "Collection with an int64 key named 'KeyId'" do
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                  before(:all) do
         | 
| 247 | 
            +
                    stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 248 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 249 | 
            +
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/int64_ids/edmx_boat_service.xml", __FILE__)), :headers => {})
         | 
| 250 | 
            +
                    @svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 251 | 
            +
                  end
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                  context "has the correct metadata" do
         | 
| 254 | 
            +
                    before(:all) do
         | 
| 255 | 
            +
                      @id_meta = @svc.class_metadata['Boat']['KeyId']
         | 
| 256 | 
            +
                    end
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                    subject { @id_meta }
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                    its(:name)                { should eq('KeyId') }
         | 
| 261 | 
            +
                    its(:type)                { should eq('Edm.Int64') }
         | 
| 262 | 
            +
                    its(:nullable)            { should be_false }
         | 
| 263 | 
            +
                    its(:fc_target_path)      { should be_nil }
         | 
| 264 | 
            +
                    its(:fc_keep_in_content)  { should be_nil }
         | 
| 265 | 
            +
                  end
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                  context "can parse Id correctly" do
         | 
| 268 | 
            +
                    before(:each) do
         | 
| 269 | 
            +
                      stub_request(:get, "http://test.com/test.svc/Boats(213L)").
         | 
| 270 | 
            +
                        with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 271 | 
            +
                        to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/int64_ids/result_boats.xml", __FILE__)), :headers => {})
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                      @svc.Boats(213)
         | 
| 274 | 
            +
                      results = @svc.execute
         | 
| 275 | 
            +
                      @boat = results.first
         | 
| 276 | 
            +
                    end
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                    subject { @boat }
         | 
| 279 | 
            +
             | 
| 280 | 
            +
                    its(:id)      { should eq(213) }
         | 
| 281 | 
            +
                    its(:color)   { should eq('blue') }
         | 
| 282 | 
            +
                  end
         | 
| 283 | 
            +
                end
         | 
| 284 | 
            +
              end
         | 
| 285 | 
            +
             | 
| 286 | 
            +
              describe "Dual Namespaces" do
         | 
| 287 | 
            +
                before(:all) do
         | 
| 288 | 
            +
                  stub_request(:get, "http://xxxx%5Cyyyy:zzzz@test.com/test.svc/$metadata").
         | 
| 289 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 290 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/ms_system_center/edmx_ms_system_center_v2.xml", __FILE__)), :headers => {})
         | 
| 291 | 
            +
                end
         | 
| 292 | 
            +
                after(:all) do
         | 
| 293 | 
            +
                  VMM.constants.each do |constant|
         | 
| 294 | 
            +
                    VMM.send :remove_const, constant
         | 
| 295 | 
            +
                  end
         | 
| 296 | 
            +
                end
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                it "should parse the service without errors" do
         | 
| 299 | 
            +
                  lambda { OData::Service.new "http://test.com/test.svc/", { :username => "xxxx\\yyyy", :password=> "zzzz", :verify_ssl => false, :namespace => "VMM" } }.should_not raise_error
         | 
| 300 | 
            +
                end
         | 
| 301 | 
            +
              end
         | 
| 197 302 | 
             
            end
         | 
    
        data/spec/service_spec.rb
    CHANGED
    
    | @@ -3,12 +3,12 @@ require 'spec_helper' | |
| 3 3 | 
             
            module OData
         | 
| 4 4 | 
             
              describe Service do
         | 
| 5 5 | 
             
                describe "#initialize" do
         | 
| 6 | 
            -
                  it "truncates passed in end slash from uri when making the request" do | 
| 6 | 
            +
                  it "truncates passed in end slash from uri when making the request" do
         | 
| 7 7 | 
             
                    # Required for the build_classes method
         | 
| 8 8 | 
             
                    stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 9 9 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 10 10 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/edmx_empty.xml", __FILE__)), :headers => {})
         | 
| 11 | 
            -
             | 
| 11 | 
            +
             | 
| 12 12 | 
             
                    svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 13 13 | 
             
                  end
         | 
| 14 14 | 
             
                  it "doesn't error with lowercase entities" do
         | 
| @@ -16,10 +16,10 @@ module OData | |
| 16 16 | 
             
                    stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 17 17 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 18 18 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/edmx_lowercase.xml", __FILE__)), :headers => {})
         | 
| 19 | 
            -
             | 
| 19 | 
            +
             | 
| 20 20 | 
             
                    lambda { OData::Service.new "http://test.com/test.svc" }.should_not raise_error
         | 
| 21 21 | 
             
                  end
         | 
| 22 | 
            -
             | 
| 22 | 
            +
             | 
| 23 23 | 
             
                  describe "additional query string parameters" do
         | 
| 24 24 | 
             
                    before(:each) do
         | 
| 25 25 | 
             
                      # Required for the build_classes method
         | 
| @@ -36,6 +36,23 @@ module OData | |
| 36 36 | 
             
                      a_request(:get, "http://test.com/test.svc/$metadata?x=1&y=2").should have_been_made
         | 
| 37 37 | 
             
                    end
         | 
| 38 38 | 
             
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  describe "rest-client options" do
         | 
| 41 | 
            +
                    before(:each) do
         | 
| 42 | 
            +
                      # Required for the build_classes method
         | 
| 43 | 
            +
                      stub_request(:get, /http:\/\/test\.com\/test\.svc\/\$metadata(?:\?.+)?/).
         | 
| 44 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 45 | 
            +
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/edmx_empty.xml", __FILE__)), :headers => {})
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                    it "should accept in options that will be passed to the rest-client lib" do
         | 
| 48 | 
            +
                      svc = OData::Service.new "http://test.com/test.svc/", { :rest_options => { :ssl_ca_file => "ca_certificate.pem" } }
         | 
| 49 | 
            +
                      svc.options[:rest_options].should eq Hash[:ssl_ca_file => "ca_certificate.pem"]
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                    it "should merge the rest options with the built in options" do
         | 
| 52 | 
            +
                      svc = OData::Service.new "http://test.com/test.svc/", { :rest_options => { :ssl_ca_file => "ca_certificate.pem" } }
         | 
| 53 | 
            +
                      svc.instance_variable_get(:@rest_options).should eq Hash[:verify_ssl => 1, :user => nil, :password => nil, :ssl_ca_file => "ca_certificate.pem"]
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                  end
         | 
| 39 56 | 
             
                end
         | 
| 40 57 | 
             
                describe "additional query string parameters" do
         | 
| 41 58 | 
             
                  before(:each) do
         | 
| @@ -52,7 +69,7 @@ module OData | |
| 52 69 | 
             
                  end
         | 
| 53 70 | 
             
                  it "should pass the parameters as part of a save" do
         | 
| 54 71 | 
             
                    svc = OData::Service.new "http://test.com/test.svc/", { :additional_params => { :x=>1, :y=>2 } }
         | 
| 55 | 
            -
                    new_flight = ZDemoFlight.new | 
| 72 | 
            +
                    new_flight = ZDemoFlight.new
         | 
| 56 73 | 
             
                    svc.AddToflight_dataCollection(new_flight)
         | 
| 57 74 | 
             
                    svc.save_changes
         | 
| 58 75 | 
             
                    a_request(:post, "http://test.com/test.svc/flight_dataCollection?x=1&y=2").should have_been_made
         | 
| @@ -75,9 +92,9 @@ module OData | |
| 75 92 | 
             
                  end
         | 
| 76 93 | 
             
                  it "should pass the parameters as part of a batch save" do
         | 
| 77 94 | 
             
                    svc = OData::Service.new "http://test.com/test.svc/", { :additional_params => { :x=>1, :y=>2 } }
         | 
| 78 | 
            -
                    new_flight = ZDemoFlight.new | 
| 95 | 
            +
                    new_flight = ZDemoFlight.new
         | 
| 79 96 | 
             
                    svc.AddToflight_dataCollection(new_flight)
         | 
| 80 | 
            -
                    new_flight2 = ZDemoFlight.new | 
| 97 | 
            +
                    new_flight2 = ZDemoFlight.new
         | 
| 81 98 | 
             
                    svc.AddToflight_dataCollection(new_flight2)
         | 
| 82 99 | 
             
                    svc.save_changes
         | 
| 83 100 | 
             
                    a_request(:post, "http://test.com/test.svc/$batch?x=1&y=2").should have_been_made
         | 
| @@ -103,7 +120,28 @@ module OData | |
| 103 120 | 
             
                    a_request(:get, "http://test.com/test.svc/get_top_flight?x=1&y=2").should have_been_made
         | 
| 104 121 | 
             
                  end
         | 
| 105 122 | 
             
                end
         | 
| 106 | 
            -
             | 
| 123 | 
            +
             | 
| 124 | 
            +
                describe "exception handling" do
         | 
| 125 | 
            +
                  before(:each) do
         | 
| 126 | 
            +
                    stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 127 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 128 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/edmx_categories_products.xml", __FILE__)), :headers => {})
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                    stub_request(:get, "http://test.com/test.svc/Categories?$select=Price").
         | 
| 131 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 132 | 
            +
                    to_return(:status => 400, :body => File.new(File.expand_path("../fixtures/error_without_message.xml", __FILE__)), :headers => {})
         | 
| 133 | 
            +
                  end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                  it "includes a generic message if the error is not in the response" do
         | 
| 136 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 137 | 
            +
                    svc.Categories.select "Price"
         | 
| 138 | 
            +
                    expect { svc.execute }.to raise_error(OData::ServiceError) { |error|
         | 
| 139 | 
            +
                      error.http_code.should eq 400
         | 
| 140 | 
            +
                      error.message.should eq "Server returned error but no message."
         | 
| 141 | 
            +
                    }
         | 
| 142 | 
            +
                  end
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 107 145 | 
             
                describe "lowercase collections" do
         | 
| 108 146 | 
             
                  before(:each) do
         | 
| 109 147 | 
             
                    # Required for the build_classes method
         | 
| @@ -111,12 +149,12 @@ module OData | |
| 111 149 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 112 150 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/edmx_lowercase.xml", __FILE__)), :headers => {})
         | 
| 113 151 | 
             
                  end
         | 
| 114 | 
            -
             | 
| 152 | 
            +
             | 
| 115 153 | 
             
                  it "should respond_to a lowercase collection" do
         | 
| 116 154 | 
             
                    svc = OData::Service.new "http://test.com/test.svc"
         | 
| 117 155 | 
             
                    svc.respond_to?('acronyms').should be_true
         | 
| 118 156 | 
             
                  end
         | 
| 119 | 
            -
             | 
| 157 | 
            +
             | 
| 120 158 | 
             
                  it "should allow a lowercase collections to be queried" do
         | 
| 121 159 | 
             
                    svc = OData::Service.new "http://test.com/test.svc"
         | 
| 122 160 | 
             
                    lambda { svc.send('acronyms') }.should_not raise_error
         | 
| @@ -142,19 +180,19 @@ module OData | |
| 142 180 | 
             
                    results.first.should be_a_kind_of(ZDemoFlight)
         | 
| 143 181 | 
             
                  end
         | 
| 144 182 | 
             
                end
         | 
| 145 | 
            -
             | 
| 183 | 
            +
             | 
| 146 184 | 
             
                describe "collections, objects, metadata etc" do
         | 
| 147 185 | 
             
                  before(:each) do
         | 
| 148 186 | 
             
                    # Metadata
         | 
| 149 187 | 
             
                    stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 150 188 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 151 189 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/feed_customization/edmx_feed_customization.xml", __FILE__)), :headers => {})
         | 
| 152 | 
            -
             | 
| 190 | 
            +
             | 
| 153 191 | 
             
                    # Content - Products
         | 
| 154 192 | 
             
                    stub_request(:get, /http:\/\/test\.com\/test\.svc\/Products(?:.*)/).
         | 
| 155 193 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 156 194 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/feed_customization/result_feed_customization_products_expand.xml", __FILE__)), :headers => {})
         | 
| 157 | 
            -
             | 
| 195 | 
            +
             | 
| 158 196 | 
             
                    # Content - Categories expanded Products
         | 
| 159 197 | 
             
                    stub_request(:get, /http:\/\/test\.com\/test\.svc\/Categories(?:.*)/).
         | 
| 160 198 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| @@ -208,9 +246,9 @@ module OData | |
| 208 246 | 
             
                        meta.nullable.should eq true
         | 
| 209 247 | 
             
                        meta.fc_target_path.should eq "SyndicationSummary"
         | 
| 210 248 | 
             
                        meta.fc_keep_in_content.should eq false
         | 
| 211 | 
            -
                      end | 
| 212 | 
            -
                    end | 
| 213 | 
            -
             | 
| 249 | 
            +
                      end
         | 
| 250 | 
            +
                    end
         | 
| 251 | 
            +
             | 
| 214 252 | 
             
                    describe "single class" do
         | 
| 215 253 | 
             
                      it "should handle properties where a property is represented in the syndication title instead of the properties collection" do
         | 
| 216 254 | 
             
                        svc = OData::Service.new "http://test.com/test.svc/"
         | 
| @@ -224,46 +262,46 @@ module OData | |
| 224 262 | 
             
                        results = svc.execute
         | 
| 225 263 | 
             
                        results.first.Description.should eq "Whole grain bread"
         | 
| 226 264 | 
             
                      end
         | 
| 227 | 
            -
                    end | 
| 228 | 
            -
             | 
| 265 | 
            +
                    end
         | 
| 266 | 
            +
             | 
| 229 267 | 
             
                    describe "expanded inline class" do
         | 
| 230 268 | 
             
                      it "should handle properties where a property is represented in the syndication title instead of the properties collection" do
         | 
| 231 269 | 
             
                        svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 232 270 | 
             
                        svc.Categories
         | 
| 233 271 | 
             
                        results = svc.execute
         | 
| 234 | 
            -
             | 
| 272 | 
            +
             | 
| 235 273 | 
             
                        beverages = results[1]
         | 
| 236 | 
            -
             | 
| 274 | 
            +
             | 
| 237 275 | 
             
                        milk = beverages.Products.first
         | 
| 238 276 | 
             
                        milk.Name.should eq "Milk"
         | 
| 239 277 | 
             
                        milk.Description.should eq "Low fat milk"
         | 
| 240 | 
            -
             | 
| 278 | 
            +
             | 
| 241 279 | 
             
                        lemonade = beverages.Products.last
         | 
| 242 280 | 
             
                        lemonade.Name.should eq "Pink Lemonade"
         | 
| 243 281 | 
             
                        lemonade.Description.should eq "36 Ounce Cans (Pack of 3)"
         | 
| 244 282 | 
             
                      end
         | 
| 245 283 | 
             
                    end
         | 
| 246 284 | 
             
                  end
         | 
| 247 | 
            -
             | 
| 285 | 
            +
             | 
| 248 286 | 
             
                  describe "handling inline collections/properties" do
         | 
| 249 287 | 
             
                    it "should make plural named properties arrays and not a single class" do
         | 
| 250 288 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 251 289 | 
             
                      svc.Categories
         | 
| 252 290 | 
             
                      results = svc.execute
         | 
| 253 291 | 
             
                      food = results[0]
         | 
| 254 | 
            -
             | 
| 292 | 
            +
             | 
| 255 293 | 
             
                      food.Products.should be_an Array
         | 
| 256 294 | 
             
                    end
         | 
| 257 | 
            -
             | 
| 295 | 
            +
             | 
| 258 296 | 
             
                    it "should not make an array if the navigation property name is singular" do
         | 
| 259 297 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 260 298 | 
             
                      svc.Products
         | 
| 261 299 | 
             
                      results = svc.execute
         | 
| 262 300 | 
             
                      product = results.first
         | 
| 263 301 | 
             
                      product.Category.should_not be_an Array
         | 
| 264 | 
            -
                    end | 
| 302 | 
            +
                    end
         | 
| 265 303 | 
             
                  end
         | 
| 266 | 
            -
             | 
| 304 | 
            +
             | 
| 267 305 | 
             
                  describe "navigation properties" do
         | 
| 268 306 | 
             
                    it "should fill in PropertyMetadata for navigation properties" do
         | 
| 269 307 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| @@ -271,27 +309,27 @@ module OData | |
| 271 309 | 
             
                    end
         | 
| 272 310 | 
             
                  end
         | 
| 273 311 | 
             
                end
         | 
| 274 | 
            -
             | 
| 312 | 
            +
             | 
| 275 313 | 
             
                describe "single layer inheritance" do
         | 
| 276 314 | 
             
                  before(:each) do
         | 
| 277 315 | 
             
                    # Metadata
         | 
| 278 316 | 
             
                    stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 279 317 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 280 318 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/inheritance/edmx_pluralsight.xml", __FILE__)), :headers => {})
         | 
| 281 | 
            -
             | 
| 319 | 
            +
             | 
| 282 320 | 
             
                    # Content - Courses
         | 
| 283 321 | 
             
                    stub_request(:get, /http:\/\/test\.com\/test\.svc\/Courses(?:.*)/).
         | 
| 284 322 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 285 323 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/inheritance/result_pluralsight_courses.xml", __FILE__)), :headers => {})
         | 
| 286 324 | 
             
                  end
         | 
| 287 | 
            -
             | 
| 325 | 
            +
             | 
| 288 326 | 
             
                  it "should build all inherited attributes" do
         | 
| 289 327 | 
             
                    OData::Service.new "http://test.com/test.svc/"
         | 
| 290 328 | 
             
                    methods = Course.instance_methods.reject {|m| Object.methods.index(m)}
         | 
| 291 | 
            -
             | 
| 329 | 
            +
             | 
| 292 330 | 
             
                    # Ruby 1.9 uses symbols, and 1.8 uses strings, so this normalizes the data
         | 
| 293 331 | 
             
                    methods.map! {|m| m.to_sym}
         | 
| 294 | 
            -
             | 
| 332 | 
            +
             | 
| 295 333 | 
             
                    methods.should include(:Title)
         | 
| 296 334 | 
             
                    methods.should include(:Description)
         | 
| 297 335 | 
             
                    methods.should include(:VideoLength)
         | 
| @@ -319,7 +357,7 @@ module OData | |
| 319 357 | 
             
                    course.Category.should_not be_nil
         | 
| 320 358 | 
             
                  end
         | 
| 321 359 | 
             
                end
         | 
| 322 | 
            -
             | 
| 360 | 
            +
             | 
| 323 361 | 
             
                describe "handling partial collections" do
         | 
| 324 362 | 
             
                  before(:each) do
         | 
| 325 363 | 
             
                    # Metadata
         | 
| @@ -360,15 +398,40 @@ module OData | |
| 360 398 | 
             
                    end
         | 
| 361 399 | 
             
                    results.count.should eq 3
         | 
| 362 400 | 
             
                  end
         | 
| 401 | 
            +
             | 
| 402 | 
            +
                  context "with additional_params" do
         | 
| 403 | 
            +
                    before(:each) do
         | 
| 404 | 
            +
                      stub_request(:get, "http://test.com/test.svc/$metadata?extra_param=value").
         | 
| 405 | 
            +
                     with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 406 | 
            +
                     to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/partial/partial_feed_metadata.xml", __FILE__)), :headers => {})
         | 
| 407 | 
            +
             | 
| 408 | 
            +
                      stub_request(:get, "http://test.com/test.svc/Partials?extra_param=value").
         | 
| 409 | 
            +
                        with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 410 | 
            +
                        to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/partial/partial_feed_part_1.xml", __FILE__)), :headers => {})
         | 
| 411 | 
            +
             | 
| 412 | 
            +
                      stub_request(:get, "http://test.com/test.svc/Partials?$skiptoken='ERNSH'&extra_param=value").
         | 
| 413 | 
            +
                        with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 414 | 
            +
                        to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/partial/partial_feed_part_2.xml", __FILE__)), :headers => {})
         | 
| 415 | 
            +
                    end
         | 
| 416 | 
            +
             | 
| 417 | 
            +
                    it "should persist the additional parameters for the next call" do
         | 
| 418 | 
            +
                      svc = OData::Service.new("http://test.com/test.svc/", :eager_partial => false, :additional_params => { :extra_param => 'value' })
         | 
| 419 | 
            +
                      svc.Partials
         | 
| 420 | 
            +
                      svc.execute
         | 
| 421 | 
            +
                      svc.next
         | 
| 422 | 
            +
             | 
| 423 | 
            +
                      a_request(:get, "http://test.com/test.svc/Partials?$skiptoken='ERNSH'&extra_param=value").should have_been_made
         | 
| 424 | 
            +
                    end
         | 
| 425 | 
            +
                  end
         | 
| 363 426 | 
             
                end
         | 
| 364 | 
            -
             | 
| 427 | 
            +
             | 
| 365 428 | 
             
                describe "link queries" do
         | 
| 366 429 | 
             
                  before(:each) do
         | 
| 367 430 | 
             
                    # Required for the build_classes method
         | 
| 368 431 | 
             
                    stub_request(:get, /http:\/\/test\.com\/test\.svc\/\$metadata(?:\?.+)?/).
         | 
| 369 432 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 370 433 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/edmx_categories_products.xml", __FILE__)), :headers => {})
         | 
| 371 | 
            -
             | 
| 434 | 
            +
             | 
| 372 435 | 
             
                    stub_request(:get, "http://test.com/test.svc/Categories(1)/$links/Products").
         | 
| 373 436 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 374 437 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/links/result_links_query.xml", __FILE__)), :headers => {})
         | 
| @@ -381,72 +444,72 @@ module OData | |
| 381 444 | 
             
                    results.first.should be_a_kind_of(URI)
         | 
| 382 445 | 
             
                    results[0].path.should eq "/SampleService/RubyOData.svc/Products(1)"
         | 
| 383 446 | 
             
                    results[1].path.should eq "/SampleService/RubyOData.svc/Products(2)"
         | 
| 384 | 
            -
                    results[2].path.should eq "/SampleService/RubyOData.svc/Products(3)" | 
| 447 | 
            +
                    results[2].path.should eq "/SampleService/RubyOData.svc/Products(3)"
         | 
| 385 448 | 
             
                  end
         | 
| 386 449 | 
             
                end
         | 
| 387 | 
            -
             | 
| 450 | 
            +
             | 
| 388 451 | 
             
                describe "sample service" do
         | 
| 389 452 | 
             
                  before(:each) do
         | 
| 390 453 | 
             
                    # Required for the build_classes method
         | 
| 391 454 | 
             
                    stub_request(:get, /http:\/\/test\.com\/test\.svc\/\$metadata(?:\?.+)?/).
         | 
| 392 455 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 393 456 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/edmx_categories_products.xml", __FILE__)), :headers => {})
         | 
| 394 | 
            -
             | 
| 457 | 
            +
             | 
| 395 458 | 
             
                    stub_request(:get, /http:\/\/test\.com\/test\.svc\/Products\(\d\)/).
         | 
| 396 459 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 397 460 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_single_product.xml", __FILE__)), :headers => {})
         | 
| 398 | 
            -
             | 
| 461 | 
            +
             | 
| 399 462 | 
             
                    stub_request(:get, /http:\/\/test\.com\/test\.svc\/Products\(\d{2,}\)/).
         | 
| 400 463 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 401 464 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_single_product_not_found.xml", __FILE__)), :headers => {})
         | 
| 402 | 
            -
             | 
| 465 | 
            +
             | 
| 403 466 | 
             
                    stub_request(:get, "http://test.com/test.svc/Products(1)/Category").
         | 
| 404 467 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 405 468 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_single_category.xml", __FILE__)), :headers => {})
         | 
| 406 | 
            -
             | 
| 469 | 
            +
             | 
| 407 470 | 
             
                    stub_request(:get, "http://test.com/test.svc/Categories(1)").
         | 
| 408 471 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 409 472 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_single_category.xml", __FILE__)), :headers => {})
         | 
| 410 | 
            -
             | 
| 473 | 
            +
             | 
| 411 474 | 
             
                    stub_request(:get, "http://test.com/test.svc/Categories(1)/Products").
         | 
| 412 475 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 413 476 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_multiple_category_products.xml", __FILE__)), :headers => {})
         | 
| 414 | 
            -
             | 
| 477 | 
            +
             | 
| 415 478 | 
             
                    stub_request(:post, "http://test.com/test.svc/Categories(1)/$links/Products").to_return(:status => 204)
         | 
| 416 479 | 
             
                    stub_request(:post, "http://test.com/test.svc/$batch").to_return(:status => 202)
         | 
| 417 480 | 
             
                  end
         | 
| 418 | 
            -
             | 
| 481 | 
            +
             | 
| 419 482 | 
             
                  describe "lazy loading" do
         | 
| 420 483 | 
             
                    after(:each) do
         | 
| 421 484 | 
             
                      Object.send(:remove_const, 'Product') if Object.const_defined? 'Product'
         | 
| 422 485 | 
             
                      Object.send(:remove_const, 'Category') if Object.const_defined? 'Category'
         | 
| 423 486 | 
             
                    end
         | 
| 424 | 
            -
             | 
| 487 | 
            +
             | 
| 425 488 | 
             
                    it "should have a load property method" do
         | 
| 426 489 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 427 490 | 
             
                      svc.should respond_to(:load_property)
         | 
| 428 491 | 
             
                    end
         | 
| 429 | 
            -
             | 
| 492 | 
            +
             | 
| 430 493 | 
             
                    it "should throw an exception if the object isn't tracked" do
         | 
| 431 494 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 432 495 | 
             
                      new_object = Product.new
         | 
| 433 | 
            -
                      lambda { svc.load_property(new_object, "Category") }.should raise_error( | 
| 496 | 
            +
                      lambda { svc.load_property(new_object, "Category") }.should raise_error(NotSupportedError, "You cannot load a property on an entity that isn't tracked")
         | 
| 434 497 | 
             
                    end
         | 
| 435 | 
            -
             | 
| 498 | 
            +
             | 
| 436 499 | 
             
                    it "should throw an exception if there isn't a method matching the navigation property passed in" do
         | 
| 437 500 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 438 501 | 
             
                      svc.Products(1)
         | 
| 439 502 | 
             
                      product = svc.execute.first
         | 
| 440 | 
            -
                      lambda { svc.load_property(product, "NoMatchingMethod") }.should raise_error(ArgumentError, "'NoMatchingMethod' is not a valid navigation property") | 
| 503 | 
            +
                      lambda { svc.load_property(product, "NoMatchingMethod") }.should raise_error(ArgumentError, "'NoMatchingMethod' is not a valid navigation property")
         | 
| 441 504 | 
             
                    end
         | 
| 442 | 
            -
             | 
| 505 | 
            +
             | 
| 443 506 | 
             
                    it "should throw an exception if the method passed in is a standard property (non-navigation)" do
         | 
| 444 507 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 445 508 | 
             
                      svc.Products(1)
         | 
| 446 509 | 
             
                      product = svc.execute.first
         | 
| 447 | 
            -
                      lambda { svc.load_property(product, "Name") }.should raise_error(ArgumentError, "'Name' is not a valid navigation property") | 
| 510 | 
            +
                      lambda { svc.load_property(product, "Name") }.should raise_error(ArgumentError, "'Name' is not a valid navigation property")
         | 
| 448 511 | 
             
                    end
         | 
| 449 | 
            -
             | 
| 512 | 
            +
             | 
| 450 513 | 
             
                    it "should fill a single navigation property" do
         | 
| 451 514 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 452 515 | 
             
                      svc.Products(1)
         | 
| @@ -456,7 +519,7 @@ module OData | |
| 456 519 | 
             
                      product.Category.Id.should eq 1
         | 
| 457 520 | 
             
                      product.Category.Name.should eq 'Category 1'
         | 
| 458 521 | 
             
                    end
         | 
| 459 | 
            -
             | 
| 522 | 
            +
             | 
| 460 523 | 
             
                    it "should fill a collection navigation property" do
         | 
| 461 524 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 462 525 | 
             
                      svc.Categories(1)
         | 
| @@ -466,59 +529,68 @@ module OData | |
| 466 529 | 
             
                      category.Products[0].Id.should eq 1
         | 
| 467 530 | 
             
                      category.Products[1].Id.should eq 2
         | 
| 468 531 | 
             
                    end
         | 
| 532 | 
            +
             | 
| 533 | 
            +
                    it "should not mutate the object's metadata" do
         | 
| 534 | 
            +
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 535 | 
            +
                      svc.Products(1)
         | 
| 536 | 
            +
                      product = svc.execute.first
         | 
| 537 | 
            +
                      original_metadata = product.__metadata.to_json
         | 
| 538 | 
            +
                      svc.load_property(product, "Category")
         | 
| 539 | 
            +
                      product.__metadata.to_json.should == original_metadata
         | 
| 540 | 
            +
                    end
         | 
| 469 541 | 
             
                  end
         | 
| 470 | 
            -
             | 
| 542 | 
            +
             | 
| 471 543 | 
             
                  describe "find, create, add, update, and delete" do
         | 
| 472 544 | 
             
                    after(:each) do
         | 
| 473 545 | 
             
                      Object.send(:remove_const, 'Product') if Object.const_defined? 'Product'
         | 
| 474 546 | 
             
                      Object.send(:remove_const, 'Category') if Object.const_defined? 'Category'
         | 
| 475 547 | 
             
                    end
         | 
| 476 | 
            -
             | 
| 548 | 
            +
             | 
| 477 549 | 
             
                    it "should implement an AddTo method for collection" do
         | 
| 478 550 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 479 551 | 
             
                      svc.should respond_to :AddToCategories
         | 
| 480 552 | 
             
                      svc.should respond_to :AddToProducts
         | 
| 481 553 | 
             
                    end
         | 
| 482 | 
            -
             | 
| 554 | 
            +
             | 
| 483 555 | 
             
                    it "should create objects with an initialize method that can build the object from a hash" do
         | 
| 484 556 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 485 557 | 
             
                      product = Product.new 'Id' => 1000, 'Name' => 'New Product'
         | 
| 486 558 | 
             
                      product.Id.should eq 1000
         | 
| 487 559 | 
             
                      product.Name.should eq 'New Product'
         | 
| 488 560 | 
             
                    end
         | 
| 489 | 
            -
             | 
| 561 | 
            +
             | 
| 490 562 | 
             
                    it "should create objects that rejects keys that don't have corresponding methods" do
         | 
| 491 563 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 492 564 | 
             
                      lambda { Product.new 'NotAProperty' => true }.should raise_error NoMethodError
         | 
| 493 565 | 
             
                    end
         | 
| 494 | 
            -
             | 
| 566 | 
            +
             | 
| 495 567 | 
             
                    it "should create objects that expose a properties class method that lists the properties for the object" do
         | 
| 496 568 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 497 569 | 
             
                      Product.properties.should include 'Id'
         | 
| 498 570 | 
             
                      Product.properties.should include 'Name'
         | 
| 499 | 
            -
                      Product.properties.should include 'Category' | 
| 571 | 
            +
                      Product.properties.should include 'Category'
         | 
| 500 572 | 
             
                    end
         | 
| 501 | 
            -
             | 
| 573 | 
            +
             | 
| 502 574 | 
             
                    it "should have full metadata for a property returned from the properties method" do
         | 
| 503 575 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 504 576 | 
             
                      Product.properties['Category'].should be_a PropertyMetadata
         | 
| 505 577 | 
             
                      Product.properties['Category'].nav_prop.should be_true
         | 
| 506 578 | 
             
                    end
         | 
| 507 | 
            -
             | 
| 579 | 
            +
             | 
| 508 580 | 
             
                    it "should create objects that expose an id property" do
         | 
| 509 581 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 510 582 | 
             
                      svc.Products(1)
         | 
| 511 583 | 
             
                      product = svc.execute.first
         | 
| 512 584 | 
             
                      product.should respond_to :id
         | 
| 513 585 | 
             
                    end
         | 
| 514 | 
            -
             | 
| 586 | 
            +
             | 
| 515 587 | 
             
                    it "should extract the id from the metadata" do
         | 
| 516 588 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 517 589 | 
             
                      svc.Products(1)
         | 
| 518 590 | 
             
                      product = svc.execute.first
         | 
| 519 591 | 
             
                      product.id.should eq 1
         | 
| 520 592 | 
             
                    end
         | 
| 521 | 
            -
             | 
| 593 | 
            +
             | 
| 522 594 | 
             
                    describe "Class.first method" do
         | 
| 523 595 | 
             
                      it "should exist on the create server objects" do
         | 
| 524 596 | 
             
                        svc = OData::Service.new "http://test.com/test.svc/"
         | 
| @@ -528,7 +600,7 @@ module OData | |
| 528 600 | 
             
                        svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 529 601 | 
             
                        product = Product.first(nil)
         | 
| 530 602 | 
             
                        product.should be_nil
         | 
| 531 | 
            -
                      end | 
| 603 | 
            +
                      end
         | 
| 532 604 | 
             
                      it "should return nil if an id isn't found" do
         | 
| 533 605 | 
             
                        svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 534 606 | 
             
                        product = Product.first(1234567890)
         | 
| @@ -541,29 +613,29 @@ module OData | |
| 541 613 | 
             
                      end
         | 
| 542 614 | 
             
                    end
         | 
| 543 615 | 
             
                  end
         | 
| 544 | 
            -
             | 
| 616 | 
            +
             | 
| 545 617 | 
             
                  describe "namespaces" do
         | 
| 546 618 | 
             
                    after(:each) do
         | 
| 547 619 | 
             
                      VisoftInc::Sample::Models.send(:remove_const, 'Product')        if VisoftInc::Sample::Models.const_defined? 'Product'
         | 
| 548 620 | 
             
                      VisoftInc::Sample::Models.send(:remove_const, 'Category')       if VisoftInc::Sample::Models.const_defined? 'Category'
         | 
| 549 | 
            -
             | 
| 621 | 
            +
             | 
| 550 622 | 
             
                      VisoftInc::Sample.send(:remove_const, 'Models')                 if VisoftInc::Sample.const_defined? 'Models'
         | 
| 551 | 
            -
                      VisoftInc.send(:remove_const, 'Sample')                         if VisoftInc.const_defined? 'Sample' | 
| 623 | 
            +
                      VisoftInc.send(:remove_const, 'Sample')                         if VisoftInc.const_defined? 'Sample'
         | 
| 552 624 | 
             
                      Object.send(:remove_const, 'VisoftInc')                         if Object.const_defined? 'VisoftInc'
         | 
| 553 625 | 
             
                    end
         | 
| 554 | 
            -
             | 
| 626 | 
            +
             | 
| 555 627 | 
             
                    it "should create models in the specified namespace if the option is set (using a .NET style namespace with dots)" do
         | 
| 556 628 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/", { :namespace => 'VisoftInc.Sample.Models' }
         | 
| 557 629 | 
             
                      defined?(VisoftInc::Sample::Models::Product).nil?.should be_false, 'VisoftInc::Sample::Models::Product was expected to be defined, but was not'
         | 
| 558 630 | 
             
                      defined?(VisoftInc::Sample::Models::Category).nil?.should be_false, 'VisoftInc::Sample::Models::Category was expected to be defined, but was not'
         | 
| 559 631 | 
             
                    end
         | 
| 560 | 
            -
             | 
| 632 | 
            +
             | 
| 561 633 | 
             
                    it "should create models in the specified namespace if the option is set (using Ruby style namespaces with double colons)" do
         | 
| 562 634 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/", { :namespace => 'VisoftInc::Sample::Models' }
         | 
| 563 635 | 
             
                      defined?(VisoftInc::Sample::Models::Product).nil?.should be_false, 'VisoftInc::Sample::Models::Product was expected to be defined, but was not'
         | 
| 564 636 | 
             
                      defined?(VisoftInc::Sample::Models::Category).nil?.should be_false, 'VisoftInc::Sample::Models::Category was expected to be defined, but was not'
         | 
| 565 637 | 
             
                    end
         | 
| 566 | 
            -
             | 
| 638 | 
            +
             | 
| 567 639 | 
             
                    it "should fill object defined in a namespace" do
         | 
| 568 640 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/", { :namespace => 'VisoftInc::Sample::Models' }
         | 
| 569 641 | 
             
                      svc.Categories(1)
         | 
| @@ -573,19 +645,19 @@ module OData | |
| 573 645 | 
             
                      category.Id.should eq 1
         | 
| 574 646 | 
             
                      category.Name.should eq 'Category 1'
         | 
| 575 647 | 
             
                    end
         | 
| 576 | 
            -
             | 
| 648 | 
            +
             | 
| 577 649 | 
             
                    it "should fill the class_metadata hash" do
         | 
| 578 650 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/", { :namespace => 'VisoftInc::Sample::Models' }
         | 
| 579 651 | 
             
                      svc.class_metadata.should_not be_empty
         | 
| 580 652 | 
             
                    end
         | 
| 581 | 
            -
             | 
| 653 | 
            +
             | 
| 582 654 | 
             
                    it "should add a key (based on the name) for each property class_metadata hash" do
         | 
| 583 655 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/", { :namespace => 'VisoftInc::Sample::Models' }
         | 
| 584 656 | 
             
                      svc.class_metadata['VisoftInc::Sample::Models::Product'].should have_key 'Id'
         | 
| 585 657 | 
             
                      svc.class_metadata['VisoftInc::Sample::Models::Product'].should have_key 'Name'
         | 
| 586 658 | 
             
                      svc.class_metadata['VisoftInc::Sample::Models::Product'].should have_key 'Description'
         | 
| 587 659 | 
             
                    end
         | 
| 588 | 
            -
             | 
| 660 | 
            +
             | 
| 589 661 | 
             
                    it "should lazy load objects defined in a namespace" do
         | 
| 590 662 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/", { :namespace => 'VisoftInc::Sample::Models' }
         | 
| 591 663 | 
             
                      svc.Categories(1)
         | 
| @@ -593,7 +665,7 @@ module OData | |
| 593 665 | 
             
                      svc.load_property category, 'Products'
         | 
| 594 666 | 
             
                      category.Products.should_not be_nil
         | 
| 595 667 | 
             
                      category.Products.first.Id.should eq 1
         | 
| 596 | 
            -
                      category.Products.first.Name.should eq 'Widget 1' | 
| 668 | 
            +
                      category.Products.first.Name.should eq 'Widget 1'
         | 
| 597 669 | 
             
                    end
         | 
| 598 670 | 
             
                  end
         | 
| 599 671 |  | 
| @@ -602,15 +674,15 @@ module OData | |
| 602 674 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 603 675 | 
             
                      svc.should respond_to(:add_link)
         | 
| 604 676 | 
             
                    end
         | 
| 605 | 
            -
             | 
| 677 | 
            +
             | 
| 606 678 | 
             
                    it "shouldn't be allowed if a parent isn't tracked" do
         | 
| 607 679 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 608 680 | 
             
                      category = Category.new :Name => 'New Category'
         | 
| 609 681 | 
             
                      property = nil # Not needed for this test
         | 
| 610 682 | 
             
                      product = nil # Not needed for this test
         | 
| 611 | 
            -
                      lambda { svc.add_link(category, property, product) }.should raise_error( | 
| 683 | 
            +
                      lambda { svc.add_link(category, property, product) }.should raise_error(NotSupportedError, "You cannot add a link on an entity that isn't tracked (Category)")
         | 
| 612 684 | 
             
                    end
         | 
| 613 | 
            -
             | 
| 685 | 
            +
             | 
| 614 686 | 
             
                    it "shouldn't be allowed if a property isn't found on the parent" do
         | 
| 615 687 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 616 688 | 
             
                      svc.Categories(1)
         | 
| @@ -619,7 +691,7 @@ module OData | |
| 619 691 | 
             
                      product = nil # Not needed for this test
         | 
| 620 692 | 
             
                      lambda { svc.add_link(category, property, product) }.should raise_error(ArgumentError, "'NotAProperty' is not a valid navigation property for Category")
         | 
| 621 693 | 
             
                    end
         | 
| 622 | 
            -
             | 
| 694 | 
            +
             | 
| 623 695 | 
             
                    it "shouldn't be allowed if a property isn't a navigation property on the parent" do
         | 
| 624 696 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 625 697 | 
             
                      svc.Categories(1)
         | 
| @@ -628,16 +700,16 @@ module OData | |
| 628 700 | 
             
                      product = nil # Not needed for this test
         | 
| 629 701 | 
             
                      lambda { svc.add_link(category, property, product) }.should raise_error(ArgumentError, "'Name' is not a valid navigation property for Category")
         | 
| 630 702 | 
             
                    end
         | 
| 631 | 
            -
             | 
| 703 | 
            +
             | 
| 632 704 | 
             
                    it "shouldn't be allowed if a child isn't tracked" do
         | 
| 633 705 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 634 706 | 
             
                      svc.Categories(1)
         | 
| 635 707 | 
             
                      category = svc.execute.first
         | 
| 636 708 | 
             
                      property = 'Products'
         | 
| 637 | 
            -
                      product = Product.new :Name => 'Widget 1' | 
| 638 | 
            -
                      lambda { svc.add_link(category, property, product) }.should raise_error( | 
| 709 | 
            +
                      product = Product.new :Name => 'Widget 1'
         | 
| 710 | 
            +
                      lambda { svc.add_link(category, property, product) }.should raise_error(NotSupportedError, "You cannot add a link on a child entity that isn't tracked (Product)")
         | 
| 639 711 | 
             
                    end
         | 
| 640 | 
            -
             | 
| 712 | 
            +
             | 
| 641 713 | 
             
                    it "should perform a post against the correct URL with the correct body on a single_save" do
         | 
| 642 714 | 
             
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 643 715 | 
             
                      svc.Categories(1)
         | 
| @@ -704,8 +776,240 @@ module OData | |
| 704 776 | 
             
                    end
         | 
| 705 777 | 
             
                  end
         | 
| 706 778 | 
             
                end
         | 
| 779 | 
            +
             | 
| 780 | 
            +
                describe "JSON serialization of objects" do
         | 
| 781 | 
            +
                  before(:each) do
         | 
| 782 | 
            +
                    # Required for the build_classes method
         | 
| 783 | 
            +
                    stub_request(:get, "http://blabla:@test.com/test.svc/$metadata").
         | 
| 784 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 785 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/ms_system_center/edmx_ms_system_center.xml", __FILE__)), :headers => {})
         | 
| 786 | 
            +
             | 
| 787 | 
            +
                    stub_request(:get, "http://blabla:@test.com/test.svc/VirtualMachines").
         | 
| 788 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 789 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/ms_system_center/virtual_machines.xml", __FILE__)), :headers => {})
         | 
| 790 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc/", { :username => "blabla", :password=> "", :verify_ssl => false, :namespace => "VMM" }
         | 
| 791 | 
            +
                    svc.VirtualMachines
         | 
| 792 | 
            +
                    results = svc.execute
         | 
| 793 | 
            +
                    @json = results.first.as_json
         | 
| 794 | 
            +
                  end
         | 
| 795 | 
            +
             | 
| 796 | 
            +
                  it "Should quote Edm.Int64 properties" do
         | 
| 797 | 
            +
                    @json["PerfDiskBytesWrite"].should be_a(String)
         | 
| 798 | 
            +
                  end
         | 
| 799 | 
            +
             | 
| 800 | 
            +
                  it "Should output collections with metadata" do
         | 
| 801 | 
            +
                    @json["VMNetworkAssignments"].should be_a(Hash)
         | 
| 802 | 
            +
                    @json["VMNetworkAssignments"].should have_key("__metadata")
         | 
| 803 | 
            +
                    @json["VMNetworkAssignments"]["__metadata"].should be_a(Hash)
         | 
| 804 | 
            +
                    @json["VMNetworkAssignments"]["__metadata"].should have_key("type")
         | 
| 805 | 
            +
                    @json["VMNetworkAssignments"]["__metadata"]["type"].should eq("Collection(VMM.VMNetworkAssignment)")
         | 
| 806 | 
            +
                    @json["VMNetworkAssignments"].should have_key("results")
         | 
| 807 | 
            +
                    @json["VMNetworkAssignments"]["results"].should be_a(Array)
         | 
| 808 | 
            +
                    @json["VMNetworkAssignments"]["results"].should eq([])
         | 
| 809 | 
            +
                  end
         | 
| 810 | 
            +
                end
         | 
| 811 | 
            +
             | 
| 812 | 
            +
                describe "handling of Microsoft System Center 2012" do
         | 
| 813 | 
            +
                  before(:each) do
         | 
| 814 | 
            +
                    # Required for the build_classes method
         | 
| 815 | 
            +
                    stub_request(:get, "http://blabla:@test.com/test.svc/$metadata").
         | 
| 816 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 817 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/ms_system_center/edmx_ms_system_center.xml", __FILE__)), :headers => {})
         | 
| 818 | 
            +
             | 
| 819 | 
            +
                    stub_request(:get, "http://blabla:@test.com/test.svc/VirtualMachines").
         | 
| 820 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 821 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/ms_system_center/virtual_machines.xml", __FILE__)), :headers => {})
         | 
| 822 | 
            +
             | 
| 823 | 
            +
                    stub_request(:get, "http://blabla:@test.com/test.svc/HardwareProfiles?$filter=Memory%20eq%203500").
         | 
| 824 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 825 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/ms_system_center/hardware_profiles.xml", __FILE__)), :headers => {})
         | 
| 826 | 
            +
             | 
| 827 | 
            +
                    stub_request(:get, "http://blabla:@test.com/test.svc/VMTemplates").
         | 
| 828 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 829 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/ms_system_center/vm_templates.xml", __FILE__)), :headers => {})
         | 
| 830 | 
            +
                  end
         | 
| 831 | 
            +
             | 
| 832 | 
            +
                  after(:all) do
         | 
| 833 | 
            +
                    VMM.constants.each do |constant|
         | 
| 834 | 
            +
                      VMM.send :remove_const, constant
         | 
| 835 | 
            +
                    end
         | 
| 836 | 
            +
                  end
         | 
| 837 | 
            +
             | 
| 838 | 
            +
                  it "should successfully parse null valued string properties" do
         | 
| 839 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc/", { :username => "blabla", :password=> "", :verify_ssl => false, :namespace => "VMM" }
         | 
| 840 | 
            +
                    svc.VirtualMachines
         | 
| 841 | 
            +
                    results = svc.execute
         | 
| 842 | 
            +
                    results.first.should be_a_kind_of(VMM::VirtualMachine)
         | 
| 843 | 
            +
                    results.first.CostCenter.should be_nil
         | 
| 844 | 
            +
                  end
         | 
| 845 | 
            +
             | 
| 846 | 
            +
                  it "should successfully return a virtual machine" do
         | 
| 847 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc/", { :username => "blabla", :password=> "", :verify_ssl => false, :namespace => "VMM" }
         | 
| 848 | 
            +
                    svc.VirtualMachines
         | 
| 849 | 
            +
                    results = svc.execute
         | 
| 850 | 
            +
                    results.first.should be_a_kind_of(VMM::VirtualMachine)
         | 
| 851 | 
            +
                  end
         | 
| 852 | 
            +
             | 
| 853 | 
            +
                  it "should successfully return a hardware profile for results that include a collection of complex types" do
         | 
| 854 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc/", { :username => "blabla", :password=> "", :verify_ssl => false, :namespace => "VMM" }
         | 
| 855 | 
            +
                    svc.HardwareProfiles.filter("Memory eq 3500")
         | 
| 856 | 
            +
                    results = svc.execute
         | 
| 857 | 
            +
                    results.first.should be_a_kind_of(VMM::HardwareProfile)
         | 
| 858 | 
            +
                  end
         | 
| 859 | 
            +
             | 
| 860 | 
            +
                  it "should successfully return a collection of complex types" do
         | 
| 861 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc/", { :username => "blabla", :password=> "", :verify_ssl => false, :namespace => "VMM" }
         | 
| 862 | 
            +
                    svc.HardwareProfiles.filter("Memory eq 3500")
         | 
| 863 | 
            +
                    results = svc.execute
         | 
| 864 | 
            +
                    granted_list = results.first.GrantedToList
         | 
| 865 | 
            +
                    granted_list.should be_a_kind_of(Array)
         | 
| 866 | 
            +
                    granted_list.first.should be_a_kind_of(VMM::UserAndRole)
         | 
| 867 | 
            +
                    granted_list.first.RoleName.should == "Important Tenant"
         | 
| 868 | 
            +
                  end
         | 
| 869 | 
            +
             | 
| 870 | 
            +
             | 
| 871 | 
            +
                  it "should successfully return results that include a collection of Edm types" do
         | 
| 872 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc/", { :username => "blabla", :password=> "", :verify_ssl => false, :namespace => "VMM" }
         | 
| 873 | 
            +
                    svc.VMTemplates
         | 
| 874 | 
            +
                    results = svc.execute
         | 
| 875 | 
            +
                    results.first.should be_a_kind_of(VMM::VMTemplate)
         | 
| 876 | 
            +
                  end
         | 
| 877 | 
            +
             | 
| 878 | 
            +
                  it "should successfully return a collection of Edm types" do
         | 
| 879 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc/", { :username => "blabla", :password=> "", :verify_ssl => false, :namespace => "VMM" }
         | 
| 880 | 
            +
                    svc.VMTemplates
         | 
| 881 | 
            +
                    results = svc.execute
         | 
| 882 | 
            +
                    boot_order = results.first.BootOrder
         | 
| 883 | 
            +
                    boot_order.should be_a_kind_of(Array)
         | 
| 884 | 
            +
                    boot_order.first.should be_a_kind_of(String)
         | 
| 885 | 
            +
                    boot_order.should eq ['CD', 'IdeHardDrive', 'PxeBoot', 'Floppy']
         | 
| 886 | 
            +
                  end
         | 
| 887 | 
            +
                end
         | 
| 888 | 
            +
             | 
| 889 | 
            +
                describe "handling of nested expands" do
         | 
| 890 | 
            +
                  before(:each) do
         | 
| 891 | 
            +
                    stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 892 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 893 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/nested_expands/edmx_northwind.xml", __FILE__)), :headers => {})
         | 
| 894 | 
            +
             | 
| 895 | 
            +
                    stub_request(:get, "http://test.com/test.svc/Products?$expand=Category,Category/Products&$top=2").
         | 
| 896 | 
            +
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 897 | 
            +
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/nested_expands/northwind_products_category_expands.xml", __FILE__)), :headers => {})
         | 
| 898 | 
            +
                  end
         | 
| 899 | 
            +
             | 
| 900 | 
            +
                  it "should successfully parse the results" do
         | 
| 901 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc", { :namespace => "NW" }
         | 
| 902 | 
            +
                    svc.Products.expand('Category').expand('Category/Products').top(2)
         | 
| 903 | 
            +
                    lambda { svc.execute }.should_not raise_exception
         | 
| 904 | 
            +
                  end
         | 
| 905 | 
            +
             | 
| 906 | 
            +
                  it "should successfully parse a Category as a Category" do
         | 
| 907 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc", { :namespace => "NW" }
         | 
| 908 | 
            +
                    svc.Products.expand('Category').expand('Category/Products').top(2)
         | 
| 909 | 
            +
                    products = svc.execute
         | 
| 910 | 
            +
                    products.first.Category.should be_a_kind_of(NW::Category)
         | 
| 911 | 
            +
                  end
         | 
| 912 | 
            +
             | 
| 913 | 
            +
                  it "should successfully parse the Category properties" do
         | 
| 914 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc", { :namespace => "NW" }
         | 
| 915 | 
            +
                    svc.Products.expand('Category').expand('Category/Products').top(2)
         | 
| 916 | 
            +
                    products = svc.execute
         | 
| 917 | 
            +
                    products.first.Category.CategoryID.should eq 1
         | 
| 918 | 
            +
                  end
         | 
| 919 | 
            +
             | 
| 920 | 
            +
                  it "should successfully parse the Category children Products" do
         | 
| 921 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc", { :namespace => "NW" }
         | 
| 922 | 
            +
                    svc.Products.expand('Category').expand('Category/Products').top(2)
         | 
| 923 | 
            +
                    products = svc.execute
         | 
| 924 | 
            +
                    products.first.Category.Products.length.should eq 12
         | 
| 925 | 
            +
                  end
         | 
| 926 | 
            +
             | 
| 927 | 
            +
                  it "should successfully parse the Category's child Product properties" do
         | 
| 928 | 
            +
                    svc = OData::Service.new "http://test.com/test.svc", { :namespace => "NW" }
         | 
| 929 | 
            +
                    svc.Products.expand('Category').expand('Category/Products').top(2)
         | 
| 930 | 
            +
                    products = svc.execute
         | 
| 931 | 
            +
                    products.first.Category.Products.first.ProductName.should eq "Chai"
         | 
| 932 | 
            +
                  end
         | 
| 933 | 
            +
                end
         | 
| 934 | 
            +
             | 
| 935 | 
            +
                describe "handling of custom select queries" do
         | 
| 936 | 
            +
             | 
| 937 | 
            +
                  context "when results are found" do
         | 
| 938 | 
            +
                    before(:each) do
         | 
| 939 | 
            +
                      stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 940 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 941 | 
            +
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/edmx_categories_products.xml", __FILE__)), :headers => {})
         | 
| 942 | 
            +
             | 
| 943 | 
            +
                      stub_request(:get, "http://test.com/test.svc/Products?$select=Name,Price").
         | 
| 944 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 945 | 
            +
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_select_products_name_price.xml", __FILE__)), :headers => {})
         | 
| 946 | 
            +
                    end
         | 
| 947 | 
            +
             | 
| 948 | 
            +
                    subject do
         | 
| 949 | 
            +
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 950 | 
            +
                      svc.Products.select "Name", "Price"
         | 
| 951 | 
            +
                      svc.execute
         | 
| 952 | 
            +
                    end
         | 
| 953 | 
            +
             | 
| 954 | 
            +
                    it { should be_an Array }
         | 
| 955 | 
            +
                    it { should_not be_empty }
         | 
| 956 | 
            +
                    its(:first) { should be_a Product }
         | 
| 957 | 
            +
                  end
         | 
| 958 | 
            +
             | 
| 959 | 
            +
                  context "when there isn't a property by the name specified" do
         | 
| 960 | 
            +
                    before(:each) do
         | 
| 961 | 
            +
                      stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 962 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 963 | 
            +
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/edmx_categories_products.xml", __FILE__)), :headers => {})
         | 
| 964 | 
            +
             | 
| 965 | 
            +
                      stub_request(:get, "http://test.com/test.svc/Categories?$select=Price").
         | 
| 966 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 967 | 
            +
                      to_return(:status => 400, :body => File.new(File.expand_path("../fixtures/sample_service/result_select_categories_no_property.xml", __FILE__)), :headers => {})
         | 
| 968 | 
            +
                    end
         | 
| 969 | 
            +
             | 
| 970 | 
            +
                    it "raises an exception" do
         | 
| 971 | 
            +
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 972 | 
            +
                      svc.Categories.select "Price"
         | 
| 973 | 
            +
                      expect { svc.execute }.to raise_error(OData::ServiceError) { |error|
         | 
| 974 | 
            +
                        error.http_code.should eq 400
         | 
| 975 | 
            +
                        error.message.should eq "Type 'RubyODataService.Category' does not have a property named 'Price' or there is no type with 'Price' name."
         | 
| 976 | 
            +
                      }
         | 
| 977 | 
            +
                    end
         | 
| 978 | 
            +
                  end
         | 
| 979 | 
            +
             | 
| 980 | 
            +
                  context "when a property requires $expand to traverse" do
         | 
| 981 | 
            +
                    before(:each) do
         | 
| 982 | 
            +
                      stub_request(:get, "http://test.com/test.svc/$metadata").
         | 
| 983 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 984 | 
            +
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/edmx_categories_products.xml", __FILE__)), :headers => {})
         | 
| 985 | 
            +
             | 
| 986 | 
            +
                      stub_request(:get, "http://test.com/test.svc/Categories?$select=Name,Products/Name").
         | 
| 987 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 988 | 
            +
                      to_return(:status => 400, :body => File.new(File.expand_path("../fixtures/sample_service/result_select_categories_travsing_no_expand.xml", __FILE__)), :headers => {})
         | 
| 989 | 
            +
             | 
| 990 | 
            +
                      stub_request(:get, "http://test.com/test.svc/Categories?$select=Name,Products/Name&$expand=Products").
         | 
| 991 | 
            +
                      with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 992 | 
            +
                      to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/sample_service/result_select_categories_expand.xml", __FILE__)), :headers => {})
         | 
| 993 | 
            +
                    end
         | 
| 994 | 
            +
             | 
| 995 | 
            +
                    it "doesn't error" do
         | 
| 996 | 
            +
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 997 | 
            +
                      svc.Categories.select "Name", "Products/Name"
         | 
| 998 | 
            +
                      expect { svc.execute }.to_not raise_error
         | 
| 999 | 
            +
                    end
         | 
| 1000 | 
            +
             | 
| 1001 | 
            +
                    it "returns the classes with the properties filled in" do
         | 
| 1002 | 
            +
                      svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 1003 | 
            +
                      svc.Categories.select "Name", "Products/Name"
         | 
| 1004 | 
            +
                      results = svc.execute
         | 
| 1005 | 
            +
                      category = results.first
         | 
| 1006 | 
            +
                      category.Name.should eq "Category 0001"
         | 
| 1007 | 
            +
                      product = category.Products.first
         | 
| 1008 | 
            +
                      product.Name.should eq "Widget 0001"
         | 
| 1009 | 
            +
                    end
         | 
| 1010 | 
            +
                  end
         | 
| 1011 | 
            +
                end
         | 
| 707 1012 | 
             
              end
         | 
| 708 | 
            -
                
         | 
| 709 1013 | 
             
              describe_private OData::Service do
         | 
| 710 1014 | 
             
                describe "parse value" do
         | 
| 711 1015 | 
             
                  before(:each) do
         | 
| @@ -714,13 +1018,13 @@ module OData | |
| 714 1018 | 
             
                    with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).
         | 
| 715 1019 | 
             
                    to_return(:status => 200, :body => File.new(File.expand_path("../fixtures/edmx_empty.xml", __FILE__)), :headers => {})
         | 
| 716 1020 | 
             
                  end
         | 
| 717 | 
            -
             | 
| 1021 | 
            +
             | 
| 718 1022 | 
             
                  it "should not error on an 'out of range' date" do
         | 
| 719 1023 | 
             
                    # This date was returned in the Netflix OData service and failed with an ArgumentError: out of range using 1.8.7 (2010-12-23 patchlevel 330) [i386-mingw32]
         | 
| 720 1024 | 
             
                    svc = OData::Service.new "http://test.com/test.svc/"
         | 
| 721 1025 | 
             
                    element_to_parse = Nokogiri::XML.parse('<d:AvailableFrom m:type="Edm.DateTime">2100-01-01T00:00:00</d:AvailableFrom>').elements[0]
         | 
| 722 | 
            -
                    lambda { svc. | 
| 1026 | 
            +
                    lambda { svc.parse_value_xml(element_to_parse) }.should_not raise_exception
         | 
| 723 1027 | 
             
                  end
         | 
| 724 1028 | 
             
                end
         | 
| 725 1029 | 
             
              end
         | 
| 726 | 
            -
            end
         | 
| 1030 | 
            +
            end
         |