- 前端
- UI组件
【免费下载链接】ckeditor4
The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.
本文以 CKEditor 4 仓库中的手工测试文档 ieradiofix.md 为主线,讲解 Forms 插件在 IE9–11 下"创建/修改 radio 按钮时 selected 状态丢失"缺陷(ticket #834)的完整验证流程,并深入 radio 对话框 的源码,剖析该修复的实现策略与自动化测试的对应关系。读完后可掌握:如何用 bender 手工测试框架编写回归用例、如何从源码层面理解编辑器对表单控件checked属性的跨浏览器处理差异。
一、测试文档定位:一份 bender 手工回归测试
tests/plugins/forms/manual/ieradiofix.md 是 CKEditor 4 测试体系中典型的bender 手工测试(manual test)文档,其头部元数据声明了该用例的回归背景:
@bender-tags: bug, 4.8.0, forms, 834 @bender-ui: collapsed @bender-ckeditor-plugins: forms, wysiwygarea, toolbar, sourcearea各标签的含义:
| 标签 | 含义 |
|---|---|
bug, 834 | 该用例针对缺陷 ticket #834("IE9-11 下编辑器不保存 Forms 插件插入的 radio 按钮选中状态") |
4.8.0 | 该缺陷在 CKEditor 4.8.0 中修复,用例用于 4.8.0 起各版本回归 |
forms | 属于 Forms 插件测试组 |
forms, wysiwygarea, toolbar, sourcearea | 测试页需加载这 4 个插件——wysiwygarea提供编辑区,toolbar提供 "Radio" 工具栏按钮,sourcearea提供"检查源码"能力 |
每个.md手工测试都配有一个同名.html宿主页面。ieradiofix.html 的内容非常简洁:
<body> <div id="editor"> <p>Example text</p> </div> <script> if ( !CKEDITOR.env.ie ) { bender.ignore(); } CKEDITOR.replace( 'editor' ); </script> </body>注意其中的关键逻辑:在非 IE 浏览器中直接bender.ignore(),即该手工用例只在 IE 环境下执行——这正是"IE radio fix"的用意:其他浏览器走不同的代码分支(见下文源码分析),已有独立用例覆盖(如 checkboxradiochangestate.md 验证了 trac#12465 中 Webkit/Blink 分支的同类问题)。
测试框架侧,bender.js 将tests/plugins/**归入Plugins测试组,使用yui断言框架;根目录的 bender-runner.config.json 则面向 CI(默认在 Linux 上使用 Chrome/Firefox 跑自动化测试),而本用例属于手工测试,需人工在 IE 中逐步执行后判定通过与否。
二、手工验证步骤:从创建到修改的完整闭环
原文档定义了 7 步操作,覆盖了 radio 控件"新建"和"编辑"两条路径,务必完整执行:
- Click in the editor.(点击编辑器)
- Click "Radio" button.(点击工具栏 "Radio" 按钮)
- Check "Selected" field in the dialog and press "Ok" to create a radio button.(在对话框中勾选 "Selected",按 "Ok" 创建带选中状态的 radio 按钮)
- Check source in editor.(切换到源码模式检查内容)
- Double click the radio.(双击该 radio 控件重新打开对话框)
- Check "Selected" field in the dialog and press "Ok" to modify radio.(再次勾选 "Selected" 并 "Ok" 修改 radio)
- Check source in editor.(再次检查源码)
判定标准:
Expected(预期):
- The state of radio button is changed according to settings.(radio 的选中状态随对话框设置变化)
- In source mode appears
checkedattribute when radio button is marked as selected.(标记为选中时,源码模式中应出现checked属性)
Unexpected(缺陷表现,即 #834 的原始症状):
- The state of radio button is not saved.
checkedattribute isnot presentin source mode.(状态未保存,源码中缺失checked属性)
也就是说,该用例的验收口径是:对话框中勾选 "Selected" 后,生成的 HTML 必须持久化出checked属性,且这一行为在 IE 下与标准浏览器一致。
三、修复背景:ticket #834 与 CKEditor 4.8.0
仓库变更日志 CHANGES.md 中,4.8 版本的 Fixed Issues 一节明确记录了这一修复:
#834: [IE9-11] Fixed: The editor does not save the selected state of radio buttons inserted by the Form Elements plugin.
即缺陷影响范围为 IE9 至 IE11。这解释了为什么手工用例ieradiofix的宿主页面要主动跳过非 IE 环境,以及为什么标签中同时标注了4.8.0与834。
四、源码剖析:radio 对话框 commit 中的 IE 特判
用例的验证对象是 plugins/forms/dialogs/radio.js 中checked字段的commit逻辑(L90-L123)。该字段定义了三种浏览器分支:
commit: function( data ) { var element = data.element; if ( !CKEDITOR.env.ie ) { var value = this.getValue(); // Blink/Webkit needs to change checked property, not attribute. (trac#12465) if ( CKEDITOR.env.webkit ) { element.$.checked = value; } if ( value ) element.setAttribute( 'checked', 'checked' ); else element.removeAttribute( 'checked' ); } else { var isElementChecked = element.getAttribute( 'checked' ); var isChecked = !!this.getValue(); if ( isElementChecked != isChecked ) { var replace = CKEDITOR.dom.element.createFromHtml( '<input type="radio"' + ( isChecked ? ' checked="checked"' : '' ) + '></input>', editor.document ); element.copyAttributes( replace, { type: 1, checked: 1 } ); replace.replace( element ); // Ugly hack which fix IE issues with radiobuttons (#834). if ( isChecked ) { replace.setAttribute( 'checked', 'checked' ); } editor.getSelection().selectElement( replace ); data.element = replace; } } }三个分支各有针对性:
- 非 IE 标准分支:直接
setAttribute('checked','checked')/removeAttribute('checked')读写属性即可。 - Webkit/Blink 分支:源码注释指向 trac#12465——这类内核下仅改属性不足以反映真实选中态,还需同步原生
element.$.checked属性。对应的独立手工用例是 checkboxradiochangestate.md。 - IE 分支(#834 修复本体):IE 下对已插入 DOM 的 radio 直接改
checked属性并不可靠,策略是"换元素"——用createFromHtml新建一个目标状态的<input type="radio">,通过copyAttributes( replace, { type: 1, checked: 1 } )保留type与checked后replace( element )替换原节点。而if ( isChecked ) replace.setAttribute( 'checked', 'checked' )这一行被注释明确称为 "Ugly hack which fix IE issues with radiobuttons (#834)":IE 在替换 DOM 时会丢弃新节点的checked属性,必须在替换完成后再显式补写一次,才能保证源码输出中checked属性存在——这正是手工用例第 4、7 步"检查源码"要验证的最终结果。
checkbox对话框(plugins/forms/dialogs/checkbox.js)采用完全相同的"重建 + 替换"策略处理 IE 分支,说明这是针对 IE 表单控件属性写入缺陷的插件级统一应对模式。
五、插件侧配套:内容过滤、双击打开与 IE 数据清理
手工用例的每一步操作都对应 plugins/forms/plugin.js 中的注册逻辑:
工具栏 "Radio" 按钮与命令(L86):
addButtonCommand( 'Radio', 'radio', dialogPath + 'radio.js' )注册命令与对话框,用例第 2 步即由此触发。命令的 ACF(Advanced Content Filter)规则为(L41-L51):allowedContent = { radio: 'input[type,name,checked,required]', ... };checked被显式列入 radio 的允许属性——这是用例"源码中出现checked"能通过过滤的前提;若 ACF 未放行,即便 DOM 上写入了属性,getHtml输出仍会被剥离。双击打开对话框(L211-L243):编辑器
doubleclick监听中,element.is('input')且type == 'radio'时设置evt.data.dialog = 'radio',即用例第 5 步"双击 radio"的实际入口。IE 数据清理(L251-L268):
afterInit中针对 IE 注册了htmlFilter规则,当checkbox/radio的value为 IE 默认注入的'on'时删除该属性(attrs.value == 'on' && delete attrs.value),并保证缺失type的输入框补为text。这保证了 IE 下源码输出不会混入编辑器外的脏属性,与 #834 修复共同构成"IE 表单属性可预测"的完整链路。
六、自动化测试的交叉印证
手工用例之外,仓库还有一套覆盖 radio 对话框的自动化测试 tests/plugins/forms/radio.js,其"fill fields"用例断言了对话框提交后的精确源码输出:
bot.dialog( 'radio', function( dialog ) { dialog.setValueOf( 'info', 'name', 'name' ); dialog.setValueOf( 'info', 'value', 'value' ); dialog.setValueOf( 'info', 'checked', 'checked' ); dialog.setValueOf( 'info', 'required', 'required' ); dialog.getButton( 'ok' ).click(); assert.areSame( '<input checked="checked" name="name" required="required" type="radio" value="value" />', bot.getData( false, true ) ); } );该断言与手工用例的 Expected 一致:勾选 "Selected" 后源码必须包含checked="checked"。其余用例还包括:
test dialog model during radio creation/test dialog model with existing radio:验证 radio.js 中getModel在新建场景返回null(CREATION 模式)、选中已有 radio 时返回对应元素(EDITING 模式);test empty fields:验证清空字段后属性被移除,其中专门注明了"IE is problematic: you cannot removevaluefrom the input"这一 IE 遗留限制;- 通过 tests/plugins/forms/_helpers/tools.js 的
assertRequiredAttribute验证required布尔属性按 HTML 规范解析(存在即勾选,无论值为何)。
需要说明的适用前提:自动化测试在 CI 中面向 Chrome/Firefox 等现代浏览器(见 bender-runner.config.json 的browsers配置),而 IE 分支的回归保障正依赖ieradiofix这类在 IE 中手工执行的手工用例——两者互补,共同锁定 #834 不复发。
七、小结
- ieradiofix.md 是一份针对 IE9–11 的回归手工用例:创建与修改 radio 两条路径均需验证源码中
checked属性的持久化。 - 修复本体位于 radio.js 的 IE 分支:以"重建元素并替换"规避 IE 属性写入缺陷,并在替换后显式补写
checked属性(源码中自注为 #834 的 "Ugly hack")。 - 验证链条完整闭环:ACF 放行
checked属性 →commit写入 DOM →sourcearea源码可查 → 自动化断言(radio.js)与现代浏览器分支(trac#12465)分别兜底。
- 前端
- UI组件
【免费下载链接】ckeditor4
The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.
相关推荐
CKEditor 4 forms 插件回归测试详解:双击对话框无法切换复选框/单选按钮选中状态(12465)
CKEditor 4 forms 插件回归测试详解:双击对话框无法切换复选框/单选按钮选中状态( 12465) 本文围绕 CKEditor 4 中一份人工回归测
前端UI组件CKEditor 4 Autocomplete 手动测试指南:修复按住鼠标按钮时下拉项无法插入的问题(Bug 2107)
CKEditor 4 Autocomplete 手动测试指南:修复按住鼠标按钮时下拉项无法插入的问题(Bug 2107) 导读 本文以 CKEditor 4 仓
前端UI组件CKEditor 4 工具栏开关按钮与 aria-pressed 无障碍状态:从手动测试到源码实现
CKEditor 4 工具栏开关按钮与 aria pressed 无障碍状态:从手动测试到源码实现 本文围绕 CKEditor 4 中开关型(toggle)工具
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考