Problem/Motivation

The table drag handles are no longer keyboard-accessible. These are used in many places in the content-authoring and site-building UIs.

When table drag handles have focus, the up/down arrow keys should re-order the table rows. This has stopped working. It was working as of D8.0.0-beta10, and works in D7.43.

Where the table rows have a tree structure (e.g. menu UI) the left/right keys let a user change the indented (parent) relationship. The left/right keys are still working as expected.

Steps to Reproduce

Note: if testing with macOS, you'll need to make sure the tab key is configured to cycle focus through all links and controls - follow these Detailed instructions.

  1. Install 7.43
  2. Admin > Structure > Menus > Management >list links
    /#overlay=admin/structure/menu/manage/management
  3. Tab a bunch until focus is on the arrow(handle) for SubMenuItem (i.e. Dashboard)
    focusonhandle

Up Arrow

  1. Focus on Dashboard
  2. Press up arrow
    upfocusonhandle
  3. left/right arrow doesn't do anything

Down Arrow

  1. Focus on Dashboard
  2. Press down arrow
    downfocusonhandle
  3. left/right arrow doesn't do anything

Left/Right Arrow

  1. Focus on Dashboard
  2. Press down arrow a lot to get it under Taxonomy.
  3. left arrow does something
    yesleftfocusonhandle
  4. right arrow does something
    yesrightfocusonhandle

Proposed resolution

Restore the old keyboard behaviour:

  • When a drag handle has focus, up-down arrow keys change the vertical order of the table rows.
  • When drag handles are used on tree structures, the left/right keys can be used to control indentation.

Remaining tasks

  • Find out where the regression happened. - DONE. It was broken by commit dcf9ab4, between 8.0.0-beta11 and 8.0.0-beta12.
  • Fix it - restore old keyboard behaviour.

User interface changes

None as such. This is about restoring keyboard-accessible behaviour that stopped working. No changes are intended for pointing devices such as mice.

API changes

None.

Data model changes

None.

CommentFileSizeAuthor
#118 2725259-118.patch25.34 KBandrewmacpherson
#118 interdiff-2725259-1114-118.txt870 bytesandrewmacpherson
#116 interdiff-98-114.txt22.66 KBtedbow
#114 2725259-114.patch25.34 KBtedbow
#114 interdiff-109-114.txt15.05 KBtedbow
#109 2725259-109.patch30.13 KBtedbow
#109 interdiff-104-109.txt1.85 KBtedbow
#108 2725259-104-x50.patch32.25 KBtedbow
#106 2725259-106.patch26.98 KBtedbow
#106 interdiff-105-106.txt2.26 KBtedbow
#105 2725259-105.patch27.25 KBtedbow
#105 interdiff-98-105.txt5.5 KBtedbow
#104 interdiff-2725259-103-104.txt1.42 KBsardara
#104 2725259-104.patch30.36 KBsardara
#103 interdiff-2725259-98-103.txt5.22 KBsardara
#103 2725259-103.patch29.37 KBsardara
#98 interdiff-2725259-92-98.txt1.17 KBandrewmacpherson
#98 2725259-98.patch25.34 KBandrewmacpherson
#92 interdiff-2725259-87-92.txt1.06 KBandrewmacpherson
#92 2725259-92-tests-only.patch21.63 KBandrewmacpherson
#92 2725259-92.patch25.24 KBandrewmacpherson
#87 2725259-87-tests-only.patch21.92 KBandrewmacpherson
#87 interdiff-2725259-85-87.txt1.68 KBandrewmacpherson
#87 2725259-87.patch25.53 KBandrewmacpherson
#85 2725259-85.patch24.79 KBclaudiu.cristea
#84 2725259-84-8.6.x.patch24.89 KBclaudiu.cristea
#84 2725259-84.interdiff.txt838 bytesclaudiu.cristea
#84 2725259-84.patch24.82 KBclaudiu.cristea
#83 2725259-83-draggable-table-test-no-rows.png69.89 KBandrewmacpherson
#81 2725259-80-8.6.x.patch24.81 KBclaudiu.cristea
#80 2725259-80.interdiff.txt4.81 KBclaudiu.cristea
#80 2725259-80.patch24.73 KBclaudiu.cristea
#78 2725259-76.interdiff-61-78.txt845 bytesclaudiu.cristea
#78 2725259-78.patch24.5 KBclaudiu.cristea
#76 2725259-76.patch27.26 KBsardara
#74 2725259-74.patch27.26 KBsardara
#72 2725259-72.patch27.05 KBsardara
#69 interdiff_66-69.txt2.68 KBsardara
#69 2725259-69.patch26.54 KBsardara
#66 interdiff_61-66.txt3.42 KBsardara
#66 2725259-66.patch26.08 KBsardara
#8 tabledrag-arrow-fix.patch1.72 KBdroplet
#16 focusonhandle.png11.89 KBtechmsi
#16 downfocusonhandle.png13.38 KBtechmsi
#16 upfocusonhandle.png13.24 KBtechmsi
#16 yesleftfocusonhandle.png13.92 KBtechmsi
#16 noleftfocusonhandle.png14.12 KBtechmsi
#16 yesrightfocusonhandle.png14.07 KBtechmsi
#25 2725259-pre-patch.gif479.63 KBGrandmaGlassesRopeMan
#25 2725259-post-patch.gif595.29 KBGrandmaGlassesRopeMan
#30 2725259-30.patch1.66 KBeffulgentsia
#31 interdiff-2725259-30-31.txt4.81 KBGrandmaGlassesRopeMan
#31 2725259-31.patch3.4 KBGrandmaGlassesRopeMan
#43 Selection_239.png8.67 KBkwoxer
#43 Selection_240.png8.6 KBkwoxer
#44 Selection_241.png9.58 KBkwoxer
#46 Selection_242.png13.34 KBkwoxer
#58 2725259-58.patch3.48 KBsardara
#60 2725259-60-test-only.patch20.86 KBsardara
#61 2725259-61.patch24.34 KBsardara
#61 interdiff_58-61.txt20.12 KBsardara
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

andrewmacpherson created an issue. See original summary.

andrewmacpherson’s picture

Priority: Normal » Major

Prioritizing as major, because it affects a LOT of site-builder and content-editor tasks.

It's mitigated by the row weights fallback UI, but that's far more tedious to use. I expect this would be a big disappointment for keyboard users upgrading from D7 :-(

andrewmacpherson’s picture

Title: [regression] Table Drag handles no longer respon to up/down arrow keys » [regression] Table Drag handles no longer respond to up/down arrow keys
andrewmacpherson’s picture

Issue summary: View changes

Works in 8.0.0-beta10

andrewmacpherson’s picture

Issue summary: View changes

It stopped working by 8.0.0-beta12

andrewmacpherson’s picture

Issue summary: View changes
Related issues: +#2489826: tabledrag is broken

Git bisect narrows it down to commit dcf9ab4.

#2489826: tabledrag is broken

Oh, the irony ;-) That issue was about fixing the in-out nesting behaviour of tabledrag with tree nesting. The left/right arrow keyboard behaviour is indeed currently working in 8.1.1, but the up/down arrow keys are not.

andrewmacpherson’s picture

Issue summary: View changes
droplet’s picture

Status: Active » Needs review
FileSize
1.72 KB

My bad. Totally forget about keyboards testing

andrewmacpherson’s picture

@droplet Thanks. I'll test this soon.

andrewmacpherson’s picture

Status: Needs review » Reviewed & tested by the community

Looking good! I tried editing the administration menu (which has a tree) and the field UI for content types (single-level). Keyboard behaviour is fixed, and mouse-drag behaviour is still working as expected.

So far I've tested it with Firefox 46 and Chromium 49 on Linux. The patch only changes some jQuery which has good cross browser support, so let's RTBC this.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

Looks like the new JavascriptTestBase could be used here.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

droplet’s picture

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

techmsi’s picture

Bug Still exists

Keys up/down, right/left still don't work.

Area tested

  • Admin Menu

Tested on simplytest.me with & without patch

on Chrome 55

  • in drupal 7.43
  • in drupal 8.3.x

Patch doesn't make an item in the menu move with the arrow keys
On 7.43 without the patch, I cannot reproduce the key controls working.

techmsi’s picture

droplet’s picture

It works after patching (in Chrome 58). Ensure you've clean the caches.

xjm’s picture

Thanks @techmsi for the thorough issue update and testing steps! Adding issue credit.

xjm’s picture

Issue tags: +Triaged for D8 major current state
xjm’s picture

@techmsi, there was another contributor you looked at this issue during the sprint; do you know their username?

droplet’s picture

Status: Needs work » Needs review

I tested it on my Mac Chrome 55. Still working. If anyone could capture a GIF or VIDEO that will help.

Note: It won't drag on the single parent. For example in D8 Admin menu, you can't drop default "Administration".

Needed more debug info. Thanks ALL.

droplet’s picture

xjm’s picture

Issue tags: +Triaged core major

@catch, @cilefen, @alexpott, @Cottser, @lauriii and I discussed this issue and agreed that it is major priority due to the impact of the accessibility regression. Thanks @techmsi for helping get this triaged!

GrandmaGlassesRopeMan’s picture

Version: 8.3.x-dev » 8.4.x-dev
Assigned: Unassigned » GrandmaGlassesRopeMan

Reviewing.

GrandmaGlassesRopeMan’s picture

Assigned: GrandmaGlassesRopeMan » Unassigned
FileSize
479.63 KB
595.29 KB

Alright. Tested this in Chrome 58 on macOS. This probably still needs JS tests.

Prior to the patch the keyboard interaction behavior is a strange, as expected.

With the patch applied, the keyboard interaction behavior is what I would expect.

mgifford’s picture

Very nice visualization @drpal how did you make it?

We should include it more often.

droplet’s picture

@mgifford,

I'm not sure what @drpal used. But on MacOS, you can do it as simple as:
http://osxdaily.com/2013/06/21/mac-virtual-keyboard-os-x/

Windows:
https://support.microsoft.com/en-us/help/10762/windows-use-on-screen-key...
(Windows, only click with mouse has hover effect)

droplet’s picture

Status: Needs review » Needs work

Missing a test :)

mgifford’s picture

Thanks @droplet - no idea how I missed that.. Very useful!

effulgentsia’s picture

Status: Needs work » Needs review
FileSize
1.66 KB

#8 no longer applies. This is a straight reroll. It's not correct, since it doesn't include the change to the tabledrag.es6.js file, so if someone can reroll to include that, that would be awesome. Just posting this in the meantime for anyone wanting to do additional manual testing.

GrandmaGlassesRopeMan’s picture

- rerolled from #30 to include the changes in the *.es6.js file.

andrewmacpherson’s picture

Glad to see some more progress on this.

#25 - @droplet, I love the animated GIF evidence with on-screen keyboards!!!! Would love to see more of that in a11y issues, it's a great way to demonstrate bugs and fixes.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andrewmacpherson’s picture

Version: 8.5.x-dev » 8.4.x-dev

Bug, so eligible for 8.4.x

dawehner’s picture

While doing some manual testing I saw that up, down and right works as expected. Left has a little bit of a problem IMHO, it just goes up one level max.

I went to /admin/structure/menu/manage/admin and focused content. I was able to move it into admin/structure/content-types, but once I tried to move it out again the maximum level back as /admin/structure. Is this another level of the same bug basically, or should this be handled in its own issue?

GrandmaGlassesRopeMan’s picture

@dawehner Can you record that behavior? It might be a new bug.

droplet’s picture

@dawehner,

Can you use Mouse to do the same thing? and compare the behavior with D7 also.

GrandmaGlassesRopeMan’s picture

Issue tags: +Vienna2017
fisherman90’s picture

I'm trying to reproduce record the behavior described by @dawehner

geophysicist’s picture

Assigned: Unassigned » geophysicist
kwoxer’s picture

I'm reviewing this from the DrupalCon.

fisherman90’s picture

FileSize
5.49 MB

Here's my recording of the behavior after the patch 31 on 8.4.

@dawehner (#35) I think this isn't a bug maybe. Because if your element is in the second or third level and the left button is used - if it should go one level up then - it could result in a jump of the screen in long lists, which could confuse the user. Also we then have to assume if the element should go over or under it's previous parent element. The way it's now, the user has the control over it by moving the element up - before the parent element - or down - past the parent element and it's children.

Also, if the selected element is the last one in the parent's children, the left button works as expected, because then we can assume it should be sorted after the parent element.

For me it's in a usable state. What are your thoughts about it?

kwoxer’s picture

FileSize
8.67 KB
8.6 KB

Patch 31 works properly as @fisherman90 said and has a good usability.

Issues

There are still 2 issues, I would really appreciate being fixed in terms of usability.

Issue#1: Showing lines

There is just one more thing that would be amazing when also be done. So currently there are no lines showing the corresponding elements. As this really helps when moving elements, it would be great to always show them:
as it currently is

So currently thelines are just shown when arrow keys are used once:
as it should be

For me that does not make sense:

  1. for someone using the keyboard, at the very first use there is no lines feedback which is bad
  2. for someone switching from drag&drop to keyboard drag, it's confusing (currently shown when parent element is clicked)
  3. in general the lines would improve usability

Possible solutions:

  1. always show the lines
  2. show the lines when tab was used
  3. show the lines some element has been selected or some class on the DOM is placed or whatever

Issue#2: Visual feedback (exclamation mark) when move was forbidden

The other issue for keyboard using would be to give visual feedback when something went wront like going left was not possible like you see in that picture. Instead of just doing nothing there needs to be at least something to be happening like showing an information.

visual feedback needed

kwoxer’s picture

FileSize
9.58 KB
geophysicist’s picture

@kwoxer
You want to apply * for all child elements of cahnged menu item?

kwoxer’s picture

FileSize
13.34 KB
kwoxer’s picture

Hi @geophysicist no you get me wrong. I updated the pictures. So it's not about the asterisks. It's just about the lines. :)

geophysicist’s picture

I will try to apply some notifications when it's not possible to move items left.

fisherman90’s picture

We should put the visual feedback into a seperate issue, so that patch can go to RTBC once the accessibility group was looking over it. @geophysicist ok?

kwoxer’s picture

kwoxer’s picture

lmendes-omibee’s picture

Patch is tested and working in Drupal 8.4 - MacOS Chrome. Safari and Firefox on MacOS won't focus the arrows unless the accessibility settings in the browser are updated. Example: https://stackoverflow.com/a/11713537

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

joshmiller’s picture

Assigned: geophysicist » Unassigned
Status: Needs review » Needs work

assumed unassigned after months of inactivity.

Also, needs accessibility work according to above feedback.

andrewmacpherson’s picture

Issue summary: View changes

@joshmiller - fixing accessibility is the entire point of this issue :-) Keyboard control of the tabledrag handle is broken in all browsers, and was previously working in D7 and D8 beta.

The macOS setting in #52 is useful to know about if you're doing manual testing of patches here. I added it in the issue summary.

But the macOS setting isn't part of the bug here. Background story:

This has been the behaviour of mac Safari for at least 7 years. Safari gained a behaviour where users could choose between making links and form controls tab-able, or just form controls. Apple marketed it as "advanced form control" or something. Later the setting was moved to the system preferences, and eventually other browsers on OS X started respecting this system preference too.

It's not up to us to try and work around such OS-level user preferences. Mac users who rely on keyboard-only control will need to have this user preference enabled in order to navigate any website at all, not just Drupal's tabledrag handles. We just have assume the OS-level preference is set to tab though links.

On Windows and Linux browsers, this user preference doesn't exist. The tab key takes you though all links and form controls. Macs used to behave this way too once. Why Apple introduced the setting is something I've never quite understood. I think it has to do with making things easier for people who generally use a mouse pointer, but like to use the tab key when completing forms. Data entry by people who don't have motor disabilities.

Anyway, the macOS setting is a red herring as far as this bug is concerned.

mgifford’s picture

Wonder if it might make sense to think about a solution that works with #2920006: Research accessibility of drag-and-drop grid interfaces. too.

claudiu.cristea’s picture

sardara’s picture

Status: Needs work » Needs review
FileSize
3.48 KB

Re-rolling against 8.5.x. Setting needs review just for the bot, the patch still misses tests.

sardara’s picture

Status: Needs review » Needs work

Back to needs work for the tests.

sardara’s picture

Status: Needs work » Needs review
FileSize
20.86 KB

Wrote tests to cover keyboard accessibility.
As @claudiu pointed out in the related issue #2769825: Cannot swap tabledrag rows by dragging the lower over the upper row in tests there are issue dragging items from a lower row to an upper one, so I also added the root - leaf test to cover that part too. It's missing test coverage regarding grouped items though, as that adds a bit extra complexity due to the grouping itself and I ran out of time for now.

Note: I took the test module code from #2769825: Cannot swap tabledrag rows by dragging the lower over the upper row in tests written by @claudiu and adapted it.

sardara’s picture

Adding the full patch and the interdiff with #58 just to show that there were no additional changes.

The last submitted patch, 60: 2725259-60-test-only.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

The last submitted patch, 61: 2725259-61.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

sardara’s picture

Status: Needs review » Needs work

Looking into the failures.

sardara’s picture

Assigned: Unassigned » sardara
sardara’s picture

Adding a drupalci.yml to try to debug the failures. Also replaced assertions.

sardara’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 66: 2725259-66.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

sardara’s picture

sardara’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 69: 2725259-69.patch, failed testing. View results

sardara’s picture

Status: Needs work » Needs review
FileSize
27.05 KB

This is really strange. Trying to get the browser output again.

Status: Needs review » Needs work

The last submitted patch, 72: 2725259-72.patch, failed testing. View results

sardara’s picture

Status: Needs work » Needs review
FileSize
27.26 KB

Still trying to get the proper drupalci.yml in.

Status: Needs review » Needs work

The last submitted patch, 74: 2725259-74.patch, failed testing. View results

sardara’s picture

Status: Needs work » Needs review
FileSize
27.26 KB

Ops, the latest patch accidentally included a wrong selector. In the meantime I managed to reproduce the issue locally. The CI runs chromedriver with --headless. If I do the same, the test fails. I'll look into it.

Status: Needs review » Needs work

The last submitted patch, 76: 2725259-76.patch, failed testing. View results

claudiu.cristea’s picture

Status: Needs work » Needs review
FileSize
24.5 KB
845 bytes

This is a patch against #61.

claudiu.cristea’s picture

Assigned: sardara » Unassigned
claudiu.cristea’s picture

Adding the changes from #66 and #69.

claudiu.cristea’s picture

The 8.6.x version of #80.

claudiu.cristea’s picture

Ready for RTBC.

andrewmacpherson’s picture

Status: Needs review » Needs work
Issue tags: -Needs accessibility review
FileSize
69.89 KB

Thanks for moving forward with writing the tests!

I did manual testing with latest Firefox and Chrome on Linux, and I'm happy with it the behaviour. I tested both nested tables (the administration menu) and flat tables (display fields for article), with keyboard and mouse.

Something I want to check: has manual cross-browser testing been done? I haven't tried with IE, Edge, or Safari. Or touch screens.

I don't understand the draggable table test module - it doesn't have any rows! Here's a screenshot of what I see:

It seems that that TableDragTestForm::buildForm() only outputs rows if some state is set, and this gets done programatically by the methods in the functional JS test class.
I think this test module should be set up so we can do manual testing with it too - test modules aren't just for the testbots (we did a lot of manual testing on various test modules while getting inline form errors ready, for instance).
If the FunctionalJS tests need particular states, that's fine, but it would be good if there was an output format for when no state was available. Or maybe we could have a couple of test tables (one nested, one flat), and put these in primary tabs on the test page?

claudiu.cristea’s picture

I disagree that testing modules *should* necessary work by their own. However, I added a default set of 5 rows to the table. Tests are overriding with their rows.

claudiu.cristea’s picture

Version: 8.5.x-dev » 8.6.x-dev
FileSize
24.79 KB

Reroll and moved the bug in 8.6.x.

andrewmacpherson’s picture

Review of patch#85:

I did another round of manual testing, and covered all our supported desktop browsers on Windows 10 and macOS High Sierra. I also tested it with Android 8 + Chrome on a phone, with a USB keyboard. All good. I haven't tested it on iOS because I didn't have a Bluetooth keyboard handy.

Thanks for updating the test module. The default rows in the test module really helped me understand what was going on in the tests (by following them manually). We still don't have many keyboard accessibility tests, so this was really useful.

I think the tests in #85 cover all the possible movements, except for the scenario where you move a row which has nested children. So I've added one of those movements, after the sequence we already have.

+    // Nesting should be allowed to maximum level 3.
     $this->moveRowWithKeyboard($this->findRowById(4), 'right', 4);

Nit: we're expecting level 2. I changed this comment in this patch.

It's good to see that Mink NodeElement::keyPress() works as expected with the WebDriverTestBase. The PhantomJS driver is buggy with key events.

andrewmacpherson’s picture

Status: Needs review » Needs work

The last submitted patch, 87: 2725259-87-tests-only.patch, failed testing. View results

andrewmacpherson’s picture

Status: Needs work » Needs review

Last comment has a passing patch, and a failing tests-only patch, to confuse the bots.

sardara’s picture

@andrewmacpherson good to add at least one test for the nested children. I took it initially out that part because the nesting functionality has many scenarios to cover.
I am actually not happy about the code I wrote in assertTableRow() line 281-283. When the tests are asserting that nothing is changed, those lines will wait pointlessly. We should try to remove them.

andrewmacpherson’s picture

@sardara: These ones? I noticed them when I was testing #85.

    // To wait until all the JS DOM manipulations are done, wait for the parent
    // input field to be updated.
    $row->waitFor(10, function () use ($row, $id, $parent) {
      return $row->find('xpath', "//input[@type='hidden'][@name='table[$id][parent]'][@value='{$parent}']");
    });

I couldn't understand why we needed to wait up to 10s here. There's already a wait of 500ms at the end of moveRowWithKeyboard(), so there's time for the DOM updates to complete before we even call assertDraggableTable().

This patch removes them. The tests still run fine on my machine, let's see how they do with the testbots here.

Status: Needs review » Needs work

The last submitted patch, 92: 2725259-92-tests-only.patch, failed testing. View results

andrewmacpherson’s picture

Status: Needs work » Needs review
claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

Perfect. I only did a reroll so I guess I can RTBC.

sardara’s picture

@andrewmacpherson yes those lines. They were added when trying to solve the failures on the tests, which were solved by @claudiu.cristea with the change of mink driver. So yes, they are useless.
Thanks for updating the patch!

GrandmaGlassesRopeMan’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/misc/tabledrag.es6.js
@@ -558,10 +558,10 @@
+          let $previousRow = $(self.rowObject.element).prev('tr').eq(0);

Looks like you forgot to run prettier.

andrewmacpherson’s picture

FileSize
25.34 KB
1.17 KB

Updated the es6 file with prettier. That's a new thing in my workflow.

I see that running yarn build:js afterwards doesn't result in any changes to the tabledrag.js file. Is that expected - prettier's just about the readability of the es6 source file?

andrewmacpherson’s picture

Status: Needs work » Needs review
claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

@andrewmacpherson Thank you

claudiu.cristea’s picture

Status: Reviewed & tested by the community » Needs review

One more thing after re-reading the patch. We should test also if the "You have unsaved changes." message is show on the page after a row drag.

Also...

+++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
@@ -0,0 +1,346 @@
+    $this->getSession()->wait(500);

This not a correct way to wait. We have to wait until some JS condition is met, not an amount of time.

volkswagenchick’s picture

Issue tags: +badcamp 2018

Tagging for badcamp, thanks

sardara’s picture

Version: 8.6.x-dev » 8.7.x-dev
FileSize
29.37 KB
5.22 KB

Tackling last remark from @claudiu.cristea.
Added a js library that adds an event to the row handle. Due to the order of inclusion of the js libraries, this event will be executed after the ones added by the tabledrag library.
In the php test a css class is added before moving a row, and then the test will wait until said class is removed by the script.
The tabledrag library allows to add custom handlers to be specified on some events, but we need one that gets executed even when no swapping/dragging happens. This is useful for tests when no changes should happen.
The test js library added only takes care of the "keydown" event, meaning that for now it works only when rows are moved through the keyboard, as this is what the test does. Further support can be added when needed.

sardara’s picture

Missed the remark about the changed warning. Attaching a patch with an extra test.

tedbow’s picture

  1. Re #103
    @sardara while this is clever way for test to wait for the changes I think if we can avoid our test depending on extra Javascript on the page we should

    I have changed assertDraggableTable() keep checking the structure of the table for 2 second until correct. This is similar to \Behat\Mink\Element\Element::waitFor() which is used by \Drupal\FunctionalJavascriptTests\JSWebAssert::waitForElement() and similar methods.

    Since the checks happen every .1 seconds most runs will only wait .1 seconds but the tests are running slow as we see random failures in DrupalCI the test will still pass.

  2. #104 looks good except.
    +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -241,6 +241,28 @@
    +    $this->moveRowWithKeyboard($this->findRowById(5), 'down');
    +    $this->assertSession()->pageTextNotContains('You have unsaved changes.');
    

    I think will still need to wait for this text to appear to avoid random test failures on DrupalCI

tedbow’s picture

  1. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -0,0 +1,402 @@
    +   * @return \Behat\Mink\Element\NodeElement|mixed|null
    +   *   The row element.
    

    This can't return a null if we assert it is not. Also because we passing it to moveRowWithKeyboard() so it will always be NodeElement

  2. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -0,0 +1,402 @@
    +    if (!$row) {
    +      throw new ElementNotFoundException($this->getSession(), 'row');
    +    }
    

    I am not sure why we are throwing exceptions vs just asserting that $row is not empty.

  3. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -0,0 +1,402 @@
    +    if (!in_array($arrow, ['left', 'right', 'up', 'down'])) {
    +      throw new \InvalidArgumentException('The arrow parameter must be one of "left", "right", "up" or "down".');
    +    }
    

    I think it would simpler just throw an exception if $keys[$arrow] is not set.

  4. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -0,0 +1,402 @@
    +    if (!$row) {
    +      throw new ElementNotFoundException($this->getSession(), 'row');
    +    }
    ...
    +      throw new \InvalidArgumentException('The arrow parameter must be one of "left", "right", "up" or "down".');
    

    I am not sure why we are throwing exceptions vs just asserting that $row is not empty.

sardara’s picture

Replying to #105 remarks:

1. Using an arbitrary amount of time is exactly what was asked by @claudiu.cristea to be avoided in #101. This is especially true because we have some parts of the test that verify that some rows cannot be moved. By depending on a real condition (the class being removed by JS) we are sure that the row wasn't moved.
2. Yes it should wait indeed as it happens on blur of the handle, which is after moving the row.

+++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
@@ -0,0 +1,402 @@
+    $this->assertEmpty($assert_session->waitForElement('css', '.messages--warning:contains("You have unsaved changes.")', 1000));

Isn't this subject to random failures on the CI anyway? It could take more than 1 second to show.

+++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
@@ -0,0 +1,402 @@
+    do {

This won't do. We have assertions where we check that rows are not moved under some conditions. This code still doesn't ensure that the table operations are over and it will return true over the first check. In those cases we would be relying on 2 seconds being enough time for JS to finish.

Replying to #106 remarks:

1. Yes indeed the function doc makes no sense, good catch.
2. Why use an assertEmpty() instead of throwing a proper exception of a specific type? I think using ElementNotFoundException is more correct and it's usually thrown in these scenarios. If we want to improve that, we should use \Behat\Mink\WebAssert::elementExists() which returns also the node given the xpath.
3. Agree.
4. I think this is duplicate of the first point.

tedbow’s picture

This is especially true because we have some parts of the test that verify that some rows cannot be moved.

I do see why my way won't work yet for this case.

The problem I mainly see with #104 is that our test covering Javascript code now depends on Javascript code that itself is not tested. If we can find a way to avoid that we should but maybe we can't.

Reviewing #104 locally again it is actually failing randomly for me on \Drupal\FunctionalJavascriptTests\TableDrag\TableDragTest::assertTableRow()
But not on the same line.

For now here is a version of 104 that will run only this test 50 times. To see if these random fails happen on DrupalCI.

tedbow’s picture

I am not sure what was happening locally for me. #108 seems to show no random test errors.

my comment

The problem I mainly see with #104 is that our test covering Javascript code now depends on Javascript code that itself is not tested. If we can find a way to avoid that we should but maybe we can't.

So maybe we can't

Switching back to @sardara's patch at #104 with just a couple of changes.

from my review on #106
1. fixed
2. If you search for "throw new ElementNotFoundException(" in core you there is only 1 instance outside of \Drupal\FunctionalJavascriptTests\JSWebAssert or \Drupal\Tests\WebAssert. If you search for $this->assertNotEmpty( you will find many instances where it is being used to check if expected element is not empty.

I think we should change just to make this more readable alongside other core tests.

fixed
3. fixed

sardara’s picture

@tedbow which errors are you getting? I only had issues if I touch the browser window while tests are running (as focus gets shifted around).

Regarding your comment

The problem I mainly see with #104 is that our test covering Javascript code now depends on Javascript code that itself is not tested. If we can find a way to avoid that we should but maybe we can't.

This test itself tests the extra JavaScript, because if the class added in the php code is not removed by the JS code the test will fail. So I think we are safe.

Regarding point 2 of #109, it's ok for me too to change it.

By the way, did the test run really 50 times? I see only 3.

tedbow’s picture

  1. @tedbow which errors are you getting? I only had issues if I touch the browser window while tests are running (as focus gets shifted around).

    This may have been the problem. I only noticed when the test browser was in the background.

  2. By the way, did the test run really 50 times? I see only 3.

    +++ b/core/drupalci.yml
    @@ -3,48 +3,15 @@
    -        testgroups: '--all'
    +        testgroups: '--class "Drupal\FunctionalJavascriptTests\TableDrag\TableDragTest"'
    ...
    +        repeat: 50
    

    Run only this test 50x

    Yeah the report page I don't think counts duplicate runs. this test class has 3 test methods so that is where it comes from. You have to click through to
    View results on dispatcher -> Console Output

    That will get you here: https://dispatcher.drupalci.org/job/drupal_patches/79372/console
    where you can see the test running and passing 50x.

GrandmaGlassesRopeMan’s picture

- JavaScript is 👍, these changes are minor and the test coverage appears to be robust.
- @andrewmacpherson, it looks like you've provided a number of reviews on the accessibility side of this patch.
- The two additional feature requests from #43 are part of a series of followups, #2912732: Table Drag always showing lines and #2912737: Table Drag showing visual feedback when move was forbidden

sardara’s picture

That will get you here: https://dispatcher.drupalci.org/job/drupal_patches/79372/console
where you can see the test running and passing 50x.

Oh yeah makes sense, thanks for the explanation!

tedbow’s picture

Sorry to change a test that is already passing but here are couple test changes that I think make the test more readable and more certain it is not passing just because the structure of the test.

  1. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -0,0 +1,413 @@
    +    $this->assertDraggableTable([
    +      ['id' => 1, 'weight' => 0, 'parent' => '', 'indentation' => 0, 'changed' => FALSE],
    +      ['id' => 2, 'weight' => -10, 'parent' => 1, 'indentation' => 1, 'changed' => TRUE],
    +      ['id' => 3, 'weight' => 0, 'parent' => '', 'indentation' => 0, 'changed' => FALSE],
    +      ['id' => 4, 'weight' => 0, 'parent' => '', 'indentation' => 0, 'changed' => FALSE],
    +      ['id' => 5, 'weight' => 0, 'parent' => '', 'indentation' => 0, 'changed' => FALSE],
    +    ]);
    

    Only 1 row in the table has changed here.
    But for anyone to really review this test assertion you have to actually confirm not only that row index 1 has changed you also have to confirm that all other rows have not changed.

    We could make this test more understandable by assigning the table structure to $expected_table at the beginning of the method and before every assert updating only the rows in $expected_table that actually should have been changed. This will help make sure the test is not working because of copy/paste error in any case.

    Changed in subsequent calls.

  2. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -0,0 +1,413 @@
    +    // Rows marked as root cannot be moved as children of another row.
    +    $this->moveRowWithKeyboard($this->findRowById(5), 'right');
    +    $this->assertDraggableTable([
    +      ['id' => 1, 'weight' => 0, 'parent' => '', 'indentation' => 0, 'changed' => FALSE],
    +      ['id' => 2, 'weight' => 0, 'parent' => 1, 'indentation' => 1, 'changed' => FALSE],
    +      ['id' => 3, 'weight' => 0, 'parent' => 1, 'indentation' => 1, 'changed' => FALSE],
    +      ['id' => 4, 'weight' => 0, 'parent' => '', 'indentation' => 0, 'changed' => FALSE],
    +      ['id' => 5, 'weight' => 0, 'parent' => '', 'indentation' => 0, 'changed' => FALSE],
    +    ]);
    

    Here we are asserting the table structure has not changed. But to review the test and make sure it is not passing because of problem in the test itself you actually have to make sure array passed to assertDraggableTable() is exactly the same as the previous call.

    Again we can fix this by using a variable $expected_table that we know hasn't changed(because it is not passed by reference).

sardara’s picture

I'm fine with the change even if I fail to see the issue as we are reviewing the patch so it's not hard to verify that the lines are correct.
Anyway let's go this way, but I would like to focus on getting this patch committed as the bug is quite severe, breaking accessibility to tables.

tedbow’s picture

FileSize
22.66 KB

Just adding an interdiff from 109 which is the last it was RTBC. It was just pushed back for test change not for the actual JS fix.

a lot of the diff is the test module that @sardara put in in #103 so that we can confirm that something did NOT move if it should not have. I pushed back on this but I am not convinced we need it as per #109

bnjmnm’s picture

Status: Needs review » Needs work

Two nits and I can RTBC it

  1. +++ b/core/modules/system/tests/modules/tabledrag_test/js/tabledrag_test.es6.js
    @@ -0,0 +1,21 @@
    + * Testing behaviours for tabledrag library.
    

    Change "behaviours" to "behaviors" to match Drupal's naming

  2. +++ b/core/modules/system/tests/modules/tabledrag_test/js/tabledrag_test.es6.js
    @@ -0,0 +1,21 @@
    +   *   Removes a test class from the handle elements to allow verifying that dragging operatios have been executed.
    

    Typo with "operatios"

andrewmacpherson’s picture

Status: Needs work » Needs review
FileSize
870 bytes
25.34 KB

Fixes #117.
Also wraps the docblock in comment in 117.2 to fit under 80 chars.

bnjmnm’s picture

Status: Needs review » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 118: 2725259-118.patch, failed testing. View results

tedbow’s picture

Status: Needs work » Reviewed & tested by the community

Setting back to RTBC because random unrelated fail in MediaStandardProfileTest. I checked and there doesn't to be anything related to a table drag there.

If test fails again it will automatically get kicked back.

alexpott’s picture

@lauriii asked me to look at this issue from a backport perspective.

  • The change is all about changing (‘tr:first-of-type’) to (‘tr’).eq(0) - this is a minimal change and is not API
  • There is excellent test coverage and the new test fails when run against the old code.
  • This is the only usage of the :first-of-type pseudo selector in core.

Therefore for +1 to commit and +1 to backporting to 8.6.x

alexpott’s picture

I ran the new test against 8.6.x locally and it passes.

  • lauriii committed 735aaca on 8.7.x
    Issue #2725259 by sardara, andrewmacpherson, claudiu.cristea, tedbow,...

  • lauriii committed 62e67b8 on 8.6.x
    Issue #2725259 by sardara, andrewmacpherson, claudiu.cristea, tedbow,...
lauriii’s picture

Status: Reviewed & tested by the community » Fixed

I think we should be safe backporting this since this only affects keyboard navigation code which prior to this change is completely broken. This is due to the fact that the selectors used before are simply broken. Using :first-of-type in .next() doesn't make sense since it has been designed to match the first of type inside their parent. This selector will simply never match because .next() can only match elements that are not the first element inside the parent element.

Thank you also for adding extensive test coverage for tabledrag. This will significantly improve the maintainability of this component.

Committed 735aaca and pushed to 8.7.x, as well as cherry-picked to 8.6.x. Thanks!

lauriii credited Cottser.

lauriii credited catch.

lauriii credited cilefen.

lauriii’s picture

Fixed commit credit

  • lauriii committed 9ecea57 on 8.7.x
    Revert "Issue #2725259 by sardara, andrewmacpherson, claudiu.cristea,...

  • lauriii committed 3f89a20 on 8.6.x
    Revert "Issue #2725259 by sardara, andrewmacpherson, claudiu.cristea,...

  • lauriii committed 8018374 on 8.7.x
    Issue #2725259 by sardara, andrewmacpherson, claudiu.cristea, tedbow,...

  • lauriii committed 65c0f9a on 8.6.x
    Issue #2725259 by sardara, andrewmacpherson, claudiu.cristea, tedbow,...
andrewmacpherson’s picture

Awesome! It's a huge relief to see this one fixed at last - it will have a very broad impact for accessibility and usability. Thanks to everyone who worked on this.

This fixes tabledrag for sighted keyboard users, but there are improvements we can make to help screen reader and speech control users, who still need to use the show-weights alternative. I opened #3027229: Modernize tabledrag accessibility. to follow this.

A significant outcome of this issue, is we now have a lot more insight into writing functional tests for keyboard operations, distinct from mouse operations. Prior to using WebDriver this was awkward anyway (Goutte keyboard driving was flaky). Between this issue and #2711907: [regression] Some ajax-enabled buttons are not keyboard operable, we now have enough experience to start expanding functional JS coverage for keyboard accessibility, using WebDriverTestBase or Nightwatch.

Committers: can you start asking for keyboard behaviour tests, wherever the patch involves a keyboard event in JS? You can tag issues with needs accessiblity review to get advice on expected behaviours. Meanwhile, I'll start a list of existing keyboard behaviour that we can write test cases for.

lauriii’s picture

@andrewmacpherson I think requiring tests for keyboard behavior is a good idea. We should open a new issue to add it to the Drupal core gates.

andrewmacpherson’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.