赛普拉斯-从函数设置全局变量

时间:2020-03-25 06:11:39

标签: javascript asynchronous cypress

我有以下流程:

1)在一页上,我得到一个字段的值:

 var myID;
 cy.get('#MYID').
        then(($txt) => {
            myID=  $txt.text();
        })
       .should('not.equal', null); 

2)然后,我导航到新页面并尝试检查此新页面是否包含此ID:

cy.get('#myTable').find('td').contains(myID);

它表示未定义myID。我知道第一个功能是异步的,请阅读说明它可以使用别名的文档。别名的问题在于,它必须位于beforeEach()函数中,不要长篇大论,在这个测试案例中我无法使用。我尝试使用async / await,但由于它仍未定义,因此对我似乎不起作用。

3 个答案:

答案 0 :(得分:1)

这里的基本问题是Cypress命令与创建它们的测试代码异步运行。如果您将控制台日志放入代码中,就会看到此信息,

var myID;
cy.get('#MYID')
  .then(($txt) => {
    myID=  $txt.text();
    console.log('1', myID);
  })
 .should('not.equal', null); 

console.log('2', myID);

这将打印出来

2 undefined
1 myText

您可以使用别名来克服此问题,并在命令链中传递一个值。

请参见此section of the docs,该示例显示了在“请勿使用此”示例中使用的类似代码。

在测试之间清除

BUT 别名,因此您应该设置beforeEach()以获得每个测试所需ID的新副本。

获取文本值的方式还有另一个问题。

在没有return语句的情况下,.then()命令会将接收到的任何主题传递给下一个命令。参见then- Yields

另外,回调函数中最后一个赛普拉斯命令的结果将作为新主题产生,并在没有返回值的情况下流入下一个命令 。< / p>

因此.should('not.equal', null)正在测试元素不为null,而不是文本也不为空。

更好的方法是转到.invoke('text'),它等效于$txt.text()并将文本值产生到.should()

.should('not.equal', null)也不会测试内容是否存在,因为空元素会从element.text()返回空字符串。请改用.should('not.equal', '')

通过别名保存

describe('grabbing ID for use in multiple tests', () => {

  beforeEach(() => {
    cy.visit('my-page-1.html')
    cy.get('#MYID')
      .invoke('text')
      .as('mySavedID')
  })

  it('ID should not be null', () => {

    cy.get('@mySavedID')
      .should('not.equal', '')

  })

  it('ID should be found in table', () => {

    cy.visit('app/navigate-to-new-page-2.html');
    cy.get('@mySavedID').then(myID => {
      cy.get('#myTable').find('td').contains(myID);
    })

  })
})

通过排队设置变量进行保存

如果访问第1页非常耗时,则别名模式可能并不理想。

在这种情况下,您可以通过自定义命令保存变量。区别在于您在.then()中拥有的代码被移到了排队的命令中,因此不会发生异步问题。

describe('grabbing ID for use in multiple tests', () => {

  let savedVariable;

  Cypress.Commands.add("saveVariable", {prevSubject: true}, (value) => {
    savedVariable = value;
  });

  it('id should not be null', () => {

    cy.visit('my-page-1')
    cy.get('#someId')
      .invoke('text')
      .should('not.equal', '')
      .saveVariable()

    // OR test the variable separately like this

    cy.wrap(savedVariable)
      .should('not.equal', '')
  })

  it('id should be found in table', () => {

    cy.visit('my-page-2');
    cy.get('#myTable').find('td').contains(savedVariable);

  })
})

注意
如果两个页面位于同一域中,例如SPA的两个页面,则以上内容有效。否则,测试运行程序会在遇到新域时重置自身,并且所有javascript变量都将丢失。

答案 1 :(得分:1)

在插件级别保存数据并通过任务访问它。调用 cy.visit 时会重新加载其他级别。将 data 和任务添加到 plugins/index.js

// plugins/index.js   
/// <reference types="cypress" />
module.exports = (on, config) => {

  // data will be stored here
  const data = {};

  // configuring tasks
  on('task', {
    setValue: (params) => {
      const { key, value } = params;
      data[key] = value;
      return value;
    },
    getValue: (params) => {
      const { key } = params;
      return data[key] || null;
    }
  })        
}

并在场景中使用:

// my.spec.js
/// <reference types="cypress" />
context('keeps data safe when changing pages', () => {
  it('visits first page and saves data', () => {
    return cy.visit('https://google.com').then(() => {
      // saving data 
      return cy.task('setValue', { key: 'visited', value: 'google' });
    })
  });

  it('visits another page and checks that data is available', () => {
    return cy.visit('https://example.com').then(() => {
      // getting data
      return cy.task('getValue', { key: 'visited' });
    }).then((value) => {
      expect(value).to.equal('google');
    });
  })
});

答案 2 :(得分:0)

不确定这是否是个好主意,但您可以将数据保存在 Cypress 全局对象上。

context('Pass data via the Cypress object', () => {

  before(() => {
    Cypress._savedData = {}
  })

  it('visits first page and saves data', () => {

    cy.visit('https://google.com');
    cy.get('#MYID')
      .should('not.equal', null)
      .then($el => Cypress._savedData[myID] = $el.text() )

  });

  it('visits another page and checks that data is available', () => {

    cy.visit('https://example.com');
    cy.get('#myTable').find('td').contains(Cypress._savedData[myID]);

  })
});