public async Task DeleteItemAsync_ConditionalFailure() { await InitializeAsync(true); // Arrange var idToDelete = GetRandomId(); // Act // Update the version on the server. await ModifyServerVersionAsync(idToDelete); var jsonDocument = await table !.GetItemAsync(idToDelete); Assert.NotNull(jsonDocument); await table !.DeleteItemAsync(jsonDocument); Assert.Equal(MovieCount, MovieServer.GetMovieCount()); Assert.NotNull(MovieServer.GetMovieById(idToDelete)); var exception = await Assert.ThrowsAsync <PushFailedException>(() => table !.PushItemsAsync()); Assert.Equal(MovieCount, MovieServer.GetMovieCount()); Assert.NotNull(MovieServer.GetMovieById(idToDelete)); Assert.NotNull(exception.PushResult); Assert.Single(exception.PushResult.Errors); var error = exception.PushResult.Errors.First(); Assert.Equal(idToDelete, error.Item.Value <string>("id")); }
public async Task BasicPatchTests([CombinatorialValues("movies", "movies_pagesize")] string table) { var id = GetRandomId(); var expected = MovieServer.GetMovieById(id) !; expected.Title = "Test Movie Title"; expected.Rating = "PG-13"; var patchDoc = new Dictionary <string, object>() { { "title", "Test Movie Title" }, { "rating", "PG-13" } }; var response = await MovieServer.SendRequest(HttpMethod.Patch, $"tables/{table}/{id}", patchDoc, "application/json", null); await AssertResponseWithLoggingAsync(HttpStatusCode.OK, response); var result = response.DeserializeContent <ClientMovie>(); Assert.NotNull(result); var stored = MovieServer.GetMovieById(id); Assert.NotNull(stored); AssertEx.SystemPropertiesSet(stored, StartTime); AssertEx.SystemPropertiesChanged(expected, stored); AssertEx.SystemPropertiesMatch(stored, result); Assert.Equal <IMovie>(expected, result !); AssertEx.ResponseHasConditionalHeaders(stored, response); }
public async Task UndeleteItemAsync_ConditionalFailure() { // Arrange var id = GetRandomId(); var jsonDocument = CreateJsonDocument(new IdEntity { Id = id, Version = "dGVzdA==" }); var expected = MovieServer.GetMovieById(id); // Act var exception = await Assert.ThrowsAsync <DatasyncConflictException>(() => table.UndeleteItemAsync(jsonDocument)).ConfigureAwait(false); // Assert Assert.NotNull(exception.Request); Assert.NotNull(exception.Response); Assert.Equal(HttpStatusCode.PreconditionFailed, exception.Response?.StatusCode); var entity = MovieServer.GetMovieById(id); Assert.NotNull(entity); AssertJsonDocumentMatches(entity, exception.Value); Assert.Equal <IMovie>(expected, entity); Assert.Equal <ITableData>(expected, entity); AssertEx.ResponseHasConditionalHeaders(entity, exception.Response); }
[InlineData("tables/movies_legal/id-113", HttpStatusCode.NotFound, "X-Auth", "success")] // Any movie that is not R-rated in the DB will do here. public async Task FailedReplaceTests(string relativeUri, HttpStatusCode expectedStatusCode, string?headerName = null, string?headerValue = null) { var id = relativeUri.Split('/').Last(); var expected = MovieServer.GetMovieById(id) !; ClientMovie blackPantherMovie = new() { Id = id, BestPictureWinner = true, Duration = 134, Rating = "PG-13", ReleaseDate = DateTimeOffset.Parse("16-Feb-2018"), Title = "Black Panther", Year = 2018 }; Dictionary <string, string> headers = new(); if (headerName != null && headerValue != null) { headers.Add(headerName, headerValue); } // Act var response = await MovieServer.SendRequest(HttpMethod.Put, relativeUri, blackPantherMovie, headers); // Assert await AssertResponseWithLoggingAsync(expectedStatusCode, response); var entity = MovieServer.GetMovieById(id); if (entity != null) { Assert.Equal <IMovie>(expected, entity); Assert.Equal <ITableData>(expected, entity); } }
public async Task BasicCreateTests([CombinatorialValues("movies", "movies_pagesize")] string table, bool hasId) { var movieToAdd = GetSampleMovie <ClientMovie>(); if (hasId) { movieToAdd.Id = Guid.NewGuid().ToString("N"); } var response = await MovieServer.SendRequest <ClientMovie>(HttpMethod.Post, $"tables/{table}", movieToAdd); await AssertResponseWithLoggingAsync(HttpStatusCode.Created, response); var result = response.DeserializeContent <ClientMovie>(); Assert.NotNull(result); Assert.True(Guid.TryParse(result !.Id, out _)); if (hasId) { Assert.Equal(movieToAdd.Id, result !.Id); } Assert.Equal(TestData.Movies.Count + 1, MovieServer.GetMovieCount()); var entity = MovieServer.GetMovieById(result !.Id); Assert.NotNull(entity); AssertEx.SystemPropertiesSet(entity, StartTime); AssertEx.SystemPropertiesMatch(entity, result); Assert.Equal <IMovie>(movieToAdd, result !); Assert.Equal <IMovie>(movieToAdd, entity !); AssertEx.ResponseHasConditionalHeaders(entity, response); AssertEx.HasHeader(response, "Location", $"https://localhost/tables/{table}/{result.Id}"); }
public async Task ReplaceItemAsync_ConditionalFailure() { // Arrange var id = GetRandomId(); var original = MovieServer.GetMovieById(id) !; var expected = ClientMovie.From(original); expected.Title = "Replacement Title"; expected.Rating = "PG-13"; expected.Version = "dGVzdA=="; // Act var exception = await Assert.ThrowsAsync <DatasyncConflictException <ClientMovie> >(() => table.ReplaceItemAsync(expected)).ConfigureAwait(false); // Assert Assert.NotNull(exception.Request); Assert.NotNull(exception.Response); Assert.Equal(MovieCount, MovieServer.GetMovieCount()); var entity = MovieServer.GetMovieById(id); Assert.NotNull(entity); AssertEx.SystemPropertiesSet(entity, startTime); AssertEx.SystemPropertiesMatch(entity, exception.Item); Assert.Equal <IMovie>(original, exception.Item); Assert.Equal <IMovie>(original, entity); Assert.Equal <ITableData>(original, entity); AssertEx.ResponseHasConditionalHeaders(entity, exception.Response); }
public async Task GetAsyncItems_AsPages_RetrievesItems() { // Arrange int itemCount = 0, pageCount = 0; var pageable = (table.GetAsyncItems <ClientMovie>("") as AsyncPageable <ClientMovie>) !.AsPages(); Assert.NotNull(pageable); var enumerator = pageable.GetAsyncEnumerator(); while (await enumerator.MoveNextAsync().ConfigureAwait(false)) { pageCount++; var page = enumerator.Current; Assert.NotNull(page); foreach (var item in page.Items) { itemCount++; Assert.NotNull(item.Id); var expected = MovieServer.GetMovieById(item.Id); Assert.Equal <IMovie>(expected, item); } } Assert.Equal(MovieCount, itemCount); Assert.Equal(3, pageCount); }
public async Task ReplaceItemAsync_SoftDeleted_ReturnsGone() { // Arrange var id = GetRandomId(); await MovieServer.SoftDeleteMoviesAsync(x => x.Id == id).ConfigureAwait(false); var original = MovieServer.GetMovieById(id) !; var expected = ClientMovie.From(original); expected.Title = "Replacement Title"; expected.Rating = "PG-13"; var json = CreateJsonDocument(expected); var table = client.GetRemoteTable("soft"); // Act var exception = await Assert.ThrowsAsync <DatasyncInvalidOperationException>(() => soft.ReplaceItemAsync(json)).ConfigureAwait(false); var stored = MovieServer.GetMovieById(id).Clone(); // Assert Assert.Equal(HttpStatusCode.Gone, exception.Response?.StatusCode); Assert.Equal <IMovie>(original, stored); Assert.Equal <ITableData>(original, stored); }
public async Task BasicV2QueryTest(string query, int expectedItemCount, string[] firstExpectedItems) { Dictionary <string, string> headers = new() { { "ZUMO-API-VERSION", "2.0.0" } }; var response = await MovieServer.SendRequest(HttpMethod.Get, query, headers).ConfigureAwait(false); await AssertResponseWithLoggingAsync(HttpStatusCode.OK, response); // Response payload can be decoded var result = response.DeserializeContent <List <ClientMovie> >(); Assert.NotNull(result); // Payload has the right content Assert.Equal(expectedItemCount, result !.Count); // The first n items must match what is expected Assert.True(result.Count >= firstExpectedItems.Length); Assert.Equal(firstExpectedItems, result.Take(firstExpectedItems.Length).Select(m => m.Id).ToArray()); for (int idx = 0; idx < firstExpectedItems.Length; idx++) { var expected = MovieServer.GetMovieById(firstExpectedItems[idx]); var actual = result[idx]; Assert.Equal <IMovie>(expected !, actual); AssertEx.SystemPropertiesMatch(expected, actual); } }
public async Task AuthenticatedDeleteTests( [CombinatorialValues(0, 1, 2, 3, 7, 14, 25)] int index, [CombinatorialValues(null, "failed", "success")] string userId, [CombinatorialValues("movies_rated", "movies_legal")] string table) { string id = Utils.GetMovieId(index); Dictionary <string, string> headers = new(); Utils.AddAuthHeaders(headers, userId); var response = await MovieServer.SendRequest(HttpMethod.Delete, $"tables/{table}/{id}", headers); if (userId != "success") { var statusCode = table.Contains("legal") ? HttpStatusCode.UnavailableForLegalReasons : HttpStatusCode.Unauthorized; await AssertResponseWithLoggingAsync(statusCode, response); Assert.Equal(TestData.Movies.Count, MovieServer.GetMovieCount()); Assert.NotNull(MovieServer.GetMovieById(id)); } else { await AssertResponseWithLoggingAsync(HttpStatusCode.NoContent, response); Assert.Equal(TestData.Movies.Count - 1, MovieServer.GetMovieCount()); Assert.Null(MovieServer.GetMovieById(id)); } }
public async Task ReplaceItemAsync_Validation(string propName, object propValue) { // Arrange var id = GetRandomId(); var original = MovieServer.GetMovieById(id) !; var expected = ClientMovie.From(original); var entity = expected.Clone(); switch (propName) { case "duration": entity.Duration = (int)propValue; break; case "rating": entity.Rating = (string)propValue; break; case "title": entity.Title = (string)propValue; break; case "year": entity.Year = (int)propValue; break; } // Act var exception = await Assert.ThrowsAsync <DatasyncInvalidOperationException>(() => table.ReplaceItemAsync(entity)).ConfigureAwait(false); var stored = MovieServer.GetMovieById(id); // Assert Assert.Equal(HttpStatusCode.BadRequest, exception.Response?.StatusCode); Assert.Equal <IMovie>(expected, stored); Assert.Equal <ITableData>(original, stored); }
public async Task BasicPatchTests([CombinatorialValues("movies", "movies_pagesize")] string table) { var id = GetRandomId(); var expected = MovieServer.GetMovieById(id) !; expected.Title = "Test Movie Title"; expected.Rating = "PG-13"; var patchDoc = new PatchOperation[] { new PatchOperation("replace", "title", "Test Movie Title"), new PatchOperation("replace", "rating", "PG-13") }; var response = await MovieServer.SendPatch($"tables/{table}/{id}", patchDoc); await AssertResponseWithLoggingAsync(HttpStatusCode.OK, response); var result = response.DeserializeContent <ClientMovie>(); var stored = MovieServer.GetMovieById(id); AssertEx.SystemPropertiesSet(stored, StartTime); AssertEx.SystemPropertiesChanged(expected, stored); AssertEx.SystemPropertiesMatch(stored, result); Assert.Equal <IMovie>(expected, result !); AssertEx.ResponseHasConditionalHeaders(stored, response); }
public async Task GetAsyncItems_AsPages_RetrievesItems() { // Arrange int itemCount = 0, pageCount = 0; var pageable = (table.GetAsyncItems("$count=true") as AsyncPageable <JToken>) !.AsPages(); Assert.NotNull(pageable); var enumerator = pageable.GetAsyncEnumerator(); while (await enumerator.MoveNextAsync().ConfigureAwait(false)) { pageCount++; var page = enumerator.Current; Assert.NotNull(page); foreach (var item in page.Items) { itemCount++; var itemId = item.Value <string>("id"); Assert.NotNull(itemId); var expected = MovieServer.GetMovieById(itemId); AssertVersionMatches(expected.Version, item.Value <string>("version") !); } } Assert.Equal(MovieCount, itemCount); Assert.Equal(3, pageCount); }
public async Task AuthenticatedReadTests( [CombinatorialValues(0, 1, 2, 3, 7, 14, 25)] int index, [CombinatorialValues(null, "failed", "success")] string userId, [CombinatorialValues("movies_rated", "movies_legal")] string table) { string id = Utils.GetMovieId(index); var expected = MovieServer.GetMovieById(id) !; Dictionary <string, string> headers = new(); Utils.AddAuthHeaders(headers, userId); var response = await MovieServer.SendRequest(HttpMethod.Get, $"tables/{table}/{id}", headers); if (userId != "success") { var statusCode = table.Contains("legal") ? HttpStatusCode.UnavailableForLegalReasons : HttpStatusCode.Unauthorized; await AssertResponseWithLoggingAsync(statusCode, response); } else { await AssertResponseWithLoggingAsync(HttpStatusCode.OK, response); var actual = response.DeserializeContent <ClientMovie>(); Assert.Equal <IMovie>(expected, actual !); AssertEx.SystemPropertiesMatch(expected, actual); AssertEx.ResponseHasConditionalHeaders(expected, response); } }
public async Task GetAsyncItems_RetrievesItems() { await InitializeAsync(true); // Arrange int count = 0; var enumerable = table !.GetAsyncItems(""); Assert.NotNull(enumerable); var enumerator = enumerable !.GetAsyncEnumerator(); while (await enumerator.MoveNextAsync()) { count++; var item = enumerator.Current; var itemId = item.Value <string>("id"); Assert.NotNull(item); Assert.NotNull(itemId); var expected = MovieServer.GetMovieById(itemId); AssertVersionMatches(expected.Version, item.Value <string>("version") !); } Assert.Equal(MovieCount, count); }
public async Task ReplaceItemAsync_Validation(string propName, object propValue) { await InitializeAsync(); // Arrange var id = GetRandomId(); var original = MovieServer.GetMovieById(id) !; var expected = ClientMovie.From(original); var entity = expected.Clone(); switch (propName) { case "duration": entity.Duration = (int)propValue; break; case "rating": entity.Rating = (string)propValue; break; case "title": entity.Title = (string)propValue; break; case "year": entity.Year = (int)propValue; break; } // Act await table !.ReplaceItemAsync(entity); var exception = await Assert.ThrowsAsync <PushFailedException>(() => table !.PushItemsAsync()); var stored = MovieServer.GetMovieById(id); // Assert Assert.Single(exception.PushResult.Errors); }
public async Task CreateItemAsync_OverwriteSystemProperties(bool useUpdatedAt, bool useVersion) { var movieToAdd = GetSampleMovie <ClientMovie>(); movieToAdd.Id = Guid.NewGuid().ToString("N"); if (useUpdatedAt) { movieToAdd.UpdatedAt = DateTimeOffset.Parse("2018-12-31T01:01:01.000Z"); } if (useVersion) { movieToAdd.Version = Convert.ToBase64String(Guid.NewGuid().ToByteArray()); } var result = movieToAdd.Clone(); // Act await table.InsertItemAsync(result).ConfigureAwait(false); // Assert Assert.Equal(movieToAdd.Id, result.Id); Assert.Equal <IMovie>(movieToAdd, result); Assert.Equal(MovieCount + 1, MovieServer.GetMovieCount()); var entity = MovieServer.GetMovieById(result.Id) !; if (useUpdatedAt) { Assert.NotEqual(movieToAdd.UpdatedAt, result.UpdatedAt); } if (useVersion) { Assert.NotEqual(movieToAdd.Version, result.Version); } Assert.Equal <IMovie>(movieToAdd, entity); }
public async Task CreateItemAsync_Basic(bool hasId) { var movieToAdd = GetSampleMovie <ClientMovie>(); if (hasId) { movieToAdd.Id = Guid.NewGuid().ToString("N"); } var result = movieToAdd.Clone(); // Act await table.InsertItemAsync(result).ConfigureAwait(false); // Assert Assert.True(Guid.TryParse(result.Id, out _)); if (hasId) { Assert.Equal(movieToAdd.Id, result.Id); } Assert.Equal <IMovie>(movieToAdd, result); Assert.Equal(MovieCount + 1, MovieServer.GetMovieCount()); var entity = MovieServer.GetMovieById(result.Id) !; Assert.Equal <IMovie>(movieToAdd, entity); AssertEx.SystemPropertiesMatch(entity, result); }
public async Task Delete_OnVersion(string headerName, string?headerValue, HttpStatusCode expectedStatusCode) { const string id = "id-107"; var expected = MovieServer.GetMovieById(id) !; Dictionary <string, string> headers = new() { { headerName, headerValue ?? expected.GetETag() } }; var response = await MovieServer.SendRequest(HttpMethod.Delete, $"tables/movies/{id}", headers); await AssertResponseWithLoggingAsync(expectedStatusCode, response); switch (expectedStatusCode) { case HttpStatusCode.NoContent: Assert.Equal(TestData.Movies.Count - 1, MovieServer.GetMovieCount()); Assert.Null(MovieServer.GetMovieById(id)); break; case HttpStatusCode.PreconditionFailed: var actual = response.DeserializeContent <ClientMovie>(); Assert.NotNull(actual); Assert.Equal <IMovie>(expected, actual !); AssertEx.SystemPropertiesMatch(expected, actual); AssertEx.ResponseHasConditionalHeaders(expected, response); break; } }
public async Task DeleteItemAsync_ConditionalFailure() { // Arrange var id = GetRandomId(); var expected = MovieServer.GetMovieById(id); var item = new ClientMovie { Id = id, Version = "dGVzdA==" }; // Act var exception = await Assert.ThrowsAsync <DatasyncConflictException <ClientMovie> >(() => table.DeleteItemAsync(item)).ConfigureAwait(false); // Assert Assert.NotNull(exception.Request); Assert.NotNull(exception.Response); Assert.Equal(MovieCount, MovieServer.GetMovieCount()); var entity = MovieServer.GetMovieById(id); Assert.NotNull(entity); AssertEx.SystemPropertiesSet(entity, startTime); AssertEx.SystemPropertiesMatch(entity, exception.Item); Assert.Equal <IMovie>(expected, exception.Item); Assert.Equal <IMovie>(expected, entity); Assert.Equal <ITableData>(expected, entity); AssertEx.ResponseHasConditionalHeaders(entity, exception.Response); }
public async Task GetAsyncItems_RetrievesItems() { await InitializeAsync(); // Arrange int count = 0; var query = table !.CreateQuery().IncludeTotalCount(true); var pageable = table !.GetAsyncItems(query) as AsyncPageable <ClientMovie>; Assert.NotNull(pageable); var enumerator = pageable !.GetAsyncEnumerator(); while (await enumerator.MoveNextAsync()) { count++; var item = enumerator.Current; Assert.NotNull(item); Assert.NotNull(item.Id); var expected = MovieServer.GetMovieById(item.Id); Assert.Equal <IMovie>(expected, item); Assert.Equal(MovieCount, pageable.Count); } Assert.Equal(MovieCount, count); }
public async Task DeleteItemAsync_ConditionalFailure() { await InitializeAsync(); // Arrange var id = GetRandomId(); var expected = MovieServer.GetMovieById(id); var item = ClientMovie.From(MovieServer.GetMovieById(id)); await ModifyServerVersionAsync(id); // Act await table !.DeleteItemAsync(item); Assert.Equal(MovieCount, MovieServer.GetMovieCount()); var exception = await Assert.ThrowsAsync <PushFailedException>(() => table !.PushItemsAsync()); // Assert Assert.Equal(MovieCount, MovieServer.GetMovieCount()); var entity = MovieServer.GetMovieById(id); // Check the PushFailedException Assert.Single(exception.PushResult.Errors); var error = exception.PushResult.Errors.First(); AssertSystemPropertiesMatch(entity, error.Result); }
public async Task GetAsyncItems_NoArgs_RetrievesItems() { // Arrange int count = 0; var pageable = table.GetAsyncItems() as AsyncPageable <ClientMovie>; Assert.NotNull(pageable); var enumerator = pageable !.GetAsyncEnumerator(); while (await enumerator.MoveNextAsync().ConfigureAwait(false)) { count++; var item = enumerator.Current; Assert.NotNull(item); Assert.NotNull(item.Id); var expected = MovieServer.GetMovieById(item.Id); Assert.Equal <IMovie>(expected, item); } Assert.Equal(MovieCount, count); }
public async Task FailedDeleteTests(string relativeUri, HttpStatusCode expectedStatusCode) { var response = await MovieServer.SendRequest(HttpMethod.Delete, relativeUri); await AssertResponseWithLoggingAsync(expectedStatusCode, response); Assert.Equal(TestData.Movies.Count, MovieServer.GetMovieCount()); }
public async Task ReadSoftDeletedItem_ReturnsGoneIfDeleted([CombinatorialValues("soft", "soft_logged")] string table) { var id = GetRandomId(); await MovieServer.SoftDeleteMoviesAsync(x => x.Id == id); var response = await MovieServer.SendRequest(HttpMethod.Get, $"tables/{table}/{id}"); await AssertResponseWithLoggingAsync(HttpStatusCode.Gone, response); }
public async Task BasicDeleteTests() { var id = GetRandomId(); var response = await MovieServer.SendRequest(HttpMethod.Delete, $"tables/movies/{id}"); await AssertResponseWithLoggingAsync(HttpStatusCode.NoContent, response); Assert.Equal(TestData.Movies.Count - 1, MovieServer.GetMovieCount()); Assert.Null(MovieServer.GetMovieById(id)); }
public async Task GetItemAsync_GetIfNotSoftDeleted() { // Arrange var id = GetRandomId(); var expected = MovieServer.GetMovieById(id) !; // Act var response = await soft.GetItemAsync(id).ConfigureAwait(false); // Assert AssertJsonDocumentMatches(expected, response); }
public async Task SoftDeleteItem_SetsDeletedFlag([CombinatorialValues("soft", "soft_logged")] string table) { var id = GetRandomId(); var response = await MovieServer.SendRequest(HttpMethod.Delete, $"tables/{table}/{id}"); await AssertResponseWithLoggingAsync(HttpStatusCode.NoContent, response); Assert.Equal(TestData.Movies.Count, MovieServer.GetMovieCount()); var entity = MovieServer.GetMovieById(id) !; Assert.True(entity.Deleted); }
public async Task GetItemAsync_GetIfNotSoftDeleted() { // Arrange var id = GetRandomId(); var expected = MovieServer.GetMovieById(id) !; // Act var response = await soft.GetItemAsync(id).ConfigureAwait(false); // Assert AssertEx.SystemPropertiesMatch(expected, response); Assert.Equal <IMovie>(expected, response); }
public async Task DeleteItemAsync_ConditionalSuccess() { // Arrange var id = GetRandomId(); var item = ClientMovie.From(MovieServer.GetMovieById(id)); // Act await table.DeleteItemAsync(item).ConfigureAwait(false); // Assert Assert.Equal(MovieCount - 1, MovieServer.GetMovieCount()); Assert.Null(MovieServer.GetMovieById(id)); }