diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..859df2a1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +Changelog +========= + +2.x +------------ + +- Removed HTML5 validation diff --git a/ExampleTests/ExampleHtml5Test.php b/ExampleTests/ExampleHtml5Test.php deleted file mode 100644 index 51ca0cf1..00000000 --- a/ExampleTests/ExampleHtml5Test.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Liip\FooBundle\Tests; - -use Liip\FunctionalTestBundle\Controller\DefaultController; -use Liip\FunctionalTestBundle\Test\Html5WebTestCase; - -/** - * @author Lukas Smith - * @author Daniel Barsotti - */ -class ExampleHtml5Test extends Html5WebTestCase -{ - protected $kernelDir = '/app/main'; - - public function testIndex() - { - $content = $this->fetchContent('/'); - $this->assertIsValidHtml5($content, '/'); - } - - public function testBasicAuthentication() - { - $this->loadFixtures(['Liip\FooBundle\Tests\Fixtures\LoadUserData']); - - $content = $this->fetchContent('/', 'GET', true); - $this->assertSame('Hello foo!', $content); - } - - public function testGenerateInMissingDir() - { - $this->runCommand('main:generate-html', ['output-dir' => './doesntexist']); - $this->assertFileNotExists($this->dir.'/index.html'); - } - - public function testIndexAction() - { - $view = $this->getServiceMockBuilder('FooView')->getMock(); - - $view->expects($this->once()) - ->method('setTemplate') - ->with('FooBundle:Default:index.twig') - ->will($this->returnValue(null)) - ; - - $view->expects($this->once()) - ->method('handle') - ->with() - ->will($this->returnValue('success')) - ; - - $controller = new DefaultController($view); - - $this->assertSame('success', $controller->indexAction()); - } -} diff --git a/README.md b/README.md index 65ceb9b7..64b646c3 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,12 @@ Table of contents: +- [changelog](CHANGELOG.md) - [Installation](#installation) - [Basic usage and methods](#basic-usage) - [Command tests](#command-tests) - [Database and fixtures](#database-tests) - [Create an already logged client](#create-an-already-logged-client) -- [HTML5 Validator](#html5-validator) - [Query Counter](#query-counter) - [Caveats](#caveats) - [paratest](paratest.md) @@ -22,7 +22,7 @@ Introduction ============ This Bundle provides base classes for functional tests to assist in setting up -test-databases, loading fixtures and HTML5 validation. It also provides a DI +test-databases and loading fixtures. It also provides a DI aware mock builder for unit tests. Installation @@ -642,98 +642,6 @@ security: For more details, you can check the implementation of `WebTestCase` in that bundle. -HTML5 Validator ---------------- - -The online validator: http://validator.nu/ -The documentation: http://about.validator.nu/ -Documentation about the web service: https://github.com/validator/validator/wiki/Service:-HTTP-interface - -Dependencies ------------- - -To run the validator you require the following dependencies: - - * A java JDK 5 or later - * Python - * SVN - * Mercurial - -Note: The script wants to see a Sun-compatible jar executable. Debian fastjar will not work. - -Compilation and Execution -------------------------- - -Before starting: - - * Set the `JAVA_HOME` environment variable to the root of the installed JDK - * Add the location of `javac` to your `PATH` (`$JAVA_HOME/bin`). - * Alternatively you can use the `--javac=/usr/bin/javac` parameter of the `build.py` script. - -Then: - -```sh -$ mkdir checker; cd checker -$ git clone https://github.com/validator/validator.git -$ cd validator -$ python ./build/build.py all; python ./build/build.py all -``` - -Note: Yes, the last line is there twice intentionally. Running the script twice tends to fix -a `ClassCastException` on the first run. - -Note: If at some point for some reason the compilation fails and you are forced to re-run it, -it may be necessary to manually remove the htmlparser directory from your disk (the compilation -process will complain about that). - -This will download the necessary components, compile the validator and run it. This will require -about 10 minutes on the first run. - -Once the validator is executed it can be reached at http://localhost:8888/ Further instructions on how to build the validator can be found at http://validator.github.io/validator/#build-instructions. - -Execution ---------- - -Once the validator has been compiled, it can be run with the following command: - -```sh -cd checker -python build/build.py run -``` - -Using the Validator in Functional Tests ---------------------------------------- - -The `Liip\FunctionalTestBundle\Test\Html5WebTestCase` class allows to write -functional tests that validate content against the HTML5 validator. In order to -work the validator service must be running on the machine where the tests are -executed. - -This class provides the following testing methods: - - * **validateHtml5**: This runs a validation on the provided content and returns - the full messages of the validation service (including warnings and - information). This method is not meant as a test method but rather as a - helper to access the validator service. Internally the test method below will - use this helper to access the validation service. - - * **assertIsValidHtml5**: This will validate the provided content. If the - validation succeeds, execution silently continues, otherwise the calling test - will fail and display a list of validation errors. - - * **assertIsValidHtml5Snippet**: This will validate an HTML5 snippets (i.e. not - a full HTML5 document) by wrapping it into an HTML5 document. If the - validation succeeds, execution silently continues, otherwise the calling test - will fail and display a list of validation errors. - - * **assertIsValidHtml5AjaxResponse**: This will validate an AJAX response in a - specific format (probably not generic enough). If the validation succeeds, - execution silently continues, otherwise the calling test will fail and - display a list of validation errors. - - * **setHtml5Wrapper**: Allow to change the default HTML5 code that is used as a - wrapper around snippets to validate - Query Counter ============= diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 5106c927..da54a959 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -50,22 +50,6 @@ public function getConfigTreeBuilder() ->end() ->end() ->end() - ->arrayNode('html5validation') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('url') - ->defaultValue('https://validator.nu/') - ->end() - ->arrayNode('ignores') - ->prototype('scalar')->end() - ->defaultValue([]) - ->end() - ->arrayNode('ignores_extract') - ->prototype('scalar')->end() - ->defaultValue([]) - ->end() - ->end() - ->end() ->arrayNode('paratest') ->addDefaultsIfNotSet() ->children() diff --git a/src/Test/Html5WebTestCase.php b/src/Test/Html5WebTestCase.php deleted file mode 100644 index 232d743e..00000000 --- a/src/Test/Html5WebTestCase.php +++ /dev/null @@ -1,212 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Liip\FunctionalTestBundle\Test; - -/** - * @author Daniel Barsotti - * - * The on-line validator: https://validator.nu/ - * The documentation: https://about.validator.nu/ - * Documentation about the web service: https://github.com/validator/validator/wiki/Service:-HTTP-interface - */ -abstract class Html5WebTestCase extends WebTestCase -{ - // can't be empty: - // - // HTML5 validation failed: - // Line 5: Element “title” must not be empty. - protected $html5Wrapper = <<<'HTML' -<!DOCTYPE html> -<html> -<head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - <title>HTML5 - - -<> - - -HTML; - - protected $validationServiceAvailable = false; - - public function __construct($name = null, array $data = [], $dataName = '') - { - parent::__construct($name, $data, $dataName); - - $this->validationServiceAvailable = $this->isValidationServiceAvailable(); - } - - /** - * Check if the HTML5 validation service is available. - */ - public function isValidationServiceAvailable() - { - $validationUrl = $this->getHtml5ValidatorServiceUrl(); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $validationUrl); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - $res = curl_exec($ch); - - curl_close($ch); - - return false !== $res; - } - - public function getValidationServiceAvailable() - { - return $this->validationServiceAvailable; - } - - /** - * Get the URL of the HTML5 validation service from the config. - * - * @return string - */ - protected function getHtml5ValidatorServiceUrl() - { - return $this->getContainer()->getParameter('liip_functional_test.html5validation.url'); - } - - /** - * Allows a subclass to set a custom HTML5 wrapper to test validity of HTML snippets. - * The $wrapper may contain valid HTML5 code + the <> placeholder. - * This placeholder will be replaced by the tested snippet before validation. - * - * @param string $wrapper The custom HTML5 wrapper - */ - protected function setHtml5Wrapper($wrapper) - { - $this->html5Wrapper = $wrapper; - } - - /** - * Run the HTML5 validation on the content and returns the results as an array. - * - * @param string $content The HTML content to validate - * - * @return array|false - */ - public function validateHtml5($content) - { - $validationUrl = $this->getHtml5ValidatorServiceUrl(); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $validationUrl); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, [ - 'out' => 'json', - 'parser' => 'html5', - 'content' => $content, - ]); - - $res = curl_exec($ch); - - curl_close($ch); - - if ($res) { - return json_decode($res); - } - - // The HTML5 validation service could not be reached - return false; - } - - /** - * Assert the content passed is valid HTML5. If yes, the function silently - * runs, and if no it will make the test fail and display a summary of the - * validation errors along with the line number where they occured. - * - * Warning: this function is completely agnostic about what it is actually - * validating, thus it cannot display the validated URL. It is up to the - * test programmer to use the $message parameter to add information about the - * current URL. When the test fails, the message will be displayed in addition - * to the error summary. - * - * @param string $content The content to validate - * @param string $message An additional message to display when the test fails - */ - public function assertIsValidHtml5($content, $message = '') - { - if (!$this->getValidationServiceAvailable()) { - return $this->skipTestWithInvalidService(); - } - - $res = $this->validateHtml5($content); - // json_decode returned null if the validator service didn't - // return JSON - if ((null === $res) || (false === $res) || (false === $res->messages)) { - return $this->skipTestWithInvalidService(); - } - - $err_count = 0; - $err_msg = 'HTML5 validation failed'; - if ('' !== $message) { - $err_msg .= " [$message]"; - } - $err_msg .= ":\n"; - - $ignores = $this->getContainer()->getParameter('liip_functional_test.html5validation.ignores'); - /* - * unfortunately, the bamboo html5 validator.nu gives back an empty "message" about the error with brightcove object, but we have to ignore the error - * if our local validator.nu instance is fixed, this stuff should go away - */ - $ignores_extract = $this->getContainer()->getParameter('liip_functional_test.html5validation.ignores_extract'); - - foreach ($res->messages as $row) { - if ('error' === $row->type) { - foreach ($ignores as $ignore) { - if (preg_match($ignore, $row->message)) { - continue 2; - } - } - foreach ($ignores_extract as $ignore_extract) { - if (preg_match($ignore_extract, $row->extract)) { - continue 2; - } - } - - ++$err_count; - if (empty($row->message)) { - $err_msg .= " Line {$row->lastLine}: Empty error message about {$row->extract}\n"; - } else { - $err_msg .= " Line {$row->lastLine}: {$row->message}\n"; - } - } - } - $this->assertTrue(0 === $err_count, $err_msg); - } - - /** - * Assert the content passed is a valid HTML5 snippets (i.e. that the content, - * wrapped into a basic HTML5 document body will pass the validation). - * - * @param string $snippet The snippet to validate - * @param string $message An additional message to display when the test fails - */ - public function assertIsValidHtml5Snippet($snippet, $message = '') - { - $content = str_replace('<>', $snippet, $this->html5Wrapper); - $this->assertIsValidHtml5($content, $message); - } - - /** - * Marks test as skipped with validation server error message. - */ - protected function skipTestWithInvalidService() - { - $url = $this->getHtml5ValidatorServiceUrl(); - $this->markTestSkipped("HTML5 Validator service not found at '$url' !"); - } -} diff --git a/tests/AppConfig/config.yml b/tests/AppConfig/config.yml index 45bf2f3b..a5299399 100644 --- a/tests/AppConfig/config.yml +++ b/tests/AppConfig/config.yml @@ -15,12 +15,6 @@ liip_functional_test: authentication: username: "foobar" password: "12341234" - html5validation: - url: http://example.com/ - ignores: ['ignore_1', 'ignore_2'] - ignores_extract: - - 'ignore_extract_1' - - 'ignore_extract_2' paratest: process: 3 phpunit: 'vendor/bin/phpunit' diff --git a/tests/DependencyInjection/ConfigurationConfigTest.php b/tests/DependencyInjection/ConfigurationConfigTest.php index 01b5c33b..c2d1b63f 100644 --- a/tests/DependencyInjection/ConfigurationConfigTest.php +++ b/tests/DependencyInjection/ConfigurationConfigTest.php @@ -43,15 +43,6 @@ public function parametersProvider() ['query.max_query_count', 1], ['authentication.username', 'foobar'], ['authentication.password', '12341234'], - ['html5validation.url', 'http://example.com/'], - ['html5validation.ignores', [ - 'ignore_1', - 'ignore_2', - ]], - ['html5validation.ignores_extract', [ - 'ignore_extract_1', - 'ignore_extract_2', - ]], ['paratest.process', 3], ['paratest.phpunit', 'vendor/bin/phpunit'], ]; diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index a0cb37c1..65cfd98a 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -59,9 +59,6 @@ public function parametersProvider() ['query.max_query_count', null], ['authentication.username', ''], ['authentication.password', ''], - ['html5validation.url', 'https://validator.nu/'], - ['html5validation.ignores', []], - ['html5validation.ignores_extract', []], ['paratest.process', 5], ['paratest.phpunit', './bin/phpunit'], ]; diff --git a/tests/Test/Html5WebTestCaseMockTest.php b/tests/Test/Html5WebTestCaseMockTest.php deleted file mode 100644 index 7b25e1e5..00000000 --- a/tests/Test/Html5WebTestCaseMockTest.php +++ /dev/null @@ -1,303 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Liip\FunctionalTestBundle\Tests\Test; - -/* Used by annotations */ -use Liip\FunctionalTestBundle\Test\Html5WebTestCase; -use PHPUnit\Framework\AssertionFailedError; -use PHPUnit\Framework\SkippedTestError; -use PHPUnit\Framework\TestCase; - -/** - * Test Html5WebTestCase class with mocked methods instead of inheriting from - * the class. - * - * Mocked methods are tested in Html5WebTestCaseTest. - * - * try/catch blocks are based on PHPUnit internal tests: - * - * @see https://github.com/sebastianbergmann/phpunit/blob/b12b9c37e382c096b93c3f26e7395775f59a5eea/tests/Framework/AssertTest.php#L3560-L3574 - */ -class Html5WebTestCaseMockTest extends TestCase -{ - /** - * @param array $methods - * - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getMockedClass($methods = []) - { - return $this->getMockBuilder('Liip\FunctionalTestBundle\Test\Html5WebTestCase') - ->disableOriginalConstructor() - ->setMethods($methods) - ->getMock(); - } - - /** - * @param \PHPUnit_Framework_MockObject_MockObject $mock - * @param string $function - * @param mixed $return - */ - private function addMethod($mock, $function, $return) - { - $mock->expects($this->once()) - ->method($function) - ->willReturn($return); - } - - private function addMethodGetHtml5ValidatorServiceUrl($mock, $return) - { - $this->addMethod($mock, 'getHtml5ValidatorServiceUrl', $return); - } - - private function addMethodGetValidationServiceAvailable($mock, $return) - { - $this->addMethod($mock, 'getValidationServiceAvailable', $return); - } - - private function addMethodValidateHtml5($mock, $return) - { - $this->addMethod($mock, 'validateHtml5', $return); - } - - public function testIsValidationServiceAvailable() - { - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass(['getHtml5ValidatorServiceUrl']); - - $this->addMethodGetHtml5ValidatorServiceUrl($mock, null); - - // The "null" URL for validator service will return an error. - $this->assertFalse( - $mock->isValidationServiceAvailable() - ); - } - - public function testValidateHtml5() - { - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass(['getHtml5ValidatorServiceUrl']); - - $this->addMethodGetHtml5ValidatorServiceUrl($mock, null); - - $this->assertFalse( - $mock->validateHtml5('') - ); - } - - public function testAssertIsValidHtml5() - { - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass( - ['getValidationServiceAvailable', 'validateHtml5'] - ); - - $this->addMethodGetValidationServiceAvailable($mock, true); - - // Return successful result from validator. - $res = new \ArrayObject(); - $res->messages = []; - - $this->addMethodValidateHtml5($mock, $res); - - $mock->assertIsValidHtml5(''); - } - - public function testAssertIsValidHtml5Fail() - { - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass( - ['getValidationServiceAvailable', 'validateHtml5'] - ); - - $this->addMethodGetValidationServiceAvailable($mock, true); - - // Return error messages from validator. - $res = new \ArrayObject(); - $res->messages = [ - (object) ['type' => 'error', 'message' => 'foo', 'lastLine' => 1], - ]; - - $this->addMethodValidateHtml5($mock, $res); - - $string = <<<'EOF' -HTML5 validation failed: - Line 1: foo - -Failed asserting that false is true. -EOF; - - try { - $mock->assertIsValidHtml5('baz'); - } catch (AssertionFailedError $e) { - $this->assertSame($string, $e->getMessage()); - - return; - } - - $this->fail('Test failed.'); - } - - public function testAssertIsValidHtml5FailWithIgnores() - { - /* @see http://gianarb.it/blog/symfony-unit-test-controller-with-phpunit#expectations */ - /** @var \Symfony\Component\DependencyInjection\ContainerInterface $container */ - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface') - ->getMock(); - $container->expects($this->any()) - ->method('getParameter') - ->will($this->onConsecutiveCalls(['#foo#'], ['#bar#'])); - - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass( - [ - 'getValidationServiceAvailable', - 'validateHtml5', - 'getContainer', - ] - ); - - $this->addMethodGetValidationServiceAvailable($mock, true); - - // Return error messages from validator. - $res = new \ArrayObject(); - $res->messages = [ - (object) ['type' => 'error', 'message' => 'no', 'lastLine' => 1, 'extract' => 'no'], - (object) ['type' => 'error', 'message' => '', 'lastLine' => 2, 'extract' => 'no'], - // $ignores and $ignores_extract arrays. - (object) ['type' => 'error', 'message' => 'foo', 'lastLine' => 3], - (object) ['type' => 'error', 'message' => 'bar', 'lastLine' => 4, 'extract' => 'bar'], - ]; - - $this->addMethodValidateHtml5($mock, $res); - - $mock->expects($this->any()) - ->method('getContainer') - ->willReturn($container); - - $string = <<<'EOF' -HTML5 validation failed [baz]: - Line 1: no - Line 2: Empty error message about no - -Failed asserting that false is true. -EOF; - - try { - $mock->assertIsValidHtml5('', 'baz'); - } catch (AssertionFailedError $e) { - $this->assertSame($string, $e->getMessage()); - - return; - } - - $this->fail('Test failed.'); - } - - public function testAssertIsValidHtml5SkipTestServiceNotAvailable() - { - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass( - ['getValidationServiceAvailable', 'getHtml5ValidatorServiceUrl'] - ); - - $this->addMethodGetValidationServiceAvailable($mock, false); - - $this->addMethodGetHtml5ValidatorServiceUrl($mock, 'http://localhost/'); - - try { - $mock->assertIsValidHtml5(''); - } catch (SkippedTestError $e) { - $this->assertSame( - 'HTML5 Validator service not found at \'http://localhost/\' !', - $e->getMessage() - ); - - return; - } - - $this->fail('Test failed.'); - } - - public function testAssertIsValidHtml5SkipTestServiceReturnFalse() - { - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass( - [ - 'getValidationServiceAvailable', - 'getHtml5ValidatorServiceUrl', - 'validateHtml5', - ] - ); - - $this->addMethodGetValidationServiceAvailable($mock, true); - - $this->addMethodGetHtml5ValidatorServiceUrl($mock, 'http://localhost/'); - - // This will force the test to skip. - $this->addMethodValidateHtml5($mock, false); - - try { - $mock->assertIsValidHtml5(''); - } catch (SkippedTestError $e) { - $this->assertSame( - 'HTML5 Validator service not found at \'http://localhost/\' !', - $e->getMessage() - ); - - return; - } - - $this->fail('Test failed.'); - } - - public function testAssertIsValidHtml5Snippet() - { - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass( - ['getValidationServiceAvailable', 'validateHtml5'] - ); - - $this->addMethodGetValidationServiceAvailable($mock, true); - - // Return successful result from validator. - $res = new \ArrayObject(); - $res->messages = []; - - $this->addMethodValidateHtml5($mock, $res); - - $mock->assertIsValidHtml5Snippet(''); - } - - /** - * @expectedException \PHPUnit\Framework\AssertionFailedError - */ - public function testAssertIsValidHtml5SnippetFail() - { - /** @var Html5WebTestCase $mock */ - $mock = $this->getMockedClass( - ['getValidationServiceAvailable', 'validateHtml5'] - ); - - $this->addMethodGetValidationServiceAvailable($mock, true); - - // Return error messages from validator. - $res = new \ArrayObject(); - $res->messages = [ - (object) ['type' => 'error', 'message' => 'foo', 'lastLine' => 1], - ]; - - $this->addMethodValidateHtml5($mock, $res); - - $mock->assertIsValidHtml5Snippet('

Hello World!

'); - } -} diff --git a/tests/Test/Html5WebTestCaseTest.php b/tests/Test/Html5WebTestCaseTest.php deleted file mode 100644 index 71447b3c..00000000 --- a/tests/Test/Html5WebTestCaseTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Liip\FunctionalTestBundle\Tests\Test; - -use Liip\FunctionalTestBundle\Test\Html5WebTestCase; - -/** - * Test methods that are mocked in Html5WebTestCaseMockTest. - */ -class Html5WebTestCaseTest extends Html5WebTestCase -{ - public function __construct() - { - parent::__construct('', [], ''); - } - - public function testGetValidationServiceAvailable() - { - $this->assertInternalType( - 'bool', - $this->getValidationServiceAvailable() - ); - } - - public function testGetHtml5ValidatorServiceUrl() - { - $this->assertSame( - 'https://validator.nu/', - $this->getHtml5ValidatorServiceUrl() - ); - } - - public function testSetHtml5Wrapper() - { - $this->setHtml5Wrapper('foo bar'); - - $this->assertSame( - 'foo bar', - $this->html5Wrapper - ); - } -}