* @author Bernhard Posselt * @copyright 2012 Alessandro Cosentino * @copyright 2012-2014 Bernhard Posselt */ namespace OCA\News\Tests\Unit\Controller; use OCA\News\Controller\FeedController; use OCA\News\Db\Folder; use OCA\News\Service\FeedServiceV2; use OCA\News\Service\FolderServiceV2; use OCA\News\Service\ImportService; use OCA\News\Service\ItemServiceV2; use OCP\AppFramework\Http; use OCA\News\Db\Feed; use OCA\News\Db\ListType; use OCA\News\Service\Exceptions\ServiceNotFoundException; use OCA\News\Service\Exceptions\ServiceConflictException; use OCP\IConfig; use OCP\IRequest; use OCP\IUser; use OCP\IUserSession; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; class FeedControllerTest extends TestCase { /** * @var string */ private $appName; private $exampleResult; private $uid; /** * @var MockObject|FolderServiceV2 */ private $folderService; /** * @var MockObject|FeedServiceV2 */ private $feedService; /** * @var MockObject|ImportService */ private $importService; /** * @var MockObject|ItemServiceV2 */ private $itemService; /** * @var MockObject|IConfig */ private $settings; /** * @var MockObject|IUser */ private $user; /** * @var FeedController */ private $class; /** * Gets run before each test */ public function setUp(): void { $this->appName = 'news'; $this->uid = 'jack'; $this->settings = $this->getMockBuilder(IConfig::class) ->disableOriginalConstructor() ->getMock(); $this->itemService = $this ->getMockBuilder(ItemServiceV2::class) ->disableOriginalConstructor() ->getMock(); $this->feedService = $this ->getMockBuilder(FeedServiceV2::class) ->disableOriginalConstructor() ->getMock(); $this->importService = $this ->getMockBuilder(ImportService::class) ->disableOriginalConstructor() ->getMock(); $this->folderService = $this ->getMockBuilder(FolderServiceV2::class) ->disableOriginalConstructor() ->getMock(); $this->user = $this->getMockBuilder(IUser::class)->getMock(); $this->user->expects($this->any()) ->method('getUID') ->will($this->returnValue($this->uid)); $this->userSession = $this->getMockBuilder(IUserSession::class) ->getMock(); $this->userSession->expects($this->any()) ->method('getUser') ->will($this->returnValue($this->user)); $request = $this->getMockBuilder(IRequest::class) ->disableOriginalConstructor() ->getMock(); $this->class = new FeedController( $request, $this->folderService, $this->feedService, $this->itemService, $this->importService, $this->settings, $this->userSession ); $this->exampleResult = [ 'activeFeed' => [ 'id' => 0, 'type' => ListType::ALL_ITEMS ] ]; } public function testIndex() { $result = [ 'feeds' => [ ['a feed'], ], 'starred' => 4 ]; $this->feedService->expects($this->once()) ->method('findAllForUser') ->with($this->uid) ->will($this->returnValue($result['feeds'])); $this->itemService->expects($this->once()) ->method('newest') ->with($this->uid) ->will($this->throwException(new ServiceNotFoundException(''))); $this->itemService->expects($this->once()) ->method('starred') ->with($this->uid) ->will($this->returnValue([1, 2, 3, 4])); $response = $this->class->index(); $this->assertEquals($result, $response); } public function testIndexHighestItemIdExists() { $result = [ 'feeds' => [ ['a feed'], ], 'starred' => 2, 'newestItemId' => 5 ]; $this->feedService->expects($this->once()) ->method('findAllForUser') ->with($this->uid) ->will($this->returnValue($result['feeds'])); $this->itemService->expects($this->once()) ->method('newest') ->with($this->uid) ->will($this->returnValue(Feed::fromParams(['id' => 5]))); $this->itemService->expects($this->once()) ->method('starred') ->with($this->uid) ->will($this->returnValue([1, 2])); $response = $this->class->index(); $this->assertEquals($result, $response); } /** * Configure settings with active mocks * * @param $id * @param $type */ private function activeInitMocks($id, $type): void { $this->settings->expects($this->exactly(2)) ->method('getUserValue') ->withConsecutive( [$this->uid, $this->appName, 'lastViewedFeedId'], [$this->uid, $this->appName, 'lastViewedFeedType'] ) ->willReturnOnConsecutiveCalls($id, $type); } public function testActive() { $id = 3; $type = ListType::STARRED; $result = [ 'activeFeed' => [ 'id' => $id, 'type' => $type ] ]; $this->activeInitMocks($id, $type); $response = $this->class->active(); $this->assertEquals($result, $response); } public function testActiveFeed() { $id = 3; $type = ListType::FEED; $result = [ 'activeFeed' => [ 'id' => $id, 'type' => $type ] ]; $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, $id) ->will($this->returnValue(new Feed())); $this->activeInitMocks($id, $type); $response = $this->class->active(); $this->assertEquals($result, $response); } public function testActiveFeedDoesNotExist() { $id = 3; $type = ListType::FEED; $ex = new ServiceNotFoundException('hiu'); $result = $this->exampleResult; $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, $id) ->will($this->throwException($ex)); $this->activeInitMocks($id, $type); $response = $this->class->active(); $this->assertEquals($result, $response); } public function testActiveFolder() { $type = ListType::FOLDER; $folder = new Folder(); $folder->setId(3); $result = [ 'activeFeed' => [ 'id' => 3, 'type' => 1 ] ]; $this->folderService->expects($this->once()) ->method('find') ->with($this->uid, 3) ->will($this->returnValue($folder)); $this->activeInitMocks(3, $type); $response = $this->class->active(); $this->assertEquals($result, $response); } public function testActiveFolderDoesNotExist() { $id = 3; $type = ListType::FOLDER; $ex = new ServiceNotFoundException('hiu'); $result = $this->exampleResult; $this->folderService->expects($this->once()) ->method('find') ->with($this->uid, $id) ->will($this->throwException($ex)); $this->activeInitMocks($id, $type); $response = $this->class->active(); $this->assertEquals($result, $response); } public function testActiveActiveIsNull() { $id = 3; $type = null; $result = $this->exampleResult; $this->activeInitMocks($id, $type); $response = $this->class->active(); $this->assertEquals($result, $response); } public function testCreate() { $result = [ 'feeds' => [new Feed()], 'newestItemId' => 3 ]; $this->itemService->expects($this->once()) ->method('newest') ->will($this->returnValue(Feed::fromParams(['id' => 3]))); $this->feedService->expects($this->once()) ->method('purgeDeleted') ->with($this->uid, false); $this->feedService->expects($this->once()) ->method('fetch') ->with($result['feeds'][0]); $this->feedService->expects($this->once()) ->method('create') ->with($this->uid, 'hi', 4, false, 'yo') ->will($this->returnValue($result['feeds'][0])); $response = $this->class->create('hi', 4, 'yo'); $this->assertEquals($result, $response); } public function testCreateOldFolderId() { $result = [ 'feeds' => [new Feed()], 'newestItemId' => 3 ]; $this->itemService->expects($this->once()) ->method('newest') ->will($this->returnValue(Feed::fromParams(['id' => 3]))); $this->feedService->expects($this->once()) ->method('purgeDeleted') ->with($this->uid, false); $this->feedService->expects($this->once()) ->method('fetch') ->with($result['feeds'][0]); $this->feedService->expects($this->once()) ->method('create') ->with($this->uid, 'hi', null, false, 'yo') ->will($this->returnValue($result['feeds'][0])); $response = $this->class->create('hi', 0, 'yo'); $this->assertEquals($result, $response); } public function testCreateNoItems() { $result = ['feeds' => [new Feed()]]; $this->feedService->expects($this->once()) ->method('purgeDeleted') ->with($this->uid, false); $this->itemService->expects($this->once()) ->method('newest') ->will($this->throwException(new ServiceNotFoundException(''))); $this->feedService->expects($this->once()) ->method('create') ->with($this->uid, 'hi', 4, false, 'yo') ->will($this->returnValue($result['feeds'][0])); $this->feedService->expects($this->once()) ->method('fetch') ->with($result['feeds'][0]); $response = $this->class->create('hi', 4, 'yo'); $this->assertEquals($result, $response); } public function testCreateReturnsErrorForInvalidCreate() { $msg = 'except'; $ex = new ServiceNotFoundException($msg); $this->feedService->expects($this->once()) ->method('purgeDeleted') ->with($this->uid, false); $this->feedService->expects($this->once()) ->method('create') ->will($this->throwException($ex)); $response = $this->class->create('hi', 4, 'test'); $params = json_decode($response->render(), true); $this->assertEquals($msg, $params['message']); $this->assertEquals( $response->getStatus(), Http::STATUS_UNPROCESSABLE_ENTITY ); } public function testCreateReturnsErrorForDuplicateCreate() { $msg = 'except'; $ex = new ServiceConflictException($msg); $this->feedService->expects($this->once()) ->method('purgeDeleted') ->with($this->uid, false); $this->feedService->expects($this->once()) ->method('create') ->will($this->throwException($ex)); $response = $this->class->create('hi', 4, 'test'); $params = json_decode($response->render(), true); $this->assertEquals($msg, $params['message']); $this->assertEquals($response->getStatus(), Http::STATUS_CONFLICT); } public function testDelete() { $feed = $this->getMockBuilder(Feed::class) ->getMock(); $feed->expects($this->once()) ->method('setDeletedAt'); $this->feedService->expects($this->once()) ->method('find') ->with('jack', 4) ->willReturn($feed); $this->feedService->expects($this->once()) ->method('update') ->with('jack', $feed); $this->class->delete(4); } public function testDeleteDoesNotExist() { $msg = 'hehe'; $this->feedService->expects($this->once()) ->method('find') ->will($this->throwException(new ServiceNotFoundException($msg))); $response = $this->class->delete(4); $params = json_decode($response->render(), true); $this->assertEquals($msg, $params['message']); $this->assertEquals($response->getStatus(), Http::STATUS_NOT_FOUND); } public function testUpdate() { $feed = new Feed(); $feed->setId(3); $feed->setUnreadCount(44); $result = [ 'feeds' => [ [ 'id' => $feed->getId(), 'unreadCount' => $feed->getUnreadCount() ] ] ]; $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, 4) ->will($this->returnValue($feed)); $this->feedService->expects($this->once()) ->method('fetch') ->with($feed) ->will($this->returnValue($feed)); $response = $this->class->update(4); $this->assertEquals($result, $response); } public function testUpdateReturnsJSONError() { $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, 4) ->will($this->throwException(new ServiceNotFoundException('NO!'))); $response = $this->class->update(4); $render = $response->render(); $this->assertEquals('{"message":"NO!"}', $render); $this->assertEquals($response->getStatus(), Http::STATUS_NOT_FOUND); } public function testImport() { $feed = new Feed(); $expected = [ 'starred' => 3, 'feeds' => [$feed] ]; $this->importService->expects($this->once()) ->method('importArticles') ->with($this->uid, ['json'],) ->will($this->returnValue($feed)); $this->itemService->expects($this->once()) ->method('starred') ->with($this->uid) ->will($this->returnValue([1, 2, 3])); $response = $this->class->import(['json']); $this->assertEquals($expected, $response); } public function testImportCreatesNoAdditionalFeed() { $this->importService->expects($this->once()) ->method('importArticles') ->with($this->uid, ['json']) ->will($this->returnValue(null)); $this->itemService->expects($this->once()) ->method('starred') ->with($this->uid) ->will($this->returnValue([1, 2, 3])); $response = $this->class->import(['json']); $this->assertEquals(['starred' => 3], $response); } public function testReadFeed() { $expected = [ 'feeds' => [ [ 'id' => 4, 'unreadCount' => 0 ] ] ]; $this->feedService->expects($this->once()) ->method('read') ->with($this->uid, 4, 5); $response = $this->class->read(4, 5); $this->assertEquals($expected, $response); } public function testRestore() { $feed = $this->getMockBuilder(Feed::class) ->getMock(); $feed->expects($this->once()) ->method('setDeletedAt') ->with(null); $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, 4) ->willReturn($feed); $this->feedService->expects($this->once()) ->method('update') ->with($this->uid, $feed); $this->class->restore(4); } public function testRestoreDoesNotExist() { $msg = 'hehe'; $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, 4) ->will($this->throwException(new ServiceNotFoundException($msg))); $response = $this->class->restore(4); $params = json_decode($response->render(), true); $this->assertEquals($msg, $params['message']); $this->assertEquals($response->getStatus(), Http::STATUS_NOT_FOUND); } public function testPatch() { $feed = $this->getMockBuilder(Feed::class) ->getMock(); $feed->expects($this->never()) ->method('setFolderId'); $feed->expects($this->once()) ->method('setPinned') ->with(true); $feed->expects($this->once()) ->method('setFullTextEnabled') ->with(false); $feed->expects($this->once()) ->method('setUpdateMode') ->with(1); $feed->expects($this->never()) ->method('setOrdering') ->with(true); $feed->expects($this->never()) ->method('setTitle') ->with(true); $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, 4) ->will($this->returnValue($feed)); $this->feedService->expects($this->once()) ->method('update') ->with($this->uid, $feed); $this->class->patch(4, true, false, 1); } public function testPatchFolder() { $feed = $this->getMockBuilder(Feed::class) ->getMock(); $feed->expects($this->once()) ->method('setFolderId') ->with(5); $feed->expects($this->once()) ->method('setPinned') ->with(true); $feed->expects($this->once()) ->method('setFullTextEnabled') ->with(false); $feed->expects($this->once()) ->method('setUpdateMode') ->with(1); $feed->expects($this->never()) ->method('setOrdering') ->with(true); $feed->expects($this->never()) ->method('setTitle') ->with(true); $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, 4) ->will($this->returnValue($feed)); $this->feedService->expects($this->once()) ->method('update') ->with($this->uid, $feed); $this->class->patch(4, true, false, 1, null, 5); } public function testPatchDoesNotExist() { $msg = 'hehe'; $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, 4) ->will($this->throwException(new ServiceNotFoundException($msg))); $response = $this->class->patch(4, 2); $params = json_decode($response->render(), true); $this->assertEquals($msg, $params['message']); $this->assertEquals($response->getStatus(), Http::STATUS_NOT_FOUND); } public function testPatchDoesNotExistOnUpdate() { $feed = $this->getMockBuilder(Feed::class) ->getMock(); $feed->expects($this->once()) ->method('setFolderId') ->with(1); $feed->expects($this->once()) ->method('setPinned') ->with(true); $feed->expects($this->once()) ->method('setFullTextEnabled') ->with(false); $feed->expects($this->once()) ->method('setUpdateMode') ->with(1); $feed->expects($this->once()) ->method('setOrdering') ->with(1); $feed->expects($this->once()) ->method('setTitle') ->with('title'); $this->feedService->expects($this->once()) ->method('find') ->with($this->uid, 4) ->will($this->returnValue($feed)); $this->feedService->expects($this->once()) ->method('update') ->with($this->uid, $feed) ->will($this->throwException(new ServiceNotFoundException('test'))); $response = $this->class->patch(4, 2, false, 1, 1, 1, 'title'); $params = json_decode($response->render(), true); $this->assertEquals('test', $params['message']); $this->assertEquals($response->getStatus(), Http::STATUS_NOT_FOUND); } }