包装选择中断 dusk 测试
Wrapped selects breaking dusk tests
我正在使用 dusk 进行浏览器测试。最近我开始使用mdbootstrap,但这不是重点。关键是 mdb 包装 selects 的方式使它们无法像我通常那样进行测试。
我在 blade 中做了什么:
<select class="mdb-select md-form" id="selectId" name="selectName">
@foreach($elements as $element)
<option value="{{ $element->id }}">{{ $element->display_name }}</option>
@endforeach
</select>
我的DOM长得真像
<div class="select-wrapper mdb-select md-form">
<span class="caret">▼</span>
<input type="text" class="select-dropdown" readonly="true" data-activates="select-options-f8364f16-85fb-4f93-a212-a11ee81271f1" value="" data-cip-id="cIPJQ342845639">
<ul id="select-options-f8364f16-85fb-4f93-a212-a11ee81271f1" class="dropdown-content select-dropdown w-100">
<li class="active"><span class="filtrable">Some Text</span></li>
</ul>
<select class="mdb-select md-form initialized" id="selectId" name="selectName">
<option value="1"></option>
</select>
</div>
尝试使用正常 select('@selector', 'value');
会导致 "Element is not currently visible and may not be manipulated"
错误。
我现在可以如何测试我的 select 有什么想法吗?
当我只有一个 select 时,我也许可以尝试手动单击那些 ul 和 li 标签,但是当我有多个时,麻烦就开始了。包装器 ID 不可预测,因此我无法对其进行硬编码。
感谢 Jonas Staudenmeir,我能够构建一个不错的解决方案。
我通过向 select 提供元素的 class 或 id 和项目的文本,为 select 元素的一项编写了一个函数.
我还写了一个函数来测试特定项目是否 selected.
它可能看起来有点快和脏,也许可以改进它,但我现在很高兴。
select 函数:
/**
* Selects an mdBootstrap select
* @param Browser $browser
* @param $method string "id" or "class"
* @param $selector string id or class of the searched select element
* @param $text string text of the select item to select
*/
public function mdbSelectByNativeSelector(Browser $browser, $method, $selector, $text)
{
$text = trim($text);
//Find the select element itself
$selects = $browser->elements(".select-wrapper");
$select = 0;
foreach ($selects as $el)
{
if ($el->findElement(WebDriverBy::tagName("select"))->getAttribute($method) == $selector)
{
$select = $el;
}
}
PHPUnit::assertTrue(is_a($select, RemoteWebElement::class), "Select with {$method} {$selector} not found!");
$select->click();
//Find the content of the select
$select_content = $select->findElement(WebDriverBy::className("dropdown-content"));
//Select the nthElement (li) of the select content.
$liElements = $select_content->findElements(WebDriverBy::tagName("li"));
foreach ($liElements as $el)
{
if ($el->getText() == $text)
{
$el->click();
return;
}
}
}
断言 selected 函数:
/**
* Tests if an mdbSelect is selected
* @param $method string "id" or "name"
* @param $selector string the id or name of the native select element
* @param $text string the content of the selectable element (value not possible because it's flushed away)
* @return DuskBrowser
*/
public function assertMDBSelected($method, $selector, $text)
{
//Find the select element itself
$selects = $this->elements(".select-wrapper");
$select = 0;
$success = false;
foreach ($selects as $el)
{
if ($el->findElement(WebDriverBy::tagName("select"))->getAttribute($method) == $selector)
{
$select = $el;
}
}
PHPUnit::assertTrue(is_a($el, RemoteWebElement::class), "Didn't find expected native select with {$method} {$selector}.");
//Find the content of the select
$select_content = $select->findElement(WebDriverBy::className("dropdown-content"));
//Select the nthElement (li) of the select content.
$liElements = $select_content->findElements(WebDriverBy::tagName("li"));
foreach ($liElements as $el)
{
if (strpos($el->getAttribute("class"), "active") !== false)
{
//We need to ltrim because mdb inserts some problematic whitespaces in the text.
if(ltrim($el->findElement(WebDriverBy::tagName("span"))->getAttribute("innerHTML")) == $text){
$success = true;
break;
}
}
}
PHPUnit::assertTrue($success, "Select is not selected!");
return $this;
}
对最后一个功能说几句:
要使用自己的 dusk 断言,您需要创建自己的浏览器。我关注了this guide。
这里最重要的步骤:
- 创建一个扩展
Browser
的 class DuskBrowser
- 在此处包含您的自定义断言函数。
覆盖 protected
函数 newBrowser
。
它唯一的工作是 return 一个新的 DuskBrowser。
protected function newBrowser($driver)
{
return new DuskBrowser($driver);
}
我正在使用 dusk 进行浏览器测试。最近我开始使用mdbootstrap,但这不是重点。关键是 mdb 包装 selects 的方式使它们无法像我通常那样进行测试。
我在 blade 中做了什么:
<select class="mdb-select md-form" id="selectId" name="selectName">
@foreach($elements as $element)
<option value="{{ $element->id }}">{{ $element->display_name }}</option>
@endforeach
</select>
我的DOM长得真像
<div class="select-wrapper mdb-select md-form">
<span class="caret">▼</span>
<input type="text" class="select-dropdown" readonly="true" data-activates="select-options-f8364f16-85fb-4f93-a212-a11ee81271f1" value="" data-cip-id="cIPJQ342845639">
<ul id="select-options-f8364f16-85fb-4f93-a212-a11ee81271f1" class="dropdown-content select-dropdown w-100">
<li class="active"><span class="filtrable">Some Text</span></li>
</ul>
<select class="mdb-select md-form initialized" id="selectId" name="selectName">
<option value="1"></option>
</select>
</div>
尝试使用正常 select('@selector', 'value');
会导致 "Element is not currently visible and may not be manipulated"
错误。
我现在可以如何测试我的 select 有什么想法吗?
当我只有一个 select 时,我也许可以尝试手动单击那些 ul 和 li 标签,但是当我有多个时,麻烦就开始了。包装器 ID 不可预测,因此我无法对其进行硬编码。
感谢 Jonas Staudenmeir,我能够构建一个不错的解决方案。
我通过向 select 提供元素的 class 或 id 和项目的文本,为 select 元素的一项编写了一个函数.
我还写了一个函数来测试特定项目是否 selected.
它可能看起来有点快和脏,也许可以改进它,但我现在很高兴。
select 函数:
/**
* Selects an mdBootstrap select
* @param Browser $browser
* @param $method string "id" or "class"
* @param $selector string id or class of the searched select element
* @param $text string text of the select item to select
*/
public function mdbSelectByNativeSelector(Browser $browser, $method, $selector, $text)
{
$text = trim($text);
//Find the select element itself
$selects = $browser->elements(".select-wrapper");
$select = 0;
foreach ($selects as $el)
{
if ($el->findElement(WebDriverBy::tagName("select"))->getAttribute($method) == $selector)
{
$select = $el;
}
}
PHPUnit::assertTrue(is_a($select, RemoteWebElement::class), "Select with {$method} {$selector} not found!");
$select->click();
//Find the content of the select
$select_content = $select->findElement(WebDriverBy::className("dropdown-content"));
//Select the nthElement (li) of the select content.
$liElements = $select_content->findElements(WebDriverBy::tagName("li"));
foreach ($liElements as $el)
{
if ($el->getText() == $text)
{
$el->click();
return;
}
}
}
断言 selected 函数:
/**
* Tests if an mdbSelect is selected
* @param $method string "id" or "name"
* @param $selector string the id or name of the native select element
* @param $text string the content of the selectable element (value not possible because it's flushed away)
* @return DuskBrowser
*/
public function assertMDBSelected($method, $selector, $text)
{
//Find the select element itself
$selects = $this->elements(".select-wrapper");
$select = 0;
$success = false;
foreach ($selects as $el)
{
if ($el->findElement(WebDriverBy::tagName("select"))->getAttribute($method) == $selector)
{
$select = $el;
}
}
PHPUnit::assertTrue(is_a($el, RemoteWebElement::class), "Didn't find expected native select with {$method} {$selector}.");
//Find the content of the select
$select_content = $select->findElement(WebDriverBy::className("dropdown-content"));
//Select the nthElement (li) of the select content.
$liElements = $select_content->findElements(WebDriverBy::tagName("li"));
foreach ($liElements as $el)
{
if (strpos($el->getAttribute("class"), "active") !== false)
{
//We need to ltrim because mdb inserts some problematic whitespaces in the text.
if(ltrim($el->findElement(WebDriverBy::tagName("span"))->getAttribute("innerHTML")) == $text){
$success = true;
break;
}
}
}
PHPUnit::assertTrue($success, "Select is not selected!");
return $this;
}
对最后一个功能说几句:
要使用自己的 dusk 断言,您需要创建自己的浏览器。我关注了this guide。
这里最重要的步骤:
- 创建一个扩展
Browser
的 class - 在此处包含您的自定义断言函数。
覆盖
protected
函数newBrowser
。 它唯一的工作是 return 一个新的 DuskBrowser。protected function newBrowser($driver)
{
return new DuskBrowser($driver);
}
DuskBrowser