Skip to content

Commit

Permalink
Merge pull request #23 from roelofr/feature/html5-tests-and-support
Browse files Browse the repository at this point in the history
HTML5 and user-generated content support
  • Loading branch information
eduardokum authored Apr 13, 2020
2 parents c74662f + df8ab3f commit fff797e
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 67 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"illuminate/contracts": "^5.3 | ^6.0 | ^7.0",
"illuminate/support": "^5.3 | ^6.0 | ^7.0",
"illuminate/mail": "^5.3 | ^6.0 | ^7.0 | ^8.0",
"squizlabs/php_codesniffer": "^3.5"
"squizlabs/php_codesniffer": "^3.5",
"masterminds/html5": "^2.0"
},
"require-dev": {
"php": ">=7.0",
Expand Down
8 changes: 5 additions & 3 deletions src/Listeners/SwiftEmbedImages.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Eduardokum\LaravelMailAutoEmbed\Embedder\Base64Embedder;
use Eduardokum\LaravelMailAutoEmbed\Embedder\Embedder;
use Eduardokum\LaravelMailAutoEmbed\Models\EmbeddableEntity;
use Masterminds\HTML5;
use ReflectionClass;
use Swift_Events_SendEvent;
use Swift_Events_SendListener;
Expand Down Expand Up @@ -61,8 +62,9 @@ private function attachImages()
$body = $this->message->getBody();

// Parse document
$document = new DOMDocument();
if (!$document->loadHTML($body)) {
$parser = new HTML5();
$document = $parser->loadHTML($body);
if (!$document) {
// Cannot read
return;
}
Expand All @@ -71,7 +73,7 @@ private function attachImages()
$this->attachImagesToDom($document);

// Replace body
$this->message->setBody($document->saveHTML());
$this->message->setBody($parser->saveHTML($document));
}

/**
Expand Down
45 changes: 45 additions & 0 deletions tests/FormatTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Eduardokum\LaravelMailAutoEmbed\Tests;

use Eduardokum\LaravelMailAutoEmbed\Listeners\SwiftEmbedImages;
use Eduardokum\LaravelMailAutoEmbed\Tests\Traits\InteractsWithSwift;

/**
* Tests some scenarios, like HTML5 mails and mail with "invalid" HTML that mail clients
* like
*/
class FormatTest extends TestCase
{
use InteractsWithSwift;
private const HANDLE_CONFIG = [
'enabled' => true,
'method' => 'attachment'
];

/**
* @test
*/
public function testValidHtml5Message()
{
$message = $this->handleBeforeSendPerformedEvent('formats/html5-valid.html', self::HANDLE_CONFIG);

$this->assertEmailImageTags([
'url' => 'cid:',
'entity' => 'cid:',
], $message->getBody());
}

/**
* @test
*/
public function testUserGeneratedHtml5Message()
{
$message = $this->handleBeforeSendPerformedEvent('formats/html5-user-generated.html', self::HANDLE_CONFIG);

$this->assertEmailImageTags([
'url' => 'cid:',
'entity' => 'cid:',
], $message->getBody());
}
}
65 changes: 2 additions & 63 deletions tests/MailTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,11 @@
namespace Eduardokum\LaravelMailAutoEmbed\Tests;

use Eduardokum\LaravelMailAutoEmbed\Listeners\SwiftEmbedImages;
use Eduardokum\LaravelMailAutoEmbed\Tests\Traits\InteractsWithSwift;

class MailTest extends TestCase
{
/**
* @param string $htmlMessage
* @return \Swift_Message
*/
private function createSwiftMessage($htmlMessage)
{
$message = new \Swift_Message('test', $htmlMessage);

return $message;
}

/**
* @param \Swift_Message $message
* @return \Swift_Events_SendEvent
*/
private function createSwiftEvent(\Swift_Message $message)
{
$dispatcher = new \Swift_Events_SimpleEventDispatcher();
$transport = new \Swift_Transport_NullTransport($dispatcher);
$event = new \Swift_Events_SendEvent($transport, $message);

return $event;
}

/**
* @param string $libraryFile
* @param array $options
* @return \Swift_Message
*/
private function handleBeforeSendPerformedEvent($libraryFile, $options)
{
$htmlMessage = $this->getLibraryFile($libraryFile);
$message = $this->createSwiftMessage($htmlMessage);

$embedPlugin = new SwiftEmbedImages($options);
$embedPlugin->beforeSendPerformed($this->createSwiftEvent($message));

return $message;
}
use InteractsWithSwift;

/**
* @test
Expand Down Expand Up @@ -181,28 +144,4 @@ public function testDoesntHandleSendPerformedEvent()
$embedPlugin->sendPerformed($this->createSwiftEvent($message))
);
}

/**
* Check the body for image tags with the given keys as comment preceding them.
* @param array $expectations
* @param string $body
* @return void
*/
protected function assertEmailImageTags($expectations, $body)
{
foreach ($expectations as $comment => $src) {
// Gimmick of using a DOMDocument parser
$src = str_replace('\\', '%5C', \htmlspecialchars($src));

// Fix for PHPUnit <8.0
// phpcs:ignore Generic.Files.LineLength.TooLong
$method = \method_exists($this, 'assertStringContainsString') ? 'assertStringContainsString' : 'assertContains';

// Check if the string is contained within the string
$this->$method(
sprintf('<!-- %s --><img src="%s', $comment, $src),
$body
);
}
}
}
72 changes: 72 additions & 0 deletions tests/Traits/InteractsWithSwift.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Eduardokum\LaravelMailAutoEmbed\Tests\Traits;

use Eduardokum\LaravelMailAutoEmbed\Listeners\SwiftEmbedImages;

/**
* Shared code for creating messages and events
*/
trait InteractsWithSwift
{
/**
* @param string $htmlMessage
* @return \Swift_Message
*/
protected function createSwiftMessage($htmlMessage)
{
$message = new \Swift_Message('test', $htmlMessage);

return $message;
}

/**
* @param \Swift_Message $message
* @return \Swift_Events_SendEvent
*/
protected function createSwiftEvent(\Swift_Message $message)
{
$dispatcher = new \Swift_Events_SimpleEventDispatcher();
$transport = new \Swift_Transport_NullTransport($dispatcher);
$event = new \Swift_Events_SendEvent($transport, $message);

return $event;
}

/**
* @param string $libraryFile
* @param array $options
* @return \Swift_Message
*/
protected function handleBeforeSendPerformedEvent($libraryFile, $options)
{
$htmlMessage = $this->getLibraryFile($libraryFile);
$message = $this->createSwiftMessage($htmlMessage);

$embedPlugin = new SwiftEmbedImages($options);
$embedPlugin->beforeSendPerformed($this->createSwiftEvent($message));

return $message;
}

/**
* Check the body for image tags with the given keys as comment preceding them.
* @param array $expectations
* @param string $body
* @return void
*/
protected function assertEmailImageTags($expectations, $body)
{
foreach ($expectations as $comment => $src) {
// Fix for PHPUnit <8.0
// phpcs:ignore Generic.Files.LineLength.TooLong
$method = \method_exists($this, 'assertStringContainsString') ? 'assertStringContainsString' : 'assertContains';

// Check if the string is contained within the string
$this->$method(
sprintf('<!-- %s --><img src="%s', $comment, $src),
$body
);
}
}
}
72 changes: 72 additions & 0 deletions tests/lib/formats/html5-user-generated.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
</head>

<body>
<main>
<article>
<h1>Lorem Ipsum</h1>

<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla, dolorum assumenda aliquam blanditiis,
necessitatibus mollitia delectus sapiente amet earum minima qui non deserunt quidem, doloremque
architecto voluptatem eveniet illo aperiam.
</p>

<p>
<!-- Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup -->
<table>
<caption>Superheros and sidekicks</caption>
<colgroup>
<col>
<col span="2" class="batman">
<col span="2" class="flash">
</colgroup>
<tr>
<td> </td>
<th scope="col">Batman</th>
<th scope="col">Robin</th>
<th scope="col">The Flash</th>
<th scope="col">Kid Flash</th>
</tr>
<tr>
<th scope="row">Skill</th>
<td>Smarts</td>
<td>Dex, acrobat</td>
<td>Super speed</td>
<td>Super speed</td>
</tr>
</table>
</p>

<p>
<figure>
<!-- url --><img src="http://localhost/test.png" />
<caption>Lorem ipsum</caption>
</figure>
</p>
</article>

<aside>
<header>
<h1>Lorem Ipsum</h1>
</header>

<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempore cum, blanditiis a minima aspernatur
corporis pariatur, perferendis explicabo consectetur tenetur iste, fuga possimus corrupti dolorem
laudantium sapiente sunt error autem.
</p>

<figure>
<!-- entity --><img src="embed:Eduardokum\LaravelMailAutoEmbed\Tests\fixtures\PictureEntity:1" />
<caption>Lorem Ipsum</caption>
</figure>
</aside>
</main>
</body>

</html>
45 changes: 45 additions & 0 deletions tests/lib/formats/html5-valid.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
</head>

<body>
<main>
<article>
<h1>Lorem Ipsum</h1>

<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla, dolorum assumenda aliquam blanditiis,
necessitatibus mollitia delectus sapiente amet earum minima qui non deserunt quidem, doloremque
architecto voluptatem eveniet illo aperiam.
</p>


<figure>
<!-- url --><img src="http://localhost/test.png" />
<caption>Lorem ipsum</caption>
</figure>
</article>

<aside>
<header>
<h1>Lorem Ipsum</h1>
</header>

<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempore cum, blanditiis a minima aspernatur
corporis pariatur, perferendis explicabo consectetur tenetur iste, fuga possimus corrupti dolorem
laudantium sapiente sunt error autem.
</p>

<figure>
<!-- entity --><img src="embed:Eduardokum\LaravelMailAutoEmbed\Tests\fixtures\PictureEntity:1" />
<caption>Lorem Ipsum</caption>
</figure>
</aside>
</main>
</body>

</html>

0 comments on commit fff797e

Please sign in to comment.