using System; using System.Collections.Generic; using System.Linq; using System.Text; using NUnit.Framework; using Rhino.Mocks; using Chefbook.DataAccess; using Chefbook.DataObjects; using Chefbook.ViewModels; using System.Collections.Specialized; namespace UnitTests.ViewModelsTests { [TestFixture] public class RecipeViewModelFixture { private RecipeViewModel recipeVM; private Recipe recipe; [SetUp] public void Init() { recipe = new Recipe(null); recipe.CookTime = TimeSpan.FromMinutes(90); recipe.PrepTime = TimeSpan.FromMinutes(90); recipeVM = new RecipeViewModel(recipe); } [Test] public void IngredientsAssignedBeforeSettingModelShouldNotBeUndoable() { var ing1 = new Ingredient(recipe); recipeVM.AddIngredient(new IngredientViewModel(new Ingredient())); recipeVM = new RecipeViewModel(); recipeVM.RecipeModel = recipe; recipeVM.AddIngredient(new IngredientViewModel(new Ingredient())); Assert.AreEqual(3, recipeVM.Ingredients.Count); Assert.True(recipeVM.Undo()); Assert.AreEqual(2, recipeVM.Ingredients.Count); Assert.False(recipeVM.Undo()); Assert.False(recipeVM.Undo()); Assert.AreEqual(2, recipeVM.Ingredients.Count); } [Test] public void ChangingNameFiresPropertyChangedTest() { recipeVM.AssertPropertyChangedFired(() => recipeVM.Name = "Hello", "Name"); Assert.AreEqual("Hello", recipe.Name); Assert.AreEqual("Hello", recipeVM.Name); recipeVM.AssertPropertyChangedFired(() => recipeVM.Name = "Hello"); recipeVM.AssertPropertyChangedFired(() => recipeVM.Name = "World", "Name"); Assert.AreEqual("World", recipe.Name); Assert.AreEqual("World", recipeVM.Name); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "Name"); Assert.AreEqual("Hello", recipe.Name); Assert.AreEqual("Hello", recipeVM.Name); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "Name"); Assert.AreEqual(string.Empty, recipeVM.Name); Assert.AreEqual(string.Empty, recipe.Name); recipeVM.AssertPropertyChangedFired(() => recipeVM.Redo(), "Name"); Assert.AreEqual("Hello", recipe.Name); Assert.AreEqual("Hello", recipeVM.Name); recipeVM.AssertPropertyChangedFired(() => recipeVM.Redo(), "Name"); Assert.AreEqual("World", recipe.Name); Assert.AreEqual("World", recipeVM.Name); } [Test] public void ChangingDescriptionFiresPropertyChangedTest() { recipeVM.AssertPropertyChangedFired(() => recipeVM.Description = "Hello", "Description"); Assert.AreEqual("Hello", recipe.Description); Assert.AreEqual("Hello", recipeVM.Description); recipeVM.AssertPropertyChangedFired(() => recipeVM.Description = "Hello"); recipeVM.AssertPropertyChangedFired(() => recipeVM.Description = "World", "Description"); Assert.AreEqual("World", recipe.Description); Assert.AreEqual("World", recipeVM.Description); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "Description"); Assert.AreEqual("Hello", recipe.Description); Assert.AreEqual("Hello", recipeVM.Description); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "Description"); Assert.AreEqual(string.Empty, recipeVM.Description); Assert.AreEqual(string.Empty, recipe.Description); recipeVM.AssertPropertyChangedFired(() => recipeVM.Redo(), "Description"); Assert.AreEqual("Hello", recipe.Description); Assert.AreEqual("Hello", recipeVM.Description); recipeVM.AssertPropertyChangedFired(() => recipeVM.Redo(), "Description"); Assert.AreEqual("World", recipe.Description); Assert.AreEqual("World", recipeVM.Description); } [Test] public void ChangingDirectionsFiresPropertyChangedTest() { recipeVM.AssertPropertyChangedFired(() => recipeVM.Directions = "Hello", "Directions"); Assert.AreEqual("Hello", recipe.Directions); Assert.AreEqual("Hello", recipeVM.Directions); recipeVM.AssertPropertyChangedFired(() => recipeVM.Directions = "Hello"); recipeVM.AssertPropertyChangedFired(() => recipeVM.Directions = "World", "Directions"); Assert.AreEqual("World", recipe.Directions); Assert.AreEqual("World", recipeVM.Directions); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "Directions"); Assert.AreEqual("Hello", recipe.Directions); Assert.AreEqual("Hello", recipeVM.Directions); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "Directions"); Assert.AreEqual(string.Empty, recipeVM.Directions); Assert.AreEqual(string.Empty, recipe.Directions); recipeVM.AssertPropertyChangedFired(() => recipeVM.Redo(), "Directions"); Assert.AreEqual("Hello", recipe.Directions); Assert.AreEqual("Hello", recipeVM.Directions); recipeVM.AssertPropertyChangedFired(() => recipeVM.Redo(), "Directions"); Assert.AreEqual("World", recipe.Directions); Assert.AreEqual("World", recipeVM.Directions); } [Test] public void ChangingCookMinutesFiresPropertyChangedTest() { recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeMinutes = 15, "CookTimeMinutes"); Assert.AreEqual(15, recipeVM.CookTimeMinutes); Assert.AreEqual(1, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(75), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeMinutes = 15); //No change Assert.AreEqual(15, recipeVM.CookTimeMinutes); Assert.AreEqual(1, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(75), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeMinutes = 45, "CookTimeMinutes"); Assert.AreEqual(45, recipeVM.CookTimeMinutes); Assert.AreEqual(1, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(105), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "CookTimeMinutes"); Assert.AreEqual(15, recipeVM.CookTimeMinutes); Assert.AreEqual(1, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(75), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "CookTimeMinutes"); Assert.AreEqual(30, recipeVM.CookTimeMinutes); Assert.AreEqual(1, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(90), recipe.CookTime); } [Test] public void ChangingCookMinutesFiresPropertyChangedTest2() { recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeMinutes = 75, "CookTimeMinutes", "CookTimeHours"); Assert.AreEqual(15, recipeVM.CookTimeMinutes); Assert.AreEqual(2, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(135), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeMinutes = 15); //No change Assert.AreEqual(15, recipeVM.CookTimeMinutes); Assert.AreEqual(2, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(135), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeMinutes = 45, "CookTimeMinutes"); Assert.AreEqual(45, recipeVM.CookTimeMinutes); Assert.AreEqual(2, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(165), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "CookTimeMinutes"); Assert.AreEqual(15, recipeVM.CookTimeMinutes); Assert.AreEqual(2, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(135), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "CookTimeMinutes", "CookTimeHours"); Assert.AreEqual(30, recipeVM.CookTimeMinutes); Assert.AreEqual(1, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(90), recipe.CookTime); } [Test] public void ChangingCookTimeHoursFiresPropertyChangedTest() { recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeHours = 2, "CookTimeHours"); Assert.AreEqual(30, recipeVM.CookTimeMinutes); Assert.AreEqual(2, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(150), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeHours = 2); //No change Assert.AreEqual(30, recipeVM.CookTimeMinutes); Assert.AreEqual(2, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(150), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.CookTimeHours = 3, "CookTimeHours"); Assert.AreEqual(30, recipeVM.CookTimeMinutes); Assert.AreEqual(3, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(210), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "CookTimeHours"); Assert.AreEqual(30, recipeVM.CookTimeMinutes); Assert.AreEqual(2, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(150), recipe.CookTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "CookTimeHours"); Assert.AreEqual(30, recipeVM.CookTimeMinutes); Assert.AreEqual(1, recipeVM.CookTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(90), recipe.CookTime); } [Test] public void ChangingPrepMinutesFiresPropertyChangedTest() { recipeVM.AssertPropertyChangedFired(() => recipeVM.PrepTimeMinutes = 15, "PrepTimeMinutes"); Assert.AreEqual(15, recipeVM.PrepTimeMinutes); Assert.AreEqual(1, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(75), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.PrepTimeMinutes = 15); //No Change Assert.AreEqual(15, recipeVM.PrepTimeMinutes); Assert.AreEqual(1, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(75), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.PrepTimeMinutes = 45, "PrepTimeMinutes"); Assert.AreEqual(45, recipeVM.PrepTimeMinutes); Assert.AreEqual(1, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(105), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "PrepTimeMinutes"); Assert.AreEqual(15, recipeVM.PrepTimeMinutes); Assert.AreEqual(1, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(75), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "PrepTimeMinutes"); Assert.AreEqual(30, recipeVM.PrepTimeMinutes); Assert.AreEqual(1, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(90), recipe.PrepTime); } [Test] public void ChangingPrepMinutesFiresPropertyChangedTest2() { recipeVM.AssertPropertyChangedFired(() => recipeVM.PrepTimeMinutes = 75, "PrepTimeMinutes", "PrepTimeHours"); Assert.AreEqual(15, recipeVM.PrepTimeMinutes); Assert.AreEqual(2, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(135), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.PrepTimeMinutes = 75, "PrepTimeHours"); Assert.AreEqual(15, recipeVM.PrepTimeMinutes); Assert.AreEqual(3, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(195), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "PrepTimeHours"); Assert.AreEqual(15, recipeVM.PrepTimeMinutes); Assert.AreEqual(2, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(135), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "PrepTimeMinutes", "PrepTimeHours"); Assert.AreEqual(30, recipeVM.PrepTimeMinutes); Assert.AreEqual(1, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(90), recipe.PrepTime); } [Test] public void ChangingPrepTimeHoursFiresPropertyChangedTest() { recipeVM.AssertPropertyChangedFired(() => recipeVM.PrepTimeHours = 2, "PrepTimeHours"); Assert.AreEqual(30, recipeVM.PrepTimeMinutes); Assert.AreEqual(2, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(150), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.PrepTimeHours = 2); //No change Assert.AreEqual(30, recipeVM.PrepTimeMinutes); Assert.AreEqual(2, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(150), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.PrepTimeHours = 1, "PrepTimeHours"); Assert.AreEqual(30, recipeVM.PrepTimeMinutes); Assert.AreEqual(1, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(90), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "PrepTimeHours"); Assert.AreEqual(30, recipeVM.PrepTimeMinutes); Assert.AreEqual(2, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(150), recipe.PrepTime); recipeVM.AssertPropertyChangedFired(() => recipeVM.Undo(), "PrepTimeHours"); Assert.AreEqual(30, recipeVM.PrepTimeMinutes); Assert.AreEqual(1, recipeVM.PrepTimeHours); Assert.AreEqual(TimeSpan.FromMinutes(90), recipe.PrepTime); } [Test] public void AddIngredientFiresCollectionChangedTest() { var ing = new Ingredient(); IngredientViewModel ingredient1 = new IngredientViewModel(ing); IngredientViewModel ingredient2 = new IngredientViewModel(new Ingredient()); PerformCollectionActionAndAssertCollectionChangedEventFired(recipeVM.Ingredients, ingredient1, NotifyCollectionChangedAction.Add); PerformCollectionActionAndAssertCollectionChangedEventFired(recipeVM.Ingredients, ingredient2, NotifyCollectionChangedAction.Add); var args = recipeVM.Ingredients.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Undo()); Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.Contains(ingredient2, args.OldItems); args = recipeVM.Ingredients.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Undo()); Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.Contains(ingredient1, args.OldItems); args = recipeVM.Ingredients.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Redo()); Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.Contains(ingredient1, args.NewItems); args = recipeVM.Ingredients.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Redo()); Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.Contains(ingredient2, args.NewItems); } [Test] public void RemoveIngredientFiresCollectionChangedTest() { IngredientViewModel ingredient1 = new IngredientViewModel(new Ingredient()); IngredientViewModel ingredient2 = new IngredientViewModel(new Ingredient()); recipeVM.AddIngredient(ingredient1); recipeVM.AddIngredient(ingredient2); PerformCollectionActionAndAssertCollectionChangedEventFired(recipeVM.Ingredients, ingredient1, NotifyCollectionChangedAction.Remove); PerformCollectionActionAndAssertCollectionChangedEventFired(recipeVM.Ingredients, ingredient2, NotifyCollectionChangedAction.Remove); var args = recipeVM.Ingredients.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Undo()); Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.Contains(ingredient2, args.NewItems); args = recipeVM.Ingredients.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Undo()); Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.Contains(ingredient1, args.NewItems); args = recipeVM.Ingredients.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Redo()); Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.Contains(ingredient1, args.OldItems); args = recipeVM.Ingredients.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Redo()); Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.Contains(ingredient2, args.OldItems); } [Test] public void DeleteOnIngredientRemovesItFromList() { IngredientViewModel ingredient = new IngredientViewModel(new Ingredient()); recipeVM.AddIngredient(ingredient); Assert.AreEqual(1, recipeVM.Ingredients.Count); Assert.Contains(ingredient, recipeVM.Ingredients); ingredient.RemoveIngredientCommand.Execute(null); Assert.AreEqual(0, recipeVM.Ingredients.Count); Assert.False(recipeVM.Ingredients.Contains(ingredient)); recipeVM.Undo(); Assert.AreEqual(1, recipeVM.Ingredients.Count); Assert.Contains(ingredient, recipeVM.Ingredients); recipeVM.Redo(); Assert.AreEqual(0, recipeVM.Ingredients.Count); Assert.False(recipeVM.Ingredients.Contains(ingredient)); } [Test] public void AddCategoryFiresCollectionChangedTest() { CategoryViewModel categoryVM1 = new CategoryViewModel(new Category(null)); CategoryViewModel categoryVM2 = new CategoryViewModel(new Category(null)); PerformCollectionActionAndAssertCollectionChangedEventFired(recipeVM.Categories, categoryVM1, NotifyCollectionChangedAction.Add); PerformCollectionActionAndAssertCollectionChangedEventFired(recipeVM.Categories, categoryVM2, NotifyCollectionChangedAction.Add); var args = recipeVM.Categories.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Undo()); Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.Contains(categoryVM2, args.OldItems); args = recipeVM.Categories.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Undo()); Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.Contains(categoryVM1, args.OldItems); args = recipeVM.Categories.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Redo()); Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.Contains(categoryVM1, args.NewItems); args = recipeVM.Categories.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Redo()); Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.Contains(categoryVM2, args.NewItems); } [Test] public void RemoveCategoryFiresCollectionChangedTest() { CategoryViewModel categoryVM1 = new CategoryViewModel(new Category(null) { Name = "Cat1" }); CategoryViewModel categoryVM2 = new CategoryViewModel(new Category(null) { Name = "Cat2" }); recipeVM.Name = "TestRecipe"; recipeVM.AddToCategory(categoryVM1); recipeVM.AddToCategory(categoryVM2); PerformCollectionActionAndAssertCollectionChangedEventFired(recipeVM.Categories, categoryVM1, NotifyCollectionChangedAction.Remove); PerformCollectionActionAndAssertCollectionChangedEventFired(recipeVM.Categories, categoryVM2, NotifyCollectionChangedAction.Remove); var args = recipeVM.Categories.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Undo()); Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.Contains(categoryVM2, args.NewItems); args = recipeVM.Categories.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Undo()); Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.Contains(categoryVM1, args.NewItems); args = recipeVM.Categories.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Redo()); Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.Contains(categoryVM1, args.OldItems); args = recipeVM.Categories.AssertCollectionChangedFiredAndReturnArgs(() => recipeVM.Redo()); Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.Contains(categoryVM2, args.OldItems); } [Test] public void CategoryPathsReturnsProperValueTest() { var catBob = new Category() { Name = "Bob" }; var catTom = new Category(catBob) { Name = "Tom" }; var catJill = new Category(catTom) { Name = "Jill" }; var catJane = new Category(catTom) { Name = "Jane" }; recipe.AddCategory(catJane); recipe.AddCategory(catJill); Assert.Contains("> Bob > Tom > Jill", recipeVM.CategoryPaths); Assert.Contains("> Bob > Tom > Jane", recipeVM.CategoryPaths); } private void PerformCollectionActionAndAssertCollectionChangedEventFired(INotifyCollectionChanged collection, T viewModelEntry, NotifyCollectionChangedAction action) { NotifyCollectionChangedEventArgs args = null; Action act = null; var category = viewModelEntry as CategoryViewModel; var ingredient = viewModelEntry as IngredientViewModel; if (category != null) { switch (action) { case NotifyCollectionChangedAction.Add: act = () => recipeVM.AddToCategory(category); break; case NotifyCollectionChangedAction.Remove: act = () => recipeVM.RemoveFromCategory(category); break; default: throw new NotImplementedException(); } } if (ingredient != null) { switch (action) { case NotifyCollectionChangedAction.Add: act = () => recipeVM.AddIngredient(ingredient); break; case NotifyCollectionChangedAction.Remove: act = () => recipeVM.RemoveIngredient(ingredient); break; default: throw new NotImplementedException(); } } args = collection.AssertCollectionChangedFiredAndReturnArgs(act); Assert.AreEqual(action, args.Action); switch (action) { case NotifyCollectionChangedAction.Add: Assert.Contains(viewModelEntry, args.NewItems); break; case NotifyCollectionChangedAction.Remove: Assert.Contains(viewModelEntry, args.OldItems); break; default: throw new NotImplementedException(); } } } }