You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cypress上传文件后点击提交仍提示File is Required问题排查

问题描述

Cypress自动化测试场景下,向文件输入控件上传文件后点击上传按钮,系统内部校验仍提示「File is Required(文件为必填项)」。
测试用例代码如下:

it.only('Check the item upload file validations', () => {
    cy.get('[icon="fa fa-cloud-upload"]').click()
    cy.get('[id="itemListController"]',{force:true}).attachFile('itemfile.xlsx')
    cy.get('.p-float-label > [type="submit"]').click()
    // cy.pause()  
})

异常表现:代码执行过程中,文件输入框位置已经清晰显示了上传的文件名,但系统始终判定未挂载待上传文件,触发必填校验报错。
问题对应截图:
文件上传必填校验报错截图
点击提交按钮前,目标上传文件的DOM元素结构如下:

<input _ngcontent-wul-c516="" id="itemListController" formcontrolname="itemListController" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" type="file" hidden="" class="ng-untouched ng-pristine ng-invalid">
问题根因

从DOM上的ng-untouched、ng-pristine、ng-invalid类名可以判断,这是Angular框架的响应式表单控件,异常核心原因是文件上传操作没有触发Angular依赖的状态同步机制:

  • cypress-file-upload插件的attachFile方法默认仅给input DOM元素赋值文件对象,没有完整派发Angular表单监听的input、change事件,Angular变更检测没有感知到控件值变化,JS层绑定的表单值始终为空,因此校验逻辑判定文件未上传。视觉上看到文件名是浏览器原生file input赋值后的默认渲染效果,不代表框架层已经同步到该值。
  • 选择元素时传入{force:true}参数会跳过Cypress默认的交互事件模拟(包括焦点、失焦、变更等事件派发),进一步加剧了状态不同步的问题。
  • 该file input带有hidden属性,属于Angular组件库常见的“隐藏原生输入框+自定义上传UI”的实现模式,单纯给原生input赋值不会触发组件内部封装的状态更新逻辑。
修复方案

按优先级尝试以下方案即可解决:

  • 方案一:给attachFile方法补充事件触发配置,主动派发Angular需要的同步事件,同时增加状态断言,等表单控件状态更新完成后再点击提交,修改后的代码如下:
it.only('Check the item upload file validations', () => {
  cy.get('[icon="fa fa-cloud-upload"]').click()
  cy.get('[id="itemListController"]', {force: true})
    .attachFile('itemfile.xlsx', {
      subjectType: 'input',
      force: true,
      // 主动派发框架监听的事件,冒泡到根节点确保能被监听到
      triggerEvents: ['input', 'change', 'blur']
    })
  // 显式等待控件状态更新为有效,避免事件未完成冒泡就提交
  cy.get('[id="itemListController"]')
    .should('not.have.class', 'ng-pristine')
    .and('have.class', 'ng-valid')
  cy.get('.p-float-label > [type="submit"]').click()
})
  • 方案二:如果上述配置仍不生效,可以在上传完成后手动给input元素派发事件,主动触发Angular变更检测:
cy.get('[id="itemListController"]', {force: true})
  .attachFile('itemfile.xlsx')
  .then($input => {
    const inputEl = $input[0]
    inputEl.dispatchEvent(new Event('input', { bubbles: true }))
    inputEl.dispatchEvent(new Event('change', { bubbles: true }))
    inputEl.dispatchEvent(new Event('blur', { bubbles: true }))
  })
// 后续补充状态断言、提交操作即可
  • 方案三:若项目使用的是PrimeNG等封装度较高的上传组件,可以直接调用组件实例的文件上传方法赋值,绕过DOM操作的事件同步问题:通过cy.get(...).invoke('ngInjector')拿到控件实例后,直接给对应formControl赋值文件对象,再调用控件的更新方法即可。

内容的提问来源于stack exchange,提问作者Avishka Perera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:15:42