MDL-85658 behat: Wait until the iframe is completely loaded

This commit is contained in:
Huong Nguyen
2026-02-13 08:53:05 +07:00
parent 746815af49
commit 89fa7c1818
+62
View File
@@ -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_name_string>(?:[^"]|\\")*)" iframe is interactable$/
* @Given /^I wait until "(?P<iframe_name_string>(?:[^"]|\\")*)" 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 = <<<EOF
(function() {
const xpath = "{$iframexpath}";
const el = document.evaluate(
xpath,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;
if (!el) { return false; }
const rect = el.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) { return false; }
const x = rect.left + rect.width / 2;
const y = rect.top + rect.height / 2;
const target = document.elementFromPoint(x, y);
return target === el || el.contains(target);
})()
EOF;
return (bool) $this->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_name_string>(?:[^"]|\\")*)" iframe is interactable and switch to it$/
* @Given /^I wait until "(?P<iframe_name_string>(?:[^"]|\\")*)" 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.
*