From 7bfb575f633d5a828afd4be41525d7c16cbf60cb Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Tue, 22 May 2018 07:48:54 +0800 Subject: [PATCH] MDL-62514 behat: Add a wait_for_pending_js to form field --- lib/behat/behat_base.php | 36 ++++++++++++++--------- lib/behat/form_field/behat_form_field.php | 14 +++++++++ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lib/behat/behat_base.php b/lib/behat/behat_base.php index f1daac04d05..a6cca8ad2f1 100644 --- a/lib/behat/behat_base.php +++ b/lib/behat/behat_base.php @@ -28,10 +28,11 @@ // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. -use Behat\Mink\Exception\DriverException, - Behat\Mink\Exception\ExpectationException as ExpectationException, - Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException, - Behat\Mink\Element\NodeElement as NodeElement; +use Behat\Mink\Exception\DriverException; +use Behat\Mink\Exception\ExpectationException; +use Behat\Mink\Exception\ElementNotFoundException; +use Behat\Mink\Element\NodeElement; +use Behat\Mink\Session; /** * Steps definitions base class. @@ -709,23 +710,30 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext { /** * Waits for all the JS to be loaded. * - * @throws \Exception - * @throws NoSuchWindow - * @throws UnknownError - * @return bool True or false depending whether all the JS is loaded or not. + * @return bool Whether any JS is still pending completion. */ public function wait_for_pending_js() { - // Waiting for JS is only valid for JS scenarios. if (!$this->running_javascript()) { - return; + // JS is not available therefore there is nothing to wait for. + return false; } + return static::wait_for_pending_js_in_session($this->getSession()); + } + + /** + * Waits for all the JS to be loaded. + * + * @param Session $session The Mink Session where JS can be run + * @return bool Whether any JS is still pending completion. + */ + public static function wait_for_pending_js_in_session(Session $session) { // We don't use behat_base::spin() here as we don't want to end up with an exception // if the page & JSs don't finish loading properly. for ($i = 0; $i < self::EXTENDED_TIMEOUT * 10; $i++) { $pending = ''; try { - $jscode = ' + $jscode = trim(preg_replace('/\s+/', ' ', ' return (function() { if (typeof M === "undefined") { if (document.readyState === "complete") { @@ -740,8 +748,8 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext { } else { return "incomplete" } - }());'; - $pending = $this->getSession()->evaluateScript($jscode); + }());')); + $pending = $session->evaluateScript($jscode); } catch (NoSuchWindow $nsw) { // We catch an exception here, in case we just closed the window we were interacting with. // No javascript is running if there is no window right? @@ -762,7 +770,7 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext { usleep(100000); } - // Timeout waiting for JS to complete. It will be catched and forwarded to behat_hooks::i_look_for_exceptions(). + // Timeout waiting for JS to complete. It will be caught and forwarded to behat_hooks::i_look_for_exceptions(). // It is unlikely that Javascript code of a page or an AJAX request needs more than self::EXTENDED_TIMEOUT seconds // to be loaded, although when pages contains Javascript errors M.util.js_complete() can not be executed, so the // number of JS pending code and JS completed code will not match and we will reach this point. diff --git a/lib/behat/form_field/behat_form_field.php b/lib/behat/form_field/behat_form_field.php index 56d7124f117..d6da75c63c4 100644 --- a/lib/behat/form_field/behat_form_field.php +++ b/lib/behat/form_field/behat_form_field.php @@ -172,6 +172,20 @@ class behat_form_field { return get_class($this->session->getDriver()) !== 'Behat\Mink\Driver\GoutteDriver'; } + /** + * Waits for all the JS activity to be completed. + * + * @return bool Whether any JS is still pending completion. + */ + protected function wait_for_pending_js() { + if (!$this->running_javascript()) { + // JS is not available therefore there is nothing to wait for. + return false; + } + + return behat_base::wait_for_pending_js_in_session($this->session); + } + /** * Gets the field internal id used by selenium wire protocol. *