From fc4cc9f26d4b8f885d01a4671c16e1af2a1f20c0 Mon Sep 17 00:00:00 2001 From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com> Date: Mon, 16 Mar 2026 17:50:53 +0100 Subject: [PATCH] test: add unit test coverage for simple events, cache and parser AI-assisted: OpenCode + Claude Haiku 4.5 Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com> --- tests/Unit/Cache/CachedMailboxTest.php | 74 +++++++++++++++++++ tests/Unit/Cache/HordeSyncTokenParserTest.php | 62 ++++++++++++++++ tests/Unit/Cache/HordeSyncTokenTest.php | 46 ++++++++++++ .../Events/BeforeImapClientCreatedTest.php | 24 ++++++ .../Events/BeforeMessageDeletedEventTest.php | 28 +++++++ .../Events/DraftMessageCreatedEventTest.php | 27 +++++++ tests/Unit/Events/DraftSavedEventTest.php | 51 +++++++++++++ .../Events/MailboxesSynchronizedEventTest.php | 24 ++++++ tests/Unit/Events/MessageDeletedEventTest.php | 29 ++++++++ tests/Unit/Events/MessageFlaggedEventTest.php | 45 +++++++++++ tests/Unit/Events/MessageSentEventTest.php | 27 +++++++ .../Events/NewMessageReceivedEventTest.php | 23 ++++++ .../Events/NewMessagesSynchronizedTest.php | 44 +++++++++++ .../Events/OutboxMessageCreatedEventTest.php | 27 +++++++ tests/Unit/Events/SaveDraftEventTest.php | 41 ++++++++++ .../Unit/Events/SynchronizationEventTest.php | 39 ++++++++++ tests/Unit/Html/ParserTest.php | 63 ++++++++++++++++ 17 files changed, 674 insertions(+) create mode 100644 tests/Unit/Cache/CachedMailboxTest.php create mode 100644 tests/Unit/Cache/HordeSyncTokenParserTest.php create mode 100644 tests/Unit/Cache/HordeSyncTokenTest.php create mode 100644 tests/Unit/Events/BeforeImapClientCreatedTest.php create mode 100644 tests/Unit/Events/BeforeMessageDeletedEventTest.php create mode 100644 tests/Unit/Events/DraftMessageCreatedEventTest.php create mode 100644 tests/Unit/Events/DraftSavedEventTest.php create mode 100644 tests/Unit/Events/MailboxesSynchronizedEventTest.php create mode 100644 tests/Unit/Events/MessageDeletedEventTest.php create mode 100644 tests/Unit/Events/MessageFlaggedEventTest.php create mode 100644 tests/Unit/Events/MessageSentEventTest.php create mode 100644 tests/Unit/Events/NewMessageReceivedEventTest.php create mode 100644 tests/Unit/Events/NewMessagesSynchronizedTest.php create mode 100644 tests/Unit/Events/OutboxMessageCreatedEventTest.php create mode 100644 tests/Unit/Events/SaveDraftEventTest.php create mode 100644 tests/Unit/Events/SynchronizationEventTest.php create mode 100644 tests/Unit/Html/ParserTest.php diff --git a/tests/Unit/Cache/CachedMailboxTest.php b/tests/Unit/Cache/CachedMailboxTest.php new file mode 100644 index 0000000000..2b1b7463b4 --- /dev/null +++ b/tests/Unit/Cache/CachedMailboxTest.php @@ -0,0 +1,74 @@ +assertNull($mailbox->getUids()); + $this->assertNull($mailbox->getUidValidity()); + $this->assertNull($mailbox->getHighestModSeq()); + } + + public function testSetAndGetUids(): void { + $mailbox = new CachedMailbox(); + $uids = [1, 2, 3, 4, 5]; + + $mailbox->setUids($uids); + + $this->assertSame($uids, $mailbox->getUids()); + } + + public function testSetAndGetUidValidity(): void { + $mailbox = new CachedMailbox(); + $uidValidity = 123456; + + $mailbox->setUidValidity($uidValidity); + + $this->assertSame($uidValidity, $mailbox->getUidValidity()); + } + + public function testSetAndGetHighestModSeq(): void { + $mailbox = new CachedMailbox(); + $modSeq = 987654; + + $mailbox->setHighestModSeq($modSeq); + + $this->assertSame($modSeq, $mailbox->getHighestModSeq()); + } + + public function testSetNullValues(): void { + $mailbox = new CachedMailbox(); + $mailbox->setUids([1, 2, 3]); + $mailbox->setUidValidity(123); + $mailbox->setHighestModSeq(456); + + $mailbox->setUids(null); + $mailbox->setUidValidity(null); + $mailbox->setHighestModSeq(null); + + $this->assertNull($mailbox->getUids()); + $this->assertNull($mailbox->getUidValidity()); + $this->assertNull($mailbox->getHighestModSeq()); + } + + public function testSetEmptyUidArray(): void { + $mailbox = new CachedMailbox(); + $uids = []; + + $mailbox->setUids($uids); + + $this->assertSame([], $mailbox->getUids()); + } +} diff --git a/tests/Unit/Cache/HordeSyncTokenParserTest.php b/tests/Unit/Cache/HordeSyncTokenParserTest.php new file mode 100644 index 0000000000..304bbdd6a9 --- /dev/null +++ b/tests/Unit/Cache/HordeSyncTokenParserTest.php @@ -0,0 +1,62 @@ +parser = new HordeSyncTokenParser(); + } + + public function testParseCompleteToken(): void { + $token = base64_encode('U1234,V5678,H9999'); + + $result = $this->parser->parseSyncToken($token); + + $this->assertSame(1234, $result->getNextUid()); + $this->assertSame(5678, $result->getUidValidity()); + $this->assertSame(9999, $result->getHighestModSeq()); + } + + public function testParseTokenWithoutHighestModSeq(): void { + $token = base64_encode('U1234,V5678'); + + $result = $this->parser->parseSyncToken($token); + + $this->assertSame(1234, $result->getNextUid()); + $this->assertSame(5678, $result->getUidValidity()); + $this->assertNull($result->getHighestModSeq()); + } + + public function testParseTokenWithOnlyNextUid(): void { + $token = base64_encode('U1000'); + + $result = $this->parser->parseSyncToken($token); + + $this->assertSame(1000, $result->getNextUid()); + $this->assertNull($result->getUidValidity()); + $this->assertNull($result->getHighestModSeq()); + } + + public function testParseEmptyToken(): void { + $token = base64_encode(''); + + $result = $this->parser->parseSyncToken($token); + + $this->assertNull($result->getNextUid()); + $this->assertNull($result->getUidValidity()); + $this->assertNull($result->getHighestModSeq()); + } +} diff --git a/tests/Unit/Cache/HordeSyncTokenTest.php b/tests/Unit/Cache/HordeSyncTokenTest.php new file mode 100644 index 0000000000..0334c342e5 --- /dev/null +++ b/tests/Unit/Cache/HordeSyncTokenTest.php @@ -0,0 +1,46 @@ +assertSame($nextUid, $token->getNextUid()); + $this->assertSame($uidValidity, $token->getUidValidity()); + $this->assertSame($highestModSeq, $token->getHighestModSeq()); + } + + public function testConstructorWithNullValues(): void { + $token = new HordeSyncToken(null, null, null); + + $this->assertNull($token->getNextUid()); + $this->assertNull($token->getUidValidity()); + $this->assertNull($token->getHighestModSeq()); + } + + public function testConstructorWithPartialValues(): void { + $nextUid = 100; + $uidValidity = 200; + + $token = new HordeSyncToken($nextUid, $uidValidity, null); + + $this->assertSame($nextUid, $token->getNextUid()); + $this->assertSame($uidValidity, $token->getUidValidity()); + $this->assertNull($token->getHighestModSeq()); + } +} diff --git a/tests/Unit/Events/BeforeImapClientCreatedTest.php b/tests/Unit/Events/BeforeImapClientCreatedTest.php new file mode 100644 index 0000000000..dbb14db1f7 --- /dev/null +++ b/tests/Unit/Events/BeforeImapClientCreatedTest.php @@ -0,0 +1,24 @@ +createMock(Account::class); + + $event = new BeforeImapClientCreated($account); + + $this->assertSame($account, $event->getAccount()); + } +} diff --git a/tests/Unit/Events/BeforeMessageDeletedEventTest.php b/tests/Unit/Events/BeforeMessageDeletedEventTest.php new file mode 100644 index 0000000000..850991b7d2 --- /dev/null +++ b/tests/Unit/Events/BeforeMessageDeletedEventTest.php @@ -0,0 +1,28 @@ +createMock(Account::class); + $folderId = 'INBOX'; + $messageId = 123; + + $event = new BeforeMessageDeletedEvent($account, $folderId, $messageId); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($folderId, $event->getFolderId()); + $this->assertSame($messageId, $event->getMessageId()); + } +} diff --git a/tests/Unit/Events/DraftMessageCreatedEventTest.php b/tests/Unit/Events/DraftMessageCreatedEventTest.php new file mode 100644 index 0000000000..05cf73bde9 --- /dev/null +++ b/tests/Unit/Events/DraftMessageCreatedEventTest.php @@ -0,0 +1,27 @@ +createMock(Account::class); + $draft = $this->createMock(Message::class); + + $event = new DraftMessageCreatedEvent($account, $draft); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($draft, $event->getDraft()); + } +} diff --git a/tests/Unit/Events/DraftSavedEventTest.php b/tests/Unit/Events/DraftSavedEventTest.php new file mode 100644 index 0000000000..2231217743 --- /dev/null +++ b/tests/Unit/Events/DraftSavedEventTest.php @@ -0,0 +1,51 @@ +createMock(Account::class); + $newMessageData = $this->createMock(NewMessageData::class); + $draft = $this->createMock(Message::class); + + $event = new DraftSavedEvent($account, $newMessageData, $draft); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($newMessageData, $event->getNewMessageData()); + $this->assertSame($draft, $event->getDraft()); + } + + public function testConstructorWithoutOptionalParams(): void { + $account = $this->createMock(Account::class); + + $event = new DraftSavedEvent($account); + + $this->assertSame($account, $event->getAccount()); + $this->assertNull($event->getNewMessageData()); + $this->assertNull($event->getDraft()); + } + + public function testConstructorWithPartialParams(): void { + $account = $this->createMock(Account::class); + $newMessageData = $this->createMock(NewMessageData::class); + + $event = new DraftSavedEvent($account, $newMessageData); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($newMessageData, $event->getNewMessageData()); + $this->assertNull($event->getDraft()); + } +} diff --git a/tests/Unit/Events/MailboxesSynchronizedEventTest.php b/tests/Unit/Events/MailboxesSynchronizedEventTest.php new file mode 100644 index 0000000000..d4043bee64 --- /dev/null +++ b/tests/Unit/Events/MailboxesSynchronizedEventTest.php @@ -0,0 +1,24 @@ +createMock(Account::class); + + $event = new MailboxesSynchronizedEvent($account); + + $this->assertSame($account, $event->getAccount()); + } +} diff --git a/tests/Unit/Events/MessageDeletedEventTest.php b/tests/Unit/Events/MessageDeletedEventTest.php new file mode 100644 index 0000000000..f6cec2ef68 --- /dev/null +++ b/tests/Unit/Events/MessageDeletedEventTest.php @@ -0,0 +1,29 @@ +createMock(Account::class); + $mailbox = $this->createMock(Mailbox::class); + $messageId = 42; + + $event = new MessageDeletedEvent($account, $mailbox, $messageId); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($mailbox, $event->getMailbox()); + $this->assertSame($messageId, $event->getMessageId()); + } +} diff --git a/tests/Unit/Events/MessageFlaggedEventTest.php b/tests/Unit/Events/MessageFlaggedEventTest.php new file mode 100644 index 0000000000..36410fb553 --- /dev/null +++ b/tests/Unit/Events/MessageFlaggedEventTest.php @@ -0,0 +1,45 @@ +createMock(Account::class); + $mailbox = $this->createMock(Mailbox::class); + $uid = 12345; + $flag = 'Seen'; + $set = true; + + $event = new MessageFlaggedEvent($account, $mailbox, $uid, $flag, $set); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($mailbox, $event->getMailbox()); + $this->assertSame($uid, $event->getUid()); + $this->assertSame($flag, $event->getFlag()); + $this->assertTrue($event->isSet()); + } + + public function testFlagUnset(): void { + $account = $this->createMock(Account::class); + $mailbox = $this->createMock(Mailbox::class); + $uid = 99999; + $flag = 'Flagged'; + $set = false; + + $event = new MessageFlaggedEvent($account, $mailbox, $uid, $flag, $set); + + $this->assertFalse($event->isSet()); + } +} diff --git a/tests/Unit/Events/MessageSentEventTest.php b/tests/Unit/Events/MessageSentEventTest.php new file mode 100644 index 0000000000..5f58c43b6a --- /dev/null +++ b/tests/Unit/Events/MessageSentEventTest.php @@ -0,0 +1,27 @@ +createMock(Account::class); + $localMessage = $this->createMock(LocalMessage::class); + + $event = new MessageSentEvent($account, $localMessage); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($localMessage, $event->getLocalMessage()); + } +} diff --git a/tests/Unit/Events/NewMessageReceivedEventTest.php b/tests/Unit/Events/NewMessageReceivedEventTest.php new file mode 100644 index 0000000000..2d1a1b49da --- /dev/null +++ b/tests/Unit/Events/NewMessageReceivedEventTest.php @@ -0,0 +1,23 @@ +assertSame($uri, $event->getUri()); + } +} diff --git a/tests/Unit/Events/NewMessagesSynchronizedTest.php b/tests/Unit/Events/NewMessagesSynchronizedTest.php new file mode 100644 index 0000000000..357c98b538 --- /dev/null +++ b/tests/Unit/Events/NewMessagesSynchronizedTest.php @@ -0,0 +1,44 @@ +createMock(Account::class); + $mailbox = $this->createMock(Mailbox::class); + $messages = [ + $this->createMock(Message::class), + $this->createMock(Message::class), + ]; + + $event = new NewMessagesSynchronized($account, $mailbox, $messages); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($mailbox, $event->getMailbox()); + $this->assertSame($messages, $event->getMessages()); + $this->assertCount(2, $event->getMessages()); + } + + public function testConstructorWithEmptyMessages(): void { + $account = $this->createMock(Account::class); + $mailbox = $this->createMock(Mailbox::class); + $messages = []; + + $event = new NewMessagesSynchronized($account, $mailbox, $messages); + + $this->assertEmpty($event->getMessages()); + } +} diff --git a/tests/Unit/Events/OutboxMessageCreatedEventTest.php b/tests/Unit/Events/OutboxMessageCreatedEventTest.php new file mode 100644 index 0000000000..738c3ad25f --- /dev/null +++ b/tests/Unit/Events/OutboxMessageCreatedEventTest.php @@ -0,0 +1,27 @@ +createMock(Account::class); + $message = $this->createMock(Message::class); + + $event = new OutboxMessageCreatedEvent($account, $message); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($message, $event->getDraft()); + } +} diff --git a/tests/Unit/Events/SaveDraftEventTest.php b/tests/Unit/Events/SaveDraftEventTest.php new file mode 100644 index 0000000000..51ec716633 --- /dev/null +++ b/tests/Unit/Events/SaveDraftEventTest.php @@ -0,0 +1,41 @@ +createMock(Account::class); + $newMessageData = $this->createMock(NewMessageData::class); + $draft = $this->createMock(Message::class); + + $event = new SaveDraftEvent($account, $newMessageData, $draft); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($newMessageData, $event->getNewMessageData()); + $this->assertSame($draft, $event->getDraft()); + } + + public function testConstructorWithoutDraft(): void { + $account = $this->createMock(Account::class); + $newMessageData = $this->createMock(NewMessageData::class); + + $event = new SaveDraftEvent($account, $newMessageData, null); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($newMessageData, $event->getNewMessageData()); + $this->assertNull($event->getDraft()); + } +} diff --git a/tests/Unit/Events/SynchronizationEventTest.php b/tests/Unit/Events/SynchronizationEventTest.php new file mode 100644 index 0000000000..d0010eae0a --- /dev/null +++ b/tests/Unit/Events/SynchronizationEventTest.php @@ -0,0 +1,39 @@ +createMock(Account::class); + $logger = $this->createMock(LoggerInterface::class); + $rebuildThreads = true; + + $event = new SynchronizationEvent($account, $logger, $rebuildThreads); + + $this->assertSame($account, $event->getAccount()); + $this->assertSame($logger, $event->getLogger()); + $this->assertTrue($event->isRebuildThreads()); + } + + public function testConstructorWithoutRebuildThreads(): void { + $account = $this->createMock(Account::class); + $logger = $this->createMock(LoggerInterface::class); + $rebuildThreads = false; + + $event = new SynchronizationEvent($account, $logger, $rebuildThreads); + + $this->assertFalse($event->isRebuildThreads()); + } +} diff --git a/tests/Unit/Html/ParserTest.php b/tests/Unit/Html/ParserTest.php new file mode 100644 index 0000000000..3e76d261dd --- /dev/null +++ b/tests/Unit/Html/ParserTest.php @@ -0,0 +1,63 @@ +

Test content

'; + + $doc = Parser::parseToDomDocument($html); + + $this->assertInstanceOf(DOMDocument::class, $doc); + } + + public function testParseMinimalHtml(): void { + $html = ''; + + $doc = Parser::parseToDomDocument($html); + + $this->assertInstanceOf(DOMDocument::class, $doc); + } + + public function testParseMalformedHtml(): void { + $html = '

Unclosed paragraph'; + + $doc = Parser::parseToDomDocument($html); + + $this->assertInstanceOf(DOMDocument::class, $doc); + } + + public function testParseHtmlWithSpecialCharacters(): void { + $html = '

Test & special < > chars

'; + + $doc = Parser::parseToDomDocument($html); + + $this->assertInstanceOf(DOMDocument::class, $doc); + $paragraphs = $doc->getElementsByTagName('p'); + $this->assertEquals(1, $paragraphs->length); + $textContent = $paragraphs->item(0)->textContent; + $this->assertStringContainsString('&', $textContent); + $this->assertStringContainsString('<', $textContent); + $this->assertStringContainsString('>', $textContent); + } + + public function testParseComplexHtml(): void { + $html = 'Test

Content

'; + + $doc = Parser::parseToDomDocument($html); + + $this->assertInstanceOf(DOMDocument::class, $doc); + $this->assertNotNull($doc->documentElement); + } +}