Postponed on #3180092: Update fabpot/goutte to 3.3.1 for PHP 8 compatibility.
Problem/Motivation
Goutte itself is deprecated and is just an alias to Symfony\Component\BrowserKit\HttpBrowser
. However, Drupal depends on behat/mink-goutte-driver
which of course depends on Goutte. However it does not seem like we quite depend on the particulars of the very minor features implemented in behat/mink-goutte-driver
on top of Goutte (AKA Symfony\Component\BrowserKit\HttpBrowser).
Proposed resolution
Swap out using Goutte itself with Symfony\Component\BrowserKit\HttpBrowser
and behat/mink-goutte-driver
with its existing underlying dependency behat/mink-browserkit-driver
.
Remaining tasks
Figure out what we need to change.
Replace behat/mink-goutte-driver
with behat/mink-browserkit-driver
as a dependency.
User interface changes
API changes
Data model changes
Release notes snippet
The Goutte testing browser has been deprecated and replaced with a new mink driver client, using Guzzle. This should not require any changes to browser tests unless you are interacting with specific Goutte features. Review the change record on the Goutte driver replacement for more information.
t
Comment | File | Size | Author |
---|---|---|---|
#75 | 3176655-75.patch | 23.65 KB | jungle |
#75 | raw-interdiff-73-75.txt | 510 bytes | jungle |
Comments
Comment #2
Gábor HojtsyComment #3
Gábor HojtsyComment #4
andyposttag to file issue to remove Goutte from dependencies
Comment #5
Gábor Hojtsy@andypost: I think that would happen within this issue, why not? Our developer dependencies are not considered an API are they? Also we are not directly depending on Goutte, we are only getting it because we depend directly on
behat/mink-goutte-driver
which is what we need to IMHO remove the dependency on here, otherwise we don't gain anything in terms of PHP 8 support in this issue.Comment #6
longwave+1 to removing the dependency here.
Removing Goutte here will also unblock #3104353: Upgrade to Guzzle 7
Comment #8
alexpottThis doesn't look like it is going to be simple. The test http client uses Guzzle and if we switch to BrowserKit driver we'd need to use something that implements \Symfony\Contracts\HttpClient\HttpClientInterface. I think given Goutte works on PHP 8 with no issues it might be best to do PR to allow it's use on PHP 8.
Comment #9
andypostYes, it require to add new dev dependency on
symfony/http-client ^4.4 || ^5.1
Comment #10
andypostFix status, btw tests could use
\Symfony\Component\HttpKernel\Client
and existing middleware will provide loggingComment #11
andypostThe related has collision with #6 but https://symfony.com/blog/new-in-symfony-4-3-httpclient-component
Moreover SF client is async out of box
PS: the comparison https://www.reddit.com/r/PHP/comments/hub30w/guzzle_vs_symfony_http_client/
Comment #12
tim.plunkett#10/11 seems like a follow-up.
That fixes the tests for me. But I get other cruft in composer.lock, so I'm not posting the patch
Comment #13
jungleAttaching a patch following steps in #12
Comment #15
Gábor HojtsyI am not sure there will be that many issues with the BrowserKitDriver? We are using 1.2.1 of the GoutteDriver and its a REALLY tiny layer on top of the BrowserKitDriver. https://github.com/minkphp/MinkGoutteDriver/blob/v1.2.1/src/GoutteDriver...
The fact it uses Goutte internally should be abstract to the layers above it no? The fails seem to be the result of the constructor defaulting to create a Goutte client instance but that is not happening of course in the BrowserKitDriver constructor itself. This code:
Mind you I am coming at this from the naiveté of "Never fought with this codebase before", so I may be set straight sooner or later :D
Comment #16
longwaveCopying a tiny bit of Goutte's code into our codebase allows at least some of the tests to run successfully.
Comment #17
alexpottThis is a little bit more green for me. Here I copy all of the client code from Goutte and GoutteDriver\Client into our own DrupalTestBrowser. I think this might be an acceptable way to move forward. We can then open a follow-up issue to use SF's HttpClient in the future with less rush.
Comment #19
alexpottFixing BrowserTestBaseTest
Comment #22
alexpottFixing the other BrowserTestBaseTest :)
Comment #23
alexpottThis is a pragmatic compromise but it's not really correct - we should be ensuring that the mink driver's client is not our DrupalTestBrowser. But this does work... hmmm. Note we can't do
$this->getSession()->getDriver()->getClient()
because the selenium driver doesn't implement getClient().This feels a bit odd. If we were using the HttpBrowser with BrowserKitDriver (the norm) we'd be setting up the SF http client here. I wonder if we should move this to \Drupal\Tests\BrowserTestBase::getDefaultDriverInstance()
I think we need to be explicit about not supporting the Goutte driver anymore. Tricky.
This should do check that the driver's client is an instance of DrupalTestBrowser. If we were using HttpBrowser and therefore sf's http client this would not work.
We need to remove this before commit. And reformat the code to our standards and document where the code is from.
Comment #24
alexpottAnother question posed by this issue is what are we losing by not using the GoutteDriver. That provides:
\Behat\Mink\Driver\GoutteDriver::prepareUrl()
- looks like\Behat\Mink\Driver\BrowserKitDriver::prepareUrl()
is going to do the same thing as long asif (!$this->removeHostFromUrl && !$this->removeScriptFromUrl) {
evals to true (which is does ATM).\Behat\Mink\Driver\GoutteDriver::reset()
- this also calls$this->getClient()->resetAuth();
- I think we're fine because BrowserKitDriver calls$this->client->restart();
and that resets Auth too.\Behat\Mink\Driver\GoutteDriver::getClient
is fine - it's a wrapper for type hinting purposes.\Behat\Mink\Driver\GoutteDriver::setBasicAuth()
is a worry - \Behat\Mink\Driver\BrowserKitDriver::setBasicAuth() does not do the same thing at all. I'm not sure though.At least nothing in contrib is using setBasicAuth() - see http://grep.xnddx.ru/search?text=setBasicAuth&filename= and we're not in core either. But we're probably losing some functionality here (which might not be being used by anyone).
Comment #25
Gábor Hojtsy@alexpott: re #23:
1. Yeah, we are using the same pragmatic approach in the existing code, just the checking updated.
2. Are you expecting contrib tests to rely on anything from Goutte in particular? That is really the golden ticket question here.
Re #24:
How do we test basic auth where we need it tested?
Comment #26
alexpottFixing #24.3 and part of #24.4
I think we should consider removing the auth and headers stuff from DrupalTestBrowser. I don't think it is needed. We're doing the header setting oursevles in \Drupal\Tests\basic_auth\Traits\BasicAuthTestTrait for example.
Comment #27
alexpottHere's what it'd look like without the suspiciously-unnecessary code.
Re #25/#23.1 the difference is that the Goutte mink driver is guaranteed atm (on v3) to have a guzzle client. Now we're using the browserkit driver it is not guaranteed at all.
Re #25.2 I really don't think so. Or it'd be an extreme edge case. As
\Drupal\Tests\basic_auth\Traits\BasicAuthTestTrait
shows we support headers directly in drupalGet() and that's the way you should be doing that.Comment #28
longwaveFWIW I've done a bunch of custom tests around basic auth and have never used these methods. It works as expected in drupalGet() or if you need more control over the request then you do it the same way we do in the REST tests, call getHttpClient() and set everything up yourself.
Comment #29
Gábor HojtsyAside: In the meantime, following my Goutte issue, @andypost posted an update there and @fapbot made a Goutte 4.0.1 release which is compatible with PHP 8: https://github.com/FriendsOfPHP/Goutte/releases/tag/v4.0.1 The Mink Goutte Driver still does not allow that version, so that would need to be updated as well for that alternate path to be explored.
Comment #30
alexpott#29 yeah the no change option is to ask @fabpot to make a Goutte v3 release that is PHP 8 compatible - it is compatible it is only composer that is not allowing it.
Comment #31
alexpottDoing the finally @todos and addressing #23.1
Comment #32
andypostChanging vendor hardening may need to clean-up tests from https://github.com/minkphp/MinkBrowserKitDriver/tree/v1.3.4/tests
Otherwise looks ready
Comment #33
alexpott@andypost we already do that... the browser kit driver is a dependency of the goutte driver. We're not actually adding any new code to vendor here. We're removing 2 libs from vendor.
Comment #34
alexpottRE #32
You can see it the list already in the diff... :)
Comment #35
andypostMisread patch, and indirect dependency case(
Comment #36
andypostIt may need CR or release nite snippet
Comment #37
alexpottI think we might need something. Looking at http://grep.xnddx.ru/search?text=Goutte&filename=&page=1 there behat config that'll have to change. And there's stuff like http://grep.xnddx.ru/node/30614854#line-219 which won't work.
Comment #38
andypostDrafted CR https://www.drupal.org/node/3177235
Comment #40
tim.plunkettWith https://github.com/FriendsOfPHP/Goutte/commit/abc34af, is this still needed?
Or even if it's not *needed*, is it that we still should do this?
Comment #41
Gábor Hojtsy@tim.plunkett: that was a change and new release to Goutte 4. We are on Goutte 3. Goutte 4 is just an alias to the Symfony browser that we are now using in the patch anyway directly. In head though, we are using Goutte indirectly for Mink. The Mink driver however had a release last 4.5 years ago (and is only compatible with Goutte 3), see https://github.com/minkphp/MinkGoutteDriver. So we'd need to get @fapbot to release a PHP 8 compatible Goutte 3, then get the Mink driver to be PHP 8 compatible (and as part of that allow Goutte 4). That's a lot of steps to try to maintain the status quo.
On the other hand, doing this patch would get us rid of a combination of unmaintained dependencies. As per @longwave in #6 this would also unblock moving to Guzzle 7. See #3104353: Upgrade to Guzzle 7
Comment #42
longwaveSeems unlikely anyone will trigger this, but mentioning Goutte in the message is confusing if we no longer use it.
Comment #43
alexpottGood point @longwave - and we can remove it from the dictionary :)
Comment #45
jungleA random failure, re-queued
Comment #46
andypostIt looks ready
Comment #47
alexpottWe need to tell people what to do re the situations in #37 - we also need to update the CR with those solutions. Ie. what to do if their behat config is using goutte and also what to do if their test code makes direct references to goutte code. I think this situation makes maybe means we should only remove the library in 9.2.x and leave it in 9.1.x? But we could still add DrupaTestBrowser to Drupal 9.1.x so they have something to swap to.
Here's a new patch the de-yoda's the ifs and uses Drupal snake case for variable names.
Comment #48
andypostFix tags
Comment #49
catchDoes that mean people won't be able to composer install on PHP 8 with Drupal 9.1.x? I had somewhat given up on full PHP 8 support in 9.1 a couple of weeks ago, but it seems theoretically possible this week.
#47 looks good.
Comment #50
alexpott@catch given this is only a dev dependency they would be able to install on PHP 8 as long as the don't include the core-dev package. I think if this was the last remaining dependency issue then maybe it'd be tempting but the doctrine one feel more intractable. It'd be nice to know exactly what is the impact of this change on the projects using behat testing.
Comment #51
alexpottWith @bircher's help I've done a little more research on the behat situation. The great news is that the behat extension depends on goutte-driver already so as long as we don't break goutte using goutte in core then we're okay.
The one functional change is that the following code will result in test browser output not working on goutte anymore.
... perhaps this is acceptable. I'm going to test https://www.drupal.org/project/drupalextension with this patch and see what happens.
Comment #52
alexpottI have successfully run a behat test after applying this patch.
Steps to reproduce:
composer require drupal/drupal-extension
./vendor/bin/behat --init
Replacing REPLACE_ME_WITH_BASE_URL with the base url of the site.
./vendor/bin/behat -v
No changes we necessary due to this patch. Given the drupal extension includes goutte and we;ve not broken it I think we're good from that perspective. Yes the drupal extension will need to do work to be PHP 8 compatible but that's okay - with the new DrupalTestDriver they can be - or they can only support other drivers on PHP 8.
So looking at http://grep.xnddx.ru/search?text=Goutte&filename= this leaves:
As the affected modules...
Comment #53
jibranThis will affect DTT as well so tagging.
Comment #54
alexpottI've asked @fabpot to consider backporting the PHP 8.0 compatible fix to Goutte v3 - I don't think that means we shouldn't do something like the above but it gives us more time and we can do it in a deprecated way rather than a breaking change in a minor version. Note in the original github issue @fabpot said:
https://github.com/FriendsOfPHP/Goutte/issues/429#issuecomment-707761283
So it sounds like it might be possible.
Comment #55
andyposthttps://github.com/FriendsOfPHP/Goutte/releases/tag/v3.3.1 is out
Comment #56
Gábor Hojtsy@andypost: So our https://git.drupalcode.org/project/drupal/-/blob/9.2.x/composer.lock says our behat/mink-goutte-driver is on 1.2.1, which allows for PHP 8 by itself and its composer constraints do allow it to work with fabpot/goutte 3.3.1, so looks like we would only need to update our composer.lock to ship with 3.3.1 there.
Opened #3180092: Update fabpot/goutte to 3.3.1 for PHP 8 compatibility and going to postpone this on that.
Comment #57
andypostThe issue still makes sense to get rid of deprecated dependency
Comment #58
andypostComment #59
alexpottI think now this issue can be used to prep the ground to remove the dependency on goutte & gouttedriver in Drupal 10.
Comment #60
andypostChanging parent
Comment #61
alexpottGiven that Goutte and therefore GoutteDriver are only "supported" in quotes ( https://github.com/FriendsOfPHP/Goutte/issues/429#issuecomment-720059965 ) we still need to move off it. Here's a patch for Drupal 9 that allows us to move forward whilst still supporting tests using GoutteDriver (and therefore Goutte) - the listed projects in #52 and Drupal Test Traits (#53) won't break hard in D9 but they might still need tweaks to keep exactly the same functionality.
Comment #62
alexpottSlightly more test coverage.
Comment #65
alexpottFixing the tests. The mocking being done in \Drupal\Tests\Core\Test\BrowserTestBaseTest::mockBrowserTestBaseWithDriver() is being unnecessarily restrictive. $this->once() is unnecessary - on BrowserTestBase this method will alway return the given object and there is no need to unit test the number of calls to these methods here.
Also we can add back in the test coverage for getting the guzzle client from the Goutte driver since we still support doing that.
Comment #66
longwaveDo we need to keep the behaviour inside the secondif
statement for GoutteDriver as well?No, because GoutteDriver extends BrowserKitDriver anyway.
Comment #67
longwaveIgnore the above, I was wrong - this looks good to me otherwise.
Comment #68
alexpottI think this should have a name like isTestUsingGuzzleClient() because that's what this really is.
Comment #69
andypostIs it backportable to 9.1?
Comment #70
longwaveI think #68 is a good suggestion, let's change that.
Spotted and opened while reviewing this: #3181329: BrowserHtmlDebugTrait::getResponseLogHandler() is duplicated as BrowserTestBase::getResponseLogHandler()
Comment #71
ayushmishra206 CreditAttribution: ayushmishra206 at OpenSense Labs commentedMade the changes suggested in #68. Please review.
Comment #73
jungleOccurrences of
isTestUsingDrupalTestBrowser()
should be replaced instead of renaming only.Unexpected interdiff file in patch
Comment #74
longwave#68 was addressed, back to RTBC.
Comment #75
jungleRerolled
Comment #76
catchCommitted/pushed to 9.2.x, thanks!
I think we should try to get this into 9.1.x too, but it'll need a re-roll for composer.lock
Comment #77
catchChange record is fine now.
Comment #78
catchDiscussed briefly with @alexpott - this is fine in 9.2.x, it's not need for PHP 8 compatibility any more due to the Goutte release which we already updated to, so it's just getting us ready for 10.x at this point
Comment #79
catchComment #81
catchUpdated the change record to mention 9.2.0 instead of 9.1.0, the patch was already targeting 9.2.0 so that bit's fine.
Comment #82
alexpottComment #84
xjmCreated a new patch in #3104353-31: Upgrade to Guzzle 7 to test Guzzle 7 now that removing this dependency is an option.
Comment #85
xjm