如何在Odoo12 Tour测试中用JavaScript选择动态生成下拉项?
Odoo 12 Tour 测试:定位并选择动态生成的下拉建议项
核心问题解决思路
动态ID无法复用,需改用稳定的CSS选择器定位输入框,同时利用Odoo Tour内置的异步等待机制,确保下拉列表加载完成后再执行选择操作。
可行解决方案及代码示例
方案1:拆分步骤+extra_triggers等待下拉加载
将输入与选择拆分为两个独立步骤,通过extra_triggers等待下拉列表出现后再执行选择:
tour.register('test2_tour', { test: true, url: "/web", wait_for: base.ready(), }, [ // 前置步骤... { content: "点击「Add a product」", trigger: 'a:contains("Add a product")', }, { content: "输入产品ID", trigger: 'div.o_field_widget[name="product_id"] input', // 用字段name定位,替代动态ID run: 'text 167020', extra_triggers: ['.ui-autocomplete li.ui-menu-item'], // 等待下拉建议项加载完成 }, { content: "选择首个匹配产品", trigger: '.ui-autocomplete li.ui-menu-item:first', // 定位首个下拉项 run: 'click', }, { content: "点击保存按钮", trigger: '.modal-footer .btn-primary span', // 简化选择器,替代:nth-child }, ]);
方案2:自定义run函数+base.waitFor
在单个步骤内完成输入与选择,通过base.waitFor等待下拉加载,确保操作顺序:
tour.register('test2_tour', { test: true, url: "/web", wait_for: base.ready(), }, [ // 前置步骤... { content: "点击「Add a product」", trigger: 'a:contains("Add a product")', }, { content: "输入产品ID并选择匹配项", trigger: 'div.o_field_widget[name="product_id"] input', run: function (actions) { // 输入产品ID actions.text('167020', this.$anchor); // 等待下拉列表加载完成 return base.waitFor(() => { return $('.ui-autocomplete li.ui-menu-item').length > 0; }).then(() => { // 点击首个下拉项 $('.ui-autocomplete li.ui-menu-item:first').click(); }); }, }, { content: "点击保存按钮", trigger: '.modal-footer .btn-primary span', }, ]);
关键注意事项
- 避免动态ID:优先使用字段
name属性(如name="product_id")、Odoo内置widget类名(如o_field_widget)等稳定标识定位元素。 - 拒绝
setTimeout:Odoo Tour不会等待setTimeout完成,必须使用base.waitFor或extra_triggers处理异步加载。 - 简化选择器:避免使用冗长的层级选择器,改用更通用的类名或属性选择器,提升代码健壮性。
实用参考文档
- Odoo 12官方开发者文档「Tour Tests」章节:详细介绍Tour的步骤配置、
waitFor、extra_triggers等核心API。 - Odoo官方Web模块测试示例:查看
addons/web/static/tests/tours/目录下的官方测试用例,学习Tour的最佳实践。
内容的提问来源于stack exchange,提问作者Atrofio
相关产品推荐
相关产品推荐

