【问题标题】:Cypress : Setting a variable from the result of a task赛普拉斯:根据任务结果设置变量
【发布时间】:2020-04-24 20:11:24
【问题描述】:

我需要从 cypress 场景开始期间发送的电子邮件中检索 url。

等待电子邮件并检索其中的 url 是一个异步任务,所以我创建了一个名为“readMail”的 cypress 插件:它将电子邮件地址作为输入,等待 gmail api 实际有一封电子邮件的收件人是这个地址,然后阅读邮件并返回一个解析包含在电子邮件正文中的 url 的承诺。此过程运行良好,因为来自插件的日志确实正确显示了提取的 url。

我的问题是让这个extractedUrl 可供以后用作参数,例如cy.visit(extractedUrl) :在task(...).then(...) 的主体之外,变量仍未设置。

代码如下:

it('should generate correct email', () => {
    const recipientEmail: string = 'some@email.com';
    const extractedUrl:string = '';

    // ....scenario generating a email to 'some@email.com'.....

    cy.task('readMail', recipientEmail) // plugin logs "https://some.url.com" after a few seconds
    .then((result:any) => {
        extractedUrl= result;
        console.log(result); // logs "https://some.url.com" in the terminal
        cy.log("1:" + extractedUrl); // logs "1:https://some.url.com" in cypress UI
    });
    cy.log("2:"+ extractedUrl); // logs "2:" in cypress UI
    console.log(extractedUrl); // logs nothing
    cy.visit(extractedUrl);
});

我可能遗漏了有关 cypress 如何处理异步的一些内容...我尝试了几种不同的方法:cy.wrapcypress-wait-until 插件,但找不到任何方法来使这些工作。

实际上我找到了一种方法是在测试之外声明extractedUrl并开始一个新的测试it('...', () => {...}):然后,extractedUrl实际上在下一个测试开始时具有正确的值,但这并不理想我想知道为什么。 感谢您的帮助!

【问题讨论】:

  • 请注意,在 cypress UI 中,我可以看到 cypress 实际上正在等待任务几秒钟,然后记录“2:”。这就是为什么我无法将我的异步知识与它在 cypress 中的工作方式相匹配。

标签: javascript typescript promise task cypress


【解决方案1】:

TL;DR;将整个代码放入 then 回调中

it('should generate correct email', () => {
    const recipientEmail: string = 'some@email.com';
    const extractedUrl:string = '';

    // ....scenario generating a email to 'some@email.com'.....
    // plugin logs "https://some.url.com" after a few seconds
    cy.task('readMail', recipientEmail).then((result:any) => {
        extractedUrl= result;
        console.log(result); // logs "https://some.url.com" in the terminal
        cy.log("1:" + extractedUrl); // logs "1:https://some.url.com" in cypress UI
        cy.log("2:"+ extractedUrl); // logs "2:" in cypress UI
        console.log(extractedUrl); // logs nothing
        cy.visit(extractedUrl);
    });

});

与看起来相反,赛普拉斯命令不返回承诺,它们返回类似承诺的对象,执行队列由赛普拉斯框架处理。这就是在处理 Promise 时一些合乎逻辑的操作不起作用的主要原因。

更多信息在这里:Await-ing Cypress Chains #1417

您也可以尝试cypress-promise,这是一个将类似 cypress 的 promise 对象更改为实际 promise 的插件。更多信息在这里:Cypress.io — Using async and await by Nicholas Boll

更新 #1:

您还可以使用别名来访问该值:

it('should generate correct email', () => {
    const recipientEmail: string = 'some@email.com';
    const extractedUrl:string = '';

    // ....scenario generating a email to 'some@email.com'.....
    // plugin logs "https://some.url.com" after a few seconds
    cy.task('readMail', recipientEmail).then((result:any) => {
        extractedUrl= result;
        cy.wrap(result).as('extractedUrl');
        console.log(result); // logs "https://some.url.com" in the terminal
        cy.log("1:" + extractedUrl); // logs "1:https://some.url.com" in cypress UI
    });

    cy.get('@extractedUrl').then((extractedUrl) => {
        cy.log("2:"+ extractedUrl); // logs "2:" in cypress UI
        console.log(extractedUrl); // logs nothing
        cy.visit(extractedUrl);
    })

});

【讨论】:

  • 所以我无法在 cypress 中使用 await/async 吗?无论如何,我尝试了别名方法,它似乎有效!谢谢!
  • 不,真的不可能在使用 cypress 的测试代码中使用 await/async。您可以在任务和其他插件中使用它。这是另一个了解原因的好资源:docs.cypress.io/guides/core-concepts/…
  • 在例如使用 wrap().as() a beforeEach 正在更新上下文,我可以通过this.<ALIAS> 访问该值——但为什么我不能在实际测试中使用 wrap().as() 并通过上下文访问它?为什么我必须使用 cy.get().then() 构造?
猜你喜欢
  • 1970-01-01
  • 2017-01-28
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 2022-07-22
  • 1970-01-01
  • 1970-01-01
  • 2021-08-20
相关资源
最近更新 更多