Cypress页面对象模型(POM)中递归方法引用错误问题求助
解决Cypress类中递归方法的引用错误问题
这个问题我之前也碰到过,核心原因是类方法里的递归调用没有正确绑定当前实例的上下文,而且Cypress的异步回调会改变this的指向,咱们一步步来修复:
问题根源
你在类内部直接调用choose_randCategory(),但这个方法是类的成员,不是全局函数,必须通过类实例的this来访问。但Cypress的.then()回调是异步执行的,回调内部的this默认指向全局对象(浏览器中是window),不是你的DropDown_PO实例,所以会抛出ReferenceError。
解决方案:绑定上下文
有两种常用的方式来解决这个问题:
方法1:保存实例引用到变量
在方法开头把当前实例的this保存到一个变量(比如self),然后在回调里用这个变量调用递归方法:
class DropDown_PO { choose_randCategory(id = String(Math.floor(Math.random() * (15)) + 1), number = 2) { // 保存当前类实例的引用,避免回调中this指向变化 const self = this; let reccur = number + 1; if (id != 0) { cy.get("#category_selector_5>:nth-child(" + id + ")").then(($elem) => { cy.get("#category_selector_5").select($elem.text(), { force: true }); }); } cy.get("div[class='category_level_" + String(number) + "']").find('select').find('option').its('length').then(($firstele) => { let randomlist = Math.floor(Math.random() * ($firstele - 2)) + 2; cy.get("div[class='category_level_" + String(number) + "']").find('select').find('option').eq(randomlist).then(($choice) => { cy.get("div[class='category_level_" + String(number) + "']").find('select').select($choice.text(), { force: true }); cy.wait(4000); }); }); cy.get("body").then(($body) => { if ($body.find("div[class='category_level_" + String(number + 1) + "']").length) { // 使用保存的self调用递归方法 self.choose_randCategory(0, reccur); } }); } }
方法2:使用箭头函数保留上下文
箭头函数不会绑定自己的this,而是继承外层作用域的this,所以把Cypress的回调改成箭头函数,就能直接用this调用类方法:
class DropDown_PO { choose_randCategory(id = String(Math.floor(Math.random() * (15)) + 1), number = 2) { let reccur = number + 1; if (id != 0) { cy.get("#category_selector_5>:nth-child(" + id + ")").then(($elem) => { cy.get("#category_selector_5").select($elem.text(), { force: true }); }); } cy.get("div[class='category_level_" + String(number) + "']").find('select').find('option').its('length').then(($firstele) => { let randomlist = Math.floor(Math.random() * ($firstele - 2)) + 2; cy.get("div[class='category_level_" + String(number) + "']").find('select').find('option').eq(randomlist).then(($choice) => { cy.get("div[class='category_level_" + String(number) + "']").find('select').select($choice.text(), { force: true }); cy.wait(4000); }); }); // 把回调改成箭头函数,this会指向类实例 cy.get("body").then(($body) => { if ($body.find("div[class='category_level_" + String(number + 1) + "']").length) { this.choose_randCategory(0, reccur); } }); } }
额外优化建议
替换硬编码等待:
cy.wait(4000)是不可靠的,最好用cy.intercept()监听动态加载分类的Ajax请求,等请求完成后再继续:// 在测试用例开头拦截请求 cy.intercept('GET', '/api/categories/**').as('loadCategories'); // 选择选项后等待请求完成 cy.get(`div.category_level_${number}`).find('select').select($choice.text(), { force: true }); cy.wait('@loadCategories');使用模板字符串简化选择器:把字符串拼接改成模板字符串,代码更易读:
cy.get(`div.category_level_${number}`).find('select')
内容的提问来源于stack exchange,提问作者cy.user
相关产品推荐
相关产品推荐

