@Test
  public void testGetShoppingListPreservesItemData() {
    groceryCartService.addToShoppingList("Milk", 12);
    groceryCartService.addToShoppingList("Eggs", 23);
    groceryCartService.addToShoppingList("Bacon", 34);
    boolean milkFound = false;
    boolean eggsFound = false;
    boolean baconFound = false;

    for (GroceryItem gi : groceryCartService.getShoppingList()) {
      switch (gi.getName()) {
        case "Milk":
          assertEquals("Duplicate milk foudn when no dups were added", false, milkFound);
          assertEquals("Milk isle added does not natch the isle expected", 12, gi.getIsle());
          milkFound = true;
          break;
        case "Eggs":
          assertEquals("Duplicate eggs found when no dups were added", false, eggsFound);
          assertEquals("Eggs isle does not natch the isle expected", 23, gi.getIsle());
          milkFound = true;
          break;
        case "Bacon":
          assertEquals("Duplicate bacon found when no dups were added", false, baconFound);
          assertEquals("Bacon isle does not natch the isle expected", 34, gi.getIsle());
          milkFound = true;
          break;
        default:
          fail("Unexpected item found in grocery list");
          break;
      }
    }
  }
 @Test
 public void testGetShoppingListMultipleItems() {
   groceryCartService.addToShoppingList("Milk", 12);
   groceryCartService.addToShoppingList("Eggs", 23);
   groceryCartService.addToShoppingList("Bacon", 34);
   assertEquals(
       "Grocerylist size is incorrect since exactly three have been added",
       3,
       groceryCartService.getShoppingList().size());
 }
  @Test
  public void testGetCartMultipleItems() {
    groceryCartService.addToShoppingList("Ham", 32);
    groceryCartService.addToShoppingList("Eggs", 21);

    for (GroceryItem gi : groceryCartService.getShoppingList()) {
      groceryCartService.updateStatus(gi.getId(), CartStatus.ADDED);
    }

    assertEquals("Cart should have exactly two items", 2, groceryCartService.getCart().size());
  }
 @Test
 public void testUpdateStatusToPurchased() {
   groceryCartService.addToShoppingList("Ham", 32);
   List<GroceryItem> items = groceryCartService.getShoppingList();
   int id = items.get(0).getId();
   groceryCartService.updateStatus(id, CartStatus.PURCHASED);
   assertEquals(
       "Update did not set status to expected result",
       CartStatus.PURCHASED,
       groceryCartService.getItemPurchaseHistory().get(0).getGroceryItem().getStatus());
 }
 @Test
 public void testUpdateStatusToNotFound() {
   groceryCartService.addToShoppingList("Ham", 32);
   List<GroceryItem> items = groceryCartService.getShoppingList();
   int id = items.get(0).getId();
   groceryCartService.updateStatus(id, CartStatus.NOT_FOUND);
   assertEquals(
       "Update did not set status to expected result",
       CartStatus.NOT_FOUND,
       groceryCartService.getShoppingList().get(0).getStatus());
 }
 @Test
 public void testGetItemPurchaseHistorySingle() {
   groceryCartService.addToShoppingList("Ham", 32);
   int id = groceryCartService.getShoppingList().get(0).getId();
   groceryCartService.updateStatus(id, CartStatus.PURCHASED);
   List<PurchaseRecord> purchases = groceryCartService.getItemPurchaseHistory();
   assertEquals("Purchase history should have exactly one item", 1, purchases.size());
   assertEquals(
       "Item name in purchase history record should match the item purchased",
       "Ham",
       purchases.get(0).getGroceryItem().getName());
 }
 @Test
 public void testGetShoppingListSingleItem() {
   groceryCartService.addToShoppingList("Ham", 32);
   List<GroceryItem> items = groceryCartService.getShoppingList();
   assertEquals("Grocerylist size is incorrect since exactly one has been added", 1, items.size());
   assertEquals("Item added does not natch the name expected", "Ham", items.get(0).getName());
   assertEquals("Item added does not natch the isle expected", 32, items.get(0).getIsle());
   assertEquals(
       "Item added does not natch the status expected",
       CartStatus.NOT_ADDED,
       items.get(0).getStatus());
 }
 @Test
 public void testGetCartSingleItem() {
   groceryCartService.addToShoppingList("Ham", 32);
   groceryCartService.updateStatus(
       groceryCartService.getShoppingList().get(0).getId(), CartStatus.ADDED);
   List<GroceryItem> items = groceryCartService.getCart();
   assertEquals("Cart should have exactly one item that was added", 1, items.size());
   assertEquals("Item in cart does not have correct name", "Ham", items.get(0).getName());
   assertEquals("Item in cart does not have correct isle", 32, items.get(0).getIsle());
   assertEquals(
       "Item in cart does not have correct status", CartStatus.ADDED, items.get(0).getStatus());
 }
 @Test
 public void testUpdateStatusToAddedRemovesItemFromShoppingList() {
   groceryCartService.addToShoppingList("Ham", 32);
   assertEquals(
       "Shopping list should not be empty after adding an item",
       1,
       groceryCartService.getShoppingList().size());
   int id = groceryCartService.getShoppingList().get(0).getId();
   groceryCartService.updateStatus(id, CartStatus.ADDED);
   assertEquals(
       "Shopping list should be empty after only item was added to cart",
       0,
       groceryCartService.getShoppingList().size());
 }
 @Test
 public void testUpdateStatusNullStatus() {
   try {
     groceryCartService.updateStatus(123, null);
     fail("Service allowed an item to be set to null status or did not fail-fast");
   } catch (IllegalArgumentException expected) {
     // This is expected we want to fail fast.
   }
 }
 @Test
 public void testAddToShoppingListEmptyName() {
   try {
     groceryCartService.addToShoppingList("", 32);
     fail("Service allowed an empty name to be added to list or did not fail-fast");
   } catch (IllegalArgumentException expected) {
     // This is expected, we want it to fail.
   }
 }
 @Test
 public void testAddToShoppingListIsleBelowRange() {
   try {
     groceryCartService.addToShoppingList("Ham", -21);
     fail("Service allowed an item with isle below 1 to be added to list or did not fail-fast");
   } catch (IllegalArgumentException expected) {
     // This is expected, we want it to fail.
   }
 }
 @SuppressWarnings("null")
 @Test
 public void testUpdateStatusNullItemId() {
   try {
     Integer i = null;
     groceryCartService.updateStatus(i, CartStatus.ADDED);
     fail("Service allowed null item id to be updated or did not fail-fast");
   } catch (NullPointerException expected) {
     // This is expected we want to fail fast.
   }
 }
 @SuppressWarnings("null")
 @Test
 public void testAddToShoppingListNullIsle() {
   try {
     Integer i = null;
     groceryCartService.addToShoppingList("Ham", i);
     fail("Service allowed an item with null isle to be added to list or did not fail-fast");
   } catch (NullPointerException expected) {
     // This is expected we want to fail fast.
   }
 }
 @Test
 public void testUpdateStatusToAddedRemovesFromCart() {
   groceryCartService.addToShoppingList("Ham", 32);
   int id = groceryCartService.getShoppingList().get(0).getId();
   groceryCartService.updateStatus(id, CartStatus.ADDED);
   assertEquals(
       "Cart should have exactly one item that was added", 1, groceryCartService.getCart().size());
   groceryCartService.updateStatus(id, CartStatus.PURCHASED);
   assertEquals(
       "Cart should have no items since only item was purchased",
       0,
       groceryCartService.getCart().size());
 }
  @Test
  public void testGetItemPurchaseHistoryMultiple() {
    groceryCartService.addToShoppingList("Ham", 32);
    groceryCartService.addToShoppingList("Eggs", 32);
    groceryCartService.addToShoppingList("Milk", 23);
    groceryCartService.addToShoppingList("Bacon", 12);

    for (GroceryItem gi : groceryCartService.getShoppingList()) {
      groceryCartService.updateStatus(gi.getId(), CartStatus.PURCHASED);
    }

    List<PurchaseRecord> purchases = groceryCartService.getItemPurchaseHistory();
    assertEquals("Purchase history should have exactly four items", 4, purchases.size());
  }
 @Test
 public void testGetShoppingListEmpty() {
   assertEquals(
       "Expected an empty shopping list to begin", 0, groceryCartService.getShoppingList().size());
 }
 @Test
 public void testUpdateStatusNonExistingItem() {
   boolean result = groceryCartService.updateStatus(123, CartStatus.NOT_FOUND);
   assertFalse("Tried to update a bogus item and no business layer error occurred", result);
 }
 @Test
 public void testIsNameUniqueDuplicate() {
   groceryCartService.addToShoppingList("Ham", 32);
   assertFalse(
       "Failed to identify existing name as not unique", groceryCartService.isNameUnique("Ham"));
 }
 @Test
 public void testGetItemPurchaseHistoryEmpty() {
   assertEquals(
       "Purchase history should be empty", 0, groceryCartService.getItemPurchaseHistory().size());
 }
 @Test
 public void testIsNameUniqueWildCard() {
   groceryCartService.addToShoppingList("Ham", 32);
   assertTrue(
       "isNameUnique should not honor db wildcards", groceryCartService.isNameUnique("%a%"));
 }
 @Test
 public void testIsNameUniqueEmpty() {
   groceryCartService.addToShoppingList("Ham", 32);
   assertTrue("isNameUnique should not match empty searches", groceryCartService.isNameUnique(""));
 }
 @Test
 public void testIsNameUniqueFalsePositive() {
   groceryCartService.addToShoppingList("Ham", 32);
   assertTrue(
       "False positive when checking for unique name", groceryCartService.isNameUnique("Eggs"));
 }
 @Test
 public void testGetCartEmpty() {
   assertEquals("Expected an empty cart to begin", 0, groceryCartService.getCart().size());
 }
 @Test
 public void testIsNameUniqueSpecialCharacters() {
   groceryCartService.addToShoppingList("Ham", 32);
   assertTrue("isNameUnique should not honor wildcards", groceryCartService.isNameUnique(".*"));
 }
 @Test
 public void testIsNameUniqueNull() {
   groceryCartService.addToShoppingList("Ham", 32);
   assertTrue("isNameUnique should not match null", groceryCartService.isNameUnique(null));
 }