TypeScript中cypress-tinymce调用时报编辑器实例undefined错误
报错Cannot read properties of undefined (reading 'specification')的核心原因是调用cy.setTinyMceContent命令时,全局window.tinyMCE对象未完成挂载,或是id为specification的编辑器实例还没初始化完成。
@foreachbe/cypress-tinymce库的底层实现逻辑是直接读取window.tinyMCE.editors[传入的编辑器ID]获取实例后操作内容,只要执行命令时tinyMCE全局对象不存在、或是editors集合中还没有对应ID的实例,就会抛出该属性读取失败的错误。
常见触发场景包括:
- 页面加载后立刻调用命令,没有等待TinyMCE资源加载、编辑器实例初始化完成
- 新版
@tinymce/tinymce-react默认采用异步方式加载TinyMCE资源,初始化速度慢于普通DOM元素,常规的页面加载完成信号不代表编辑器处于可用状态 - 该第三方库已多年未更新,和当前主流的TinyMCE v6/v7版本存在兼容问题,无法正确捕获编辑器初始化状态
调用命令前增加显式等待,确保编辑器实例完全就绪
不要在进入页面后直接调用setTinyMceContent,依次校验DOM渲染、全局对象挂载、实例存在三个状态后再执行操作,示例代码:// 等待编辑器外层容器渲染可见 cy.get('[cy-data-id="specification"]').should('be.visible') // 等待tinyMCE全局对象挂载,且对应ID的编辑器实例已生成 cy.window() .should('have.property', 'tinyMCE') .its('editors') .should('have.property', 'specification') // 实例就绪后设置内容 cy.setTinyMceContent('specification', 'This is testing')替换老旧第三方依赖,自定义兼容TypeScript的Cypress命令
@foreachbe/cypress-tinymce长期未维护,对新版TinyMCE和React的兼容性较差,建议直接移除该依赖,在Cypress的support/commands.ts文件中自定义命令,同时解决TS类型校验问题和事件触发问题(原库设置内容后不会触发change事件,会导致Formik无法捕获更新后的字段值):// support/commands.ts 中写入自定义命令 Cypress.Commands.add('setTinyMceContent', (editorId: string, content: string) => { cy.window({ timeout: 10000 }).then((win) => { // 等待编辑器实例初始化完成,最长等待10秒 const waitForEditor = () => new Promise<void>((resolve) => { const check = () => { if (win.tinymce?.editors[editorId]) return resolve() setTimeout(check, 100) } check() }) cy.wrap(waitForEditor()).then(() => { const editor = win.tinymce.editors[editorId] editor.setContent(content) // 手动触发变更事件,确保React侧onChange逻辑能正常响应 editor.fire('input') editor.fire('change') }) }) }) // 更新TS类型声明,和自定义命令签名保持一致 declare namespace Cypress { interface Chainable<Subject = any> { setTinyMceContent(editorId: string, content: string): Chainable<void> } }校验编辑器实际生效ID
运行Cypress测试时打开交互式运行器的控制台,执行window.tinymce.editors查看当前页面已初始化的编辑器实例ID,确认实际ID和传入的specification一致——部分表单封装组件会自动给传入的ID添加前缀,会导致ID匹配失败。
内容的提问来源于stack exchange,提问作者Wai Yan Hein

