Problem/Motivation

While working on #2757007: Convert all book web tests to BrowserTestBase, I discovered that, in a JavascriptTestBase test, it's impossible to swap 2 rows by dragging the lower over upper row. The reverse works: you can swap them by dragging the upper over the lower row.

This behaviour doesn't occur when testing manually

In order to unblock #2757007: Convert all book web tests to BrowserTestBase, I opened this dedicated issue for investigation but it can be also a starting point for a full draggable table test.

It's possible that this behaviour is caused by:

  1. a bug in our tabledrag.js implementation
  2. OR

  3. an upstream cause in \Behat\Mink\Element\NodeElement::dragTo()

I will let our JavaScript team to find the cause. I'm only providing here this starting test.

Proposed resolution

  1. Find the cause of this bug and fix if it's a Drupal bug or report upstream.
  2. Expand the test to cover all draggable table aspects like indenting, other actions test, etc.

Remaining tasks

None.

User interface changes

None.

API changes

None.

Data model changes

None.

CommentFileSizeAuthor
#46 drupal-tabledrag_testing-2769825-46.patch9.42 KBAndyF
#46 drupal-tabledrag_testing-2769825-46--FAIL.patch6.58 KBAndyF
#46 interdiff_41-46.txt4.45 KBAndyF
#41 drupal-tabledrag_testing-2769825-41.patch6.2 KBAndyF
#41 interdiff_35-41.txt622 bytesAndyF
#35 interdiff_32-35.txt618 bytesAndyF
#35 drupal-tabledrag_testing-2769825-35.patch6.12 KBAndyF
#28 interdiff_25-28.txt5.38 KBAndyF
#28 drupal-tabledrag_testing-2769825-28.patch6.24 KBAndyF
#28 drupal-tabledrag_testing-2769825-28-test-only.patch4.95 KBAndyF
#25 interdiff_18-25.txt2.24 KBAndyF
#25 drupal-tabledrag_testing-2769825-25.patch6.33 KBAndyF
#18 drupal-tabledrag_testing-2769825-18.patch6.05 KBAndyF
#18 drupal-tabledrag_testing-2769825-18-test-only.patch5.17 KBAndyF
#7 2769825-7-test.patch8.78 KBclaudiu.cristea
tabledrag.patch8.78 KBclaudiu.cristea
#32 interdiff_28-32.txt1.62 KBAndyF
#32 drupal-tabledrag_testing-2769825-32.patch6.22 KBAndyF
#48 interdiff_46-48.txt1.13 KBAndyF
#48 drupal-tabledrag_testing-2769825-48.patch9.27 KBAndyF
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

claudiu.cristea created an issue. See original summary.

claudiu.cristea’s picture

claudiu.cristea’s picture

Issue tags: +JavaScriptTest
claudiu.cristea’s picture

Title: [potential bug?] Draggable table test » Potential bug? Draggable table test
Issue summary: View changes
claudiu.cristea’s picture

Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, tabledrag.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
FileSize
8.78 KB

Forgot to add the package to the test module.

Status: Needs review » Needs work

The last submitted patch, 7: 2769825-7-test.patch, failed testing.

claudiu.cristea’s picture

OK, now #7 clearly shows the bug. Who's gonna take it? :)

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

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now 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.

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

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now 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.

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.

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

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now 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.

pfrenssen’s picture

We are experiencing the same thing when testing table drag using Behat. The symptoms are exactly the same, we can drag from up to down, but not from down to up. Behat also uses Mink to interface with the browser.

Version: 8.6.x-dev » 8.7.x-dev

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

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

AndyF’s picture

I also came up against this in #3089151: TableDrag JS :first-of-type issues. If I understand correctly, when being tested with Mink's dragTo, the JS dragRow() is being called once per entire drag action (ie if you drag row 2 over row 1, that only triggers a single call to it). I think this unusual situation causes a bug to manifest where oldY is always initially 0, which means the direction is always down, which means the row ends up one row beneath where it should be when dragging upwards.

I've rerolled the test against latest and removed the initial set of weight assertions from testDragAndDrop() because all the rows start off with a zero weight (but I'm not sure if that's ideal: should we assert the zero weight, or make them have ascending weights?). It looks like a fix might be initialising oldY in dragStart().

Thanks!

claudiu.cristea’s picture

+++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
@@ -200,6 +287,32 @@ public function testTableDragChangedWarning() {
+    $ordered = implode(', ', array_map(function ($item) {
+      return "'$item'";
+    }, $items));
+    $this->assertSame($items, array_values($strings), "Found strings, ordered as: $ordered");

In PHPUnit the assertion message should describe the failure, not the success.

claudiu.cristea’s picture

More review.

  1. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -44,6 +45,92 @@ protected function setUp() {
    +    $page->findButton(t('Show row weights'))->click();
    ...
    +    $page->findButton(t('Hide row weights'))->click();
    

    We should not translate strings in tests.

  2. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -44,6 +45,92 @@ protected function setUp() {
    +    $session->wait(500);
    

    We should wait for something. E.g. a text or a piece of markup. See JSWebAssert::waitForElement() & Co.

  3. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -44,6 +45,92 @@ protected function setUp() {
    +    $this->getSession()->wait(500000);
    

    Wait at the end of the test?

claudiu.cristea’s picture

Status: Needs review » Needs work

Needs work for #20 & #21

AndyF’s picture

Thanks for the review!

I accidentally left the wait in from debugging the test. I didn't actually write any of the test (apart from that wait!), it's just a reroll of the original patch: I wanted to verify the fix got the existing test passing.

claudiu.cristea’s picture

No, it's me who wrote the tests 😂

AndyF’s picture

claudiu.cristea’s picture

+++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
@@ -200,6 +283,32 @@ public function testTableDragChangedWarning() {
+    $ordered = implode(', ', array_map(function ($item) {
+      return "'$item'";
+    }, $items));
+    $this->assertSame($items, array_values($strings), "Found strings incorrectly ordered as: $ordered");

If the message describes the the incorrect order then we should use $strings, not $items, when we build the $ordered var.

EDIT: Then probably we want other var name. E.g. $actual_order?

claudiu.cristea’s picture

Status: Needs review » Needs work
AndyF’s picture

If the message describes the the incorrect order then we should use $strings, not $items

Oh yes, well spotted, fixed! But having done that, I wonder if it makes sense to explicitly display the values at all: here's the output I got when I forced an error with the new patch:

Found strings incorrectly ordered as: 'Row with id 1', 'Row with id 2', 'Row with id 3'
Failed asserting that Array &0 (
    0 => 'Row with id 1'
    1 => 'Row with id 2'
    2 => 'Row with id 3'
) is identical to Array &0 (
    0 => 'Row with id 1'
    1 => 'Row with id 3'
    2 => 'Row with id 2'
).

Would it be better for the message just to be "Found strings incorrectly ordered."?

I also made some small changes to bring the tests more in line with what's already there. I chose not to use \Drupal\FunctionalJavascriptTests\TableDrag\TableDragTest::assertDraggableTable() because I thought it might be more functional (and less testing implementation) to just verify the order and not the actual weight values, dunno what others might think.

Thanks!

claudiu.cristea’s picture

Status: Needs review » Needs work

...I wonder if it makes sense to explicitly display the values at all: ...

Agree, let's remove the list from the error message.

Would it be better for the message just to be "Found strings incorrectly ordered."?

"Strings found on the page but incorrectly ordered." ?

claudiu.cristea’s picture

Nit.

+++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
@@ -44,6 +45,88 @@ protected function setUp() {
+    $page->findButton('Show row weights')->click();
...
+    $page->findButton('Hide row weights')->click();

We can use here:

$page->pressButton(...);
AndyF’s picture

"Strings found on the page but incorrectly ordered." ?

👍 Much better, thanks.

We can use here:
$page->pressButton(...);

Done.

claudiu.cristea’s picture

Version: 8.9.x-dev » 8.8.x-dev

As this is a bug, it should go in 8.8.x. I've also triggered a test for 8.8.x.

claudiu.cristea’s picture

Status: Needs review » Needs work
+++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
@@ -305,7 +305,7 @@
     $actual_order = implode(', ', array_map(function ($item) {
       return "'$item'";
     }, $strings));

This is dead code, right?

AndyF’s picture

claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

Thank you. As I've only signaled the bug, and provide a raw test to prove it, I think I'm eligible to RTBC this.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. The issue title needs updating
  2. +++ b/core/misc/tabledrag.es6.js
    @@ -760,6 +760,10 @@
    +    // Set the initial y coordinate so the direction can be calculated in
    +    // dragRow().
    +    self.oldY = self.pointerCoords(event).y;
    

    Given that there are runtime changes have we worked out why this bug is not triggered when testing manually.

  3. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -44,6 +45,88 @@ protected function setUp() {
       /**
    +   * Tests row weight switch.
    +   */
    +  public function testRowWeightSwitch() {
    

    This is additional unrelated testing as far as I can see? Is there any reason this had to be added here other than for improved test coverage?

  4. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -200,6 +283,29 @@ public function testTableDragChangedWarning() {
    +  protected function assertOrder(array $items) {
    +    $session = $this->getSession();
    +    $text = $session->getPage()->getHtml();
    +    $strings = [];
    +    foreach ($items as $item) {
    +      if (($pos = strpos($text, $item)) === FALSE) {
    +        throw new ExpectationException("Cannot find '$item' in the page", $session->getDriver());
    +      }
    +      $strings[$pos] = $item;
    +    }
    +    ksort($strings);
    +    $this->assertSame($items, array_values($strings), "Strings found on the page but incorrectly ordered.");
    +  }
    

    This is a nice implementation of this. I think we should consider adding this to \Drupal\Tests\WebAssert so we can do $this->assertSession()->someFunctionNameThatIHaveNotWorkedOutYet(array) in a follow-up.

    One thing that is interesting is should this work against the raw HTML or against the page text. I think it should probably be against the the text rather than the raw HTML. Not sure though. If we do change it then the exception should be ResponseTextException.

AndyF’s picture

Given that there are runtime changes have we worked out why this bug is not triggered when testing manually.

My understanding of what's going on here is that normally the dragRow() handler is called multiple times when being dragged manually:

    $(document).on('touchmove', function (event) {
      return self.dragRow(event.originalEvent.touches[0], self);
    });
    ...
    $(document).on('mousemove pointermove', function (event) {
      return self.dragRow(event, self);
    });

So while it will always think that initially you're moving the row down, that doesn't really matter because there will be another call to dragRow() at which point oldY will be valid and it can correctly work out the direction. It's Mink that creates the unusual behaviour that there's only a single event for the drag, and the bug manifests.

claudiu.cristea’s picture

Title: Potential bug? Draggable table test » Cannot swap tabledrag rows by dragging the lower over the upper row in tests

@alexpott

#37.1: Done.

#37.3:

This is additional unrelated testing as far as I can see? Is there any reason this had to be added here other than for improved test coverage?

When this issue has been created there was no draggable table test. So the initial scope was to start a test and also signal this potential bug. In the meantime a test has been added but I see that all existing tests are using the keyboard to manipulate the rows. We can remove the test but I wouldn't do it as it really expands the coverage.

#37.4: we already have #2817657: Add methods to assert that a sequence of strings appears on the page in a given order.

One thing that is interesting is should this work against the raw HTML or against the page text. I think it should probably be against the the text rather than the raw HTML. Not sure though.

In #2817657: Add methods to assert that a sequence of strings appears on the page in a given order we add both. But, we probably want to add a @todo to remove this function when #2817657: Add methods to assert that a sequence of strings appears on the page in a given order is in. If that goes first we just rework this patch to use it.

alexpott’s picture

Yep, @claudiu.cristea adding a @todo in this issue and adding a task to search for @todo's to the other issue is a good plan

+1 to keeping the additional test coverage I just wanted to check that I understood.

AndyF’s picture

Thanks @alexpott. I've added a todo to \Drupal\FunctionalJavascriptTests\TableDrag\TableDragTest::assertOrder() and added a task to #2817657: Add methods to assert that a sequence of strings appears on the page in a given order.

claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

Great! As all points were addressed, moving back to RTBC.

AndyF’s picture

It looks like the same issue might affect claro/js/tabledrag.es6.js, should that be a separate issue?

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

@AndyF great catch. We should definitely fix it here too.

claudiu.cristea’s picture

Issue tags: +Needs tests

+1 to fix it here. And, of course, we need test coverage to run with claro.

AndyF’s picture

I've had a go at that - turns out that Claro uses a link rather than a button for the Show row weights toggle. I've added a test method ::findWeightsToggle() so it can be overridden in the Claro test, but it did occur to me that we could instead use a looser xpath in the base test, perhaps one of these (untested):

$page->find('xpath', '//button[text()="Show row weights"] | //a[text()="Show row weights"]')->click();
$page->find('xpath', '//*[text()="Show row weights"]')->click();

I erred on the side of caution and currently the base test explicitly tests it's a button and the Claro test tests it's a link. Feedback welcome (:

I also took the opportunity to change the default value of oldY to null rather than 0, I think that makes sense as it should get explicitly set in dragStart() before use.

Thanks!

claudiu.cristea’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests
  1. +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php
    @@ -371,6 +371,21 @@
    +   * Find the show/hide weight toggle element.
    
    +++ b/core/tests/Drupal/FunctionalJavascriptTests/Theme/ClaroTableDragTest.php
    @@ -0,0 +1,34 @@
    + *
    

    s/Find/Finds

  2. +++ b/core/tests/Drupal/FunctionalJavascriptTests/Theme/ClaroTableDragTest.php
    @@ -0,0 +1,34 @@
    +    $this->container->get('theme_installer')->install(['claro']);
    +    $this->config('system.theme')->set('default', 'claro')->save();
    

    I think overriding the defaultTheme protected property should do the job. Still not sure.

AndyF’s picture

Thanks @claudiu.cristea

  1. Done.
  2. Yup, that works, thanks! I stole the lines I was using before from \Drupal\FunctionalJavascriptTests\Theme\ClaroMenuUiJavascriptTest, looking more closely 3 of the existing 4 Claro functional javascript tests do it that way, and \Drupal\FunctionalJavascriptTests\Theme\ClaroViewsUiTest uses $defaultTheme, not sure if there's any meaning to be read into that?
claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

...not sure if there's any meaning to be read into that?

I guess there's nothing else than the first 3 were written before $defaultTheme landed in https://www.drupal.org/node/3083055

Claro tabledrag is fixed too now and and also has test coverage. RTBC!

Thank you!

alexpott’s picture

Version: 8.8.x-dev » 8.9.x-dev
Status: Reviewed & tested by the community » Fixed

Committed and pushed 5b9cb9b7fb to 9.0.x and 912971406c to 8.9.x. Thanks!

diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Theme/ClaroTableDragTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Theme/ClaroTableDragTest.php
index 922c6b5b3c..c1e4fbe641 100644
--- a/core/tests/Drupal/FunctionalJavascriptTests/Theme/ClaroTableDragTest.php
+++ b/core/tests/Drupal/FunctionalJavascriptTests/Theme/ClaroTableDragTest.php
@@ -11,7 +11,7 @@
  *
  * @see \Drupal\FunctionalJavascriptTests\TableDrag\TableDragTest
  */
-class ClaroTableDragTest extends TableDragTest  {
+class ClaroTableDragTest extends TableDragTest {
 
   /**
    * {@inheritdoc}

Fixed coding standards on commit.

  • alexpott committed 5b9cb9b on 9.0.x
    Issue #2769825 by AndyF, claudiu.cristea, alexpott: Cannot swap...

  • alexpott committed 9129714 on 8.9.x
    Issue #2769825 by AndyF, claudiu.cristea, alexpott: Cannot swap...
claudiu.cristea’s picture

@alexpott, as this is a bug with tests, why it's not merged also in 8.8.x?

alexpott’s picture

Version: 8.9.x-dev » 8.8.x-dev
Status: Fixed » Patch (to be ported)

I think the bugfix here is not disruptive enough to consider for backport to 8.8.x and fixing JS testing for tabledrag interactions seems like a good thing to do.

Will ask other committers once 8.8.x is open again.

alexpott’s picture

Version: 8.8.x-dev » 8.9.x-dev
Status: Patch (to be ported) » Fixed

Discussed with @lauriii and we agreed that this was not affecting live sites so not worth backporting.

Status: Fixed » Closed (fixed)

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