259 lines
7.6 KiB
PHP
259 lines
7.6 KiB
PHP
<?php
|
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
namespace Facebook\WebDriver;
|
|
|
|
use Facebook\WebDriver\Exception\NoSuchElementException;
|
|
use Facebook\WebDriver\Exception\UnexpectedTagNameException;
|
|
use Facebook\WebDriver\Exception\UnsupportedOperationException;
|
|
use Facebook\WebDriver\Support\XPathEscaper;
|
|
|
|
/**
|
|
* Models a default HTML `<select>` tag, providing helper methods to select and deselect options.
|
|
*/
|
|
class WebDriverSelect implements WebDriverSelectInterface
|
|
{
|
|
/** @var WebDriverElement */
|
|
private $element;
|
|
/** @var bool */
|
|
private $isMulti;
|
|
|
|
public function __construct(WebDriverElement $element)
|
|
{
|
|
$tag_name = $element->getTagName();
|
|
|
|
if ($tag_name !== 'select') {
|
|
throw new UnexpectedTagNameException('select', $tag_name);
|
|
}
|
|
$this->element = $element;
|
|
$value = $element->getAttribute('multiple');
|
|
$this->isMulti = $value === 'true';
|
|
}
|
|
|
|
public function isMultiple()
|
|
{
|
|
return $this->isMulti;
|
|
}
|
|
|
|
public function getOptions()
|
|
{
|
|
return $this->element->findElements(WebDriverBy::tagName('option'));
|
|
}
|
|
|
|
public function getAllSelectedOptions()
|
|
{
|
|
$selected_options = [];
|
|
foreach ($this->getOptions() as $option) {
|
|
if ($option->isSelected()) {
|
|
$selected_options[] = $option;
|
|
|
|
if (!$this->isMultiple()) {
|
|
return $selected_options;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $selected_options;
|
|
}
|
|
|
|
public function getFirstSelectedOption()
|
|
{
|
|
foreach ($this->getOptions() as $option) {
|
|
if ($option->isSelected()) {
|
|
return $option;
|
|
}
|
|
}
|
|
|
|
throw new NoSuchElementException('No options are selected');
|
|
}
|
|
|
|
public function selectByIndex($index)
|
|
{
|
|
foreach ($this->getOptions() as $option) {
|
|
if ($option->getAttribute('index') === (string) $index) {
|
|
$this->selectOption($option);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
throw new NoSuchElementException(sprintf('Cannot locate option with index: %d', $index));
|
|
}
|
|
|
|
public function selectByValue($value)
|
|
{
|
|
$matched = false;
|
|
$xpath = './/option[@value = ' . XPathEscaper::escapeQuotes($value) . ']';
|
|
$options = $this->element->findElements(WebDriverBy::xpath($xpath));
|
|
|
|
foreach ($options as $option) {
|
|
$this->selectOption($option);
|
|
if (!$this->isMultiple()) {
|
|
return;
|
|
}
|
|
$matched = true;
|
|
}
|
|
|
|
if (!$matched) {
|
|
throw new NoSuchElementException(
|
|
sprintf('Cannot locate option with value: %s', $value)
|
|
);
|
|
}
|
|
}
|
|
|
|
public function selectByVisibleText($text)
|
|
{
|
|
$matched = false;
|
|
$xpath = './/option[normalize-space(.) = ' . XPathEscaper::escapeQuotes($text) . ']';
|
|
$options = $this->element->findElements(WebDriverBy::xpath($xpath));
|
|
|
|
foreach ($options as $option) {
|
|
$this->selectOption($option);
|
|
if (!$this->isMultiple()) {
|
|
return;
|
|
}
|
|
$matched = true;
|
|
}
|
|
|
|
// Since the mechanism of getting the text in xpath is not the same as
|
|
// webdriver, use the expensive getText() to check if nothing is matched.
|
|
if (!$matched) {
|
|
foreach ($this->getOptions() as $option) {
|
|
if ($option->getText() === $text) {
|
|
$this->selectOption($option);
|
|
if (!$this->isMultiple()) {
|
|
return;
|
|
}
|
|
$matched = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$matched) {
|
|
throw new NoSuchElementException(
|
|
sprintf('Cannot locate option with text: %s', $text)
|
|
);
|
|
}
|
|
}
|
|
|
|
public function selectByVisiblePartialText($text)
|
|
{
|
|
$matched = false;
|
|
$xpath = './/option[contains(normalize-space(.), ' . XPathEscaper::escapeQuotes($text) . ')]';
|
|
$options = $this->element->findElements(WebDriverBy::xpath($xpath));
|
|
|
|
foreach ($options as $option) {
|
|
$this->selectOption($option);
|
|
if (!$this->isMultiple()) {
|
|
return;
|
|
}
|
|
$matched = true;
|
|
}
|
|
|
|
if (!$matched) {
|
|
throw new NoSuchElementException(
|
|
sprintf('Cannot locate option with text: %s', $text)
|
|
);
|
|
}
|
|
}
|
|
|
|
public function deselectAll()
|
|
{
|
|
if (!$this->isMultiple()) {
|
|
throw new UnsupportedOperationException('You may only deselect all options of a multi-select');
|
|
}
|
|
|
|
foreach ($this->getOptions() as $option) {
|
|
$this->deselectOption($option);
|
|
}
|
|
}
|
|
|
|
public function deselectByIndex($index)
|
|
{
|
|
if (!$this->isMultiple()) {
|
|
throw new UnsupportedOperationException('You may only deselect options of a multi-select');
|
|
}
|
|
|
|
foreach ($this->getOptions() as $option) {
|
|
if ($option->getAttribute('index') === (string) $index) {
|
|
$this->deselectOption($option);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public function deselectByValue($value)
|
|
{
|
|
if (!$this->isMultiple()) {
|
|
throw new UnsupportedOperationException('You may only deselect options of a multi-select');
|
|
}
|
|
|
|
$xpath = './/option[@value = ' . XPathEscaper::escapeQuotes($value) . ']';
|
|
$options = $this->element->findElements(WebDriverBy::xpath($xpath));
|
|
foreach ($options as $option) {
|
|
$this->deselectOption($option);
|
|
}
|
|
}
|
|
|
|
public function deselectByVisibleText($text)
|
|
{
|
|
if (!$this->isMultiple()) {
|
|
throw new UnsupportedOperationException('You may only deselect options of a multi-select');
|
|
}
|
|
|
|
$xpath = './/option[normalize-space(.) = ' . XPathEscaper::escapeQuotes($text) . ']';
|
|
$options = $this->element->findElements(WebDriverBy::xpath($xpath));
|
|
foreach ($options as $option) {
|
|
$this->deselectOption($option);
|
|
}
|
|
}
|
|
|
|
public function deselectByVisiblePartialText($text)
|
|
{
|
|
if (!$this->isMultiple()) {
|
|
throw new UnsupportedOperationException('You may only deselect options of a multi-select');
|
|
}
|
|
|
|
$xpath = './/option[contains(normalize-space(.), ' . XPathEscaper::escapeQuotes($text) . ')]';
|
|
$options = $this->element->findElements(WebDriverBy::xpath($xpath));
|
|
foreach ($options as $option) {
|
|
$this->deselectOption($option);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mark option selected
|
|
* @param WebDriverElement $option
|
|
*/
|
|
protected function selectOption(WebDriverElement $option)
|
|
{
|
|
if (!$option->isSelected()) {
|
|
$option->click();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mark option not selected
|
|
* @param WebDriverElement $option
|
|
*/
|
|
protected function deselectOption(WebDriverElement $option)
|
|
{
|
|
if ($option->isSelected()) {
|
|
$option->click();
|
|
}
|
|
}
|
|
}
|