【问题标题】:How to test web page has scrolling disabled with Cypress?如何使用赛普拉斯测试网页已禁用滚动?
【发布时间】:2021-06-01 01:08:44
【问题描述】:

也许这很简单,但我的 Cypress 测试无法测试锁定的滚动功能。

所以我有这个React 模态组件,它在安装时设置document.body.style.overflow = 'hidden'(仅限客户端)

我有以下Cypress 的测试套件:

  it('page cant scroll when modal is open', () => {
    cy.get('[data-testid="button"]')
      .first()
      .click();

    cy.window().scrollTo('bottom');
    
    // scroll should be disabled
    cy.window()
      .its('scrollY')
      .should('equal', 0);

    // cy.get('[data-testid="modal"]')
    //   .scrollTo('bottom')
    //   .its('scrollY')
    //   .should('not.equal', 0);
  });

Error message: Timed out retrying after 4000ms: expected 802 to equal 0

看起来赛普拉斯能够滚动window,尽管手动滚动页面时这是不可能的。

知道可能是什么问题吗?

OP 的编辑:以编程方式滚动页面仍然有效 (window.scrollTo())。 overflow 属性隐藏了滚动条,但这并不意味着滚动功能实际上被阻止(除了简单的用户交互)

我被建议使用另一种方法通过pagedownpageup 键导航来测试滚动冻结。在实际页面上使用上述键将被阻止,用户将无法滚动。

  it('page cant scroll when modal is open', () => {
    cy.get('[data-testid="button"]')
      .first()
      .click();

    cy.get('body').type('{pagedown}');

    cy.window()
      .its('scrollY')
      .should('equal', 0);

    cy.get('[data-testid="overlay"]').click();

    cy.get('body').type('{pagedown}');

    cy.window()
      .its('scrollY')
      .should('not.equal', 0);
  });

与前面的代码示例一样,这个 sn-p 也可以抛出错误。 Timed out retrying after 4000ms: expected 46 to equal 0.

【问题讨论】:

  • 因此,当模式打开时,用户会看到被阻止的滚动行为。那你为什么要测试滚动行为呢?在编写 cypress 测试时,您需要测试用户看到的内容。
  • @hurricane,因为你测试你实现的逻辑是否正常工作,不是吗?

标签: javascript reactjs scrollbar cypress react-modal


【解决方案1】:

您可以通过将overflow 属性设置为hidden 来禁用网页上的滚动行为,就像window.document.body.style.overflow = 'hidden' 一样。

假设React 模态组件设置document.body.style.overflow = 'hidden',如您之前提到的。

您可以断言scrolling 未通过one-liner 启用,如下所示:

cy.window().then(($el) => expect($el.document.body.style.overflow).to.eq('hidden'));

【讨论】:

  • 感谢您的回复!尽管将溢出样式从可见更改为隐藏是我的 Modal 组件所做的,但我并没有想到对此进行测试。我继续证明滚动 y 偏移量等于 0。
  • 看起来window.scrollTo() 工作顺利,即使设置了overflow:hidden。但如果 html 和 body 元素的样式都更新为 {overflow:hidden, height: 100%} 这不是最令人愉快的解决方案 imo,它就行不通了。
  • @pollx 很乐意为您提供帮助,我的解决方案对您有用吗?在你的评论中我不清楚。我同意这不是最令人愉快的解决方案。目前没有想到另一种解决方案。也许您可以在自定义命令中抽象出这个one-liner?所以你不会乱扔你的代码库吗?如果我认为另一种解决方案,我会发布另一个答案
  • 您的解决方案非常适合我的情况,谢谢!
  • 太棒了,所以我的下一个建议是将其添加为自定义命令,以便您可以抽象此断言。将其命名为 cy.isWindowScrollable() 或类似的名称。如果我的解决方案对您有帮助,如果您接受并支持我的回答,我将不胜感激!
【解决方案2】:

在我看来,测试expect($el.document.body.style.overflow).to.eq('hidden') 并不是很有用,因为您已经知道是这样的。你说

我有这个 React 模态组件,它在挂载时设置 document.body.style.overflow = 'hidden'

您是否在测试 React Modal 组件或它如何与应用交互?


查看Material-UI Modal(简单模态演示),当我单击“打开模态”按钮时,它会将相同的样式应用于body

<body dir="ltr" style="padding-right: 16px; overflow: hidden;">

当模式打开时,滚动条在视觉上已经消失了。

我发现最好的方法是在打开模态之前和之后测量宽度。滚动条实际上​​是附加到html 元素上的,所以这是我测量的(相对于窗口)

cy.visit('https://material-ui.com/components/modal/');

cy.window().then(win => {
  const htmlWidth = Cypress.$('html')[0].scrollWidth;
  const scrollBarWidth = win.innerWidth - htmlWidth;
  expect(scrollBarWidth).to.be.gt(0);                 // scrollbar is present
})

cy.contains('button', 'Open Modal').click();          // open the modal

cy.window().then(win => {
  const htmlWidth = Cypress.$('html')[0].scrollWidth;
  const scrollBarWidth = win.innerWidth - htmlWidth;
  expect(scrollBarWidth).to.be.eq(0);                 // scrollbar is absent
})

【讨论】:

  • 感谢您的回答!在这种情况下,页面宽度似乎是一个相当合理的测试方法!
  • 嘿,只是提到由于基于鼠标或触控板的自动滚动条行为,该测试将无法在本地 Mac 上运行。换句话说,滚动条仅在用户交互时显示,赛普拉斯无法检测其宽度。
  • 你可以通过应用.focus() 来克服这个问题——“在用户交互时”有点模糊。
猜你喜欢
  • 1970-01-01
  • 2021-10-20
  • 2023-02-14
  • 1970-01-01
  • 2018-04-14
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多