web-dev-qa-db-ja.com

サイプレスでその要素が実行可能でないことを表明する

エレメントがページ上でアクション可能ではなく(この場合、別のエレメントで覆われている)、それをクリックしようとすると、サイプレスは次のようなエラーを表示します:

_CypressError: Timed out retrying: cy.click() failed because this element:

<span>...</span>

is being covered by another element:
_

すごい!しかし、これが事実であること、つまり要素をクリックできないことを主張する方法はありますか?

これは機能しません:

  • _should.not.exist_-要素は存在します
  • _should.be.disabled_-要素は無効になっていません
  • _should.not.be.visible_-要素は表示されています(別の透明な要素で覆われているだけです)
  • これは例外ではないため、cy.on('uncaught:exception', ...)を使用します。
16
Laura

click_spec.coffee でサイプレステストを参照してください。

_it "throws when a non-descendent element is covering subject", (done) ->

  $btn = $("<button>button covered</button>")
    .attr("id", "button-covered-in-span")
    .prependTo(cy.$$("body"))

  span = $("<span>span on button</span>")
    .css(position: "absolute", 
         left: $btn.offset().left, 
         top: $btn.offset().top, 
         padding: 5, display: "inline-block", 
         backgroundColor: "yellow")
    .prependTo(cy.$$("body"))

  cy.on "fail", (err) =>
    ...
    expect(err.message).to.include "cy.click() failed because this element"
    expect(err.message).to.include "is being covered by another element"
    ...
    done()

  cy.get("#button-covered-in-span").click()
_

デバッグにはcy.on('fail')の使用のみを推奨していますが、このテストを模倣するのが最も簡単です。

これは、expect().to.throw()を使用して、例外が期待どおりに発生することを確認する単体テストに似ているため、ここでパターンが正当化されていると感じます。

念のため、click({force: true})の呼び出しを含めます。

_it('should fail the click() because element is covered', (done) => {

  // Check that click succeeds when forced
  cy.get('button').click({ force: true })

  // Use once() binding for just this fail
  cy.once('fail', (err) => {

    // Capturing the fail event swallows it and lets the test succeed

    // Now look for the expected messages
    expect(err.message).to.include('cy.click() failed because this element');
    expect(err.message).to.include('is being covered by another element');

    done();
  });

  cy.get("#button-covered-in-span").click().then(x => {
    // Only here if click succeeds (so test fails)
    done(new Error('Expected button NOT to be clickable, but click() succeeded'));
  })

})
_

カスタムコマンドとして

あなたが求めたchai拡張の作り方はわかりませんが、ロジックはカスタムコマンドでラップできます

/ cypress/support/index.js

_Cypress.Commands.add("isNotActionable", function(selector, done) {
  cy.get(selector).click({ force: true })
  cy.once('fail', (err) => {
    expect(err.message).to.include('cy.click() failed because this element');
    expect(err.message).to.include('is being covered by another element');
    done();
  });
  cy.get("#button-covered-in-span").click().then(x => {
    done(new Error('Expected element NOT to be clickable, but click() succeeded'));
  })
}) 
_

/ cypress/integration/myTest.spec.js

_it('should fail the click() because element is covered', (done) => {
  cy.isNotActionable('button', done)
});
_

注意

テストの前提(つまり、ボタンが覆われている)がfalseの場合、done()がタイムアウトすることを期待していました。

これは発生しません(理由は不明)。ただし、2回目のクリックから.then()をチェーンすることで、done()をエラーメッセージとともに呼び出すことができます。 then()コールバックは、クリックが成功した場合にのみ呼び出されます。それ以外の場合は、cy.once('fail')コールバックがクリックの失敗を処理します(サイプレス独自のテストに従って)。

13
Richard Matsen