1

I've been using Laravel and Symfony for a while and I'm very happy with the testing with DomCrawler. Now at work I'm using CakePHP 3, and I'm not comfortable with the integration testing system, it's like this:

$this->get('/miweb/add-page/rates/2');
$this->assertResponseOk();
$this->assertResponseContains( 'precio' );

$this->post('/miweb/add-page/rates/2', $data);
$this->assertResponseContains( '30€' );
$this->assertResponseContains( '90€' );

I've been looking for a way to integrate DomCrawler in the testing system, so that I could use $crawler->filter('body > p');, $form->submit() and all the functionality, but I've accomplished nothing. Has anyone done this? Is it possible?

What I've done so far is this:

<?php
class BaseIntegrationTestCase extends IntegrationTestCase
{
    public function get( $url )
    {
        $result = parent::get($url);
        $crawler = new Crawler();
        $crawler->addContent($this->_response);
        return $crawler;
    }

    public function post($url, $data = [])
    {
        $result = parent::post($url, $data);
        $crawler = new Crawler();
        $crawler->addContent($this->_response);
        return $crawler;
    }
}

And then extend my Class in the tests, but it doesn't work...

SkarXa
  • 1,184
  • 1
  • 12
  • 24
  • I've tried to hook it so post() and get() return a crawler instance, but I cant get it to do the following requests, like $crawler->form()->submit() – SkarXa Sep 11 '15 at 08:08
  • @AD7six Edited, it looks to me like the issue is that the crawler has not a base URL, whenever I try to call form() I get an error `Current URI must be an absolute URL ("")` – SkarXa Sep 11 '15 at 08:54
  • Well you're getting closer the above comment _should be in the question_. I have to assume that [domcrawler's docs](https://github.com/symfony/DomCrawler/blob/master/README.md) are accurate and you're familiar with what you're trying to use. But that doesn't really seem to be the case since the only way that works if by [passing the uri as a constructor argument](https://github.com/symfony/DomCrawler/blob/master/Crawler.php#L54). Reading the source of Cralwer/Form you can probably find a solution. As I'm not familiar with domcrawler my input ends here =). – AD7six Sep 11 '15 at 09:06
  • One suggestion: _try_ to use CakePHP's standard testing tools. If you know how to use both you can make an objective decision as to how to continue. Here, it'd be handy to see a side-by-side comparison of how to do what you're trying to do with just CakePHP - compared to how you want it to work i.e. "I'm doing this in CakePHP right now _and it works_, I want to use domcrawler, I'm doing this and it doesn't work etc.". It sounds like right now you just want to use what you're familiar with without knowing what the alternative is - nothing necessarily wrong with that, but there might be. – AD7six Sep 11 '15 at 09:09
  • I have a lot of tests already done using the Cake 3 tools, what I like of them is that they are pretty simple, BUT doing them with DomCrawler makes a test more complete, it checks that the forms are fillable and are where they should, not just passing an array of post data to the controller but ACTUALLY submitting the form – SkarXa Sep 11 '15 at 09:18
  • 1
    I've modified my class to pass http://localhost to domcrawler constructor, I'll test it a little and answer my own question if it works – SkarXa Sep 11 '15 at 09:24

1 Answers1

1

Finally I've put my class to work I'll leave it here just in case.

The main issue was that DomCrawler needs an absolute URI, but if you pass that URI to CakePHP it won't work very well, so here is my class

<?php
namespace App\Test\TestCase\Controller;

use Cake\TestSuite\IntegrationTestCase;

use Symfony\Component\DomCrawler\Crawler;

class BaseIntegrationTestCase extends IntegrationTestCase
{
    public function get( $url )
    {
        $result = parent::get($url);
        $url = (stripos($url, 'http://') !== false) ? $url : 'http://localhost' . $url ;
        $crawler = new Crawler( null, $url );
        $crawler->addContent($this->_response);
        return $crawler;
    }

    public function post($url, $data = [])
    {
        $parsed = parse_url($url);
        $result = parent::post($parsed['path'], $data);
        $url = (stripos($url, 'http://') !== false) ? $url : 'http://localhost' . $url ;
        $crawler = new Crawler( null, $url );
        $crawler->addContent($this->_response);
        return $crawler;
    }

    public function submit( \Symfony\Component\DomCrawler\Form $form )
    {
        return $this->post( $form->getUri(), $form->getPhpValues() );
    }
}

Usage example:

<?php
use App\Test\TestCase\Controller\BaseIntegrationTestCase;

class AdminsControllerTest extends BaseIntegrationTestCase
{
    function testSomething()
    {
                $data = ['hours'  => array (
                                [
                                'day' => 'Lunes',
                                'from' =>'10',
                                'to' => '22'
                                ],
                                [
                                'day' => 'Martes',
                                'from' =>'10',
                                'to' => '22'
                                ],
                                [
                                'day' => 'Miercoles',
                                'from' =>'10',
                                'to' => '22'
                                ],
                                [
                                'day' => 'Jueves',
                                'from' =>'10',
                                'to' => '22'
                                ],
                                [
                                'day' => 'Viernes',
                                'from' =>'10',
                                'to' => '23'
                                ],
                                )
        ];

        $crawler = $this->get('/miweb/add-page/TimeTable/2');
        $this->assertResponseOk();
        $this->assertResponseContains( 'horario' );

        $form = $crawler->selectButton('Guardar')->form();
        $form->setValues( $data );
        $crawler = $this->submit($form);

        // $this->post('/miweb/add-page/TimeTable/2', $data);
        $this->assertResponseContains( 'Jueves' );
        $this->assertResponseContains( 'Viernes' );
        $this->assertResponseContains( '23' );
        $this->assertCount( 7, $crawler->filter('.row.time') );

        $post = TableRegistry::get('Posts')->get(3, ['contain' => ['Elements', 'Parent']]);
        $this->assertContains( 'de 10 a 22', $post->content );
        $this->assertContains( 'Martes', $post->content );
        $this->assertEquals( 'Horarios', $post->title );
        $this->assertEquals( '1', $post->site_id );
        $this->assertEquals( 'horarios', $post->slug );
        $this->assertEquals( 'TimeTable', $post->class );

        $this->assertRedirect('/miweb/edit-page/3');
     }
}
SkarXa
  • 1,184
  • 1
  • 12
  • 24