Problem/Motivation
Our phpunit based functional javascript test will pass even if there are Javascript errors on the page.
While we test JS functionality sometimes a JS error will not break our tests because the core functionality still works but other JS that is the page of a particular site could be broken.
A user ran into this scenario on #3072231: Custom blocks break layout builder module - Quick Edit could not associate the rendered entity field markup
Proposed resolution
if a Javascript error is thrown to during a test fail the test.
Additionally
- All core tests should fail on Console errors by default. Each class should not need to set a property so that we cannot ignore console errors in core tests by forgetting this property
- Core tests should be able to set the property
protected $failOnJavascriptConsoleErrors = FALSE;to suppress errors for 2 reasons
1) This will allows use to commit this with known errors such as #3091878: MediaEmbedFilterConfigurationUiTest throws a Javascript Error or any others we find at the time we are able to commit this this issue. Before we commit this at any point we can't be sure how many tests will fail with this patch applied. We could be adding new tests that throw JS console errors with any commit.
2)After this patch is committed we could have tests start to fail for a number of reasons such as, changes in the chrome driver/browser Drupalci uses or needed updates to our JS dependences. In the example of our JS dependencies these could be security updates that we need ASAP but also cause a small non-important JS console error. In such cases we should be able to commit the dependency updates and do a follow-up to fix the error. - Any class that extends
\Drupal\FunctionalJavascriptTests\WebDriverTestBaseexcept core test, i.e Contrib and custom test, should have to opt in this behavior by settingprotected $failOnJavascriptConsoleErrors = TRUE;. This will ensure a bunch of contrib tests will not start to fail after we commit this patch. We could consider changing this to opt out in Drupal 10 - Contrib/custom tests should be able to opt in a bunch of classes at once by setting
protected $failOnJavascriptConsoleErrors = TRUE;in a base test class like,MyModuleTestBase
Remaining tasks
All
User interface changes
None
API changes
None
Data model changes
None
Release notes snippet
FunctionalJavascript tests now automatically check to see if any JavaScript errors have been thrown during the test's execution. In Drupal 10, this will cause the test to fail, while in Drupal 9.3, a deprecation warning is issued for tests that pass despite the presence of JavaScript errors. See https://www.drupal.org/node/3221100 for details.
| Comment | File | Size | Author |
|---|---|---|---|
| #33 | 3091870-32-cleanup.patch | 1.92 KB | effulgentsia |
Issue fork drupal-3091870
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
tedbowCurrently I was only to figure out how to do this by wrapping
Drupal.throwError()but maybe there is a better way.I followed the example #3070521: Trigger deprecation notifications on JavaScript deprecations to notify developers that deprecated code is being used. so basically any call to
Drupal.throwError()will save an error in the localStorage. Then in\Drupal\FunctionalJavascriptTests\WebDriverTestBase::tearDown()the session variable is checked and a test fail is set if any errors were thrown.I altered
drupalci.ymlto only run FunctionalJavascript tests to see how many tests break.Comment #4
tim.plunkettComment #5
catchComment #6
mradcliffeA brief comment about tour module in Nightwatch before I forget.
Nightwatch uses the nightwatch test install profile, which doesn't have any modules that utilize tour so javascript wouldn't get installed. I needed to install the tour_test module as well. This probably doesn't apply to FunctionalJavaScript using minimal or standard.
I'm not sure why the test-only patch didn't fail on drupalci, but it did fail locally. It could be a race condition in page load versus javascript-readiness.
Comment #7
tedbow@mradcliffe thanks for the context.
I think maybe we should keep this issue for just tests that extend \Drupal\FunctionalJavascriptTests\WebDriverTestBase and then have different but related test if we want to do the same thing with Nightwatch tests.
Here is reroll. I just had to remove the drupalci.yml changes
Comment #9
tedbowSo this references the patch in #2
The 1 fail was in MediaEmbedFilterConfigurationUiTest
Comment #10
tedbowComment #12
tim.plunkett#9.3
NW for that
Comment #13
lauriiiI'm not sure this is something we should be concerned of. Previously, we have decided to avoid complexity with the risk of contrib tests failing. If there are JS errors in a contrib module, they should be aware of it. If they want to ignore the errors, they have the option to suppress the errors.
Comment #17
tim.plunkettHiding patches now that an MR is open
Comment #21
tedbowsetting to NR
Comment #22
xjmAssuming the status should be NW for the above comment on the MR.
Comment #23
tim.plunkett@tedbow and I discussed and in D9 the errors will be surfaced as a deprecation, and only made a true failure in D10.
CR is here: https://www.drupal.org/node/3221100
Comment #24
tedbowSetting to needs Review because I addressed MR comments. This is much simpler now.
Comment #25
tim.plunkettThanks @tedbow! I really like where this ended up.
Comment #27
tedbow@lauriii didn't unRTBC this but left some nits. I confirmed that @phenaproxima fixed all the issue @lauriii brought up
So we can consider this me re-RTBCing this
Comment #28
effulgentsia commentedAdding issue credits.
Comment #29
effulgentsia commentedThe patch looks great, but I'm concerned about the removal of the
js_deprecation_log_testmodule and session storage variable and renaming it withjs_testing_log_test. I think for specific test fixtures our BC policy doesn't need to be super strict, but this affectsWebDriverTestBaseand therefore all of its subclasses, so there's more chance of some contrib or custom functional test out there that accesses the module name or session storage variable directly. I recommend leavingjs_deprecation_log_testalone, and just addingjs_testing_log_testfor the errors. And then having a follow-up issue for consolidating warnings and errors into the same test module and session storage variable, if we want to advocate for the benefits of that outweighing the BC break, or to do it via a deprecation process.Leaving this at RTBC though because the above is just my opinion, and happy to be overruled by another committer.
Comment #30
alexpott@effulgentsia contrib is currently clear - http://grep.xnddx.ru/search?text=js_deprecation_log_test&filename= I think adding this to the CR here is good enough. FWIW client projects I work on use this patch and it is vital to helping developers test that and Javascript isn't unexpected triggering errors.
Comment #31
alexpottI've added the module name change to the CR - as part of doing this the following thought occurred - as this module is enabled in \Drupal\FunctionalJavascriptTests\WebDriverTestBase::installModulesFromClassProperty() there really is not much reason for contrib or custom to ever use it's name.
Comment #33
effulgentsia commentedThanks. I'm satisfied with #30 and #31. Pushed to 9.3.x, but I noticed that doing so left behind 2 dead JS files. Here's a patch to remove them. As this is just dead code removal, marking this issue fixed, and I'll commit this patch (or someone else can) once tests pass.
Also, tagging this for release notes mention. It would be great if someone could add a release notes snippet to the issue summary, while this is still fresh in our minds.
Comment #34
alexpott@effulgentsia nice! +1 to #33 - I just noticed those files hanging about on client project and was wondering why they were still there :)
Comment #36
effulgentsia commentedI committed #33, and added a release note snippet to the issue summary. Please feel free to update it as needed.
What I wrote is:
However, it looks to me like
WebDriverTestBase::tearDown()runs:regardless of whether the test otherwise passed or not. Am I reading that correctly, and if so, do we want a followup to restrict the deprecation to only when the test passed?
Comment #38
znerol commentedFollow-up: #3331835: Some JavaScript errors are not recorded during test runs