Some information that can help when writing Selenium tests (feel free to improve):


How to setup Selenium?


The golden rule for stable test

The golden rule remains the same: wait result after js-command, before continuing the test.

# BAD!
$page->pressButton('Show row weights');
$page->selectFieldOption('fields[name][region]', 'content');

# GOOD!
$page->pressButton('Show row weights');
$this->assertSession()->waitForElementVisible('css', '[name="fields[name][region]"]');
$page->selectFieldOption('fields[name][region]', 'content');

How to get response headers and status code?

TL;DR; Give up this desire.

Selenium driver does not support this feature (https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/141).
Yes, this is a super doubtful decision, but that's life.

Here is some list of ideas in case it is absolutely necessary:

  1. Move part of the test to a lower level (like BTB).
  2. Implement the logging of headers with the help-test-module (service listening to the Response event).
  3. Implement the logging with the browser settings (this seems to be able to Firefox, but not to Chrome).
  4. Get response headers via javascript code, when ajax request.
  5. Use proxy server, like BrowserMob.

Do not try to decorate any classes from vendor libraries (like instaclick/CurlService). They contain response headers to the request to the driver, but not to the site.


getText() returns empty string for unvisible elements

Therefore, you need to make sure that the element is visible before call $element->getText().
Another solution is a combination getHtml()/strip_tags().

In general, there is a high probability of failure Selenium test for most operations with invisible elements.


Selenium cannot get 'node text' type element.

You can find the element using the text() sign:

# OK!
$page->find('xpath', '//div[text()="I love Selenium"]'));

But you can not get a 'text' element.

# ERROR!
$page->find('css', '#message')->find('xpath', 'text()');

This can be difficult when you want to get outside tags text:

<div id="message">
  <span>trash trash</span>I love Selenium
</div>

For get 'I love Selenium' you can use various manipulations to delete tags-with-content, or JS script like:

$script = "return jQuery('#message').clone().children().remove().end().text();";
$result = $this->getSession()->evaluateScript($script));

Exception "StaleElementReference"

Unfortunately, I do not know the best solution to this problem (maybe you know?). It is officially considered that it occurs when you are working with an Mink-element that contains a reference to an obsolete HTML-element. But you can get it even with a newly received item :(

A few recommendations to little reduce it for problem places:

  • Before get element, make sure that all ajax requests done (assertWaitOnAjaxRequest(), meh).
  • Make several attempts using while() { try/catch }.

The width of the window is sometimes important.

For some css/js rules the width of the browser window is important. By default, the driver runs browser in a fairly narrow window, so be careful. You can use:

$this->getSession()->resizeWindow($width, $height);
#or
$this->getSession()->maximizeWindow()

But make sure that the operation done before page loaded (or js-script running).


The 'change'/'click' sometimes do not help

It's not so much about Selenium as Drupal note.

Sometimes for AJAX buttons you need an 'mousedown' event (#2616184-52: Right click should not submit buttons with Ajax behaviors). So, instead of $element->press() (or click()), you need something like:

$this->getSession()->executeScript('jQuery("YOUR-SELECTOR").mousedown();');

Sometimes, for AJAX events you need not only to set value, but also switch the focus, like:

$element->setValue();
$element->blur();

Sometimes, to get the desired effect (example, for hide contextual links), you need to simulate a cursor event:

$element->mouseOver();
$this->getSession()->executeScript("jQuery('YOUR-SELECTOR').trigger('mouseleave')");

Multiple upload file

More stable method to upload 1 file (because it better support remote path):
$field->attachFile($path_to_file);
For multiple upload you can use
$field->setValue(implode("\n", $array_with_paths);
For support remote path see #2947517: Selenium driver: API to get remote file paths.

CommentFileSizeAuthor
#4 dragTo.patch3.83 KBAnonymous (not verified)

Comments

Anonymous’s picture

vaplas created an issue. See original summary.

Anonymous’s picture

Issue summary: View changes
Mixologic’s picture

This is magnificent. Thank you for documenting all of this.

I started work on merging together the patch in #2942900-49: Convert JavascriptTestBase Tests to use DrupalSelenium2Driver with the existing work and rerolling, I ran into an issue where the tests would pass, but some would randomly fail with Exception "StaleElementReference"

After re-running the random fails I was able to determine that it was *always* related to the dragTo, and the three places it seems to happen is thus:

\Drupal\Tests\field_layout\FunctionalJavascript\FieldLayoutTest

$field_test_text_row->find('css', '.handle')->dragTo($second_region_row);

http://cgit.drupalcode.org/drupal/tree/core/modules/field_layout/tests/s...
$field_test_text_row->find('css', '.handle')->dragTo($first_region_row);
http://cgit.drupalcode.org/drupal/tree/core/modules/field_layout/tests/s...

and
\Drupal\Tests\field_ui\FunctionalJavascript\EntityDisplayTest
$extra_field_row->find('css', '.handle')->dragTo($disabled_region_row);
http://cgit.drupalcode.org/drupal/tree/core/modules/field_ui/tests/src/F...

Still investigating a solution to how to handle these dragTo fields, but I figured I would throw this out there as something to sort out.

Anonymous’s picture

StatusFileSize
new3.83 KB

Thank you, @Mixologic!

Unfortunately, I can not reproduce the error in these places (obviously due to the slower machine).

However, the our tabledrag.js (or rather field_ui.js) is also a pretty insidious thing. It completely changes the HTML of the table, which even results in the removal of the change messages (#2663738: Moving a field to another region clears the changed fields and message).

Therefore, there are two assumptions about how these places can be strengthened:

  1. Before working with page make sure that the tabledrag has already wrapped the fields.
  2. Before saving, make sure that the form_build_id has changed the value.

Attached the patch to their implementation.

PS:
And yes, looks like in all three places nothing is checked (except maybe risky-checking). Because "Save" button always leads to a 'Your settings have been saved.' message :)

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.

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.

cilefen’s picture

Title: FAQ Selenium tests » Document a FAQ for Selenium tests
Category: Support request » Task

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.

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

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.