Как заставить behat подождать, пока элемент отобразится на экране, прежде чем заполнять его?
Когда я нажимаю на кнопку, открывается новая страница с формой, и мне нужно заполнить поле на этой странице.
Однако, как только страница начинает загружаться, behat пытается заполнить поле, которое еще не было загружено.
Я хотел бы поставить неявное ожидание, чтобы дождаться отображения поля, прежде чем пытаться его заполнить.
/**
* @Given que preencho corretamente os campos da tela
*/
public function quePreenchoCorretamenteOsCamposDaTela()
{
$faker = Faker\Factory::create();
$this->getPage()->findField('voucher_subject')->setValue($faker->text);
$this->getPage()->findField('voucher_nameRecipient')->setValue($faker->name);
}
Кто-нибудь может мне помочь?
3 answers
Вы можете использовать функцию вращения:
trait FeatureContextHelper
{
public function spin (callable $lambda, $wait = 5)
{
$lastErrorMessage = '';
for ($i = 0; $i < $wait; $i++) {
try {
if ($lambda($this)) {
return true;
}
} catch (Exception $e) {
// do nothing
$lastErrorMessage = $e->getMessage();
}
sleep(1);
}
throw new ElementNotVisible('The element is not visible ' . $lastErrorMessage);
}
}
Тогда в вашем контексте:
class FeatureContext extends MinkContext
{
use FeatureContextHelper;
/**
* @Given que preencho corretamente os campos da tela
*/
public function quePreenchoCorretamenteOsCamposDaTela()
{
$this->spin(function ($context) {
$faker = Faker\Factory::create();
$context->getSession()->getPage()->findField('voucher_subject')->setValue($faker->text);
$context->getSession()->getPage()->findField('voucher_nameRecipient')->setValue($faker->name);
return true;
}
}
}
Он попытается найти элемент в течение 5 секунд, а затем тайм-аут, если он его не нашел. Это очень хорошо работает для нас с Selenium2 и подагрой.
С моей точки зрения, теперь это можно сделать более элегантно:
$page = $this->getSession()->getPage();
$page->waitFor(5000,
function () use ($page) {
return $page->findField('voucher_subject')->isVisible();
}
);
Вы также можете обернуть это внутри некоторой функции private
.
Если вы используете драйвер, который только имитирует браузер (например, BrowserKit или Goutte), behat вернет управление только тогда, когда DOM будет правильно составлен и готов (и, конечно, никакой js не может быть интерпретирован или выполнен). Если вы используете что-то вроде Selenium2, и поле построено из асинхронного вызова (если я правильно понимаю, это ваш случай), вы должны быть уверены, что страница загружена полностью. Это потому, что на запрос есть ответ, и управление передается обратно вести себя как процесс.
Одним из возможных решений этой проблемы является добавление класса в тело непосредственно перед каждым вызовом ajax/async и удаление его сразу после завершения каждого вызова. Затем создайте функцию "spinner" в контексте вашего поведения, чтобы проверить, исчез ли класс.