Codeception: Easy way to set `HTTP_HOST` for functional tests with symfony missing.

What are you trying to achieve?

i am trying to functional test a symfony application where the routes only listen to specific domains, lets say example.com. i simply want to run $I->amOnPage('/'); and get the

symfony2 routing.yml

mybundle:
    resource: "@MyBundle/Resources/config/routing.yml"
    host: example.com

What do you get instead?

so a $I->amOnPage('/'); leads to a 404 because it is accessed with http://localhost.

What i found out

as workaround i can change all urls to also listen to localhost.

mybundle:
    resource: "@MyBundle/Resources/config/routing.yml"
    host:     "{hostname}"
    defaults: { hostname: example.com }
    requirements:
        hostname:     example.com|localhost

which is a little bit overkill to do this for all routes and maybe also have negative sideeffects.

the correct solution for the symfony browser would be setting the HTTP_HOST:

https://stackoverflow.com/a/10677520

class AgencyControllerTest extends WebTestCase
{
    public function testShowFoo()
    {
        $client = static::createClient();

        $crawler = $client->request('GET', '/', array(), array(), array(
            'HTTP_HOST'       => 'foo.domain.dev',
            'HTTP_USER_AGENT' => 'Symfony/2.0',
        ));

        $this->assertGreaterThan(0, $crawler->filter('html:contains("Text of foo domain")')->count());
    }
}

searching this repo i found that the yii framework had a similar issue, which was fixed:

https://github.com/Codeception/Codeception/pull/2350/files

     public function _createClient()
     {
         $this->client = new Yii1Connector();
+        $this->client->setServerParameter("HTTP_HOST", parse_url($this->config['url'], PHP_URL_HOST));
         $this->client->appPath = $this->config['appPath'];
         $this->client->url = $this->config['url'];
         $this->client->appSettings = [

so it looks like this is done somewhere here for symfony as the SymfonyConnector extends \Symfony\Component\HttpKernel\Client: https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module/Symfony.php#L185

    /**
     * Initialize new client instance before each test
     */
    public function _before(\Codeception\TestInterface $test)
    {
        $this->persistentServices = array_merge($this->persistentServices, $this->permanentServices);
        $this->client = new SymfonyConnector($this->kernel, $this->persistentServices, $this->config['rebootable_client']);
    }

for now i havn’t found/verified the exact location where same client as in the WebTestCase is created.

if i set the url in functional.suite.yml under Symfony2 i would assume it sets the HTTP_HOST but it does nothing.

actor: FunctionalTester
modules:
    enabled:
        - Symfony2:
#            url: 'http://example.com/'

also tried

        - PhpBrowser:
            url: 'http://example.com'

but this only leads in accessing the real webserver or the local webserver if i use a domain which points to localhost.

what helps is using a similar helper descibed in https://github.com/Codeception/Codeception/issues/2717#issue-126400964

Functional.php

<?php
namespace Helper;

class Functional extends \Codeception\Module
{
    public function setHost($host)
    {
        $this->getModule('Symfony2')->client->setServerParameter('HTTP_HOST', $host);
    }
<?php

/**
 * @group frontpage
 */

class BasicCest
{
    public function _before(FunctionalTester $I)
    {
        $I->setHost('example.com');
    }

but doing this for each cest is not that what i am looking for, i would like to set it globaly.

adding it to the frontpage group _before also doesn’t work, because the client is not initialized yet:

<?php
namespace Group;

use \Codeception\Event\TestEvent;

class Frontpage extends \Codeception\Platform\Group
{
    public static $group = 'frontpage';

    public function _before(TestEvent $e)
    {
        $this->getModule('Symfony2')->client->setServerParameter('HTTP_HOST', 'example.com');
    }
}

as i said i would wish to simply set the url setting for my symfony module so it correctly sets the HTTP_HOST for the client.

if i missed something in the docs, please point me the way, it this is currently not possible, i would be happy to see this feature soon in codeception

Details

  • Codeception version: 2.3.1
  • PHP Version: 7.1.4
  • Operating System: Windows
  • Installation type: Phar

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 22 (17 by maintainers)

Most upvoted comments

Anyone coming across this, you can resolve this by adding a custom helper to add the host header before each test…

<?php

declare(strict_types=1);

namespace App\Tests\Support\Helper;

use Codeception\Module\Symfony;
use Codeception\TestInterface;

class DynamicHosts extends \Codeception\Module
{
    protected array $requiredFields = ['host'];


    public function _before(TestInterface $test)
    {
        $symfonyModule = $this->getModule('Symfony');
        assert($symfonyModule instanceof Symfony);

        $symfonyModule->haveHttpHeader('host', $this->config['host']);
    }
}
actor: ApiTester
modules:
    enabled:
        - Asserts
        - REST:
              depends: 'Symfony'
              url: '/api'
              shortDebugResponse: 300
        - Symfony:
              app_path: 'src'
              environment: 'test'
        - '\App\Tests\Support\Helper\DynamicHosts':
              host: 'custom.host.com'