From 4ec0f2c7bd513ea98e12da8ef3b383674f7cbaf3 Mon Sep 17 00:00:00 2001 From: Zaahid Bateson Date: Mon, 22 Apr 2024 14:28:38 -0700 Subject: [PATCH] Add missing tests --- .../Header/Part/AddressGroupPartTest.php | 6 +- .../Header/Part/AddressPartTest.php | 47 +++++- .../Header/Part/CommentPartTest.php | 24 ++- .../Header/Part/ContainerPartTest.php | 95 ++++++++++-- .../Header/Part/NameValuePartTest.php | 140 ++++++++++++++++++ .../Header/Part/QuotedLiteralPartTest.php | 71 +++++++++ .../Header/Part/SubjectTokenTest.php | 53 +++++++ .../MailMimeParser/Header/Part/TokenTest.php | 33 ++++- 8 files changed, 448 insertions(+), 21 deletions(-) create mode 100644 tests/MailMimeParser/Header/Part/NameValuePartTest.php create mode 100644 tests/MailMimeParser/Header/Part/QuotedLiteralPartTest.php create mode 100644 tests/MailMimeParser/Header/Part/SubjectTokenTest.php diff --git a/tests/MailMimeParser/Header/Part/AddressGroupPartTest.php b/tests/MailMimeParser/Header/Part/AddressGroupPartTest.php index 7753cf5a..6ba8d42c 100644 --- a/tests/MailMimeParser/Header/Part/AddressGroupPartTest.php +++ b/tests/MailMimeParser/Header/Part/AddressGroupPartTest.php @@ -5,7 +5,6 @@ use PHPUnit\Framework\TestCase; use Psr\Log\LogLevel; -use Psr\Log\NullLogger; use ZBateson\MbWrapper\MbWrapper; /** @@ -46,6 +45,7 @@ public function testNameGroup() : void $part = $this->newAddressGroupPart([$name], $members); $this->assertEquals('Roman Senate', $part->getName()); + $this->assertEquals('Roman Senate', $part->getValue()); $this->assertEquals($members, $part->getAddresses()); $this->assertEquals($members[0], $part->getAddress(0)); $this->assertEquals($members[1], $part->getAddress(1)); @@ -58,9 +58,9 @@ public function testValidation() : void $part = $this->newAddressGroupPart([], []); $errs = $part->getErrors(true, LogLevel::NOTICE); $this->assertCount(2, $errs); - $this->assertEquals('Address group doesn\'t have a name', $errs[0]->getMessage()); + $this->assertNotEmpty($errs[0]->getMessage()); $this->assertEquals(LogLevel::ERROR, $errs[0]->getPsrLevel()); - $this->assertEquals('Address group doesn\'t have any email addresses defined in it', $errs[1]->getMessage()); + $this->assertNotEmpty($errs[1]->getMessage()); $this->assertEquals(LogLevel::NOTICE, $errs[1]->getPsrLevel()); } } diff --git a/tests/MailMimeParser/Header/Part/AddressPartTest.php b/tests/MailMimeParser/Header/Part/AddressPartTest.php index 2844faac..0ea30b8f 100644 --- a/tests/MailMimeParser/Header/Part/AddressPartTest.php +++ b/tests/MailMimeParser/Header/Part/AddressPartTest.php @@ -19,12 +19,17 @@ class AddressPartTest extends TestCase { // @phpstan-ignore-next-line private $mb; + private $hpf; private $logger; protected function setUp() : void { $this->logger = \mmpGetTestLogger(); $this->mb = new MbWrapper(); + $this->hpf = $this->getMockBuilder(HeaderPartFactory::class) + ->setConstructorArgs([$this->logger, $this->mb]) + ->setMethods() + ->getMock(); } private function newAddressPart($nameParts, $valueParts) @@ -40,6 +45,22 @@ private function getTokenMock(string $name) : Token ->getMock(); } + private function getQuotedMock(string $name) : QuotedLiteralPart + { + return $this->getMockBuilder(QuotedLiteralPart::class) + ->setConstructorArgs([$this->logger, $this->mb, [$this->getTokenMock($name)]]) + ->setMethods() + ->getMock(); + } + + private function getCommentMock(string $name) : CommentPart + { + return $this->getMockBuilder(CommentPart::class) + ->setConstructorArgs([$this->logger, $this->mb, $this->hpf, [$this->getTokenMock($name)]]) + ->setMethods() + ->getMock(); + } + public function testNameEmail() : void { $name = 'Julius Caeser'; @@ -49,12 +70,36 @@ public function testNameEmail() : void $this->assertEquals($email, $part->getEmail()); } + public function testEmailWithQuotedParts() : void + { + $email = 'gaius" julius "caesar@altavista.com'; + $part = $this->newAddressPart([], [$this->getTokenMock('gaius '), $this->getQuotedMock(' julius '), $this->getTokenMock(' caesa r@altavista.com')]); + $this->assertEquals($email, $part->getEmail()); + } + + public function testEmailWithCommentsAndQuotedParts() : void + { + $email = 'gaius"julius"caesar@altavista.com'; + $part = $this->newAddressPart([], [ + $this->getTokenMock('gaius '), + $this->getQuotedMock('julius'), + $this->getTokenMock('caesar'), + $this->getCommentMock('emperor, innit'), + $this->getTokenMock('@altavista.com') + ]); + $this->assertEquals($email, $part->getEmail()); + $comments = $part->getComments(); + $this->assertNotEmpty($comments); + $this->assertCount(1, $comments); + $this->assertEquals('emperor, innit', $comments[0]->getComment()); + } + public function testValidation() : void { $part = $this->newAddressPart([], []); $errs = $part->getErrors(true, LogLevel::ERROR); $this->assertCount(1, $errs); - $this->assertEquals('Address doesn\'t contain an email address', $errs[0]->getMessage()); + $this->assertNotEmpty($errs[0]->getMessage()); $this->assertEquals(LogLevel::ERROR, $errs[0]->getPsrLevel()); } } diff --git a/tests/MailMimeParser/Header/Part/CommentPartTest.php b/tests/MailMimeParser/Header/Part/CommentPartTest.php index f745ffeb..4cde1140 100644 --- a/tests/MailMimeParser/Header/Part/CommentPartTest.php +++ b/tests/MailMimeParser/Header/Part/CommentPartTest.php @@ -2,7 +2,6 @@ namespace ZBateson\MailMimeParser\Header\Part; -use Psr\Log\NullLogger; use PHPUnit\Framework\TestCase; use ZBateson\MbWrapper\MbWrapper; @@ -34,12 +33,20 @@ protected function setUp() : void private function getTokenMock(string $name) : Token { - return $this->getMockBuilder(MimeToken::class) + return $this->getMockBuilder(Token::class) ->setConstructorArgs([$this->logger, $this->mb, $name]) ->setMethods() ->getMock(); } + private function getQuotedMock(string $name) : QuotedLiteralPart + { + return $this->getMockBuilder(QuotedLiteralPart::class) + ->setConstructorArgs([$this->logger, $this->mb, [$this->getTokenMock($name)]]) + ->setMethods() + ->getMock(); + } + private function newCommentPart($childParts) { return new CommentPart($this->logger, $this->mb, $this->hpf, $childParts); @@ -53,10 +60,17 @@ public function testBasicComment() : void $this->assertEquals($comment, $part->getComment()); } - public function testMimeEncoding() : void + public function testNestedCommentPartStringValue() : void { - $part = $this->newCommentPart([$this->getTokenMock('=?US-ASCII?Q?Kilgore_Trout?=')]); + $comment = 'Some ((very) silly) "comment" made about my moustache'; + $part = $this->newCommentPart([ + $this->getTokenMock('Some '), + $this->newCommentPart([$this->newCommentPart([$this->getTokenMock('very')]), $this->getTokenMock(' silly')]), + $this->getTokenMock(' '), + $this->getQuotedMock('comment'), + $this->getTokenMock(' made about my moustache') + ]); $this->assertEquals('', $part->getValue()); - $this->assertEquals('Kilgore Trout', $part->getComment()); + $this->assertEquals($comment, $part->getComment()); } } diff --git a/tests/MailMimeParser/Header/Part/ContainerPartTest.php b/tests/MailMimeParser/Header/Part/ContainerPartTest.php index 128e39fa..4c898e0e 100644 --- a/tests/MailMimeParser/Header/Part/ContainerPartTest.php +++ b/tests/MailMimeParser/Header/Part/ContainerPartTest.php @@ -6,7 +6,7 @@ use ZBateson\MbWrapper\MbWrapper; /** - * Description of LiteralTest + * Description of ContainerPartTest * * @group HeaderParts * @group ContainerPart @@ -18,34 +18,109 @@ class ContainerPartTest extends TestCase { // @phpstan-ignore-next-line private $mb; + private $hpf; private $logger; protected function setUp() : void { $this->logger = \mmpGetTestLogger(); $this->mb = new MbWrapper(); + $this->hpf = $this->getMockBuilder(HeaderPartFactory::class) + ->setConstructorArgs([$this->logger, $this->mb]) + ->setMethods() + ->getMock(); } - private function getTokenArray(string $name) : array + private function getTokenArray(string ...$args) : array { - return [$this->getMockBuilder(MimeToken::class) - ->setConstructorArgs([$this->logger, $this->mb, $name]) - ->setMethods() - ->getMock()]; + return \array_map( + fn ($a) => $this->getMockBuilder(Token::class) + ->setConstructorArgs([$this->logger, $this->mb, $a]) + ->setMethods() + ->getMock(), + $args + ); + } + + private function getCommentPart(string $comment) : CommentPart + { + return $this->getMockBuilder(CommentPart::class) + ->setConstructorArgs([$this->logger, $this->mb, $this->hpf, $this->getTokenArray($comment)]) + ->setMethods() + ->getMock(); } - private function newContainerPart($childParts) + private function newContainerPart($childParts) : ContainerPart { return new ContainerPart($this->logger, $this->mb, $childParts); } public function testInstance() : void { - $part = $this->newContainerPart($this->getTokenArray('"')); + $part = $this->newContainerPart($this->getTokenArray('Kilgore Trout')); + $this->assertNotNull($part); + $this->assertEquals('Kilgore Trout', $part->getValue()); + } + + public function testIgnorableSpaces() : void + { + $part = $this->newContainerPart($this->getTokenArray(' ', 'Kilgore', ' ' , ' ', "\n\t ", 'Trout', ' ', "\n ", ' ')); $this->assertNotNull($part); - $this->assertEquals('"', $part->getValue()); + $this->assertEquals('Kilgore Trout', $part->getValue()); + } - $part = $this->newContainerPart($this->getTokenArray('=?US-ASCII?Q?Kilgore_Trout?=')); + public function testIgnorableSpacesWithComments() : void + { + $part = $this->newContainerPart(\array_merge( + $this->getTokenArray(' ', 'Kilgore', ' '), + [$this->getCommentPart('test a comment')], + $this->getTokenArray(' ', "\n\t ", 'Trout', ' '), + [$this->getCommentPart('test another comment')], + $this->getTokenArray(' ') + )); + $this->assertNotNull($part); $this->assertEquals('Kilgore Trout', $part->getValue()); } + + public function testGetChildParts() : void + { + $children = $this->getTokenArray(' ', 'Kilgore', ' ' , ' ', "\n\t ", 'Trout', ' ', "\n ", ' '); + $part = $this->newContainerPart($children); + $this->assertNotNull($part); + $this->assertEquals('Kilgore Trout', $part->getValue()); + $this->assertCount(9, $part->getChildParts()); + $this->assertEquals($children, $part->getChildParts()); + } + + public function testGetChildPartsWithComments() : void + { + $children = \array_merge( + $this->getTokenArray(' ', 'Kilgore', ' '), + [$this->getCommentPart('test a comment')], + $this->getTokenArray(' ', "\n\t ", 'Trout', ' '), + [$this->getCommentPart('test another comment')], + $this->getTokenArray(' ') + ); + $part = $this->newContainerPart($children); + $this->assertNotNull($part); + $this->assertEquals('Kilgore Trout', $part->getValue()); + $this->assertCount(10, $part->getChildParts()); + $this->assertEquals($children, $part->getChildParts()); + $this->assertCount(2, $part->getComments()); + $this->assertEquals([$children[3], $children[8]], $part->getComments()); + } + + public function testErrorOnChildPart() : void + { + $tokens = $this->getTokenArray('Kilgore', ' '); + $part = $this->newContainerPart([$this->newContainerPart($tokens), $this->getTokenArray(' ')[0], $this->newContainerPart($this->getTokenArray(' ', 'Trout'))]); + $tokens[0]->addError('Test', \Psr\Log\LogLevel::ERROR); + + $this->assertNotNull($part); + $this->assertEquals('Kilgore Trout', $part->getValue()); + + $errors = $part->getAllErrors(); + $this->assertCount(1, $errors); + $this->assertEquals('Test', $errors[0]->getMessage()); + } } diff --git a/tests/MailMimeParser/Header/Part/NameValuePartTest.php b/tests/MailMimeParser/Header/Part/NameValuePartTest.php new file mode 100644 index 00000000..b21c8ae6 --- /dev/null +++ b/tests/MailMimeParser/Header/Part/NameValuePartTest.php @@ -0,0 +1,140 @@ +logger = \mmpGetTestLogger(); + $this->mb = new MbWrapper(); + $this->hpf = $this->getMockBuilder(HeaderPartFactory::class) + ->setConstructorArgs([$this->logger, $this->mb]) + ->setMethods() + ->getMock(); + } + + private function getTokenArray(string ...$args) : array + { + return \array_map( + fn ($a) => $this->getMockBuilder(Token::class) + ->setConstructorArgs([$this->logger, $this->mb, $a]) + ->setMethods() + ->getMock(), + $args + ); + } + + private function getCommentPart(string $comment) : CommentPart + { + return $this->getMockBuilder(CommentPart::class) + ->setConstructorArgs([$this->logger, $this->mb, $this->hpf, $this->getTokenArray($comment)]) + ->setMethods() + ->getMock(); + } + + private function getContainerPart(string $value) : ContainerPart + { + return $this->getMockBuilder(ContainerPart::class) + ->setConstructorArgs([$this->logger, $this->mb, [$this->getToken($value)]]) + ->setMethods() + ->getMock(); + } + + private function assertNameValue($expectedName, $expectedValue, ?array $actualNameArray = null, ?array $actualValueArray = null) : NameValuePart + { + if ($actualNameArray === null) { + $actualNameArray = $this->getTokenArray($expectedName); + } + if ($actualValueArray === null) { + $actualValueArray = $this->getTokenArray($expectedValue); + } + $part = new NameValuePart( + $this->logger, + $this->mb, + $actualNameArray, + $actualValueArray + ); + $this->assertEquals($expectedName, $part->getName()); + $this->assertEquals($expectedValue, $part->getValue()); + return $part; + } + + public function testBasicNameValuePair() : void + { + $this->assertNameValue('Name', 'Value'); + } + + public function testIgnorableSpaces() : void + { + $parts = $this->getTokenArray(' ', 'Kilgore', ' ' , ' ', "\n\t ", 'Trout', ' ', "\n ", ' '); + $this->assertNameValue('Kilgore Trout', 'Kilgore Trout', $parts, $parts); + } + + public function testIgnorableSpacesWithComments() : void + { + $parts = \array_merge( + $this->getTokenArray(' ', 'Kilgore', ' '), + [$this->getCommentPart('test a comment')], + $this->getTokenArray(' ', "\n\t ", 'Trout', ' '), + [$this->getCommentPart('test another comment')], + $this->getTokenArray(' ') + ); + $this->assertNameValue('Kilgore Trout', 'Kilgore Trout', $parts, $parts); + } + + public function testGetChildParts() : void + { + $parts = $this->getTokenArray(' ', 'Kilgore', ' ' , ' ', "\n\t ", 'Trout', ' ', "\n ", ' '); + $part = $this->assertNameValue('Kilgore Trout', 'Kilgore Trout', $parts, $parts); + $children = \array_merge($parts, $parts); + $this->assertCount(count($children), $part->getChildParts()); + $this->assertEquals($children, $part->getChildParts()); + } + + public function testGetChildPartsWithComments() : void + { + $parts = \array_merge( + $this->getTokenArray(' ', 'Kilgore', ' '), + [$this->getCommentPart('test a comment')], + $this->getTokenArray(' ', "\n\t ", 'Trout', ' '), + [$this->getCommentPart('test another comment')], + $this->getTokenArray(' ') + ); + $part = $this->assertNameValue('Kilgore Trout', 'Kilgore Trout', $parts, $parts); + $children = \array_merge($parts, $parts); + $this->assertCount(count($children), $part->getChildParts()); + $this->assertEquals($children, $part->getChildParts()); + $this->assertCount(4, $part->getComments()); + $this->assertEquals([$children[3], $children[8], $children[3], $children[8]], $part->getComments()); + } + + public function testErrorOnChildPart() : void + { + $parts = $this->getTokenArray(' ', 'Kilgore', ' ' , ' ', "\n\t ", 'Trout', ' ', "\n ", ' '); + $part = $this->assertNameValue('Kilgore Trout', 'Kilgore Trout', $parts, $parts); + $parts[0]->addError('Test', \Psr\Log\LogLevel::ERROR); + + $errors = $part->getAllErrors(); + $this->assertCount(2, $errors); + $this->assertEquals('Test', $errors[0]->getMessage()); + } +} diff --git a/tests/MailMimeParser/Header/Part/QuotedLiteralPartTest.php b/tests/MailMimeParser/Header/Part/QuotedLiteralPartTest.php new file mode 100644 index 00000000..1a91874b --- /dev/null +++ b/tests/MailMimeParser/Header/Part/QuotedLiteralPartTest.php @@ -0,0 +1,71 @@ +logger = \mmpGetTestLogger(); + $this->mb = new MbWrapper(); + $this->hpf = $this->getMockBuilder(HeaderPartFactory::class) + ->setConstructorArgs([$this->logger, $this->mb]) + ->setMethods() + ->getMock(); + } + + private function getTokenArray(string ...$args) : array + { + return \array_map( + fn ($a) => $this->getMockBuilder(Token::class) + ->setConstructorArgs([$this->logger, $this->mb, $a, false, true]) + ->setMethods() + ->getMock(), + $args + ); + } + + private function getCommentPart(string $comment) : CommentPart + { + return $this->getMockBuilder(CommentPart::class) + ->setConstructorArgs([$this->logger, $this->mb, $this->hpf, $this->getTokenArray($comment)]) + ->setMethods() + ->getMock(); + } + + private function newQuotedLiteralPart($childParts) : QuotedLiteralPart + { + return new QuotedLiteralPart($this->logger, $this->mb, $childParts); + } + + public function testInstance() : void + { + $part = $this->newQuotedLiteralPart($this->getTokenArray('Kilgore Trout')); + $this->assertNotNull($part); + $this->assertEquals('Kilgore Trout', $part->getValue()); + } + + public function testNotIgnorableSpaces() : void + { + $part = $this->newQuotedLiteralPart($this->getTokenArray(' ', 'Kilgore', ' ' , ' ', "\n\t", ' ', 'Trout', ' ', "\n ", ' ')); + $this->assertNotNull($part); + $this->assertEquals(" Kilgore \t Trout ", $part->getValue()); + } +} diff --git a/tests/MailMimeParser/Header/Part/SubjectTokenTest.php b/tests/MailMimeParser/Header/Part/SubjectTokenTest.php new file mode 100644 index 00000000..9a063a9c --- /dev/null +++ b/tests/MailMimeParser/Header/Part/SubjectTokenTest.php @@ -0,0 +1,53 @@ +mb = new MbWrapper(); + } + + private function newSubjectToken($value) + { + return new SubjectToken(\mmpGetTestLogger(), $this->mb, $value); + } + + public function testInstance() : void + { + $token = $this->newSubjectToken('testing'); + $this->assertNotNull($token); + $this->assertEquals('testing', $token->getValue()); + $this->assertEquals('testing', (string) $token); + } + + public function testNewLines() : void + { + $token = $this->newSubjectToken("tes\n\tting"); + $this->assertNotNull($token); + $this->assertEquals("tes\tting", $token->getValue()); + } + + public function testNewLinesTabAndSpace() : void + { + $token = $this->newSubjectToken("tes\n\t ting"); + $this->assertNotNull($token); + $this->assertEquals("tes\tting", $token->getValue()); + } +} diff --git a/tests/MailMimeParser/Header/Part/TokenTest.php b/tests/MailMimeParser/Header/Part/TokenTest.php index 9294e8d6..8c51f100 100644 --- a/tests/MailMimeParser/Header/Part/TokenTest.php +++ b/tests/MailMimeParser/Header/Part/TokenTest.php @@ -25,9 +25,9 @@ protected function setUp() : void $this->mb = new MbWrapper(); } - private function newToken($value, $isLiteral = false) + private function newToken($value, $isLiteral = false, $preserveSpaces = false) { - return new Token(\mmpGetTestLogger(), $this->mb, $value, $isLiteral); + return new Token(\mmpGetTestLogger(), $this->mb, $value, $isLiteral, $preserveSpaces); } public function testInstance() : void @@ -37,4 +37,33 @@ public function testInstance() : void $this->assertEquals('testing', $token->getValue()); $this->assertEquals('testing', (string) $token); } + + public function testNewLines() : void + { + $token = $this->newToken("tes\n\tting"); + $this->assertNotNull($token); + $this->assertEquals("tes\tting", $token->getValue()); + } + + public function testNewLinesTabAndSpace() : void + { + $token = $this->newToken("tes\n\t ting"); + $this->assertNotNull($token); + $this->assertEquals("tes\t ting", $token->getValue()); + } + + public function testLiteralAndPreserveSpace() : void + { + $token = $this->newToken(' '); + $this->assertNotNull($token); + $this->assertEquals(' ', $token->getValue()); + + $token = $this->newToken("\n ", false, true); + $this->assertNotNull($token); + $this->assertEquals(' ', $token->getValue()); + + $token = $this->newToken("\n ", true); + $this->assertNotNull($token); + $this->assertEquals("\n ", $token->getValue()); + } }