nextcloud-news/tests/Unit/Service/ItemServiceTest.php

635 lines
18 KiB
PHP

<?php
/**
* Nextcloud - News
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Alessandro Cosentino <cosenal@gmail.com>
* @author Bernhard Posselt <dev@bernhard-posselt.com>
* @copyright 2012 Alessandro Cosentino
* @copyright 2012-2014 Bernhard Posselt
*/
namespace OCA\News\Tests\Unit\Service;
use OCA\News\Db\ItemMapperV2;
use OCA\News\Service\Exceptions\ServiceConflictException;
use OCA\News\Service\Exceptions\ServiceValidationException;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCA\News\Service\ItemServiceV2;
use \OCP\AppFramework\Db\DoesNotExistException;
use \OCA\News\Db\Item;
use \OCA\News\Db\ListType;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\IConfig;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
/**
* Class ItemServiceTest
*
* @package OCA\News\Tests\Unit\Service
*/
class ItemServiceTest extends TestCase
{
/**
* @var MockObject|ItemMapperV2
*/
private $mapper;
/**
* @var ItemServiceV2
*/
private $class;
/**
* @var MockObject|IConfig
*/
private $config;
/**
* @var MockObject|LoggerInterface
*/
private $logger;
/**
* @var int
*/
private $newestItemId;
/**
* @var string
*/
private $user;
protected function setUp(): void
{
$this->mapper = $this->getMockBuilder(ItemMapperV2::class)
->disableOriginalConstructor()
->getMock();
$this->config = $this->getMockBuilder(IConfig::class)
->disableOriginalConstructor()
->getMock();
$this->logger = $this->getMockBuilder(LoggerInterface::class)
->disableOriginalConstructor()
->getMock();
$this->class = new ItemServiceV2(
$this->mapper,
$this->config,
$this->logger
);
$this->user = 'jack';
$this->id = 3;
$this->updatedSince = 20333;
$this->showAll = true;
$this->offset = 5;
$this->limit = 20;
$this->newestItemId = 4;
}
public function testFindAllNewFeed()
{
$this->mapper->expects($this->once())
->method('findAllInFeedAfter')
->with('jack', 2, 20333, true)
->will($this->returnValue([]));
$result = $this->class->findAllInFeedAfter($this->user, 2, 20333, true);
$this->assertEquals([], $result);
}
public function testFindAllNewFolder()
{
$this->mapper->expects($this->once())
->method('findAllInFolderAfter')
->with('jack', 2, 20333, true)
->will($this->returnValue([]));
$result = $this->class->findAllInFolderAfter($this->user, 2, 20333, true);
$this->assertEquals([], $result);
}
public function testFindAllNewItem()
{
$this->mapper->expects($this->once())
->method('findAllAfter')
->with('jack', 2, 20333)
->will($this->returnValue([]));
$result = $this->class->findAllAfter($this->user, 2, 20333);
$this->assertEquals([], $result);
}
public function testFindAllNewItemWrongType()
{
$this->expectException(ServiceValidationException::class);
$this->expectExceptionMessage('Trying to find in unknown type');
$this->mapper->expects($this->never())
->method('findAllAfter');
$result = $this->class->findAllAfter($this->user, 5, 20333);
$this->assertEquals([], $result);
}
public function testFindAllFeed()
{
$this->mapper->expects($this->once())
->method('findAllFeed')
->with('jack', 3, 20, 5, true, false, [])
->will($this->returnValue(['val']));
$result = $this->class->findAllInFeedWithFilters(
'jack',
3,
20,
5,
true,
false
);
$this->assertEquals(['val'], $result);
}
public function testFindAllFolder()
{
$this->mapper->expects($this->once())
->method('findAllFolder')
->with('jack', 3, 20, 5, true, true, [])
->will($this->returnValue(['val']));
$result = $this->class->findAllInFolderWithFilters(
'jack',
3,
20,
5,
true,
true,
[]
);
$this->assertEquals(['val'], $result);
}
public function testFindAllItems()
{
$type = ListType::STARRED;
$this->mapper->expects($this->once())
->method('findAllItems')
->with('jack', $type, 20, 5, true, [])
->will($this->returnValue(['val']));
$result = $this->class->findAllWithFilters('jack', $type, 20, 5, true);
$this->assertEquals(['val'], $result);
}
public function testFindAllSearch()
{
$type = ListType::STARRED;
$search = ['test'];
$this->mapper->expects($this->once())
->method('findAllItems')
->with('jack', $type, 20, 5, true, $search)
->will($this->returnValue(['val']));
$result = $this->class->findAllWithFilters('jack', $type, 20, 5, true, $search);
$this->assertEquals(['val'], $result);
}
public function testFindAll()
{
$this->mapper->expects($this->once())
->method('findAll')
->will($this->returnValue(['val']));
$result = $this->class->findAll();
$this->assertEquals(['val'], $result);
}
public function testStarByGuid()
{
$itemId = 3;
$feedId = 5;
$guidHash = md5('hihi');
$item = new Item();
$item->setId($itemId);
$item->setStarred(false);
$expectedItem = new Item();
$expectedItem->setStarred(true);
$expectedItem->setId($itemId);
$this->mapper->expects($this->once())
->method('findForUserByGuidHash')
->with('jack', $feedId, $guidHash)
->will($this->returnValue($item));
$this->mapper->expects($this->once())
->method('update')
->with($this->equalTo($expectedItem));
$this->class->starByGuid('jack', $feedId, $guidHash, true);
$this->assertTrue($item->isStarred());
}
public function testUnstar()
{
$itemId = 3;
$feedId = 5;
$guidHash = md5('hihi');
$item = new Item();
$item->setId($itemId);
$item->setStarred(true);
$expectedItem = new Item();
$expectedItem->setStarred(true); //workaround to set starred as updated field
$expectedItem->setStarred(false);
$expectedItem->setId($itemId);
$this->mapper->expects($this->once())
->method('findForUserByGuidHash')
->with('jack', $feedId, $guidHash)
->will($this->returnValue($item));
$this->mapper->expects($this->once())
->method('update')
->with($this->equalTo($expectedItem));
$this->class->starByGuid('jack', $feedId, $guidHash, false);
$this->assertFalse($item->isStarred());
}
public function testRead()
{
$item = $this->getMockBuilder(Item::class)
->getMock();
$item->expects($this->once())
->method('setUnread')
->with(false);
$this->mapper->expects($this->once())
->method('findFromUser')
->with('jack', 3)
->will($this->returnValue($item));
$this->mapper->expects($this->once())
->method('update')
->with($item)
->will($this->returnValue($item));
$this->class->read('jack', 3, true);
}
public function testStar()
{
$item = $this->getMockBuilder(Item::class)
->getMock();
$item->expects($this->once())
->method('setStarred')
->with(true);
$this->mapper->expects($this->once())
->method('findFromUser')
->with('jack', 3)
->will($this->returnValue($item));
$this->mapper->expects($this->once())
->method('update')
->with($item)
->will($this->returnValue($item));
$this->class->star('jack', 3, true);
}
public function testStarByGuidDoesNotExist()
{
$this->expectException(ServiceNotFoundException::class);
$this->mapper->expects($this->once())
->method('findForUserByGuidHash')
->will($this->throwException(new DoesNotExistException('')));
$this->class->starByGuid('jack', 1, 'hash', true);
}
public function testStarByGuidDuplicate()
{
$this->expectException(ServiceConflictException::class);
$this->mapper->expects($this->once())
->method('findForUserByGuidHash')
->will($this->throwException(new MultipleObjectsReturnedException('')));
$this->class->starByGuid('jack', 1, 'hash', true);
}
public function testReadAll()
{
$highestItemId = 6;
$this->mapper->expects($this->once())
->method('readAll')
->with('jack', $highestItemId);
$this->class->readAll('jack', $highestItemId);
}
public function testGetNewestItemId()
{
$this->mapper->expects($this->once())
->method('newest')
->with($this->equalTo('jack'))
->will($this->returnValue(Item::fromParams(['id' => 12])));
$result = $this->class->newest('jack');
$this->assertEquals(12, $result->getId());
}
public function testGetNewestItemIdDoesNotExist()
{
$this->mapper->expects($this->once())
->method('newest')
->with($this->equalTo('jack'))
->will(
$this->throwException(
new DoesNotExistException('There are no items')
)
);
$this->expectException(ServiceNotFoundException::class);
$this->class->newest('jack');
}
public function testGetNewestItemDuplicate()
{
$this->mapper->expects($this->once())
->method('newest')
->with($this->equalTo('jack'))
->will(
$this->throwException(
new MultipleObjectsReturnedException('There are no items')
)
);
$this->expectException(ServiceConflictException::class);
$this->class->newest('jack');
}
public function testStarredCount()
{
$this->mapper->expects($this->once())
->method('findAllFromUser')
->with('jack', ['starred' => 1])
->will($this->returnValue([new Item(), new Item()]));
$result = $this->class->starred('jack');
$this->assertEquals(2, count($result));
}
public function testInsertOrUpdateInserts()
{
$item = $this->getMockBuilder(Item::class)
->getMock();
$item->expects($this->once())
->method('getFeedId')
->will($this->returnValue(1));
$item->expects($this->once())
->method('getGuidHash')
->will($this->returnValue('hash'));
$this->mapper->expects($this->once())
->method('findByGuidHash')
->with(1, 'hash')
->will($this->throwException(new DoesNotExistException('exception')));
$this->mapper->expects($this->once())
->method('insert')
->with($item)
->will($this->returnValue($item));
$result = $this->class->insertOrUpdate($item);
$this->assertEquals($item, $result);
}
public function testInsertOrUpdateUpdates()
{
$item = $this->getMockBuilder(Item::class)
->getMock();
$db_item = $this->getMockBuilder(Item::class)
->getMock();
$item->expects($this->once())
->method('getFeedId')
->will($this->returnValue(1));
$item->expects($this->once())
->method('getGuidHash')
->will($this->returnValue('hash'));
$item->expects($this->once())
->method('setUnread')
->with(true)
->will($this->returnSelf());
$db_item->expects($this->once())
->method('isUnread')
->will($this->returnValue(true));
$item->expects($this->once())
->method('setStarred')
->with(true)
->will($this->returnSelf());
$db_item->expects($this->once())
->method('isStarred')
->will($this->returnValue(true));
$item->expects($this->once())
->method('generateSearchIndex')
->will($this->returnSelf());
$item->expects($this->once())
->method('getFingerprint')
->will($this->returnValue('fingerA'));
$db_item->expects($this->once())
->method('getFingerprint')
->will($this->returnValue('fingerB'));
$item->expects($this->never())
->method('resetUpdatedFields');
$this->mapper->expects($this->once())
->method('findByGuidHash')
->with(1, 'hash')
->will($this->returnValue($db_item));
$this->mapper->expects($this->once())
->method('update')
->with($item)
->will($this->returnValue($item));
$result = $this->class->insertOrUpdate($item);
$this->assertEquals($item, $result);
}
public function testInsertOrUpdateSkipsSame()
{
$item = $this->getMockBuilder(Item::class)
->getMock();
$db_item = $this->getMockBuilder(Item::class)
->getMock();
$item->expects($this->once())
->method('getFeedId')
->will($this->returnValue(1));
$item->expects($this->once())
->method('getGuidHash')
->will($this->returnValue('hash'));
$item->expects($this->once())
->method('setUnread')
->with(true)
->will($this->returnSelf());
$db_item->expects($this->once())
->method('isUnread')
->will($this->returnValue(true));
$item->expects($this->once())
->method('setStarred')
->with(true)
->will($this->returnSelf());
$db_item->expects($this->once())
->method('isStarred')
->will($this->returnValue(true));
$item->expects($this->once())
->method('generateSearchIndex')
->will($this->returnSelf());
$item->expects($this->once())
->method('getFingerprint')
->will($this->returnValue('fingerA'));
$db_item->expects($this->once())
->method('getFingerprint')
->will($this->returnValue('fingerA'));
$item->expects($this->once())
->method('resetUpdatedFields');
$this->mapper->expects($this->once())
->method('findByGuidHash')
->with(1, 'hash')
->will($this->returnValue($db_item));
$this->mapper->expects($this->once())
->method('update')
->with($item)
->will($this->returnValue($item));
$result = $this->class->insertOrUpdate($item);
$this->assertEquals($item, $result);
}
public function testFindByGuidHash()
{
$item = $this->getMockBuilder(Item::class)
->getMock();
$this->mapper->expects($this->once())
->method('findByGuidHash')
->with(1, 'a')
->will($this->returnValue($item));
$result = $this->class->findByGuidHash(1, 'a');
$this->assertEquals($item, $result);
}
public function testFindAllInFeed()
{
$items = [new Item(), new Item()];
$this->mapper->expects($this->once())
->method('findAllInFeedAfter')
->with('jack', 1, PHP_INT_MIN, false)
->will($this->returnValue($items));
$result = $this->class->findAllInFeed('jack', 1);
$this->assertEquals($items, $result);
}
public function testPurgeOverThreshold()
{
$this->mapper->expects($this->once())
->method('deleteOverThreshold')
->with(1, true)
->will($this->returnValue(1));
$result = $this->class->purgeOverThreshold(1, true);
$this->assertEquals(1, $result);
}
public function testPurgeOverThresholdWithNegative()
{
$this->mapper->expects($this->never())
->method('deleteOverThreshold');
$result = $this->class->purgeOverThreshold(-1, true);
$this->assertEquals(null, $result);
}
public function testPurgeOverThresholdNull()
{
$this->config->expects($this->exactly(2))
->method('getAppValue')
->withConsecutive(['news', 'autoPurgeCount', 200], ['news', 'purgeUnread', false])
->willReturnOnConsecutiveCalls(200, false);
$this->mapper->expects($this->once())
->method('deleteOverThreshold')
->with(200, false);
$this->class->purgeOverThreshold();
}
public function testPurgeOverThresholdSet()
{
$this->config->expects($this->once())
->method('getAppValue')
->with('news', 'purgeUnread', false)
->will($this->returnValue(false));
$this->mapper->expects($this->once())
->method('deleteOverThreshold')
->with(5);
$this->class->purgeOverThreshold(5);
}
}