У меня проблемы с Бехатом, ожидающим, пока элемент «вползет».
В меню панели администратора каждый основной элемент перемещается вниз, открывая подменю, как показано здесь:
Я добавил красную линию для отображения меню и зеленую для подменю просто для ясности.
Проблема в том, что это меню «скользит». Это прекрасный эффект, но он портит мои тесты. :)
Я пытаюсь использовать функцию вращения, чтобы заставить Behat дождаться, пока подменю станет видимым, прежде чем пытаться щелкнуть в нем.
Код:
/**
* @When I wait for :cssSelector
* @param $cssSelector
* @throws \Exception
*/
public function iWaitFor($cssSelector)
{
$this->spin(function($context) use ($cssSelector) {
/** @var $context FeatureContext */
return !is_null($context->getSession()->getPage()->find('css', $cssSelector));
});
}
/**
* @When I wait for :text to appear
* @Then I should see :text appear
* @param $text
* @throws \Exception
*/
public function iWaitForTextToAppear($text)
{
$this->spin(function($context) use ($text) {
/** @var $context FeatureContext */
return $context->getSession()->getPage()->hasContent($text);
});
}
/**
* @When I wait for :text to disappear
* @Then I should see :text disappear
* @param $text
* @throws \Exception
*/
public function iWaitForTextToDisappear($text)
{
$this->spin(function($context) use ($text) {
/** @var $context FeatureContext */
return !$context->getSession()->getPage()->hasContent($text);
});
}
/**
* Based on Behat's own example
* @see http://docs.behat.org/en/v2.5/cookbook/using_spin_functions.html#adding-a-timeout
* @param $lambda
* @param int $wait
* @throws \Exception
*/
public function spin($lambda, $wait = 60)
{
$time = time();
$stopTime = $time + $wait;
while (time() < $stopTime)
{
try {
if ($lambda($this)) {
return;
}
} catch (\Exception $e) {
// do nothing
}
usleep(250000);
}
throw new \Exception("Spin function timed out after {$wait} seconds");
}
И фрагмент характеристики:
@javascript
Scenario Outline: Create a new piece of artwork
Given I am logged in to the CMS as "adminUser"
Then I should see "Artwork"
When I follow "Artwork"
Then I should see "Pieces" appear
When I follow "Pieces"
Then I should see "Manage Artwork Pieces"
Однако, хотя это прекрасно работает в моей среде разработки Vagrant, в Jenkins происходит сбой, когда он пытается follow "Pieces"
после подтверждения появления «Pieces». Оба работают под управлением Selenium с Firefox в XVFB на безголовом Linux.
Это версии, которые я сейчас использую:
╔═════════════╦══════════════╦════════════╗
║ Environment ║ Development ║ Testing ║
╠═════════════╬══════════════╬════════════╣
║ Linux ║ Ubuntu 14.04 ║ CentOS 6.6 ║
║ PHP ║ 5.5.9 ║ 5.4.38 ║
║ Behat ║ 3.0.x-dev ║ 3.0.x-dev ║
║ Selenium ║ 2.45.0 ║ 2.45.0 ║
║ XVFB ║ 1.15.1 ║ 1.15.0 ║
║ Firefox ║ 36.0.4 ║ 31.5.0 ║
╚═════════════╩══════════════╩════════════╝
Я собираюсь убедиться, что Firefox и Selenium обновлены настолько, насколько это возможно, чтобы увидеть, решит ли это проблему, однако это было постоянной проблемой в течение некоторого времени, поэтому я не уверен.
Дополнение
Я пропустил пример фактического сообщения об ошибке:
When I follow "Carousel" # tests/Behat/Cms/Features/1.1.Carousel.feature:11
Offset within element cannot be scrolled into view: (110, 17): http://www.###.co.uk/admin/fp/carousel
Build info: version: '2.44.0', revision: '76d78cf', time: '2014-10-23 20:02:37'
Это сразу после Then I should see "Carousel" appear
Кроме того, ошибки возникают почти случайно. Мне нужен надежный способ убедиться, что тест не будет продолжаться до тех пор, пока страница не будет в состоянии, позволяющем продолжить его. Я хочу избежать чего-либо вроде «ожидания» или всего, что зависит от JavaScript или Selenium в частности (на случай, если я переключусь на другой драйвер).
Обновление: Обновлен Selenium на тестовом компьютере до версии 2.45.0, проблема осталась. Исправленная версия PHP в Dev Environment выше, была 5.4, на самом деле 5.5.9.