Cypress自定义截图问题:无法获取specName致路径与文件名异常
Cypress自定义失败截图文件名与路径问题解决
问题根源
你的代码存在以下核心问题导致无法获取specName:
- 变量作用域混淆:
specName定义在浏览器环境的函数内,但sendSpecNameToPlugin任务运行在Node环境,两者无法共享变量 - 事件注册错误:
takess.ts中在函数内部注册Cypress.on('after:screenshot'),但该事件在Node端的setupNodeEvents中处理更合适 - 路径计算错误:相对路径
../../screenshots无法准确定位到目标目录,应该基于Cypress配置的路径构建
修正后的代码实现
1. 重构takess.ts(Node端逻辑)
import fs from 'fs'; import path from 'path'; // 存储specName的变量,在Node环境作用域内 let specName = ''; export const setSpecName = (name: string) => { specName = name; }; export function renameAndMoveScreenshot(details: any) { // 优先使用details中的specName,没有则用存储的specName const testName = (details.specName || specName).replace(/\.|\/|\s/g, '_'); const timeStamp = new Date().toISOString().replace(/:/g, '_'); const fileName = `${testName}--${timeStamp} (failed).png`; // 构建目标目录:基于项目根目录到dist/cypress/apps/hr/screenshots/[specName] const targetDir = path.resolve(__dirname, '../../dist/cypress/apps/hr/screenshots', specName.replace('.cy.ts', '')); const newPath = path.join(targetDir, fileName); // 创建目录(递归创建父目录) if (!fs.existsSync(targetDir)) { fs.mkdirSync(targetDir, { recursive: true }); } return new Promise((resolve, reject) => { fs.rename(details.path, newPath, (err) => { if (err) { reject(err); } else { resolve({ path: newPath }); } }); }); }
2. 修正Cypress.config.ts
import { defineConfig } from 'cypress'; import { setSpecName, renameAndMoveScreenshot } from './lib/takess'; export default defineConfig({ e2e: { setupNodeEvents(on, config) { // 注册任务接收specName on('task', { sendSpecNameToPlugin: (name: string) => { setSpecName(name); return null; // 任务必须返回值 } }); // 在Node端处理after:screenshot事件 on('after:screenshot', (details) => { // 只处理失败测试的截图 if (details.testFailed) { return renameAndMoveScreenshot(details); } return details; // 非失败截图保持默认处理 }); }, }, });
3. 调整测试文件login.spec.ts
/// <reference types="cypress"/> describe('screenshot test', () => { beforeEach(()=>{ cy.visit('/'); // 在每个测试前传递specName cy.task('sendSpecNameToPlugin', Cypress.spec.name); }); it('Visits the hr test and fails intentionally', () => { // 故意让测试失败,触发自动截图 cy.get('non-existent-element').should('exist'); }); });
关键说明
- 变量作用域:将
specName存储在Node环境的作用域内,通过setSpecName函数从测试任务中传递值,确保前后端环境能正确共享 - 路径构建:使用
path.resolve和path.join构建绝对路径,避免相对路径的不确定性,确保截图存入dist/cypress/apps/hr/screenshots/login.cy.ts目录下 - 失败截图触发:Cypress默认会在测试失败时自动截取截图,通过
details.testFailed判断只处理失败的截图,无需手动调用cy.screenshot
内容的提问来源于stack exchange,提问作者Christian Rudolf Tan
相关产品推荐
相关产品推荐

