Cypress.io - 如何等待返回调用属性的方法的结果?

Jan*_*ess 2 invoke node.js pageobjects typescript cypress

我有一个方法可以获取元素的 href 属性hrefAppTheme并检查它是否是 string-array 的值之一appThemes

describe('...',() => {
    it('should ...', () => {
      (...)
      let defaultAppTheme = '';
      onMenuPage.hrefAppTheme.invoke('attr', 'href')
        .then(hrefVal => {
          if (typeof hrefVal !== 'undefined') {
            expect(hrefVal).to.be.oneOf(onMenuPage.appThemes);
            defaultAppTheme = hrefVal;

      //referencing the variable 'defaultAppTheme' further below...
    }
  });
Run Code Online (Sandbox Code Playgroud)

可以安全地假设this.hrefAppTheme.invoke('attr', 'href')总是返回用户主题之一(字符串),因为上面的代码工作可靠。

由于事实证明我需要在几个不同的地方使用该逻辑,因此我想将其提取到一个方法中并将其放入页面对象类中。这就是我所拥有的:

export default class MenuPage {
  (...)
  getUserTheme(): string {
    let userTheme = '';
    cy.then(() => {
      this.hrefAppTheme.invoke('attr', 'href')
        .then(resVal => {
          if (typeof resVal !== 'undefined') {
            userTheme = resVal;
          }
        });
    });
    return userTheme;
  }
Run Code Online (Sandbox Code Playgroud)

我认为我需要使用cy.wrap()- 方法来分配返回的字符串:

describe('...',() => {
    it('should ...', () => {
      (...)
      let defaultAppTheme = '';
      cy.wrap(onMenuPage.getUserTheme()).then(resVal => {
        defaultAppTheme = resVal;
        expect(defaultAppTheme).to.be.oneOf(onMenuPage.appThemes);
      });

      //referencing the variable 'defaultAppTheme' further below...
Run Code Online (Sandbox Code Playgroud)

但是,这样做有问题,因为返回的值始终是空字符串,而不是解析的值:

AssertionError: expected '' to be one of [ 'theme-light.css', 'theme-dark.css' ]
      + expected - actual

      +[ 'theme-light.css', 'theme-dark.css' ]
Run Code Online (Sandbox Code Playgroud)

等待调用属性的结果会导致错误

如何返回 (...) 的解析值myWebelement.invoke('attr', 'href').then(hrefVal => {,以及如何通过调用此方法将其分配给变量?

或者是否有更好的方法将工作代码提取到方法中?

Lol*_*ola 7

this.hrefAppTheme已经是一个 Chainer,因为它可以.invoke('attr', 'href')在它之后使用。您可以通过返回它来简化。

接下来的内容.then(resVal...)都是关于修改resVal. 将你的userThemevar 移到那里并返回它。返回值修改先前链接器的结果。

export default class MenuPage {
  (...)
  getUserTheme(): Chainable<string> {
    
    return this.hrefAppTheme.invoke('attr','href') // return the whole chain
      .then(resVal => {
        let userTheme = '';
        if (typeof resVal !== 'undefined') {
          userTheme = resVal;
        }
        return userTheme;   // return here to modify the chainer result
      });
  }
Run Code Online (Sandbox Code Playgroud)

然后在测试中,就像任何自定义命令一样使用它

describe('...',() => {
    it('should ...', () => {

      onMenuPage.getUserTheme().then(defaultAppTheme => {
        expect(defaultAppTheme).to.be.oneOf(onMenuPage.appThemes);
      });
Run Code Online (Sandbox Code Playgroud)

AssertionError:预期 '' 为 [ 'theme-light.css', 'theme-dark.css' ] 之一

您现在可能可以明白为什么会发生该错误,因为返回值是userTheme = ''当 resVal 为 时undefined

可以通过默认返回预期字符串 1 来解决此问题:

export default class MenuPage {
  (...)
  getUserTheme(): Chainable<string> {
    
    return this.hrefAppTheme.invoke('attr','href') 
      .then(resVal => {
        let userTheme = 'theme-light.css';        // change default value
        if (typeof resVal !== 'undefined') {
          userTheme = resVal;
        }
        return userTheme;  
      });
  }
Run Code Online (Sandbox Code Playgroud)

  • 然而,这是更好的答案 - 删除不必要的“cy.then()”,此外它还纠正了引发“断言错误”的菜鸟错误。 (4认同)
  • `getUserTheme(): string` 不正确,因为它实际上返回 `getUserTheme(): Chainable&lt;string&gt;` (2认同)