2012-11-09 19:16:16 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace SilverStripe\Framework\Test\Behaviour;
|
|
|
|
|
|
|
|
use Behat\Behat\Context\ClosuredContextInterface,
|
2012-12-08 12:20:20 +01:00
|
|
|
Behat\Behat\Context\TranslatedContextInterface,
|
|
|
|
Behat\Behat\Context\BehatContext,
|
|
|
|
Behat\Behat\Context\Step,
|
|
|
|
Behat\Behat\Exception\PendingException,
|
2013-06-04 17:29:28 +02:00
|
|
|
Behat\Mink\Exception\ElementNotFoundException,
|
|
|
|
Behat\Gherkin\Node\PyStringNode,
|
2013-06-07 11:45:09 +02:00
|
|
|
Behat\Gherkin\Node\TableNode,
|
|
|
|
Behat\Mink\Element\NodeElement;
|
2012-11-09 19:16:16 +01:00
|
|
|
|
|
|
|
|
|
|
|
// PHPUnit
|
|
|
|
require_once 'PHPUnit/Autoload.php';
|
|
|
|
require_once 'PHPUnit/Framework/Assert/Functions.php';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* CmsUiContext
|
|
|
|
*
|
|
|
|
* Context used to define steps related to SilverStripe CMS UI like Tree or Panel.
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
class CmsUiContext extends BehatContext {
|
2012-12-08 12:20:20 +01:00
|
|
|
protected $context;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes context.
|
|
|
|
* Every scenario gets it's own context object.
|
|
|
|
*
|
|
|
|
* @param array $parameters context parameters (set them up through behat.yml)
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function __construct(array $parameters) {
|
2012-12-08 12:20:20 +01:00
|
|
|
// Initialize your context here
|
|
|
|
$this->context = $parameters;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get Mink session from MinkContext
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function getSession($name = null) {
|
2012-12-08 12:20:20 +01:00
|
|
|
return $this->getMainContext()->getSession($name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Then /^I should see the CMS$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iShouldSeeTheCms() {
|
2012-12-08 12:20:20 +01:00
|
|
|
$page = $this->getSession()->getPage();
|
|
|
|
$cms_element = $page->find('css', '.cms');
|
|
|
|
assertNotNull($cms_element, 'CMS not found');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Then /^I should see a "([^"]*)" notice$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iShouldSeeANotice($notice) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$this->getMainContext()->assertElementContains('.notice-wrap', $notice);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Then /^I should see a "([^"]*)" message$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iShouldSeeAMessage($message) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$this->getMainContext()->assertElementContains('.message', $message);
|
|
|
|
}
|
|
|
|
|
2013-11-15 12:03:43 +01:00
|
|
|
protected function getCmsTabsElement() {
|
2013-09-30 23:36:46 +02:00
|
|
|
$this->getSession()->wait(
|
|
|
|
5000,
|
|
|
|
"window.jQuery && window.jQuery('.cms-content-header-tabs').size() > 0"
|
|
|
|
);
|
2012-12-08 12:20:20 +01:00
|
|
|
|
|
|
|
$page = $this->getSession()->getPage();
|
|
|
|
$cms_content_header_tabs = $page->find('css', '.cms-content-header-tabs');
|
|
|
|
assertNotNull($cms_content_header_tabs, 'CMS tabs not found');
|
|
|
|
|
|
|
|
return $cms_content_header_tabs;
|
|
|
|
}
|
|
|
|
|
2013-11-15 12:03:43 +01:00
|
|
|
protected function getCmsContentToolbarElement() {
|
2012-12-08 12:20:20 +01:00
|
|
|
$this->getSession()->wait(
|
|
|
|
5000,
|
2013-09-30 23:36:46 +02:00
|
|
|
"window.jQuery && window.jQuery('.cms-content-toolbar').size() > 0 "
|
2012-12-08 12:20:20 +01:00
|
|
|
. "&& window.jQuery('.cms-content-toolbar').children().size() > 0"
|
|
|
|
);
|
|
|
|
|
|
|
|
$page = $this->getSession()->getPage();
|
|
|
|
$cms_content_toolbar_element = $page->find('css', '.cms-content-toolbar');
|
|
|
|
assertNotNull($cms_content_toolbar_element, 'CMS content toolbar not found');
|
|
|
|
|
|
|
|
return $cms_content_toolbar_element;
|
|
|
|
}
|
|
|
|
|
2013-11-15 12:03:43 +01:00
|
|
|
protected function getCmsTreeElement() {
|
2013-09-30 23:36:46 +02:00
|
|
|
$this->getSession()->wait(
|
|
|
|
5000,
|
|
|
|
"window.jQuery && window.jQuery('.cms-tree').size() > 0"
|
|
|
|
);
|
2012-12-08 12:20:20 +01:00
|
|
|
|
|
|
|
$page = $this->getSession()->getPage();
|
|
|
|
$cms_tree_element = $page->find('css', '.cms-tree');
|
|
|
|
assertNotNull($cms_tree_element, 'CMS tree not found');
|
|
|
|
|
|
|
|
return $cms_tree_element;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Given /^I should see a "([^"]*)" button in CMS Content Toolbar$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iShouldSeeAButtonInCmsContentToolbar($text) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$cms_content_toolbar_element = $this->getCmsContentToolbarElement();
|
|
|
|
|
|
|
|
$element = $cms_content_toolbar_element->find('named', array('link_or_button', "'$text'"));
|
|
|
|
assertNotNull($element, sprintf('%s button not found', $text));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-09-14 00:20:22 +02:00
|
|
|
* @When /^I should see "([^"]*)" in the tree$/
|
2012-12-08 12:20:20 +01:00
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function stepIShouldSeeInCmsTree($text) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$cms_tree_element = $this->getCmsTreeElement();
|
|
|
|
|
|
|
|
$element = $cms_tree_element->find('named', array('content', "'$text'"));
|
|
|
|
assertNotNull($element, sprintf('%s not found', $text));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-09-14 00:20:22 +02:00
|
|
|
* @When /^I should not see "([^"]*)" in the tree$/
|
2012-12-08 12:20:20 +01:00
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function stepIShouldNotSeeInCmsTree($text) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$cms_tree_element = $this->getCmsTreeElement();
|
|
|
|
|
|
|
|
$element = $cms_tree_element->find('named', array('content', "'$text'"));
|
|
|
|
assertNull($element, sprintf('%s found', $text));
|
|
|
|
}
|
|
|
|
|
2013-09-14 00:20:22 +02:00
|
|
|
/**
|
2014-04-14 06:50:51 +02:00
|
|
|
* Applies a specific action to an element
|
|
|
|
*
|
|
|
|
* @param NodeElement $element Element to act on
|
|
|
|
* @param string $action Action, which may be one of 'hover', 'double click', 'right click', or 'left click'
|
|
|
|
* The default 'click' behaves the same as left click
|
2013-09-14 00:20:22 +02:00
|
|
|
*/
|
2014-04-14 06:50:51 +02:00
|
|
|
protected function interactWithElement($element, $action = 'click') {
|
|
|
|
switch($action) {
|
|
|
|
case 'hover':
|
|
|
|
$element->mouseOver();
|
|
|
|
break;
|
|
|
|
case 'double click':
|
|
|
|
$element->doubleClick();
|
|
|
|
break;
|
|
|
|
case 'right click':
|
|
|
|
$element->rightClick();
|
|
|
|
break;
|
|
|
|
case 'left click':
|
|
|
|
case 'click':
|
|
|
|
default:
|
|
|
|
$element->click();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @When /^I (?P<method>(?:(?:double |right |left |)click)|hover) on "(?P<link>[^"]*)" in the context menu/
|
|
|
|
*/
|
|
|
|
public function stepIClickOnElementInTheContextMenu($method, $link) {
|
|
|
|
$context = $this->getMainContext();
|
|
|
|
// Wait until context menu has appeared
|
|
|
|
$this->getSession()->wait(
|
|
|
|
1000,
|
|
|
|
"window.jQuery && window.jQuery('.jstree-apple-context').size() > 0"
|
|
|
|
);
|
|
|
|
$regionObj = $context->getRegionObj('.jstree-apple-context');
|
|
|
|
assertNotNull($regionObj, "Context menu could not be found");
|
|
|
|
|
|
|
|
$linkObj = $regionObj->findLink($link);
|
|
|
|
if (empty($linkObj)) {
|
|
|
|
throw new \Exception(sprintf(
|
|
|
|
'The link "%s" was not found in the context menu on the page %s',
|
|
|
|
$link,
|
|
|
|
$this->getSession()->getCurrentUrl()
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->interactWithElement($linkObj, $method);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @When /^I (?P<method>(?:(?:double |right |left |)click)|hover) on "(?P<text>[^"]*)" in the tree$/
|
|
|
|
*/
|
|
|
|
public function stepIClickOnElementInTheTree($method, $text) {
|
2013-09-14 00:20:22 +02:00
|
|
|
$treeEl = $this->getCmsTreeElement();
|
|
|
|
$treeNode = $treeEl->findLink($text);
|
|
|
|
assertNotNull($treeNode, sprintf('%s not found', $text));
|
2014-04-14 06:50:51 +02:00
|
|
|
$this->interactWithElement($treeNode, $method);
|
2013-09-14 00:20:22 +02:00
|
|
|
}
|
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
/**
|
|
|
|
* @When /^I expand the "([^"]*)" CMS Panel$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iExpandTheCmsPanel() {
|
2014-02-17 22:21:07 +01:00
|
|
|
//Tries to find the first visiable toggle in the page
|
2012-12-08 12:20:20 +01:00
|
|
|
$page = $this->getSession()->getPage();
|
2014-02-17 22:21:07 +01:00
|
|
|
$toggle_elements = $page->findAll('css', '.toggle-expand');
|
|
|
|
assertNotNull($toggle_elements, 'Panel toggle not found');
|
|
|
|
foreach($toggle_elements as $toggle){
|
|
|
|
if($toggle->isVisible()){
|
|
|
|
$toggle->click();
|
|
|
|
}
|
|
|
|
}
|
2012-12-08 12:20:20 +01:00
|
|
|
}
|
|
|
|
|
2014-07-28 08:25:08 +02:00
|
|
|
/**
|
|
|
|
* @When /^I (expand|collapse) "([^"]*)" in the tree$/
|
|
|
|
*/
|
|
|
|
public function iExpandInTheTree($action, $nodeText) {
|
|
|
|
//Tries to find the first visiable matched Node in the page
|
|
|
|
$page = $this->getSession()->getPage();
|
|
|
|
$treeEl = $this->getCmsTreeElement();
|
|
|
|
$treeNode = $treeEl->findLink($nodeText);
|
|
|
|
assertNotNull($treeNode, sprintf('%s link not found', $nodeText));
|
|
|
|
$cssIcon = $treeNode->getParent()->getAttribute("class");
|
|
|
|
if($action == "expand") {
|
|
|
|
//ensure it is collapsed
|
|
|
|
if(false === strpos($cssIcon, 'jstree-open')) {
|
|
|
|
$nodeIcon = $treeNode->getParent()->find('css', '.jstree-icon');
|
|
|
|
assertTrue($nodeIcon->isVisible(), "CMS node '$nodeText' not found");
|
|
|
|
$nodeIcon->click();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//ensure it is expanded
|
|
|
|
if(false === strpos($cssIcon, 'jstree-closed')) {
|
|
|
|
$nodeIcon = $treeNode->getParent()->find('css', '.jstree-icon');
|
|
|
|
assertTrue($nodeIcon->isVisible(), "CMS node '$nodeText' not found");
|
|
|
|
$nodeIcon->click();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @When /^I should (not |)see a "([^"]*)" CMS tab$/
|
|
|
|
*/
|
|
|
|
public function iShouldSeeACmsTab($negate, $tab) {
|
|
|
|
$this->getSession()->wait(
|
|
|
|
5000,
|
|
|
|
"window.jQuery && window.jQuery('.ui-tabs-nav').size() > 0"
|
|
|
|
);
|
|
|
|
|
|
|
|
$page = $this->getSession()->getPage();
|
|
|
|
$tabsets = $page->findAll('css', '.ui-tabs-nav');
|
|
|
|
assertNotNull($tabsets, 'CMS tabs not found');
|
|
|
|
|
|
|
|
$tab_element = null;
|
|
|
|
foreach($tabsets as $tabset) {
|
|
|
|
$tab_element = $tabset->find('named', array('link_or_button', "'$tab'"));
|
|
|
|
if($tab_element) break;
|
|
|
|
}
|
|
|
|
if($negate) {
|
|
|
|
assertNull($tab_element, sprintf('%s tab found', $tab));
|
|
|
|
} else {
|
|
|
|
assertNotNull($tab_element, sprintf('%s tab not found', $tab));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
/**
|
|
|
|
* @When /^I click the "([^"]*)" CMS tab$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iClickTheCmsTab($tab) {
|
2013-09-30 23:36:46 +02:00
|
|
|
$this->getSession()->wait(
|
|
|
|
5000,
|
|
|
|
"window.jQuery && window.jQuery('.ui-tabs-nav').size() > 0"
|
|
|
|
);
|
2012-12-08 12:20:20 +01:00
|
|
|
|
|
|
|
$page = $this->getSession()->getPage();
|
|
|
|
$tabsets = $page->findAll('css', '.ui-tabs-nav');
|
|
|
|
assertNotNull($tabsets, 'CMS tabs not found');
|
|
|
|
|
|
|
|
$tab_element = null;
|
|
|
|
foreach($tabsets as $tabset) {
|
|
|
|
if($tab_element) continue;
|
|
|
|
$tab_element = $tabset->find('named', array('link_or_button', "'$tab'"));
|
|
|
|
}
|
|
|
|
assertNotNull($tab_element, sprintf('%s tab not found', $tab));
|
|
|
|
|
|
|
|
$tab_element->click();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Then /^I can see the preview panel$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iCanSeeThePreviewPanel() {
|
2012-12-08 12:20:20 +01:00
|
|
|
$this->getMainContext()->assertElementOnPage('.cms-preview');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Given /^the preview contains "([^"]*)"$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function thePreviewContains($content) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$driver = $this->getSession()->getDriver();
|
2013-08-22 12:48:11 +02:00
|
|
|
// TODO Remove once we have native support in Mink and php-webdriver,
|
|
|
|
// see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI
|
|
|
|
$origWindowName = $driver->getWebDriverSession()->window_handle();
|
2012-12-08 12:20:20 +01:00
|
|
|
|
2013-08-22 12:48:11 +02:00
|
|
|
$driver->switchToIFrame('cms-preview-iframe');
|
2012-12-08 12:20:20 +01:00
|
|
|
$this->getMainContext()->assertPageContainsText($content);
|
2013-08-22 12:48:11 +02:00
|
|
|
$driver->switchToWindow($origWindowName);
|
2012-12-08 12:20:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Given /^I set the CMS mode to "([^"]*)"$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iSetTheCmsToMode($mode) {
|
2012-12-08 12:20:20 +01:00
|
|
|
return array(
|
|
|
|
new Step\When(sprintf('I fill in the "Change view mode" dropdown with "%s"', $mode)),
|
|
|
|
new Step\When('I wait for 1 second') // wait for CMS layout to redraw
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Given /^I wait for the preview to load$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iWaitForThePreviewToLoad() {
|
2012-12-08 12:20:20 +01:00
|
|
|
$driver = $this->getSession()->getDriver();
|
2013-08-22 14:10:54 +02:00
|
|
|
// TODO Remove once we have native support in Mink and php-webdriver,
|
|
|
|
// see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI
|
|
|
|
$origWindowName = $driver->getWebDriverSession()->window_handle();
|
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
$driver->switchToIFrame('cms-preview-iframe');
|
|
|
|
$this->getSession()->wait(
|
|
|
|
5000,
|
2013-10-07 23:43:30 +02:00
|
|
|
"window.jQuery && !window.jQuery('iframe[name=cms-preview-iframe]').hasClass('loading')"
|
2012-12-08 12:20:20 +01:00
|
|
|
);
|
2013-08-22 14:10:54 +02:00
|
|
|
$driver->switchToWindow($origWindowName);
|
2012-12-08 12:20:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Given /^I switch the preview to "([^"]*)"$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function iSwitchThePreviewToMode($mode) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$controls = $this->getSession()->getPage()->find('css', '.cms-preview-controls');
|
|
|
|
assertNotNull($controls, 'Preview controls not found');
|
|
|
|
|
|
|
|
$label = $controls->find('xpath', sprintf(
|
|
|
|
'.//label[(@for="%s")]',
|
|
|
|
$mode
|
|
|
|
));
|
|
|
|
assertNotNull($label, 'Preview mode switch not found');
|
|
|
|
|
|
|
|
$label->click();
|
|
|
|
|
|
|
|
return new Step\When('I wait for the preview to load');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Given /^the preview does not contain "([^"]*)"$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function thePreviewDoesNotContain($content) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$driver = $this->getSession()->getDriver();
|
2013-08-22 12:48:11 +02:00
|
|
|
// TODO Remove once we have native support in Mink and php-webdriver,
|
|
|
|
// see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI
|
|
|
|
$origWindowName = $driver->getWebDriverSession()->window_handle();
|
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
$driver->switchToIFrame('cms-preview-iframe');
|
|
|
|
$this->getMainContext()->assertPageNotContainsText($content);
|
2013-08-22 12:48:11 +02:00
|
|
|
$driver->switchToWindow($origWindowName);
|
2012-12-08 12:20:20 +01:00
|
|
|
}
|
|
|
|
|
2014-04-01 00:04:42 +02:00
|
|
|
/**
|
|
|
|
* When I follow "my link" in preview
|
|
|
|
*
|
|
|
|
* @When /^(?:|I )follow "(?P<link>(?:[^"]|\\")*)" in preview$/
|
|
|
|
*/
|
|
|
|
public function clickLinkInPreview($link) {
|
|
|
|
$driver = $this->getSession()->getDriver();
|
|
|
|
// TODO Remove once we have native support in Mink and php-webdriver,
|
|
|
|
// see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI
|
|
|
|
$origWindowName = $driver->getWebDriverSession()->window_handle();
|
|
|
|
$driver->switchToIFrame('cms-preview-iframe');
|
|
|
|
|
|
|
|
$link = $this->fixStepArgument($link);
|
|
|
|
$this->getSession()->getPage()->clickLink($link);
|
|
|
|
|
|
|
|
$driver->switchToWindow($origWindowName);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When I press "submit" in preview
|
|
|
|
*
|
|
|
|
* @When /^(?:|I )press "(?P<button>(?:[^"]|\\")*)" in preview$/
|
|
|
|
*/
|
|
|
|
public function pressButtonInPreview($button) {
|
|
|
|
$driver = $this->getSession()->getDriver();
|
|
|
|
// TODO Remove once we have native support in Mink and php-webdriver,
|
|
|
|
// see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI
|
|
|
|
$origWindowName = $driver->getWebDriverSession()->window_handle();
|
|
|
|
$driver->switchToIFrame('cms-preview-iframe');
|
|
|
|
|
|
|
|
$button = $this->fixStepArgument($button);
|
|
|
|
$this->getSession()->getPage()->pressButton($button);
|
|
|
|
|
|
|
|
$driver->switchToWindow($origWindowName);
|
|
|
|
}
|
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
/**
|
2013-06-04 17:29:28 +02:00
|
|
|
* Workaround for chosen.js dropdowns or tree dropdowns which hide the original dropdown field.
|
2012-12-08 12:20:20 +01:00
|
|
|
*
|
|
|
|
* @When /^(?:|I )fill in the "(?P<field>(?:[^"]|\\")*)" dropdown with "(?P<value>(?:[^"]|\\")*)"$/
|
|
|
|
* @When /^(?:|I )fill in "(?P<value>(?:[^"]|\\")*)" for the "(?P<field>(?:[^"]|\\")*)" dropdown$/
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
public function theIFillInTheDropdownWith($field, $value) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$field = $this->fixStepArgument($field);
|
|
|
|
$value = $this->fixStepArgument($value);
|
|
|
|
|
2013-09-14 19:45:01 +02:00
|
|
|
$nativeField = $this->getSession()->getPage()->find(
|
|
|
|
'named',
|
|
|
|
array('select', $this->getSession()->getSelectorsHandler()->xpathLiteral($field))
|
|
|
|
);
|
2013-06-04 17:29:28 +02:00
|
|
|
if($nativeField) {
|
|
|
|
$nativeField->selectOption($value);
|
2013-06-05 14:37:54 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
// Given the fuzzy matching, we might get more than one matching field.
|
|
|
|
$formFields = array();
|
|
|
|
|
|
|
|
// Find by label
|
|
|
|
$formField = $this->getSession()->getPage()->findField($field);
|
2013-09-14 18:29:04 +02:00
|
|
|
if($formField && $formField->getTagName() == 'select') {
|
|
|
|
$formFields[] = $formField;
|
|
|
|
}
|
2012-12-08 12:20:20 +01:00
|
|
|
|
|
|
|
// Fall back to finding by title (for dropdowns without a label)
|
|
|
|
if(!$formFields) {
|
|
|
|
$formFields = $this->getSession()->getPage()->findAll(
|
|
|
|
'xpath',
|
|
|
|
sprintf(
|
|
|
|
'//*[self::select][(./@title="%s")]',
|
|
|
|
$field
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-06-05 14:37:54 +02:00
|
|
|
// Find by name (incl. hidden fields)
|
|
|
|
if(!$formFields) {
|
|
|
|
$formFields = $this->getSession()->getPage()->findAll('xpath', "//*[@name='$field']");
|
|
|
|
}
|
|
|
|
|
2013-09-14 18:29:04 +02:00
|
|
|
// Find by label
|
|
|
|
if(!$formFields) {
|
|
|
|
$label = $this->getSession()->getPage()->find('xpath', "//label[.='$field']");
|
|
|
|
if($label && $for = $label->getAttribute('for')) {
|
|
|
|
$formField = $this->getSession()->getPage()->find('xpath', "//*[@id='$for']");
|
|
|
|
if($formField) $formFields[] = $formField;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
assertGreaterThan(0, count($formFields), sprintf(
|
2013-06-05 14:37:54 +02:00
|
|
|
'Chosen.js dropdown named "%s" not found',
|
|
|
|
$field
|
|
|
|
));
|
2012-12-08 12:20:20 +01:00
|
|
|
|
2013-06-05 14:37:54 +02:00
|
|
|
// Traverse up to field holder
|
2013-06-07 11:45:09 +02:00
|
|
|
$container = null;
|
2012-12-08 12:20:20 +01:00
|
|
|
foreach($formFields as $formField) {
|
2013-06-07 11:45:09 +02:00
|
|
|
$container = $this->findParentByClass($formField, 'field');
|
|
|
|
if($container) break; // Default to first visible container
|
2012-12-08 12:20:20 +01:00
|
|
|
}
|
2012-12-08 12:20:20 +01:00
|
|
|
|
2013-06-07 11:45:09 +02:00
|
|
|
assertNotNull($container, 'Chosen.js field container not found');
|
2013-06-19 14:03:43 +02:00
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
// Click on newly expanded list element, indirectly setting the dropdown value
|
|
|
|
$linkEl = $container->find('xpath', './/a[./@href]');
|
|
|
|
assertNotNull($linkEl, 'Chosen.js link element not found');
|
|
|
|
$this->getSession()->wait(100); // wait for dropdown overlay to appear
|
|
|
|
$linkEl->click();
|
2013-06-19 14:03:43 +02:00
|
|
|
|
2013-06-07 11:45:09 +02:00
|
|
|
if(in_array('treedropdown', explode(' ', $container->getAttribute('class')))) {
|
2013-06-05 14:37:54 +02:00
|
|
|
// wait for ajax dropdown to load
|
|
|
|
$this->getSession()->wait(
|
|
|
|
5000,
|
2013-09-30 23:36:46 +02:00
|
|
|
"window.jQuery && "
|
|
|
|
. "window.jQuery('#" . $container->getAttribute('id') . " .treedropdownfield-panel li').length > 0"
|
2013-06-05 14:37:54 +02:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// wait for dropdown overlay to appear (might be animated)
|
|
|
|
$this->getSession()->wait(300);
|
2012-12-08 12:20:20 +01:00
|
|
|
}
|
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
$listEl = $container->find('xpath', sprintf('.//li[contains(normalize-space(string(.)), \'%s\')]', $value));
|
2013-06-05 14:37:54 +02:00
|
|
|
if(null === $listEl) {
|
|
|
|
throw new \InvalidArgumentException(sprintf(
|
2012-12-08 12:20:20 +01:00
|
|
|
'Chosen.js list element with title "%s" not found',
|
|
|
|
$value
|
|
|
|
));
|
2013-06-05 14:37:54 +02:00
|
|
|
}
|
2012-12-08 12:20:20 +01:00
|
|
|
|
2013-06-07 11:45:09 +02:00
|
|
|
$listLinkEl = $listEl->find('xpath', './/a');
|
|
|
|
if($listLinkEl) {
|
|
|
|
$listLinkEl->click();
|
|
|
|
} else {
|
|
|
|
$listEl->click();
|
|
|
|
}
|
2012-12-08 12:20:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns fixed step argument (with \\" replaced back to ").
|
|
|
|
*
|
|
|
|
* @param string $argument
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2013-11-15 12:03:43 +01:00
|
|
|
protected function fixStepArgument($argument) {
|
2012-12-08 12:20:20 +01:00
|
|
|
return str_replace('\\"', '"', $argument);
|
|
|
|
}
|
2013-06-07 11:45:09 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the closest parent element having a specific class attribute.
|
|
|
|
*
|
|
|
|
* @param NodeElement $el
|
|
|
|
* @param String $class
|
|
|
|
* @return Element|null
|
|
|
|
*/
|
|
|
|
protected function findParentByClass(NodeElement $el, $class) {
|
|
|
|
$container = $el->getParent();
|
2013-11-15 12:03:43 +01:00
|
|
|
while($container && $container->getTagName() != 'body') {
|
2013-06-07 11:45:09 +02:00
|
|
|
if($container->isVisible() && in_array($class, explode(' ', $container->getAttribute('class')))) {
|
|
|
|
return $container;
|
2013-11-15 12:03:43 +01:00
|
|
|
}
|
2013-06-07 11:45:09 +02:00
|
|
|
$container = $container->getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
2012-11-09 19:16:16 +01:00
|
|
|
}
|