Tests > increase code coverage

This commit is contained in:
Meritoo
2018-06-09 14:25:20 +02:00
parent 2e60176d95
commit abf0ebf7ec
3 changed files with 827 additions and 39 deletions

View File

@@ -10,7 +10,6 @@ namespace Meritoo\Common\Utilities;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use ReflectionException;
/**
* Useful methods for repository
@@ -20,73 +19,143 @@ use ReflectionException;
*/
class Repository
{
/**
* Name of key responsible for sorting/position of an item in array
*
* @var string
*/
const POSITION_KEY = 'position';
/**
* Replenishes positions of given items
*
* @param array $items The items
* @param bool $asLast (optional) If is set to true, items are placed at the end (default behaviour). Otherwise
* - at top.
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $asLast (optional) If is set to true, items are placed at the end (default behaviour). Otherwise -
* at top.
* @param bool $force (optional) If is set to true, positions are set even there is no extreme position.
* Otherwise - if extreme position is not found (is null) replenishment is stopped / skipped
* Otherwise - if extreme position is unknown (is null) replenishment is stopped / skipped
* (default behaviour).
*
* @throws ReflectionException
*/
public static function replenishPositions($items, $asLast = true, $force = false)
public static function replenishPositions(array &$items, $asLast = true, $force = false)
{
$position = self::getExtremePosition($items, $asLast);
/*
* Extreme position is unknown, but it's required?
* Use 0 as default/start value
*/
if (null === $position && $force) {
$position = 0;
}
if (null !== $position && !empty($items)) {
foreach ($items as $item) {
if (method_exists($item, 'getPosition')) {
if (null === $item->getPosition()) {
if ($asLast) {
++$position;
} else {
--$position;
}
/*
* Extreme position is unknown or there are no items to sort?
* Nothing to do
*/
if (null === $position || empty($items)) {
return;
}
if (method_exists($item, 'setPosition')) {
$item->setPosition($position);
}
}
}
foreach ($items as &$item) {
/*
* The item is not sortable?
*/
if (!self::isSortable($item)) {
continue;
}
/*
* Position has been set?
* Nothing to do
*/
if (self::isSorted($item)) {
continue;
}
/*
* Calculate position
*/
if ($asLast) {
++$position;
} else {
--$position;
}
/*
* It's an object?
* Use proper method to set position
*/
if (is_object($item)) {
$item->setPosition($position);
continue;
}
/*
* It's an array
* Use proper key to set position
*/
$item[static::POSITION_KEY] = $position;
}
}
/**
* Returns extreme position (max or min) of given items
*
* @param array $items The items
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $max (optional) If is set to true, maximum value is returned. Otherwise - minimum.
* @return int
*
* @throws ReflectionException
*/
public static function getExtremePosition($items, $max = true)
public static function getExtremePosition(array $items, $max = true)
{
/*
* No items?
* Nothing to do
*/
if (empty($items)) {
return null;
}
$extreme = null;
if (!empty($items)) {
foreach ($items as $item) {
if (Reflection::hasMethod($item, 'getPosition')) {
$position = $item->getPosition();
foreach ($items as $item) {
/*
* The item is not sortable?
*/
if (!self::isSortable($item)) {
continue;
}
if ($max) {
if ($position > $extreme) {
$extreme = $position;
}
} else {
if ($position < $extreme) {
$extreme = $position;
}
}
$position = null;
/*
* Let's grab the position
*/
if (is_object($item)) {
$position = $item->getPosition();
} elseif (array_key_exists(static::POSITION_KEY, $item)) {
$position = $item[static::POSITION_KEY];
}
/*
* Maximum value is expected?
*/
if ($max) {
/*
* Position was found and it's larger than previously found position (the extreme position)?
*/
if (null === $extreme || (null !== $position && $position > $extreme)) {
$extreme = $position;
}
continue;
}
/*
* Minimum value is expected here.
* Position was found and it's smaller than previously found position (the extreme position)?
*/
if (null === $extreme || (null !== $position && $position < $extreme)) {
$extreme = $position;
}
}
@@ -113,4 +182,54 @@ class Repository
->createQueryBuilder($alias)
->orderBy(sprintf('%s.%s', $alias, $property), $direction);
}
/**
* Returns information if given item is sortable
*
* Sortable means it's an:
* - array
* or
* - object and has getPosition() and setPosition()
*
* @param mixed $item An item to verify (object who has "getPosition()" and "setPosition()" methods or an array)
* @return bool
*/
private static function isSortable($item)
{
return is_array($item)
||
(
is_object($item)
&&
Reflection::hasMethod($item, 'getPosition')
&&
Reflection::hasMethod($item, 'setPosition')
);
}
/**
* Returns information if given item is sorted (position has been set)
*
* @param mixed $item An item to verify (object who has "getPosition()" and "setPosition()" methods or an array)
* @return bool
*/
private static function isSorted($item)
{
/*
* Given item is not sortable?
*/
if (!self::isSortable($item)) {
return false;
}
/*
* It's an object or it's an array
* and position has been set?
*/
return
(is_object($item) && null !== $item->getPosition())
||
(is_array($item) && isset($item[static::POSITION_KEY]));
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Utilities\Repository;
/**
* Sortable object/entity.
* Used for testing the Repository class.
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Sortable
{
/**
* Position used while sorting
*
* @var int
*/
private $position;
/**
* Class constructor
*
* @param int $position (optional) Position used while sorting
*/
public function __construct($position = null)
{
$this->position = $position;
}
/**
* Returns position used while sorting
*
* @return int
*/
public function getPosition()
{
return $this->position;
}
/**
* Sets position used while sorting
*
* @param int $position Position used while sorting
*/
public function setPosition($position)
{
$this->position = $position;
}
/**
* Returns representation of object as string
*
* @return string
*/
public function __toString()
{
return sprintf('%s (position: %d)', self::class, $this->getPosition());
}
}

View File

@@ -0,0 +1,603 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Utilities;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Test\Utilities\Repository\Sortable;
use Meritoo\Common\Utilities\Repository;
use stdClass;
/**
* Test case of the useful methods for repository
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class RepositoryTest extends BaseTestCase
{
public function testConstructor()
{
static::assertHasNoConstructor(Repository::class);
}
public function testReplenishPositionsWithoutItems()
{
$items = [];
Repository::replenishPositions($items);
static::assertEquals([], $items);
}
public function testReplenishPositionsUsingNotSortableObjects()
{
$before = [
new stdClass(),
new stdClass(),
new stdClass(),
];
$after = [
new stdClass(),
new stdClass(),
new stdClass(),
];
/*
* Using defaults
*/
Repository::replenishPositions($before);
static::assertEquals($before, $after);
/*
* Place items at the top
*/
Repository::replenishPositions($before, false);
static::assertEquals($before, $after);
/*
* Set positions even there is no extreme position (at the end)
*/
Repository::replenishPositions($before, true, true);
static::assertEquals($before, $after);
/*
* Set positions even there is no extreme position (at the top)
*/
Repository::replenishPositions($before, false, true);
static::assertEquals($before, $after);
}
/**
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @dataProvider provideArraysWithoutExtremePosition
*/
public function testReplenishPositionsUsingArraysWithoutExtremePosition(array $items)
{
Repository::replenishPositions($items);
static::assertEquals($items, $items);
Repository::replenishPositions($items, false);
static::assertEquals($items, $items);
}
/**
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $asLast If is set to true, items are placed at the end (default behaviour). Otherwise - at top.
* @param array $expected Items with replenished positions
*
* @dataProvider provideArraysWithoutExtremePosition
*/
public function testReplenishPositionsUsingArraysWithoutExtremePositionForce(array $items, $asLast, array $expected)
{
Repository::replenishPositions($items, $asLast, true);
static::assertEquals($expected, $items);
}
/**
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $asLast If is set to true, items are placed at the end (default behaviour). Otherwise - at top.
* @param array $expected Items with replenished positions
*
* @dataProvider provideArraysWithExtremePosition
*/
public function testReplenishPositionsUsingArraysWithExtremePositionForce(array $items, $asLast, array $expected)
{
Repository::replenishPositions($items, $asLast, true);
static::assertEquals($expected, $items);
}
/**
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @dataProvider provideObjectsWithoutExtremePosition
*/
public function testReplenishPositionsUsingObjectsWithoutExtremePosition(array $items)
{
Repository::replenishPositions($items);
static::assertEquals($items, $items);
Repository::replenishPositions($items, false);
static::assertEquals($items, $items);
}
/**
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $asLast If is set to true, items are placed at the end (default behaviour). Otherwise - at top.
* @param array $expected Items with replenished positions
*
* @dataProvider provideObjectsWithoutExtremePosition
*/
public function testReplenishPositionsUsingObjectsWithoutExtremePositionForce(array $items, $asLast, array $expected)
{
Repository::replenishPositions($items, $asLast, true);
static::assertEquals($expected, $items);
}
/**
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $asLast If is set to true, items are placed at the end (default behaviour). Otherwise - at top.
* @param array $expected Items with replenished positions
*
* @dataProvider provideObjectsWithExtremePosition
*/
public function testReplenishPositionsUsingObjectsWithExtremePositionForce(array $items, $asLast, array $expected)
{
Repository::replenishPositions($items, $asLast, true);
static::assertEquals($expected, $items);
}
public function testGetExtremePositionWithoutItems()
{
static::assertNull(Repository::getExtremePosition([]));
static::assertNull(Repository::getExtremePosition([], false));
}
/**
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $max (optional) If is set to true, maximum value is returned. Otherwise - minimum.
* @param int $expected Extreme position (max or min) of given items
*
* @dataProvider provideArraysWithoutExtremePositionToGetExtremePosition
*/
public function testGetExtremePositionUsingArraysWithoutExtremePosition(array $items, $max, $expected)
{
static::assertEquals($expected, Repository::getExtremePosition($items, $max));
}
public function testGetExtremePositionUsingObjects()
{
}
public function testGetEntityOrderedQueryBuilder()
{
}
/**
* Provides arrays without extreme position used to replenish positions of them
*
* @return Generator
*/
public function provideArraysWithoutExtremePosition()
{
yield[
[
[],
[],
],
true,
[
[
Repository::POSITION_KEY => 1,
],
[
Repository::POSITION_KEY => 2,
],
],
];
yield[
[
[],
[],
],
false,
[
[
Repository::POSITION_KEY => -1,
],
[
Repository::POSITION_KEY => -2,
],
],
];
yield[
[
[
'lorem' => 'ipsum',
'dolor',
'sit' => 1,
],
[
'abc' => 'def',
'ghi' => null,
'jkl' => 10,
],
],
true,
[
[
'lorem' => 'ipsum',
'dolor',
'sit' => 1,
Repository::POSITION_KEY => 1,
],
[
'abc' => 'def',
'ghi' => null,
'jkl' => 10,
Repository::POSITION_KEY => 2,
],
],
];
yield[
[
[
'lorem' => 'ipsum',
'dolor',
'sit' => 1,
],
[
'abc' => 'def',
'ghi' => null,
'jkl' => 10,
],
],
false,
[
[
'lorem' => 'ipsum',
'dolor',
'sit' => 1,
Repository::POSITION_KEY => -1,
],
[
'abc' => 'def',
'ghi' => null,
'jkl' => 10,
Repository::POSITION_KEY => -2,
],
],
];
}
/**
* Provides arrays with extreme position used to replenish positions of them
*
* @return Generator
*/
public function provideArraysWithExtremePosition()
{
yield[
[
[
Repository::POSITION_KEY => 1,
],
[],
[],
],
true,
[
[
Repository::POSITION_KEY => 1,
],
[
Repository::POSITION_KEY => 2,
],
[
Repository::POSITION_KEY => 3,
],
],
];
yield[
[
[],
[],
[
Repository::POSITION_KEY => 1,
],
],
true,
[
[
Repository::POSITION_KEY => 2,
],
[
Repository::POSITION_KEY => 3,
],
[
Repository::POSITION_KEY => 1,
],
],
];
yield[
[
[
Repository::POSITION_KEY => 1,
],
[],
[],
],
false,
[
[
Repository::POSITION_KEY => 1,
],
[
Repository::POSITION_KEY => 0,
],
[
Repository::POSITION_KEY => -1,
],
],
];
yield[
[
[],
[],
[
Repository::POSITION_KEY => 1,
],
],
false,
[
[
Repository::POSITION_KEY => 0,
],
[
Repository::POSITION_KEY => -1,
],
[
Repository::POSITION_KEY => 1,
],
],
];
}
/**
* Provides objects without extreme position used to replenish positions of them
*
* @return Generator
*/
public function provideObjectsWithoutExtremePosition()
{
yield[
[
new Sortable(),
new Sortable(),
new Sortable(),
],
true,
[
new Sortable(1),
new Sortable(2),
new Sortable(3),
],
];
yield[
[
new Sortable(),
new Sortable(),
new Sortable(),
],
false,
[
new Sortable(-1),
new Sortable(-2),
new Sortable(-3),
],
];
}
/**
* Provides objects with extreme position used to replenish positions of them
*
* @return Generator
*/
public function provideObjectsWithExtremePosition()
{
yield[
[
new Sortable(1),
new Sortable(),
new Sortable(),
],
true,
[
new Sortable(1),
new Sortable(2),
new Sortable(3),
],
];
yield[
[
new Sortable(),
new Sortable(1),
new Sortable(),
],
true,
[
new Sortable(2),
new Sortable(1),
new Sortable(3),
],
];
yield[
[
new Sortable(1),
new Sortable(),
new Sortable(),
],
false,
[
new Sortable(1),
new Sortable(0),
new Sortable(-1),
],
];
}
/**
* Provides arrays without extreme position used to get extreme position
*
* @return Generator
*/
public function provideArraysWithoutExtremePositionToGetExtremePosition()
{
yield[
[],
false,
null,
];
yield[
[],
true,
null,
];
yield[
[
[
'lorem' => 'ipsum',
'dolor',
'sit' => 1,
],
[
'abc' => 'def',
'ghi' => null,
'jkl' => 10,
],
],
true,
null,
];
yield[
[
[
'lorem' => 'ipsum',
'dolor',
'sit' => 1,
],
[
'abc' => 'def',
'ghi' => null,
'jkl' => 10,
],
],
false,
null,
];
}
/**
* Provides arrays with extreme position used to get extreme position
*
* @return Generator
*/
public function provideArraysWithExtremePositionToGetExtremePosition()
{
yield[
[
[
Repository::POSITION_KEY => 1,
],
[],
[],
],
true,
1,
];
yield[
[
[
Repository::POSITION_KEY => 1,
],
[],
[],
],
false,
1,
];
yield[
[
[],
[],
[
Repository::POSITION_KEY => 1,
],
],
true,
1,
];
yield[
[
[],
[],
[
Repository::POSITION_KEY => 1,
],
],
false,
1,
];
yield[
[
[
Repository::POSITION_KEY => 1,
],
[],
[
Repository::POSITION_KEY => 2,
],
[],
],
true,
1,
];
yield[
[
[
Repository::POSITION_KEY => 1,
],
[],
[
Repository::POSITION_KEY => 2,
],
[],
],
false,
2,
];
}
}