public async Task RefreshAsync_Succeeds_WhenIdIsNull()
        {
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...");
            await service.SyncContext.InitializeAsync(new MobileServiceLocalStoreMock(), new MobileServiceSyncHandler());

            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            var item = new StringIdType() { String = "what?" };
            await table.RefreshAsync(item);
        }
        public async Task RefreshAsync_Succeeds_WhenIdIsNull()
        {
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp);
            await service.SyncContext.InitializeAsync(new MobileServiceLocalStoreMock(), new MobileServiceSyncHandler());

            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            var item = new StringIdType() { String = "what?" };
            await table.RefreshAsync(item);
        }
        public async Task RefreshAsync_ThrowsInvalidOperationException_WhenIdItemDoesNotExist()
        {
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...");
            await service.SyncContext.InitializeAsync(new MobileServiceLocalStoreMock(), new MobileServiceSyncHandler());

            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            var item = new StringIdType() { Id = "abc" };
            InvalidOperationException ex = await ThrowsAsync<InvalidOperationException>(() => table.RefreshAsync(item));
            Assert.AreEqual(ex.Message, "Item not found in local store.");
        }
        public async Task RefreshAsync_UpdatesItem_WhenItExistsInStore()
        {
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...");
            await service.SyncContext.InitializeAsync(new MobileServiceLocalStoreMock(), new MobileServiceSyncHandler());

            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            // add item to store
            var item = new StringIdType() { String = "what?" };
            await table.InsertAsync(item);

            Assert.IsNotNull(item.Id, "Id must be generated");

            // update it in store
            item.String = "nothing!";
            await table.UpdateAsync(item);

            // read it back into new object
            var refreshed = new StringIdType() { Id = item.Id };
            await table.RefreshAsync(refreshed);

            Assert.AreEqual(refreshed.String, "nothing!");
        }
        public async Task PushAsync_ExecutesThePendingOperations()
        {
            var hijack = new TestHttpHandler();
            var store = new MobileServiceLocalStoreMock();
            hijack.SetResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}");
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            var item = new StringIdType() { Id = "an id", String = "what?" };
            await table.InsertAsync(item);

            Assert.AreEqual(store.TableMap[table.TableName].Count, 1);

            await service.SyncContext.PushAsync();
        }
        public async Task DeleteAsyncWithStringIdTypeAndInvalidStringIdParameter()
        {
            string[] testIdData = IdTestData.InvalidStringIds;

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("{\"id\":\"" + testId + "\",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();
                Exception exception = null;
                try
                {
                    StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                    await table.DeleteAsync(item);
                }
                catch (Exception e)
                {
                    exception = e;
                }

                Assert.IsNotNull(exception);
                Assert.IsTrue(exception.Message.Contains("An id must not contain any control characters or the characters") || 
                              exception.Message.Contains("is longer than the max string id length of 255 characters"));
            }
        }
 public Task FeatureHeaderValidation_TypedTableViaQueryToCollection()
 {
     var obj = new StringIdType { Id = "the id", String = "hey" };
     return this.ValidateFeaturesHeader("TT,TC", true, t => t.Where(a => a.String != null).ToCollectionAsync());
 }
 public Task FeatureHeaderValidation_TypedTableDelete()
 {
     var obj = new StringIdType { Id = "the id", String = "hey" };
     return this.ValidateFeaturesHeader("TT", false, t => t.DeleteAsync(obj));
 }
        /// <summary>
        /// Tests that the second operation on the same item will throw if first operation is in the queue
        /// </summary>
        /// <param name="firstOperation">The operation that was already in queue.</param>
        /// <param name="secondOperation">The operation that came in late but could not be collapsed.</param>
        /// <returns></returns>
        private async Task TestCollapseThrow(Func<IMobileServiceSyncTable<StringIdType>, StringIdType, Task> firstOperation, Func<IMobileServiceSyncTable<StringIdType>, StringIdType, Task> secondOperation)
        {
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...");
            await service.SyncContext.InitializeAsync(new MobileServiceLocalStoreMock(), new MobileServiceSyncHandler());
            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            var item = new StringIdType() { Id = "an id", String = "what?" };
            await firstOperation(table, item);
            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);

            await ThrowsAsync<InvalidOperationException>(() => secondOperation(table, item));

            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);
        }
        public async Task Collapse_DeletesTheError_OnReplace()
        {
            var store = new MobileServiceLocalStoreMock();
            var hijack = new TestHttpHandler();
            MobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

            var item = new StringIdType() { Id = "item1", String = "what?" };

            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());
            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            await table.InsertAsync(item);
            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);

            string id = store.TableMap[MobileServiceLocalSystemTables.OperationQueue].Values.First().Value<string>("id");

            // inject an error to test if it is deleted on collapse
            store.TableMap[MobileServiceLocalSystemTables.SyncErrors] = new Dictionary<string, JObject>() { { id, new JObject() } };

            await table.UpdateAsync(item);
            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);

            // error should be deleted
            Assert.AreEqual(store.TableMap[MobileServiceLocalSystemTables.SyncErrors].Count, 0);
        }
        public async Task DeleteAsync_CancelsAll_WhenInsertIsInQueue()
        {
            var hijack = new TestHttpHandler();
            hijack.SetResponseContent("[{\"id\":\"abc\",\"String\":\"Hey\"}]");
            hijack.OnSendingRequest = req =>
            {
                Assert.Fail("No request should be made.");
                return Task.FromResult(req);
            };
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);
            await service.SyncContext.InitializeAsync(new MobileServiceLocalStoreMock(), new MobileServiceSyncHandler());
            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            var item = new StringIdType() { Id = "an id", String = "what?" };

            await table.InsertAsync(item);
            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);

            await table.DeleteAsync(item);
            await service.SyncContext.PushAsync();

            Assert.AreEqual(service.SyncContext.PendingOperations, 0L);
        }
        public async Task UpdateAsyncWithStringIdTypeAndNonStringIdResponseContent()
        {
            object[] testIdData = IdTestData.ValidIntIds.Concat(
                                  IdTestData.InvalidIntIds).Cast<object>().Concat(
                                  IdTestData.NonStringNonIntValidJsonIds).ToArray();

            foreach (object testId in testIdData)
            {
                string stringTestId = testId.ToString().ToLower();

                TestHttpHandler hijack = new TestHttpHandler();

                hijack.SetResponseContent("{\"id\":" + stringTestId.ToLower() + ",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                StringIdType item = new StringIdType() { Id = "an id", String = "what?" };
                await table.UpdateAsync(item);

                Assert.AreEqual(testId.ToString(), item.Id);
                Assert.AreEqual("Hey", item.String);
            }
        }
        public async Task UpdateAsyncWithStringIdTypeAndStringIdResponseContent()
        {
            string[] testIdData = IdTestData.ValidStringIds.Concat(
                                  IdTestData.EmptyStringIds).Concat(
                                  IdTestData.InvalidStringIds).ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();

                // Make the testId JSON safe
                string jsonTestId = testId.Replace("\\", "\\\\").Replace("\"", "\\\"");

                hijack.SetResponseContent("{\"id\":\"" + jsonTestId + "\",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                StringIdType item = new StringIdType() { Id = "an id", String = "what?" };
                await table.UpdateAsync(item);

                Assert.AreEqual(testId, item.Id);
                Assert.AreEqual("Hey", item.String);
            }
        }
        public async Task InsertAsyncWithStringIdTypeAndNullIdItem()
        {
            TestHttpHandler hijack = new TestHttpHandler();
            hijack.SetResponseContent("{\"id\":\"an id\",\"String\":\"Hey\"}");
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

            IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

            hijack.OnSendingRequest = async request =>
            {
                string requestContent = await request.Content.ReadAsStringAsync();
                JObject itemAsJObject = JObject.Parse(requestContent);
                Assert.AreEqual(null, (string)itemAsJObject["id"]);
                Assert.AreEqual("what?", (string)itemAsJObject["String"]);
                return request;
            };

            StringIdType item = new StringIdType() { Id = null, String = "what?" };
            await table.InsertAsync(item);

            Assert.AreEqual("an id", item.Id);
            Assert.AreEqual("Hey", item.String);
        }
        public async Task RefreshAsyncWithStringIdTypeAndNullIdParameter()
        {
            TestHttpHandler hijack = new TestHttpHandler();
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

            IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

            StringIdType item = new StringIdType() { String = "Hey" };
            await table.RefreshAsync(item);

            Assert.AreEqual(null, item.Id);
            Assert.AreEqual("Hey", item.String);
        }
        public async Task RefreshAsyncWithStringIdTypeAndEmptyStringIdItem()
        {
            string[] testIdData = IdTestData.EmptyStringIds;

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("[{\"id\":\"" + testId + "\",\"String\":\"Hey\"}]");
                IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                await table.RefreshAsync(item);

                Assert.AreEqual(testId, item.Id);
                Assert.AreEqual("what?", item.String);
            }
        }
        public async Task RefreshAsyncWithStringIdTypeAndStringIdItem()
        {
            string[] testIdData = IdTestData.ValidStringIds.ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("[{\"id\":\"" + testId + "\",\"String\":\"Hey\"}]");
                IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                await table.RefreshAsync(item);
                
                string idForOdataQuery = Uri.EscapeDataString(testId.Replace("'", "''"));
                Uri expectedUri = new Uri(string.Format("http://www.test.com/tables/StringIdType?$filter=(id eq '{0}')", idForOdataQuery));

                Assert.AreEqual(testId, item.Id);
                Assert.AreEqual("Hey", item.String);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task DeleteAsync_DoesNotUpsertResultOnStore_WhenOperationIsPushed()
        {
            var storeMock = new MobileServiceLocalStoreMock();

            var hijack = new TestHttpHandler();
            hijack.AddResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}"); // for insert
            hijack.AddResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}"); // for delete
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

            await service.SyncContext.InitializeAsync(storeMock, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            // first add an item
            var item = new StringIdType() { Id = "abc", String = "what?" };
            await table.InsertAsync(item);

            Assert.AreEqual(storeMock.TableMap[table.TableName].Count, 1);

            // for good measure also push it
            await service.SyncContext.PushAsync();

            await table.DeleteAsync(item);

            Assert.AreEqual(storeMock.TableMap[table.TableName].Count, 0);

            // now play it on server
            await service.SyncContext.PushAsync();

            // wait we don't want to upsert the result back because its delete operation
            Assert.AreEqual(storeMock.TableMap[table.TableName].Count, 0);
            // looks good
        }
        public async Task DeleteAsync_Throws_WhenInsertWasAttempted()
        {
            var hijack = new TestHttpHandler();
            hijack.Response = new HttpResponseMessage(HttpStatusCode.RequestTimeout); // insert response
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);
            await service.SyncContext.InitializeAsync(new MobileServiceLocalStoreMock(), new MobileServiceSyncHandler());
            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            var item = new StringIdType() { Id = "an id", String = "what?" };
            await table.InsertAsync(item);
            // insert is in queue
            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);

            var pushException = await ThrowsAsync<MobileServicePushFailedException>(service.SyncContext.PushAsync);
            Assert.AreEqual(pushException.PushResult.Errors.Count(), 1);

            var delException = await ThrowsAsync<InvalidOperationException>(() => table.DeleteAsync(item));
            Assert.AreEqual(delException.Message, "The item is in inconsistent state in the local store. Please complete the pending sync by calling PushAsync() before deleting the item.");

            // insert still in queue
            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);
        }
        public async Task UpdateAsyncWithStringIdTypeAndNoIdResponseContent()
        {
            TestHttpHandler hijack = new TestHttpHandler();
            hijack.SetResponseContent("{\"String\":\"Hey\"}");
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

            IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

            StringIdType item = new StringIdType() { Id = "an id", String = "what?" };
            await table.UpdateAsync(item);

            Assert.AreEqual("an id", item.Id);
            Assert.AreEqual("Hey", item.String);
        }
        public async Task PullAsync_DoesNotTriggerPush_WhenThereIsNoOperationInTable()
        {
            var hijack = new TestHttpHandler();
            hijack.AddResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}"); // for insert
            hijack.AddResponseContent("[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"World\"}]"); // for pull
            hijack.AddResponseContent("[]"); // last page

            var store = new MobileServiceLocalStoreMock();
            store.ReadResponses.Enqueue("[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"World\"}]"); // for pull

            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            // insert item in pull table
            IMobileServiceSyncTable table1 = service.GetSyncTable("someTable");
            await table1.InsertAsync(new JObject() { { "id", "abc" } });

            // but push to clear the queue
            await service.SyncContext.PushAsync();
            Assert.AreEqual(store.TableMap[table1.TableName].Count, 1); // item is inserted
            Assert.AreEqual(hijack.Requests.Count, 1); // first push

            // then insert item in other table
            IMobileServiceSyncTable<StringIdType> table2 = service.GetSyncTable<StringIdType>();
            var item = new StringIdType() { Id = "an id", String = "what?" };
            await table2.InsertAsync(item);

            await table1.PullAsync(null, null);

            Assert.AreEqual(store.TableMap[table1.TableName].Count, 2); // table should contain 2 pulled items
            Assert.AreEqual(hijack.Requests.Count, 3); // 1 for push and 2 for pull
            Assert.AreEqual(store.TableMap[table2.TableName].Count, 1); // this table should not be touched
        }
        public async Task UpdateAsyncWithStringIdTypeAndStringIdItem()
        {
            string[] testIdData = IdTestData.ValidStringIds.ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("{\"id\":\"" + testId + "\",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                hijack.OnSendingRequest = async request =>
                {
                    string requestContent = await request.Content.ReadAsStringAsync();
                    JObject itemAsJObject = JObject.Parse(requestContent);
                    Assert.AreEqual(testId, (string)itemAsJObject["id"]);
                    Assert.AreEqual("what?", (string)itemAsJObject["String"]);
                    string idForUri = Uri.EscapeDataString(testId);
                    Uri expectedUri = new Uri(string.Format("http://www.test.com/tables/StringIdType/{0}", idForUri));
                    Assert.AreEqual(request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
                    return request;
                };

                StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                await table.UpdateAsync(item);

                Assert.AreEqual(testId, item.Id);
                Assert.AreEqual("Hey", item.String);
            }
        }
        /// <summary>
        /// Tests that the second operation on the same item will cancel one of the two operations how ever other operations between the two (on other items) are not reordered
        /// </summary>
        /// <param name="firstOperationOnItem1">first operation on item 1</param>
        /// <param name="operationOnItem2">operation on item 2</param>
        /// <param name="secondOperationOnItem1">second operation on item 1</param>
        /// <param name="assertRequest">To check which of the two operations got cancelled</param>
        private async Task TestCollapseCancel(Func<IMobileServiceSyncTable<StringIdType>, StringIdType, Task> firstOperationOnItem1,
                                              Func<IMobileServiceSyncTable<StringIdType>, StringIdType, Task> operationOnItem2,
                                              Func<IMobileServiceSyncTable<StringIdType>, StringIdType, Task> secondOperationOnItem1,
                                              Action<HttpRequestMessage, int> assertRequest,
                                              Action<Dictionary<string, JObject>> assertQueue)
        {
            var store = new MobileServiceLocalStoreMock();
            var hijack = new TestHttpHandler();
            MobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

            var item1 = new StringIdType() { Id = "item1", String = "what?" };
            var item2 = new StringIdType() { Id = "item2", String = "this" };
            int executed = 0;
            hijack.SetResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}");
            hijack.OnSendingRequest = req =>
            {
                ++executed;
                assertRequest(req, executed);
                return Task.FromResult(req);
            };

            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());
            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            await firstOperationOnItem1(table, item1);
            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);

            await operationOnItem2(table, item2);
            Assert.AreEqual(service.SyncContext.PendingOperations, 2L);

            await secondOperationOnItem1(table, item1);
            Assert.AreEqual(service.SyncContext.PendingOperations, 2L);

            Dictionary<string, JObject> queue = store.TableMap[MobileServiceLocalSystemTables.OperationQueue];
            assertQueue(queue);

            await service.SyncContext.PushAsync();

            Assert.AreEqual(service.SyncContext.PendingOperations, 0L);
            Assert.AreEqual(executed, 2); // total two operations executed
        }
        public async Task DeleteAsyncWithStringIdTypeAndStringIdItem()
        {
            string[] testIdData = IdTestData.ValidStringIds;

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("{\"id\":\"" + testId + "\",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                hijack.OnSendingRequest = request =>
                {
                    Assert.IsNull(request.Content);
                    string idForUri = Uri.EscapeDataString(testId);
                    Uri expectedUri = new Uri(string.Format("http://www.test.com/tables/StringIdType/{0}", idForUri));
                    Assert.AreEqual(request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
                    return new TaskFactory<HttpRequestMessage>().StartNew(() => request);
                };

                StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                await table.DeleteAsync(item);

                Assert.AreEqual(null, item.Id);
                Assert.AreEqual("what?", item.String);
            }
        }
        /// <summary>
        /// Tests that throwing an exception of type toThrow from the http handler causes the push sync to be aborted
        /// </summary>
        /// <param name="toThrow">The exception to simulate coming from http layer</param>
        /// <param name="expectedStatus">The expected status of push operation as reported in PushCompletionResult and PushFailedException</param>
        /// <returns></returns>
        private async Task TestPushAbort(Exception toThrow, MobileServicePushStatus expectedStatus)
        {
            bool thrown = false;
            var hijack = new TestHttpHandler();
            hijack.OnSendingRequest = req =>
            {
                if (!thrown)
                {
                    thrown = true;
                    throw toThrow;
                }
                return Task.FromResult(req);
            };

            var operationHandler = new MobileServiceSyncHandlerMock();

            hijack.SetResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}");
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);
            await service.SyncContext.InitializeAsync(new MobileServiceLocalStoreMock(), operationHandler);

            IMobileServiceSyncTable<StringIdType> table = service.GetSyncTable<StringIdType>();

            var item = new StringIdType() { Id = "an id", String = "what?" };
            await table.InsertAsync(item);

            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);

            MobileServicePushFailedException ex = await ThrowsAsync<MobileServicePushFailedException>(service.SyncContext.PushAsync);

            Assert.AreEqual(ex.PushResult.Status, expectedStatus);
            Assert.AreEqual(ex.PushResult.Errors.Count(), 0);

            Assert.AreEqual(operationHandler.PushCompletionResult.Status, expectedStatus);

            // the insert operation is still in queue
            Assert.AreEqual(service.SyncContext.PendingOperations, 1L);

            await service.SyncContext.PushAsync();

            Assert.AreEqual(service.SyncContext.PendingOperations, 0L);
            Assert.AreEqual(operationHandler.PushCompletionResult.Status, MobileServicePushStatus.Complete);
        }
        public async Task UpdateAsyncWithStringIdTypeAndNullIdResponseContent()
        {
            TestHttpHandler hijack = new TestHttpHandler();
            hijack.SetResponseContent("{\"id\":null,\"String\":\"Hey\"}");
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);

            IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

            StringIdType item = new StringIdType() { Id = "an id", String = "what?" };
            await table.UpdateAsync(item);

            Assert.AreEqual("an id", item.Id);
            Assert.AreEqual("Hey", item.String);
        }
        public async Task DeleteAsyncWithStringIdTypeAndEmptyStringIdItem()
        {
            string[] testIdData = IdTestData.EmptyStringIds;

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("{\"id\":\"an id\",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();
                Exception exception = null;
                try
                {
                    StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                    await table.DeleteAsync(item);
                }
                catch (Exception e)
                {
                    exception = e;
                }

                Assert.IsNotNull(exception);
                Assert.IsTrue(exception.Message.Contains("The id can not be null or an empty string."));
            }
        }
 public Task FeatureHeaderValidation_TypedTableDeleteWithQuery()
 {
     var obj = new StringIdType { Id = "the id", String = "hey" };
     return this.ValidateFeaturesHeader("TT,QS", false, t => t.DeleteAsync(obj, new Dictionary<string, string> { { "a", "b" } }));
 }
        public async Task PurgeAsync_DoesNotTriggerPush_WhenThereIsNoOperationInTable()
        {
            var hijack = new TestHttpHandler();
            hijack.SetResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}");
            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            // insert item in purge table
            IMobileServiceSyncTable table1 = service.GetSyncTable("someTable");
            await table1.InsertAsync(new JObject() { { "id", "abc" } });

            // but push to clear the queue
            await service.SyncContext.PushAsync();
            Assert.AreEqual(store.TableMap[table1.TableName].Count, 1); // item is inserted
            Assert.AreEqual(hijack.Requests.Count, 1); // first push

            // then insert item in other table
            IMobileServiceSyncTable<StringIdType> table2 = service.GetSyncTable<StringIdType>();
            var item = new StringIdType() { Id = "an id", String = "what?" };
            await table2.InsertAsync(item);

            // try purge on first table now
            await table1.PurgeAsync();

            Assert.AreEqual(store.DeleteQueries[0].TableName, MobileServiceLocalSystemTables.SyncErrors); // push deletes all sync erros
            Assert.AreEqual(store.DeleteQueries[1].TableName, table1.TableName); // purged table
            Assert.AreEqual(hijack.Requests.Count, 1); // still 1 means no other push happened
            Assert.AreEqual(store.TableMap[table2.TableName].Count, 1); // this table should not be touched
        }
        public async Task DeleteAsyncWithStringIdTypeAndNullIdItem()
        {
            TestHttpHandler hijack = new TestHttpHandler();
            hijack.SetResponseContent("{\"id\":\"an id\",\"String\":\"Hey\"}");
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", "secret...", hijack);

            IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

            Exception exception = null;
            try
            {
                StringIdType item = new StringIdType() { Id = null, String = "what?" };
                await table.DeleteAsync(item);
            }
            catch (Exception e)
            {
                exception = e;
            }

            Assert.IsNotNull(exception);
            Assert.IsTrue(exception.Message.Contains("Expected id member not found."));
        }