Problem/Motivation
All requests made explicitly by FunctionalJavascript tests (AJAX or otherwise), we've got logic analyzing the response explicitly — drupalGet() and all other methods in test logic call rely on \Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware to make requests. That code explicitly inspects the response it receives.
When the request is sent by the headless browser (triggered by triggering a button for example) instead, then this code does not run: since the request is not triggered by PHP code, but by the browser.
Steps to reproduce
Proposed resolution
Apply a solution similar to #3070521: Trigger deprecation notifications on JavaScript deprecations to notify developers that deprecated code is being used.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | 3228956-2.patch | 2.07 KB | wim leers |
Comments
Comment #2
wim leersComment #4
xjmCrossposting from the other issue.
larowlan
xjm:
larowlan:
@Wim Leers:
Comment #5
xjmComment #6
xjmComment #7
xjmThe testing subsystem maintainers might be able to help with an alternate solution for this also, but definitely we'll want FM signoff as this significantly impacts yada yada.
Comment #8
wim leersSuspicion confirmed by the failing tests!
Typing this from my phone, thanks @xjm for copying over relevant info — I was holding off on doing that until the suspicion was confirmed by DrupalCI 🥸
Will update the issue summary tomorrow.
Comment #9
larowlanShouldn't the browser accept and send cookies? We're using a real browser here.
If the test UA didn't get set then we wouldn't get logged in sessions in the test and any request the browser makes back to the site under test would punch through the valid test UA and hit the live site (not the prefixed one).
So I don't think the issue is the cookies, I think the issue is that there is no one there to hear the exceptions.
With requests made via the driver, we've got stuff that reads back the headers. But with requests the browser makes we don't. i.e I suspect the responses coming back with the ajax would have the headers - but they're not being read outside of drupalGet.
We've got some prior art here - #3070521: Trigger deprecation notifications on JavaScript deprecations to notify developers that deprecated code is being used - but all of that seems very brittle, sending a header in a child site, to be read in JS, to be stored in session storage, to be read back by the driver on tearDown 😱
Another alternative is something like https://www.previousnext.com.au/blog/making-your-drupal-8-kernel-tests-f... where we'd have a specialised logger that we setup in any functional JS test that we then check in the tear down. We could just have it write to a key value collection or something so it could be used to communicate from the child site to the runner.
Comment #10
alexpottThe thunder distribution checks the logs on tearDown for this reason - https://github.com/thunder/thunder-distribution/blob/54da56bbf30ef0a3c81... This works for Thunder because we don't have any tests that expect a PHP notice or error - core has such tests and similar tests probably exist in contrib and custom code too. One problem with this approach is that error gets reported in tearDown so it can be very disconnected from where the error actually occurs.
I do think that if #3070521: Trigger deprecation notifications on JavaScript deprecations to notify developers that deprecated code is being used is working then leveraging is probably the best bet. If it is brittle then we need to change the way that works too.
Comment #11
wim leersObviously that did not happen… but doing it now! :)
#9
It's not the cookie, it's theHoly crap, it is the cookie!User-Agentrequest header.drupal_valid_test_ua()'s name obviously suggests it's the User Agent, but then the relevant code does this:Geez!!
Indeed! So … I got the issue title right (it indeed does not work for AJAX requests), but I got the cause wrong (it's not that because the request does not have the correct user agent, it's because the AJAX request's response is not explicitly processed/asserted).
The end result is the same.
Comment #12
wim leersCan you elaborate on this?
(It seems like a waste of time to copy a pattern that is used in a single place that we want to change anyway?)
Comment #13
xjmWe can split off child issues for the individual failures listed in https://www.drupal.org/pift-ci-job/2154378.
Comment #14
xjmTests that don't fail when they should is a major bug IMO.
Comment #15
alexpott@chr.fritsch pointed me to #3061251: Expose Ajax errors in Javascript tests which is related. When ajax does fail it can be really hard to work out what is wrong.
Comment #16
alexpottThis is related to #2400477: Drupal never displays non-fatal error messages to the screen during Ajax requests and these issues almost feel like dupes - different solutions though.
There's also the wider issue about reporting JS errors - see #1419652: JavaScript logging and error reporting
Comment #18
mikelutzI ended up here from [3225381] which is a regression caused by [3084436]. We unset a render array key which caused a array key undefined notice in a template function. but the test didn't catch the notice, for reasons described here.
Because the standard error handler hides these from the ajax response, the forms generally work in real life. I got stuck on this because the ajax call above was failing for me on my local version, and I couldn't export a config. Took some digging, but long story short, I had devel installed and had the error handler set to none, which reverts back to the standard php handler, plus error_reporting E_ALL for local development. All this together means the notice is printed in the response body, above the JSON. All that to say, with a local setup like this, those failures become real, and those forms/buttons don't work. Easy enough to re-enable the drupal error handler in devel for me, but it confused me for a bit.
The one thing they found in [3225381] is that it turns out to be difficult to write a failing test for those bugs without having some framework in the test system to detect them. I posted a proof of concept test in that issue which disables the drupal error handler for that test, but it would be much better to globally expose the notices and warnings, rather than changing the error handler for each of the tests. I haven't gone through all the failures here, but if they are easy enough to fix, it might be worth considering doing them all at once along with a system to prevent future warnings and notices from cropping up in Ajax requests.