Created
July 17, 2017 18:10
-
-
Save weverson83/262142b9d745c4aed535c52d09f09409 to your computer and use it in GitHub Desktop.
Category Tree - PHPUnit Test Case
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class CategoryTreeTest extends PHPUnit_Framework_TestCase | |
{ | |
/** | |
* @return array | |
*/ | |
public function getCategories(){ | |
$root = [ | |
'id' => 'root', | |
'parent' => null, | |
'children' => [], | |
]; | |
$books = [ | |
'id' => 'books', | |
'parent' => 'root', | |
'children' => [], | |
]; | |
$movies = [ | |
'id' => 'movies', | |
'parent' => 'root', | |
'children' => [], | |
]; | |
$fantasy = [ | |
'id' => 'fantasy', | |
'parent' => 'books', | |
'children' => [], | |
]; | |
$tolkien = [ | |
'id' => 'tolkien', | |
'parent' => 'fantasy', | |
'children' => [], | |
]; | |
$root['children'] = [&$books, &$movies]; | |
$books['children'] = [&$fantasy]; | |
$fantasy['children'] = [&$tolkien]; | |
return $root; | |
} | |
/** | |
* @return array | |
*/ | |
public function getProductsAssignments() | |
{ | |
return [ | |
'B001' => ['movies', 'fantasy'], | |
'D8' => ['tolkien', 'root'], | |
'H12' => ['books', 'tolkien', 'root', 'movies', 'fantasy'], | |
'RX20' => [], | |
]; | |
} | |
/** | |
* @param string $categoryId | |
* @param array $currentCategory | |
* @return array | false | |
*/ | |
public function getCategoryById($categoryId, $currentCategory = null) | |
{ | |
if (!$currentCategory) { | |
$currentCategory = $this->getCategories(); | |
} | |
if ($currentCategory['id'] == $categoryId) { | |
return $currentCategory; | |
} | |
$result = array_reduce($currentCategory['children'], function ($result, $child) use ($categoryId) { | |
$category = $this->getCategoryById($categoryId, $child); | |
if ($category) { | |
$result = $category; | |
} | |
return $result; | |
}, false); | |
return $result; | |
} | |
/** | |
* @param $productId | |
* @return array | |
*/ | |
protected function getProductCategories($productId) | |
{ | |
$assignments = $this->getProductsAssignments(); | |
if (!array_key_exists($productId, $assignments)) { | |
return []; | |
} | |
return array_reduce($assignments[$productId], function ($result, $categoryId) { | |
$currentCategory = $this->getCategoryById($categoryId); | |
if ($currentCategory !== false) { | |
$result[] = $currentCategory; | |
} | |
return $result; | |
}, []); | |
} | |
/** | |
* @param $productId | |
* @return array | |
*/ | |
public function getPaths($productId) | |
{ | |
$paths = array_reduce($this->getProductCategories($productId), function ($result, $category) { | |
do { | |
$path[] = $category['id']; | |
} | |
while ($category = $this->getCategoryById($category['parent'])); | |
if (count($path) > 1) { | |
$result[] = array_reverse($path); | |
} | |
return $result; | |
}, []); | |
if (!count($paths)) { | |
return ['EMPTY']; | |
} | |
$paths = $this->transformIntoString($this->removeDuplicatedTrees($paths)); | |
usort($paths, function ($pathA, $pathB) { | |
return strcmp($pathA, $pathB); | |
}); | |
return $paths; | |
} | |
/** | |
* @param $paths | |
* @return mixed | |
*/ | |
protected function transformIntoString($paths) | |
{ | |
return array_reduce($paths, function ($result, $path) { | |
$result[] = implode(';', $path); | |
return $result; | |
}, []); | |
} | |
/** | |
* @param $paths | |
* @return array | |
*/ | |
protected function removeDuplicatedTrees($paths) | |
{ | |
for ($i = 0; $i < count($paths); $i++) { | |
for ($j = count($paths) - 1; $j > $i; $j--) { | |
if (count(array_intersect($paths[$i], $paths[$j])) > 1) { | |
$paths[$i] = $paths[$i] + $paths[$j]; | |
unset($paths[$j]); | |
} | |
} | |
} | |
return $paths; | |
} | |
public function testGetCategoryById() | |
{ | |
$root = $this->getCategories(); | |
$this->assertEquals($root, $this->getCategoryById('root')); | |
$this->assertEquals($root['children'][0], $this->getCategoryById('books')); | |
$this->assertEquals($root['children'][1], $this->getCategoryById('movies')); | |
$this->assertEquals($root['children'][0]['children'][0], $this->getCategoryById('fantasy')); | |
$this->assertEquals($root['children'][0]['children'][0]['children'][0], $this->getCategoryById('tolkien')); | |
} | |
public function testPathIsEmptyWhenNoProductIdIsSpecified() | |
{ | |
$this->assertEquals(['EMPTY'], $this->getPaths('')); | |
} | |
public function testPathIsEmptyWhenInvalidProductIdIsSpecified() | |
{ | |
$this->assertEquals(['EMPTY'], $this->getPaths('XXXXXXXX')); | |
} | |
public function testPathIsEmptyWhenProductCategoryIsRoot() | |
{ | |
$this->assertEquals(['EMPTY'], $this->getPaths('RX20')); | |
} | |
public function testPathsReturnsInAlphabeticalOrder() | |
{ | |
$this->assertEquals( | |
[ | |
'root;books;fantasy', | |
'root;movies', | |
], $this->getPaths('B001')); | |
} | |
public function testGetPathsOnFourthLevel() | |
{ | |
$this->assertEquals(['root;books;fantasy;tolkien'], $this->getPaths('D8')); | |
} | |
public function testOnlyTheLongestPathIsReturnedWhenProductHas2CategoriesIntTeSameTree() | |
{ | |
$this->assertEquals(['root;books;fantasy;tolkien', 'root;movies'], $this->getPaths('H12')); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment