2017-10-13 147 views
2

当我点击一个按钮,一个新的页面打开一个表单,我需要填写该页面上的一个字段。如何让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); 
    } 

有人能帮助我吗?

+0

使用带定时器的“do-while”循环。 – lauda

+0

量角器或水貂是否没有提供framewokr功能? –

回答

1

可以使用旋转功能:

在上下文
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和Goutte。

0

如果你使用的是只模拟浏览器的驱动程序(比如BrowserKit或Goutte),只有当DOM被正确编写并准备好(当然没有js可以被解释或执行)时,behat才会有控制权。如果你使用类似Selenium2的东西,并且该字段是从异步调用构建的(如果我理解正确,这是你的情况),取决于你是否确定该页面是完整加载的。这是因为请求有响应,并且控制权被传回Behat进程。
这个问题的一个可能的解决方案是在每个ajax/async调用之前将一个类追加到主体中,并在每次调用完成后将其剥离。然后,在你的behat上下文中创建一个“微调器”函数来检查课程是否会消失。

+0

我用这个旋转功能,它的工作原理!谢谢! ' $ element = null;使用(&$ element){$ element = $ context-> getSession() - > getPage() - > findField('voucher_subject'); return $ element && $ element-> isVisible(); }); $ element-> setValue($ faker-> text); ' –

1

从我的角度来看可以做到这一点,现在更优雅:

$page = $this->getSession()->getPage(); 

$page->waitFor(5000, 
    function() use ($page) { 
     return $page->findField('voucher_subject')->isVisible(); 
    } 
); 

你也可以把这个包里面的一些private功能。

相关问题