我有一个页面用于编辑我的应用程序中的类别。它使用Twitter Bootstrap进行布局,非常简单。它看起来像这样:
+===========================================
| page header - contains menus, etc.
+===========================================
Category Editor
+----+------------+-------------------+
| ID | Status | Name |
+----+------------+-------------------+
| 1 | [active] | Category Name 1 |
| 2 | [inactive] | Category Name 2 |
| ... more rows ... |
+----+------------+-------------------+
[Add new row] [Save]
(方括号内的项为按钮)
该页面基本上是一个列出所有类别的表,以及它们的ID值和一个切换它们状态的按钮(active
或inactive
)。我使用Knockout来绑定表行&它们对我的模型的价值
表单的工作方式是这样的:
要将状态从活动更改为非活动(反之亦然),请单击该按钮。这将更新视图模型并更改按钮中的文本。
要编辑类别名称,单击它。这将隐藏名称(在
<span>
中)并在相同的表单元格中显示<input>
元素。当你输入完新名称后,离开(模糊)输入元素:更新后的名称将被显示,输入元素将再次隐藏。要保存你所有的编辑,点击保存按钮。
就我所知一切正常。现在我想用Selenium编写一些测试来测试这个功能。我使用的是Selenium server 2.38.0和PHPUnit。
我遇到的问题是,无论如何,我不能让输入元素模糊。我在谷歌上搜索了很多不同的东西,找到了很多不同的建议。我试过:
使用Selenium的
keyPress
方法发送一个制表符到输入元素(我已经尝试过"'t"
,"'9"
,"''t"
,"''9"
,'${KEY_TAB}'
)使用Selenium的
type
方法发送一个制表符(与上面相同的字符串)使用Selenium的
click
方法点击不相关的页面元素使用Selenium的
mouseDownAt
和mouseUpAt
来模拟鼠标按下一个不相关的页面元素。设置
fireEvent
发送"blur"到输入元素fireEvent
发送一个"focus"到输入元素,紧接着另一个fireEvent
发送一个"blur"事件fireEvent
发送一个"focusout"到输入元素
有人知道如何模糊使用硒的输入元素吗?
编辑:为了它的价值,我已经缩小到Firefox的问题。
问题
这似乎是Selenium和Firefox 31.0的问题。我可以使用Firefox的Selenium IDE插件和Selenium Server来复制它。
问题来了:
在我的页面标记中,我有一个包含单元格的表,如下所示:
<td data-bind="click: handleNameClick" class="form-group">
<span class="item-name" data-bind="text: name, visible: !isEditing()"></span>
<input required type="text" class="form-control" data-bind="value: name, visible: isEditing(), hasFocus: isEditing">
</td>
当单击
<td>
时,我的视图模型上的handleNameClick()
方法被调用。这个方法看起来像这样:自我。handleNameClick = function() {self.isEditing(真正的);}
当
isEditing
为true
时,<input>
可见,<span>
隐藏;当false
时,<span>
可见,<input>
隐藏。hasFocus
绑定是用来处理blur
事件的——当<input>
失去焦点时,isEditing
的值从true
变为false
,并且<input>
被隐藏。
这最后一步在Chrome中工作很好,无论是在硒控制下还是当我使用表单时。在Selenium控制下,不是在Firefox中工作。
解决方案
为了解决这个问题,我创建了一个变通方法,其中handleNameClick
在视图模型中的项目上迭代,并在将isEditing
设置为true
之前将isEditing
设置为false
。我的handleNameClick
方法现在看起来像这样:
self.handleNameClick = function() {
// iterate over the parent's items array and set isEditing to false
// for all of them
//
$.each(self.parent.items(), function (i, v){ v.isEditing(false); });
// now set isEditing = true for this item
//
self.isEditing(true);
}
其中self.parent
是视图模型,并在每个项目实例化时传递给构造函数。
不是最好的解决方案,但它可以工作,并可能使页面更有弹性。