Problem/Motivation

drupalPostAjaxForm() is simulating the behaviour of ajax.js, so using it, doesn't really provide fundamental guarantees.
#2809161: Convert Javascript/AJAX testing to use JavascriptTestBase suggests to convert them to JavascriptTestBase

Proposed resolution

  1. Figure out which part of the test is testing PHP code and which part ajax behaviour
  2. Extract the ajax behaviour into a test that extends JavascriptTestBase

Remaining tasks

User interface changes

API changes

Data model changes

CommentFileSizeAuthor
#60 2809503-60.patch63.7 KBLendude
#60 interdiff-2809503-57-60.txt1.5 KBLendude
#57 interdiff-2809503-51-57.txt601 bytesvoleger
#57 2809503-57.patch62.66 KBvoleger
#51 2809503-51.patch62.65 KBandypost
#51 interdiff.txt1.98 KBandypost
#50 2809503-49.patch62.61 KBandypost
#50 interdiff.txt1.62 KBandypost
#47 interdiff-2809503-39-47.txt5.75 KBvoleger
#47 2809503-47.patch62.66 KBvoleger
#39 2809503-39.patch61.65 KBmarkdorison
#38 interdiff-2809503-37-38.txt4.17 KBmarkdorison
#38 2809503-38.patch41.73 KBmarkdorison
#37 2809503-37.patch41.97 KBmarkdorison
#34 2809503-34.patch61.89 KBLendude
#34 interdiff-2809503-27-34.txt2.64 KBLendude
#27 2809503-27.patch60.58 KBLendude
#27 interdiff-2809503-23-27.txt2.55 KBLendude
#23 2809503-23.patch59.35 KBjibran
#23 interdiff-077cf3.txt4.99 KBjibran
#19 2809503-19.patch59.56 KBLendude
#19 interdiff-2809503-17-19.txt10.91 KBLendude
#17 2809503-17.patch70.83 KBLendude
#17 interdiff-2809503-15-17.txt2.41 KBLendude
#15 2809503-15.patch69.8 KBLendude
#15 interdiff-2809503-13-15.txt10.94 KBLendude
#13 2809503-13.patch58.53 KBLendude
#8 2809503-8.patch95.45 KBAnonymous (not verified)
#6 interdiff-5-6.txt20.63 KBAnonymous (not verified)
#6 2809503-6.patch85.15 KBAnonymous (not verified)
#5 2809503-5.patch70.07 KBAnonymous (not verified)
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner created an issue. See original summary.

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.

michielnugter’s picture

Component: phpunit » file system
Issue tags: +phpunit initiative

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.

Anonymous’s picture

Status: Active » Needs review
FileSize
70.07 KB

The first push :) This patch is not very convenient to read). But if someone is already working on this problem, then this stuff can be useful. Review some main points:


1.
FileFieldWidgetTest::testMultiValuedWidget() contains part of test, where we try to upload more files than allowed form via drupalPostForm. But in BTB:drupalPostForm() we can not test this, because it is blocked by Behat\Mink. We need to find some the most convenient alternative. Now this code is left in the simpletest location.
2.
A similar problem occurs in testTemporaryFileRemovalExploit() and testTemporaryFileRemovalExploitAnonymous(), where we need change hidden field, but it also prevent by Behat\Mink. I added a small hack to work around this. But this is only a temporary solution:
+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -806,7 +807,14 @@ protected function submitForm(array $edit, $submit, $form_html_id = NULL) {
-      $field = $assert_session->fieldExists($name, $form);
+      try {
+        $field = $assert_session->fieldExists($name, $form);
+      }
+      catch (ElementNotFoundException $e) {
+        // @todo: DON'T COMMIT WHILE WE HAVE IT!
+        $field = $assert_session->hiddenFieldExists($name, $form);
+      }

Also these tests have test coverage for nojs and js side. But I can not find any special behavior in javascript. All logical in the server side and does not depend on how the post-request is sent. Current patch implemented a separate tests for js, but perhaps this does not make sense. In the next patch it will be removed (or sent back to the simpletest before clarifying problem with send hidden fields?)


3.
Upload button not works now (it is hidden by default, and does not work show it by manual). So, the patch testing Remove button on visible, but not Upload. Also we already have few issues about the problems with javascript uploading:
4.
BTB:uploadNodeFiles has regression with name of submit button. How many tests will affect if revert it again?
+++ b/core/modules/file/tests/src/Functional/FileFieldTestBase.php
@@ -224,7 +146,8 @@ public function uploadNodeFiles(array $files, $field_name, $nid_or_type, $new_re
-    $this->drupalPostForm("node/$nid/edit", $edit, t('Save and keep published'));
+    $this->drupalPostForm("node/$nid/edit", $edit, t('Save'));


5.
FileFieldTestBase contains a couple of methods that would be useful in javascript tests too. Therefore, they are transferred to the TestFileCreationTrait:
  • createFileField()
  • attachFileField()
  • updateFileField()

7.
JS:testWidgetElement() contains some test based on uploading phase. It is possible to be better to made additional module, that will be return file by control, for more stable testing (sorry for the clumsy explanation).
Anonymous’s picture

This patch is still an unreadable (--find-copies do not help, because there are lots of whitespace changes). I will work on a step-by-step description later. Now I just wanted to share the last state.


Patch contains DrupalPostFormHack trait, which contains drupalPostFormHack(), which works like drupalPostForm() from simpletest. But with differences:
  • multipart Guzzle instead of cURL
  • \Behat\Mink\Element\NodeElement instead of \SimpleXMLElement
  • no ajax, headers, extra_post args (because i only ported the minimum for the test to work, this method is very raw now).
  • for save result after post request is used $postResponse instead of $this->setRawContent($content);, because i don't know how to implement setRawContent() in BTB. As result:
    Before:
    $this->drupalPostForm($url, $edit, $button);
    $this->assertRaw($message);

    After:

    $this->drupalPostFormHack($url, $edit, $button);
    $this->assertContains($message, (string) $this->postResponse->getBody());

In other words, I just stole the handleForm() from simpletest with replaces SimpleXMLElement/NodeElement API. And used this to prepare a multipart request through the Guzzle client.


Now we can fully port FileFieldWidgetTest, without BrowserTestBase::submitForm() modifications 🚀. This is possible, thanks to the replacement of the standard drupalPostForm() on drupalPostFormHack() in hack part of testMultiValuedWidget() and doTestTemporaryFileRemovalExploit().
Anonymous’s picture

Anonymous’s picture

Patch with #2917885: Add drupalPostFormWithInvalidOptions() to BrowserTestBase and #2919352: Move methods from FileFieldTestBase to Trait. Even if it is green, it still needs refactoring (for example, FileFieldTestBaseTrait are not used to the fullest while).

Anonymous’s picture

Title: Convert AJAX part of \Drupal\file\Tests\FileFieldWidgetTest to JavascriptTestBase » [PP-2] Convert AJAX part of \Drupal\file\Tests\FileFieldWidgetTest to JavascriptTestBase
Status: Needs review » Postponed

🎉 Green, woot! In fact, the patch contains very minor changes. I will present a readable interdiff after the dependent issues are solved:

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.

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.

Lendude’s picture

Title: [PP-2] Convert AJAX part of \Drupal\file\Tests\FileFieldWidgetTest to JavascriptTestBase » Convert AJAX part of \Drupal\file\Tests\FileFieldWidgetTest to JavascriptTestBase
Status: Postponed » Needs work

Taking this of postponed so we can take a fresh look at this. We've done some file conversions now, so maybe we can get this to work too now.

Lendude’s picture

Status: Needs work » Needs review
FileSize
58.53 KB

New stab at this, trying to make this more minimal.

I only converted part of the testMultiValuedWidget test to WebDriverTestBase since that seems like the most complex use case, all the others seem a little too much with the both js and nojs options.

testMultiValuedWidget tries to upload multiple files which Mink doesn't support (see https://github.com/minkphp/Mink/issues/358) because Selenium doesn't support it (see https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/...)

#2917885: Add drupalPostFormWithInvalidOptions() to BrowserTestBase was aimed at working around this, but that seems like massive overkill just for this and that would mean we need to maintain that too. Bah!

So this strips out the overloading of the file widget, so we lose coverage for that. There are no other tests for this (kernel/unit). So that is not good. If anybody has an idea how to tackle this, feel free to chime in!

Status: Needs review » Needs work

The last submitted patch, 13: 2809503-13.patch, failed testing. View results

Lendude’s picture

Status: Needs work » Needs review
FileSize
10.94 KB
69.8 KB

Ha!, so Mink doesn't support multiple file uploads, but Chromedriver does, so here is a Nightwatch test for it. Works on my machine, lets see if the bot can handle it!

Haven't fixed the other fail yet, just about nightwatch test for now.

Status: Needs review » Needs work

The last submitted patch, 15: 2809503-15.patch, failed testing. View results

Lendude’s picture

Status: Needs work » Needs review
FileSize
2.41 KB
70.83 KB

So the bot handles the Nightwatch test differently then local testing. I've borrowed from \Drupal\Tests\file\Functional\MultipleFileUploadTest how to do multiple file uploads. Doesn't quite work in our scenario since the raised error is a warning not a blocking error, it gets redirected to the node view page and the error is lost.

But we can verify that only 3 files are uploaded.

I would suggest using this version and try to get the nightwatch test running in a follow up. So removed that for now.

Status: Needs review » Needs work

The last submitted patch, 17: 2809503-17.patch, failed testing. View results

Lendude’s picture

Status: Needs work » Needs review
FileSize
10.91 KB
59.56 KB

Ok, now with the Nightwatch test really removed.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Patch seems ready to me.

The last submitted patch, 8: 2809503-8.patch, failed testing. View results

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Needs a reroll

Lendude’s picture

Status: Needs review » Reviewed & tested by the community

Thanks @jibran.

Reroll looks good, back to RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

So this strips out the overloading of the file widget, so we lose coverage for that. There are no other tests for this (kernel/unit). So that is not good. If anybody has an idea how to tackle this, feel free to chime in!

I think we need the nightwatch issue created and probably committed before we commit this one as we'd be losing test coverage.

I only converted part of the testMultiValuedWidget test to WebDriverTestBase since that seems like the most complex use case, all the others seem a little too much with the both js and nojs options.

This assumes the multi value widget and single value widget share the same codepaths both in JS and non-JS which would surprise me. Are we sure that losing this coverage is ok?

Lendude’s picture

Lendude’s picture

Status: Needs work » Needs review
FileSize
2.55 KB
60.58 KB

Added a javascript test for the single file widget.
Also cleaned up some stale comments.

the Nightwatch test can take a while to land I'm afraid, bot vs local.

Mixologic’s picture

I did a bunch of research over in https://www.drupal.org/project/drupal/issues/3028957, and I've come to the conclusion that we should probably be able to do this in a FunctionalJavascriptTest. Mink doesnt support uploading multiple files, and neither does nightwatch.js, so we'll have to do it ourselves.

We can add a new method to core/tests/Drupal/FunctionalJavascriptTests/DrupalSelenium2Driver.php that adds an additional behavior similar to "attachFile" https://github.com/minkphp/MinkSelenium2Driver/blob/a65a77efd76cce4fd1fd...

But one that accepts an xpath, and an array of filenames.
"attachMultipleFiles". It would do what uploadFile in the original driver does, except it would upload all the files to the remote chromedriver , (by mimicing what 'uploadFile' does here:

https://github.com/minkphp/MinkSelenium2Driver/blob/a65a77efd76cce4fd1fd..., and finally it would concatenate the filenames together with the \n's and set that to the value of the filefield button.

Then, we can use that similar to how we used attachFile directly in the quickedit test:
http://cgit.drupalcode.org/drupal/tree/core/modules/image/tests/src/Func...

Except, we'll have to step around Mink's implementation of attachFile (https://github.com/minkphp/Mink/blob/master/src/Element/NodeElement.php#...) and use our's directly on the driver.

so pseudo something like :

    $input = $this->assertSession()->elementExists('css', '#edit-field-test-image-0-upload');
    //loop from 1 to 4 for the 4 files
    $array_of_local_filepaths[] = $this->container->get('file_system')->realpath('test_image_0.png'); \\ whatever it is we do to provide files to tests
    $this->getSession()->getDriver()->attachMultipleFiles($xpath, $array_of_local_filepaths); \\ use our implementation of attachMultipleFiles
    // Submit the form

This is all a mess of pseudo code and ideas, but I dont see how else we're going to mimic uploading multiple files at the same time and also have our chrome instance be non local/not inside the SUT at all.

alexpott’s picture

How about we convert everything but the multiple upload test and then do that in a follow-up. So we only have one thing to focus on in that issue?

mondrake’s picture

Hi, not sure if this helps, but the test in #2644468: Multiple image upload breaks image dimensions is managing multiple files upload in the ImageWidget.

Mixologic’s picture

@alexpott: re #29: sure that makes sense, I had put it here because It was originally part of this test. And I think that work may already be done for us.

@mondrake re: #30 Awesome. Yes, that issue is doing pretty much exactly what I was imagining we'd need to do. I think the blocker to getting this last test in is actually #2947517: Selenium driver: API to get remote file paths, which appears to be pretty much the follow up we want, and it's already somewhat solved for us.

mondrake’s picture

#31 I'll bump #2947517: Selenium driver: API to get remote file paths to critical then, since that's a blocker for this and an helper for #2644468: Multiple image upload breaks image dimensions which is a crtical on its own.

Lendude’s picture

Tried the multiple file upload scenario with the method from #2947517: Selenium driver: API to get remote file paths, upload 4 files with cardinality 3 and got the expected error, so when that lands/works this should be trivial to test and there should be no need to split this.

Lendude’s picture

Thanks @all for all the research and digging done for this!

Here is a patch that should be green when #2947517: Selenium driver: API to get remote file paths lands.

Status: Needs review » Needs work

The last submitted patch, 34: 2809503-34.patch, failed testing. View results

jibran’s picture

+++ b/core/modules/file/tests/src/Functional/FileFieldWidgetTest.php
@@ -0,0 +1,536 @@
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);
...
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);
...
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);
...
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);
...
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);
...
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);
...
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);

These can be replaced with loadUnchanged.

markdorison’s picture

Status: Needs work » Needs review
FileSize
41.97 KB

Re-rolled #34.

markdorison’s picture

Incorporated suggestion from #36.

markdorison’s picture

FileSize
61.65 KB

Had accidentally removed FileFieldTestBase.php when re-rolling patch. Resolved that here.

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

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

Status: Needs review » Needs work

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

voleger’s picture

voleger’s picture

Status: Needs work » Needs review

Looks like #39 pass the tests. +1 for rtbc.

jibran’s picture

Needs some PHPCS love.

alexpott’s picture

Checking changed files...
PHPCS: core/modules/file/tests/src/Functional/FileFieldTestBase.php passed
PHPCS: core/modules/file/tests/src/Functional/FileFieldWidgetTest.php passed

FILE: ...ules/file/tests/src/FunctionalJavascript/FileFieldWidgetTest.php
----------------------------------------------------------------------
FOUND 25 ERRORS AFFECTING 25 LINES
----------------------------------------------------------------------
 153 | ERROR | [x] Line indented incorrectly; expected 2 spaces,
     |       |     found 0
 156 | ERROR | [x] Line indented incorrectly; expected 2 spaces,
     |       |     found 0
 157 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 158 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 159 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 160 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 162 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 163 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 165 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 166 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 167 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 168 | ERROR | [x] Line indented incorrectly; expected 6 spaces,
     |       |     found 4
 169 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 170 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 171 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 172 | ERROR | [x] Line indented incorrectly; expected 6 spaces,
     |       |     found 4
 173 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 175 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 176 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 177 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 178 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 179 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 180 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 186 | ERROR | [x] Line indented incorrectly; expected 4 spaces,
     |       |     found 2
 187 | ERROR | [x] Line indented incorrectly; expected 2 spaces,
     |       |     found 0
----------------------------------------------------------------------
PHPCBF CAN FIX THE 25 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Time: 50ms; Memory: 8Mb

Re #45

voleger’s picture

Status: Needs work » Needs review
FileSize
62.66 KB
5.75 KB

Addressed #46

andypost’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/file/tests/src/Functional/FileFieldTestBase.php
    @@ -20,10 +20,10 @@
    -  * Modules to enable.
    -  *
    -  * @var array
    -  */
    +   * Modules to enable.
    +   *
    +   * @var array
    +   */
    
    +++ b/core/modules/file/tests/src/Functional/FileFieldWidgetTest.php
    @@ -0,0 +1,528 @@
    +  /**
    +   * Modules to enable.
    +   *
    +   * @var array
    +   */
    +  public static $modules = ['comment', 'block'];
    

    should use inheritdoc

  2. +++ b/core/modules/file/tests/src/Functional/FileFieldWidgetTest.php
    @@ -0,0 +1,528 @@
    +  protected function setUp() {
    +    parent::setUp();
    +    $this->drupalPlaceBlock('system_breadcrumb_block');
    +  }
    

    should go after variables as we have it all over core

alexpott’s picture

public static $modules should be protected not public - whilst we're changing them

andypost’s picture

Status: Needs work » Needs review
FileSize
1.62 KB
62.61 KB

Fixed it

andypost’s picture

FileSize
1.98 KB
62.65 KB

Fix #49 and comments for test classes

Manuel Garcia’s picture

So excited this is the last one! Just a drive by review here:

+++ b/core/modules/file/tests/src/Functional/FileFieldWidgetTest.php
@@ -0,0 +1,525 @@
+    $this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
...
+    $this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
...
+    $this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
...
+    $this->assertResponse(403, 'Confirmed that access is denied for the file without the needed permission.');
...
+    $this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');

assertResponse() is deprecated, can we use $this->assertSession()->statusCodeEquals() instead?

+++ b/core/modules/file/tests/src/FunctionalJavascript/FileFieldWidgetTest.php
@@ -0,0 +1,205 @@
+    $this->adminUser = $this->drupalCreateUser(['access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer node fields', 'administer node display', 'administer nodes', 'bypass node access']);

Can we split these permissions into multiple lines?

Lendude’s picture

Please keep in mind we are still trying to do the minimal changes for this to pass, even though this is the last one and we all feel bad for it so we want to give it some extra love ;)

Manuel Garcia’s picture

lol, fair enough @Lendude :D

andypost’s picture

Still not sure about changes, this 2 files are new so should not use deprecated methods, but there's more - this methods has no second argument (message)
The same applies to assertRaw()

voleger’s picture

This issue is about conversion. Regarding #55 we have #3027952: [Plan] Remove the usage of deprecated methods in tests.

voleger’s picture

+++ b/core/modules/file/tests/src/Functional/FileFieldTestBase.php
@@ -44,6 +45,7 @@ protected function setUp() {
+   *   The new unsaved file entity.

+++ b/core/modules/file/tests/src/FunctionalJavascript/FileFieldWidgetTest.php
@@ -0,0 +1,205 @@
+   *   The File entity object.

The only thing that requires to be consistent.

+ 1 for rtbc

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, patch is looking good now so RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I've done a line-by-line comparision of the old test with the new tests and only one thing appears to be missing (and there might be a reason for that but it is not documented here). The JS part of ::testWidgetValidation() has not been converted to a test in \Drupal\Tests\file\FunctionalJavascript\FileFieldWidgetTest

Lendude’s picture

@alexpott spot on, yeah that got lost somewhere, added it.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Nice catch @alexpott. Interdiff looks good. As #59 is addressed so back to RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Thanks @Lendude - I checked the new test and it does match the old functionality.

 ___________________________________________________________________________________________________________________
< Committed http://cgit.drupalcode.org/drupal/commit/?id=a726a43 and pushed to 8.7.x. Thanks! >
 -------------------------------------------------------------------------------------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

yay... no... YAYAYAYAYAYAYAYAYAYAYAYYAYAYAYAYAYAYAYAYAY!

  • alexpott committed a726a43 on 8.7.x
    Issue #2809503 by Lendude, markdorison, voleger, andypost, jibran,...
Lendude’s picture

WOOOOOOOO!

Status: Fixed » Closed (fixed)

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