From 5e833628dcfb0c86b989213b097809d8451afc61 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Mon, 5 Jul 2021 23:11:21 +0200 Subject: [PATCH] Tests: introduce dedicated tests for the `PHPMailer::html2text()` method So far, this method did not have dedicated tests. The test file this commit introduces, tests all aspects of the method as well as documents the current behaviour of the method for specific, outlier situations. --- test/PHPMailer/Html2TextTest.php | 232 +++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 test/PHPMailer/Html2TextTest.php diff --git a/test/PHPMailer/Html2TextTest.php b/test/PHPMailer/Html2TextTest.php new file mode 100644 index 00000000..ce0ce509 --- /dev/null +++ b/test/PHPMailer/Html2TextTest.php @@ -0,0 +1,232 @@ + + * @author Andy Prevost + * @copyright 2012 - 2020 Marcus Bointon + * @copyright 2004 - 2009 Andy Prevost + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + */ + +namespace PHPMailer\Test\PHPMailer; + +use PHPMailer\PHPMailer\PHPMailer; +use PHPMailer\Test\TestCase; + +/** + * Test HTML to text conversion functionality. + * + * @covers \PHPMailer\PHPMailer\PHPMailer::html2text + */ +final class Html2TextTest extends TestCase +{ + + /** + * Test converting an arbitrary HTML string into plain text. + * + * @dataProvider dataHtml2Text + * + * @param string $input Arbitrary string, potentially containing HTML. + * @param string $expected The expected function return value. + * @param string $charset Optional. Charset to use. + */ + public function testHtml2Text($input, $expected, $charset = null) + { + if (isset($charset)) { + $this->Mail->CharSet = $charset; + } + + $result = $this->Mail->html2text($input); + self::assertSame($expected, $result); + } + + /** + * Data provider. + * + * @return array + */ + public function dataHtml2Text() + { + return [ + 'Plain text, no encoded entities, surrounded by whitespace' => [ + 'input' => ' Lorem ipsum dolor sit amet, consectetur adipiscing elit. ', + 'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + ], + 'Plain text with encoded entities' => [ + 'input' => 'Iñtërnâtiônàlizætiøn', + 'expected' => 'Iñtërnâtiônàlizætiøn', + 'charset' => PHPMailer::CHARSET_UTF8 + ], + + 'Simple HTML, including HTML comment and encoded quotes' => [ + 'input' => '

Test paragraph.

' + . '' + . ' Other text with ' and "', + 'expected' => 'Test paragraph. Other text with \' and "', + ], + 'Simple HTML, including self-closing tags' => [ + 'input' => '

Test
paragraph
alt text.

', + 'expected' => 'Testparagraph.', + ], + 'Simple HTML, paragraph fusing' => [ + 'input' => '
+

color is blue

size is huge

+

material is wood

+
', + 'expected' => 'color is bluesize is huge +material is wood', + ], + 'Full HTML message with head, title, body etc' => [ + 'input' => << + + HTML email test + + +

PHPMailer does HTML!

+

This is a test message written in HTML.
+ Go to + http://code.google.com/a/apache-extras.org/p/phpmailer/ + for new versions of PHPMailer.

+

Thank you!

+ + +EOT + , + // Note: be careful when updating & saving this file. The the trailing space on + // the line with "Go to " needs to be preserved! + 'expected' => << [ + 'input' => '\' ?>2', + 'expected' => '2', + ], + 'HTML with script tag' => [ + 'input' => 'loremipsum', + 'expected' => 'loremipsum', + ], + 'HTML with style tag with content. uppercase HTML tags' => [ + 'input' => "loremipsum", + 'expected' => 'loremipsum', + ], + 'HTML with script tag nested in style tag' => [ + 'input' => "loremipsum", + 'expected' => 'loremipsum', + ], + + 'Plain text which will turn into HTML script tag on decoding' => [ + 'input' => 'lorem<script>alert("xss")</script>ipsum', + 'expected' => 'loremipsum', + ], + 'HTML with a "less than" sign in the text' => [ + 'input' => '

Complex ' + . 'text <50% ' + . 'with ' + . 'tags

', + 'expected' => 'Complex text', + ], + 'HTML with an encoded "less than" sign in the text' => [ + 'input' => '

Complex ' + . 'text <50% ' + . 'with ' + . 'tags

', + 'expected' => 'Complex text <50% with tags', + ], + ]; + } + + /** + * Test the use of the `$callback` parameter to use a custom callback function or fall back to the + * native implementation. + * + * @dataProvider dataHtml2TextAdvanced + * + * @param string $input Arbitrary string, potentially containing HTML. + * @param callable $callback A callback function to use. + * @param string $expected The expected function return value. + */ + public function testHtml2TextAdvanced($input, $callback, $expected) + { + $result = $this->Mail->html2text($input, $callback); + self::assertSame($expected, $result); + } + + /** + * Data provider. + * + * Note: the callbacks used here are inherently unsafe, but that's not the point + * of the test. The point is to make sure that the function logic correctly chooses + * the use of the native conversion versus a provided callback function, not to test + * that the callback does the conversion correctly. + * + * @return array + */ + public function dataHtml2TextAdvanced() + { + return [ + 'No HTML, simple (unsafe) function name callback' => [ + 'input' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + 'callback' => 'strip_tags', + 'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + ], + 'Has HTML, simple (unsafe) closure callback' => [ + 'input' => 'Lorem
ipsum
dolor sit amet
,' + . ' consectetur elit.', + 'callback' => static function ($html) { + return strip_tags($html); + }, + 'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing() elit.', + ], + 'Has HTML, simple (unsafe) static class method callback' => [ + 'input' => 'Lorem
ipsum
dolor sit amet
,' + . ' consectetur elit.', + 'callback' => [__CLASS__, 'methodBasedCallback'], + 'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing() elit.', + ], + 'Has HTML, simple (unsafe) object method callback' => [ + 'input' => 'Lorem
ipsum
dolor sit amet
,' + . ' consectetur elit.', + 'callback' => [$this, 'methodBasedCallback'], + 'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing() elit.', + ], + 'Has HTML, explicitly use internal converter (callback = true)' => [ + 'input' => 'Lorem
ipsum
dolor sit amet
,' + . ' consectetur elit.', + 'callback' => true, + 'expected' => 'Lorem ipsum dolor sit amet, consectetur elit.', + ], + 'Has HTML, use internal converter due to passing invalid callback (function)' => [ + 'input' => 'Lorem
ipsum
dolor sit amet
,' + . ' consectetur elit.', + 'callback' => 'functionwhichdoesnotexist', + 'expected' => 'Lorem ipsum dolor sit amet, consectetur elit.', + ], + 'Has HTML, use internal converter due to passing invalid callback (static method)' => [ + 'input' => 'Lorem
ipsum
dolor sit amet
,' + . ' consectetur elit.', + 'callback' => ['claswhichdoesnotexist', 'foo'], + 'expected' => 'Lorem ipsum dolor sit amet, consectetur elit.', + ], + ]; + } + + /** + * Simplistic callback function. + */ + public static function methodBasedCallback($html) + { + return strip_tags($html); + } +}