Test the HTML with DOM parser and PHPUnit

When testing code that returns HTML in PHP, I’ve been doing lazy checks with regular expressions.

But I decided to run test with DOM, because I had been feeling uneasy.

 

Initially, I tried to use DOMDocument::loadHTML for it. But I got an error when the HTML contains the <section /> like following.

DOMDocument::loadHTML(): Tag section invalid in Entity, line: 1

So, I used following libraries and it looks good to me.

  • symfony/dom-crawler
  • symfony/css-selector

 

Install dependencies

To install those libraries, run composer command like following.

$ composer require symfony/dom-crawler symfony/css-selector --dev

 

Write a method that returns a DOM

First, prepare a method that returns DOM when passing HTML.

<?php

class Sample_Test extends UnitTestCase
{
    private function dom( $html )
    {
        $dom = new Symfony\Component\DomCrawler\Crawler();
        $dom->addHTMLContent( $html, "UTF-8" );
        return $dom;
    }
}

 

Write a test

test_html() is the test to check the HTML. It is checking how many nodes that matches the CSS selector.

<?php

class Sample_Test extends UnitTestCase
{
    public function test_html()
    {
        $result = do_something();
        $dom = $this->dom( $result );

        $this->assertSame( 1, count( $dom->filter( '.col-3' ) ) );
        $this->assertSame( 6, count( $dom->filter( 'section.item' ) ) );
    }

    private function dom( $html )
    {
        $dom = new Symfony\Component\DomCrawler\Crawler();
        $dom->addHTMLContent( $html, "UTF-8" );
        return $dom;
    }
}

do_something() is a function that returns HTML. I passed CSS selector to `$dom->filter()` and asserted the number of the nodes.

 

Test whether it is valid HTML

Unfortunately, dom-clawler can’t test whether it is valid HTML.

But, I guess we can check if we forget to close tag or so like following.

private function assertMaybeValidHTML( $html )
{
    $html = str_replace( 'section', 'div', $html );
    $html = str_replace( 'aside', 'div', $html );
    $dom = new DOMDocument();
    $dom->loadHTML( '<html><body>' . $html . '</body></html>' );
}

 


Leave a Reply

Your email address will not be published. Required fields are marked *