File: /home/xedaptot/be.naniguide.com/tests/Unit/UrlServiceMoreTest.php
<?php
namespace Tests\Unit;
use Tests\TestCase;
use App\Model\TrackingDomain;
use DOMDocument;
use DomXpath;
use Exception;
use App\Services\UrlService;
class UrlServiceMoreTest extends TestCase
{
public const RELATIVE = 'images/sample.png';
public const ABSOLUTE = '/fake/sample.png';
public const PUBLIC = 'http://cdn.example.com/sample.png';
public const PROTOCOL_RELATIVE = '//cdn.example.com/sample.png';
public const SHARP = '#';
public const TRACKING_DOMAIN = 'track.example.com';
public const TRACKING_HOST = 'http://track.example.com/';
protected function setUp(): void
{
parent::setUp();
// Set base URL
config()->set('app.url', 'https://example.com');
// @important: route("named route") does not respect config(app.url)
// it uses the actual request url or localhost (in console)
// So, force it in test
$this->app['url']->forceRootUrl(config('app.url'));
}
public function getHtml()
{
return strtr("
<html>
<body>
<img name='relative' src='%relative'>
<img name='absolute' src='%absolute'>Click me</a>
<a name='public' href='%public'>
<a name='protocol_relative' href='%protocol_relative'>Click me</a>
<img name='sharp' src='%sharp'>
</body>
</html>
", [
'%relative' => self::RELATIVE,
'%absolute' => self::ABSOLUTE,
'%public' => self::PUBLIC,
'%protocol_relative' => self::PROTOCOL_RELATIVE,
'%sharp' => self::SHARP,
]);
}
public function getElementByAttribute($html, $attribute, $value)
{
$document = new DOMDocument();
$document->encoding = 'utf-8';
$document->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'), LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_HTML_NODEFDTD);
$xpath = new DomXpath($document);
$elements = $xpath->query("//*[@{$attribute}='$value']");
if (empty($elements)) {
throw new Exception("Cannot find element with '$attribute'='$value'");
}
if (sizeof($elements) > 1) {
throw new Exception("There are more than one elements with '$attribute'='$value'");
}
return $elements[0];
}
public function getElementAttributes($html)
{
$map = [
'img' => 'src',
'link' => 'href',
'a' => 'href',
];
$out = [];
$names = [ 'relative', 'absolute', 'public', 'protocol_relative', 'sharp' ];
foreach ($names as $name) {
$element = $this->getElementByAttribute($html, 'name', $name);
$out[$name] = $element->getAttribute($map[$element->nodeName]);
}
/* result looks like
Array
(
[relative] => http://localhost/images/sample.png
[absolute] => http://localhost/fake/sample.png
[public] => http://localhost/p/click?url=aHR0cDovL2Nkbi5leGFtcGxlLmNvbS9zYW1wbGUucG5n
[cdn] => http://localhost/p/click?url=aHR0cDovL2Nkbi5leGFtcGxlLmNvbS9zYW1wbGUucG5n
[sharp] => #
)
*/
return $out;
}
public function test_more_test_without_tracking_domain()
{
$html = app(UrlService::class)->transformHtmlUrls($this->getHtml(), $msgId = null, $trackingDomain = null);
$out = $this->getElementAttributes($html);
// Transformed
$this->assertEquals($out['relative'], 'https://example.com/images/sample.png');
$this->assertEquals($out['absolute'], 'https://example.com/fake/sample.png'); // unchanged
$this->assertEquals($out['public'], 'http://example.com/p/click?url=aHR0cDovL2Nkbi5leGFtcGxlLmNvbS9zYW1wbGUucG5n');
$this->assertEquals($out['protocol_relative'], 'http://example.com/p/click?url=Ly9jZG4uZXhhbXBsZS5jb20vc2FtcGxlLnBuZw'); // unchanged
$this->assertEquals($out['sharp'], self::SHARP); // unchanged
}
public function test_more_test_with_tracking_domain()
{
$domain = new TrackingDomain();
$domain->name = self::TRACKING_DOMAIN;
$domain->scheme = 'http';
$domain->verification_method = TrackingDomain::VERIFICATION_METHOD_HOST;
$html = app(UrlService::class)->transformHtmlUrls($this->getHtml(), $msgId = null, $domain);
$out = $this->getElementAttributes($html);
// Transformed
$this->assertEquals($out['relative'], 'http://track.example.com/?t=aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWFnZXMvc2FtcGxlLnBuZw');
$this->assertEquals($out['absolute'], 'http://track.example.com/?t=aHR0cHM6Ly9leGFtcGxlLmNvbS9mYWtlL3NhbXBsZS5wbmc');
$this->assertEquals($out['public'], 'http://track.example.com/?t=aHR0cDovL2V4YW1wbGUuY29tL3AvY2xpY2s_dXJsPWFIUjBjRG92TDJOa2JpNWxlR0Z0Y0d4bExtTnZiUzl6WVcxd2JHVXVjRzVu');
$this->assertEquals($out['protocol_relative'], 'http://track.example.com/?t=aHR0cDovL2V4YW1wbGUuY29tL3AvY2xpY2s_dXJsPUx5OWpaRzR1WlhoaGJYQnNaUzVqYjIwdmMyRnRjR3hsTG5CdVp3');
$this->assertEquals($out['sharp'], self::SHARP); // unchanged
}
}