Symfony1 功能测试和sfWidgetFormChoice,具有多个true
我想测试编辑表单的用户,该表单中有一个Symfony1 功能测试和sfWidgetFormChoice,具有多个true,symfony1,symfony-1.4,symfony-forms,Symfony1,Symfony 1.4,Symfony Forms,我想测试编辑表单的用户,该表单中有一个。在功能测试中,如何从该表单小部件中选择或取消选择值 表单设置: 'regions_list' => new sfWidgetFormDoctrineChoice(array( 'multiple' => true, 'model' => 'Region' )), 功能测试: $browser-> getRoute('profile')-> //setField('profile[regions_list]
。在功能测试中,如何从该表单小部件中选择或取消选择
值
表单设置:
'regions_list' => new sfWidgetFormDoctrineChoice(array(
'multiple' => true,
'model' => 'Region'
)),
功能测试:
$browser->
getRoute('profile')->
//setField('profile[regions_list]', '[9][8]')-> // tried syntaxmany combinations
click('Save Profile', array(
'profile' => array(
// 'regions_list' => ???,
// I've tried many combinations even with setField and none made sense and where testable so far
)
))->
with('form')->begin()->
hasErrors(0)->
hasGlobalError(0)->
end()
;
我从来没有在
点击()
周围放置带('form')的,这是我的测试:
$browser->
getRoute('profile')->
click('Save Profile', array(
'profile' => array('regions_list' => array(8,9)
// with: <option value="8">something</option><option value="9">else</option>
// ... and other fields
)
))->
end()->
with('form')->begin()->
debug() -> // added this line so you can see what is happening
hasErrors(0)->
hasGlobalError(0)->
end()
;
$browser->
getRoute('profile')->
单击('保存配置文件',数组(
'profile'=>array('regions\u list'=>array(8,9)
//有什么事吗
//…和其他领域
)
))->
结束()->
使用('form')->begin()->
debug()->//添加了这一行,以便您可以看到发生了什么
hasErrors(0)->
hasGlobalError(0)->
完()
;
好吧,在深入研究click()过程之后,我无法得到我期望的结果
解决办法如下:
在
标记中,我希望如果我不发布任何值,它将按原样重新发布,如果我指定了值,它将只发布这些值,而不会尝试通过值控制开/关
它现在的反应方式是将初始值和所选值合并在一起,并替换与所选值键匹配的初始值键,这对我来说没有意义,因为这些键或它们的顺序是不相关的。我只关心选择的选项值
我的问题的答案是:在当前的实现中,您无法实现您所期望的
解决方案:
覆盖(或提交补丁,如果有时间)sfBrowserBase类中的doClickElement函数,该函数可能如下所示:(查找3条注释//修复选择多个和最后2个要添加的方法)
现在:
“profile'=>array('regions\u list'=>array(8,9))适合我。您尝试了setField(“profile[regions\u list]”,array(8,9))
?我已经尝试过了,现在又尝试过了,但在1.4.5版本中它不起作用=(我将尝试使用最新的1.4.x从头开始进行测试,以确保如果我是唯一一个没有得到它的人,那么不会造成混乱!昨天在发布我的问题时,我确实考虑过这一点;)我正在使用的这个项目是在1.4.5上,它不起作用=(但我想我可能会尝试使用最新版本?更准确地说,我得到了一个区域列表无效,并且debug()中发布的区域列表值显示了一个数组,上面有两个值(8,9),后面是已经存在的值,因此这些值也不会被取消选择。我得到了[无效]
当我试图添加一个不存在的区域
id时。这不正是验证程序在做它的工作吗?是的。没错。所以试着看看[8,9]是不是确实存在于区域
表中的id。
public function doClickElement(DOMElement $item, $arguments = array(), $options = array())
{
$method = strtolower(isset($options['method']) ? $options['method'] : 'get');
if ('a' == $item->nodeName)
{
if (in_array($method, array('post', 'put', 'delete')))
{
if (isset($options['_with_csrf']) && $options['_with_csrf'])
{
$arguments['_with_csrf'] = true;
}
return array($item->getAttribute('href'), $method, $arguments);
}
else
{
return array($item->getAttribute('href'), 'get', $arguments);
}
}
else if ('button' == $item->nodeName || ('input' == $item->nodeName && in_array($item->getAttribute('type'), array('submit', 'button', 'image'))))
{
// add the item's value to the arguments
$this->parseArgumentAsArray($item->getAttribute('name'), $item->getAttribute('value'), $arguments);
// use the ancestor form element
do
{
if (null === $item = $item->parentNode)
{
throw new Exception('The clicked form element does not have a form ancestor.');
}
}
while ('form' != $item->nodeName);
}
// form attributes
$url = $item->getAttribute('action');
if (!$url || '#' == $url)
{
$url = $this->stack[$this->stackPosition]['uri'];
}
$method = strtolower(isset($options['method']) ? $options['method'] : ($item->getAttribute('method') ? $item->getAttribute('method') : 'get'));
// merge form default values and arguments
$defaults = array();
$arguments = sfToolkit::arrayDeepMerge($this->fields, $arguments);
// fix for select multiple
$select_multiple_to_check = array();
$xpath = $this->getResponseDomXpath();
foreach ($xpath->query('descendant::input | descendant::textarea | descendant::select', $item) as $element)
{
if ($element->hasAttribute('disabled'))
{
continue;
}
$elementName = $element->getAttribute('name');
$nodeName = $element->nodeName;
$value = null;
if ($nodeName == 'input' && ($element->getAttribute('type') == 'checkbox' || $element->getAttribute('type') == 'radio'))
{
// fix for select multiple
if (substr($elementName, -2) == '[]')
{
$select_multiple_to_check[$elementName] = true;
}
if ($element->getAttribute('checked'))
{
$value = $element->hasAttribute('value') ? $element->getAttribute('value') : '1';
}
}
else if ($nodeName == 'input' && $element->getAttribute('type') == 'file')
{
$filename = array_key_exists($elementName, $arguments) ? $arguments[$elementName] : sfToolkit::getArrayValueForPath($arguments, $elementName, '');
if (is_readable($filename))
{
$fileError = UPLOAD_ERR_OK;
$fileSize = filesize($filename);
}
else
{
$fileError = UPLOAD_ERR_NO_FILE;
$fileSize = 0;
}
unset($arguments[$elementName]);
$this->parseArgumentAsArray($elementName, array('name' => basename($filename), 'type' => '', 'tmp_name' => $filename, 'error' => $fileError, 'size' => $fileSize), $this->files);
}
else if ('input' == $nodeName && !in_array($element->getAttribute('type'), array('submit', 'button', 'image')))
{
$value = $element->getAttribute('value');
}
else if ($nodeName == 'textarea')
{
$value = '';
foreach ($element->childNodes as $el)
{
$value .= $this->getResponseDom()->saveXML($el);
}
}
else if ($nodeName == 'select')
{
if ($multiple = $element->hasAttribute('multiple'))
{
// fix for select multiple
$select_multiple_to_check[$elementName] = true;
$elementName = str_replace('[]', '', $elementName);
$value = array();
}
else
{
$value = null;
}
$found = false;
foreach ($xpath->query('descendant::option', $element) as $option)
{
if ($option->getAttribute('selected'))
{
$found = true;
if ($multiple)
{
$value[] = $option->getAttribute('value');
}
else
{
$value = $option->getAttribute('value');
}
}
}
$option = $xpath->query('descendant::option', $element)->item(0);
if (!$found && !$multiple && $option instanceof DOMElement)
{
$value = $option->getAttribute('value');
}
}
if (null !== $value)
{
$this->parseArgumentAsArray($elementName, $value, $defaults);
}
}
// fix for select multiple
foreach($select_multiple_to_check as $elementName => $uselessbool)
{
$path = array_filter(preg_split('/(\[ | \[\] | \])/x', $elementName), create_function('$s', 'return $s !== "";'));
if ($this->findInArrayByArrayPath($arguments, $path) !== false)
{
$this->unsetInArrayByArrayPath($defaults, $path);
}
}
$arguments = sfToolkit::arrayDeepMerge($defaults, $arguments);
if (in_array($method, array('post', 'put', 'delete')))
{
return array($url, $method, $arguments);
}
else
{
$queryString = http_build_query($arguments, null, '&');
$sep = false === strpos($url, '?') ? '?' : '&';
return array($url.($queryString ? $sep.$queryString : ''), 'get', array());
}
}
// fix for select multiple
// taken from http://stackoverflow.com/questions/3145068/set-multi-dimensional-array-by-key-path-from-array-values/3145199#3145199
public function findInArrayByArrayPath(&$array, &$path, $_i=0) {
// sanity check
if ( !(is_array($array) && is_array($path)) ) return false;
$c = count($path); if ($_i >= $c) return false;
if ($_i==0) {$path = array_values($path);} // to make sure we don't get skipped numeric keys which does happens in the preg_split above
$k = $path[$_i];
if (array_key_exists($k, $array))
return ($_i == $c-1) ? $array[$k] : $this->findInArrayByArrayPath($array[$k], $path, $_i+1);
else
return false;
}
// fix for select multiple
public function unsetInArrayByArrayPath(&$array, &$path, $_i=0) {
// sanity check
if ( !(is_array($array) && is_array($path)) ) return false;
$c = count($path); if ($_i >= $c) return false;
if ($_i==0) {$path = array_values($path);} // to make sure we don't get skipped numeric keys which does happens in the preg_split above
$k = $path[$_i];
if (array_key_exists($k, $array))
if ($_i == $c-1) {
unset($array[$k]);
return true;
} else {
return $this->unsetInArrayByArrayPath($array[$k], $path, $_i+1);
}
else
return false;
}