<?php
declare(strict_types=1);
namespace tests;
use DOMDocument;
use DOMNodeList;
use DOMXPath;
use Exception;
use PHPUnit\Framework\TestCase;
use WebPage;
class WebPageHtmlOutputTest extends TestCase
{
protected function createDomDocumentFromHtmlString(string $htmlString): DOMDocument
{
libxml_use_internal_errors(false);
libxml_clear_errors();
$domDocument = new DOMDocument();
$domDocument->strictErrorChecking = true;
if ($htmlString === '') {
$this->fail('HTML string is empty');
}
if (@$domDocument->loadHTML($htmlString, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_PEDANTIC) === false) {
$this->fail('unable to load HTML from string');
}
if (($lastError = libxml_get_last_error()) !== false) {
$this->fail('unable to load HTML from string: ' . $lastError->message);
}
return $domDocument;
}
protected function xPathQuery(DOMDocument $domDocument, string $xPathExpression): DOMNodeList
{
$DOMXPath = new DOMXPath($domDocument);
if (($result = @$DOMXPath->query($xPathExpression)) !== false) {
return $result;
}
$this->markTestSkipped('bad XPath expression?');
}
protected function assertWebPageMatchesXPath(WebPage $webPage, string $xPathExpression, string $message = ''): void
{
$domDocument = $this->createDomDocumentFromHtmlString($webPage->toHTML());
$domNodeList = $this->xPathQuery($domDocument, $xPathExpression);
$this->assertCount(1, $domNodeList, $message);
}
public function testBasicHtmlStructure()
{
$webPage = new WebPage('title');
$this->assertWebPageMatchesXPath($webPage, '/html', 'html tag not found');
$this->assertWebPageMatchesXPath($webPage, '/html[contains(@lang, "fr")]', 'html language attribute not found');
$this->assertWebPageMatchesXPath($webPage, '/html/head', 'head tag not found');
$this->assertWebPageMatchesXPath($webPage, '/html/head/meta[contains(translate(@charset, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "utf-8")]', 'meta tag with charset attribute not found');
$this->assertWebPageMatchesXPath($webPage, '/html/head/meta[contains(@name, "viewport")]', 'meta tag with viewport attribute not found');
$this->assertWebPageMatchesXPath($webPage, '/html/head/title', 'title tag not found');
$this->assertWebPageMatchesXPath($webPage, '/html/body', 'body tag not found');
}
public function testTitleAsConstructorParameter()
{
$title = 'test / Title';
$webPage = new WebPage($title);
$this->assertWebPageMatchesXPath($webPage, '/html/head/title[normalize-space(text()) = "' . $title . '"]', 'title set in constructor not found in head');
}
public function testSetTitle()
{
$webPage = new WebPage();
$title = 'test / Title';
$webPage->setTitle($title);
$this->assertWebPageMatchesXPath($webPage, '/html/head/title[normalize-space(text()) = "' . $title . '"]', 'title set with setTitle() not found in head');
}
public function testAppendToHead()
{
$webPage = new WebPage('title');
$webPage->appendToHead('<meta http-equiv="refresh" content="30">');
$this->assertWebPageMatchesXPath($webPage, '/html/head/meta[@http-equiv = "refresh"]', 'content set with appendToHead() not found in head');
}
public function testAppendCss()
{
$webPage = new WebPage('title');
$css = '#css { color: red;}';
$webPage->appendCss($css);
$this->assertWebPageMatchesXPath($webPage, '/html/head/style[normalize-space(text()) = "' . $css . '"]', 'content set with appendCss() not found in head');
}
public function testAppendCssUrl()
{
$webPage = new WebPage('title');
$url = 'http://example.com/css/style.css';
$webPage->appendCssUrl($url);
$this->assertWebPageMatchesXPath($webPage, '/html/head/link[@href = "' . $url . '"]', 'url set with appendCssUrl() not found in link tag');
$this->assertWebPageMatchesXPath($webPage, '/html/head/link[@href = "' . $url . '" and @rel = "stylesheet"]', 'url set with appendCssUrl() not found in link tag with attribute rel');
}
public function testAppendJs()
{
$webPage = new WebPage('title');
$js = "window.alert('hello world!');";
$webPage->appendJs($js);
$this->assertWebPageMatchesXPath($webPage, '/html/head/script[normalize-space(text()) = "' . $js . '"]', 'content set with appendJs() not found in head');
}
public function testAppendJsUrl()
{
$webPage = new WebPage('title');
$url = 'http://example.com/js/script.js';
$webPage->appendJsUrl($url);
$this->assertWebPageMatchesXPath($webPage, '/html/head/script[@src = "' . $url . '"]', 'url set with appendJs() not found in script tag');
}
public function testAppendContent()
{
$webPage = new WebPage('title');
$webPage->appendContent('<div class="content">Hello</div>');
$webPage->appendContent('<div id="world">World!</div>');
$this->assertWebPageMatchesXPath($webPage, '/html/body/div[@class = "content" and text() = "Hello"]', 'content set with appendContent() not found in body');
$this->assertWebPageMatchesXPath($webPage, '/html/body/div[@id = "world" and text() = "World!"]', 'content set with appendContent() not found in body');
$this->assertWebPageMatchesXPath($webPage, '/html/body/div[@class = "content"]/following-sibling::div[@id = "world"]', 'content set with appendContent() not properly ordered');
}
}