From 110b17afcd0ae9d205027c102968fb7ebd318a60 Mon Sep 17 00:00:00 2001 From: Anna Larch Date: Mon, 7 Nov 2022 20:53:47 +0100 Subject: Tests Signed-off-by: Anna Larch --- lib/BackgroundJob/IMipMessageJob.php | 4 +- .../Service/DraftServiceIntegrationTest.php | 272 ++++++++++ tests/Unit/Controller/DraftsControllerTest.php | 597 +++++++++++++++++++++ tests/Unit/Service/DraftsServiceTest.php | 270 +++++++--- tests/Unit/Service/MailTransmissionTest.php | 83 +++ 5 files changed, 1160 insertions(+), 66 deletions(-) create mode 100644 tests/Integration/Service/DraftServiceIntegrationTest.php create mode 100644 tests/Unit/Controller/DraftsControllerTest.php diff --git a/lib/BackgroundJob/IMipMessageJob.php b/lib/BackgroundJob/IMipMessageJob.php index 371645c91..c2038ac92 100644 --- a/lib/BackgroundJob/IMipMessageJob.php +++ b/lib/BackgroundJob/IMipMessageJob.php @@ -33,12 +33,12 @@ class IMipMessageJob extends TimedJob { private IMipService $iMipService; public function __construct(ITimeFactory $time, - IMipService $iMipService) { + IMipService $draftsService) { parent::__construct($time); // Run once per hour $this->setInterval(60 * 60); - $this->iMipService = $iMipService; + $this->iMipService = $draftsService; } protected function run($argument): void { diff --git a/tests/Integration/Service/DraftServiceIntegrationTest.php b/tests/Integration/Service/DraftServiceIntegrationTest.php new file mode 100644 index 000000000..b31ec7cab --- /dev/null +++ b/tests/Integration/Service/DraftServiceIntegrationTest.php @@ -0,0 +1,272 @@ + + * + * Mail + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Mail\Tests\Integration\Service; + +use ChristophWurst\Nextcloud\Testing\TestUser; +use OC; +use OCA\Mail\Account; +use OCA\Mail\Contracts\IAttachmentService; +use OCA\Mail\Contracts\IMailManager; +use OCA\Mail\Contracts\IMailTransmission; +use OCA\Mail\Db\LocalAttachmentMapper; +use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\LocalMessageMapper; +use OCA\Mail\Db\MailAccount; +use OCA\Mail\IMAP\IMAPClientFactory; +use OCA\Mail\Service\AccountService; +use OCA\Mail\Service\Attachment\AttachmentService; +use OCA\Mail\Service\Attachment\AttachmentStorage; +use OCA\Mail\Service\DraftsService; +use OCA\Mail\Service\OutboxService; +use OCA\Mail\Tests\Integration\Framework\ImapTest; +use OCA\Mail\Tests\Integration\Framework\ImapTestAccount; +use OCA\Mail\Tests\Integration\TestCase; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Folder; +use OCP\IServerContainer; +use OCP\IUser; +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; + +class DraftServiceIntegrationTest extends TestCase { + use ImapTest, + ImapTestAccount, + TestUser; + + /** @var MailAccount */ + private $account; + + /** @var IUser */ + private $user; + + /** @var IAttachmentService */ + private $attachmentService; + + /** @var IMailTransmission */ + private $transmission; + + /** @var OutboxService */ + private $service; + + /** @var IEventDispatcher */ + private $eventDispatcher; + + /** @var IMAPClientFactory */ + private $clientFactory; + + /** @var LocalMessageMapper */ + private $mapper; + + /** @var Folder */ + private $userFolder; + + /** @var AccountService|\PHPUnit\Framework\MockObject\MockObject */ + private $accountService; + + /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ + private $timeFactory; + + protected function setUp(): void { + parent::setUp(); + + $this->resetImapAccount(); + $this->disconnectImapAccount(); + + $this->user = $this->createTestUser(); + $this->account = $this->createTestAccount($this->user->getUID()); + $c = OC::$server->get(ContainerInterface::class); + $userContainer = $c->get(IServerContainer::class); + $this->userFolder = $userContainer->getUserFolder($this->account->getUserId()); + $mailManager = OC::$server->get(IMailManager::class); + $this->attachmentService = new AttachmentService( + $this->userFolder, + OC::$server->get(LocalAttachmentMapper::class), + OC::$server->get(AttachmentStorage::class), + $mailManager, + OC::$server->get(\OCA\Mail\IMAP\MessageMapper::class), + new NullLogger() + ); + $this->client = $this->getClient($this->account); + $this->mapper = OC::$server->get(LocalMessageMapper::class); + $this->transmission = OC::$server->get(IMailTransmission::class); + $this->eventDispatcher = OC::$server->get(IEventDispatcher::class); + $this->clientFactory = OC::$server->get(IMAPClientFactory::class); + $this->accountService = $this->createMock(AccountService::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + + $this->db = \OC::$server->getDatabaseConnection(); + $qb = $this->db->getQueryBuilder(); + $delete = $qb->delete($this->mapper->getTableName()); + $delete->execute(); + + $this->service = new DraftsService( + $this->transmission, + $this->mapper, + $this->attachmentService, + $this->eventDispatcher, + $this->clientFactory, + $mailManager, + $this->createMock(LoggerInterface::class), + $this->accountService, + $this->timeFactory + ); + } + + public function testSaveAndGetMessage(): void { + $message = new LocalMessage(); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setAccountId($this->account->getId()); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setHtml(true); + + $to = [[ + 'label' => 'Penny', + 'email' => 'library@stardewvalley.com' + ]]; + + $saved = $this->service->saveMessage(new Account($this->account), $message, $to, [], []); + $this->assertNotEmpty($message->getRecipients()); + $this->assertEmpty($message->getAttachments()); + + $retrieved = $this->service->getMessage($message->getId(), $this->user->getUID()); + $this->assertNotEmpty($message->getRecipients()); + $this->assertEmpty($message->getAttachments()); + + self::assertCount(1, $retrieved->getRecipients()); + } + + public function testSaveAndDeleteMessage(): void { + $message = new LocalMessage(); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setAccountId($this->account->getId()); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setHtml(true); + + $to = [[ + 'label' => 'Penny', + 'email' => 'library@stardewvalley.com' + ]]; + + $saved = $this->service->saveMessage(new Account($this->account), $message, $to, [], []); + $this->assertNotEmpty($message->getRecipients()); + $this->assertEmpty($message->getAttachments()); + + $this->service->deleteMessage($this->user->getUID(), $saved); + + $this->expectException(DoesNotExistException::class); + $this->service->getMessage($message->getId(), $this->user->getUID()); + } + + public function testSaveAndUpdateMessage(): void { + $message = new LocalMessage(); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setAccountId($this->account->getId()); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setHtml(true); + + $to = [[ + 'label' => 'Penny', + 'email' => 'library@stardewvalley.com' + ]]; + + $saved = $this->service->saveMessage(new Account($this->account), $message, $to, [], []); + $this->assertNotEmpty($message->getRecipients()); + $this->assertCount(1, $saved->getRecipients()); + $this->assertEmpty($message->getAttachments()); + + $saved->setSubject('Your Trailer will be put up for sale'); + $cc = [[ + 'label' => 'Pam', + 'email' => 'buyMeABeer@stardewvalley.com' + ]]; + $updated = $this->service->updateMessage(new Account($this->account), $saved, $to, $cc, []); + + $this->assertNotEmpty($updated->getRecipients()); + $this->assertEquals('Your Trailer will be put up for sale', $updated->getSubject()); + $this->assertCount(2, $updated->getRecipients()); + } + public function testSaveAndConvertToOutboxMessage(): void { + $message = new LocalMessage(); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setAccountId($this->account->getId()); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setHtml(true); + + $to = [[ + 'label' => 'Penny', + 'email' => 'library@stardewvalley.com' + ]]; + + $saved = $this->service->saveMessage(new Account($this->account), $message, $to, [], []); + $this->assertNotEmpty($message->getRecipients()); + $this->assertCount(1, $saved->getRecipients()); + $this->assertEmpty($message->getAttachments()); + + $saved->setSubject('Your Trailer will be put up for sale'); + $cc = [[ + 'label' => 'Pam', + 'email' => 'buyMeABeer@stardewvalley.com' + ]]; + $saved->setType(LocalMessage::TYPE_OUTGOING); + $saved->setSendAt(123456); + $updated = $this->service->updateMessage(new Account($this->account), $saved, $to, $cc, []); + + $this->assertNotEmpty($updated->getRecipients()); + $this->assertEquals('Your Trailer will be put up for sale', $updated->getSubject()); + $this->assertCount(2, $updated->getRecipients()); + $this->assertEquals(LocalMessage::TYPE_OUTGOING, $saved->getType()); + } + + + public function testSaveAndSendMessage(): void { + $message = new LocalMessage(); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setAccountId($this->account->getId()); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setHtml(true); + + $to = [[ + 'label' => 'Penny', + 'email' => 'library@stardewvalley.com' + ]]; + + $saved = $this->service->saveMessage(new Account($this->account), $message, $to, [], []); + $this->assertNotEmpty($message->getRecipients()); + $this->assertCount(1, $saved->getRecipients()); + $this->assertEmpty($message->getAttachments()); + + $this->service->sendMessage($saved, new Account($this->account)); + + $this->expectException(DoesNotExistException::class); + $this->service->getMessage($message->getId(), $this->user->getUID()); + } +} diff --git a/tests/Unit/Controller/DraftsControllerTest.php b/tests/Unit/Controller/DraftsControllerTest.php new file mode 100644 index 000000000..503431106 --- /dev/null +++ b/tests/Unit/Controller/DraftsControllerTest.php @@ -0,0 +1,597 @@ + + * + * @copyright 2022 Anna Larch + * + * Mail + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Mail\Tests\Unit\Controller; + +use ChristophWurst\Nextcloud\Testing\TestCase; +use OC\AppFramework\Http; +use OCA\Mail\Account; +use OCA\Mail\Controller\DraftsController; +use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; +use OCA\Mail\Exception\ClientException; +use OCA\Mail\Exception\ServiceException; +use OCA\Mail\Http\JsonResponse; +use OCA\Mail\Service\AccountService; +use OCA\Mail\Service\DraftsService; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\DB\Exception; +use OCP\IRequest; + +class DraftsControllerTest extends TestCase { + protected function setUp(): void { + parent::setUp(); + + $this->appName = 'mail'; + $this->service = $this->createMock(DraftsService::class); + $this->userId = 'john'; + $this->request = $this->createMock(IRequest::class); + $this->accountService = $this->createMock(AccountService::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + + $this->controller = new DraftsController( + $this->appName, + $this->userId, + $this->request, + $this->service, + $this->accountService, + $this->timeFactory + ); + } + + public function testMove(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + $account = new Account(new MailAccount()); + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willReturn($message); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willReturn($account); + $this->service->expects(self::once()) + ->method('sendMessage') + ->with($message, $account); + + $expected = JsonResponse::success('Message moved to IMAP', Http::STATUS_ACCEPTED); + $actual = $this->controller->move($message->getId()); + + $this->assertEquals($expected, $actual); + } + + public function testMoveNoMessage(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willThrowException(new DoesNotExistException('')); + $this->accountService->expects(self::never()) + ->method('find'); + $this->service->expects(self::never()) + ->method('sendMessage'); + + $this->expectException(DoesNotExistException::class); + $expected = JsonResponse::fail('', Http::STATUS_NOT_FOUND); + $actual = $this->controller->move($message->getId()); + + $this->assertEquals($expected, $actual); + } + + public function testSendClientException(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willReturn($message); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willThrowException(new ClientException()); + $this->service->expects(self::never()) + ->method('sendMessage'); + + $this->expectException(ClientException::class); + $this->controller->move($message->getId()); + } + + public function testSendServiceException(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + $account = new Account(new MailAccount()); + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willReturn($message); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willReturn($account); + $this->service->expects(self::once()) + ->method('sendMessage') + ->willThrowException(new ServiceException()); + + $this->expectException(ServiceException::class); + $this->controller->move($message->getId()); + } + + public function testDestroy(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + $account = new Account(new MailAccount()); + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willReturn($message); + $this->accountService->expects(self::once()) + ->method('find') + ->willReturn($account); + $this->service->expects(self::once()) + ->method('deleteMessage') + ->with($this->userId, $message); + + $expected = JsonResponse::success('Message deleted', Http::STATUS_ACCEPTED); + $actual = $this->controller->destroy($message->getId()); + + $this->assertEquals($expected, $actual); + } + + public function testDestroyNoMessage(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willThrowException(new DoesNotExistException('')); + $this->accountService->expects(self::never()) + ->method('find'); + $this->service->expects(self::never()) + ->method('deleteMessage'); + + $this->expectException(DoesNotExistException::class); + $expected = JsonResponse::fail('', Http::STATUS_NOT_FOUND); + $actual = $this->controller->destroy($message->getId()); + + $this->assertEquals($expected, $actual); + } + + public function testCreate(): void { + $message = new LocalMessage(); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setSendAt(null); + $message->setUpdatedAt(123456); + $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; + $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; + + $account = new Account(new MailAccount()); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willReturn($account); + $this->timeFactory->expects(self::once()) + ->method('getTime') + ->willReturn(123456); + $this->service->expects(self::once()) + ->method('saveMessage') + ->with($account, $message, $to, $cc, [], []); + + $expected = JsonResponse::success($message, Http::STATUS_CREATED); + $actual = $this->controller->create( + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + $to, + $cc, + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId() + ); + + $this->assertEquals($expected, $actual); + } + + public function testCreateFromDraft(): void { + $message = new LocalMessage(); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setSendAt(null); + $message->setUpdatedAt(123456); + $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; + $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; + + $account = new Account(new MailAccount()); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willReturn($account); + $this->service->expects(self::once()) + ->method('handleDraft'); + $this->timeFactory->expects(self::once()) + ->method('getTime') + ->willReturn(123456); + $this->service->expects(self::once()) + ->method('saveMessage') + ->with($account, $message, $to, $cc, [], []); + + $expected = JsonResponse::success($message, Http::STATUS_CREATED); + $actual = $this->controller->create( + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + $to, + $cc, + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId(), + null, + 1 + ); + + $this->assertEquals($expected, $actual); + } + + public function testCreateWithEmptyRecipients(): void { + $message = new LocalMessage(); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setSendAt(null); + $message->setUpdatedAt(123456); + + $account = new Account(new MailAccount()); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willReturn($account); + $this->timeFactory->expects(self::once()) + ->method('getTime') + ->willReturn(123456); + $this->service->expects(self::once()) + ->method('saveMessage') + ->with($account, $message, [], [], [], []); + + $expected = JsonResponse::success($message, Http::STATUS_CREATED); + $actual = $this->controller->create( + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + [], + [], + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId() + ); + + $this->assertEquals($expected, $actual); + } + + public function testCreateAccountNotFound(): void { + $message = new LocalMessage(); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_OUTGOING); + $message->setSendAt(null); + $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; + $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; + + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willThrowException(new ClientException()); + $this->service->expects(self::never()) + ->method('saveMessage'); + + $this->expectException(ClientException::class); + $actual = $this->controller->create( + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + $to, + $cc, + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId() + ); + } + + public function testCreateDbException(): void { + $message = new LocalMessage(); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_OUTGOING); + $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; + $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; + + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()); + $this->service->expects(self::once()) + ->method('saveMessage') + ->willThrowException(new Exception()); + + $this->expectException(Exception::class); + $this->controller->create( + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + $to, + $cc, + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId() + ); + } + + public function testUpdate(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setFailed(false); + $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; + $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willReturn($message); + $account = new Account(new MailAccount()); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willReturn($account); + $this->service->expects(self::once()) + ->method('updateMessage') + ->with($account, $message, $to, $cc, [], []) + ->willReturn($message); + + $expected = JsonResponse::success($message, Http::STATUS_ACCEPTED); + $actual = $this->controller->update( + $message->getId(), + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + false, + $to, + $cc, + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId() + ); + + $this->assertEquals($expected, $actual); + } + + public function testUpdateMoveToOutbox(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_OUTGOING); + $message->setFailed(false); + $message->setSendAt(123456); + $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; + $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willReturn($message); + $account = new Account(new MailAccount()); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willReturn($account); + $this->service->expects(self::once()) + ->method('updateMessage') + ->with($account, $message, $to, $cc, [], []) + ->willReturn($message); + + $expected = JsonResponse::success($message, Http::STATUS_ACCEPTED); + $actual = $this->controller->update( + $message->getId(), + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + false, + $to, + $cc, + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId(), + $message->getSendAt() + ); + + $this->assertEquals($expected, $actual); + } + + + public function testUpdateMessageNotFound(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setFailed(false); + $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; + $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willThrowException(new DoesNotExistException('')); + $this->service->expects(self::never()) + ->method('updateMessage'); + + + $this->expectException(DoesNotExistException::class); + $expected = JsonResponse::fail('', Http::STATUS_NOT_FOUND); + $actual = $this->controller->update( + $message->getId(), + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + false, + $to, + $cc, + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId() + ); + + $this->assertEquals($expected, $actual); + } + + public function testUpdateDbException(): void { + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + $message->setAliasId(2); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setEditorBody('

message

'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setFailed(false); + $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; + $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; + + $this->service->expects(self::once()) + ->method('getMessage') + ->with($message->getId(), $this->userId) + ->willReturn($message); + $account = new Account(new MailAccount()); + $this->accountService->expects(self::once()) + ->method('find') + ->with($this->userId, $message->getAccountId()) + ->willReturn($account); + $this->service->expects(self::once()) + ->method('updateMessage') + ->with($account, $message, $to, $cc, [], []) + ->willThrowException(new Exception()); + + $this->expectException(Exception::class); + $this->controller->update( + $message->getId(), + $message->getAccountId(), + $message->getSubject(), + $message->getBody(), + '

message

', + $message->isHtml(), + false, + $to, + $cc, + [], + [], + $message->getAliasId(), + $message->getInReplyToMessageId() + ); + } +} diff --git a/tests/Unit/Service/DraftsServiceTest.php b/tests/Unit/Service/DraftsServiceTest.php index f5262b157..af144f950 100644 --- a/tests/Unit/Service/DraftsServiceTest.php +++ b/tests/Unit/Service/DraftsServiceTest.php @@ -33,11 +33,16 @@ use OCA\Mail\Contracts\IMailManager; use OCA\Mail\Db\LocalAttachment; use OCA\Mail\Db\LocalMessage; use OCA\Mail\Db\LocalMessageMapper; +use OCA\Mail\Db\MailAccount; +use OCA\Mail\Db\Message; use OCA\Mail\Db\Recipient; +use OCA\Mail\Events\DraftMessageCreatedEvent; use OCA\Mail\Exception\ClientException; +use OCA\Mail\Exception\NotImplemented; use OCA\Mail\IMAP\IMAPClientFactory; use OCA\Mail\Service\AccountService; use OCA\Mail\Service\Attachment\AttachmentService; +use OCA\Mail\Service\DraftsService; use OCA\Mail\Service\MailTransmission; use OCA\Mail\Service\OutboxService; use OCP\AppFramework\Db\DoesNotExistException; @@ -46,7 +51,7 @@ use OCP\DB\Exception; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; -class OutboxServiceTest extends TestCase { +class DraftsServiceTest extends TestCase { /** @var MailTransmission|MockObject */ private $transmission; @@ -54,7 +59,7 @@ class OutboxServiceTest extends TestCase { private $mapper; /** @var OutboxService */ - private $outboxService; + private $draftsService; /** @var string */ private $userId; @@ -88,73 +93,35 @@ class OutboxServiceTest extends TestCase { $this->attachmentService = $this->createMock(AttachmentService::class); $this->clientFactory = $this->createMock(IMAPClientFactory::class); $this->mailManager = $this->createMock(IMailManager::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->eventDispatcher = $this->createMock(EventDispatcher::class); $this->accountService = $this->createMock(AccountService::class); $this->timeFactory = $this->createMock(ITimeFactory::class); - $this->logger = $this->createMock(LoggerInterface::class); - $this->outboxService = new OutboxService( + $this->draftsService = new DraftsService( $this->transmission, $this->mapper, $this->attachmentService, - $this->createMock(EventDispatcher::class), + $this->eventDispatcher, $this->clientFactory, $this->mailManager, - $this->accountService, - $this->timeFactory, $this->logger, + $this->accountService, + $this->timeFactory ); $this->userId = 'linus'; $this->time = $this->createMock(ITimeFactory::class); } public function testGetMessages(): void { - $this->mapper->expects(self::once()) - ->method('getAllForUser') - ->with($this->userId) - ->willReturn([ - [ - 'id' => 1, - 'type' => 0, - 'account_id' => 1, - 'alias_id' => 2, - 'send_at' => $this->time->getTime(), - 'subject' => 'Test', - 'body' => 'Test', - 'html' => false, - 'reply_to_id' => null, - 'draft_id' => 99 - - ], - [ - 'id' => 2, - 'type' => 0, - 'account_id' => 1, - 'alias_id' => 2, - 'send_at' => $this->time->getTime(), - 'subject' => 'Second Test', - 'body' => 'Second Test', - 'html' => true, - 'reply_to_id' => null, - 'draft_id' => null - ] - ]); - - $this->outboxService->getMessages($this->userId); - } - - public function testGetMessagesNoneFound(): void { - $this->mapper->expects(self::once()) - ->method('getAllForUser') - ->with($this->userId) - ->willThrowException(new Exception()); - - $this->expectException(Exception::class); - $this->outboxService->getMessages($this->userId); + $this->expectException(NotImplemented::class); + $this->draftsService->getMessages($this->userId); } public function testGetMessage(): void { $message = new LocalMessage(); $message->setAccountId(1); - $message->setSendAt($this->time->getTime()); + $message->setSendAt(null); + $message->setUpdatedAt(123456); $message->setSubject('Test'); $message->setBody('Test Test Test'); $message->setHtml(true); @@ -165,7 +132,7 @@ class OutboxServiceTest extends TestCase { ->with(1, $this->userId) ->willReturn($message); - $this->outboxService->getMessage(1, $this->userId); + $this->draftsService->getMessage(1, $this->userId); } public function testNoMessage(): void { @@ -175,14 +142,14 @@ class OutboxServiceTest extends TestCase { ->willThrowException(new DoesNotExistException('Could not fetch any messages')); $this->expectException(DoesNotExistException::class); - $this->outboxService->getMessage(1, $this->userId); + $this->draftsService->getMessage(1, $this->userId); } public function testDeleteMessage(): void { $message = new LocalMessage(); $message->setId(10); $message->setAccountId(1); - $message->setSendAt($this->time->getTime()); + $message->setSendAt(null); $message->setSubject('Test'); $message->setBody('Test Test Test'); $message->setHtml(true); @@ -195,17 +162,18 @@ class OutboxServiceTest extends TestCase { ->method('deleteWithRecipients') ->with($message); - $this->outboxService->deleteMessage($this->userId, $message); + $this->draftsService->deleteMessage($this->userId, $message); } public function testSaveMessage(): void { $message = new LocalMessage(); $message->setAccountId(1); - $message->setSendAt($this->time->getTime()); + $message->setSendAt(null); $message->setSubject('Test'); $message->setBody('Test Test Test'); $message->setHtml(true); $message->setInReplyToMessageId('abcd'); + $message->setType(LocalMessage::TYPE_DRAFT); $to = [ [ 'label' => 'Lewis', @@ -245,17 +213,18 @@ class OutboxServiceTest extends TestCase { ->method('saveLocalMessageAttachments') ->with($this->userId, 10, $attachmentIds); - $this->outboxService->saveMessage($account, $message, $to, $cc, $bcc, $attachments); + $this->draftsService->saveMessage($account, $message, $to, $cc, $bcc, $attachments); } public function testSaveMessageNoAttachments(): void { $message = new LocalMessage(); $message->setAccountId(1); - $message->setSendAt($this->time->getTime()); + $message->setSendAt(null); $message->setSubject('Test'); $message->setBody('Test Test Test'); $message->setHtml(true); $message->setInReplyToMessageId('abcd'); + $message->setType(LocalMessage::TYPE_DRAFT); $to = [ [ 'label' => 'Lewis', @@ -288,12 +257,70 @@ class OutboxServiceTest extends TestCase { $this->attachmentService->expects(self::never()) ->method('saveLocalMessageAttachments'); - $result = $this->outboxService->saveMessage($account, $message, $to, $cc, $bcc, $attachments); + $result = $this->draftsService->saveMessage($account, $message, $to, $cc, $bcc, $attachments); $this->assertEquals($message2->getId(), $result->getId()); $this->assertEmpty($result->getAttachments()); } public function testUpdateMessage(): void { + $message = new LocalMessage(); + $message->setId(10); + $message->setAccountId(1); + $message->setSendAt(null); + $message->setSubject('Test'); + $message->setBody('Test Test Test'); + $message->setHtml(true); + $message->setInReplyToMessageId('abcd'); + $message->setType(LocalMessage::TYPE_DRAFT); + $old = Recipient::fromParams([ + 'label' => 'Pam', + 'email' => 'BuyMeAnAle@startdewvalley.com', + 'type' => Recipient::TYPE_TO, + ]); + $message->setRecipients([$old]); + $to = [ + [ + 'label' => 'Linus', + 'email' => 'tent-living@startdewvalley.com', + 'type' => Recipient::TYPE_TO, + ] + ]; + $cc = []; + $bcc = []; + $attachments = [['type' => '']]; + $attachmentIds = [3]; + $rTo = Recipient::fromParams([ + 'label' => 'Linus', + 'email' => 'tent-living@startdewvalley.com', + 'type' => Recipient::TYPE_TO, + ]); + $message2 = $message; + $message2->setRecipients([$rTo]); + $account = $this->createConfiguredMock(Account::class, [ + 'getUserId' => $this->userId + ]); + $client = $this->createMock(\Horde_Imap_Client_Socket::class); + + $this->mapper->expects(self::once()) + ->method('updateWithRecipients') + ->with($message, [$rTo], $cc, $bcc) + ->willReturn($message2); + $this->clientFactory->expects(self::once()) + ->method('getClient') + ->with($account) + ->willReturn($client); + $this->attachmentService->expects(self::once()) + ->method('handleAttachments') + ->with($account, $attachments, $client) + ->willReturn($attachmentIds); + $this->attachmentService->expects(self::once()) + ->method('updateLocalMessageAttachments') + ->with($this->userId, $message2, $attachmentIds); + + $this->draftsService->updateMessage($account, $message, $to, $cc, $bcc, $attachments); + } + + public function testConvertToOutboxMessage(): void { $message = new LocalMessage(); $message->setId(10); $message->setAccountId(1); @@ -302,6 +329,7 @@ class OutboxServiceTest extends TestCase { $message->setBody('Test Test Test'); $message->setHtml(true); $message->setInReplyToMessageId('abcd'); + $message->setType(LocalMessage::TYPE_OUTGOING); $old = Recipient::fromParams([ 'label' => 'Pam', 'email' => 'BuyMeAnAle@startdewvalley.com', @@ -347,10 +375,10 @@ class OutboxServiceTest extends TestCase { ->method('updateLocalMessageAttachments') ->with($this->userId, $message2, $attachmentIds); - $this->outboxService->updateMessage($account, $message, $to, $cc, $bcc, $attachments); + $this->draftsService->updateMessage($account, $message, $to, $cc, $bcc, $attachments); } - public function testUpdateMessageNoAttachments(): void { + public function testConvertToOutboxMessageNoRecipients(): void { $message = new LocalMessage(); $message->setId(10); $message->setAccountId(1); @@ -359,6 +387,55 @@ class OutboxServiceTest extends TestCase { $message->setBody('Test Test Test'); $message->setHtml(true); $message->setInReplyToMessageId('abcd'); + $message->setType(LocalMessage::TYPE_OUTGOING); + $old = Recipient::fromParams([ + 'label' => 'Pam', + 'email' => 'BuyMeAnAle@startdewvalley.com', + 'type' => Recipient::TYPE_TO, + ]); + $message->setRecipients([$old]); + $to = []; + $cc = []; + $bcc = []; + $attachments = [['type' => '']]; + $attachmentIds = [3]; + $message2 = $message; + $message2->setRecipients([]); + $account = $this->createConfiguredMock(Account::class, [ + 'getUserId' => $this->userId + ]); + $client = $this->createMock(\Horde_Imap_Client_Socket::class); + + $this->mapper->expects(self::never()) + ->method('updateWithRecipients') + ->with($message, [], $cc, $bcc) + ->willReturn($message2); + $this->clientFactory->expects(self::never()) + ->method('getClient') + ->with($account) + ->willReturn($client); + $this->attachmentService->expects(self::never()) + ->method('handleAttachments') + ->with($account, $attachments, $client) + ->willReturn($attachmentIds); + $this->attachmentService->expects(self::never()) + ->method('updateLocalMessageAttachments') + ->with($this->userId, $message2, $attachmentIds); + + $this->expectException(ClientException::class); + $this->draftsService->updateMessage($account, $message, $to, $cc, $bcc, $attachments); + } + + public function testUpdateMessageNoAttachments(): void { + $message = new LocalMessage(); + $message->setId(10); + $message->setAccountId(1); + $message->setSendAt(null); + $message->setSubject('Test'); + $message->setBody('Test Test Test'); + $message->setHtml(true); + $message->setInReplyToMessageId('abcd'); + $message->setType(LocalMessage::TYPE_DRAFT); $old = Recipient::fromParams([ 'label' => 'Pam', 'email' => 'BuyMeAnAle@startdewvalley.com', @@ -396,7 +473,7 @@ class OutboxServiceTest extends TestCase { ->method('getClient'); $this->attachmentService->expects(self::never()) ->method('handleAttachments'); - $result = $this->outboxService->updateMessage($account, $message, $to, $cc, $bcc, $attachments); + $result = $this->draftsService->updateMessage($account, $message, $to, $cc, $bcc, $attachments); $this->assertEmpty($result->getAttachments()); } @@ -408,6 +485,7 @@ class OutboxServiceTest extends TestCase { $message->setBody('Test Test Test'); $message->setHtml(true); $message->setInReplyToMessageId('laskdjhsakjh33233928@startdewvalley.com'); + $message->setType(LocalMessage::TYPE_OUTGOING); $to = [ [ 'label' => 'Gunther', @@ -430,7 +508,7 @@ class OutboxServiceTest extends TestCase { ->method('saveLocalMessageAttachments'); $this->expectException(Exception::class); - $this->outboxService->saveMessage($account, $message, $to, [], []); + $this->draftsService->saveMessage($account, $message, $to, [], []); } public function testSendMessage(): void { @@ -462,7 +540,7 @@ class OutboxServiceTest extends TestCase { ->method('deleteWithRecipients') ->with($message); - $this->outboxService->sendMessage($message, $account); + $this->draftsService->sendMessage($message, $account); } public function testSendMessageTransmissionError(): void { @@ -494,6 +572,70 @@ class OutboxServiceTest extends TestCase { ->method('deleteWithRecipients'); $this->expectException(ClientException::class); - $this->outboxService->sendMessage($message, $account); + $this->draftsService->sendMessage($message, $account); + } + + public function testHandleDraft(): void { + $mailAccount = new MailAccount(); + $mailAccount->setUserId('admin'); + $account = new Account($mailAccount); + $draftId = 1; + $message = new Message(); + + $this->mailManager->expects(self::once()) + ->method('getMessage') + ->with($account->getUserId(), $draftId) + ->willReturn($message); + $this->eventDispatcher->expects(self::once()) + ->method('dispatchTyped') + ->with(new DraftMessageCreatedEvent($account, $message)); + + $this->draftsService->handleDraft($account, $draftId); + } + + public function testFlush(): void { + $time = 123456; + $message = new LocalMessage(); + $message->setId(1); + $message->setAccountId(1); + $messages = [$message]; + $mailAccount = new MailAccount(); + $mailAccount->setUserId('linus'); + $account = new Account($mailAccount); + + $this->timeFactory->expects(self::once()) + ->method('getTime') + ->willReturn($time); + $this->mapper->expects(self::once()) + ->method('findDueDrafts') + ->with($time) + ->willReturn($messages); + $this->accountService->expects(self::once()) + ->method('findById') + ->willReturn($account); + $this->logger->expects(self::once()) + ->method('debug'); + + $this->draftsService->flush(); + } + + public function testFlushNoMessages(): void { + $time = 123456; + + $this->timeFactory->expects(self::once()) + ->method('getTime') + ->willReturn($time); + $this->mapper->expects(self::once()) + ->method('findDueDrafts') + ->with($time) + ->willReturn([]); + $this->accountService->expects(self::never()) + ->method('findById'); + $this->logger->expects(self::never()) + ->method('debug'); + $this->logger->expects(self::never()) + ->method('warning'); + + $this->draftsService->flush(); } } diff --git a/tests/Unit/Service/MailTransmissionTest.php b/tests/Unit/Service/MailTransmissionTest.php index 5490a1d07..571245a34 100644 --- a/tests/Unit/Service/MailTransmissionTest.php +++ b/tests/Unit/Service/MailTransmissionTest.php @@ -38,6 +38,7 @@ use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Message as DbMessage; use OCA\Mail\Db\Recipient; use OCA\Mail\Events\MessageSentEvent; +use OCA\Mail\Exception\ClientException; use OCA\Mail\IMAP\IMAPClientFactory; use OCA\Mail\IMAP\MessageMapper; use OCA\Mail\Model\Message; @@ -518,4 +519,86 @@ class MailTransmissionTest extends TestCase { $this->assertStringContainsString('Content-Type: image/png', $rawMessage); $this->assertStringContainsString('Content-Disposition: inline', $rawMessage); } + + public function testSendLocalDraft(): void { + $mailAccount = new MailAccount(); + $mailAccount->setId(10); + $mailAccount->setUserId('gunther'); + $mailAccount->setName('Gunther'); + $mailAccount->setEmail('gunther@stardewvalley-museum.com'); + $mailAccount->setDraftsMailboxId(123); + $message = new LocalMessage(); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setAccountId($mailAccount->getId()); + $message->setAliasId(2); + $message->setSendAt(123); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setAttachments([]); + $to = Recipient::fromParams([ + 'email' => 'emily@stardewvalleypub.com', + 'label' => 'Emily', + 'type' => Recipient::TYPE_TO + ]); + $message->setRecipients([$to]); + + $alias = Alias::fromParams([ + 'id' => 1, + 'accountId' => 10, + 'name' => 'Emily', + 'alias' => 'Emmerlie' + ]); + $this->aliasService->expects(self::once()) + ->method('find') + ->with($message->getAliasId(), $mailAccount->getUserId()) + ->willReturn($alias); + + $replyMessage = new DbMessage(); + $replyMessage->setMessageId('abc'); + + $this->transmission->sendLocalMessage(new Account($mailAccount), $message, true); + } + + public function testSendLocalDraftNoDraftsMailbox(): void { + $mailAccount = new MailAccount(); + $mailAccount->setId(10); + $mailAccount->setUserId('gunther'); + $mailAccount->setName('Gunther'); + $mailAccount->setEmail('gunther@stardewvalley-museum.com'); + $message = new LocalMessage(); + $message->setType(LocalMessage::TYPE_DRAFT); + $message->setAccountId($mailAccount->getId()); + $message->setAliasId(2); + $message->setSendAt(123); + $message->setSubject('subject'); + $message->setBody('message'); + $message->setHtml(true); + $message->setInReplyToMessageId('abc'); + $message->setAttachments([]); + $to = Recipient::fromParams([ + 'email' => 'emily@stardewvalleypub.com', + 'label' => 'Emily', + 'type' => Recipient::TYPE_TO + ]); + $message->setRecipients([$to]); + + $alias = Alias::fromParams([ + 'id' => 1, + 'accountId' => 10, + 'name' => 'Emily', + 'alias' => 'Emmerlie' + ]); + $this->aliasService->expects(self::once()) + ->method('find') + ->with($message->getAliasId(), $mailAccount->getUserId()) + ->willReturn($alias); + + $replyMessage = new DbMessage(); + $replyMessage->setMessageId('abc'); + + $this->expectException(ClientException::class); + $this->transmission->sendLocalMessage(new Account($mailAccount), $message, true); + } } -- cgit v1.2.3