<?php
use App\ContentLoader;
use App\ImgCountHandler;
use Domain\Page;
use Domain\Site;
use Infrastructure\Repository\PageRepository;
use PHPUnit\Framework\TestCase;
class ImgCountHandlerTest extends TestCase
{
public function testCountImgTagsInEmptyList(): void
{
$content = self::EMPTY_CONTENT;
$handler = new ImgCountHandler(new Site(self::ROOT_URL), self::ROOT_URL, ContentLoader::getInstance());
$this->assertEquals(0, $this->invokeMethod($handler, 'countImgTags', [&$content]));
}
public function testCountImgTags(): void
{
$content = self::TEST_PAGE_ROOT;
$handler = new ImgCountHandler(new Site(self::ROOT_URL), self::ROOT_URL, ContentLoader::getInstance());
$this->assertEquals(3, $this->invokeMethod($handler, 'countImgTags', [&$content]));
}
public function testPageProcessing(): void
{
$page = new Page(self::ROOT_URL);
$handler = new ImgCountHandler(new Site(self::ROOT_URL), self::ROOT_URL,
ContentLoader::getInstance());
$content = self::TEST_PAGE_ROOT;
$this->invokeMethod($handler, 'pageProcessing', [$page, &$content]);
$this->assertEquals(3, $page->getImgCount());
foreach ($page->getChildren() as $child) {
$this->assertContains($child->getUrl(), ['http://www.example.com/',
'http://www.example.com/users/345120']);
}
}
public function testPageProcessingRecursive(): void
{
$loaderStub = $this->createStubForTestPageProcessingRecursive();
$handler = new ImgCountHandler(new Site(self::ROOT_URL), self::ROOT_URL, $loaderStub);
$this->invokeMethod($handler, 'pageProcessingRecursive', [[self::ROOT_URL]]);
/** @var PageRepository $repository */
$repository = $this->getInnerPropertyValue($handler, 'repository');
$controlUrlList = [
'http://www.example.com/',
'http://www.example.com/users/345120',
'http://www.example.com/users/345'
];
$unexpectedUrls = [];
foreach ($repository->getPagesIterator() as $url => $page) {
if (($i = array_search($url, $controlUrlList, true)) === false) {
$unexpectedUrls[] = $url;
} else {
unset($controlUrlList[$i]);
}
}
$this->assertEmpty($controlUrlList);
$this->assertEmpty($unexpectedUrls);
$this->assertEquals(3, $repository->get('http://www.example.com/')->getImgCount());
$this->assertEquals(2, $repository->get('http://www.example.com/users/345120')->getImgCount());
$this->assertEquals(4, $repository->get('http://www.example.com/users/345')->getImgCount());
$this->assertGreaterThan(0, $repository->get('http://www.example.com/')->getProcessingTime());
$this->assertGreaterThan(0, $repository->get('http://www.example.com/users/345120')->getProcessingTime());
$this->assertGreaterThan(0, $repository->get('http://www.example.com/users/345')->getProcessingTime());
}
public function testHandle(): void
{
$loaderStub = $this->createStubForTestPageProcessingRecursive();
$handler = new ImgCountHandler(new Site(self::ROOT_URL), self::ROOT_URL, $loaderStub);
$report = $handler->handle(self::ROOT_URL);
/** @var PageRepository $repository */
$repository = $this->getInnerPropertyValue($handler, 'repository');
$sorted = [];
/** @var Page $page */
foreach ($repository->getPagesIterator() as $page) {
$sorted[] = [
$page->getUrl(),
$page->getImgCount()
];
}
$this->assertEquals([
['http://www.example.com/users/345', 4],
['http://www.example.com/', 3],
['http://www.example.com/users/345120', 2]
], $sorted);
}
private const
ROOT_URL = 'http://www.example.com',
EMPTY_CONTENT = '<body><html><div></div></html></body>',
TEST_PAGE_ROOT = '<html>
<body>
<img src="http://www.example.com">Example</img>
<a href="http://www.example.com">Example</a>
<div>
<img src="http://www.stackoverflow.com/users/345120">SO</img>
<a href="http://www.stackoverflow.com/users/345120">SO</a>
</div>
<img src="www.stackoverflow.com/users/345120">SO</img>
<a href="//www.stackoverflow.com/users/345120">SO</a>
<a href="/users/345120">SO</a>
</body>
</html>',
TEST_PAGE_1 = '<html>
<body>
<img src="http://www.example.com">Example</img>
<a href="http://www.example.com">Example</a>
<div>
<img src="http://www.stackoverflow.com/users/345120">SO</img>
<a href="http://www.stackoverflow.com/users/345120">SO</a>
</div>
<a href="//www.stackoverflow.com/users/345120">SO</a>
<a href="/users/345">SO</a>
</body>
</html>',
TEST_PAGE_2 = '<html>
<body>
<img src="http://www.example.com">Example</img>
<a href="http://www.example.com">Example</a>
<div>
<img src="http://www.stackoverflow.com/users/345120">SO</img>
<a href="http://www.stackoverflow.com/users/345120">SO</a>
</div>
<img src="www.stackoverflow.com/users/345120">SO</img>
<a href="//www.stackoverflow.com/users/345120">SO</a>
<img src="http://www.example.com">Example</img>
<a href="/users/345120">SO</a>
</body>
</html>';
/**
* Call protected/private method of a class.
*
* @param object &$object Instantiated object that we will run method on.
* @param string $methodName Method name to call
* @param array $parameters Array of parameters to pass into method
*
* @return mixed Method return.
* @throws Throwable
*/
public function invokeMethod(&$object, $methodName, array $parameters = array())
{
$reflection = new ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
return $method->invokeArgs($object, $parameters);
}
/**
* Return value of a private property using ReflectionClass
*
* @param stdClass $instance
* @param string $property
*
* @return mixed
* @throws ReflectionException
*/
private function getInnerPropertyValue($instance, $property)
{
$reflector = new ReflectionClass($instance);
$reflector_property = $reflector->getProperty($property);
$reflector_property->setAccessible(true);
return $reflector_property->getValue($instance);
}
private function createStubForTestPageProcessingRecursive()
{
$loaderStub = $this->createMock(ContentLoader::class);
$map = [
[
[], []
], [
['http://www.example.com/'],
['http://www.example.com/' => self::TEST_PAGE_ROOT]
], [
['http://www.example.com/users/345120'],
['http://www.example.com/users/345120' => self::TEST_PAGE_1]
], [
['http://www.example.com/users/345'],
['http://www.example.com/users/345' => self::TEST_PAGE_2]
],
];
$loaderStub->method('loadContent')
->willReturnMap($map);
return $loaderStub;
}
}
|