mail/tests/Unit/Service/DraftsServiceTest.php

572 строки
17 KiB
PHP

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Mail\Tests\Unit\Service;
use ChristophWurst\Nextcloud\Testing\TestCase;
use OC\EventDispatcher\EventDispatcher;
use OCA\Mail\Account;
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\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;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\DB\Exception;
use OCP\EventDispatcher\IEventDispatcher;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class DraftsServiceTest extends TestCase {
/** @var MailTransmission|MockObject */
private $transmission;
/** @var LocalMessageMapper|MockObject */
private $mapper;
/** @var OutboxService */
private $draftsService;
/** @var string */
private $userId;
/** @var ITimeFactory|MockObject */
private $time;
/** @var AttachmentService|MockObject */
private $attachmentService;
/** @var IMAPClientFactory|MockObject */
private $clientFactory;
/** @var IMailManager|MockObject */
private $mailManager;
private IEventDispatcher $eventDispatcher;
/** @var AccountService|MockObject */
private $accountService;
/** @var ITimeFactory|MockObject */
private $timeFactory;
/** @var MockObject|LoggerInterface */
private $logger;
protected function setUp(): void {
parent::setUp();
$this->transmission = $this->createMock(MailTransmission::class);
$this->mapper = $this->createMock(LocalMessageMapper::class);
$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->draftsService = new DraftsService(
$this->transmission,
$this->mapper,
$this->attachmentService,
$this->eventDispatcher,
$this->clientFactory,
$this->mailManager,
$this->logger,
$this->accountService,
$this->timeFactory
);
$this->userId = 'linus';
$this->time = $this->createMock(ITimeFactory::class);
}
public function testGetMessage(): void {
$message = new LocalMessage();
$message->setAccountId(1);
$message->setSendAt(null);
$message->setUpdatedAt(123456);
$message->setSubject('Test');
$message->setBody('Test Test Test');
$message->setHtml(true);
$message->setInReplyToMessageId('abcd');
$this->mapper->expects(self::once())
->method('findById')
->with(1, $this->userId)
->willReturn($message);
$this->draftsService->getMessage(1, $this->userId);
}
public function testNoMessage(): void {
$this->mapper->expects(self::once())
->method('findById')
->with(1, $this->userId)
->willThrowException(new DoesNotExistException('Could not fetch any messages'));
$this->expectException(DoesNotExistException::class);
$this->draftsService->getMessage(1, $this->userId);
}
public function testDeleteMessage(): 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');
$this->attachmentService->expects(self::once())
->method('deleteLocalMessageAttachments')
->with($this->userId, $message->getId());
$this->mapper->expects(self::once())
->method('deleteWithRecipients')
->with($message);
$this->draftsService->deleteMessage($this->userId, $message);
}
public function testSaveMessage(): void {
$message = new LocalMessage();
$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);
$to = [
[
'label' => 'Lewis',
'email' => 'tent-living@startdewvalley.com',
'type' => Recipient::TYPE_TO,
]
];
$cc = [];
$bcc = [];
$attachments = [[]];
$attachmentIds = [1];
$rTo = Recipient::fromParams([
'label' => 'Lewis',
'email' => 'tent-living@startdewvalley.com',
'type' => Recipient::TYPE_TO,
]);
$message2 = $message;
$message2->setId(10);
$account = $this->createConfiguredMock(Account::class, [
'getUserId' => $this->userId
]);
$client = $this->createMock(\Horde_Imap_Client_Socket::class);
$this->mapper->expects(self::once())
->method('saveWithRecipients')
->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('saveLocalMessageAttachments')
->with($this->userId, 10, $attachmentIds);
$this->draftsService->saveMessage($account, $message, $to, $cc, $bcc, $attachments);
}
public function testSaveMessageNoAttachments(): void {
$message = new LocalMessage();
$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);
$to = [
[
'label' => 'Lewis',
'email' => 'tent-living@startdewvalley.com',
'type' => Recipient::TYPE_TO,
]
];
$cc = [];
$bcc = [];
$attachments = [];
$rTo = Recipient::fromParams([
'label' => 'Lewis',
'email' => 'tent-living@startdewvalley.com',
'type' => Recipient::TYPE_TO,
]);
$message2 = $message;
$message2->setId(10);
$account = $this->createConfiguredMock(Account::class, [
'getUserId' => $this->userId
]);
$this->mapper->expects(self::once())
->method('saveWithRecipients')
->with($message, [$rTo], $cc, $bcc)
->willReturn($message2);
$this->clientFactory->expects(self::never())
->method('getClient');
$this->attachmentService->expects(self::never())
->method('handleAttachments');
$this->attachmentService->expects(self::never())
->method('saveLocalMessageAttachments');
$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);
$message->setSendAt($this->time->getTime());
$message->setSubject('Test');
$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 = [
[
'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 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',
'type' => Recipient::TYPE_TO,
]);
$message->setRecipients([$old]);
$to = [
[
'label' => 'Linus',
'email' => 'tent-living@startdewvalley.com',
'type' => Recipient::TYPE_TO,
]
];
$cc = [];
$bcc = [];
$attachments = [];
$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
]);
$this->mapper->expects(self::once())
->method('updateWithRecipients')
->with($message, [$rTo], $cc, $bcc)
->willReturn($message2);
$this->attachmentService->expects(self::once())
->method('updateLocalMessageAttachments')
->with($this->userId, $message2, $attachments);
$this->clientFactory->expects(self::never())
->method('getClient');
$this->attachmentService->expects(self::never())
->method('handleAttachments');
$result = $this->draftsService->updateMessage($account, $message, $to, $cc, $bcc, $attachments);
$this->assertEmpty($result->getAttachments());
}
public function testSaveMessageError(): void {
$message = new LocalMessage();
$message->setAccountId(1);
$message->setSendAt($this->time->getTime());
$message->setSubject('Test');
$message->setBody('Test Test Test');
$message->setHtml(true);
$message->setInReplyToMessageId('laskdjhsakjh33233928@startdewvalley.com');
$message->setType(LocalMessage::TYPE_OUTGOING);
$to = [
[
'label' => 'Gunther',
'email' => 'museum@startdewvalley.com',
'type' => Recipient::TYPE_TO,
]
];
$rTo = Recipient::fromParams([
'label' => 'Gunther',
'email' => 'museum@startdewvalley.com',
'type' => Recipient::TYPE_TO,
]);
$account = $this->createMock(Account::class);
$this->mapper->expects(self::once())
->method('saveWithRecipients')
->with($message, [$rTo], [], [])
->willThrowException(new Exception());
$this->attachmentService->expects(self::never())
->method('saveLocalMessageAttachments');
$this->expectException(Exception::class);
$this->draftsService->saveMessage($account, $message, $to, [], []);
}
public function testSendMessage(): void {
$message = new LocalMessage();
$message->setId(1);
$recipient = new Recipient();
$recipient->setEmail('museum@startdewvalley.com');
$recipient->setLabel('Gunther');
$recipient->setType(Recipient::TYPE_TO);
$recipients = [$recipient];
$attachment = new LocalAttachment();
$attachment->setMimeType('image/png');
$attachment->setFileName('SlimesInTheMines.png');
$attachment->setCreatedAt($this->time->getTime());
$attachments = [$attachment];
$message->setRecipients($recipients);
$message->setAttachments($attachments);
$account = $this->createConfiguredMock(Account::class, [
'getUserId' => $this->userId
]);
$this->transmission->expects(self::once())
->method('saveLocalDraft')
->with($account, $message);
$this->attachmentService->expects(self::once())
->method('deleteLocalMessageAttachments')
->with($account->getUserId(), $message->getId());
$this->mapper->expects(self::once())
->method('deleteWithRecipients')
->with($message);
$this->draftsService->sendMessage($message, $account);
}
public function testSendMessageTransmissionError(): void {
$message = new LocalMessage();
$message->setId(1);
$recipient = new Recipient();
$recipient->setEmail('museum@startdewvalley.com');
$recipient->setLabel('Gunther');
$recipient->setType(Recipient::TYPE_TO);
$recipients = [$recipient];
$attachment = new LocalAttachment();
$attachment->setMimeType('image/png');
$attachment->setFileName('SlimesInTheMines.png');
$attachment->setCreatedAt($this->time->getTime());
$attachments = [$attachment];
$message->setRecipients($recipients);
$message->setAttachments($attachments);
$account = $this->createConfiguredMock(Account::class, [
'getUserId' => $this->userId
]);
$this->transmission->expects(self::once())
->method('saveLocalDraft')
->with($account, $message)
->willThrowException(new ClientException());
$this->attachmentService->expects(self::never())
->method('deleteLocalMessageAttachments');
$this->mapper->expects(self::never())
->method('deleteWithRecipients');
$this->expectException(ClientException::class);
$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();
}
}