From 557c1787c0e1a6fc03a1b2dfb64ef851ed969b09 Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Sun, 9 May 2021 21:30:26 +0200 Subject: [PATCH] Add GildedRose-Refactoring-Kata refactoring --- src/main/java/com/gildedrose/GildedRose.java | 66 ++-------- .../gildedrose/product/category/AgedBrie.java | 38 ++++++ .../product/category/BackStagePass.java | 51 +++++++ .../gildedrose/product/category/Conjured.java | 32 +++++ .../product/category/Legendary.java | 42 ++++++ .../gildedrose/updater/GenericUpdater.java | 124 ++++++++++++++++++ .../java/com/gildedrose/updater/Updater.java | 15 +++ .../gildedrose/updater/UpdaterFactory.java | 54 ++++++++ .../java/com/gildedrose/utils/Articles.java | 77 +++++++++++ .../utils/EncapsulateItemBuilder.java | 58 ++++++++ .../gildedrose/utils/EncapsulatedItem.java | 85 ++++++++++++ .../java/com/gildedrose/AgedBrieTest.java | 96 ++++++++++++++ .../com/gildedrose/BackStagePassTest.java | 87 ++++++++++++ src/test/java/com/gildedrose/BaseTest.java | 28 ++++ .../java/com/gildedrose/ConjuredTest.java | 65 +++++++++ .../java/com/gildedrose/GildedRoseTest.java | 17 --- .../java/com/gildedrose/LegendaryTest.java | 63 +++++++++ .../java/com/gildedrose/TexttestFixture.java | 31 +++-- 18 files changed, 947 insertions(+), 82 deletions(-) create mode 100644 src/main/java/com/gildedrose/product/category/AgedBrie.java create mode 100644 src/main/java/com/gildedrose/product/category/BackStagePass.java create mode 100644 src/main/java/com/gildedrose/product/category/Conjured.java create mode 100644 src/main/java/com/gildedrose/product/category/Legendary.java create mode 100644 src/main/java/com/gildedrose/updater/GenericUpdater.java create mode 100644 src/main/java/com/gildedrose/updater/Updater.java create mode 100644 src/main/java/com/gildedrose/updater/UpdaterFactory.java create mode 100644 src/main/java/com/gildedrose/utils/Articles.java create mode 100644 src/main/java/com/gildedrose/utils/EncapsulateItemBuilder.java create mode 100644 src/main/java/com/gildedrose/utils/EncapsulatedItem.java create mode 100644 src/test/java/com/gildedrose/AgedBrieTest.java create mode 100644 src/test/java/com/gildedrose/BackStagePassTest.java create mode 100644 src/test/java/com/gildedrose/BaseTest.java create mode 100644 src/test/java/com/gildedrose/ConjuredTest.java delete mode 100644 src/test/java/com/gildedrose/GildedRoseTest.java create mode 100644 src/test/java/com/gildedrose/LegendaryTest.java diff --git a/src/main/java/com/gildedrose/GildedRose.java b/src/main/java/com/gildedrose/GildedRose.java index e6feb751..05ec8298 100644 --- a/src/main/java/com/gildedrose/GildedRose.java +++ b/src/main/java/com/gildedrose/GildedRose.java @@ -1,62 +1,22 @@ package com.gildedrose; + +import com.gildedrose.updater.UpdaterFactory; +import com.gildedrose.utils.EncapsulatedItem; + +import java.util.Objects; + + class GildedRose { - Item[] items; + final EncapsulatedItem[] items; - public GildedRose(Item[] items) { - this.items = items; + public GildedRose(final EncapsulatedItem[] items) { + Objects.requireNonNull(items, "Null EncapsulateItem[] items"); + this.items = items.clone(); } - public void updateQuality() { - for (int i = 0; i < items.length; i++) { - if (!items[i].name.equals("Aged Brie") - && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - - if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].sellIn < 11) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - - if (items[i].sellIn < 6) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } - } - } - - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].sellIn = items[i].sellIn - 1; - } - - if (items[i].sellIn < 0) { - if (!items[i].name.equals("Aged Brie")) { - if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - items[i].quality = items[i].quality - items[i].quality; - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } + for(final EncapsulatedItem item: items){ + UpdaterFactory.getUpdater(item).update(); } } } \ No newline at end of file diff --git a/src/main/java/com/gildedrose/product/category/AgedBrie.java b/src/main/java/com/gildedrose/product/category/AgedBrie.java new file mode 100644 index 00000000..f49f3fcd --- /dev/null +++ b/src/main/java/com/gildedrose/product/category/AgedBrie.java @@ -0,0 +1,38 @@ +package com.gildedrose.product.category; + +import com.gildedrose.Item; +import com.gildedrose.updater.GenericUpdater; +import com.gildedrose.utils.EncapsulatedItem; + +/** + * Aged Brie class handler. + * Conditions: + * + * + */ +public class AgedBrie extends GenericUpdater { + + + /** + * Constructor that creates a AgedBrie Object. + * @param item the Age Brie {@link Item} + */ + public AgedBrie(final T item) { + super(item); + } + /** + * "Aged Brie" actually increases in Quality the older it gets + */ + protected void updateAfterSaleDate(final EncapsulatedItem item) { + increasesQuality(item); + } + /** + * {@inheritDoc} + */ + protected void updateQuality(final EncapsulatedItem item) { + increasesQuality(item); + } +} diff --git a/src/main/java/com/gildedrose/product/category/BackStagePass.java b/src/main/java/com/gildedrose/product/category/BackStagePass.java new file mode 100644 index 00000000..1388aa28 --- /dev/null +++ b/src/main/java/com/gildedrose/product/category/BackStagePass.java @@ -0,0 +1,51 @@ +package com.gildedrose.product.category; + +import com.gildedrose.updater.GenericUpdater; +import com.gildedrose.utils.EncapsulatedItem; + +/** + * BackstagePass class handler (). + * Conditions: + *
    + *
  • Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less.
  • + *
  • Quality drops to 0 after the concert
  • + *
+ * + */ +public class BackStagePass extends GenericUpdater { + + /** + * Represent 5 days + */ + private static final int QUALITY_DAY_X2 = 5; + /** + * Represent 10 days + */ + private static final int QUALITY_DAY_X3 = 10; + + /** + * Constructor that creates a BackstagePass Object. + * @param item the Back Stage Pass {@link EncapsulatedItem} + */ + public BackStagePass(final T item) { + super(item); + } + /** + *

Quality drops to 0 after the concert.

+ */ + protected void updateAfterSaleDate(final EncapsulatedItem item) { + item.setQuality(0); + } + /** + *

Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less.

+ */ + protected void updateQuality(final EncapsulatedItem item) { + increasesQuality(item); + if (item.getSellIn() <= QUALITY_DAY_X3) { + increasesQuality(item); + } + if (item.getSellIn() <= QUALITY_DAY_X2) { + increasesQuality(item); + } + } +} diff --git a/src/main/java/com/gildedrose/product/category/Conjured.java b/src/main/java/com/gildedrose/product/category/Conjured.java new file mode 100644 index 00000000..23ec4617 --- /dev/null +++ b/src/main/java/com/gildedrose/product/category/Conjured.java @@ -0,0 +1,32 @@ +package com.gildedrose.product.category; + +import com.gildedrose.updater.GenericUpdater; +import com.gildedrose.utils.EncapsulatedItem; + +/** + * Conjures class handler (). + * Conditions: + *
    + *
  • "Conjured" items degrade in Quality twice as fast as normal items.
  • + *
+ * + */ +public class Conjured extends GenericUpdater { + + private static final int decrementFactor = 2; + private static final int incrementFactor = 2; + + /** + * Constructor that creates a Conjured Object. + * @param item the Conjured {@link EncapsulatedItem} + */ + public Conjured(final T item) { + super(item, incrementFactor, decrementFactor); + } + /** + * {@inheritDoc} + */ + protected void updateQuality(final EncapsulatedItem item) { + lowerQuality(item); + } +} diff --git a/src/main/java/com/gildedrose/product/category/Legendary.java b/src/main/java/com/gildedrose/product/category/Legendary.java new file mode 100644 index 00000000..7893c466 --- /dev/null +++ b/src/main/java/com/gildedrose/product/category/Legendary.java @@ -0,0 +1,42 @@ +package com.gildedrose.product.category; + +import com.gildedrose.updater.GenericUpdater; +import com.gildedrose.utils.EncapsulatedItem; + +/** + * Legendary class handler (). + * Conditions: + *
    + *
  • Never has to be sold or decreases in Quality.
  • + *
+ * + */ +public class Legendary extends GenericUpdater { + + //TODO: All the legendary item have immutable quality of 80 or just only the Sulfuras? + /** + * Constructor that creates a Legendary Object. + * @param item the Legendary {@link EncapsulatedItem} + */ + public Legendary(final T item) { + super(item); + } + /** + * {@inheritDoc} + */ + protected void updateAfterSaleDate(final EncapsulatedItem item) { + // do nothing + } + /** + * {@inheritDoc} + */ + protected void updateSellIn(final EncapsulatedItem item) { + // do nothing + } + /** + * {@inheritDoc} + */ + protected void updateQuality(final EncapsulatedItem item) { + // do nothing + } +} diff --git a/src/main/java/com/gildedrose/updater/GenericUpdater.java b/src/main/java/com/gildedrose/updater/GenericUpdater.java new file mode 100644 index 00000000..d4541e39 --- /dev/null +++ b/src/main/java/com/gildedrose/updater/GenericUpdater.java @@ -0,0 +1,124 @@ +package com.gildedrose.updater; + +import com.gildedrose.Item; +import com.gildedrose.product.category.AgedBrie; +import com.gildedrose.product.category.BackStagePass; +import com.gildedrose.product.category.Conjured; +import com.gildedrose.product.category.Legendary; +import com.gildedrose.utils.EncapsulatedItem; + +/** + * Generic updater for products. All those products that do not require a custom + * update can / should use this class and the default methods. + */ +public class GenericUpdater implements Updater { + + /** + *

the value associated with the instance to decrement.

+ */ + private final int decrementQualityFactor; + /** + *

the value associated with the instance to increment.

+ */ + private final int incrementQualityFactor; + /** + *

The maximum size to which the quality can be.

+ */ + private static final int MAX_QUALITY = 50; + + /** + *

The {@link EncapsulatedItem} to update.

+ */ + private final EncapsulatedItem item; + + /** + *

Constructor for GenericUpdater.

+ * + * @param item the {@link EncapsulatedItem} to manipulate + */ + public GenericUpdater(final T item) { + this.item = item; + this.incrementQualityFactor = 1; + this.decrementQualityFactor = 1; + } + + /** + *

Constructor for GenericUpdater.

+ * + * @param item the {@link Item} to update + * @param incrementQualityFactor the value associated with the instance to increment + * @param decrementQualityFactor the value associated with the instance to decrement + */ + public GenericUpdater(final T item, final int incrementQualityFactor, final int decrementQualityFactor) { + this.item = item; + this.incrementQualityFactor = incrementQualityFactor; + this.decrementQualityFactor = decrementQualityFactor; + } + + /** + * {@inheritDoc} + */ + @Override + public void update() { + updateQuality(item); + updateSellIn(item); + if (item.getSellIn() < 0) { + updateAfterSaleDate(item); + } + } + + /** + *

Increment the quality of tge given {@link EncapsulatedItem}.

+ * + * @param item the {@link EncapsulatedItem} to update the quality. + * + */ + protected void increasesQuality(final EncapsulatedItem item) { + if (item.getQuality() < MAX_QUALITY) { + item.setQuality(item.getQuality() + incrementQualityFactor); + } + } + /** + *

Update the expired properties of tge given {@link EncapsulatedItem}.

+ *

It depends on each product how to update the quality after the sale date

+ * + * @see AgedBrie + * @see Legendary + * @see BackStagePass + * @see Conjured + * + * @param item the {@link EncapsulatedItem} to update the quality. + */ + protected void updateAfterSaleDate(final EncapsulatedItem item) { + lowerQuality(item); + } + /** + *

Update the Quality properties of tge given {@link EncapsulatedItem}.

+ * + * @param item the {@link EncapsulatedItem} to update the quality. + * + */ + protected void updateQuality(final EncapsulatedItem item) { + lowerQuality(item); + } + /** + *

Decrement the quality of tge given {@link EncapsulatedItem}.

+ * + * @param item the {@link EncapsulatedItem} to update the quality. + * + */ + protected void lowerQuality(final EncapsulatedItem item) { + if (item.getQuality() > 0) { + item.setQuality(item.getQuality() - decrementQualityFactor); + } + } + /** + *

Update the sell in properties of tge given {@link EncapsulatedItem}.

+ * + * @param item the {@link EncapsulatedItem} to update the quality. + * + */ + protected void updateSellIn(final EncapsulatedItem item) { + item.setSellIn(item.getSellIn() - 1); + } +} diff --git a/src/main/java/com/gildedrose/updater/Updater.java b/src/main/java/com/gildedrose/updater/Updater.java new file mode 100644 index 00000000..52d607f4 --- /dev/null +++ b/src/main/java/com/gildedrose/updater/Updater.java @@ -0,0 +1,15 @@ +package com.gildedrose.updater; + +import com.gildedrose.utils.EncapsulatedItem; + +/** + * Base interface from where all the different product updaters will implement. + * Contain only one abstract method {@code update} + */ +public interface Updater{ + + /** + * Updates the {@link EncapsulatedItem} properties + */ + void update(); +} diff --git a/src/main/java/com/gildedrose/updater/UpdaterFactory.java b/src/main/java/com/gildedrose/updater/UpdaterFactory.java new file mode 100644 index 00000000..4954f036 --- /dev/null +++ b/src/main/java/com/gildedrose/updater/UpdaterFactory.java @@ -0,0 +1,54 @@ +package com.gildedrose.updater; + +import com.gildedrose.product.category.Conjured; +import com.gildedrose.utils.Articles; +import com.gildedrose.product.category.AgedBrie; +import com.gildedrose.product.category.BackStagePass; +import com.gildedrose.product.category.Legendary; +import com.gildedrose.utils.EncapsulatedItem; + +import java.util.Objects; + +/** + *

Factory class that is responsible for returning the right object type from a given item.

+ */ +public class UpdaterFactory { + + /** + * Main method of the factory. It receives an item and based on the name it + * generates an object according to the category.

+ * + *

If the name of the item can't found in the {@link Articles} will be return a default implementation + * {@link GenericUpdater}

+ * + * These can be: + *
    + *
  • AgedBrie {@link AgedBrie}
  • + *
  • BackStagePass {@link BackStagePass}
  • + *
  • Conjured {@link Conjured}
  • + *
  • Legendary {@link Legendary}
  • + *
+ * @see AgedBrie + * @see Legendary + * @see BackStagePass + * @see Conjured + * @see GenericUpdater + * @return a new implementation of {@link Updater} given the input {@code item}, + * @throws NullPointerException if {@code item} is {@code null} + */ + public static Updater getUpdater(final EncapsulatedItem item) { + Objects.requireNonNull(item, "Null EncapsulateItem items"); + switch (Articles.getArticle(item.getName())){ + case AGED_BRIE: + return new AgedBrie<>(item); + case SULFURAS: + return new Legendary<>(item); + case TAFKAL_80ETC: + return new BackStagePass<>(item); + case CONJURED: + return new Conjured<>(item); + default: + return new GenericUpdater<>(item); + } + } +} diff --git a/src/main/java/com/gildedrose/utils/Articles.java b/src/main/java/com/gildedrose/utils/Articles.java new file mode 100644 index 00000000..8a50cfe1 --- /dev/null +++ b/src/main/java/com/gildedrose/utils/Articles.java @@ -0,0 +1,77 @@ +package com.gildedrose.utils; + + +/** + * The {@link Articles} enum defines types of a Articles. + * The following types are defined: + *
    + *
  • Aged Brie
  • + *
  • Backstage passes to a TAFKAL80ETC concert
  • + *
  • Sulfuras, Hand of Ragnaros
  • + *
  • Conjured Mana Cake
  • + *
  • Default
  • + *
+ */ +public enum Articles { + + /** + * Aged Brie + */ + AGED_BRIE ("Aged Brie"), + + /** + * the Backstage passes + */ + TAFKAL_80ETC ("Backstage passes to a TAFKAL80ETC concert"), + + /** + * Sulfuras, Hand of Ragnaros + */ + SULFURAS ("Sulfuras, Hand of Ragnaros"), + /** + * Conjured Mana Cake + */ + CONJURED ("Conjured Mana Cake"), + + /** + * Unknown article. + */ + DEFAULT ("DEFAULT"); + + /** + * The article name. + */ + private final String article; + + Articles(final String article) { + this.article = article; + } + + /** + * Gets the article name. + * + * @return the article. + */ + public String getArticle() { + return article; + } + + /** + * Gets the article name given an article. + * + * @param article the article String to match + * @return the article given a {@code}. {@code DEFAULT} if not found, can be null + */ + public static Articles getArticle(final String article) { + for (final Articles a : values()) { + if (a.getArticle().equals(article)) { + return a; + } + } + return DEFAULT; + } + + + + +} diff --git a/src/main/java/com/gildedrose/utils/EncapsulateItemBuilder.java b/src/main/java/com/gildedrose/utils/EncapsulateItemBuilder.java new file mode 100644 index 00000000..8a0644c6 --- /dev/null +++ b/src/main/java/com/gildedrose/utils/EncapsulateItemBuilder.java @@ -0,0 +1,58 @@ +package com.gildedrose.utils; + +/** + *

Builder for the object {@link EncapsulatedItem}.

+ */ +public class EncapsulateItemBuilder { + + /** + * The name of the product. + */ + private String name; + /** + * SellIn value which denotes the number of days we have to sell the item. + */ + private int sellIn; + /** + * Quality value which denotes how valuable the item is. + */ + private int quality; + + /** + * Constructs a new instance of Encapsulate ItemBuilder which initialize + * the {@code name}, {@code sellIn} and {@code quality}. + */ + public EncapsulateItemBuilder() { + this.name = ""; + this.quality = 0; + this.sellIn = 0; + } + /** + *

Set the name of the item.

+ */ + public EncapsulateItemBuilder named(final String name) { + this.name = name; + return this; + } + /** + *

Set the quality value.

+ */ + public EncapsulateItemBuilder ofQuality(final int quality) { + this.quality = quality; + return this; + } + /** + *

Set the sellIn value.

+ */ + public EncapsulateItemBuilder toSellIn(final int sellIn) { + this.sellIn = sellIn; + return this; + } + + /** + * Create the {@link EncapsulatedItem} object from all the previously set data. + */ + public EncapsulatedItem build() { + return new EncapsulatedItem(name, sellIn, quality); + } +} diff --git a/src/main/java/com/gildedrose/utils/EncapsulatedItem.java b/src/main/java/com/gildedrose/utils/EncapsulatedItem.java new file mode 100644 index 00000000..256f9b8a --- /dev/null +++ b/src/main/java/com/gildedrose/utils/EncapsulatedItem.java @@ -0,0 +1,85 @@ +package com.gildedrose.utils; + +import java.io.Serializable; + +/** + *

Item copy object with all data encapsulated.

+ */ +public class EncapsulatedItem implements Serializable { + + private static final long serialVersionUID = 1989175797960240011L; + /** + * The name of the product. + */ + private String name; + /** + * SellIn value which denotes the number of days we have to sell the item. + */ + private int sellIn; + /** + * Quality value which denotes how valuable the item is. + */ + private int quality; + + /** + * Constructs a new instance of EncapsulateItem with the given {@code name}, {@code sellIn} and {@code quality}. + * @param name The name of the product. + * @param sellIn The number of days we have to sell the item + * @param quality The value which denotes how valuable the item is + */ + public EncapsulatedItem(final String name, final int sellIn, final int quality) { + this.setName(name); + this.setSellIn(sellIn); + this.setQuality(quality); + } + + /** + *

Gets the name suitable for display.

+ * + * @return the name. + */ + public String getName() { + return name; + } + + /** + *

Set the name of the item.

+ */ + public void setName(String name) { + this.name = name; + } + + /** + *

Gets the sell in suitable for display.

+ * + * @return the sellIn value. + */ + public int getSellIn() { + return sellIn; + } + /** + *

Set the sellIn value.

+ */ + public void setSellIn(final int sellIn) { + this.sellIn = sellIn; + } + /** + *

Gets the quality suitable for display.

+ * + * @return the quality value. + */ + public int getQuality() { + return quality; + } + /** + *

Set the quality value.

+ */ + public void setQuality(final int quality) { + this.quality = quality; + } + + @Override + public String toString() { + return this.getName() + ", " + this.getSellIn() + ", " + this.getQuality(); + } +} diff --git a/src/test/java/com/gildedrose/AgedBrieTest.java b/src/test/java/com/gildedrose/AgedBrieTest.java new file mode 100644 index 00000000..d752a7d8 --- /dev/null +++ b/src/test/java/com/gildedrose/AgedBrieTest.java @@ -0,0 +1,96 @@ +package com.gildedrose; + +import com.gildedrose.utils.Articles; +import com.gildedrose.utils.EncapsulatedItem; +import org.junit.jupiter.api.Test; + + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * Unit tests for methods of {@link com.gildedrose.product.category.AgedBrie} + * which been moved to their own test classes. + */ +class AgedBrieTest extends BaseTest{ + + @Test + void lowerQualityAndUpQuantityByOne() { + + // given + final int sellIn = 2; + final int quality = 2; + final EncapsulatedItem item = createItem(Articles.AGED_BRIE.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertAll( + () -> assertEquals(sellIn -1, item.getSellIn()), + () -> assertEquals(quality + 1, item.getQuality()) + ); + } + + @Test + void increaseQualityToDouble() { + + // given + final int sellIn = 0; + final int quality = 2; + final EncapsulatedItem item = createItem(Articles.AGED_BRIE.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(quality + 2, item.getQuality()); + } + + @Test + void tryUpdateQualityAboveMax() { + + // given + final int sellIn = 2; + final int quality = 50; + final EncapsulatedItem item = createItem(Articles.AGED_BRIE.getArticle(), sellIn, quality); + // when + updateQuality(item); + + // then + assertEquals(50, item.getQuality(), "The Quality of an item is never more than 50"); + } + + @Test + void toStringEncapsulateItem() { + // given + final int sellIn = 2; + final int quality = 2; + final EncapsulatedItem item = createItem(Articles.AGED_BRIE.getArticle(), sellIn, quality); + // when + updateQuality(item); + // then + assertEquals("Aged Brie, " + (sellIn - 1) + ", " + (quality + 1), item.toString()); + } + + @Test + void checkNullItems() { + // given + final int sellIn = 2; + final int quality = 2; + final EncapsulatedItem item = createItem(Articles.AGED_BRIE.getArticle(), sellIn, quality); + // when + // then + assertThrows(NullPointerException.class, () -> updateQuality(item, null)); + } + + @Test + void checkNullItemsInsideArray() { + // given + // when + // then + assertThrows(NullPointerException.class, () -> updateQuality((EncapsulatedItem) null)); + } + +} diff --git a/src/test/java/com/gildedrose/BackStagePassTest.java b/src/test/java/com/gildedrose/BackStagePassTest.java new file mode 100644 index 00000000..b3a154d2 --- /dev/null +++ b/src/test/java/com/gildedrose/BackStagePassTest.java @@ -0,0 +1,87 @@ +package com.gildedrose; + +import com.gildedrose.utils.Articles; +import com.gildedrose.utils.EncapsulatedItem; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Unit tests for methods of {@link com.gildedrose.product.category.BackStagePass} + * which been moved to their own test classes. + */ +public class BackStagePassTest extends BaseTest{ + + @Test + void lowerQualityAndUpQuantityByOne() { + + // given + final int sellIn = 15; + final int quality = 3; + final EncapsulatedItem item = createItem(Articles.TAFKAL_80ETC.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(quality + 1, item.getQuality()); + } + @Test + void increaseQualityToDouble() { + + // given + final int sellIn = 9; + final int quality = 3; + final EncapsulatedItem item = createItem(Articles.TAFKAL_80ETC.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(quality + 2, item.getQuality()); + } + @Test + void dropAfterConcert() { + + // given + final int sellIn = 0; + final int quality = 3; + final EncapsulatedItem item = createItem(Articles.TAFKAL_80ETC.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(sellIn, item.getQuality()); + } + + @Test + void increaseQualityToDoubleByThree() { + + // given + final int sellIn = 2; + final int quality = 2; + final EncapsulatedItem item = createItem(Articles.TAFKAL_80ETC.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(quality + 3, item.getQuality()); + } + + @Test + void tryUpdateQualityAboveMax() { + + // given + final int sellIn = 5; + final int quality = 50; + final EncapsulatedItem item = createItem(Articles.AGED_BRIE.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(50, item.getQuality(), "The Quality of an item is never more than 50"); + } +} diff --git a/src/test/java/com/gildedrose/BaseTest.java b/src/test/java/com/gildedrose/BaseTest.java new file mode 100644 index 00000000..60f9317a --- /dev/null +++ b/src/test/java/com/gildedrose/BaseTest.java @@ -0,0 +1,28 @@ +package com.gildedrose; + +import com.gildedrose.utils.EncapsulatedItem; +import com.gildedrose.utils.EncapsulateItemBuilder; + +public class BaseTest { + + /** + * Create a {@link EncapsulatedItem} object given the {@code code}, {@code sellIn} and {@code quality}. + * @param name The name of the product. + * @param sellIn The number of days we have to sell the item + * @param quality The value which denotes how valuable the item is + */ + protected EncapsulatedItem createItem(final String name, final int sellIn, final int quality){ + return new EncapsulateItemBuilder() + .named(name) + .ofQuality(quality) + .toSellIn(sellIn) + .build(); + } + /** + * Create the instance of {@link GildedRose} and update the Quality of the {@code items} + */ + protected void updateQuality(final EncapsulatedItem...items){ + new GildedRose(items).updateQuality(); + } + +} diff --git a/src/test/java/com/gildedrose/ConjuredTest.java b/src/test/java/com/gildedrose/ConjuredTest.java new file mode 100644 index 00000000..60d8f502 --- /dev/null +++ b/src/test/java/com/gildedrose/ConjuredTest.java @@ -0,0 +1,65 @@ +package com.gildedrose; + +import com.gildedrose.utils.Articles; +import com.gildedrose.utils.EncapsulatedItem; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Unit tests for methods of {@link com.gildedrose.product.category.Conjured} + * which been moved to their own test classes. + */ +class ConjuredTest extends BaseTest{ + + @Test + void lowerQualityByTwoAndUpQuantityByOne() { + + // given + final int sellIn = 4; + final int quality = 4; + final EncapsulatedItem item = createItem(Articles.CONJURED.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertAll( + () -> assertEquals(sellIn -1, item.getSellIn()), + () -> assertEquals(quality - 2, item.getQuality()) + ); + } + + @Test + void increaseQualityToDouble() { + + // given + final int sellIn = 0; + final int quality = 2; + final EncapsulatedItem item = createItem(Articles.AGED_BRIE.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(quality + 2, item.getQuality()); + } + + @Test + void tryUpdateQualityAboveMax() { + + // given + final int sellIn = 4; + final int quality = 50; + final EncapsulatedItem item = createItem(Articles.AGED_BRIE.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(50, item.getQuality(), "The Quality of an item is never more than 50"); + } + + +} diff --git a/src/test/java/com/gildedrose/GildedRoseTest.java b/src/test/java/com/gildedrose/GildedRoseTest.java deleted file mode 100644 index 7c5fc0a2..00000000 --- a/src/test/java/com/gildedrose/GildedRoseTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gildedrose; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class GildedRoseTest { - - @Test - void foo() { - Item[] items = new Item[] { new Item("foo", 0, 0) }; - GildedRose app = new GildedRose(items); - app.updateQuality(); - assertEquals("foo", app.items[0].name); - } - -} diff --git a/src/test/java/com/gildedrose/LegendaryTest.java b/src/test/java/com/gildedrose/LegendaryTest.java new file mode 100644 index 00000000..cf7a61e3 --- /dev/null +++ b/src/test/java/com/gildedrose/LegendaryTest.java @@ -0,0 +1,63 @@ +package com.gildedrose; + +import com.gildedrose.utils.Articles; +import com.gildedrose.utils.EncapsulatedItem; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Unit tests for methods of {@link com.gildedrose.product.category.Legendary} + * which been moved to their own test classes. + */ +class LegendaryTest extends BaseTest{ + + @Test + void tryLowerQualityAndUpQuantityByOne() { + + // given + final int sellIn = 2; + final int quality = 2; + final EncapsulatedItem item = createItem(Articles.SULFURAS.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertAll( + () -> assertEquals(sellIn, item.getSellIn()), + () -> assertEquals(quality, item.getQuality()) + ); + } + + @Test + void increaseQualityToDouble() { + + // given + final int sellIn = 4; + final int quality = 80; + final EncapsulatedItem item = createItem(Articles.SULFURAS.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(quality, item.getQuality()); + } + + @Test + void tryIncreaseQuality() { + + // given + final int sellIn = -1; + final int quality = 80; + final EncapsulatedItem item = createItem(Articles.SULFURAS.getArticle(), sellIn, quality); + + // when + updateQuality(item); + + // then + assertEquals(quality, item.getQuality()); + } +} diff --git a/src/test/java/com/gildedrose/TexttestFixture.java b/src/test/java/com/gildedrose/TexttestFixture.java index d059c88f..088e5a71 100644 --- a/src/test/java/com/gildedrose/TexttestFixture.java +++ b/src/test/java/com/gildedrose/TexttestFixture.java @@ -1,20 +1,13 @@ package com.gildedrose; +import com.gildedrose.utils.EncapsulatedItem; +import com.gildedrose.utils.EncapsulateItemBuilder; + public class TexttestFixture { public static void main(String[] args) { System.out.println("OMGHAI!"); - Item[] items = new Item[] { - new Item("+5 Dexterity Vest", 10, 20), // - new Item("Aged Brie", 2, 0), // - new Item("Elixir of the Mongoose", 5, 7), // - new Item("Sulfuras, Hand of Ragnaros", 0, 80), // - new Item("Sulfuras, Hand of Ragnaros", -1, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), - new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), - // this conjured item does not work properly yet - new Item("Conjured Mana Cake", 3, 6) }; + final EncapsulatedItem[] items = buildItems(); GildedRose app = new GildedRose(items); @@ -26,7 +19,7 @@ public class TexttestFixture { for (int i = 0; i < days; i++) { System.out.println("-------- day " + i + " --------"); System.out.println("name, sellIn, quality"); - for (Item item : items) { + for (EncapsulatedItem item : items) { System.out.println(item); } System.out.println(); @@ -34,4 +27,18 @@ public class TexttestFixture { } } + private static EncapsulatedItem[] buildItems() { + return new EncapsulatedItem[] { + new EncapsulateItemBuilder().named("+5 Dexterity Vest").toSellIn(10).ofQuality(20).build(), + new EncapsulateItemBuilder().named("Aged Brie").toSellIn(2).ofQuality(0).build(), + new EncapsulateItemBuilder().named("Elixir of the Mongoose").toSellIn(5).ofQuality(7).build(), + new EncapsulateItemBuilder().named("Sulfuras, Hand of Ragnaros").toSellIn(0).ofQuality(80).build(), + new EncapsulateItemBuilder().named("Sulfuras, Hand of Ragnaros").toSellIn(-1).ofQuality(80).build(), + new EncapsulateItemBuilder().named("Backstage passes to a TAFKAL80ETC concert").toSellIn(15).ofQuality(20).build(), + new EncapsulateItemBuilder().named("Backstage passes to a TAFKAL80ETC concert").toSellIn(10).ofQuality(49).build(), + new EncapsulateItemBuilder().named("Backstage passes to a TAFKAL80ETC concert").toSellIn(5).ofQuality(49).build(), + new EncapsulateItemBuilder().named("Conjured Mana Cake").toSellIn(3).ofQuality(6).build(),}; + + } + }