Problem/Motivation

In #2925064: [1/2] JS codestyle: no-restricted-syntax we broke Drupal.behaviors.copyFieldValue(). It was fixed in #2941106: Site email address in the install profile form is no longer copied to the user email address but we should add test coverage so we don't break it again.

Proposed resolution

Add test coverage.

Remaining tasks

User interface changes

None

API changes

None

Data model changes

None

CommentFileSizeAuthor
#59 interdiff.txt1.57 KBlauriii
#59 2944089-59.patch4.1 KBlauriii
#57 interdiff_56-57.txt2.29 KBTanuj.
#57 2944089-57.patch4.2 KBTanuj.
#56 interdiff_51_56.txt2.35 KBAbhisheksingh27
#56 2944089-56.patch4.25 KBAbhisheksingh27
#51 interdiff_48-51.txt1.01 KBmrinalini9
#51 2944089-51.patch4.34 KBmrinalini9
#49 Screenshot 2023-03-09 at 6.56.38 PM.png137.8 KBSantosh_Verma
#48 2944089-48.patch4.45 KBsmustgrave
#48 interdiff-44-48.txt1.56 KBsmustgrave
#44 2944089-44.patch4.34 KBsmustgrave
#44 interdiff-42-44.txt1.22 KBsmustgrave
#42 2944089-42.patch4.53 KBsmustgrave
#42 interdiff-39-42.txt1.08 KBsmustgrave
#40 2944089-40.patch764 bytesNivethaSubramaniyan
#39 d8-test-behaviors-copyFieldValue-2944089-39.patch4.5 KBkarishmaamin
#28 interdiff-22-28.txt1.29 KBmsankhala
#28 d8-test-behaviors-copyFieldValue-2944089-28.patch4.47 KBmsankhala
#26 d8-test-behaviors-copyFieldValue-2944089-26.patch4.41 KBmsankhala
#22 d8-test-behaviors-copyFieldValue-2944089-22.patch4.41 KBmsankhala
#6 d8-test-behaviors-copyFieldValue-2944089-6.patch3.8 KBmsankhala
#9 d8-test-behaviors-copyFieldValue-2944089-9.patch5.89 KBmsankhala
#11 d8-test-behaviors-copyFieldValue-2944089-11.patch4.19 KBmsankhala
#16 d8-test-behaviors-copyFieldValue-2944089-16.patch4.71 KBmsankhala
#18 interdiff-16-18.txt2.96 KBAda Hernandez
#18 d8-test-behaviors-copyFieldValue-2944089-18.patch4.5 KBAda Hernandez
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alexpott created an issue. See original summary.

msankhala’s picture

Assigned: Unassigned » msankhala
msankhala’s picture

I tried writing Javascript test case for Drupal.behaviours.copyFieldValue Here is in progress code in gist https://gist.github.com/msankhala/e6bed178e64c4369b755eb4ef7a76088

I took core/tests/Drupal/FunctionalJavascriptTests/Core/Installer/Form/SelectProfileFormTest.php test case as starting point for this. I simply copied core/tests/Drupal/FunctionalJavascriptTests/Core/Installer/Form/SelectProfileFormTest.php
to core/tests/Drupal/FunctionalJavascriptTests/Core/Installer/Form/ConfigureSiteFormTest.php and created new method called testSiteEmailCopiedToAccountEmail() and started writing test scenario in this method.

I am not sure how to wait till Drupal installation is complete and redirected to Configure Site screen, where actually Drupal.behaviours.copyFieldValue is in action. Can someone guide me in this?

Or this should go into System module. Should i create new module inside core/modules/system/tests/modules which will provide form with two email fields and load this Javascript behaviour on that page and test it there? Because Drupal.behaviours.copyFieldValue is part of system module.

alexpott’s picture

@msankhala it'd be better to decouple the test from the installer. I think the test should set up a form and js to do this.

msankhala’s picture

@alexpott Thanks for your guide. I'll move this test to system module.

msankhala’s picture

Here is my first Drupal Functional Javascript test. I created a controller which simply return \Drupal\Core\Installer\Form\SiteConfigureFormand then tested Drupal.behaviors.copyFieldValuefunctionality on this form.

msankhala’s picture

Assigned: msankhala » Unassigned
Status: Active » Needs review
alexpott’s picture

@msankhala it'd be great to completely decouple from site configure form. We just need a form that uses the JS to test. Test is looking good. It would be good to include a test-only patch that reverts #2941106: Site email address in the install profile form is no longer copied to the user email address so we can see that the test is indeed testing the JS as promised.

msankhala’s picture

Thanks @alexpott for feedback. Here is new tests only patch. Now this does not uses \Drupal\Core\Installer\Form\SiteConfigureFormform anymore.

alexpott’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/system/tests/modules/site_configure_test/site_configure_test.info.yml
    @@ -0,0 +1,6 @@
    +name: 'Site Configure Test'
    

    Let's not base all of this around Site configure... In fact let's make this a part of the already existing system_test module.

  2. +++ b/core/modules/system/tests/modules/site_configure_test/src/Form/SiteConfigureTestForm.php
    @@ -0,0 +1,91 @@
    +class SiteConfigureTestForm extends FormBase {
    

    Let's call this CopyFieldValueTestForm.

  3. +++ b/core/modules/system/tests/modules/site_configure_test/src/Form/SiteConfigureTestForm.php
    @@ -0,0 +1,91 @@
    +    return 'site_configure_test_form';
    

    Let's return something different here. Based on the class name

  4. +++ b/core/modules/system/tests/modules/site_configure_test/src/Form/SiteConfigureTestForm.php
    @@ -0,0 +1,91 @@
    +   * Return only part of configure site form which is required to test
    +   * Drupal.behaviors.copyFieldValue.
    

    Let's not even call it configure site form. And in fact we can just simply the entire form to the two fields. They don't even need to be email fields.

    When this is done the docs here should be

    /**
     * {@inheritdoc}
     */
    
  5. +++ b/core/modules/system/tests/modules/site_configure_test/src/Form/SiteConfigureTestForm.php
    @@ -0,0 +1,91 @@
    +   * ¶
    

    Extra space on the line end.

msankhala’s picture

Status: Needs work » Needs review
FileSize
4.19 KB

Hi @alexpott yes this test can completely be decoupled from site configure form. Here is new patch as per your suggestion.

alexpott’s picture

Status: Needs review » Needs work
  1. Nice work decoupling from the site configure form
  2. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,40 @@
    +    $page->fillField('edit-source-field', 'admin@example.com');
    +    $this->assertEquals($source_field->getValue(), $target_field->getValue());
    +
    

    There is a possible timing issue here. After filling the field the JS will run async with the test. There's no helper to wait for an element value but we should wait. So we'll need to do something like:

      $page = $this->getSession()->getPage();
      $result = $page->waitFor(10, function () use ($page) {
        // Something that checks the field value... might need to pass in the assertSession into here too.
      });
    

    Also let's just use a random string since any random value should be copied instead of 'admin@example.com'.

  3. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,40 @@
    +    // Now target field is already filled. Now changing source field should not
    +    // change target field.
    +    $page->fillField('edit-source-field', '');
    +    $this->assertNotEquals($source_field->getValue(), $target_field->getValue());
    

    This is a tricky test. Not sure how to wait here because we are essentially waiting for nothing to happen. I think we'll have to add an explicit wait(1) and document why.

msankhala’s picture

@alexpott Isn't it advised to avoid waiting for a specific number of seconds?

I tried with waitFor as you suggested. This caused two things.

  1. Number of assertions increased from 4 to 103.
  2. If all the assertions run successfully then there is no issue but if i explicitly fail the second assertion by changing assertNotEquals to assertEquals then it breaks the test.
    // Test Drupal.behaviors.copyFieldValue. Check if source field is filled,
    // target field is also filled with same value.
    $page->fillField('edit-source-field', 'test@example.com');
    // After filling the field the JS will run async so add wait of 10s.
    $page->waitFor(10, function () use ($source_field, $target_field) {
      $this->assertEquals($source_field->getValue(), $target_field->getValue());
    });

    // Now target field is already filled. Now changing source field should not
    // change target field.
    $page->fillField('edit-source-field', '');
    // Adding explicit wait of 1s to allow js to update field.
    $page->waitFor(1, function () use ($source_field, $target_field) {
      $this->assertNotEquals($source_field->getValue(), $target_field->getValue());
    });
  }

This returns:

Testing Drupal\Tests\system\FunctionalJavascript\CopyFieldValueTest


Time: 19.51 seconds, Memory: 6.00MB

OK (1 test, 103 assertions)

Process finished with exit code 0

As you can see it is making 103 assertions.

In second assertion if i change assertNotEquals to assertEquals like:

    // Test Drupal.behaviors.copyFieldValue. Check if source field is filled,
    // target field is also filled with same value.
    $page->fillField('edit-source-field', 'test@example.com');
    // After filling the field the JS will run async so add wait of 10s.
    $page->waitFor(10, function () use ($source_field, $target_field) {
      $this->assertEquals($source_field->getValue(), $target_field->getValue());
    });

    // Now target field is already filled. Now changing source field should not
    // change target field.
    $page->fillField('edit-source-field', '');
    // Adding explicit wait of 1s to allow js to update field.
    $page->waitFor(1, function () use ($source_field, $target_field) {
      $this->assertEquals($source_field->getValue(), $target_field->getValue());
    });

This returns:

Testing Drupal\Tests\system\FunctionalJavascript\CopyFieldValueTest

PHP Fatal error:  Uncaught Exception: Serialization of 'Closure' is not allowed in -:68
Stack trace:
#0 -(68): serialize(Array)
#1 -(100): __phpunit_run_isolated_test()
#2 {main}
  thrown in - on line 68


Time: 18.37 seconds, Memory: 6.00MB
alexpott’s picture

@msankhala you shouldn't do an assert in the waitFor callback. You need to assert on the result of the waiting. The callback should return something falsey to continue waiting or something truthy to stop waiting. So for example:

    // Test Drupal.behaviors.copyFieldValue. Check if source field is filled,
    // target field is also filled with same value.
    $page->fillField('edit-source-field', 'test@example.com');
    // After filling the field the JS will run async so add wait of 10s.
    $this->assertTrue($page->waitFor(10, function () use ($source_field, $target_field) {
      return $source_field->getValue() == $target_field->getValue();
    }));

As noted there is nothing the second time to wait for so doing this is not going to work. Or I guess you could do:

    // After filling the field the JS will run async so add wait of 1s. Just to ensure the JS doesn't unexpected fill the field.
    $this->assertFalse($page->waitFor(1, function () use ($source_field, $target_field) {
      // This should never be TRUE.
      return $source_field->getValue() == $target_field->getValue();
    }));

However this code is no different to do sleep(1) because as stated you are testing that nothing has happened.

alexpott’s picture

After filling the field the JS will run async so add wait of 10s. this is also not quite right - we are waiting for up to 10secs for the fields to be equal. Under normal conditions this will never wait that long.

msankhala’s picture

Status: Needs work » Needs review
FileSize
4.71 KB

Thanks @alexpott for detailed feedback. I missed the whole point of waitFor and added assertion inside the callback. Here is updated patch. Please review.

alexpott’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/system/tests/modules/system_test/src/Form/CopyFieldValueTestForm.php
    @@ -0,0 +1,58 @@
    +<?php
    +
    +
    +namespace Drupal\system_test\Form;
    

    Too many lines.

  2. +++ b/core/modules/system/tests/modules/system_test/src/Form/CopyFieldValueTestForm.php
    @@ -0,0 +1,58 @@
    +
    +class CopyFieldValueTestForm extends FormBase {
    

    Should have some docs.

  3. +++ b/core/modules/system/tests/modules/system_test/src/Form/CopyFieldValueTestForm.php
    @@ -0,0 +1,58 @@
    +    $form['actions'] = ['#type' => 'actions'];
    +    $form['actions']['submit'] = [
    +      '#type' => 'submit',
    +      '#value' => $this->t('Save and continue'),
    +      '#button_type' => 'primary',
    +    ];
    

    I'm not sure this is necessary.

  4. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    +    // Retrieve the Configure site form page.
    

    This isn't true - don't really need a comment either.

  5. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    +    $random = new Random();
    +    $random_string = $random->string();
    ...
    +    $page->fillField('edit-source-field', $random_string);
    

    Can just be $page->fillField('edit-source-field', $this->randomString()); [EDIT] hmmm actually made we want the random string in a variable - see comment below.

  6. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    +      return $source_field->getValue() == $target_field->getValue();
    

    It could be worth asserting that
    $target_field->getValue() == $random_string instead since the fields both start with the same empty value.

  7. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    +      return $source_field->getValue() == $target_field->getValue();
    

    As above let's just do return $target_field->getValue() == '';

Ada Hernandez’s picture

Ada Hernandez’s picture

Status: Needs work » Needs review
alexpott’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
@@ -0,0 +1,52 @@
+    $random = new Random();
+    $random_string = $random->string();

$random_string = $this->randomString();
no need to create a new Random.

msankhala’s picture

+++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
@@ -0,0 +1,52 @@
+//      $random_string = '';

Remove comment.

msankhala’s picture

Status: Needs work » Needs review
FileSize
4.41 KB
  1. Removed comment.
  2. Removed $random = new Random(); object.
  3. created $source_field_selector variable.
yogen.prasad’s picture

Assigned: Unassigned » yogen.prasad
msankhala’s picture

Assigned: yogen.prasad » Unassigned

Can anyone review this?

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.

msankhala’s picture

Patch for 8.7.x. Even though nothing changed between 8.6.x to 8.7.x.

Status: Needs review » Needs work

The last submitted patch, 26: d8-test-behaviors-copyFieldValue-2944089-26.patch, failed testing. View results

msankhala’s picture

Here is the updated patch which fixes the failing test.

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.

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

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll
karishmaamin’s picture

Assigned: Unassigned » karishmaamin
karishmaamin’s picture

Assigned: karishmaamin » Unassigned
Status: Needs work » Needs review
FileSize
4.5 KB

Re-rolled patch against 10.1.x. Please review

NivethaSubramaniyan’s picture

Fixing CCF in #39

nod_’s picture

Status: Needs review » Needs work

Thanks NivethaSubramaniyan unfortunately you're missing many files from the previous patch.

smustgrave’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
1.08 KB
4.53 KB
nod_’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,55 @@
    +    // After filling the field the JS will run async so wait up to 10s.
    +    $this->assertTrue($page->waitFor(10, function () use ($target_field, $random_string) {
    +      return $target_field->getValue() == $random_string;
    +    }));
    

    Going with $this->assertTrue($target_field->getValue() == $ random_string); works.

    it needs to wait for the blur event on the source field, by the time $target_field->focus() is done, the blur event has already been executed (because of the order in which those event are spec'ed to occur).

  2. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,55 @@
    +    // After filling the field the JS will run async so add wait of 1s. Just to
    +    // ensure the JS doesn't unexpected fill the field.
    +    $this->assertFalse($page->waitFor(1, function () use ($target_field) {
    +      // This should never be TRUE.
    +      return $target_field->getValue() == '';
    

    Here we should probably check that the target field has the same value as before : $random_string that would allow us to remove the waitFor as well.

smustgrave’s picture

Status: Needs work » Needs review
FileSize
1.22 KB
4.34 KB

Addressed points in #43

nod_’s picture

Status: Needs review » Reviewed & tested by the community

looks good to me

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
@@ -0,0 +1,50 @@
+    // After filling the field the JS will run async so add wait of 1s. Just to
+    // ensure the JS doesn't unexpected fill the field.

There's no wait here... imo we should do the same focus as in the positive test case and that should be good as I think the fill field will move the focus back to the source field

smustgrave’s picture

So should it not wait?

smustgrave’s picture

Status: Needs work » Needs review
FileSize
1.56 KB
4.45 KB
Santosh_Verma’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
137.8 KB

reviewed the patch on comment #48, patch applied successfully on D10 and there is no functionality break in the website, can we merge now

longwave’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
@@ -0,0 +1,54 @@
+    $assert_session->assertWaitOnAjaxRequest();
...
+    $assert_session->assertWaitOnAjaxRequest();

There's no AJAX going on here so waiting for AJAX is pointless.

mrinalini9’s picture

Status: Needs work » Needs review
FileSize
4.34 KB
1.01 KB

Updated patch #48 by addressing #50, please review it.

Thanks!

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Even though I worked on the ticket, this was previously marked RTBC and the update was removing 2 lines so think I can still move it back to RTBC.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 51: 2944089-51.patch, failed testing. View results

smustgrave’s picture

Status: Needs work » Reviewed & tested by the community

Random failure

lauriii’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/system/tests/modules/system_test/src/Form/CopyFieldValueTestForm.php
    @@ -0,0 +1,53 @@
    +    // We are only testing the javascript part of form. We are not submitting
    
    +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    + * Tests copy field value javascript functionality works fine.
    ...
    +   * Tests copy field value javascript functionality.
    

    Nit: javascript should be replaced with JavaScript.

  2. +++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml
    --- /dev/null
    +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    
    +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    +    $assert_session = $this->assertSession();
    

    Unused variable.

  3. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    +    // Now focus target field.
    ...
    +    // Now focus target field.
    

    This comment is redundant because that's exactly how the following line would read..

  4. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    +    $this->assertTrue($target_field->getValue() == $random_string);
    ...
    +    $this->assertTrue($target_field->getValue() == $random_string);
    

    You can use $this->assertEquals() here 😇

  5. +++ b/core/modules/system/tests/src/FunctionalJavascript/CopyFieldValueTest.php
    @@ -0,0 +1,52 @@
    +    // After filling the field the JS will run async. Just to ensure the JS
    

    I'm not sure I understand this comment. Isn't the expectation that nothing happens to the target at this point? Why is this comment explaining that the JavaScript will run async?

Abhisheksingh27’s picture

Status: Needs work » Needs review
FileSize
4.25 KB
2.35 KB

Uploading updated #51 patch with suggested 1,2 and 3 changes in comment #55.

Tanuj.’s picture

#56 doesn't fix issues 1,4,5 mentioned in #55, re-uploading patch to fix all the mentioned issues, please review.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs Review Queue Initiative

#57 appears to address the points from #55

lauriii’s picture

Minor adjustments to code comments.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 59: 2944089-59.patch, failed testing. View results

smustgrave’s picture

Status: Needs work » Reviewed & tested by the community

Random failure.

  • nod_ committed f88d58b0 on 10.1.x
    Issue #2944089 by msankhala, smustgrave, lauriii, Ada Hernandez,...
nod_’s picture

Status: Reviewed & tested by the community » Fixed

Committed f88d58b and pushed to 10.1.x. Thanks!

Status: Fixed » Closed (fixed)

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