symfony / panther

A browser testing and web crawling library for PHP and Symfony
MIT License
2.93k stars 220 forks source link

How to get updated version of Crawler after site interaction? #514

Open Dherlou opened 2 years ago

Dherlou commented 2 years ago

Hey there,

I want to assert the new document state after interacting with the document.

I set the test client and web server up like this in my test super class, which uses the PantherTestCaseTrait:

$this->client = Client::createChromeClient(
    'drivers/chromedriver',
    [
        '--headless',
        '--disable-dev-shm-usage',
        '--no-sandbox'
    ],
    [
        'request_timeout_in_ms' => 20000000
    ]
);

self::startWebServer();

Then I execute a simple test script, where an input field should be filled and the new value asserted:

$crawler = $this->client->request('GET', 'http://127.0.0.1:9080/en/login');
$field = $crawler->filterXPath('//input[@id="password"]');
$this->assertCount(1, $field);
$field->sendKeys('dummy');
// already tried this: $crawler = $this->client->refreshCrawler();
$text = $crawler->filterXPath('//input[@id="password"]')->text(); // also tried ->html();
// this makes the assertion true: $text = $this->client->executeScript('return document.getElementById("password").value;');
$this->assertEquals('dummy', $text);

The last assertion fails, because '' != 'dummy', so the crawler does not have the input field filled. However, if I use the commented line for the assertion by retrieving the value directly from JavaScript, the test succeeds. What am I doing wrong?

domis86 commented 2 years ago

can you check what is the type of $crawler->filterXPath('//input[@id="password"]') ?

If is something related to "form field" then maybe can you try this getValue() method on it? : https://github.com/symfony/panther/blob/main/src/DomCrawler/Field/FormFieldTrait.php#L47

But please also do: $crawler = $this->client->refreshCrawler(); And can you pause for 1 second before refreshing crawler? (using sleep(1))

Dherlou commented 2 years ago

The type is 'object' and the class is 'Symfony\Component\Panther\DomCrawler\Crawler'. The field does exist and is updated, as I can verify it with the JavaScript injection line.

I was able to get the value of the password field with $crawler->filter('#submit')->form()->getValues()['_password'];. I am just wondering, why this works and $crawler->filterXPath('//input[@id="password"]')->html() is not... Adding the 1s sleep followed by the refreshCrawler() did not change anything by its own.

(Edit: The field id is "password" and the name is "_password".)