symfony / panther

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

Does panther load external JavaScript files? #516

Closed Dherlou closed 2 years ago

Dherlou commented 2 years ago

Hey there,

I have the problem that the JavaScript files referenced by my web page under test (symfony) do not seem to be loaded, hence registered event listeners etc. are missing in the test.

Short Demo: My webpage contains the line <script src="/build/app.js" nonce=""></script> close to the bottom, which loads a webpack-bundled JavaScript file. I added jQuery(function() { document.body.appendChild(document.createElement("nav")); }); as a small test, which appends a nav element at the bottom of the page, when the js file and the page are loaded. When I open the website via apache webserver in my browser the page does contains <nav></nav> after the script tag. When I am running panther tests and output the $crawler->html(), the <nav></nav> are missing, hence I guess the JavaScript file is not loaded.

Panther Configuration:

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

Am I missing a configuration setting that tells Panther browser to load external JavaScript files or what is going on?

Thanks in advance!

domis86 commented 2 years ago

can you do this after you execute the javascript which appends nav ? :

sleep(1);
$crawler = $this->client->refreshCrawler();

and then check again if nav was added

Dherlou commented 2 years ago

Sounds good, doesn't work.

Could this be an effect of the same reason that causes my other problem (#514)?

codegain commented 2 years ago

@DeveloperPad Check twice if the JS file can be accessed via the network. In my case I used a proxy on the build server which the application did use to access https://localhost/app.js and failed (of course).

Otherwise, I use this snippet to check if the site was fully loaded right after $client->request($url, 'GET')

/**
 * Wait for page to finish loading.
 *
 * @return void
 */
protected function waitForPageLoad(): void
{
    // Wait for HTML to be ready
    $this->client->getWebDriver()->wait()->until(
        WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::tagName('html')),
        'Page did not load in time'
    );
    $this->client->refreshCrawler();
}
Dherlou commented 2 years ago

@codegain Sorry for the late reply. I moved in December and had some vacation. :)

Your hint lead me in the right direction. I ensured that the JS file is network-accessible by requesting it directly via GET-method and printing its content. It did put out the content as expected, so I could interpret this as "accessible via network". However, the script still didn't load. I then took a look into the browser log, which showed me that the JS file is not loaded due to CSP. The CSPListener in Symfony was still using the domain of the development environment on which I am developing remotely. So all I had to do was skip the CSPListener registration during CI tests. Since then it has been working like a charm.

Thanks for your help.