Cypress中如何将文件名存入数组并遍历实现文件上传
Cypress实现fixture目录批量文件上传的正确方案
原有实现的核心问题
cy.fixture('files/')的原生逻辑是读取指定路径的单个fixture文件,传入目录路径不会自动返回目录下的文件清单数组,反而会触发fixture路径不存在的报错,这是运行失败的核心原因- 通过
.as()设置的自定义别名,不能直接用裸变量名files在测试逻辑中引用,会出现未定义的错误 - 遍历逻辑写法不符合Cypress的异步链式调用规则:
each回调本身会把当前遍历项作为参数传入,不需要再通过索引从原数组中手动取值
具体实现步骤
1. 注册自定义任务读取本地文件列表
因为浏览器上下文没有权限读取本地文件系统,需要借助Cypress的Node层能力,在配置文件中注册自定义任务,读取cypress/fixture/files目录下的所有文件清单:
在cypress.config.js(或对应TS配置文件)的setupNodeEvents中新增任务:
const fs = require('fs'); const path = require('path'); module.exports = defineConfig({ e2e: { setupNodeEvents(on, config) { on('task', { getFixtureFileList() { // 定位fixture下的files目标目录 const targetDir = path.join(__dirname, 'cypress/fixture/files'); // 读取目录内容,过滤掉子文件夹仅保留文件 return fs.readdirSync(targetDir).filter((fileItem) => { return fs.statSync(path.join(targetDir, fileItem)).isFile(); }) } }) }, }, })
2. 在beforeEach钩子里加载文件清单
替换原来的cy.fixture读目录写法,通过自定义任务拿到文件数组后设置别名:
beforeEach(() => { cy.task('getFixtureFileList').as('uploadFiles') })
3. 逐文件遍历完成上传操作
不要直接引用裸变量拿文件清单,通过Cypress的链式调用获取别名对应的数组,逐个读取文件内容组装上传参数:
describe('批量文件上传测试', () => { it('遍历目标目录完成所有文件上传', () => { // 直接链式获取别名存的文件数组,无上下文绑定问题 cy.get('@uploadFiles').each((fileName) => { // 读取对应路径下的单个fixture文件内容 cy.fixture(`files/${fileName}`, null).then((fileContent) => { // 按照上传接口要求构造File对象 const targetFile = new File([fileContent], fileName, {type: 'application/octet-stream'}) // 调用上传API cy.request({ method: 'POST', url: '/你的上传接口地址', form: true, body: { file: targetFile } }) }) }) }) })
常见注意事项
- 重点提醒:如果处理图片、压缩包等二进制格式文件,读取fixture时要传入
null作为编码参数,避免Cypress默认用文本编码解析文件导致内容损坏 - 不要在
it回调中用箭头函数结合this.别名的写法获取值,箭头函数会丢失Cypress的测试上下文绑定,链式调用cy.get('@别名')的写法更稳定 - 自定义任务的返回值必须是可序列化的内容,不能返回文件流或Buffer,仅返回文件名称清单就足够,文件内容读取仍然在测试链路上通过
cy.fixture完成,避免任务传输大文件内容导致的性能问题
内容的提问来源于stack exchange,提问作者Pranjal Prakash Srivastava
相关产品推荐
相关产品推荐

