cypress.io:如何从cy.then或cy.each函数中发送触发器? [英] Cypress.io: How to send a trigger out of cy.then or cy.each function?

查看:81
本文介绍了cypress.io:如何从cy.then或cy.each函数中发送触发器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图验证天气,如果页面元素之间是否有我想要的存储关键字.

I try to verify weather if there have store keyword I want between the elements of pages.

例如:

store关键字=苹果"

store keyword = "apple"

页面的部分结构:

<tbody>
  <tr>
    <td class="store">
      <img class="offer-store" ... alt="amazon store" .../></td>
    <td ...
    ...</td>
  </tr>
  ...
  <tr>
    <td class="store">
      <img class="offer-store" ... alt="apple store" .../></td>
    <td ...
    ...</td>
  </tr>
</tbody>

我有3个产品,需要验证每个产品的商店都包含store关键字.

I have 3 products,need to verify that every product have a store contains store keyword.

一种产品可能有10页,每页有10家商店.

One product may have 10 pages,and have 10 stores per page.

转到产品页面,然后开始查找商店关键字.

Go to a product page,and start to find store keyword.

如果我在第三页的第二家商店中找到store关键字,则转到另一个产品页面.

If I find store keyword in second store on third page,then go to another product page.

我的策略:

for(var i = 0; i < 3; i++) // three product
{
  //assume I can go to store page of a product here(using var i)
  for(var j = 1; j < 10; j++) //search 10 store pages of the product
  { 
    cy.get(".offer-store").each(($item)=>{  
    cy.get($item).its('context').invoke('attr','alt').then((store)=>{
      if(store.indexOf('apple')!=-1)
        cy.log("found store!!")
        //send trigger to break cy.then, cy.each and a for loop
      })
    })
    cy.get('.btn-group').contains('>').click({force: true}) 
    //go to next page if not found in this page
  }
}

一开始,我使用变量作为触发器来执行中断命令.

At the beginning,I use a variable as a trigger to do break command.

以后我知道您不能将外部变量更改为触发器,需要在cy.then()或cy.each()的末尾使用cy.then()进行进一步的操作.

I know later that you can't change outer variable as a trigger,need to use cy.then() at the end of cy.then() or cy.each() to do further operation.

我尝试使用except()代替if()进行验证,但是当它在第一个元素中没有找到关键字时会出现断言错误(但是我想找到下一个).而且我还尝试了一个未捕获的异常:忽略错误:

I have tried to use except() to do verification instead of if(),but it will get assertion error when it did not find keyword in first element(but I want to find next one). And I also tried to make a uncaught:exception to ignore error:

Cypress.on('uncaught:exception', (err, runnable) => {
    return false
})

我将此代码放在cypress/support/commands.js上,但没有用.

I put this code at cypress/support/commands.js,and it didn't work.

我尝试的另一种方法是在cy.then()/cy.each()中返回一个值作为触发器,我得到了

Another way I tried is that return a value as a trigger in cy.then()/cy.each(),and I got

CypressError: cy.then() failed because you are mixing up async and sync code.

我的问题:

1.在这种情况下,如何发送触发器来中断cy.then,cy.each和for循环?

1.How to send trigger to break cy.then, cy.each and a for loop in this case?

2.如何忽略断言错误?

2.How to ignore assertion error?

推荐答案

您所追求的目标可能最好是通过递归命令/帮助程序来解决,该命令/帮助程序对页面进行爬网直到找到商店或没有其他页面为止

What you're after is probably best solved by a recursive command/helper that crawls the pages until a store is found or until no other page/stores are left.

下面, findStore 是一个调用 _walkStores 的函数,该函数是递归的.它会抓取当前页面,并在未找到任何内容的情况下尝试加载下一页.

Below, the findStore is a function that calls _walkStores which is recursive. It crawls current page, and tries to load next page if nothing is found.

describe('test', () => {
    function _walkStores ( store ) {
        let found = false;
        return cy.get('.store').each( elem => {
            if ( Cypress.$(elem).find(`[data-store="${store}"]`).length ) {
                found = true;
                return false; // exit early (not required)
            }
        }).then(() => {
            if ( found ) {
                return true;
            } else {
                if ( Cypress.$('.nextPage').length ) {
                    cy.get('.nextPage').click();

                    // if your `.nextPage` button doesn't immediately repaint 
                    //  DOM as my mock helper does, you should assert url
                    //  change or something similar, before calling _walkStores,
                    //  so as to ensure the _walkStores doesn't retrieve the
                    //  same old DOM nodes
                    return _walkStores(store);
                }
                return false;
            }
        });
    }

    function findStore ( store ) {
        return _walkStores(store).then( found => {
            expect(found, `store "${store}"`).to.true;
        });
    }

    function loadProduct ( name ) {
        cy.window().then(win => {
            const pages = [
                `
                    <div class="store">
                        <div class="offer-store" data-store="apple">Apple</div>
                    </div>
                    <div class="store">
                        <div class="offer-store" data-store="amazon">Amazon</div>
                    </div>
                    <button class="nextPage" onclick="nextPage()">next</button>
                `,
                `
                    <div class="store">
                        <div class="offer-store" data-store="microsoft">Microsoft</div>
                    </div>
                    <div class="store">
                        <div class="offer-store" data-store="dell">Dell</div>
                    </div>
                    <button class="nextPage" onclick="nextPage()">next</button>
                `,
                `
                    <div class="store">
                        <div class="offer-store" data-store="ibm">IBM</div>
                    </div>
                    <div class="store">
                        <div class="offer-store" data-store="lenovo">Lenovo</div>
                    </div>
                `,
            ];

            const doc = win.document;

            win.nextPage = () => {
                const page = pages.shift();
                if ( !page ) return;
                doc.querySelector('.content').innerHTML = 'loading...';
                setTimeout(() => {
                    doc.querySelector('.content').innerHTML = page;
                }, 1000 );
            };
            doc.body.innerHTML = `
                <h1>${name}</h1>
                <div class="content">
                    ${pages.shift()}
                </div>
            `;
        });
    }

    it('test', () => {
        ['Laptop A', 'Laptop B'].forEach( name => {
            loadProduct(name);
            // will pass
            findStore('ibm');
        });

        // will fail
        findStore('xx');
    });
});

这篇关于cypress.io:如何从cy.then或cy.each函数中发送触发器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆