public void When_Updating_ComplexType_Property_On_Client_Then_That_Property_Must_Be_Updated_On_Server()
        {
            var prods = Any.Products().ToArray();
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(prods.AsQueryable())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery = context.CreateQuery<Product>("/" + "Products(3)");
                Product prod3 = context.ExecuteSingleAsync<Product, IProduct>(dQuery).Result as Product;

                var newComment = new Description { Title = Any.AlphanumericString(), Details = Any.AlphanumericString() };
                newComment.SetContainer(() => new Tuple<EntityBase, string>(prod3, "Comment"));

                prod3.Comment = newComment;
                prod3.CallOnPropertyChanged("Comment");
                prod3.UpdateAsync().Wait();

                Product updatedProd3 = context.ExecuteSingleAsync<Product, IProduct>(dQuery).Result as Product;
                updatedProd3.Comment.Details.Should().Be(newComment.Details);
                updatedProd3.Comment.Title.Should().Be(newComment.Title);
            }
        }
Example #2
0
        public void When_Querying_For_NonExistent_EntitySet_Then_Throw_DataServiceQueryException_With_NotFound_Status_Code()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var action = new Action(() =>
                {
                    var dQuery   = context.CreateQuery <Product>("/" + "RandomEntitySet");
                    var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                });

                //check for AggregateException with DataServiceQueryException as InnerException.
                //Also retrieve the DataServiceQueryException InnerException.
                DataServiceQueryException innerException = action.ShouldThrow <AggregateException>()
                                                           .WithInnerException <DataServiceQueryException>()
                                                           .And.InnerException as DataServiceQueryException;

                //Check for 'Not Found' code.
                innerException.Response.StatusCode.Should().Be(404);
            }
        }
        public void When_Updating_Property_On_Client_With_OnPropertyChanged_Then_That_Property_Must_Be_Updated_On_Server()
        {
            var prods = Any.Products().ToArray();
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(prods.AsQueryable())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;

                Product prod1 = products.CurrentPage[1] as Product;
                string newCategory = Any.AlphanumericString();
                prod1.Category = newCategory;
                // Calling 'OnPropertyChanged' for 'Category'
                // So 'Category' property must not be updated on the server side.
                prod1.CallOnPropertyChanged("Category");
                prod1.UpdateAsync().Wait();

                var updatedProducts = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(5);
                (updatedProducts.CurrentPage[1] as Product).Category.Should().Be(newCategory, "The 'Product.Category' Property should be changed");
            }
        }
        public void When_Updating_Property_On_Client_Without_OnPropertyChanged_Then_That_Property_Must_Not_Be_Updated_On_Server()
        {
            var prods = Any.Products().ToArray();
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(prods.AsQueryable())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;

                Product prod2 = products.CurrentPage[2] as Product;
                string newName = Any.CompanyName();
                prod2.Name = newName;
                // Skip calling 'OnPropertyChanged' for 'Name'
                // So 'Name' property must not be updated on the server side.
                //prod2.CallOnPropertyChanged("Name");
                prod2.UpdateAsync().Wait();

                var updatedProducts = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(5);
                (updatedProducts.CurrentPage[2] as Product).Name.Should().NotBe(newName, "The 'Product.Name' Property should not be changed");
            }
        }
        public void When_One_Unsuccessful_And_Successful_Queries_Are_Batched_Then_Two_Corresponding_BatchResults_Are_Failure_Success()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(8))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                IReadOnlyQueryableSet <Product> productsSet = new ReadOnlyQueryableSet <Product>(
                    context.CreateQuery <Product>("SomeRandomEntitySet"),
                    context);
                IReadOnlyQueryableSet <Product> prod3 = new ReadOnlyQueryableSet <Product>(
                    context.CreateQuery <Product>("Products(3)"),
                    context);

                var batchResult = context.ExecuteBatchAsync(productsSet, prod3).Result;
                batchResult.Count().Should().Be(2);

                batchResult[0].FailureResult.
                Should().BeOfType <DataServiceClientException>().
                Which.
                StatusCode.Should().Be(404);

                batchResult[1].SuccessResult.
                CurrentPage.Count.Should().Be(1);
                batchResult[1].SuccessResult.
                CurrentPage[0].
                Should().BeOfType <Product>().
                Which.
                Id.Should().Be(3);
            }
        }
        public void When_Querying_For_Series_Of_NavigationProperties_Then_Each_Query_Return_Expected_EntityType_Or_Collection()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithSuppliedProducts(Any.Suppliers())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var dQuery = context.CreateQuery<SuppliedProduct>("/" + "SuppliedProducts");
                IReadOnlyQueryableSet<SuppliedProduct> productSet = new ReadOnlyQueryableSet<SuppliedProduct>(dQuery, context);
                var products = productSet.Expand(p => p.Supplier).ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(25);

                var suppliedProduct = products.CurrentPage.RandomElement() as SuppliedProduct;
                string supplierPath = suppliedProduct.GetPath("Supplier");
                var supplierQuery = context.CreateQuery<Supplier>(supplierPath);
                IReadOnlyQueryableSet<Supplier> supplierSet = new ReadOnlyQueryableSet<Supplier>(supplierQuery, context);
                //TODO - Unable to expand a collection
                var supplier = supplierSet.Expand(s => s.Products).ExecuteSingleAsync().Result;
                suppliedProduct.Supplier.Id.Should().Be(supplier.Id);

                // Hence querying for the SuppliedProducts
                string productsPath = supplier.GetPath("Products");
                dQuery = context.CreateQuery<SuppliedProduct>(productsPath);
                productSet = new ReadOnlyQueryableSet<SuppliedProduct>(dQuery, context);
                products = productSet.ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(5);
                products.CurrentPage.Should().Contain(p => p.Id == suppliedProduct.Id);
            }
        }
        public void When_Updating_Binary_Primitive_Property_On_Client_Then_That_Property_Must_Be_Updated_On_Server()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithSuppliedProducts(Any.Suppliers())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery    = context.CreateQuery <Supplier>("/" + "Suppliers");
                var suppliers = context.ExecuteAsync <Supplier, ISupplier>(dQuery).Result;
                suppliers.CurrentPage.Count.Should().Be(5);

                var supplier = suppliers.CurrentPage[2] as Supplier;
                // make sure that the binary primitive property is serialized
                supplier.Blob.Should().NotBeNullOrEmpty();

                // lets update the binary primitive property
                var newBlob = Any.Sequence <byte>(x => Any.Byte()).ToArray();
                supplier.Blob = newBlob;
                supplier.CallOnPropertyChanged("Blob");
                supplier.UpdateAsync().Wait();

                var updatedsuppliers = context.ExecuteAsync <Supplier, ISupplier>(dQuery).Result;
                updatedsuppliers.CurrentPage.Count.Should().Be(5);
                updatedsuppliers.CurrentPage[2].Blob.Should().BeEquivalentTo(newBlob);
            }
        }
        public void When_Two_Successful_Queries_Are_Batched_Then_Two_BatchResults_Are_Successful()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(8))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                IReadOnlyQueryableSet <Product> productsSet = new ReadOnlyQueryableSet <Product>(
                    context.CreateQuery <Product>("Products"),
                    context);
                IReadOnlyQueryableSet <Product> prod3 = new ReadOnlyQueryableSet <Product>(
                    context.CreateQuery <Product>("Products(3)"),
                    context);

                var batchResult = context.ExecuteBatchAsync(productsSet, prod3).Result;
                batchResult.Count().Should().Be(2);

                foreach (var result in batchResult)
                {
                    result.SuccessResult.Should().NotBeNull();
                    result.FailureResult.Should().BeNull();
                }

                var products = batchResult[0].SuccessResult;
                products.CurrentPage.Count.Should().Be(8);

                products = batchResult[1].SuccessResult;
                products.CurrentPage.Count.Should().Be(1);
                (products.CurrentPage[0] as Product).Id.Should().Be(3);
            }
        }
        public void When_Query_Matches_Multiple_EntityTypes_Then_Using_ExecuteSingleAsync_Must_Fail()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(8))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                IReadOnlyQueryableSet<IProduct> readOnlySet = new ReadOnlyQueryableSet<IProduct>(dQuery, context);

                //Query using linq
                var linqQuery = from prod in readOnlySet
                                orderby prod.Category
                                select prod;

                var action = new Action(() =>
                {
                    var product = linqQuery.ExecuteSingleAsync().Result;
                });

                action.ShouldThrow<AggregateException>().
                    WithInnerException<InvalidOperationException>().
                    WithInnerMessage("Sequence contains more than one element");
            }
        }
        public void When_Updating_GeoSpatial_Primitive_Property_On_Client_Then_That_Property_Must_Be_Updated_On_Server()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithSuppliedProducts(Any.Suppliers())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery    = context.CreateQuery <Supplier>("/" + "Suppliers");
                var suppliers = context.ExecuteAsync <Supplier, ISupplier>(dQuery).Result;
                suppliers.CurrentPage.Count.Should().Be(5);

                var supplier = suppliers.CurrentPage[2] as Supplier;
                // make sure that the binary primitive property is serialized
                supplier.Location.Should().NotBeNull();

                // lets update the geospatial primitive property
                var newLocation = GeographyPoint.Create(Any.Double(-90, 90), Any.Double(-180, 180));
                supplier.Location = newLocation;
                supplier.CallOnPropertyChanged("Location");

                // Bug - Location is a property of primitive type - "Microsoft.Spatial.GeographyPoint".
                // Its underlying type is "Microsoft.Data.Spatial.GeographyPointImplementation".
                // In the ASP.Net stack when deserializing the 'Location' property InvalidCastException is thrown.
                supplier.UpdateAsync().Wait();

                var updatedsuppliers = context.ExecuteAsync <Supplier, ISupplier>(dQuery).Result;
                updatedsuppliers.CurrentPage.Count.Should().Be(5);
                updatedsuppliers.CurrentPage[2].Location.Should().Be(newLocation);
            }
        }
        public void When_Updating_Property_On_Client_With_OnPropertyChanged_Then_That_Property_Must_Be_Updated_On_Server()
        {
            var prods = Any.Products().ToArray();

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(prods.AsQueryable())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery   = context.CreateQuery <Product>("/" + "Products");
                var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;

                Product prod1       = products.CurrentPage[1] as Product;
                string  newCategory = Any.AlphanumericString();
                prod1.Category = newCategory;
                // Calling 'OnPropertyChanged' for 'Category'
                // So 'Category' property must not be updated on the server side.
                prod1.CallOnPropertyChanged("Category");
                prod1.UpdateAsync().Wait();

                var updatedProducts = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(5);
                (updatedProducts.CurrentPage[1] as Product).Category.Should().Be(newCategory, "The 'Product.Category' Property should be changed");
            }
        }
        public void When_Using_OrderBy_Clause_Then_Returned_Sequence_Is_Sorted_Ascending()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(8))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                IReadOnlyQueryableSet<IProduct> readOnlySet = new ReadOnlyQueryableSet<IProduct>(dQuery, context);

                //Query directly
                var products = readOnlySet.OrderBy(p => p.Name).ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(8);
                products.CurrentPage.Should().BeInAscendingOrder(p => p.Name);

                //Query using linq
                var linqQuery = from prod in readOnlySet
                                orderby prod.Category
                                select prod;
                products = linqQuery.ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(8);
                products.CurrentPage.Should().BeInAscendingOrder(p => p.Category);
            }
        }
        public void When_Updating_Property_On_Client_Without_OnPropertyChanged_Then_That_Property_Must_Not_Be_Updated_On_Server()
        {
            var prods = Any.Products().ToArray();

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(prods.AsQueryable())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery   = context.CreateQuery <Product>("/" + "Products");
                var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;

                Product prod2   = products.CurrentPage[2] as Product;
                string  newName = Any.CompanyName();
                prod2.Name = newName;
                // Skip calling 'OnPropertyChanged' for 'Name'
                // So 'Name' property must not be updated on the server side.
                //prod2.CallOnPropertyChanged("Name");
                prod2.UpdateAsync().Wait();

                var updatedProducts = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(5);
                (updatedProducts.CurrentPage[2] as Product).Name.Should().NotBe(newName, "The 'Product.Name' Property should not be changed");
            }
        }
        public void When_Querying_For_NonExistent_EntitySet_Then_Throw_DataServiceQueryException_With_NotFound_Status_Code()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var action = new Action(() =>
                {
                    var dQuery = context.CreateQuery<Product>("/" + "RandomEntitySet");
                    var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                });

                //check for AggregateException with DataServiceQueryException as InnerException.
                //Also retrieve the DataServiceQueryException InnerException.
                DataServiceQueryException innerException = action.ShouldThrow<AggregateException>()
                    .WithInnerException<DataServiceQueryException>()
                    .And.InnerException as DataServiceQueryException;

                //Check for 'Not Found' code.
                innerException.Response.StatusCode.Should().Be(404);
            }
        }
        public void When_Adding_EntityType_With_All_Properties_Then_It_Must_Be_Added_To_Server_With_All_Properties()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery = context.CreateQuery <Product>("/" + "Products");

                var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                products.CurrentPage.Count.Should().Be(5);

                var newProduct = new Product();
                newProduct.Id       = 6;
                newProduct.Name     = Any.CompanyName();
                newProduct.Price    = Any.Decimal();
                newProduct.Category = Any.AlphanumericString();
                newProduct.CallOnPropertyChanged("Id");
                newProduct.CallOnPropertyChanged("Name");
                newProduct.CallOnPropertyChanged("Price");
                newProduct.CallOnPropertyChanged("Category");

                context.AddObject("Products", newProduct);
                context.SaveChangesAsync().Wait();

                var updatedProducts = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(6);
                updatedProducts.CurrentPage[5].Should().BeSameAs(newProduct);
            }
        }
Example #16
0
        public void When_Query_Matches_Multiple_EntityTypes_Then_Using_ExecuteSingleAsync_Must_Fail()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(8))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");
                IReadOnlyQueryableSet <IProduct> readOnlySet = new ReadOnlyQueryableSet <IProduct>(dQuery, context);

                //Query using linq
                var linqQuery = from prod in readOnlySet
                                orderby prod.Category
                                select prod;

                var action = new Action(() =>
                {
                    var product = linqQuery.ExecuteSingleAsync().Result;
                });

                action.ShouldThrow <AggregateException>().
                WithInnerException <InvalidOperationException>().
                WithInnerMessage("Sequence contains more than one element");
            }
        }
        public void When_Adding_EntityType_With_All_Properties_Then_It_Must_Be_Added_To_Server_With_All_Properties()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery = context.CreateQuery<Product>("/" + "Products");

                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                products.CurrentPage.Count.Should().Be(5);

                var newProduct = new Product();
                newProduct.Id = 6;
                newProduct.Name = Any.CompanyName();
                newProduct.Price = Any.Decimal();
                newProduct.Category = Any.AlphanumericString();
                newProduct.CallOnPropertyChanged("Id");
                newProduct.CallOnPropertyChanged("Name");
                newProduct.CallOnPropertyChanged("Price");
                newProduct.CallOnPropertyChanged("Category");

                context.AddObject("Products", newProduct);
                context.SaveChangesAsync().Wait();

                var updatedProducts = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(6);
                updatedProducts.CurrentPage[5].Should().BeSameAs(newProduct);
            }
        }
        public void When_Two_Unsuccessful_Queries_Are_Batched_Then_Two_BatchResults_Are_Failures()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(8))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                IReadOnlyQueryableSet <Product> productsSet = new ReadOnlyQueryableSet <Product>(
                    context.CreateQuery <Product>("SomeRandomEntitySet"),
                    context);
                IReadOnlyQueryableSet <Product> prod10 = new ReadOnlyQueryableSet <Product>(
                    context.CreateQuery <Product>("Products(10)"),
                    context);

                var batchResult = context.ExecuteBatchAsync(productsSet, prod10).Result;
                batchResult.Count().Should().Be(2);

                foreach (var result in batchResult)
                {
                    result.SuccessResult.Should().BeNull();
                    result.FailureResult.Should().NotBeNull();

                    result.FailureResult.
                    Should().BeOfType <DataServiceClientException>().
                    Which.
                    StatusCode.Should().Be(404);
                }
            }
        }
        public void When_Executing_Function_On_Client_Then_Function_Is_Called_On_Server_And_Returns_Expected_EntityCollection()
        {
            var products               = Any.Products().ToList();
            var relatedProducts        = products.RandomSequence(2).ToList();
            var productRatingAgentMock = new Mock <ODataV4TestService.Agents.IProductAgent>(MockBehavior.Strict);

            productRatingAgentMock.Setup(p => p.RelatedProducts()).Returns(relatedProducts.AsQueryable());

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(products.AsQueryable(), productRatingAgentMock.Object)
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                Uri requestUri = new Uri(scenario.GetBaseAddress() + "/Products(2)/ODataV4TestService.Models.RelatedProducts");
                var results    = context.ExecuteAsync <Product>(requestUri, "GET", false,
                                                                new OperationParameter[] { new UriOperationParameter("start", DateTimeOffset.Now),
                                                                                           new UriOperationParameter("end", DateTimeOffset.UtcNow) }).Result.ToList();

                results.Count.Should().Be(2);
                results[0].Id.Should().Be(relatedProducts[0].Id);
                results[1].Name.Should().Be(relatedProducts[1].Name);
            }
        }
        public void When_Updating_ComplexType_Property_On_Client_Then_That_Property_Must_Be_Updated_On_Server()
        {
            var prods = Any.Products().ToArray();

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(prods.AsQueryable())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var     dQuery = context.CreateQuery <Product>("/" + "Products(3)");
                Product prod3  = context.ExecuteSingleAsync <Product, IProduct>(dQuery).Result as Product;

                var newComment = new Description {
                    Title = Any.AlphanumericString(), Details = Any.AlphanumericString()
                };
                newComment.SetContainer(() => new Tuple <EntityBase, string>(prod3, "Comment"));

                prod3.Comment = newComment;
                prod3.CallOnPropertyChanged("Comment");
                prod3.UpdateAsync().Wait();

                Product updatedProd3 = context.ExecuteSingleAsync <Product, IProduct>(dQuery).Result as Product;
                updatedProd3.Comment.Details.Should().Be(newComment.Details);
                updatedProd3.Comment.Title.Should().Be(newComment.Title);
            }
        }
Example #21
0
        public void When_Using_Orderby_Clause_After_Projections_Then_Throw_NotSupportedException()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithSuppliedProducts(Any.Suppliers())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var dQuery = context.CreateQuery <SuppliedProduct>("/" + "SuppliedProducts");
                IReadOnlyQueryableSet <SuppliedProduct> prodSet = new ReadOnlyQueryableSet <SuppliedProduct>(dQuery, context);

                var linqQuery =
                    from prod in prodSet
                    where prod.Id < 400
                    select new { supplier = prod.Supplier, prod } into x
                orderby x.supplier.Name
                select x;

                var action = new Action(() =>
                {
                    var products = linqQuery.ExecuteAsync().Result;
                });

                action.ShouldThrow <AggregateException>().
                WithInnerException <NotSupportedException>().
                WithInnerMessage("The orderby query option cannot be specified after the select query option.");
            }
        }
Example #22
0
        public void When_Querying_For_Series_Of_NavigationProperties_Then_Each_Query_Return_Expected_EntityType_Or_Collection()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithSuppliedProducts(Any.Suppliers())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var dQuery = context.CreateQuery <SuppliedProduct>("/" + "SuppliedProducts");
                IReadOnlyQueryableSet <SuppliedProduct> productSet = new ReadOnlyQueryableSet <SuppliedProduct>(dQuery, context);
                var products = productSet.Expand(p => p.Supplier).ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(25);

                var    suppliedProduct = products.CurrentPage.RandomElement() as SuppliedProduct;
                string supplierPath    = suppliedProduct.GetPath("Supplier");
                var    supplierQuery   = context.CreateQuery <Supplier>(supplierPath);
                IReadOnlyQueryableSet <Supplier> supplierSet = new ReadOnlyQueryableSet <Supplier>(supplierQuery, context);
                //TODO - Unable to expand a collection
                var supplier = supplierSet.Expand(s => s.Products).ExecuteSingleAsync().Result;
                suppliedProduct.Supplier.Id.Should().Be(supplier.Id);

                // Hence querying for the SuppliedProducts
                string productsPath = supplier.GetPath("Products");
                dQuery     = context.CreateQuery <SuppliedProduct>(productsPath);
                productSet = new ReadOnlyQueryableSet <SuppliedProduct>(dQuery, context);
                products   = productSet.ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(5);
                products.CurrentPage.Should().Contain(p => p.Id == suppliedProduct.Id);
            }
        }
        public void When_Two_Successful_Queries_Are_Batched_Then_Two_BatchResults_Are_Successful()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(8))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                IReadOnlyQueryableSet<Product> productsSet = new ReadOnlyQueryableSet<Product>(
                                                                    context.CreateQuery<Product>("Products"),
                                                                    context);
                IReadOnlyQueryableSet<Product> prod3 = new ReadOnlyQueryableSet<Product>(
                                                                    context.CreateQuery<Product>("Products(3)"),
                                                                    context);

                var batchResult = context.ExecuteBatchAsync(productsSet, prod3).Result;
                batchResult.Count().Should().Be(2);

                foreach (var result in batchResult)
                {
                    result.SuccessResult.Should().NotBeNull();
                    result.FailureResult.Should().BeNull();
                }

                var products = batchResult[0].SuccessResult;
                products.CurrentPage.Count.Should().Be(8);

                products = batchResult[1].SuccessResult;
                products.CurrentPage.Count.Should().Be(1);
                (products.CurrentPage[0] as Product).Id.Should().Be(3);
            }
        }
        public void When_Two_Unsuccessful_Queries_Are_Batched_Then_Two_BatchResults_Are_Failures()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(8))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                IReadOnlyQueryableSet<Product> productsSet = new ReadOnlyQueryableSet<Product>(
                                                                    context.CreateQuery<Product>("SomeRandomEntitySet"),
                                                                    context);
                IReadOnlyQueryableSet<Product> prod10 = new ReadOnlyQueryableSet<Product>(
                                                                    context.CreateQuery<Product>("Products(10)"),
                                                                    context);

                var batchResult = context.ExecuteBatchAsync(productsSet, prod10).Result;
                batchResult.Count().Should().Be(2);

                foreach (var result in batchResult)
                {
                    result.SuccessResult.Should().BeNull();
                    result.FailureResult.Should().NotBeNull();

                    result.FailureResult.
                    Should().BeOfType<DataServiceClientException>().
                    Which.
                    StatusCode.Should().Be(404);
                }
            }
        }
Example #25
0
        public void When_Using_OrderBy_Clause_Then_Returned_Sequence_Is_Sorted_Ascending()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(8))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");
                IReadOnlyQueryableSet <IProduct> readOnlySet = new ReadOnlyQueryableSet <IProduct>(dQuery, context);

                //Query directly
                var products = readOnlySet.OrderBy(p => p.Name).ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(8);
                products.CurrentPage.Should().BeInAscendingOrder(p => p.Name);

                //Query using linq
                var linqQuery = from prod in readOnlySet
                                orderby prod.Category
                                select prod;
                products = linqQuery.ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(8);
                products.CurrentPage.Should().BeInAscendingOrder(p => p.Category);
            }
        }
        public void When_Querying_For_Non_Existent_EntityType_Then_Throw_Exception()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var action = new Action(() =>
                {
                    //query for a missing product based on the 'Id'
                    var dQuery = context.CreateQuery<Product>("/" + "Products(7)");

                    // this should ideally return null or thrown an exception that reflects 404.
                    Product missingProd = context.ExecuteSingleAsync<Product, IProduct>(dQuery).Result as Product;
                    //Product missingProd = dQuery.Where(p => p.Id == 7).First();
                });

                //check for AggregateException with DataServiceQueryException as InnerException.
                //Also retrieve the DataServiceQueryException InnerException.
                DataServiceQueryException innerException = action.ShouldThrow<AggregateException>()
                    .WithInnerException<DataServiceQueryException>()
                    .And.InnerException as DataServiceQueryException;

                //Check for 'Not Found' code.
                innerException.Response.StatusCode.Should().Be(404);
            }
        }
Example #27
0
        public void When_Querying_For_Non_Existent_EntityType_Then_Throw_Exception()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var action = new Action(() =>
                {
                    //query for a missing product based on the 'Id'
                    var dQuery = context.CreateQuery <Product>("/" + "Products(7)");

                    // this should ideally return null or thrown an exception that reflects 404.
                    Product missingProd = context.ExecuteSingleAsync <Product, IProduct>(dQuery).Result as Product;
                    //Product missingProd = dQuery.Where(p => p.Id == 7).First();
                });

                //check for AggregateException with DataServiceQueryException as InnerException.
                //Also retrieve the DataServiceQueryException InnerException.
                DataServiceQueryException innerException = action.ShouldThrow <AggregateException>()
                                                           .WithInnerException <DataServiceQueryException>()
                                                           .And.InnerException as DataServiceQueryException;

                //Check for 'Not Found' code.
                innerException.Response.StatusCode.Should().Be(404);
            }
        }
        public void When_Querying_For_Existing_EntityType_Then_Return_The_EntityType()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                //query for a single product based on the 'Id'
                var dQuery = context.CreateQuery<Product>("/" + "Products(3)");
                Product prod3 = context.ExecuteSingleAsync<Product, IProduct>(dQuery).Result as Product;
                prod3.Id.Should().Be(3);
            }
        }
Example #29
0
        public void When_Querying_For_Existing_EntityType_Then_Return_The_EntityType()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                //query for a single product based on the 'Id'
                var     dQuery = context.CreateQuery <Product>("/" + "Products(3)");
                Product prod3  = context.ExecuteSingleAsync <Product, IProduct>(dQuery).Result as Product;
                prod3.Id.Should().Be(3);
            }
        }
        public void When_Querying_For_Existing_EntitySet_Then_Return_The_EntitySet()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");

                //query for all the products
                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                products.CurrentPage.Count.Should().Be(5);
                (products.CurrentPage[2] as Product).Id.Should().Be(3);
            }
        }
        public void When_Querying_For_Existing_EntitySet_Using_EntityType_Interface_Then_Return_The_EntitySet()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                IReadOnlyQueryableSet<IProduct> readOnlySet = new ReadOnlyQueryableSet<IProduct>(dQuery, context);

                var products = readOnlySet.ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(5);
                (products.CurrentPage[2] as Product).Id.Should().Be(3);
            }
        }
Example #32
0
        public void When_Querying_For_Existing_EntitySet_Then_Return_The_EntitySet()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");

                //query for all the products
                var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                products.CurrentPage.Count.Should().Be(5);
                (products.CurrentPage[2] as Product).Id.Should().Be(3);
            }
        }
Example #33
0
        public void When_Querying_For_Existing_EntitySet_Using_EntityType_Interface_Then_Return_The_EntitySet()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");
                IReadOnlyQueryableSet <IProduct> readOnlySet = new ReadOnlyQueryableSet <IProduct>(dQuery, context);

                var products = readOnlySet.ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(5);
                (products.CurrentPage[2] as Product).Id.Should().Be(3);
            }
        }
        public void When_Updates_To_Properties_Are_Delayed_Then_They_Must_Be_Updated_After_Calling_SaveChanges()
        {
            var prods = Any.Products().ToArray();

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(prods.AsQueryable())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery   = context.CreateQuery <Product>("/" + "Products");
                var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;

                Product prod1       = products.CurrentPage[1] as Product;
                string  newCategory = Any.AlphanumericString();
                prod1.Category = newCategory;
                prod1.CallOnPropertyChanged("Category");
                var productFetcher = TestRestShallowObjectFetcher.CreateFetcher(context, prod1);
                productFetcher.UpdateAsync(prod1, true).Wait();

                Product prod2   = products.CurrentPage[2] as Product;
                string  newName = Any.CompanyName();
                prod2.Name = newName;
                prod2.CallOnPropertyChanged("Name");
                productFetcher = TestRestShallowObjectFetcher.CreateFetcher(context, prod2);
                productFetcher.UpdateAsync(prod2, true).Wait();

                Product prod3    = products.CurrentPage[3] as Product;
                decimal newPrice = Any.Decimal();
                prod3.Price = newPrice;
                prod3.CallOnPropertyChanged("Price");
                productFetcher = TestRestShallowObjectFetcher.CreateFetcher(context, prod3);
                productFetcher.UpdateAsync(prod3, true).Wait();

                var response = context.SaveChangesAsync().Result;
                response.Count().Should().Be(3);

                // Make sure everything is updated on the server
                var updatedProducts = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(5);
                (updatedProducts.CurrentPage[1] as Product).Category.Should().Be(newCategory);
                (updatedProducts.CurrentPage[2] as Product).Name.Should().Be(newName);
                (updatedProducts.CurrentPage[3] as Product).Price.Should().Be(newPrice);
            }
        }
Example #35
0
        public void When_Using_Filter_Clause_On_Expanded_Navigation_Property_Then_Returned_Sequence_Is_Filtered()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithSuppliedProducts(Any.Suppliers())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var dQuery = context.CreateQuery <SuppliedProduct>("/" + "SuppliedProducts");
                IReadOnlyQueryableSet <ISuppliedProduct> productSet = new ReadOnlyQueryableSet <ISuppliedProduct>(dQuery, context);
                var products = productSet.Expand(p => (p as SuppliedProduct).Supplier).
                               Where(p => p.Supplier.Id == 2).
                               ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(5);
            }
        }
Example #36
0
        public void When_Using_Expand_Clause_On_EntityType_Interface_Then_Resulting_Sequence_Must_Be_Expanded()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithSuppliedProducts(Any.Suppliers())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var dQuery = context.CreateQuery <SuppliedProduct>("/" + "SuppliedProducts");
                IReadOnlyQueryableSet <ISuppliedProduct> productSet = new ReadOnlyQueryableSet <ISuppliedProduct>(dQuery, context);

                var products = productSet.Expand(p => p.Supplier)
                               .ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(25);
                products.CurrentPage.Should().OnlyContain(p => p.Supplier != null);
            }
        }
Example #37
0
        public void When_SkipCount_EqualsTo_EntitySet_Count_Then_Return_EntitySet_With_Zero_Elements()
        {
            int skipCount     = 8;
            int productsCount = 8;

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(productsCount))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");
                IReadOnlyQueryableSet <IProduct> readOnlySet = new ReadOnlyQueryableSet <IProduct>(dQuery, context);

                //skip the top 8 results
                var products = readOnlySet.Skip(skipCount).ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(0);
            }
        }
        public void When_Deleting_EntityType_On_Client_Then_It_Should_Must_Be_Deleted_On_Server()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products())
                       .Start())
            {
                var context  = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery   = context.CreateQuery <Product>("/" + "Products");
                var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;

                Product prod1 = products.CurrentPage[1] as Product;
                prod1.Id.Should().Be(2);
                prod1.DeleteAsync().Wait();

                var updatedProducts = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(4);
                (updatedProducts.CurrentPage[1] as Product).Id.Should().Be(3);
            }
        }
Example #39
0
        public void When_Query_Matches_One_EntityType_Then_Using_ExecuteSingleAsync_Must_Succeed()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(8))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");
                IReadOnlyQueryableSet <IProduct> readOnlySet = new ReadOnlyQueryableSet <IProduct>(dQuery, context);

                //Query using linq
                var linqQuery = from prod in readOnlySet
                                where prod.Id == 2
                                select prod;

                var product = linqQuery.ExecuteSingleAsync().Result;
                product.Id.Should().Be(2);
            }
        }
Example #40
0
        public void When_TakeCount_GreaterThan_EntitySet_Count_Then_Return_EntitySet_With_EntitySet_Count()
        {
            int takeCount     = 10;
            int productsCount = 8;

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(productsCount))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");
                IReadOnlyQueryableSet <IProduct> readOnlySet = new ReadOnlyQueryableSet <IProduct>(dQuery, context);

                //take the top 10 results
                var products = readOnlySet.Take(takeCount).ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(productsCount);
                (products.CurrentPage[7] as Product).Id.Should().Be(8);
            }
        }
        public void When_Query_Matches_One_EntityType_Then_Using_ExecuteSingleAsync_Must_Succeed()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(8))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                IReadOnlyQueryableSet<IProduct> readOnlySet = new ReadOnlyQueryableSet<IProduct>(dQuery, context);

                //Query using linq
                var linqQuery = from prod in readOnlySet
                                where prod.Id == 2
                                select prod;

                var product = linqQuery.ExecuteSingleAsync().Result;
                product.Id.Should().Be(2);
            }
        }
        public void When_PageSize_GreaterThan_EntitySet_Count_Then_Return_PagedCollection_With_Single_Page()
        {
            int pageSize = 10;
            int productsCount = Any.Int(1, pageSize - 1);
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(productsCount))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;

                products.MorePagesAvailable.Should().BeFalse();
                products.CurrentPage.Count.Should().Be(productsCount);

                //When no more pages are available 'GetNextPageAsync' should return null
                products.GetNextPageAsync().Result.Should().BeNull();
            }
        }
        public void When_Executing_Action_On_Client_Then_Action_Is_Called_On_Server_With_Correct_Parameters()
        {
            var rating = Any.Int();
            var productRatingAgentMock = new Mock<ODataV4TestService.Agents.IProductAgent>(MockBehavior.Strict);
            productRatingAgentMock.Setup(p => p.AddRating(It.Is<ODataV4TestService.Models.ProductRating>(r => r.ProductId == 2 && r.Rating == rating)));

            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(), productRatingAgentMock.Object)
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                Uri requestUri = new Uri(scenario.GetBaseAddress() + "/Products(2)/ODataV4TestService.Models.Rate");
                context.ExecuteAsync(requestUri, "POST",
                new OperationParameter[] { new BodyOperationParameter("Rating", rating) }).Wait();

                productRatingAgentMock.Verify(p => p.AddRating(It.IsAny<ODataV4TestService.Models.ProductRating>()), Times.Once);
            }
        }
        public void When_Executing_Action_On_Client_Then_Action_Is_Called_On_Server_With_Correct_Parameters()
        {
            var rating = Any.Int();
            var productRatingAgentMock = new Mock <ODataV4TestService.Agents.IProductAgent>(MockBehavior.Strict);

            productRatingAgentMock.Setup(p => p.AddRating(It.Is <ODataV4TestService.Models.ProductRating>(r => r.ProductId == 2 && r.Rating == rating)));

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(), productRatingAgentMock.Object)
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                Uri requestUri = new Uri(scenario.GetBaseAddress() + "/Products(2)/ODataV4TestService.Models.Rate");
                context.ExecuteAsync(requestUri, "POST",
                                     new OperationParameter[] { new BodyOperationParameter("Rating", rating) }).Wait();

                productRatingAgentMock.Verify(p => p.AddRating(It.IsAny <ODataV4TestService.Models.ProductRating>()), Times.Once);
            }
        }
        public void When_PageSize_EqualsTo_EntitySet_Count_Then_Return_PagedCollection_With_Single_Page()
        {
            int productsCount = 10;
            int pageSize      = 10;

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products(productsCount))
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");
                IPagedCollection products = (IPagedCollection)context.ExecuteAsync <Product, IProduct>(dQuery).Result;

                products.MorePagesAvailable.Should().BeFalse();
                products.CurrentPage.Count.Should().Be(pageSize);

                //When no more pages are available 'GetNextPageAsync' should return null
                products.GetNextPageAsync().Result.Should().BeNull();
            }
        }
        public void When_Updates_To_Entities_Are_Batched_Then_Entities_Must_Be_Updated_On_Server()
        {
            var prods = Any.Products().ToArray();

            using (var scenario =
                       new ODataScenario()
                       .WithProducts(prods.AsQueryable())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery   = context.CreateQuery <Product>("/" + "Products");
                var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;

                Product prod1       = products.CurrentPage[1] as Product;
                string  newCategory = Any.AlphanumericString();
                prod1.Category = newCategory;
                prod1.CallOnPropertyChanged("Category");

                Product prod2   = products.CurrentPage[2] as Product;
                string  newName = Any.CompanyName();
                prod2.Name = newName;
                prod2.CallOnPropertyChanged("Name");

                Product prod3    = products.CurrentPage[3] as Product;
                decimal newPrice = Any.Decimal();
                prod3.Price = newPrice;
                prod3.CallOnPropertyChanged("Price");

                var response = context.SaveChangesAsync(SaveChangesOptions.BatchWithSingleChangeset).Result;
                response.Count().Should().Be(3);
                response.IsBatchResponse.Should().BeTrue();

                var updatedProducts = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(5);
                (updatedProducts.CurrentPage[1] as Product).Category.Should().Be(newCategory);
                (updatedProducts.CurrentPage[2] as Product).Name.Should().Be(newName);
                (updatedProducts.CurrentPage[3] as Product).Price.Should().Be(newPrice);
            }
        }
        public void When_Adding_EntityType_With_Partial_Properties_Then_It_Must_Be_Added_To_Server_With_Partial_Properties()
        {
            using (var scenario =
                       new ODataScenario()
                       .WithProducts(Any.Products())
                       .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery  = context.CreateQuery <Product>("/" + "Products");

                var products = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                products.CurrentPage.Count.Should().Be(5);

                var    newProduct = new Product();
                string newName    = Any.CompanyName();
                newProduct.Id       = 6;
                newProduct.Name     = newName;
                newProduct.Price    = Any.Decimal();
                newProduct.Category = Any.AlphanumericString();

                // calling 'OnPropertyChanged' only for 'Id' and 'Name' properties
                newProduct.CallOnPropertyChanged("Id");
                newProduct.CallOnPropertyChanged("Name");

                context.AddObject("Products", newProduct);
                context.SaveChangesAsync().Wait();

                var updatedProducts = context.ExecuteAsync <Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(6);

                // the 'Id' and 'Name' properties must be set
                updatedProducts.CurrentPage[5].Id.Should().Be(6);
                updatedProducts.CurrentPage[5].Name.Should().Be(newName);

                // the 'Price' and 'Category' properties must not be set
                updatedProducts.CurrentPage[5].Price.Should().Be(0);
                updatedProducts.CurrentPage[5].Category.Should().BeNull();
            }
        }
        public void When_Adding_EntityType_With_Partial_Properties_Then_It_Must_Be_Added_To_Server_With_Partial_Properties()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");

                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                products.CurrentPage.Count.Should().Be(5);

                var newProduct = new Product();
                string newName = Any.CompanyName();
                newProduct.Id = 6;
                newProduct.Name = newName;
                newProduct.Price = Any.Decimal();
                newProduct.Category = Any.AlphanumericString();

                // calling 'OnPropertyChanged' only for 'Id' and 'Name' properties
                newProduct.CallOnPropertyChanged("Id");
                newProduct.CallOnPropertyChanged("Name");

                context.AddObject("Products", newProduct);
                context.SaveChangesAsync().Wait();

                var updatedProducts = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(6);

                // the 'Id' and 'Name' properties must be set
                updatedProducts.CurrentPage[5].Id.Should().Be(6);
                updatedProducts.CurrentPage[5].Name.Should().Be(newName);

                // the 'Price' and 'Category' properties must not be set
                updatedProducts.CurrentPage[5].Price.Should().Be(0);
                updatedProducts.CurrentPage[5].Category.Should().BeNull();
            }
        }
        public void When_PageSize_LesserThan_EntitySet_Count_Then_Return_PagedCollection_With_Multiple_Pages()
        {
            int pageSize = 10;
            int productsCount = Any.Int(pageSize + 1, 50);
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(productsCount))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                int totalPagesCount = 0;

                while (products.MorePagesAvailable)
                {
                    totalPagesCount++;
                    products.CurrentPage.Count.Should().Be(pageSize);
                    products = products.GetNextPageAsync().Result;
                }

                // 'productsCount' is divisible by 'pageSize'.
                // Then the last page has 'pageSize' elements in it.
                if (productsCount % pageSize == 0)
                {
                    totalPagesCount.Should().Be((productsCount / pageSize) - 1);
                    products.CurrentPage.Count.Should().Be(pageSize);
                }
                else
                {
                    totalPagesCount.Should().Be(productsCount / pageSize);
                    products.CurrentPage.Count.Should().Be(productsCount % pageSize);
                }

                //When no more pages are available 'GetNextPageAsync' should return null
                products.GetNextPageAsync().Result.Should().BeNull();
            }
        }
        public void When_Querying_For_NavigationProperty_Then_Return_Single_Expected_EntityType()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithSuppliedProducts(Any.Suppliers())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var dQuery = context.CreateQuery<SuppliedProduct>("/" + "SuppliedProducts");
                IReadOnlyQueryableSet<SuppliedProduct> productSet = new ReadOnlyQueryableSet<SuppliedProduct>(dQuery, context);
                var products = productSet.Expand(p => p.Supplier).ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(25);

                var suppliedProduct = products.CurrentPage.RandomElement() as SuppliedProduct;
                string supplierPath = suppliedProduct.GetPath("Supplier");
                var supplierQuery = context.CreateQuery<Supplier>(supplierPath);

                IReadOnlyQueryableSet<Supplier> supplierSet = new ReadOnlyQueryableSet<Supplier>(supplierQuery, context);
                var supplier = supplierSet.ExecuteSingleAsync().Result;
                suppliedProduct.Supplier.Id.Should().Be(supplier.Id);
            }
        }
        public void When_Executing_Function_On_Client_Then_Function_Is_Called_On_Server_And_Returns_Expected_EntityType()
        {
            var products = Any.Products().ToList();
            var bestProduct = products.RandomElement();
            var productRatingAgentMock = new Mock<ODataV4TestService.Agents.IProductAgent>(MockBehavior.Strict);
            productRatingAgentMock.Setup(p => p.GetBest()).Returns(bestProduct);

            using (var scenario =
                    new ODataScenario()
                        .WithProducts(products.AsQueryable(), productRatingAgentMock.Object)
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                Uri requestUri = new Uri(scenario.GetBaseAddress() + "/Products/ODataV4TestService.Models.Best");
                var bestProducts = context.ExecuteAsync<Product>(requestUri, "GET", true,
                new OperationParameter[] { }).Result.ToList();

                bestProducts.Count().Should().Be(1);
                bestProducts[0].Id.Should().Be(bestProduct.Id);
                bestProducts[0].Name.Should().Be(bestProduct.Name);
            }
        }
        public void When_Querying_For_NavigationPropertyCollection_Then_Return_Expected_EntityTypeCollection()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithSuppliedProducts(Any.Suppliers())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var dQuery = context.CreateQuery<Supplier>("/" + "Suppliers");
                IReadOnlyQueryableSet<Supplier> supplierSet = new ReadOnlyQueryableSet<Supplier>(dQuery, context);
                var suppliers = supplierSet.ExecuteAsync().Result;
                suppliers.CurrentPage.Count.Should().Be(5);

                var supplier = suppliers.CurrentPage.RandomElement();
                string productsPath = supplier.GetPath("Products");
                var dQueryProds = context.CreateQuery<SuppliedProduct>(productsPath);
                var productSet = new ReadOnlyQueryableSet<SuppliedProduct>(dQueryProds, context);

                var products = productSet.ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(5);
                products.CurrentPage.Should().Contain(p => p.SupplierId == supplier.Id);
            }
        }
        public void When_Executing_Function_On_Client_Then_Function_Is_Called_On_Server_And_Returns_Expected_EntityCollection()
        {
            var products = Any.Products().ToList();
            var relatedProducts = products.RandomSequence(2).ToList();
            var productRatingAgentMock = new Mock<ODataV4TestService.Agents.IProductAgent>(MockBehavior.Strict);
            productRatingAgentMock.Setup(p => p.RelatedProducts()).Returns(relatedProducts.AsQueryable());

            using (var scenario =
                    new ODataScenario()
                        .WithProducts(products.AsQueryable(), productRatingAgentMock.Object)
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                Uri requestUri = new Uri(scenario.GetBaseAddress() + "/Products(2)/ODataV4TestService.Models.RelatedProducts");
                var results = context.ExecuteAsync<Product>(requestUri, "GET", false,
                new OperationParameter[] {  new UriOperationParameter("start", DateTimeOffset.Now),
                                            new UriOperationParameter("end", DateTimeOffset.UtcNow) }).Result.ToList();

                results.Count.Should().Be(2);
                results[0].Id.Should().Be(relatedProducts[0].Id);
                results[1].Name.Should().Be(relatedProducts[1].Name);
            }
        }
        public void When_One_Unsuccessful_And_Successful_Queries_Are_Batched_Then_Two_Corresponding_BatchResults_Are_Failure_Success()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(8))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                IReadOnlyQueryableSet<Product> productsSet = new ReadOnlyQueryableSet<Product>(
                                                                    context.CreateQuery<Product>("SomeRandomEntitySet"),
                                                                    context);
                IReadOnlyQueryableSet<Product> prod3 = new ReadOnlyQueryableSet<Product>(
                                                                    context.CreateQuery<Product>("Products(3)"),
                                                                    context);

                var batchResult = context.ExecuteBatchAsync(productsSet, prod3).Result;
                batchResult.Count().Should().Be(2);

                batchResult[0].FailureResult.
                    Should().BeOfType<DataServiceClientException>().
                    Which.
                    StatusCode.Should().Be(404);

                batchResult[1].SuccessResult.
                    CurrentPage.Count.Should().Be(1);
                batchResult[1].SuccessResult.
                    CurrentPage[0].
                    Should().BeOfType<Product>().
                    Which.
                    Id.Should().Be(3);
            }
        }
        public void When_TakeCount_EqualsTo_EntitySet_Count_Then_Return_EntitySet_With_TakeCount()
        {
            int takeCount = 8;
            int productsCount = 8;
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products(productsCount))
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                IReadOnlyQueryableSet<IProduct> readOnlySet = new ReadOnlyQueryableSet<IProduct>(dQuery, context);

                //take the top 10 results
                var products = readOnlySet.Take(takeCount).ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(takeCount);
                (products.CurrentPage[7] as Product).Id.Should().Be(8);
            }
        }
        public void When_Updates_To_Entities_Are_Batched_Then_Entities_Must_Be_Updated_On_Server()
        {
            var prods = Any.Products().ToArray();
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(prods.AsQueryable())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;

                Product prod1 = products.CurrentPage[1] as Product;
                string newCategory = Any.AlphanumericString();
                prod1.Category = newCategory;
                prod1.CallOnPropertyChanged("Category");

                Product prod2 = products.CurrentPage[2] as Product;
                string newName = Any.CompanyName();
                prod2.Name = newName;
                prod2.CallOnPropertyChanged("Name");

                Product prod3 = products.CurrentPage[3] as Product;
                decimal newPrice = Any.Decimal();
                prod3.Price = newPrice;
                prod3.CallOnPropertyChanged("Price");

                var response = context.SaveChangesAsync(SaveChangesOptions.BatchWithSingleChangeset).Result;
                response.Count().Should().Be(3);
                response.IsBatchResponse.Should().BeTrue();

                var updatedProducts = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(5);
                (updatedProducts.CurrentPage[1] as Product).Category.Should().Be(newCategory);
                (updatedProducts.CurrentPage[2] as Product).Name.Should().Be(newName);
                (updatedProducts.CurrentPage[3] as Product).Price.Should().Be(newPrice);
            }
        }
        public void When_Using_Expand_Clause_On_EntityType_Interface_Then_Resulting_Sequence_Must_Be_Expanded()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithSuppliedProducts(Any.Suppliers())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());

                var dQuery = context.CreateQuery<SuppliedProduct>("/" + "SuppliedProducts");
                IReadOnlyQueryableSet<ISuppliedProduct> productSet = new ReadOnlyQueryableSet<ISuppliedProduct>(dQuery, context);

                var products = productSet.Expand(p => p.Supplier)
                    .ExecuteAsync().Result;
                products.CurrentPage.Count.Should().Be(25);
                products.CurrentPage.Should().OnlyContain(p => p.Supplier != null);
            }
        }
        public void When_Updating_GeoSpatial_Primitive_Property_On_Client_Then_That_Property_Must_Be_Updated_On_Server()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithSuppliedProducts(Any.Suppliers())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery = context.CreateQuery<Supplier>("/" + "Suppliers");
                var suppliers = context.ExecuteAsync<Supplier, ISupplier>(dQuery).Result;
                suppliers.CurrentPage.Count.Should().Be(5);

                var supplier = suppliers.CurrentPage[2] as Supplier;
                // make sure that the binary primitive property is serialized
                supplier.Location.Should().NotBeNull();

                // lets update the geospatial primitive property
                var newLocation = GeographyPoint.Create(Any.Double(-90, 90), Any.Double(-180, 180));
                supplier.Location = newLocation;
                supplier.CallOnPropertyChanged("Location");

                // Bug - Location is a property of primitive type - "Microsoft.Spatial.GeographyPoint".
                // Its underlying type is "Microsoft.Data.Spatial.GeographyPointImplementation".
                // In the ASP.Net stack when deserializing the 'Location' property InvalidCastException is thrown.
                supplier.UpdateAsync().Wait();

                var updatedsuppliers = context.ExecuteAsync<Supplier, ISupplier>(dQuery).Result;
                updatedsuppliers.CurrentPage.Count.Should().Be(5);
                updatedsuppliers.CurrentPage[2].Location.Should().Be(newLocation);
            }
        }
        public void When_Updating_Binary_Primitive_Property_On_Client_Then_That_Property_Must_Be_Updated_On_Server()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithSuppliedProducts(Any.Suppliers())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                context.MergeOption = MergeOption.OverwriteChanges;
                var dQuery = context.CreateQuery<Supplier>("/" + "Suppliers");
                var suppliers = context.ExecuteAsync<Supplier, ISupplier>(dQuery).Result;
                suppliers.CurrentPage.Count.Should().Be(5);

                var supplier = suppliers.CurrentPage[2] as Supplier;
                // make sure that the binary primitive property is serialized
                supplier.Blob.Should().NotBeNullOrEmpty();

                // lets update the binary primitive property
                var newBlob = Any.Sequence<byte>(x => Any.Byte()).ToArray();
                supplier.Blob = newBlob;
                supplier.CallOnPropertyChanged("Blob");
                supplier.UpdateAsync().Wait();

                var updatedsuppliers = context.ExecuteAsync<Supplier, ISupplier>(dQuery).Result;
                updatedsuppliers.CurrentPage.Count.Should().Be(5);
                updatedsuppliers.CurrentPage[2].Blob.Should().BeEquivalentTo(newBlob);
            }
        }
        public void When_Deleting_EntityType_On_Client_Then_It_Should_Must_Be_Deleted_On_Server()
        {
            using (var scenario =
                    new ODataScenario()
                        .WithProducts(Any.Products())
                        .Start())
            {
                var context = GetDataServiceContext(scenario.GetBaseAddress());
                var dQuery = context.CreateQuery<Product>("/" + "Products");
                var products = context.ExecuteAsync<Product, IProduct>(dQuery).Result;

                Product prod1 = products.CurrentPage[1] as Product;
                prod1.Id.Should().Be(2);
                prod1.DeleteAsync().Wait();

                var updatedProducts = context.ExecuteAsync<Product, IProduct>(dQuery).Result;
                updatedProducts.CurrentPage.Count.Should().Be(4);
                (updatedProducts.CurrentPage[1] as Product).Id.Should().Be(3);
            }
        }