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

使用Cypress无法折叠Ace Editor折叠控件的问题求助

问题描述

我正在使用Cypress编写集成测试,需要在React应用中点击Ace Editor的折叠控件。该控件位于<span>标签内,初始类为"ace_fold-widget ace_start ace_open",手动点击后类会变为"ace_fold-widget ace_start ace_closed"。

无论尝试哪种方式与该元素交互,它都无法响应Cypress命令——现象是控件的箭头图标显示为折叠状态、类也发生变化,但实际并未折叠代码行,之后元素又会恢复原状。操作父元素也无变化,触发其changeFold事件同样无效。

我尝试过以下方法:

// 带force选项的点击
cy.get('Ace widget element').click({force: true})

// 断言类并触发change事件
cy.get('Ace widget element').invoke('have.class', 'ace_fold-widget ace_start ace_closed').trigger('change')

// 触发mousedown事件
cy.get('Ace widget element').trigger('mousedown')

// 直接触发click事件
cy.get('Ace widget element').trigger('click')

// 尝试触发changeFold事件
cy.get('Ace widget element').trigger('changeFold')

也尝试过原生JS操作:

cy.get('Ace widget element').then(function($input) {
    $input[0].setAttribute('test', 'my new value')
  })
  .should('have.attr', 'test', 'my new value')

注:'Ace widget element'是示例,实际使用的是正确定位器。DOM结构如下:
Ace折叠控件的DOM结构


解决方案

Ace Editor的折叠交互依赖内部状态管理,直接模拟DOM点击常无法触发编辑器核心逻辑,建议通过调用Ace原生API实现折叠:

方法1:直接调用Ace实例的折叠API

Ace Editor实例通常挂载在编辑器容器的env.editor属性上,可直接调用折叠方法:

// 定位Ace编辑器容器,替换为你的实际选择器
cy.get('.ace_editor')
  .then($editor => {
    const aceInstance = $editor[0].env.editor;
    const session = aceInstance.getSession();
    
    // 指定要折叠的起始行号(可根据业务场景动态获取)
    const targetRow = 0; 
    session.fold(targetRow); // 执行折叠
    
    // 验证折叠是否生效
    expect(session.isFolded(targetRow)).to.be.true;
  });

方法2:通过折叠控件反向定位行号并折叠

如果需要针对特定折叠控件操作,可通过DOM元素位置反向获取对应行号:

// 定位目标折叠控件,替换为你的实际选择器
cy.get('.ace_fold-widget.ace_start.ace_open')
  .then($widget => {
    const editorContainer = $widget.closest('.ace_editor')[0];
    const aceInstance = editorContainer.env.editor;
    
    // 获取控件对应的行号
    const row = aceInstance.renderer.$cursorLayer.getPixelPosition($widget[0]).row;
    aceInstance.getSession().fold(row);
  });

方法3:模拟完整鼠标事件链

若API调用方式受限,可尝试模拟完整的鼠标交互序列(Ace可能依赖完整事件触发):

cy.get('.ace_fold-widget.ace_start.ace_open')
  .trigger('mouseover')
  .trigger('mousedown', {button: 0})
  .trigger('mouseup', {button: 0})
  .trigger('click', {force: true});

额外注意事项

  • 确保操作前编辑器已完全加载稳定,可添加等待:
    cy.get('.ace_editor').should('be.visible');
    cy.wait(500); // 可选:等待编辑器初始化完成
    
  • React重渲染可能重置Ace状态,操作时需确保组件处于稳定状态。

内容的提问来源于stack exchange,提问作者Nikola Kojčić

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 22:25:21