Files
nextcloud-forum/tests/unit/Controller/ReadMarkerControllerTest.php

242 lines
7.7 KiB
PHP

<?php
declare(strict_types=1);
namespace OCA\Forum\Tests\Controller;
use OCA\Forum\AppInfo\Application;
use OCA\Forum\Controller\ReadMarkerController;
use OCA\Forum\Db\ReadMarker;
use OCA\Forum\Db\ReadMarkerMapper;
use OCA\Forum\Service\NotificationService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
class ReadMarkerControllerTest extends TestCase {
private ReadMarkerController $controller;
/** @var ReadMarkerMapper&MockObject */
private ReadMarkerMapper $readMarkerMapper;
/** @var NotificationService&MockObject */
private NotificationService $notificationService;
/** @var IUserSession&MockObject */
private IUserSession $userSession;
/** @var LoggerInterface&MockObject */
private LoggerInterface $logger;
/** @var IRequest&MockObject */
private IRequest $request;
protected function setUp(): void {
$this->request = $this->createMock(IRequest::class);
$this->readMarkerMapper = $this->createMock(ReadMarkerMapper::class);
$this->notificationService = $this->createMock(NotificationService::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->controller = new ReadMarkerController(
Application::APP_ID,
$this->request,
$this->readMarkerMapper,
$this->notificationService,
$this->userSession,
$this->logger
);
}
public function testIndexReturnsReadMarkersForCurrentUser(): void {
$userId = 'user1';
$marker1 = $this->createReadMarker(1, $userId, 1, 10);
$marker2 = $this->createReadMarker(2, $userId, 2, 20);
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn($userId);
$this->userSession->method('getUser')->willReturn($user);
$this->readMarkerMapper->expects($this->once())
->method('findByUserId')
->with($userId)
->willReturn([$marker1, $marker2]);
$response = $this->controller->index();
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
$data = $response->getData();
$this->assertIsArray($data);
$this->assertCount(2, $data);
}
public function testIndexReturnsUnauthorizedWhenUserNotAuthenticated(): void {
$this->userSession->method('getUser')->willReturn(null);
$response = $this->controller->index();
$this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
$this->assertEquals(['error' => 'User not authenticated'], $response->getData());
}
public function testShowReturnsReadMarkerForThread(): void {
$userId = 'user1';
$threadId = 1;
$marker = $this->createReadMarker(1, $userId, $threadId, 10);
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn($userId);
$this->userSession->method('getUser')->willReturn($user);
$this->readMarkerMapper->expects($this->once())
->method('findByUserAndThread')
->with($userId, $threadId)
->willReturn($marker);
$response = $this->controller->show($threadId);
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
$data = $response->getData();
$this->assertEquals($threadId, $data['entityId']);
$this->assertEquals(10, $data['lastReadPostId']);
}
public function testShowReturnsUnauthorizedWhenUserNotAuthenticated(): void {
$threadId = 1;
$this->userSession->method('getUser')->willReturn(null);
$response = $this->controller->show($threadId);
$this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
$this->assertEquals(['error' => 'User not authenticated'], $response->getData());
}
public function testShowReturnsNotFoundWhenMarkerDoesNotExist(): void {
$userId = 'user1';
$threadId = 999;
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn($userId);
$this->userSession->method('getUser')->willReturn($user);
$this->readMarkerMapper->expects($this->once())
->method('findByUserAndThread')
->with($userId, $threadId)
->willThrowException(new DoesNotExistException('Read marker not found'));
$response = $this->controller->show($threadId);
$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
$this->assertEquals(['error' => 'Read marker not found'], $response->getData());
}
public function testCreateInsertsNewMarkerWhenNotExists(): void {
$userId = 'user1';
$threadId = 1;
$lastReadPostId = 10;
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn($userId);
$this->userSession->method('getUser')->willReturn($user);
$createdMarker = $this->createReadMarker(1, $userId, $threadId, $lastReadPostId);
// Mock createOrUpdate method
$this->readMarkerMapper->expects($this->once())
->method('createOrUpdate')
->with($userId, $threadId, $lastReadPostId)
->willReturn($createdMarker);
$response = $this->controller->create($threadId, $lastReadPostId);
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
$data = $response->getData();
$this->assertEquals($threadId, $data['entityId']);
$this->assertEquals($lastReadPostId, $data['lastReadPostId']);
}
public function testCreateUpdatesExistingMarker(): void {
$userId = 'user1';
$threadId = 1;
$oldPostId = 5;
$newPostId = 15;
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn($userId);
$this->userSession->method('getUser')->willReturn($user);
$existingMarker = $this->createReadMarker(1, $userId, $threadId, $oldPostId);
// Update the marker with new post ID
$existingMarker->setLastReadPostId($newPostId);
// Mock createOrUpdate method
$this->readMarkerMapper->expects($this->once())
->method('createOrUpdate')
->with($userId, $threadId, $newPostId)
->willReturn($existingMarker);
$response = $this->controller->create($threadId, $newPostId);
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
$data = $response->getData();
$this->assertEquals($threadId, $data['entityId']);
}
public function testCreateReturnsUnauthorizedWhenUserNotAuthenticated(): void {
$threadId = 1;
$lastReadPostId = 10;
$this->userSession->method('getUser')->willReturn(null);
$response = $this->controller->create($threadId, $lastReadPostId);
$this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
$this->assertEquals(['error' => 'User not authenticated'], $response->getData());
}
public function testDestroyDeletesMarkerSuccessfully(): void {
$markerId = 1;
$marker = $this->createReadMarker($markerId, 'user1', 1, 10);
$this->readMarkerMapper->expects($this->once())
->method('find')
->with($markerId)
->willReturn($marker);
$this->readMarkerMapper->expects($this->once())
->method('delete')
->with($marker);
$response = $this->controller->destroy($markerId);
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
$this->assertEquals(['success' => true], $response->getData());
}
public function testDestroyReturnsNotFoundWhenMarkerDoesNotExist(): void {
$markerId = 999;
$this->readMarkerMapper->expects($this->once())
->method('find')
->with($markerId)
->willThrowException(new DoesNotExistException('Read marker not found'));
$response = $this->controller->destroy($markerId);
$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
$this->assertEquals(['error' => 'Read marker not found'], $response->getData());
}
private function createReadMarker(int $id, string $userId, int $threadId, int $lastReadPostId): ReadMarker {
$marker = new ReadMarker();
$marker->setId($id);
$marker->setUserId($userId);
$marker->setEntityId($threadId);
$marker->setMarkerType(ReadMarker::TYPE_THREAD);
$marker->setLastReadPostId($lastReadPostId);
$marker->setReadAt(time());
return $marker;
}
}