public async Task ItRemovesTheIngredient() { var original = new Recipe(name: nameof(ItRemovesTheIngredient)); var toDelete = original.AddIngredient(new Ingredient(Guid.NewGuid().ToString()), UnitOfMeasure.Cup, 2M); original.AddIngredient(new Ingredient(Guid.NewGuid().ToString()), UnitOfMeasure.Pint, 5M); await AppFixture.InsertAsync(original); var request = new RemoveIngredientRequest { RecipeModelKey = new ModelUpdateIdentifier(original), RecipeIngredientModelKey = new ModelUpdateIdentifier(toDelete) }; await AppFixture.SendAsync(request); var saved = await AppFixture.ExecuteDbContextAsync(async db => { return(await db.Recipes.Where(x => x.Id == original.Id).Include(x => x.RecipeIngredients) .FirstOrDefaultAsync()); }); saved.RecipeIngredients.Should().HaveCount(1); saved.RecipeIngredients[0].UnitOfMeasure.Should().Be(UnitOfMeasure.Pint); }
public async Task ItAddsAnIngredient() { var ingredientName = Guid.NewGuid().ToString(); var recipe = new Recipe(name: nameof(ItAddsAnIngredient)); await AppFixture.InsertAsync(recipe); var result = await AppFixture.SendAsync(new AddIngredientRequest { RecipeKey = new ModelUpdateIdentifier(recipe), Name = ingredientName, Quantity = 42M, UnitOfMeasure = UnitOfMeasure.Pint }); var saved = await AppFixture.ExecuteDbContextAsync(db => db.RecipeIngredients .Include(ri => ri.Ingredient) .Include(ri => ri.Recipe) .Where(ri => ri.Key == result.Key) .FirstOrDefaultAsync()); saved.Ingredient.Name.Should().Be(ingredientName); saved.Recipe.Key.Should().Be(recipe.Key); saved.UnitOfMeasure.Should().Be(UnitOfMeasure.Pint); saved.Quantity.Should().Be(42M); }
public async Task CanSaveASimpleRecipe() { var recipe = new Recipe(name: "Chocolate Milk") { PrepTime = Duration.FromMinutes(3), CookTime = Duration.Zero }; var milk = new Ingredient("Milk"); var chocolateSauce = new Ingredient("Chocolate Sauce"); recipe.AddIngredient(milk, UnitOfMeasure.Cup, 1M); recipe.AddIngredient(chocolateSauce, UnitOfMeasure.Tablespoon, 2M); await AppFixture.InsertAsync(recipe); var saved = await AppFixture.ExecuteDbContextAsync(db => db.Recipes .Include(r => r.RecipeIngredients) .ThenInclude(ri => ri.Ingredient) .Where(r => r.Key == recipe.Key) .FirstOrDefaultAsync()); saved.Name.Should().Be("Chocolate Milk"); saved.PrepTime.Should().Be(Duration.FromMinutes(3)); saved.CookTime.Should().Be(Duration.Zero); saved.RecipeIngredients.Should().HaveCount(2) .And.SatisfyRespectively( first => { first.Id.Should().BeGreaterThan(0); first.Key.Should().NotBe(Guid.Empty); first.Quantity.Should().Be(1M); first.UnitOfMeasure.Should().Be(UnitOfMeasure.Cup); first.Ingredient.Should().Be(milk); }, second => { second.Id.Should().BeGreaterThan(0); second.Key.Should().NotBe(Guid.Empty); second.Quantity.Should().Be(2M); second.UnitOfMeasure.Should().Be(UnitOfMeasure.Tablespoon); second.Ingredient.Should().Be(chocolateSauce); }); }
public async Task ItSoftDeletesRecords() { var original = new Recipe(name: nameof(ItSoftDeletesRecords)); await AppFixture.InsertAsync(original); await AppFixture.ExecuteDbContextAsync(async db => { var saved = await db.Recipes.FindAsync(original.Id); saved.Should().NotBeNull("we just saved it"); saved.SoftDelete(); // db.Remove(saved); }); var deleted = await AppFixture.FindAsync <Recipe>(original.Key); deleted.Should().BeNull("Recipe {0} was soft-deleted", original.Key); }
public async Task ItTreatsVersionAsConcurrencyToken() { var original = new Recipe(name: nameof(ItTreatsVersionAsConcurrencyToken)); await AppFixture.InsertAsync(original); FluentActions.Invoking(async() => { await AppFixture.ExecuteDbContextAsync(async db => { var saved = await db.Recipes.FirstOrDefaultAsync(x => x.Key == original.Key); saved.Name = "Sally"; // record is updated by another user while this context is working with the entity // so when it goes to save, the version numbers will no longer match await db.Database.ExecuteSqlInterpolatedAsync( $"update recipes set version = version + 1 where key = {original.Key}"); }); }).Should().Throw <DbUpdateConcurrencyException>(); }
public async Task ItDeletesRecipeAndIngredients() { var recipe = new Recipe(name: nameof(ItDeletesRecipeAndIngredients)); var ingredient = new Ingredient(Guid.NewGuid().ToString()); recipe.AddIngredient(ingredient, UnitOfMeasure.Cup, 10M); await AppFixture.InsertAsync(recipe); await AppFixture.SendAsync(new RemoveRecipeRequest() { RecipeKey = new ModelUpdateIdentifier(recipe) }); var deleted = await AppFixture.ExecuteDbContextAsync(db => db.GetRecipe(recipe.Key)); deleted.Should().BeNull(because: "it was soft-deleted"); var deletedIngredient = await AppFixture.FindAsync <RecipeIngredient>(ingredient.Key); deletedIngredient.Should().BeNull(because: "it was soft-deleted"); }
public async Task ItBumpsTheVersionAndEditTime() { var original = new Recipe(name: nameof(ItBumpsTheVersionAndEditTime)); await AppFixture.InsertAsync(original); await AppFixture.ExecuteDbContextAsync(async db => { var saved = await db.Recipes.FirstOrDefaultAsync(x => x.Key == original.Key); saved.Name = "Milk"; }); var updated = await AppFixture.FindAsync <Recipe>(original.Key); updated.Name.Should().Be("Milk"); updated.Version.Should().Be(2); updated.UpdatedAt.ToUnixTimeMilliseconds().Should() .BeGreaterThan(original.UpdatedAt.ToUnixTimeMilliseconds(), because: "updated timestamps should be bumped on change"); updated.CreatedAt.Should().Be(original.CreatedAt, because: "created timestamps are never changed"); }