Codeception/Codeception — pull request #622 by elazar (2013-10-19 01:58:20+00:00)
Title: Fixed PhpBrowser module persisting HTTP authentication between tests

#138 mentions an issue with HTTP authentication persisting between tests. It mentions a fix made by @vinu, but I've scanned through the source code and haven't located any sign of such a fix. I've experienced this issue in instances where a test than sets HTTP authentication credentials precedes a test that does not, in Codeception 1.6.8.* and 1.6.10. I've tested a fix in this pull request and it does appear to address the issue.

The core problem is that neither `Goutte\Client` nor any of its subclasses (including `Codeception\Util\Connector\Goutte`) provide a public method to reset its protected `$auth` property to its default value of `null` once it has been set to a non-`null` value using the `Goutte\Client->setAuth()` method. This issue effectively causes HTTP authentication credentials to persist between Codeception tests once they've been set, even if a test that runs after they've been set doesn't explicitly reset them.

The fix in this pull request corrects this by adding `Codeception\Util\Connector\Goutte->resetAuth()` for this purpose and adding a `Codeception\Module\PhpBrowser->_before()` hook that calls it. A [pull request](https://github.com/fabpot/Goutte/pull/121) has been submitted to the Goutte project to have this lacking feature addressed at that level. If those changes are merged, the changes in this pull request to `Codeception\Util\Connector\Goutte` can be removed, but the changes to `Codeception\Module\PhpBrowser` must remain (because at that point `resetAuth()` will still need to be called by `Codeception\Module\PhpBrowser`, but will be inherited from `Goutte\Client` rather than being defined in `Codeception\Util\Connector\Goutte`).

It's not currently possible to substitute a subclass of `Codeception\Util\Connector\Goutte` that corrects this issue to `Codeception\Util\Module\PhpBrowser` because the latter instantiates the former directly rather than allowing for dependency injection. The only "clean" work-around for this would involve subclassing the latter and duplicating much of the existing logic in its `_initialize()` method.

A work-around (which is admittedly rather hacky) is to use reflection to change the accessibility of the aforementioned `$auth` property and set its value to `null` in a helper as shown below. While it isn't a very clean approach, it's must less intrusive than the aforementioned subclassing approach in that it doesn't duplicate a lot of core behavior that could change later.

```php
// _helpers/ApiGuy.php
namespace Codeception\Module;
class ApiGuy extends \Codeception\Module
{
public function _after(\Codeception\TestCase $test)
{
$client = $this->getModule('PhpBrowser') // Codeception\Module\PhpBrowser
->session // Behat\Mink\Session
->getDriver() // Behat\Mink\Driver\GoutteDriver
->getClient(); // Codeception\Util\Connector\Goutte
$auth = new \ReflectionProperty('\Codeception\Util\Connector\Goutte', 'auth');
$auth->setAccessible(true);
$auth->setValue($client, null);
$auth->setAccessible(false);
}
}
```