Cypress文件上传测试中如何触发绑定的uploadFileEvt函数执行
Cypress测试Angular文件上传触发绑定方法的实现方案
你页面中的文件输入标签代码如下:
<input type="file" #fileInput formControlName="browseDocument" id="uploadFile" (change)="uploadFileEvt($event)" name="uploadFile" accept=".pdf,.xml" />
要保证测试时绑定的uploadFileEvt方法正常触发,优先使用Cypress官方提供的原生API,不要用非官方偏方,避免出现事件触发但拿不到文件对象的问题。
推荐实现(Cypress 9.3及以上版本)
Cypress 9.3版本后内置了.selectFile()方法,会完全模拟真实用户选择文件的完整操作流程,自动触发原生change事件,Angular的事件绑定机制可以正常捕获该事件,绑定的uploadFileEvt会按预期执行。
- 提前将测试用的pdf、xml文件放到
cypress/fixtures目录下,例如准备测试文件sample.pdf - 测试代码示例:
// force:true 适配Angular项目中常见的隐藏原生file input、用自定义按钮触发选择的场景 cy.get('#uploadFile') .selectFile('cypress/fixtures/sample.pdf', { force: true }) // 操作完成后直接添加业务断言即可,比如校验上传成功提示、上传接口请求逻辑 cy.contains('文件上传成功').should('be.visible')
- 如果需要明确校验
uploadFileEvt是否被调用,可以在执行上传操作前给组件方法打桩:
// 先获取Angular组件实例,给上传事件处理方法挂载spy cy.get('@componentInstance').then(component => { cy.spy(component, 'uploadFileEvt').as('uploadHandler') }) // 执行文件选择操作 cy.get('#uploadFile').selectFile('cypress/fixtures/sample.pdf', { force: true }) // 断言处理方法确实被触发 cy.get('@uploadHandler').should('have.been.called')
避坑说明
不要使用手动给input赋值后调用.trigger('change')的写法:受浏览器安全规则限制,原生file类型input的value属性无法通过JavaScript直接修改,这种写法要么无法触发事件,要么事件回调中拿到的event.target.files为空值,导致uploadFileEvt内部的文件处理逻辑异常。
低版本Cypress兼容方案(9.3以下版本)
如果使用的Cypress版本低于9.3,没有内置.selectFile()方法,可以手动构造File对象挂载到input元素上,再派发冒泡的change事件:
// 读取fixtures中的测试文件转成blob格式 cy.fixture('sample.pdf', 'binary') .then(Cypress.Blob.binaryStringToBlob) .then(blob => { // 构造符合格式的File对象 const testFile = new File([blob], 'sample.pdf', { type: 'application/pdf' }) const dataTransfer = new DataTransfer() dataTransfer.items.add(testFile) cy.get('#uploadFile').then(input => { // 将构造好的文件列表挂载到input元素上 input[0].files = dataTransfer.files // 派发支持冒泡的change事件,保证Angular Zone能正常监听到事件 input[0].dispatchEvent(new Event('change', { bubbles: true })) }) })
内容的提问来源于stack exchange,提问作者Dvora
相关产品推荐
相关产品推荐

