Test is completed

This commit is contained in:
Dima Svetlichniy 2021-11-10 05:12:30 +02:00
parent 864f34ccc1
commit 4ebd9c7bf4
22 changed files with 1264 additions and 53 deletions

View File

@ -6,6 +6,7 @@ require_once __DIR__ . '/../vendor/autoload.php';
use GildedRose\GildedRose;
use GildedRose\Item;
use GildedRose\StrategyResolver;
echo 'OMGHAI!' . PHP_EOL;
@ -22,7 +23,7 @@ $items = [
new Item('Conjured Mana Cake', 3, 6),
];
$app = new GildedRose($items);
$app = new GildedRose($items, new StrategyResolver());
$days = 2;
if (count($argv) > 1) {

View File

@ -11,59 +11,25 @@ final class GildedRose
*/
private $items;
public function __construct(array $items)
/**
* @var StrategyResolverInterface
*/
private $strategyResolver;
public function __construct(array $items, StrategyResolverInterface $strategyResolver)
{
$this->items = $items;
$this->strategyResolver = $strategyResolver;
}
public function updateQuality(): void
{
foreach ($this->items as $item) {
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;
}
}
}
}
}
$sellInStrategy = $this->strategyResolver->getSellInStrategy($item);
$sellInStrategy->updateSellIn($item);
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;
}
}
}
$qualityStrategy = $this->strategyResolver->getQualityStrategy($item);
$qualityStrategy->updateQuality($item);
}
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace GildedRose\QualityStrategy;
class AgedBrieQualityStrategy extends BasicQualityStrategy
{
public function __construct(int $decreasingSpeed = 1)
{
parent::__construct($decreasingSpeed * -1);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace GildedRose\QualityStrategy;
use GildedRose\Item;
class BackstagePassesQualityStrategy extends BasicQualityStrategy
{
protected const SELL_IN_LAST_5_DAYS = 5;
protected const SELL_IN_LAST_10_DAYS = 10;
protected const DECREASING_SPEED_AT_LAST_5_DAYS = -3;
protected const DECREASING_SPEED_AT_LAST_10_DAYS = -2;
public function __construct(int $decreasingSpeed = 1)
{
parent::__construct($decreasingSpeed * -1);
}
protected function getCurrentDecreasingSpeed(Item $item): int
{
$decreasingSpeed = parent::getCurrentDecreasingSpeed($item);
if ($item->sell_in <= self::SELL_IN_LAST_5_DAYS) {
$decreasingSpeed = self::DECREASING_SPEED_AT_LAST_5_DAYS;
} elseif ($item->sell_in <= self::SELL_IN_LAST_10_DAYS) {
$decreasingSpeed = self::DECREASING_SPEED_AT_LAST_10_DAYS;
}
return $decreasingSpeed;
}
protected function setMinAndMaxQuality(Item $item): Item
{
if ($item->sell_in < 0) {
$item->quality = 0;
return $item;
}
return parent::setMinAndMaxQuality($item);
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace GildedRose\QualityStrategy;
use GildedRose\Item;
class BasicQualityStrategy implements QualityStrategyInterface
{
/**
* @var int
*/
protected $decreasingSpeed;
public function __construct(int $decreasingSpeed = 1)
{
$this->decreasingSpeed = $decreasingSpeed;
}
public function updateQuality(Item $item): Item
{
$item = $this->setInitialQuality($item);
$decreasingSpeed = $this->getCurrentDecreasingSpeed($item);
$item->quality -= $decreasingSpeed;
return $this->setFinalQuality($item);
}
protected function getCurrentDecreasingSpeed(Item $item): int
{
return $item->sell_in >= 0
? $this->decreasingSpeed
: $this->decreasingSpeed * 2;
}
protected function setInitialQuality(Item $item): Item
{
return $this->setMinAndMaxQuality($item);
}
protected function setFinalQuality(Item $item): Item
{
return $this->setMinAndMaxQuality($item);
}
protected function setMinAndMaxQuality(Item $item): Item
{
$item->quality = $item->quality > 0 ? $item->quality : 0;
$item->quality = $item->quality < self::QUALITY_MAX_LEVEL ? $item->quality : self::QUALITY_MAX_LEVEL;
return $item;
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace GildedRose\QualityStrategy;
class ConjuredQualityStrategy extends BasicQualityStrategy
{
public function __construct(int $decreasingSpeed = 1)
{
parent::__construct($decreasingSpeed * 2);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace GildedRose\QualityStrategy;
use GildedRose\Item;
interface QualityStrategyInterface
{
public const QUALITY_MAX_LEVEL = 50;
public function updateQuality(Item $item): Item;
}

View File

@ -0,0 +1,18 @@
<?php
namespace GildedRose\QualityStrategy;
use GildedRose\Item;
class SulfurasQualityStrategy extends BasicQualityStrategy
{
public function __construct(int $decreasingSpeed = 0)
{
parent::__construct($decreasingSpeed);
}
protected function setMinAndMaxQuality(Item $item): Item
{
return $item;
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace GildedRose\SellInStrategy;
use GildedRose\Item;
class BasicSellInStrategy implements SellInStrategyInterface
{
public function updateSellIn(Item $item): Item
{
$item->sell_in--;
return $item;
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace GildedRose\SellInStrategy;
use GildedRose\Item;
interface SellInStrategyInterface
{
public function updateSellIn(Item $item): Item;
}

View File

@ -0,0 +1,13 @@
<?php
namespace GildedRose\SellInStrategy;
use GildedRose\Item;
class SulfurasSellInStrategy implements SellInStrategyInterface
{
public function updateSellIn(Item $item): Item
{
return $item;
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace GildedRose;
use GildedRose\QualityStrategy\AgedBrieQualityStrategy;
use GildedRose\QualityStrategy\BackstagePassesQualityStrategy;
use GildedRose\QualityStrategy\BasicQualityStrategy;
use GildedRose\QualityStrategy\ConjuredQualityStrategy;
use GildedRose\QualityStrategy\QualityStrategyInterface;
use GildedRose\QualityStrategy\SulfurasQualityStrategy;
use GildedRose\SellInStrategy\BasicSellInStrategy;
use GildedRose\SellInStrategy\SellInStrategyInterface;
use GildedRose\SellInStrategy\SulfurasSellInStrategy;
class StrategyResolver implements StrategyResolverInterface
{
public function getSellInStrategy(Item $item): SellInStrategyInterface
{
switch ($item->name) {
case self::ITEM_NAME_SULFURAS:
return new SulfurasSellInStrategy();
default:
break;
}
return new BasicSellInStrategy();
}
public function getQualityStrategy(Item $item): QualityStrategyInterface
{
switch ($item->name) {
case self::ITEM_NAME_AGED_BRIE:
return new AgedBrieQualityStrategy();
case self::ITEM_NAME_SULFURAS:
return new SulfurasQualityStrategy();
case self::ITEM_NAME_BACKSTAGE_PASSES:
return new BackstagePassesQualityStrategy();
case self::ITEM_NAME_CONJURED:
return new ConjuredQualityStrategy();
default:
break;
}
return new BasicQualityStrategy();
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace GildedRose;
use GildedRose\QualityStrategy\QualityStrategyInterface;
use GildedRose\SellInStrategy\SellInStrategyInterface;
interface StrategyResolverInterface
{
public const ITEM_NAME_AGED_BRIE = 'Aged Brie';
public const ITEM_NAME_SULFURAS = 'Sulfuras, Hand of Ragnaros';
public const ITEM_NAME_BACKSTAGE_PASSES = 'Backstage passes to a TAFKAL80ETC concert';
public const ITEM_NAME_CONJURED = 'Conjured Mana Cake';
public function getSellInStrategy(Item $item): SellInStrategyInterface;
public function getQualityStrategy(Item $item): QualityStrategyInterface;
}

View File

@ -0,0 +1,172 @@
<?php
declare(strict_types=1);
namespace Tests\GildedRose;
use GildedRose\Item;
use GildedRose\StrategyResolverInterface;
use Tests\TestCase;
class AgedBrieItemTest extends TestCase
{
/**
* @group AgedBrie
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQuality(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider(): array
{
return [
'si: 0->-1, qty decrease x2: 10->12' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 0, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -1, 12),
],
],
'si: 1->0, qty: 10->11' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 1, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 0, 11),
],
],
'si: 10->9, min qty: -100->1' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 10, -100),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 9, 1),
],
],
'si: -10->-11, max qty: 49->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -10, 49),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -11, 50),
],
],
'si: 1->0, max qty: 50->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 1, 50),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 0, 50),
],
],
'si: 10->9, max qty: 105->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 10, 105),
],
'expected'
=> [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 9, 50),
],
],
];
}
/**
* @group AgedBrie
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQualityThreeTimes(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider(): array
{
return [
'si: 0->-3, qty decrease x2: 10->16' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 0, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -3, 16),
],
],
'si: 1->-2, qty: 10->15' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 1, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -2, 15),
],
],
'si: 10->7, min qty: -100->3' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 10, -100),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 7, 3),
],
],
'si: -10->-13, max qty: 45->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -10, 45),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -13, 50),
],
],
'si: 1->-2, max qty: 50->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 1, 50),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -2, 50),
],
],
'si: 10->7, max qty: 105->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 10, 105),
],
'expected'
=> [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 7, 50),
],
],
];
}
}

View File

@ -0,0 +1,197 @@
<?php
declare(strict_types=1);
namespace Tests\GildedRose;
use GildedRose\Item;
use GildedRose\StrategyResolverInterface;
use Tests\TestCase;
class BackstagePassesItemTest extends TestCase
{
/**
* @group BackstagePasses
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQuality(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider(): array
{
return [
'si: 100->99, qty: 10->11' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 100, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 99, 11),
],
],
'si: 10->9, qty increase +2: 10->12' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 10, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 9, 12),
],
],
'si: 5->4, qty increase +3: 10->13' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 5, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 4, 13),
],
],
'si: 10->9, min qty: -100->2' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 10, -100),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 9, 2),
],
],
'concert is finished, si: 0->-1, min qty: 100->0' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 0, 100),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, -1, 0),
],
],
'si: 1->0, max qty: 50->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 1, 50),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 0, 50),
],
],
'si: 10->9, max qty: 105->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 10, 105),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 9, 50),
],
],
];
}
/**
* @group BackstagePasses
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQualityThreeTimes(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider(): array
{
return [
'si: 100->97, qty: 10->13' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 100, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 97, 13),
],
],
'si: 10->7, qty increase +2: 10->16' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 10, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 7, 16),
],
],
'si: 5->2, qty increase +3: 10->19' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 5, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 2, 19),
],
],
'si: 7->4, qty increase +2 and +3: 10->18' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 7, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 4, 18),
],
],
'si: 10->7, min qty: -100->6' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 10, -100),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 7, 6),
],
],
'concert is finished, si: 2->-1, min qty: 100->0' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 2, 100),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, -1, 0),
],
],
'si: 3->0, max qty: 50->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 3, 50),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 0, 50),
],
],
'si: 10->7, max qty: 105->50' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 10, 105),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 7, 50),
],
],
];
}
}

View File

@ -0,0 +1,181 @@
<?php
declare(strict_types=1);
namespace Tests\GildedRose;
use GildedRose\Item;
use GildedRose\StrategyResolverInterface;
use Tests\TestCase;
class ConjuredItemTest extends TestCase
{
/**
* @group ConjuredItem
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQuality(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider(): array
{
return [
'si: 0->-1, qty decrease x4: 10->8' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 0, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, -1, 6),
],
],
'si: 1->0, qty decrease x2: 10->9' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 1, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 0, 8),
],
],
'si: 10->9, min qty: 0->0' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 10, 0),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 9, 0),
],
],
'si: -10->-11, min qty: 3->0' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, -10, 3),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, -11, 0),
],
],
'si: 10->9, min qty: -50->0' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 10, -50),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 9, 0),
],
],
'si: 10->9, max qty: 105->48' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 10, 105),
],
'expected'
=> [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 9, 48),
],
],
];
}
/**
* @skip
* @group ConjuredItem
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQualityThreeTimes(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider(): array
{
return [
'si: 0->-3, qty decrease x4: 20->8' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 0, 20),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, -3, 8),
],
],
'si: 3->0, qty decrease x2: 10->4' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 3, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 0, 4),
],
],
'si: 1->-2, qty decrease x2 and x4: 20->10' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 1, 20),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, -2, 10),
],
],
'si: 10->7, min qty: 0->0' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 10, 0),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 7, 0),
],
],
'si: -10->-13, qty: 11->0' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, -10, 11),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, -13, 0),
],
],
'si: 10->7, min qty: -50->0' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 10, -50),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 7, 0),
],
],
'si: 10->7, max qty: 105->44' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 10, 105),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 7, 44),
],
],
];
}
}

View File

@ -0,0 +1,169 @@
<?php
declare(strict_types=1);
namespace Tests\GildedRose;
use GildedRose\Item;
use Tests\TestCase;
class FooItemTest extends TestCase
{
/**
* @group FooItem
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQuality(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider(): array
{
return [
'si: 0->-1, qty decrease x2: 10->8' => [
'items' => [
'foo' => new Item('foo', 0, 10),
],
'expected' => [
'foo' => new Item('foo', -1, 8),
],
],
'si: 1->0, qty: 10->9' => [
'items' => [
'foo' => new Item('foo', 1, 10),
],
'expected' => [
'foo' => new Item('foo', 0, 9),
],
],
'si: 10->9, min qty: 0->0' => [
'items' => [
'foo' => new Item('foo', 10, 0),
],
'expected' => [
'foo' => new Item('foo', 9, 0),
],
],
'si: -10->-11, qty: 1->0' => [
'items' => [
'foo' => new Item('foo', -10, 1),
],
'expected' => [
'foo' => new Item('foo', -11, 0),
],
],
'si: 10->9, min qty: -50->0' => [
'items' => [
'foo' => new Item('foo', 10, -50),
],
'expected' => [
'foo' => new Item('foo', 9, 0),
],
],
'si: 10->9, max qty: 105->49' => [
'items' => [
'foo' => new Item('foo', 10, 105),
],
'expected' => [
'foo' => new Item('foo', 9, 49),
],
],
];
}
/**
* @group FooItem
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQualityThreeTimes(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider(): array
{
return [
'si: 0->-3, qty decrease x2: 10->4' => [
'items' => [
'foo' => new Item('foo', 0, 10),
],
'expected' => [
'foo' => new Item('foo', -3, 4),
],
],
'si: 3->0, qty: 10->7' => [
'items' => [
'foo' => new Item('foo', 3, 10),
],
'expected' => [
'foo' => new Item('foo', 0, 7),
],
],
'si: 1->-2, qty decrease x1 and x2: 10->5' => [
'items' => [
'foo' => new Item('foo', 1, 10),
],
'expected' => [
'foo' => new Item('foo', -2, 5),
],
],
'si: 10->7, min qty: 0->0' => [
'items' => [
'foo' => new Item('foo', 10, 0),
],
'expected' => [
'foo' => new Item('foo', 7, 0),
],
],
'si: -10->-13, qty: 1->0' => [
'items' => [
'foo' => new Item('foo', -10, 1),
],
'expected' => [
'foo' => new Item('foo', -13, 0),
],
],
'si: 10->7, max qty: 105->47' => [
'items' => [
'foo' => new Item('foo', 10, 105),
],
'expected' => [
'foo' => new Item('foo', 7, 47),
],
],
];
}
}

View File

@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
namespace Tests\GildedRose;
use GildedRose\Item;
use GildedRose\StrategyResolverInterface;
use Tests\TestCase;
class SulfurasItemTest extends TestCase
{
/**
* @group Sulfuras
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQuality(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityDataProvider(): array
{
return [
'sell-in const: -1->-1, qty const: 10->10' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, -1, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, -1, 10),
],
],
'sell-in const: 0->0, min qty: -100->-100' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 0, -100),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 0, -100),
],
],
'sell-in const: 1->1, max qty: 105->105' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 1, 105),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 1, 105),
],
],
];
}
/**
* @group Sulfuras
* @dataProvider sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider
*
* @param Item[] $items
* @param Item[] $expectedItems
*/
public function testSellInAndQualityIsCorrectAfterUpdatedQualityThreeTimes(
array $items,
array $expectedItems
): void {
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$gildedRose->updateQuality();
$this->assertSameItems($expectedItems, $items);
}
public function sellInAndQualityIsCorrectAfterUpdatedQualityThreeTimesDataProvider(): array
{
return [
'sell-in const: -1->-1, qty const: 10->10' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, -1, 10),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, -1, 10),
],
],
'sell-in const: 0->0, min qty: -100->-100' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 0, -100),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 0, -100),
],
],
'sell-in const: 1->1, max qty: 105->105' => [
'items' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 1, 105),
],
'expected' => [
'foo' => new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 1, 105),
],
],
];
}
}

View File

@ -4,17 +4,92 @@ declare(strict_types=1);
namespace Tests;
use GildedRose\GildedRose;
use GildedRose\Item;
use PHPUnit\Framework\TestCase;
use GildedRose\StrategyResolverInterface;
class GildedRoseTest extends TestCase
{
public function testFoo(): void
/**
* @group GildedRose
*/
public function testFooItemNameIsTheSameAfterUpdatedQuality(): void
{
$items = [new Item('foo', 0, 0)];
$gildedRose = new GildedRose($items);
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$this->assertSame('fixme', $items[0]->name);
$this->assertSame('foo', $items[0]->name);
}
/**
* @group GildedRose
*/
public function testDifferentMultiItemsDataIsCorrectAfterUpdatedQuality(): void
{
$items = [
new Item('another foo', 1, 10),
new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 0, 10),
new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 777, 777),
new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 5, 10),
new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 1, 10),
];
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$this->assertSameItem(new Item('another foo', 0, 9), $items[0]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -1, 12), $items[1]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 777, 777), $items[2]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 4, 13), $items[3]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 0, 8), $items[4]);
}
/**
* @group GildedRose
*/
public function testSameMultiItemsDataIsCorrectAfterUpdatedQuality(): void
{
$items = [
new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 0, 10),
new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 1, 10),
new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 5, 10),
new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 10, 10),
new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 100, 10),
];
$gildedRose = $this->initializeGlidedRose($items);
$gildedRose->updateQuality();
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, -1, 0), $items[0]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 0, 13), $items[1]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 4, 13), $items[2]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 9, 12), $items[3]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 99, 11), $items[4]);
}
/**
* @group GildedRose
*/
public function testDifferentMultiItemsDataIsCorrectAfterUpdatedQualityThirtyTimes(): void
{
$items = [
new Item('another super foo', 20, 60),
new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, 20, 0),
new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 777, 777),
new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 31, 0),
new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, 28, 777),
];
$gildedRose = $this->initializeGlidedRose($items);
for ($i = 0; $i < 30; $i++) {
$gildedRose->updateQuality();
}
$this->assertSameItem(new Item('another super foo', -10, 10), $items[0]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_AGED_BRIE, -10, 40), $items[1]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_SULFURAS, 777, 777), $items[2]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_BACKSTAGE_PASSES, 1, 45), $items[3]);
$this->assertSameItem(new Item(StrategyResolverInterface::ITEM_NAME_CONJURED, -2, 0), $items[4]);
}
}

33
php/tests/ItemTest.php Normal file
View File

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Tests;
use GildedRose\Item;
use PHPUnit\Framework\TestCase;
class ItemTest extends TestCase
{
/**
* @group Item
*/
public function testItemCanBeCreated(): void
{
$item = new Item('foo', 1, 2);
$this->assertSame('foo', $item->name);
$this->assertSame(1, $item->sell_in);
$this->assertSame(2, $item->quality);
}
/**
* @group Item
*/
public function testItemToStringIsCorrect(): void
{
$item = new Item('foo', 1, 2);
$this->assertSame('foo, 1, 2', (string) $item);
}
}

41
php/tests/TestCase.php Normal file
View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace Tests;
use GildedRose\GildedRose;
use GildedRose\Item;
use GildedRose\StrategyResolver;
use PHPUnit\Framework\TestCase as CoreTestCase;
abstract class TestCase extends CoreTestCase
{
public function assertSameItem(Item $expected, Item $actual, ?string $key = null): void
{
$actualKey = $key ?? $actual->name;
$this->assertSame($expected->name, $actual->name, sprintf('Item\'s "name" is not equal to expected; expected: %s, actual: %s', $expected->name, $actual->name));
$this->assertSame($expected->sell_in, $actual->sell_in, sprintf('Item\'s "sell in" is not equal to expected; expected: %d, actual: %d, key: %s', $expected->sell_in, $actual->sell_in, $actualKey));
$this->assertSame($expected->quality, $actual->quality, sprintf('Item\'s "quality" is not equal to expected; expected: %d, actual: %d, key: %s', $expected->quality, $actual->quality, $actualKey));
}
/**
* @param Item[] $expected
* @param Item[] $actual
*/
public function assertSameItems(array $expected, array $actual): void
{
foreach ($actual as $key => $actualItem) {
$this->assertSameItem($expected[$key], $actualItem, $key);
}
}
/**
* @param Item[] $items
*/
protected function initializeGlidedRose(array $items): GildedRose
{
return new GildedRose($items, new StrategyResolver());
}
}

View File

@ -1,8 +1,8 @@
full_name:Gilded Rose Refactoring Kata
# set your preferred editor and diff tool.
view_program:subl
diff_program:meld
view_program:nano
diff_program:diff
# Settings for the Python version
#executable:${TEXTTEST_HOME}/python/texttest_fixture.py
@ -31,4 +31,8 @@ diff_program:meld
#executable:${TEXTTEST_HOME}/TypeScript/test/golden-master-text-test.js
#interpreter:node
# Settings for the PHP version
executable:${TEXTTEST_HOME}/php/texttest_fixture.php
interpreter:php
filename_convention_scheme:standard