赛普拉斯测试 Material-UI 日期选择器不适用于 Github 操作

Posted

技术标签:

【中文标题】赛普拉斯测试 Material-UI 日期选择器不适用于 Github 操作【英文标题】:Cypress testing a Material-UI datepicker is not working on Github actions 【发布时间】:2021-12-16 07:48:09 【问题描述】:

在 github 操作中运行 cypress 测试时,我们有一个奇怪的行为。 MUI datepicker datepicker处于只读模式,不能输入任何日期(在其他环境下没问题)。

    赛普拉斯错误

    CypressError: Timed out retrying after 4000ms: cy.clear() failed 因为这个元素是只读的: <input aria-invalid="false" readonly="" type="text" aria-readonly="true" aria-label="Choose date" class="MuiOutlinedInput-input MuiInputBase-input css-1x5jdmq" value="">

    在视觉上看起来日期选择器没有任何按钮(正在发生的事情):

    控制台日志未显示错误或警告

在其他环境(windows/linux)上,测试工作正常,即使我们以无头模式(所有具有 UI 的桌面)启动测试。 MUI 日期选择器看起来与 MUI 文档 (link) 中的一样好。

Github 操作看起来像:

on:
  workflow_dispatch:

defaults:
  run:
    working-directory: ic3-test
jobs:
  build:
    runs-on: ubuntu-latest
    container: cypress/included:8.6.0

    steps:    
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v2
      with:
         node-version: '16'
    
    - name: Install dependencies
      run: npm install
      working-directory: ic3-test
                
    - name: Cypress run with env
      uses: cypress-io/github-action@v2
      with:
          # headless: true
          browser: chrome
          record: true
          working-directory: ic3-test

产生错误的 Cypress 行:

 cy.getWidget(widgetId).  // this is getting a div with wid = widgetId , works fine
        .find("input.MuiInputBase-input")
        .clear()
        .type(date). // date is a string

欢迎提供一些提示

【问题讨论】:

你能在失败的地方添加代码行吗? 看起来mui-lab 使用了来自外部库的日期函数。您的项目使用哪个库?例如:moment、luxon、dayjs、jalaali、hijri、js-joda @AlapanDas,不确定这是否会对您有所帮助。查看更新的问题 @AJcodez ,它是 date-fns -> mui.com/components/pickers @ic3 你如何将force: truetypeclear 一起添加并检查它是如何进行的 - cy.getWidget(widgetId).find("input.MuiInputBase-input").clear(force: true).type(date,force: true) 【参考方案1】:

在 azure devops 管道中运行 cypress 测试时,我们遇到了同样的错误。我认为这也是同样的原因,看看你没有任何按钮的日期选择器截图。

给我们错误的输入是@mui/lab/DatePicker

当我们在 azure devops 管道中运行 cypress 测试时,我们发现此组件呈现为 @mui/lab/MobileDatePicker。这里有解释:docs。 该版本不接受直接文本输入,但会打开一个对话框来选择/输入日期,因此 cypress 测试在尝试输入输入时失败。

我们的解决方案是直接使用@mui/lab/DesktopDatePicker

【讨论】:

有道理,我们将朝这个方向进行调查。 那是因为媒体查询赖特?现在这是要考虑的事情【参考方案2】:

这背后的原因是 Material UI 渲染了 MobileDatePicker 组件,因为查询 @media (pointer: fine) 在我们的 Github Actions Workflow 使用的无头 Chrome 上不匹配。移动组件只有只读输入,因此不能用.type().clear() 清除或输入(与DesktopDatePicker 组件相反,它具有可键入和可清除的输入)。

由于我们不想删除 MobileDatePicker 组件,因此我们创建了一个自定义命令,以便检查当前是否正在呈现移动日期选择器。如果在移动设备上,测试会打开日期选择器,单击编辑按钮,从而打开移动输入视图。

在那个输入视图中,输入字段不再是readonly。使用该命令,无论是台式机还是移动设备,都可以清除输入字段并输入。

Cypress.Commands.add(
  'chooseDatePicker',
  (selector: string, value: string) => 
    cy.get('body')
      .then(($body) => 
        const mobilePickerSelector = `$selector input[readonly]`;
        const isMobile = $body.find(mobilePickerSelector).length > 0;
        if (isMobile) 
          // The MobileDatePicker component has readonly inputs and needs to
          // be opened and clicked on edit so its inputs can be edited
          cy.get(mobilePickerSelector)
            .click();
          cy.get('[role="dialog"] [aria-label="calendar view is open, go to text input view"]')
            .click();
          cy.get(`[role="dialog"] $selector`)
            .find('input')
            .clear()
            .type(value);
          cy.contains('[role="dialog"] button', 'OK')
            .click();
         else 
          cy.get(selector)
            .find('input')
            .clear()
            .type(value);
        
      );
  ,
);

// Usage: 
const datePickerValue = '2021-01-03';
cy.chooseDatePicker('[data-testid="my-datepicker"]', datePickerValue);

【讨论】:

【参考方案3】:

由于我没有看到所有的代码,我会尽可能具体地评论,我希望你审查几个主题。

1- 检查转换后的代码中的属性。确保不应设置诸如 helperText=null 之类的属性。

2- 你可能需要安装 polyfills。例如 popper.js (传递依赖)。尽管 MUI 声称它是(波利)不需要的。技术每天都在进步,可能会有他们无法捕捉到的变化。

3- 确保工作模式正确。甚至用 Jest 测试它。这样的window.matchMedia。

【讨论】:

以上是关于赛普拉斯测试 Material-UI 日期选择器不适用于 Github 操作的主要内容,如果未能解决你的问题,请参考以下文章

如何使用赛普拉斯测试文件输入?

如何期望日期包含赛普拉斯中的另一个日期?

赛普拉斯可以运行在赛普拉斯文件夹之外导入的测试文件吗?

如何将日、月和年添加到赛普拉斯中的选定日期

赛普拉斯:测试元素是不是不存在

赛普拉斯在多项测试中冻结