Serenity-BDD如何实现隐藏元素的点击与交互操作
问题背景
自定义Screenplay模式下的Performable任务实现测试逻辑时,被上层遮挡的隐藏元素阻碍操作,需要测试角色(Actor)依次完成以下动作:
- 点击目标
<input>日期输入框 - 向输入框传入指定日期字符串
- 触发
<RETURN>回车键完成输入
原有实现代码如下:
public class Set { public static Performable dateFrom(String date) { return Task.where("{0} set 'dateFrom' filter to " + date, Click.on(SearchPage.dateTimePicker_from), Enter.theValue(date).into(SearchPage.dateTimePicker_from) .thenHit(RETURN) ); } }
运行测试抛出明确错误:[main] ERROR - Expected enabled element was not enabled
排查确认根因:目标<input>元素为隐藏状态,存在一个<div>元素遮挡在输入框上层,需要在不修改前端代码的前提下,在自定义Task中完成对该隐藏元素的交互操作。
解决方案
Serenity Screenplay 内置的Click、Enter等交互默认模拟真实用户行为,会强制校验元素可见、可点击、未被遮挡,遇到上述遮罩层+隐藏input的场景,不用改前端代码,按优先级选以下两种实现即可:
- 方案一(优先选择,完全匹配真实用户操作路径)
绝大多数日期选择组件的上层div本身就是交互触发区——用户点击div才会激活输入框、弹出日期面板。你只需要在Page对象里补充这个遮挡div的定位,先点这个触发元素,等input变为可交互状态后再执行输入、回车操作即可,示例代码:
public class Set { public static Performable dateFrom(String date) { return Task.where("{0} set 'dateFrom' filter to " + date, // 点击上层遮挡的触发div,激活日期输入框 Click.on(SearchPage.dateTimePicker_from_trigger), Enter.theValue(date).into(SearchPage.dateTimePicker_from) .thenHit(RETURN) ); } }
- 方案二(方案一不生效时使用,绕过可见性校验)
如果组件的input本身是永久隐藏(比如设置了opacity:0、display:none,用户交互全靠上层div代理),可以直接通过JS执行DOM操作,完全绕过Serenity和Selenium的元素可交互性校验,示例代码:
import net.serenitybdd.screenplay.actions.ExecuteJS; import static org.openqa.selenium.Keys.RETURN; public class Set { public static Performable dateFrom(String date) { return Task.where("{0} set 'dateFrom' filter to " + date, // JS触发元素点击事件 ExecuteJS.on(SearchPage.dateTimePicker_from).execute("arguments[0].click()"), // JS直接给input赋值 ExecuteJS.on(SearchPage.dateTimePicker_from).execute("arguments[0].value = arguments[1]", date), // JS派发回车键事件,触发组件的回车监听逻辑 ExecuteJS.on(SearchPage.dateTimePicker_from) .execute("arguments[0].dispatchEvent(new KeyboardEvent('keydown', {key:'Enter', keyCode:13, bubbles:true}))") ); } }
注意:JS操作不会触发用户真实交互时的所有事件冒泡逻辑,部分组件的输入校验、值同步逻辑是绑定在
input、change等原生事件上的,用JS赋值后建议加一步值校验,确认输入内容确实被组件识别、后续查询逻辑能正常触发。
内容的提问来源于stack exchange,提问作者Mo0rBy
相关产品推荐
相关产品推荐

