diff --git a/src/Behat/Mink/Element/NodeElement.php b/src/Behat/Mink/Element/NodeElement.php index 1f867ed0d..6a79e934f 100644 --- a/src/Behat/Mink/Element/NodeElement.php +++ b/src/Behat/Mink/Element/NodeElement.php @@ -55,6 +55,86 @@ public function getParent() return $this->find('xpath', '..'); } + /** + * Returns All child elements (including descendant) to the current one. + * + * @return static[]|null + */ + public function getAllChildren() + { + return $this->findAll('xpath', 'descendant::*'); + } + + /** + * Returns All direct child elements (NOT including deeper descendant) to the current one. + * + * @return static[]|null + */ + public function getDirectChildren() + { + return $this->findAll('xpath', 'child::*'); + } + + /** + * Returns the first child element to the current one. + * + * @return static|null + */ + public function getFirstChild() + { + return $this->find('xpath', 'child::*[1]'); + } + + /** + * Returns the last direct child element to the current one. + * + * @return static|null + */ + public function getLastChild() + { + return $this->find('xpath', 'child::*[last()]'); + } + + /** + * Returns all preceding sibling elements to the current one. + * + * @return static[]|null + */ + public function getPreviousSiblings() + { + return $this->findAll('xpath', 'preceding-sibling::*'); + } + + /** + * Returns the preceding sibling element close to the current one. + * + * @return static|null + */ + public function getPreviousSibling() + { + return $this->find('xpath', 'preceding-sibling::*[1]'); + } + + /** + * Returns all following sibling elements to the current one. + * + * @return static[]|null + */ + public function getNextSiblings() + { + return $this->findAll('xpath', 'following-sibling::*'); + } + + /** + * Returns the following sibling element close to the current one. + * + * @return static|null + */ + public function getNextSibling() + { + return $this->find('xpath', 'following-sibling::*[1]'); + } + /** * Returns current node tag name. * diff --git a/src/Behat/Mink/Element/TraversableElement.php b/src/Behat/Mink/Element/TraversableElement.php index 27843d2dd..b2834a512 100644 --- a/src/Behat/Mink/Element/TraversableElement.php +++ b/src/Behat/Mink/Element/TraversableElement.php @@ -33,6 +33,29 @@ public function findById($id) return $this->find('named', array('id', $id)); } + /** + * Finds element by its name. + * + * @param string name element name + * @return static|null + */ + public function findByName($name) + { + $name = $this->getSelectorsHandler()->xpathLiteral($name); + return $this->find('named', array('name', $name)); + } + + /** + * Finds elements by its tag. + * + * @param string tag element tag + * @return static[]|null + */ + public function findByTag($tag) + { + return $this->findAll('css', $tag); + } + /** * Checks whether element has a link with specified locator. * diff --git a/src/Behat/Mink/Selector/ExactNamedSelector.php b/src/Behat/Mink/Selector/ExactNamedSelector.php index 03315a9cf..12a21b806 100644 --- a/src/Behat/Mink/Selector/ExactNamedSelector.php +++ b/src/Behat/Mink/Selector/ExactNamedSelector.php @@ -23,6 +23,7 @@ public function __construct() $this->registerReplacement('%altMatch%', './@alt = %locator%'); $this->registerReplacement('%relMatch%', './@rel = %locator%'); $this->registerReplacement('%labelAttributeMatch%', './@label = %locator%'); + $this->registerReplacement('%nameMatch%', './@name = %locator%'); parent::__construct(); } diff --git a/src/Behat/Mink/Selector/NamedSelector.php b/src/Behat/Mink/Selector/NamedSelector.php index a7e8d193c..431217ea1 100644 --- a/src/Behat/Mink/Selector/NamedSelector.php +++ b/src/Behat/Mink/Selector/NamedSelector.php @@ -32,6 +32,7 @@ class NamedSelector implements SelectorInterface '%altMatch%' => 'contains(./@alt, %locator%)', '%relMatch%' => 'contains(./@rel, %locator%)', '%labelAttributeMatch%' => 'contains(./@label, %locator%)', + '%nameMatch%' => 'contains(./@name, %locator%)', // complex replacements '%inputTypeWithoutPlaceholderFilter%' => "%lowercaseType% = 'radio' or %lowercaseType% = 'checkbox' or %lowercaseType% = 'file'", @@ -152,6 +153,10 @@ class NamedSelector implements SelectorInterface XPATH ,'id' => << <<registerReplacement('%altMatch%', 'contains(./@alt, %locator%)'); $this->registerReplacement('%relMatch%', 'contains(./@rel, %locator%)'); $this->registerReplacement('%labelAttributeMatch%', 'contains(./@label, %locator%)'); + $this->registerReplacement('%nameMatch%', 'contains(./@name, %locator%)'); parent::__construct(); } diff --git a/tests/Selector/NamedSelectorTest.php b/tests/Selector/NamedSelectorTest.php index 2c5c03fe0..1dfe62389 100644 --- a/tests/Selector/NamedSelectorTest.php +++ b/tests/Selector/NamedSelectorTest.php @@ -141,6 +141,8 @@ public function getSelectorTests() 'table' => array('test.html', 'table', 'the-table', 2, 3), 'id' => array('test.html', 'id', 'bad-link-text', 1), + + 'name' => array('test.html', 'name', 'the-field', 11), ); }