From 3a713edefe68a5de5d9f5cc6c8d8a9d8f3f0d46b Mon Sep 17 00:00:00 2001 From: Huong Nguyen Date: Thu, 8 Jan 2026 09:49:49 +0700 Subject: [PATCH] MDL-85658 behat: Wait until the iframe is completely loaded --- public/lib/tests/behat/behat_general.php | 62 ++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/public/lib/tests/behat/behat_general.php b/public/lib/tests/behat/behat_general.php index 2c67a33668c..0561592f447 100644 --- a/public/lib/tests/behat/behat_general.php +++ b/public/lib/tests/behat/behat_general.php @@ -197,6 +197,8 @@ class behat_general extends behat_base { $this->execute_js_on_node($iframe, "{{ELEMENT}}.name = '{$iframename}';"); } $context->getSession()->switchToIFrame($iframename); + // Wait until the iframe is completely loaded and all pending operations complete. + $context->getSession()->wait(behat_base::get_extended_timeout(), behat_base::PAGE_READY_JS); // If no exception we are done. return true; @@ -205,6 +207,66 @@ class behat_general extends behat_base { ); } + /** + * Wait until the specified iframe is interactable (visible, sized, and not occluded). + * + * @Given /^I wait until "(?P(?:[^"]|\\")*)" iframe is interactable$/ + * @Given /^I wait until "(?P(?:[^"]|\\")*)" class iframe is interactable$/ + * @param string $name The name or class of the iframe + */ + public function wait_until_iframe_interactable(string $name): void { + if (!$this->running_javascript()) { + throw new DriverException( + 'iFrame interactability checks are disabled in scenarios without Javascript support', + ); + } + $this->spin( + function ($context) use ($name) { + $iframe = $context->find('iframe', $name); + $scrolljs = '{{ELEMENT}}.scrollIntoView({behavior: "auto", block: "center", inline: "center"});'; + $this->execute_js_on_node($iframe, $scrolljs); + $this->ensure_node_is_visible($iframe); + + // Check that the iframe is not occluded at its center point. + $iframexpath = $iframe->getXpath(); + $js = <<evaluate_script($js); + }, + behat_base::get_extended_timeout() + ); + } + + /** + * Wait until the specified iframe is interactable (visible, sized, and not occluded) and switche to it. + * + * @Given /^I wait until "(?P(?:[^"]|\\")*)" iframe is interactable and switch to it$/ + * @Given /^I wait until "(?P(?:[^"]|\\")*)" class iframe is interactable and switch to it$/ + * @param string $name The name of the iframe + */ + public function wait_until_iframe_interactable_and_switch_to(string $name): void { + $this->wait_until_iframe_interactable($name); + $this->switch_to_iframe($name); + } + /** * Switches to the main Moodle frame. *