【问题标题】:Moving slider with Cypress使用 Cypress 移动滑块
【发布时间】:2021-02-27 12:18:40
【问题描述】:

我有一个来自 rc-slider 的 Slider 组件,我需要 Cypress 来设置它的值。

<Slider
 min={5000}
 max={40000}
 step={500}
 value={this.state.input.amount}
 defaultValue={this.state.input.amount}
 className="sliderBorrow"
 onChange={(value) => this.updateInput("amount",value)} 
 data-cy={"input-slider"}
 />

这是我的赛普拉斯代码:

it.only("Changing slider", () => {
    cy.visit("/");
    cy.get(".sliderBorrow")
      .invoke("val", 23000)
      .trigger("change")
      .click({ force: true })
  });

到目前为止我尝试过的方法不起作用。 滑块的起点是 20000,试运行后到 22000,不管我通过什么值,任何数字范围。

看起来它以前可以工作,How do interact correctly with a range input (slider) in Cypress? 但现在不行了。

【问题讨论】:

  • 你能把错误截图也贴出来吗?
  • 问题是我没有收到错误,测试通过但滑块没有移动,它停留在原处
  • 你可以试试这个 - const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; describe('Changing Slider', () =&gt; { it('Updates the value and UI when changing a range input', () =&gt; { cy.get('.sliderBorrow').then(($range) =&gt; { const range = $range[0]; nativeInputValueSetter.call(range, 23000); range.dispatchEvent(new Event('change', { value: 23000, bubbles: true}));});});});
  • 是的,刚刚在github.com/cypress-io/cypress/issues/1570 上打开了该页面。试了一下,现在得到了这个错误:在这一行非法调用 ->> nativeInputValueSetter.call(range, 15000); Cypress 不喜欢 .call 方法
  • 在我的测试中,当我得到这样的任务时,我要求开发团队添加链接到滑块上的键值的按钮,然后单击然后检查结果。

标签: reactjs cypress


【解决方案1】:

答案非常非常简单。我发现解决方案巧合地为我的另一个测试(日期选择器)按下了输入键,并意识到按下向左或向右箭头键适用于滑块。 您也可以使用道具获得相同的结果。您唯一需要做的就是添加此依赖项:cypress-react-selector 并在此处遵循说明:cypress-react-selector

{rightarrow}使用示例

it("using arrow keys", () => {
  cy.visit("localhost:3000");

  const currentValue  = 20000;
  const targetValue = 35000;
  const increment = 500;
  const steps = (targetValue - currentValue) / increment;
  const arrows = '{rightarrow}'.repeat(steps); 

  cy.get('.rc-slider-handle')
    .should('have.attr', 'aria-valuenow', 20000)
    .type(arrows)

  cy.get('.rc-slider-handle')
    .should('have.attr', 'aria-valuenow', 35000)

})

【讨论】:

    【解决方案2】:

    @darkseid 的回答帮助我找到了最佳解决方案。

    有两个步骤

    1. 单击滑块的圆圈,将当前焦点移动到滑块上。
    2. 按键盘箭头按钮以达到您想要的值。

    我的滑块在滑块上的值之间跳转,因此这种方法可以工作。 (我正在使用离子范围滑块)

    这种方法不需要任何额外的依赖。

    // Move the focus to slider, by clicking on the slider's circle element
    cy.get(".irs-handle.single").click({ multiple: true, force: true });
    // Press right arrow two times
    cy.get(".irs-handle.single").type(
      "{rightarrow}{rightarrow}"
    );
    

    【讨论】:

      【解决方案3】:

      如果您能够稍微修改应用源代码,您或许可以使用 Application actions 解决此问题。

      应用程序操作为测试提供了应用程序的挂钩,可用于修改应用程序的内部状态。

      我使用函数组件对其进行了测试,该组件从 useState() 挂钩中公开了 setValue
      您使用了 Class 组件,所以我想您会公开this.updateInput(),类似于

        if (window.Cypress) {
          window.app = { updateInput: this.updateInput };
        }
      

      应用:index.js

      import React, { useState } from 'react';
      import { render } from 'react-dom';
      import './style.css';
      
      import Slider from 'rc-slider';
      import 'rc-slider/assets/index.css';
      
      function App() {
      
        const [value, setValue] = useState(20000);
      
        // Expose the setValue() method so that Cypress can set the app state
        if (window.Cypress) {
          window.app = { setValue };
        }
      
        return (
          <div className="App">
            <Slider
              min={5000}
              max={40000}
              step={500}
              value={value}
              defaultValue={value}
              className="sliderBorrow"
              onChange={val => setValue(val)}
              data-cy={"input-slider"}
            />
            <div style={{ marginTop: 40 }}><b>Selected Value: </b>{value}</div>
          </div>
        );
      }
      
      render(<App />, document.getElementById('root'));
      

      测试:slider.spec.js

      我发现在测试中断言值的最简单方法是使用滑块句柄的aria-valuenow 属性,但您可能有另一种方法来测试该值在页面上发生了明显变化。

      describe('Slider', () => {
      
        it("Changing slider", () => {
          cy.visit("localhost:3000");
      
          cy.get('.rc-slider-handle')
            .should('have.attr', 'aria-valuenow', 20000)
      
          cy.window().then(win => {
            win.app.setValue(35000);
          })
      
          cy.get('.rc-slider-handle')
            .should('have.attr', 'aria-valuenow', 35000)
      
        })
      })
      

      【讨论】:

      • 确认它有效吗?因为这对许多人来说是一个主要问题,而且会很好。
      • @RosenMihaylov 是的,但请注意,它不是 100% 万无一失的,例如更改处理程序 onChange={val =&gt; setValue(val)} 未通过此方法进行回归测试。使用 rc-slider 组件的唯一方法是(也许)使用 mousedown 和 mousemove 事件。
      • @RosenMihaylov 在下面看看我的解决方案
      【解决方案4】:

      我让它与流行的 react-easy-swipe 一起使用:

      cy.get('[data-cy=week-picker-swipe-container]')
        .trigger('touchstart', {
          touches: [{ pageY: 0, pageX: 0 }]
        })
        .trigger('touchmove', {
          touches: [{ pageY: 0, pageX: -30 }]
        })
      

      【讨论】:

        【解决方案5】:

        对于任何使用 Material UI/MUI 5+ 滑块的人:

        首先,这个 github 问题和评论可能有用:https://github.com/cypress-io/cypress/issues/1570#issuecomment-606445818。 我尝试通过使用滑块下方使用的类型范围访问输入来更改值,但对我来说这并没有成功。

        我使用 MUI 5+ Slider 的解决方案:

        <Slider
          disabled={false}
          step={5}
          marks
          data-cy="control-percentage"
          name="control-percentage"
          defaultValue={0}
          onChange={(event, newValue) =>
            //Handle change
          }
        />
        

        这里重要的是启用标记属性。这让我可以直接点击 cypress 测试中的标记,当然也可以抽象为一个支持函数。

        cy.get('[data-cy=control-percentage]').within(() => {
          // index 11 represents 55 in this case, depending on your step setting.
          cy.get('span[data-index=11]').click();
        });
        

        【讨论】:

          猜你喜欢
          • 2020-09-05
          • 2017-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-16
          • 2013-08-13
          相关资源
          最近更新 更多