diff --git a/Refactoring/Data/Products.json b/Refactoring/Data/Products.json index 66d190f..40aa3cd 100644 --- a/Refactoring/Data/Products.json +++ b/Refactoring/Data/Products.json @@ -2,36 +2,49 @@ { "Name": "Chips", "Price": 1.49, - "Quantity": 50 + "Quantity": 50, + "Id": 1 }, { "Name": "Cookies", "Price": 1.0, - "Quantity": 100 + "Quantity": 100, + "Id": 2 }, { "Name": "Gum", "Price": 0.85, - "Quantity": 50 + "Quantity": 50, + "Id": 3 }, { "Name": "Pop", "Price": 0.75, - "Quantity": 75 + "Quantity": 75, + "Id": 4 }, { "Name": "Candy", "Price": 0.85, - "Quantity": 30 + "Quantity": 30, + "Id": 5 }, { "Name": "Chocolate Bars", "Price": 1.25, - "Quantity": 25 + "Quantity": 25, + "Id": 6 }, { "Name": "Nuts", "Price": 1.0, - "Quantity": 1 + "Quantity": 1, + "Id": 7 + }, + { + "Name": "Soup", + "Price": 1.25, + "Quantity": 50, + "Id": 8 } ] \ No newline at end of file diff --git a/Refactoring/Product.cs b/Refactoring/Product.cs index c9ceee5..5ec260f 100644 --- a/Refactoring/Product.cs +++ b/Refactoring/Product.cs @@ -16,5 +16,12 @@ public class Product public double Price; [JsonProperty("Quantity")] public int Qty; + [JsonProperty("Id")] + public int Id; + + public bool HasStock() + { + return Qty > 0; + } } } diff --git a/Refactoring/Tusc.cs b/Refactoring/Tusc.cs index 79d2289..99707fe 100644 --- a/Refactoring/Tusc.cs +++ b/Refactoring/Tusc.cs @@ -14,6 +14,8 @@ public class Tusc private static List ProductList; private static User LoggedInUser; private static int ProductCount; + private const string QUIT_APPLICATION_INPUT = "quit"; + private const int QUIT_INDEX = -1; public static void Start(List users, List products) { @@ -50,7 +52,7 @@ private static void OrderProducts() { ShowProductList(); SelectedProductNumber = GetValidUserProductSelection(); - if (SelectedProductNumber == ProductList.Count + 1) + if (SelectedProductNumber == QUIT_INDEX) { UpdateCurrentUsersBalance(); break; @@ -58,7 +60,7 @@ private static void OrderProducts() else { Console.WriteLine(); - Console.WriteLine("You want to buy: " + ProductList[SelectedProductNumber-1].Name); + Console.WriteLine("You want to buy: " + ProductList[SelectedProductNumber - 1].Name); Console.WriteLine("Your balance is " + LoggedInUser.Balance.ToString("C")); QuantityOrdered = GetValidUserProductQuantity(); @@ -91,19 +93,19 @@ private static void OrderProduct(int SelectedProductNumber, int QuantityOrdered) private static void UpdateBalance(int SelectedProductNumber, int QuantityOrdered) { - LoggedInUser.Balance = LoggedInUser.Balance - (ProductList[SelectedProductNumber-1].Price * QuantityOrdered); + LoggedInUser.Balance = LoggedInUser.Balance - (ProductList[SelectedProductNumber - 1].Price * QuantityOrdered); } private static void RemoveItemsFromInventory(int SelectedProductNumber, int QuantityOrdered) { - ProductList[SelectedProductNumber-1].Qty = ProductList[SelectedProductNumber-1].Qty - QuantityOrdered; + ProductList[SelectedProductNumber - 1].Qty = ProductList[SelectedProductNumber - 1].Qty - QuantityOrdered; } private static void ShowOrderConfirmationMessage(int SelectedProductNumber, int QuantityOrdered) { Console.Clear(); Console.ForegroundColor = ConsoleColor.Green; - Console.WriteLine("You bought " + QuantityOrdered + " " + ProductList[SelectedProductNumber-1].Name); + Console.WriteLine("You bought " + QuantityOrdered + " " + ProductList[SelectedProductNumber - 1].Name); Console.WriteLine("Your new balance is " + LoggedInUser.Balance.ToString("C")); Console.ResetColor(); } @@ -111,12 +113,12 @@ private static void ShowOrderConfirmationMessage(int SelectedProductNumber, int private static bool VerifyStockOnHand(int SelectedProductNumber, int QuantityOrdered) { bool stockOnHand = true; - if (ProductList[SelectedProductNumber-1].Qty <= QuantityOrdered) + if (ProductList[SelectedProductNumber - 1].Qty < QuantityOrdered) { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(); - Console.WriteLine("Sorry, " + ProductList[SelectedProductNumber-1].Name + " is out of stock"); + Console.WriteLine("Sorry, " + ProductList[SelectedProductNumber - 1].Name + " is out of stock"); Console.ResetColor(); stockOnHand = false; } @@ -126,7 +128,7 @@ private static bool VerifyStockOnHand(int SelectedProductNumber, int QuantityOrd private static bool VerifyUserFundsForSelectedPurchase(int SelectedProductNumber, int QuantityOrdered) { bool fundsAvailable = true; - if ((LoggedInUser.Balance - (ProductList[SelectedProductNumber-1].Price * QuantityOrdered)) < 0) + if ((LoggedInUser.Balance - (ProductList[SelectedProductNumber - 1].Price * QuantityOrdered)) < 0) { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; @@ -194,22 +196,27 @@ private static int GetValidUserProductSelection() { int productNumber; while (true) - { - Console.WriteLine("Enter the product number:"); + { + Console.WriteLine("Enter the product number:"); string ProductNumberEntered = Console.ReadLine(); - if (validateProduct(ProductNumberEntered, out productNumber)) + if (ProductNumberEntered.Equals(QUIT_APPLICATION_INPUT, StringComparison.InvariantCultureIgnoreCase)) + { + productNumber = QUIT_INDEX; + break; + } + else if (ValidateProduct(ProductNumberEntered, out productNumber)) { - break; + break; } - } + } return productNumber; } - private static bool validateProduct(string ProductNumberEntered, out int productNumber ) + private static bool ValidateProduct(string ProductNumberEntered, out int productNumber) { bool validProductSelected = false; - - if (Int32.TryParse(ProductNumberEntered, out productNumber) && (productNumber <= ProductCount + 1)) + + if (Int32.TryParse(ProductNumberEntered, out productNumber) && (ProductNumberMatchesProductId(ProductNumberEntered))) { validProductSelected = true; } @@ -220,11 +227,20 @@ private static bool validateProduct(string ProductNumberEntered, out int product return validProductSelected; } + private static bool ProductNumberMatchesProductId(string productNumber) + { + foreach (Product product in ProductList) + { + if (product.Id.ToString() == productNumber) return true; + } + return false; + } + private static void ShowProductNumberInvalidMessage() { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(""); - Console.WriteLine("Product numbers must be numeric in the range of 1 - " + (ProductCount + 1).ToString()); + Console.WriteLine("Product numbers must be numeric in the range of 1 - " + (ProductCount).ToString()); Console.WriteLine(""); Console.ResetColor(); } @@ -236,9 +252,9 @@ private static void ShowProductList() for (int i = 0; i < ProductCount; i++) { Product prod = ProductList[i]; - Console.WriteLine(i + 1 + ": " + prod.Name + " (" + prod.Price.ToString("C") + ")"); + if (prod.HasStock()) Console.WriteLine(prod.Id + ": " + prod.Name + " (" + prod.Price.ToString("C") + ")"); } - Console.WriteLine(ProductList.Count + 1 + ": Exit"); + Console.WriteLine("Type quit to exit the application."); } private static void ShowRemainingBalance() @@ -265,7 +281,7 @@ private static bool LoginUser() User user = new User(); GetUserCredentials(ref userName, ref userPassword); - if (ValidateUserCredentials(userName, userPassword, ref user)) + if (ValidateUserCredentials(userName, userPassword, ref user)) { LoggedInUser = user; ShowSuccessfulLoginMessage(); @@ -276,7 +292,7 @@ private static bool LoginUser() ShowFailedCredentialsMessage(); } return validatedUser; - } + } private static void GetUserCredentials(ref string userName, ref string userPassword) { @@ -298,7 +314,7 @@ private static bool ValidateUserPassword(User userName, string password) { bool passwordValid = false; if (userName.Password == password) - { + { passwordValid = true; } return passwordValid; @@ -321,7 +337,7 @@ private static bool ValidateUserCredentials(string userName, string userPassword { bool validCredentials = false; - if(FindUserInUserList(userName, ref user) && ValidateUserPassword(user, userPassword)) + if (FindUserInUserList(userName, ref user) && ValidateUserPassword(user, userPassword)) { validCredentials = true; } @@ -346,7 +362,7 @@ private static bool FindUserInUserList(string name, ref User foundUser) return UserIsFound; } - + private static void ShowWelcomeMessage() { diff --git a/UnitTestProject/UnitTests.cs b/UnitTestProject/UnitTests.cs index 141b588..380cd4a 100644 --- a/UnitTestProject/UnitTests.cs +++ b/UnitTestProject/UnitTests.cs @@ -17,7 +17,7 @@ public class UnitTests private List products; private List originalProducts; - private int EXIT_NUMBER = 0; + private string EXIT_VALUE = "quit"; [SetUp] public void Test_Initialize() @@ -29,8 +29,6 @@ public void Test_Initialize() // Load products from data file originalProducts = JsonConvert.DeserializeObject>(File.ReadAllText(@"Data/Products.json")); products = DeepCopy>(originalProducts); - - EXIT_NUMBER = products.Count + 1; } [TearDown] @@ -54,7 +52,7 @@ public void Test_StartingTuscFromMainDoesNotThrowAnException() { Console.SetOut(writer); - using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_NUMBER + "\r\n\r\n")) + using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_VALUE + "\r\n\r\n")) { Console.SetIn(reader); @@ -70,7 +68,7 @@ public void Test_TuscDoesNotThrowAnException() { Console.SetOut(writer); - using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_NUMBER + "\r\n\r\n")) + using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_VALUE + "\r\n\r\n")) { Console.SetIn(reader); @@ -138,7 +136,7 @@ public void Test_UserCanCancelPurchase() { Console.SetOut(writer); - using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n0\r\n" + EXIT_NUMBER + "\r\n\r\n")) + using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n0\r\n" + EXIT_VALUE + "\r\n\r\n")) { Console.SetIn(reader); @@ -161,7 +159,7 @@ public void Test_ErrorOccursWhenBalanceLessThanPrice() { Console.SetOut(writer); - using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_NUMBER + "\r\n\r\n")) + using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_VALUE + "\r\n\r\n")) { Console.SetIn(reader); @@ -177,13 +175,13 @@ public void Test_ErrorOccursWhenProductOutOfStock() { // Update data file List tempProducts = DeepCopy>(originalProducts); - tempProducts.Where(u => u.Name == "Chips").Single().Qty = 0; + tempProducts.Where(u => u.Name == "Chips").Single().Qty = 1; using (var writer = new StringWriter()) { Console.SetOut(writer); - using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_NUMBER + "\r\n\r\n")) + using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n2\r\n" + EXIT_VALUE + "\r\n\r\n")) { Console.SetIn(reader); @@ -194,6 +192,50 @@ public void Test_ErrorOccursWhenProductOutOfStock() } } + [Test] + public void Test_ProductsWithZeroQuantityDoNotAppearInMenu() + { + // Update data file + List tempProducts = DeepCopy>(originalProducts); + tempProducts.Where(u => u.Name == "Chips").Single().Qty = 0; + + using (var writer = new StringWriter()) + { + Console.SetOut(writer); + + using (var reader = new StringReader("Jason\r\nsfa\r\n" + EXIT_VALUE + "\r\n\r\n")) + { + Console.SetIn(reader); + + Tusc.Start(users, tempProducts); + } + + Assert.IsFalse(writer.ToString().Contains(": Chips")); + } + } + + [Test] + public void Test_UserCanPurchaseProductWhenOnlyOneInStock() + { + // Update data file + List tempProducts = DeepCopy>(originalProducts); + tempProducts.Where(u => u.Name == "Chips").Single().Qty = 1; + + using (var writer = new StringWriter()) + { + Console.SetOut(writer); + + using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_VALUE + "\r\n\r\n")) + { + Console.SetIn(reader); + + Tusc.Start(users, tempProducts); + } + + Assert.IsTrue(writer.ToString().Contains("You bought 1 Chips")); + } + } + [Test] public void Test_ProductListContainsExitItem() { @@ -201,35 +243,35 @@ public void Test_ProductListContainsExitItem() { Console.SetOut(writer); - using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_NUMBER + "\r\n\r\n")) + using (var reader = new StringReader("Jason\r\nsfa\r\n1\r\n1\r\n" + EXIT_VALUE + "\r\n\r\n")) { Console.SetIn(reader); Tusc.Start(users, products); } - Assert.IsTrue(writer.ToString().Contains("" + EXIT_NUMBER + ": Exit")); + Assert.IsTrue(writer.ToString().Contains("Type quit to exit the application")); } } - //[Test] - //public void Test_UserCanExitByEnteringQuit() - //{ - // using (var writer = new StringWriter()) - // { - // Console.SetOut(writer); + [Test] + public void Test_UserCanExitByEnteringQuit() + { + using (var writer = new StringWriter()) + { + Console.SetOut(writer); - // using (var reader = new StringReader("Jason\r\nsfa\r\nquit\r\n\r\n")) - // { - // Console.SetIn(reader); + using (var reader = new StringReader("Jason\r\nsfa\r\nquit\r\n\r\n")) + { + Console.SetIn(reader); - // Tusc.Start(users, products); - // } + Tusc.Start(users, products); + } - // Assert.IsTrue(writer.ToString().Contains("Type quit to exit the application")); - // Assert.IsTrue(writer.ToString().Contains("Press Enter key to exit")); - // } - //} + Assert.IsTrue(writer.ToString().Contains("Type quit to exit the application")); + Assert.IsTrue(writer.ToString().Contains("Press Enter key to exit")); + } + } private static T DeepCopy(T obj) {