Last active
May 24, 2017 07:52
-
-
Save CatoTH/51accb6102394e3b8312 to your computer and use it in GitHub Desktop.
A helper class for Codeception that allows automated HTML5 Validation using the Nu Html Checker during acceptance testing. It uses local binaries and can therefore be run offline.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 | |
* | |
* | |
* | |
* 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'); | |
if (!$javaPath) { | |
$javaPath = 'java'; | |
} | |
$vnuPath = $this->_getConfig('vnuPath'); | |
if (!$vnuPath) { | |
$vnuPath = '/usr/local/bin/vnu.jar'; | |
} | |
$filename = DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . uniqid('html-validate') . '.html'; | |
file_put_contents($filename, $html); | |
exec($javaPath . " -Xss1024k -jar " . $vnuPath . " --format json " . $filename . " 2>&1", $return); | |
$data = json_decode($return[0], true); | |
if (!$data || !isset($data['messages']) || !is_array($data['messages'])) { | |
throw new \Exception('Invalid data returned from validation service: ' . $return); | |
} | |
return $data['messages']; | |
} | |
/** | |
* @return string | |
* @throws \Codeception\Exception\ModuleException | |
* @throws \Exception | |
*/ | |
private function getPageSource() | |
{ | |
if (!$this->hasModule('WebDriver')) { | |
throw new \Exception('This validator needs WebDriver to work'); | |
} | |
/** @var \Codeception\Module\WebDriver $webdriver */ | |
$webdriver = $this->getModule('WebDriver'); | |
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()); | |
return; | |
} | |
$failMessages = []; | |
$lines = explode("\n", $source); | |
foreach ($messages as $message) { | |
if ($message['type'] == 'error') { | |
$formattedMsg = '- Line ' . $message['lastLine'] . ', column ' . $message['lastColumn'] . ': ' . | |
$message['message'] . "\n > " . $lines[$message['lastLine'] - 1]; | |
$ignoring = false; | |
foreach ($ignoreMessages as $ignoreMessage) { | |
if (mb_stripos($formattedMsg, $ignoreMessage) !== false) { | |
$ignoring = true; | |
} | |
} | |
if (!$ignoring) { | |
$failMessages[] = $formattedMsg; | |
} | |
} | |
} | |
if (count($failMessages) > 0) { | |
\PHPUnit_Framework_Assert::fail('Invalid HTML: ' . "\n" . implode("\n", $failMessages)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I made a standalone module which doesn't require a local validator. You may be interested in checking it out.