Time and time again, we've seen regressions being introduced to Quick Edit. I don't want to know how many hours of manual testing Jesse Beach, Théodore (nod) Biadala and I have done.
Back when Quick Edit was written, Drupal 8 (and its testing infrastructure) weren't capable of executing JS. So we could not write tests. Earlier this year, a few months ago, support for that was added.
#2421427: Improve the UX of Quick Editing single-valued image fields was committed yesterday. It introduced a new in-place editor plugin. It also introduced JS test coverage for that particular in-place editor. It's time we also add JS test coverage for the rest of Quick Edit. That'll allow us to add features with confidence, but also fix bugs with confidence.
For example, #2661880: Quick Edit doesn't work for Custom Blocks referenced by other Custom Blocks had an RTBC patch, which I un-RTBC'd. Because it should have test coverage. But without a body of tests to extend, that's difficult and even unreasonable. So I postponed it on this issue.
19 of the 36 open Quick Edit issues are bug reports. That's more than 50%. Adding test coverage for each (or at least most) of them would make Quick Edit infinitely more maintainable. This issue makes that much more feasible.
Comment | File | Size | Author |
---|---|---|---|
#110 | 2828528-109.patch | 39.59 KB | Anonymous (not verified) |
#107 | 2828528-107.patch | 43.3 KB | Anonymous (not verified) |
Comments
Comment #2
Wim LeersI'll be taking this on. I'm fairly far along already.
Note that Jesse Beach did write some test coverage for Quick Edit, it lives in the "Front-end Automated Testing" module that uses QUnit/Testswarm. See http://cgit.drupalcode.org/fat/tree/tests/edit.tests.js for the test coverage.
We won't be able to copy/paste that, not remotely. But we can ensure that most if not all of the assertions there will exist in the new test.
Comment #3
Wim LeersComment #4
Wim LeersComment #5
Wim LeersNot done yet, but pretty far along :)
Comment #6
Wim LeersI just spent half a day trying to modify the title field or body field via Quick Edit. And was *this* close to giving up.
Turns out that phantomjs's default keyboard events are not actually native, they're synthetic. And as such, they're not respected by contenteditable. This has been a long-standing issue:
\Zumba\Mink\Driver\PhantomJSDriver
, hence it seems impossible to even emulate non-synthetic events… which means there's no hope of testingcontenteditable
Eventually, I found a working work-around in http://sticksnglue.com/wordpress/phantomjs-1-9-and-keyboardevent/, combined with some hackery:
Comment #7
Wim LeersAfter quite a bit of struggling with just about everything else, because PhantomJS does not send any event natively, hence most JS doesn't actually work, I found work-arounds for everything that got in the way of testing a common scenario: fixing the title and adding a new tag, but also starting to quick edit a field without actually changing anything.
Comment #8
Wim LeersClean-up: move the test method up higher, the assertion helpers down below.
Comment #9
Wim LeersComment #12
Wim LeersThis does not capture every nuance of http://cgit.drupalcode.org/fat/tree/tests/edit.tests.js, but it gets the majority. In fact, it tests with much more confidence in most respects.
This should make it quite easy to add the test coverage that #2661880: Quick Edit doesn't work for Custom Blocks referenced by other Custom Blocks and #2466715: Displaying the same entity twice on one page doesn't work as expected need.
Comment #14
Wim LeersThis should be reviewed from 2 POVs:
Comment #15
samuel.mortensonJust read through the patch, looks good and the coverage is very thorough. So for "Does this set a good enough baseline of test coverage?", I would say yes!
As someone who has written a lot of Quick Edit patches for contrib, I wonder if we could move more of the logic in testArticleNode() to protected methods.
For example, in https://www.drupal.org/files/issues/panelizer-quickedit-2693163-10.patch (a patch to add Quick Edit support to Panelizer), I wrote the following to Quick Edit a text field:
If this patch had protected methods that were high-level, i.e. quickEditTextField($field_id, $new_text), I could extend QuickEditIntegrationTest and remove a lot of the code here. I also copy+pasted this code into #2815221: Add ability to use Quick Edit to the latest_revision route, which would also benefit from having more protected methods in QuickEditIntegrationTest.
Comment #16
Wim LeersOh, yes, definitely. I just ran out of steam.
You mean these two, right?
Should be moved to
typeInPlainTextEditor($css_selector, $text_to_append)
Should be moved to
typeInFormEditorTextInputField($input_name, $text_to_append)
Comment #17
samuel.mortensonYes, as many reusable methods as possible! Ideally in a child class I would be able to start Quick Edit, initiate editing on a field, change its value, and save without ever writing a selector.
Comment #18
Wim LeersDid the refactoring asked in #15, and described in #16+#17.
Comment #19
Wim LeersHaving done that, I went back to #15 and wondered about this:
What else could we move to protected methods, what else would be valuable?
This would definitely be helpful. An
awaitEntityInstanceFieldState($entity_type_id, $entity_id, $entity_instance_id, $field_name, $awaited_state)
method wouldbe very helpful for this.This could be an
awaitFormEditor()
method.This could be a
saveQuickEdit()
method.Comment #20
samuel.mortenson"What else could we move to protected methods, what else would be valuable?" I think this is subjective, but the general requirement I would have is that child classes would only be calling QuickEditIntegrationTest methods unless they're testing an edge case for Quick Edit, or a new inline editor.
For example, you added a typeInPlainTextEditor() method, but a chid class would still have to write routines to check the initial field states, initiate Quick Edit on a field, wait for Quick Edit to load, click save, and assert that saving is complete. Since you're the maintainer and I don't want to slow down the test coverage getting in, I'll leave it up to you to decide how abstract you get. :-) We can always work on this class in other issues if we need more methods.
One super tiny nit:
The comment says "title field", but this is actually testing that the field_tags field is a candidate for Quick Editing.
Comment #21
Wim LeersYes, but those things are part of the thing you want to assert anyway. And there are helpers already to do those things. It's quite likely that many tests will want to test modifying a title, so without
typeInPlainTextEditor()
, they'd all have to duplicate that logic.However, you're right that it's a tough thing to balance :)
Fixed the nit in #20 and did everything in #19.
Comment #22
Wim LeersShould this update the test coverage introduced by #2421427: Improve the UX of Quick Editing single-valued image fields?
Comment #23
Wim LeersI stupidly did not yet realize I hadn't split it up in a base class and a test class yet. Did that now.
Comment #24
Wim LeersAnd here is then the update for the test coverage introduced by #2421427: Improve the UX of Quick Editing single-valued image fields, so that that test coverage is also more strict and uses a pattern similar to that used here. It also adds a
QuickEditImageEditorTestTrait
so that other tests can more easily include tests of theimage
in-place editor (it lives on that trait instead of onQuickEditJavaScriptTestBase
because it's not guaranteed to be available: it's only available if theimage
module is installed).Comment #26
Wim LeersThat of course failed because #2421427: Improve the UX of Quick Editing single-valued image fields is a 8.3.x-only thing. The 8.2.x version of this patch should exclude those changes.
The final
@todo
:Finished that now too. This will make adding test coverage for #2661880: Quick Edit doesn't work for Custom Blocks referenced by other Custom Blocks a lot simpler.
Unassigning, because all done.
Comment #27
Wim LeersStill one hunk for 8.3.x snuck into the 8.2.x patch. Rerolled.
Comment #29
Wim LeersThis is a blocker for at least #2661880: Quick Edit doesn't work for Custom Blocks referenced by other Custom Blocks, #2314185: [PP-1] DrupalBehaviorError: attach ; quickedit: entityElement.get(...) is undefined and #2635712: Cannot use Quick Edit to delete an image.
Comment #30
Wim LeersI don't quite understand why #26's 8.3.x patch failed. It passes locally. Retesting.
Comment #32
samuel.mortensonI think this is a great start and I would RTBC it, but I notice there are two @todos still in the patch. Do those still need addressed?
Comment #33
Wim LeersI think this is indeed ready for RTBC… except that the patch is failing for 8.3.x on testbot, but is passing locally :(
One of the @todos was more of a nice-to-have, the other one I created an issue for and linked to it in this reroll.
Comment #35
Wim LeersI'm sensing a case-sensitivity bug here, but I'm not seeing it.
Comment #36
Wim LeersI've triple-checked the case-sensitive stuff here. The filenames and classnames all have consistent casing. I have no idea what I can do anymore to push this forward. I pinged a testbot maintainer on IRC, hopefully he'll have insights:
Comment #37
Wim LeersMixologic didn't see any problems, but he noticed that it's strange to have
class QuickEditJavaScriptTestBase extends JavascriptTestBase {
, where one hasJavaScript
and the other hasJavascript
. So, making that consistent.It wouldn't make sense if this would fix it, but … here's hoping anyway :)
Comment #39
Wim LeersStill the same, as expected. I wish I was wrong :(
Comment #40
droplet CreditAttribution: droplet commentedTesting
Comment #42
michielnugter CreditAttribution: michielnugter as a volunteer and at Synetic commentedI took a quick look at the test and QuickEditIntegrationTest::testArticleNode() consistantly fails for me on PHP 7.
Looking at the test it seems that there should be a wait before the assertEquals()? It looks like it's still busy processing the request..
BTW: typeInFormEditorTextInputField() seems like it could use a waitForDebounce() (or #2837676: Provide a better way to validate all javascript activity is completed) as the formUpdated event will be triggered eventually (after the debounce finishes).
EDIT: I got the getText() error also once, randomly. To me it looks like there are some javascript waits missing?
Comment #43
Wim Leers#40: Can you provide an interdiff? What did you change?
#42: no, the failure on 8.3.x is not due to random fails. If you look at the full log for #37's 8.3.x patch, you'll see this:
So it's PHP not being able to find a certain class, for a reason I can't figure out.
Comment #45
Wim LeersReuploading #40's patches to see if something has changed (HOPEFULLY!).
Comment #48
ZeiP CreditAttribution: ZeiP at Citrus Solutions Oy commentedLet's try this.
Comment #50
ZeiP CreditAttribution: ZeiP at Citrus Solutions Oy commentedWell, it wasn't the same error, so I think the fix might've worked, but there's still something wrong. Let's try a new patch with the coding standards errors fixed.
Comment #52
ZeiP CreditAttribution: ZeiP at Citrus Solutions Oy commentedJust testing if I could get a better error message from the testbot.
Comment #54
ZeiP CreditAttribution: ZeiP as a volunteer commentedI think this fixes finding the Bold button.
Comment #55
ZeiP CreditAttribution: ZeiP as a volunteer commentedComment #56
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedOkay, this seems to work now. Attached is an interdiff; basically I just changed the operator used to find the Bold button (because it seems to now include the keyboard shortcut in the title) and fixed some coding standards errors.
Ready for review.Edit: Never mind, forgot I added a bit of debug code in. I'll need to remove that, sorry!
Comment #58
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedTrying to use a new wait method to make sure the toolbar is available when asserting.
Comment #60
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedRetry with correct argument order.
Comment #61
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedOk, it seems that using waitForElement() fixed the occasional fail issue. Attached is a final patch and an interdiff for it, should be ready for review.
Comment #63
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedLet's try adding a few more waitForElements...
Comment #64
Wim LeersOMG thank you @ZeiP for getting this going again! Your work on this is immensely appreciated!
👏👍
Comment #66
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedHeh, thanks, no problem! :) Trying to get into contributing to core and this seemed like a nice issue for that. Unfortunately my work on this issue has been a bit spammy, because I couldn't get the JS tests to work properly in my local environment, and have to use testbot for running each iteration instead.
Hopefully won't take too many more trials to figure this out. Adding a more permanent idea of the debugging check; this allows us to see a more useful stack/error message from the testbot when the quickedit toolbar assertion fails. Let's try.
Comment #68
droplet CreditAttribution: droplet commented@ZeiP,
You could use this snippet to do a quick test
Comment #69
droplet CreditAttribution: droplet commentedI will provide interdiff later
Comment #70
droplet CreditAttribution: droplet commentedComment #71
droplet CreditAttribution: droplet commented(Don't use this patch)
Comment #72
droplet CreditAttribution: droplet commentedAhh I got the problem. Needs some input from @wim since I don't familiar with quickedit Default behavior. (I thought it's a bug)
No "Title" when your mouse doesn't hover it
Comment #73
droplet CreditAttribution: droplet commented// Click the title field.
And on the test, it says `Click` but I can't see any click action on test.Comment #74
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedI added waitForElements() without creating the necessary object first; trying to fix that.
Comment #76
droplet CreditAttribution: droplet commentedMany errors in the test tho..
fixed few tests and see if any random fail on test bot. I guess it can be split and commit test without problems first
Comment #78
droplet CreditAttribution: droplet commentedEDITED: The problem on Title is fixed. Now it's failed on a diff point.
Comment #79
droplet CreditAttribution: droplet commentedDon't work on this patch. Use patch #78
I commented out the fail test and see how other tests performed. and then we able to go back and fix it quick.
Comment #80
droplet CreditAttribution: droplet commentedOne note:
$this->assertEntityInstanceFieldStates
the ordering of JS object/array doesn't matter. We should update this assertion to verify per object entry instead.
Comment #81
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedFor some reason #74 was missing the change I was trying to make there. Attached is the patch again, this time with the change present.
This change is missing all @droplet's work after #66.
Comment #82
droplet CreditAttribution: droplet commentedPatch #81 is equal to #68. But one GREEN, and one RED.
Trying to run it 30 times.
Comment #84
droplet CreditAttribution: droplet commentedTo check the failure rate. It's about 50/50
https://dispatcher.drupalci.org/job/drupal_patches/21546/console
Comment #85
ZeiP CreditAttribution: ZeiP as a volunteer and at Citrus Solutions Oy commentedRight, sorry – it isn't equal, but it indeed does the same thing. So the random fail problem still exists.
Comment #86
Wim LeersThanks so much for pushing this forward!
:( :( :(
Any ideas?
Comment #87
droplet CreditAttribution: droplet commentedno idea. I guess it's a PhantomJS bug. I tried:
- adding sleep(10), enough time to load everything in local
- use JS perform a click.
It always failed to this point:
https://github.com/drupal/drupal/blob/612c1fa68cfca2346c3d981383827278dc...
(hidden bug? I didn't dig into quickedit)
drop the label (Title) test for now I'd say.
Comment #88
tacituseu CreditAttribution: tacituseu commentedDid some debugging on testbot:
1. good run:
2. bad run:
3. weird run, with title repeated at the bottom:
4. weirder, with "Member for: 11 seconds":
5. even weirder, textfield and button under tags
All screenshots (patch).
Did find one bug/race producing similar result (toolbar without "TItle ->") and permanent error state, will describe steps to reproduce in next post.
Comment #89
tacituseu CreditAttribution: tacituseu commentedThere is a race/error state when clicking on the quickeditable field during toolbar's flight, to reproduce:
1. setup, give yourself some time/space (not needed - triggered even without this but makes it easier) by adding 200px margin, hover over the page/node title
2. click on 'Authored by' field to start the animation
3. before the toolbar reaches the target and loads the widget quickly click on the title again, results:
the toolbar is producing JS errors when moving cursor around to focus/unfocus the quickeditable fields, has no 'Title ->' prefix, and the close 'x' doesn't work.
Comment #90
droplet CreditAttribution: droplet commentedComment #91
droplet CreditAttribution: droplet commentedIt seems not the race issue on this failture
Comment #92
droplet CreditAttribution: droplet commentedTrigger with JS and then click on Title
Comment #93
droplet CreditAttribution: droplet commentedComment #94
droplet CreditAttribution: droplet commentedlast try today. Sadly, testbot has no more phantomjs.log?
Comment #96
tacituseu CreditAttribution: tacituseu commented@droplet: phantomjs logs were removed by f49a47f7.
In the meantime #2901626: CSS animations cause \Drupal\Tests\outside_in\FunctionalJavascript\OutsideInBlockFormTest random fails fixed? (not sure yet) similar issue by removing CSS animations for the test run.
Comment #97
Anonymous (not verified) CreditAttribution: Anonymous commented(opps, missed with issue, sorry)
Comment #98
Anonymous (not verified) CreditAttribution: Anonymous commentedDelightful work here! Let's continue.
Comment #99
Anonymous (not verified) CreditAttribution: Anonymous commented#98: Green!
Let's check with only #98.3 things + CS fixes.
Comment #101
Wim LeersClosed #2938308: Add QuickEdit Javascript tests as a duplicate.
Comment #102
Wim Leers#2917218: Test to prevent regression between quickedit and ckeditor landed, which added some Quick Edit JS test coverage. Hopefully that means we can land this too.
Comment #103
Anonymous (not verified) CreditAttribution: Anonymous commentedAttempt to convert the test to Selenium version resulted in the removal of most of my #98/#99 changes and the addition of new ones 🙂
Main of them:
A new 'hold_test' module has been added to freeze the response answer until the test checks all the necessary things (for example, 'Loading...' status).
It seems Phantomjs is not quite correctly processing what is happening on the page. Selenium is more sensitive, so more accurate states here (i hope).
It looks really crazy. But this is the short version, which I could find) Because Selenium cannot works with 'node text' type 😢
PhantomJS and Selenium display these values in different orders, so replacing strict
assertSame
with a more loyalassertEquals()
Unfortunately, I ran into an unclear problem when testing it on DrupalCI. Opened a separate issue for this #2957709: Selenium test fails on drupalLogin() command.
Comment #105
Anonymous (not verified) CreditAttribution: Anonymous commentedMy mistake is not enough
hold_test_response()
have been added. Also convert QuickEditImageTest to Selenium just for green tests. Main issue for this convertion is #2942900: Convert JavascriptTestBase Tests to use DrupalSelenium2Driver.Comment #106
Wim LeersThanks, @vaplas! 🎉🙏
Should this be removed once #2942900: Convert JavascriptTestBase Tests to use DrupalSelenium2Driver lands?
Comment #107
Anonymous (not verified) CreditAttribution: Anonymous commented#106: Absolutely! And since experience (bitter experience) shows that PhantomJS is not suitable for QuickEditor testing, then I suggest adding Selenium immediately at the
QuickEditJavascriptTestBase
with @todo per #106.This will also allow to get rid of the deprecated
initKeyboardEvent
trick intypeInPlainTextEditor
(although it's a pity to lose such wisdom 💡).Comment #108
Wim LeersCan't believe I lost track of this issue for so long, I'm very sorry!
Also, this is now reliably passing tests. I think it's high time to finally get this committed, so that we finally don't regress in Quick Edit anymore.
I last worked on this 1.5 years ago, so I think that makes me eligible to RTBC this.
Comment #109
Anonymous (not verified) CreditAttribution: Anonymous commentedO, you do not need an apology at all. You do the tone of work in other issues! And i'm absolutely ok with delay here :)
Comment #110
Anonymous (not verified) CreditAttribution: Anonymous commentedReroll after #2407859: Allow theming throbber element (just removed the
hold_test
module from patch).Comment #112
Anonymous (not verified) CreditAttribution: Anonymous commented#110 for 8.6.x only.
Comment #113
alexpottCrediting all the reviewers and contributors.
Comment #114
alexpottCommitted 522ab17 and pushed to 8.6.x. Thanks!
Comment #115
tacituseu CreditAttribution: tacituseu commentedPush got lost.
Comment #117
Wim Leers🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉