我遇到了以下Cypress异步行为的问题。我需要创建一个函数方法,它将从一个URL中获取一个参数并返回它,因为稍后它将在不同的地方使用
所以这个方法看起来像这样:
getParameterFromUrl(): string {
cy.url().then(url => {
cy.log(url);
const parameterFromUrl = url.match(/\d+$/)[0];
cy.log(paramterFromUrl);
// return parameterFromUrl I know this doesnt work because is within a then
}
}
然后在测试的很多部分,我需要使用这个参数:
const parameter = onMyPageObject.getParameterFromUrl();
cy.log(parameter)
我知道这是undefined。我已经检查了很多可能的解决方案,但任何说服我,因为我必须解释的代码无处不在,然后在外面和匹配的正则表达式无处不在(我不喜欢在所有)。等待只是为请求工作,所以我甚至可以使用它。
在这种情况下,我可以做些什么来改变异步行为,做一些像这样简单的事情?
4条答案
按热度按时间ha5z0ras1#
最简单的方法是从方法中返回链。
.then(... return parameterFromUrl)
只是修改你返回的内容,但是你必须返回整个链,并像Chainable<string>
一样对待它。使用该方法:
rqenqsqc2#
您不必在方法内部设置别名,可以使用Zoe提供的模式在测试外部设置别名。
然后,方法的调用者能够指定使用什么别名。
它的工作原理与Cypress给出的示例相同,您只是将一些代码推到了方法中。
t2a7ltrp3#
这永远不会像现在这样工作,仅仅因为你调用了一个异步函数。
url()
调用不会返回一个值,而是会触发一个请求,该请求将在 * 将来某个时候 * 完成,但不会立即完成。因此,getParameterFromUrl
根本不可能返回正确的响应,因为当它返回它所依赖的url
调用时,它还没有完成。这个问题有两种可能的解决方案。
第一种选择:
向
getParameterFromUrl
传递一个回调函数,这样只要url
完成并有完整的响应,它就会回调调用者。这是Javascript中最常见的模式,你的代码正在使用它。一种可能的实现方式如下:在这里,
getParameterFromUrl
接受一个函数作为参数,如果在获得最终值时调用该函数,则调用者可以使用它来知道值何时准备就绪。所以现在你把你的调用站点改成这样:请注意,您只使用回调中的最终值,而不是原始调用的返回值。如果在此调用之后有代码,则这一点很重要。
第二种选择:
让getParameterFromUrl返回一个
promise
,以符合更现代的Javascript开发。这一次我们返回一个对象,该对象将在调用完成时通知调用者并获取可用值。使用语言功能,我们可以使其更容易使用:表面上的简单性来自
async
行为,它给人一种线性执行的错觉,而实际上它不是,并且将以与以前几乎相同的顺序运行。调用者也需要修改以使用此:这要求包含函数也是
async
,这将强制使其一直到达调用树的顶部,但希望它能产生更自然的代码,更容易理解。当然,如果你想避免大量的重写,你也可以编写一个.then
调用,达到同样的效果。hfsqlsce4#
好吧,我找到了一个解决方案,但我不太喜欢它,因为未来的开发人员将不得不进入方法内部检查别名,因为我们在不同的类中
然后在另一个班级
正如我告诉你的,这在官方文档@jonrsharpe中解释过,但有几个问题。我不能直接在第二个类中使用这个.parameter,因为这会失败,第二件事是,未来的开发人员可能会在上面的很多行中使用这个@parameter,并且必须寻找实际定义别名的方法并检查别名名称。一种选择是将别名作为参数添加,但同样必须在代码中查找,因为它是在方法中键入的字符串,而不是真实的变量。另外,所有使用此参数的代码都将包含在一个新的then()命令中,这将使代码非常难以阅读。
所以是的,这个解决方案有效,但我认为它应该是一个更好的