2016-03-25 01:18:05 -07:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A helper class for Codeception (http://codeception.com/) that allows automated HTML5 Validation
|
|
|
|
* using the Nu Html Checker (http://validator.github.io/validator/) during acceptance testing.
|
|
|
|
* It uses local binaries and can therefore be run offline.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Requirements:
|
|
|
|
* =============
|
|
|
|
*
|
|
|
|
* - Codeception with WebDriver set up (PhpBrowser doesn't work)
|
|
|
|
* - java is installed locally
|
|
|
|
* - The vnu.jar is installed locally (download the .zip from https://github.com/validator/validator/releases,
|
|
|
|
* it contains the .jar file)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Installation:
|
|
|
|
* =============
|
|
|
|
*
|
|
|
|
* - Copy this file to _support/Helper/ in the codeception directory
|
|
|
|
* - Merge the following configuration to acceptance.suite.yml:
|
|
|
|
*
|
|
|
|
* modules:
|
|
|
|
* enabled:
|
|
|
|
* - \Helper\HTMLValidator
|
|
|
|
* config:
|
|
|
|
* \Helper\HTMLValidator:
|
|
|
|
* javaPath: /usr/bin/java
|
|
|
|
* vnuPath: /usr/local/bin/vnu.jar
|
2021-06-10 13:15:52 -07:00
|
|
|
*
|
2016-03-25 01:18:05 -07:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* Usage:
|
|
|
|
* ======
|
|
|
|
*
|
|
|
|
* Validate the HTML of the current page:
|
|
|
|
* $I->validateHTML();
|
|
|
|
*
|
|
|
|
* Validate the HTML of the current page, but ignore errors containing the string "Ignoreit":
|
|
|
|
* $I->validateHTML(["Ignoreme"]);
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
|
|
|
* @author Tobias Hößl <tobias@hoessl.eu>
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Helper;
|
|
|
|
|
|
|
|
use Codeception\TestCase;
|
|
|
|
|
|
|
|
class HTMLValidator extends \Codeception\Module
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @param string $html
|
|
|
|
* @return array
|
|
|
|
* @throws \Exception
|
|
|
|
*/
|
|
|
|
private function validateByVNU($html)
|
|
|
|
{
|
|
|
|
$javaPath = $this->_getConfig('javaPath');
|
2021-06-10 13:15:52 -07:00
|
|
|
if (! $javaPath) {
|
2016-03-25 01:18:05 -07:00
|
|
|
$javaPath = 'java';
|
|
|
|
}
|
|
|
|
$vnuPath = $this->_getConfig('vnuPath');
|
2021-06-10 13:15:52 -07:00
|
|
|
if (! $vnuPath) {
|
2016-03-25 01:18:05 -07:00
|
|
|
$vnuPath = '/usr/local/bin/vnu.jar';
|
|
|
|
}
|
|
|
|
|
2021-06-10 13:15:52 -07:00
|
|
|
$filename = DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.uniqid('html-validate').'.html';
|
2016-03-25 01:18:05 -07:00
|
|
|
file_put_contents($filename, $html);
|
2021-06-10 13:15:52 -07:00
|
|
|
exec($javaPath.' -Xss1024k -jar '.$vnuPath.' --format json '.$filename.' 2>&1', $return);
|
2016-03-25 01:18:05 -07:00
|
|
|
$data = json_decode($return[0], true);
|
2021-06-10 13:15:52 -07:00
|
|
|
if (! $data || ! isset($data['messages']) || ! is_array($data['messages'])) {
|
|
|
|
throw new \Exception('Invalid data returned from validation service: '.$return);
|
2016-03-25 01:18:05 -07:00
|
|
|
}
|
2021-06-10 13:15:52 -07:00
|
|
|
|
2016-03-25 01:18:05 -07:00
|
|
|
return $data['messages'];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
* @throws \Codeception\Exception\ModuleException
|
|
|
|
* @throws \Exception
|
|
|
|
*/
|
|
|
|
private function getPageSource()
|
|
|
|
{
|
2021-06-10 13:15:52 -07:00
|
|
|
if (! $this->hasModule('WebDriver')) {
|
2016-03-25 01:18:05 -07:00
|
|
|
throw new \Exception('This validator needs WebDriver to work');
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @var \Codeception\Module\WebDriver $webdriver */
|
|
|
|
$webdriver = $this->getModule('WebDriver');
|
2021-06-10 13:15:52 -07:00
|
|
|
|
2016-03-25 01:18:05 -07:00
|
|
|
return $webdriver->webDriver->getPageSource();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string[] $ignoreMessages
|
|
|
|
*/
|
|
|
|
public function validateHTML($ignoreMessages = [])
|
|
|
|
{
|
|
|
|
$source = $this->getPageSource();
|
|
|
|
try {
|
|
|
|
$messages = $this->validateByVNU($source);
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
$this->fail($e->getMessage());
|
2021-06-10 13:15:52 -07:00
|
|
|
|
2016-03-25 01:18:05 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
$failMessages = [];
|
2021-06-10 13:15:52 -07:00
|
|
|
$lines = explode("\n", $source);
|
2016-03-25 01:18:05 -07:00
|
|
|
foreach ($messages as $message) {
|
|
|
|
if ($message['type'] == 'error') {
|
2021-06-10 13:15:52 -07:00
|
|
|
$formattedMsg = '- Line '.$message['lastLine'].', column '.$message['lastColumn'].': '.
|
|
|
|
$message['message']."\n > ".$lines[$message['lastLine'] - 1];
|
|
|
|
$ignoring = false;
|
2016-03-25 01:18:05 -07:00
|
|
|
foreach ($ignoreMessages as $ignoreMessage) {
|
|
|
|
if (mb_stripos($formattedMsg, $ignoreMessage) !== false) {
|
|
|
|
$ignoring = true;
|
|
|
|
}
|
|
|
|
}
|
2021-06-10 13:15:52 -07:00
|
|
|
if (! $ignoring) {
|
2016-03-25 01:18:05 -07:00
|
|
|
$failMessages[] = $formattedMsg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (count($failMessages) > 0) {
|
2021-06-10 13:15:52 -07:00
|
|
|
\PHPUnit_Framework_Assert::fail('Invalid HTML: '."\n".implode("\n", $failMessages));
|
2016-03-25 01:18:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|