diff --git a/source/TextBlade.Core.Tests/Characters/InventoryTests.cs b/source/TextBlade.Core.Tests/Characters/InventoryTests.cs new file mode 100644 index 0000000..b9b0bd6 --- /dev/null +++ b/source/TextBlade.Core.Tests/Characters/InventoryTests.cs @@ -0,0 +1,148 @@ +using NUnit.Framework; +using TextBlade.Core.Characters; + +namespace TextBlade.Core.Tests.Characters; + +[TestFixture] +public class InventoryTests +{ + [Test] + [TestCase("Apple", 1, true)] + [TestCase("Orange", 33, true)] + [TestCase("Pear", 777, true)] + [TestCase("Banana", 0, false)] + public void Has_ReturnsTrue_IfItemIsInInventoryInAnyQuantity(string item, int inventoryQuantity, bool expected) + { + // Arrange + var inventory = new Inventory(); + + for (var i = 0; i < inventoryQuantity; i++) + { + inventory.Add(item); + } + + // Act + var actual = inventory.Has(item); + + // Assert + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + [TestCase(null)] + [TestCase("")] + [TestCase(" ")] + public void Add_Throws_IfItemIsEmpty(string itemName) + { + // Arrange + var inventory = new Inventory(); + + // Act/Assert + Assert.Throws(() => inventory.Add(itemName, 7)); + } + + [Test] + [TestCase(0)] + [TestCase(-1)] + [TestCase(-20)] + [TestCase(-333)] + public void Add_Throws_IfQuantityIsNonPositive(int quantity) + { + // Arrange + var inventory = new Inventory(); + + // Act/Assert + Assert.Throws(() => inventory.Add("Super Awesome Item", quantity)); + } + + [Test] + public void Add_AddsToOrIncreasesQuantity() + { + // Arrange + var inventory = new Inventory(); + + // Act. With and without quantity; new and existing item. + inventory.Add("Tomato"); + inventory.Add("Carrot", 3); + inventory.Add("Bell Pepper"); + inventory.Add("Bell Pepper", 5); + + // Assert + var actual = inventory.ItemQuantities; + Assert.That(actual["Tomato"], Is.EqualTo(1)); + Assert.That(actual["Carrot"], Is.EqualTo(3)); + Assert.That(actual["Bell Pepper"], Is.EqualTo(6)); + } + + [Test] + [TestCase(null)] + [TestCase("")] + [TestCase(" ")] + public void Remove_Throws_IfItemIsEmpty(string itemName) + { + // Arrange + var inventory = new Inventory(); + + // Act/Assert + Assert.Throws(() => inventory.Remove(itemName)); + } + + [Test] + [TestCase(0)] + [TestCase(-1)] + [TestCase(-20)] + [TestCase(-333)] + public void Remove_Throws_IfQuantityIsNonPositive(int quantity) + { + // Arrange + var inventory = new Inventory(); + + // Act/Assert + Assert.Throws(() => inventory.Remove("Super Awesome Item", quantity)); + } + + [Test] + public void Remove_Throws_IfWeDontHaveTheItem() + { + // Arrange + var inventory = new Inventory(); + + // Act/Assert + Assert.Throws(() => inventory.Remove("Steak")); + } + + [Test] + [TestCase(4)] + [TestCase(44)] + [TestCase(444)] + public void Remove_Throws_IfWeDontHaveTheItemInSufficientQuantities(int askQuantity) + { + // Arrange + var inventory = new Inventory(); + inventory.Add("Steak", 3); + + // Act/Assert + Assert.Throws(() => inventory.Remove("Steak", askQuantity)); + } + + [Test] + public void Remove_DecrementsQuantity_AndRemovesItemIfQuantityBecomesZero() + { + // Arrange + // Arrange + var inventory = new Inventory(); + inventory.Add("Fried Chicken", 3); + inventory.Add("French Fries", 3); + inventory.Add("Onion Rings", 3); + + // Act + inventory.Remove("Fried Chicken"); + inventory.Remove("French Fries", 2); + inventory.Remove("Onion Rings", 3); + + // Assert. + Assert.That(inventory.ItemQuantities["Fried Chicken"], Is.EqualTo(2)); + Assert.That(inventory.ItemQuantities["French Fries"], Is.EqualTo(1)); + Assert.That(inventory.ItemQuantities.ContainsKey("Onion Rings"), Is.False); + } +} diff --git a/source/TextBlade.Core/Characters/Inventory.cs b/source/TextBlade.Core/Characters/Inventory.cs index 23ea577..03d7ff3 100644 --- a/source/TextBlade.Core/Characters/Inventory.cs +++ b/source/TextBlade.Core/Characters/Inventory.cs @@ -2,7 +2,7 @@ namespace TextBlade.Core.Characters; public class Inventory { - public Dictionary ItemQuantities = new(); + public Dictionary ItemQuantities { get; set; } = new(); public bool Has(string item) { @@ -13,12 +13,12 @@ public void Add(string item, int quantity = 1) { if (string.IsNullOrWhiteSpace(item)) { - throw new ArgumentException(nameof(item)); + throw new ArgumentException("Please specify a non-empty item", nameof(item)); } if (quantity <= 0) { - throw new ArgumentException(nameof(quantity)); + throw new ArgumentOutOfRangeException("Please specify a positive quantity,", nameof(quantity)); } if (!ItemQuantities.ContainsKey(item)) @@ -33,24 +33,24 @@ public void Remove(string item, int quantity = 1) { if (string.IsNullOrWhiteSpace(item)) { - throw new ArgumentException(nameof(item)); + throw new ArgumentException("Please specify a non-empty item name", nameof(item)); } if (quantity <= 0) { - throw new ArgumentException(nameof(quantity)); + throw new ArgumentOutOfRangeException("Please specify a positive quantity", nameof(quantity)); } if (!ItemQuantities.ContainsKey(item)) { - throw new ArgumentException($"Can't remove {item}, we don't have any."); + throw new ArgumentException($"Can't remove {item}, we don't have any.", nameof(item)); } else { var existingQuantity = ItemQuantities[item]; if (existingQuantity < quantity) { - throw new ArgumentException($"Can't remove {quantity} of {item}, we only have {existingQuantity}."); + throw new ArgumentOutOfRangeException($"Can't remove {quantity} of {item}, we only have {existingQuantity}.", nameof(quantity)); } ItemQuantities[item] -= quantity; diff --git a/source/TextBlade.Core/IO/Colours.cs b/source/TextBlade.Core/IO/Colours.cs index 608dde8..a887434 100644 --- a/source/TextBlade.Core/IO/Colours.cs +++ b/source/TextBlade.Core/IO/Colours.cs @@ -1,10 +1,8 @@ -using System; - namespace TextBlade.Core.IO; public static class Colours { - public static string Command = "red"; - public static string Highlight = "#00a"; + public const string Command = "red"; + public const string Highlight = "#00a"; }