diff --git a/python/gilded_rose.py b/python/gilded_rose.py index 4f21ea64..cd512d53 100755 --- a/python/gilded_rose.py +++ b/python/gilded_rose.py @@ -1,46 +1,190 @@ # -*- coding: utf-8 -*- -class GildedRose(object): +""" +Gilded Rose Kata implementation. - def __init__(self, items): - self.items = items - - def update_quality(self): - for item in self.items: - if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert": - if item.quality > 0: - if item.name != "Sulfuras, Hand of Ragnaros": - item.quality = item.quality - 1 - else: - if item.quality < 50: - item.quality = item.quality + 1 - if item.name == "Backstage passes to a TAFKAL80ETC concert": - if item.sell_in < 11: - if item.quality < 50: - item.quality = item.quality + 1 - if item.sell_in < 6: - if item.quality < 50: - item.quality = item.quality + 1 - if item.name != "Sulfuras, Hand of Ragnaros": - item.sell_in = item.sell_in - 1 - if item.sell_in < 0: - if item.name != "Aged Brie": - if item.name != "Backstage passes to a TAFKAL80ETC concert": - if item.quality > 0: - if item.name != "Sulfuras, Hand of Ragnaros": - item.quality = item.quality - 1 - else: - item.quality = item.quality - item.quality - else: - if item.quality < 50: - item.quality = item.quality + 1 +This module defines the Item class, helper functions for quality and sell_in +management, and strategy classes for different item types. The GildedRose class +delegates item updates to the appropriate strategy. +""" class Item: - def __init__(self, name, sell_in, quality): + """ + Represents an inventory item. + + Attributes: + name (str): The name of the item. + sell_in (int): Number of days to sell the item. + quality (int): Quality value of the item. + """ + + def __init__(self, name: str, sell_in: int, quality: int) -> None: self.name = name self.sell_in = sell_in self.quality = quality - def __repr__(self): - return "%s, %s, %s" % (self.name, self.sell_in, self.quality) + def __repr__(self) -> str: + return f"{self.name}, {self.sell_in}, {self.quality}" + + +# --- Helper functions --- + +def clamp_quality(item: Item) -> None: + """ + Ensure quality is within valid bounds (0–50), except Sulfuras which is fixed at 80. + + Args: + item (Item): The item to clamp. + """ + if item.name != "Sulfuras, Hand of Ragnaros": + if item.quality < 0: + item.quality = 0 + elif item.quality > 50: + item.quality = 50 + + +def increase_quality(item: Item, amount: int = 1) -> None: + """ + Increase item quality by a given amount, respecting quality bounds. + + Args: + item (Item): The item to update. + amount (int): Amount to increase quality by (default 1). + """ + item.quality += amount + clamp_quality(item) + + +def decrease_quality(item: Item, amount: int = 1) -> None: + """ + Decrease item quality by a given amount, respecting quality bounds. + + Args: + item (Item): The item to update. + amount (int): Amount to decrease quality by (default 1). + """ + item.quality -= amount + clamp_quality(item) + + +def decrease_sell_in(item: Item, amount: int = 1) -> None: + """ + Decrease item sell_in by a given amount, except Sulfuras which never changes. + + Args: + item (Item): The item to update. + amount (int): Amount to decrease sell_in by (default 1). + """ + if item.name != "Sulfuras, Hand of Ragnaros": + item.sell_in -= amount + + +# --- Strategy classes --- + +class ItemUpdater: + """Abstract base class for item update strategies.""" + + def update(self, item: Item) -> None: + """Update the given item. Must be implemented by subclasses.""" + raise NotImplementedError + + +class SulfurasUpdater(ItemUpdater): + """Updater for Sulfuras (legendary item).""" + + def update(self, item: Item) -> None: + # Sulfuras never changes + return + + +class AgedBrieUpdater(ItemUpdater): + """Updater for Aged Brie (quality increases over time).""" + + def update(self, item: Item) -> None: + decrease_sell_in(item, 1) + if item.sell_in >= 0: + increase_quality(item, 1) + else: + increase_quality(item, 2) + + +class BackstagePassUpdater(ItemUpdater): + """Updater for Backstage passes (quality increases, then drops to 0 after concert).""" + + def update(self, item: Item) -> None: + decrease_sell_in(item, 1) + if item.sell_in < 0: + item.quality = 0 + elif item.sell_in < 5: + increase_quality(item, 3) + elif item.sell_in < 10: + increase_quality(item, 2) + else: + increase_quality(item, 1) + + +class NormalItemUpdater(ItemUpdater): + """Updater for normal items (quality decreases over time).""" + + def update(self, item: Item) -> None: + decrease_sell_in(item, 1) + if item.sell_in >= 0: + decrease_quality(item, 1) + else: + decrease_quality(item, 2) + +#new requirement +class ConjuredItemUpdater(ItemUpdater): + """Updater for Conjured items (degrade twice as fast).""" + + def update(self, item: Item) -> None: + decrease_sell_in(item, 1) + if item.sell_in >= 0: + decrease_quality(item, 2) + else: + decrease_quality(item, 4) + + +# --- Factory --- + +def get_updater(item: Item) -> ItemUpdater: + """ + Return the appropriate updater strategy for the given item. + + Args: + item (Item): The item to update. + + Returns: + ItemUpdater: Strategy instance for the item type. + """ + name = item.name + if name == "Sulfuras, Hand of Ragnaros": + return SulfurasUpdater() + if name == "Aged Brie": + return AgedBrieUpdater() + if name == "Backstage passes to a TAFKAL80ETC concert": + return BackstagePassUpdater() + if "Conjured" in name: + return ConjuredItemUpdater() + return NormalItemUpdater() + + +# --- Main class --- + +class GildedRose: + """ + Main class for updating inventory items. + + Attributes: + items (list[Item]): List of items to update. + """ + + def __init__(self, items: list[Item]) -> None: + self.items = items + + def update_quality(self) -> None: + """Update quality and sell_in for all items in inventory.""" + for item in self.items: + updater = get_updater(item) + updater.update(item) \ No newline at end of file diff --git a/python/tests/approved_files/test_gilded_rose_approvals.test_gilded_rose_approvals.approved.txt b/python/tests/approved_files/test_gilded_rose_approvals.test_gilded_rose_approvals.approved.txt index e69de29b..4e7237ff 100644 --- a/python/tests/approved_files/test_gilded_rose_approvals.test_gilded_rose_approvals.approved.txt +++ b/python/tests/approved_files/test_gilded_rose_approvals.test_gilded_rose_approvals.approved.txt @@ -0,0 +1,373 @@ +OMGHAI! +-------- day 0 -------- +name, sellIn, quality ++5 Dexterity Vest, 10, 20 +Aged Brie, 2, 0 +Elixir of the Mongoose, 5, 7 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 15, 20 +Backstage passes to a TAFKAL80ETC concert, 10, 49 +Backstage passes to a TAFKAL80ETC concert, 5, 49 +Conjured Mana Cake, 3, 6 + +-------- day 1 -------- +name, sellIn, quality ++5 Dexterity Vest, 9, 19 +Aged Brie, 1, 1 +Elixir of the Mongoose, 4, 6 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 14, 21 +Backstage passes to a TAFKAL80ETC concert, 9, 50 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Conjured Mana Cake, 2, 4 + +-------- day 2 -------- +name, sellIn, quality ++5 Dexterity Vest, 8, 18 +Aged Brie, 0, 2 +Elixir of the Mongoose, 3, 5 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 13, 22 +Backstage passes to a TAFKAL80ETC concert, 8, 50 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Conjured Mana Cake, 1, 2 + +-------- day 3 -------- +name, sellIn, quality ++5 Dexterity Vest, 7, 17 +Aged Brie, -1, 4 +Elixir of the Mongoose, 2, 4 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 12, 23 +Backstage passes to a TAFKAL80ETC concert, 7, 50 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Conjured Mana Cake, 0, 0 + +-------- day 4 -------- +name, sellIn, quality ++5 Dexterity Vest, 6, 16 +Aged Brie, -2, 6 +Elixir of the Mongoose, 1, 3 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 11, 24 +Backstage passes to a TAFKAL80ETC concert, 6, 50 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Conjured Mana Cake, -1, 0 + +-------- day 5 -------- +name, sellIn, quality ++5 Dexterity Vest, 5, 15 +Aged Brie, -3, 8 +Elixir of the Mongoose, 0, 2 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 10, 25 +Backstage passes to a TAFKAL80ETC concert, 5, 50 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Conjured Mana Cake, -2, 0 + +-------- day 6 -------- +name, sellIn, quality ++5 Dexterity Vest, 4, 14 +Aged Brie, -4, 10 +Elixir of the Mongoose, -1, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 9, 27 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Conjured Mana Cake, -3, 0 + +-------- day 7 -------- +name, sellIn, quality ++5 Dexterity Vest, 3, 13 +Aged Brie, -5, 12 +Elixir of the Mongoose, -2, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 8, 29 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Conjured Mana Cake, -4, 0 + +-------- day 8 -------- +name, sellIn, quality ++5 Dexterity Vest, 2, 12 +Aged Brie, -6, 14 +Elixir of the Mongoose, -3, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 7, 31 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Conjured Mana Cake, -5, 0 + +-------- day 9 -------- +name, sellIn, quality ++5 Dexterity Vest, 1, 11 +Aged Brie, -7, 16 +Elixir of the Mongoose, -4, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 6, 33 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Conjured Mana Cake, -6, 0 + +-------- day 10 -------- +name, sellIn, quality ++5 Dexterity Vest, 0, 10 +Aged Brie, -8, 18 +Elixir of the Mongoose, -5, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 5, 35 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Conjured Mana Cake, -7, 0 + +-------- day 11 -------- +name, sellIn, quality ++5 Dexterity Vest, -1, 8 +Aged Brie, -9, 20 +Elixir of the Mongoose, -6, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 4, 38 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Conjured Mana Cake, -8, 0 + +-------- day 12 -------- +name, sellIn, quality ++5 Dexterity Vest, -2, 6 +Aged Brie, -10, 22 +Elixir of the Mongoose, -7, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 3, 41 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Conjured Mana Cake, -9, 0 + +-------- day 13 -------- +name, sellIn, quality ++5 Dexterity Vest, -3, 4 +Aged Brie, -11, 24 +Elixir of the Mongoose, -8, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 2, 44 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Conjured Mana Cake, -10, 0 + +-------- day 14 -------- +name, sellIn, quality ++5 Dexterity Vest, -4, 2 +Aged Brie, -12, 26 +Elixir of the Mongoose, -9, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 1, 47 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Conjured Mana Cake, -11, 0 + +-------- day 15 -------- +name, sellIn, quality ++5 Dexterity Vest, -5, 0 +Aged Brie, -13, 28 +Elixir of the Mongoose, -10, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Conjured Mana Cake, -12, 0 + +-------- day 16 -------- +name, sellIn, quality ++5 Dexterity Vest, -6, 0 +Aged Brie, -14, 30 +Elixir of the Mongoose, -11, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Conjured Mana Cake, -13, 0 + +-------- day 17 -------- +name, sellIn, quality ++5 Dexterity Vest, -7, 0 +Aged Brie, -15, 32 +Elixir of the Mongoose, -12, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Conjured Mana Cake, -14, 0 + +-------- day 18 -------- +name, sellIn, quality ++5 Dexterity Vest, -8, 0 +Aged Brie, -16, 34 +Elixir of the Mongoose, -13, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Conjured Mana Cake, -15, 0 + +-------- day 19 -------- +name, sellIn, quality ++5 Dexterity Vest, -9, 0 +Aged Brie, -17, 36 +Elixir of the Mongoose, -14, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Conjured Mana Cake, -16, 0 + +-------- day 20 -------- +name, sellIn, quality ++5 Dexterity Vest, -10, 0 +Aged Brie, -18, 38 +Elixir of the Mongoose, -15, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Conjured Mana Cake, -17, 0 + +-------- day 21 -------- +name, sellIn, quality ++5 Dexterity Vest, -11, 0 +Aged Brie, -19, 40 +Elixir of the Mongoose, -16, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Conjured Mana Cake, -18, 0 + +-------- day 22 -------- +name, sellIn, quality ++5 Dexterity Vest, -12, 0 +Aged Brie, -20, 42 +Elixir of the Mongoose, -17, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Conjured Mana Cake, -19, 0 + +-------- day 23 -------- +name, sellIn, quality ++5 Dexterity Vest, -13, 0 +Aged Brie, -21, 44 +Elixir of the Mongoose, -18, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Conjured Mana Cake, -20, 0 + +-------- day 24 -------- +name, sellIn, quality ++5 Dexterity Vest, -14, 0 +Aged Brie, -22, 46 +Elixir of the Mongoose, -19, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Conjured Mana Cake, -21, 0 + +-------- day 25 -------- +name, sellIn, quality ++5 Dexterity Vest, -15, 0 +Aged Brie, -23, 48 +Elixir of the Mongoose, -20, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Conjured Mana Cake, -22, 0 + +-------- day 26 -------- +name, sellIn, quality ++5 Dexterity Vest, -16, 0 +Aged Brie, -24, 50 +Elixir of the Mongoose, -21, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Backstage passes to a TAFKAL80ETC concert, -21, 0 +Conjured Mana Cake, -23, 0 + +-------- day 27 -------- +name, sellIn, quality ++5 Dexterity Vest, -17, 0 +Aged Brie, -25, 50 +Elixir of the Mongoose, -22, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Backstage passes to a TAFKAL80ETC concert, -22, 0 +Conjured Mana Cake, -24, 0 + +-------- day 28 -------- +name, sellIn, quality ++5 Dexterity Vest, -18, 0 +Aged Brie, -26, 50 +Elixir of the Mongoose, -23, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Backstage passes to a TAFKAL80ETC concert, -23, 0 +Conjured Mana Cake, -25, 0 + +-------- day 29 -------- +name, sellIn, quality ++5 Dexterity Vest, -19, 0 +Aged Brie, -27, 50 +Elixir of the Mongoose, -24, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Backstage passes to a TAFKAL80ETC concert, -24, 0 +Conjured Mana Cake, -26, 0 + +-------- day 30 -------- +name, sellIn, quality ++5 Dexterity Vest, -20, 0 +Aged Brie, -28, 50 +Elixir of the Mongoose, -25, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Backstage passes to a TAFKAL80ETC concert, -25, 0 +Conjured Mana Cake, -27, 0 + diff --git a/python/tests/test_gilded_rose.py b/python/tests/test_gilded_rose.py index 1c92f638..d468c638 100644 --- a/python/tests/test_gilded_rose.py +++ b/python/tests/test_gilded_rose.py @@ -1,16 +1,155 @@ # -*- coding: utf-8 -*- import unittest - from gilded_rose import Item, GildedRose class GildedRoseTest(unittest.TestCase): - def test_foo(self): - items = [Item("foo", 0, 0)] - gilded_rose = GildedRose(items) - gilded_rose.update_quality() - self.assertEqual("fixme", items[0].name) - + # Normal items + + def test_normal_item_before_sell_date_degrades_by_1(self): + items = [Item("Normal Item", 10, 20)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(9, items[0].sell_in) + self.assertEqual(19, items[0].quality) + + def test_normal_item_after_sell_date_degrades_by_2(self): + items = [Item("Normal Item", 0, 20)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(-1, items[0].sell_in) + self.assertEqual(18, items[0].quality) + + def test_normal_item_quality_never_negative(self): + items = [Item("Normal Item", 10, 0)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(9, items[0].sell_in) + self.assertEqual(0, items[0].quality) + + # Aged Brie + + def test_aged_brie_increases_by_1_before_sell_date(self): + items = [Item("Aged Brie", 2, 0)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(1, items[0].sell_in) + self.assertEqual(1, items[0].quality) + + def test_aged_brie_increases_by_2_after_sell_date(self): + items = [Item("Aged Brie", 0, 0)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(-1, items[0].sell_in) + self.assertEqual(2, items[0].quality) + + def test_aged_brie_quality_capped_at_50(self): + items = [Item("Aged Brie", 5, 50)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(4, items[0].sell_in) + self.assertEqual(50, items[0].quality) + + # Backstage passes + + def test_backstage_passes_increase_by_1_when_sell_in_gt_10(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(14, items[0].sell_in) + self.assertEqual(21, items[0].quality) + + def test_backstage_passes_increase_by_2_when_sell_in_le_10_gt_5(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 10, 20)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(9, items[0].sell_in) + self.assertEqual(22, items[0].quality) + + def test_backstage_passes_increase_by_3_when_sell_in_le_5_gt_0(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 5, 20)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(4, items[0].sell_in) + self.assertEqual(23, items[0].quality) + + def test_backstage_passes_drop_to_zero_after_concert(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 0, 20)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(-1, items[0].sell_in) + self.assertEqual(0, items[0].quality) + + def test_backstage_passes_quality_capped_at_50(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 5, 49)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(4, items[0].sell_in) + self.assertEqual(50, items[0].quality) # 49 + 3 => capped at 50 + + # Sulfuras + + def test_sulfuras_never_changes(self): + items = [Item("Sulfuras, Hand of Ragnaros", 0, 80)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(0, items[0].sell_in) + self.assertEqual(80, items[0].quality) + + #Conjured items (new requirement) + + def test_conjured_item_degrades_by_2_before_sell_date(self): + items = [Item("Conjured Mana Cake", 5, 10)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(4, items[0].sell_in) + self.assertEqual(8, items[0].quality) + + def test_conjured_item_degrades_by_4_after_sell_date(self): + items = [Item("Conjured Mana Cake", 0, 10)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(-1, items[0].sell_in) + self.assertEqual(6, items[0].quality) + + def test_conjured_item_quality_never_negative(self): + items = [Item("Conjured Mana Cake", 0, 3)] + gr = GildedRose(items) + + gr.update_quality() + + self.assertEqual(-1, items[0].sell_in) + self.assertEqual(0, items[0].quality) + + if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file