UserStatusControllerTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\UserStatus\Tests\Controller;
  8. use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
  9. use OCA\UserStatus\Controller\UserStatusController;
  10. use OCA\UserStatus\Db\UserStatus;
  11. use OCA\UserStatus\Exception\InvalidClearAtException;
  12. use OCA\UserStatus\Exception\InvalidMessageIdException;
  13. use OCA\UserStatus\Exception\InvalidStatusIconException;
  14. use OCA\UserStatus\Exception\InvalidStatusTypeException;
  15. use OCA\UserStatus\Exception\StatusMessageTooLongException;
  16. use OCA\UserStatus\Service\StatusService;
  17. use OCP\AppFramework\Db\DoesNotExistException;
  18. use OCP\AppFramework\OCS\OCSBadRequestException;
  19. use OCP\AppFramework\OCS\OCSNotFoundException;
  20. use OCP\IRequest;
  21. use Psr\Log\LoggerInterface;
  22. use Test\TestCase;
  23. use Throwable;
  24. class UserStatusControllerTest extends TestCase {
  25. /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
  26. private $logger;
  27. /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */
  28. private $statusService;
  29. /** @var CalendarStatusService|\PHPUnit\Framework\MockObject\MockObject $calendarStatusService */
  30. private $calendarStatusService;
  31. /** @var UserStatusController */
  32. private $controller;
  33. protected function setUp(): void {
  34. parent::setUp();
  35. $request = $this->createMock(IRequest::class);
  36. $userId = 'john.doe';
  37. $this->logger = $this->createMock(LoggerInterface::class);
  38. $this->statusService = $this->createMock(StatusService::class);
  39. $this->calendarStatusService = $this->createMock(CalendarStatusService::class);
  40. $this->controller = new UserStatusController(
  41. 'user_status',
  42. $request,
  43. $userId,
  44. $this->logger,
  45. $this->statusService,
  46. $this->calendarStatusService,
  47. );
  48. }
  49. public function testGetStatus(): void {
  50. $userStatus = $this->getUserStatus();
  51. $this->statusService->expects($this->once())
  52. ->method('findByUserId')
  53. ->with('john.doe')
  54. ->willReturn($userStatus);
  55. $response = $this->controller->getStatus();
  56. $this->assertEquals([
  57. 'userId' => 'john.doe',
  58. 'status' => 'invisible',
  59. 'icon' => '🏝',
  60. 'message' => 'On vacation',
  61. 'clearAt' => 60000,
  62. 'statusIsUserDefined' => true,
  63. 'messageIsPredefined' => false,
  64. 'messageId' => null,
  65. ], $response->getData());
  66. }
  67. public function testGetStatusDoesNotExist(): void {
  68. $this->calendarStatusService->expects(self::once())
  69. ->method('processCalendarStatus')
  70. ->with('john.doe');
  71. $this->statusService->expects($this->once())
  72. ->method('findByUserId')
  73. ->with('john.doe')
  74. ->willThrowException(new DoesNotExistException(''));
  75. $this->expectException(OCSNotFoundException::class);
  76. $this->expectExceptionMessage('No status for the current user');
  77. $this->controller->getStatus();
  78. }
  79. /**
  80. * @param string $statusType
  81. * @param string|null $statusIcon
  82. * @param string|null $message
  83. * @param int|null $clearAt
  84. * @param bool $expectSuccess
  85. * @param bool $expectException
  86. * @param Throwable|null $exception
  87. * @param bool $expectLogger
  88. * @param string|null $expectedLogMessage
  89. *
  90. * @dataProvider setStatusDataProvider
  91. */
  92. public function testSetStatus(string $statusType,
  93. ?string $statusIcon,
  94. ?string $message,
  95. ?int $clearAt,
  96. bool $expectSuccess,
  97. bool $expectException,
  98. ?Throwable $exception,
  99. bool $expectLogger,
  100. ?string $expectedLogMessage): void {
  101. $userStatus = $this->getUserStatus();
  102. if ($expectException) {
  103. $this->statusService->expects($this->once())
  104. ->method('setStatus')
  105. ->with('john.doe', $statusType, null, true)
  106. ->willThrowException($exception);
  107. } else {
  108. $this->statusService->expects($this->once())
  109. ->method('setStatus')
  110. ->with('john.doe', $statusType, null, true)
  111. ->willReturn($userStatus);
  112. }
  113. if ($expectLogger) {
  114. $this->logger->expects($this->once())
  115. ->method('debug')
  116. ->with($expectedLogMessage);
  117. }
  118. if ($expectException) {
  119. $this->expectException(OCSBadRequestException::class);
  120. $this->expectExceptionMessage('Original exception message');
  121. }
  122. $response = $this->controller->setStatus($statusType);
  123. if ($expectSuccess) {
  124. $this->assertEquals([
  125. 'userId' => 'john.doe',
  126. 'status' => 'invisible',
  127. 'icon' => '🏝',
  128. 'message' => 'On vacation',
  129. 'clearAt' => 60000,
  130. 'statusIsUserDefined' => true,
  131. 'messageIsPredefined' => false,
  132. 'messageId' => null,
  133. ], $response->getData());
  134. }
  135. }
  136. public function setStatusDataProvider(): array {
  137. return [
  138. ['busy', '👨🏽‍💻', 'Busy developing the status feature', 500, true, false, null, false, null],
  139. ['busy', '👨🏽‍💻', 'Busy developing the status feature', 500, false, true, new InvalidStatusTypeException('Original exception message'), true,
  140. 'New user-status for "john.doe" was rejected due to an invalid status type "busy"'],
  141. ];
  142. }
  143. /**
  144. * @param string $messageId
  145. * @param int|null $clearAt
  146. * @param bool $expectSuccess
  147. * @param bool $expectException
  148. * @param Throwable|null $exception
  149. * @param bool $expectLogger
  150. * @param string|null $expectedLogMessage
  151. *
  152. * @dataProvider setPredefinedMessageDataProvider
  153. */
  154. public function testSetPredefinedMessage(string $messageId,
  155. ?int $clearAt,
  156. bool $expectSuccess,
  157. bool $expectException,
  158. ?Throwable $exception,
  159. bool $expectLogger,
  160. ?string $expectedLogMessage): void {
  161. $userStatus = $this->getUserStatus();
  162. if ($expectException) {
  163. $this->statusService->expects($this->once())
  164. ->method('setPredefinedMessage')
  165. ->with('john.doe', $messageId, $clearAt)
  166. ->willThrowException($exception);
  167. } else {
  168. $this->statusService->expects($this->once())
  169. ->method('setPredefinedMessage')
  170. ->with('john.doe', $messageId, $clearAt)
  171. ->willReturn($userStatus);
  172. }
  173. if ($expectLogger) {
  174. $this->logger->expects($this->once())
  175. ->method('debug')
  176. ->with($expectedLogMessage);
  177. }
  178. if ($expectException) {
  179. $this->expectException(OCSBadRequestException::class);
  180. $this->expectExceptionMessage('Original exception message');
  181. }
  182. $response = $this->controller->setPredefinedMessage($messageId, $clearAt);
  183. if ($expectSuccess) {
  184. $this->assertEquals([
  185. 'userId' => 'john.doe',
  186. 'status' => 'invisible',
  187. 'icon' => '🏝',
  188. 'message' => 'On vacation',
  189. 'clearAt' => 60000,
  190. 'statusIsUserDefined' => true,
  191. 'messageIsPredefined' => false,
  192. 'messageId' => null,
  193. ], $response->getData());
  194. }
  195. }
  196. public function setPredefinedMessageDataProvider(): array {
  197. return [
  198. ['messageId-42', 500, true, false, null, false, null],
  199. ['messageId-42', 500, false, true, new InvalidClearAtException('Original exception message'), true,
  200. 'New user-status for "john.doe" was rejected due to an invalid clearAt value "500"'],
  201. ['messageId-42', 500, false, true, new InvalidMessageIdException('Original exception message'), true,
  202. 'New user-status for "john.doe" was rejected due to an invalid message-id "messageId-42"'],
  203. ];
  204. }
  205. /**
  206. * @param string|null $statusIcon
  207. * @param string $message
  208. * @param int|null $clearAt
  209. * @param bool $expectSuccess
  210. * @param bool $expectException
  211. * @param Throwable|null $exception
  212. * @param bool $expectLogger
  213. * @param string|null $expectedLogMessage
  214. * @param bool $expectSuccessAsReset
  215. *
  216. * @dataProvider setCustomMessageDataProvider
  217. */
  218. public function testSetCustomMessage(?string $statusIcon,
  219. string $message,
  220. ?int $clearAt,
  221. bool $expectSuccess,
  222. bool $expectException,
  223. ?Throwable $exception,
  224. bool $expectLogger,
  225. ?string $expectedLogMessage,
  226. bool $expectSuccessAsReset = false): void {
  227. $userStatus = $this->getUserStatus();
  228. if ($expectException) {
  229. $this->statusService->expects($this->once())
  230. ->method('setCustomMessage')
  231. ->with('john.doe', $statusIcon, $message, $clearAt)
  232. ->willThrowException($exception);
  233. } else {
  234. if ($expectSuccessAsReset) {
  235. $this->statusService->expects($this->never())
  236. ->method('setCustomMessage');
  237. $this->statusService->expects($this->once())
  238. ->method('clearMessage')
  239. ->with('john.doe');
  240. $this->statusService->expects($this->once())
  241. ->method('findByUserId')
  242. ->with('john.doe')
  243. ->willReturn($userStatus);
  244. } else {
  245. $this->statusService->expects($this->once())
  246. ->method('setCustomMessage')
  247. ->with('john.doe', $statusIcon, $message, $clearAt)
  248. ->willReturn($userStatus);
  249. $this->statusService->expects($this->never())
  250. ->method('clearMessage');
  251. }
  252. }
  253. if ($expectLogger) {
  254. $this->logger->expects($this->once())
  255. ->method('debug')
  256. ->with($expectedLogMessage);
  257. }
  258. if ($expectException) {
  259. $this->expectException(OCSBadRequestException::class);
  260. $this->expectExceptionMessage('Original exception message');
  261. }
  262. $response = $this->controller->setCustomMessage($statusIcon, $message, $clearAt);
  263. if ($expectSuccess) {
  264. $this->assertEquals([
  265. 'userId' => 'john.doe',
  266. 'status' => 'invisible',
  267. 'icon' => '🏝',
  268. 'message' => 'On vacation',
  269. 'clearAt' => 60000,
  270. 'statusIsUserDefined' => true,
  271. 'messageIsPredefined' => false,
  272. 'messageId' => null,
  273. ], $response->getData());
  274. }
  275. }
  276. public function setCustomMessageDataProvider(): array {
  277. return [
  278. ['👨🏽‍💻', 'Busy developing the status feature', 500, true, false, null, false, null],
  279. ['👨🏽‍💻', '', 500, true, false, null, false, null, false],
  280. ['👨🏽‍💻', '', 0, true, false, null, false, null, false],
  281. ['👨🏽‍💻', 'Busy developing the status feature', 500, false, true, new InvalidClearAtException('Original exception message'), true,
  282. 'New user-status for "john.doe" was rejected due to an invalid clearAt value "500"'],
  283. ['👨🏽‍💻', 'Busy developing the status feature', 500, false, true, new InvalidStatusIconException('Original exception message'), true,
  284. 'New user-status for "john.doe" was rejected due to an invalid icon value "👨🏽‍💻"'],
  285. ['👨🏽‍💻', 'Busy developing the status feature', 500, false, true, new StatusMessageTooLongException('Original exception message'), true,
  286. 'New user-status for "john.doe" was rejected due to a too long status message.'],
  287. ];
  288. }
  289. public function testClearMessage(): void {
  290. $this->statusService->expects($this->once())
  291. ->method('clearMessage')
  292. ->with('john.doe');
  293. $response = $this->controller->clearMessage();
  294. $this->assertEquals([], $response->getData());
  295. }
  296. private function getUserStatus(): UserStatus {
  297. $userStatus = new UserStatus();
  298. $userStatus->setId(1337);
  299. $userStatus->setUserId('john.doe');
  300. $userStatus->setStatus('invisible');
  301. $userStatus->setStatusTimestamp(5000);
  302. $userStatus->setIsUserDefined(true);
  303. $userStatus->setCustomIcon('🏝');
  304. $userStatus->setCustomMessage('On vacation');
  305. $userStatus->setClearAt(60000);
  306. return $userStatus;
  307. }
  308. }