Problem/Motivation
As discoverd in #2832672: [PP-1] Upgrade jcalderonzumba/* for better test performance a test opening a dialog and then peforming actions within the opened dialog are at risk for random failure.
The random failure is caused by a dialog resize/reposition after content has been inserted. Currently there is no way to wait for this as this behavior is debounced.
Currently the random failures do not occur because the Mink Phantomjs driver waits an additional 100ms on each wait statement. However on upgrading the driver or switching to another driver (#2775653: JavascriptTests with webDriver) this problem will become relevant.
Proposed resolution
Either:
1. Provide a better way to assert the dialog has opened.
2. Remove the random failure factor for opening a dialog.
Steps to reproduce:
This issue improves the way we wait for a dialog to open. The reason is random failure and therefore difficult to reproduce.
To reproduce the random fail do the following:
- Apply the patch from #2832672: [PP-1] Upgrade jcalderonzumba/* for better test performance, this will make the random fail occur more often.
- Do not apply the patch from this issue.
- Run the test in views_ui/tests/src/FunctionalJavascript/FilterCriteriaTest.php multiple times untill the test fails.
- See the excellent research in #2832672: [PP-1] Upgrade jcalderonzumba/* for better test performance by @tacituseu to see an explaination on the fails.
I have run the tests on multiple 25x runs locally and I got the fails frequently before applying this patch and no more after applying this patch.
Thanks @michielnugter for the patch. And tacituseu & droplet did a lot of researching on #2832672: [PP-1] Upgrade jcalderonzumba/* for better test performance. Please credit them also if we can.
| Comment | File | Size | Author |
|---|---|---|---|
| #65 | LayoutBuilderUiTest_testReloadWithNoSections_1500x.patch | 12.3 KB | spokje |
| #51 | 2856047-51.patch | 7.23 KB | smustgrave |
| #51 | interdiff-50-51.txt | 512 bytes | smustgrave |
Comments
Comment #2
michielnugter commentedAttached a convert from the original patch and used a trait, this is a fix using option 1. Not very happy yet with the way the dialog_test module is installed and checked on, don't know a better way yet.
Alternatives:
- Wait for #2844582: Move inline javascript in JSWebAssert into a separate javascript file to get in and move the assertion to JSWebAssert.
Questions:
- I kept the updated FilterDialogTest as a test for the change. Should this be split of later on?
- Is a separate test of the dialog required or does the FilterDialogTest suffice?
Comment #3
michielnugter commentedComment #5
michielnugter commentedasserT instead of asser
Comment #7
michielnugter commentedself::$modules instead of $this->modules.
Comment #8
dawehnerThis condition feels more like an
assert()assertionComment #9
michielnugter commentedI converted it to a assertArrayHasKey(), the assert() method really is deprecated right?
Some other clean-ups as well.
Comment #11
michielnugter commentedRight, wrong kind of assert.
I was thinking about this a little more and the current check can fail if the module is loaded on a base class because of the way the $modules array works. I therefore removed the check and added a hint in the phpdoc for this method. Is this acceptable?
Comment #12
droplet commentedTagging and add a credit message :P
I will review it this weekend or so if no one does it before me.
Comment #13
droplet commentedComment #14
michielnugter commentedThanks in advance @droplet. And very true on the credits for you and tacituseu, a lot of preliminary research went into the solution for this one.
Comment #15
balagan commentedI tried to triage this and review, but I just don't know how to reproduce this. Added Needs issue summary update tag, hoping someone adds steps to reproduce, or maybe droplet comes back and reviews this.
Comment #16
balagan commentedComment #17
michielnugter commentedComment #18
michielnugter commentedI updated the steps to reproduce.
Comment #19
cilefen commented@balagan That's good work so far on triage. I could give you credit if you document the rest of the triage steps (even if brief). It is the only way to know if the triage has actually been completed. Here are some made-up examples of documented triage steps:
Thank you!
Comment #21
jibranPatch looks good to me. Do we need
core/modules/system/tests/modules/dialog_test/js/dialog.debug.jsin for all the dailogs?.
Comment #22
jibranComment #23
martin107 commentedA few small comments nothing of any consequence,
1) Since this issue was started, core now exclusively uses es6.js files which are transpiled into js
2) The variable dependency injection of the file was incorrect
This is the change.
Comment #24
jibranThis patch is blocking #2832672: [PP-1] Upgrade jcalderonzumba/* for better test performance so RTBCing it.
Comment #26
GrandmaGlassesRopeManUse arrow functions.
`use strict` not required here.
Too many spaces.
Comment #27
tim.plunkettThis adds a method that seems to be standalone.
However, it will silently do nothing if the `dialog_test` module is not installed.
I think the name is misleading. It only works for opening, not closing.
Furthermore, it does not account for a dialog that uses a fade effect, which assertWaitOnAjaxRequest() does protect against.
Comment #28
martin107 commentedI will spend sometime today resolving lint conflicts and will address the other issue while I am at it.
Comment #30
jibranFixed #26.
Comment #31
dawehnerCan we add a test inside core, outside of the views module? This makes it for example less likely that we accidentally drop it.
Comment #33
anavarreComment #34
kostyashupenkoreroll
Comment #36
krzysztof domańskiComment #42
xjmTagging so I can find this in the search; it's not a random test failure itself but it's about them.
Comment #45
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #need-reveiw-queue. We are working to keep the size of Needs Review queue [2700+ issues] to around 200, following Review a patch or merge require as a guide.
# D10 version
D10 version needed
At this time we would need a D10.1.x patch or MR for this issue.
Comment #46
smustgrave commentedRerolled for D10
Removed the es6 file from the test module.
The statusTest has changed some too so tried to address those.
Comment #47
catchAre there any other tests that can use this? I think this might have been what dawehner was getting at in #31.
Comment #48
lendudeI think a dedicated test for this trait/JS is what was asked for. Sounds like a good addition, currently if we were to remove the Views test, this functionality has no coverage.
Comment #49
smustgrave commentedDo you have an example of testing a trait?
Comment #50
smustgrave commentedSomething like this?
Comment #51
smustgrave commentedComment #52
lendudeNice, that looks great.
Code looks good, we are only updating 1 test here, should we do more here of should we open a follow-up to change more tests to use this?
I think landing this first is good, so marking RTBC, not making the follow up yet till others agree that would be the right way to handle this.
Comment #53
catchDoing more in a follow-up seems good to me.
Comment #54
lendudeOk, here is that follow up #3350260: Convert all JavaScript tests that use dialogs to use waitForDialog()
Comment #56
catchRandom failure..
Comment #57
bnjmnmSince this introduces changes intended to reduce random fails, this should have patches that customize drupalci.yml to run a single random-fail prone test several hundred times (possibly as many times as the test runner time limit allows). Include a version with and without the changes introduced here to compare the failure rate.
I also noticed that the solution here resembles something already in core specific to off canvas. Most of the lifting is done in these files:
https://git.drupalcode.org/project/drupal/-/blob/10.1.x/core/modules/sys...
https://git.drupalcode.org/project/drupal/-/blob/10.1.x/core/modules/sys...
Perhaps the changes here can be integrated the off canvas ones, even if it's just having the traits in the same dir/namespace?
Comment #58
spokjeAdding both those here, before we start work on (possible) integrating with the off canvas solution.
Comment #59
spokjeSo what we've learned here is that
FilterCriteriaTestis not broken (enough) to make any difference.Not saying the approach in the patch for dialogs is wrong, just that it can't be tested with
FilterCriteriaTestComment #60
catchMediaLibraryTest::testButton() is a recently skipped random failure that checks for a dialog, so that might be a good one to try. #3351596: Skip Drupal\Tests\ckeditor5\FunctionalJavascript\MediaLibraryTest
Comment #61
spokjeComment #62
spokjeComment #63
spokjeSadly also this one doesn't seem broken enough to be used for any proof.
Comment #64
catchMaybe LayoutBuilderUiTest - just seen it come up:
https://www.drupal.org/pift-ci-job/2634951
If we can't get it to fail out of 1500 runs, it suggests the recent instability of all these tests might not be related to the changes in this patch though.
Comment #65
spokjeEven more: If we can't get
MediaLibraryTest::testButton()to fail once in 1500 times when run on it's own, I fear it looks like the failure there has to do with concurrent running other tests?Comment #66
nod_Looks like it's failing pretty well :D
60-ish failures
Comment #67
nod_got a potential fix for the issue in #65 over at #3350972: [random test failure] Drupal\Tests\layout_builder\FunctionalJavascript\LayoutBuilderUiTest::testReloadWithNoSections() which isn't quite an issue with the timing in tests.
Comment #69
quietone commentedJust fixing tag text.
Comment #70
herved commentedPerhaps a lead on how to reproduce this reliably: smaller screen height resolution seems to affect it a lot.
We have a huge suite of behat (selenium chromium) tests on a project at work. I wanted to change the resolution (from 1600x1200 to 1600x900) and noticed a lot of failures with modals. Traced it to the debounce (20ms) in Drupal.dialog.resetSize causing dialogs to bounce 2-3 times, then stumbled on this issue. In my case, the modal appears, selenium2 webdriver attempts to scroll in the modal to click on a link inside, but the modal repositions again before it can scroll and selenium throws a "move target out of bounds" error because the links is out of reach, still hidden below. (what a nightmare to debug).
I simply reverted to 1600x1200 for now, the modal seems more stable, way less repositioning for some reason.
Comment #71
herved commentedDoes #3472624: Error: cannot call methods on dialog prior to initialization; attempted to call method 'option' solve this?
Specifically the change to execute debounce immediately/on leading edge in dialog.position.js:
const autoResize = debounce(resetSize, 20, true);