不能用 page.fill() 往富文本编辑器填内容,必须用 keyboard.type() 或 element.type() 模拟输入;定位需用 div[contenteditable="true"] 属性选择器;图片上传须用 set_input_files() 触发 change 事件。

直接说结论:不能用 page.fill() 往富文本编辑器里塞内容,必须用 page.keyboard 或元素级 type() + press() 模拟真实输入;否则格式丢失、光标错位、图片/表格插入失败是常态。
定位 contenteditable 区域不能靠 class 或 div 层级
富文本编辑器的可编辑区通常是 div[contenteditable="true"],但它的 class 名常由 Vue/React 动态生成(比如 ql-editor、ProseMirror、或一串哈希值),每次刷新都可能变。硬写 page.locator(".ql-editor") 极易失效。
- 优先用属性选择器:
page.locator("div[contenteditable='true']"),稳定且语义明确 - 若页面有多个
contenteditable,加父容器约束,比如:page.locator("#editor-container div[contenteditable='true']") - 避免用 XPath 定位 iframe 内的编辑器——Playwright 对 iframe 的跨上下文操作需显式
frame = page.frame_locator(...),容易漏掉wait_for_load_state导致后续操作报Frame not found
输入文字必须用 keyboard.type() 或 element.type()
page.fill() 会清空整个编辑器内容并替换,破坏已有格式(加粗、颜色、链接)、清空已插入的图片占位符、重置光标到开头——这在测试“追加段落”或“修改中间某句”时完全不可用。
- 对整个编辑器区域用:
editor = page.locator("div[contenteditable='true']"); editor.focus(); editor.type("新段落内容") - 需要精确控制光标位置时(比如选中某段后加粗),先用
keyboard.press("ArrowRight")移动,再keyboard.down("Shift")+ 多次press("ArrowRight")选中,最后press("Control+b") - 注意:
type()默认带延迟(约 12ms/字符),如需加速可传delay=0,但太快可能导致编辑器来不及响应,尤其在 Vue3 的nextTick场景下
处理工具栏按钮要绕过 DOM 不稳定性
加粗、斜体、插入链接等按钮,其 HTML 结构常嵌套 svg + button + 动态 data-testid,靠 CSS 选择器点击极不可靠。更稳的方式是触发编辑器原生命令。
- 直接执行 JS 命令(适用于 TinyMCE、Quill 等):
page.evaluate("document.execCommand('bold', false, null)") - 或调用编辑器实例方法(需先暴露全局变量):
page.evaluate("window.editor?.formatText('bold', true)") - 如果必须点按钮,用文本定位:
page.get_by_role("button", name="加粗").click(),比locator("button[title='Bold']")更抗 class 变化 - 警惕“按钮已渲染但不可点击”:Playwright 的自动等待只检查可见性,不检查编辑器是否 ready。建议加
page.wait_for_function("window.editor?.isReady === true")(按实际 API 调整)
图片/附件上传必须走 set_input_files() + 监听 change 事件
富文本编辑器插入图片,通常不是直接拖拽或粘贴(Playwright 尚未原生支持模拟粘贴图像),而是点击“上传”按钮 → 触发 → 选文件 → 编辑器监听 change 事件后处理。跳过 input 元素直接操作,上传必失败。
- 找到隐藏的 file input(常被
display: none):page.locator("input[type='file']").set_input_files("/path/to/image.png") - 不要用
click()激活它——很多编辑器会拦截 click 并阻止默认行为;set_input_files()会直接触发 change 事件 - 上传后需等编辑器完成渲染,可用:
page.wait_for_selector("img[src*='data:image']", state="attached"),而不是等某个 loading spinner 消失 - 若上传后图片显示为 base64,但测试需验证真实 URL,说明后端没走真正上传流程——这是环境配置问题,不是 Playwright 能解决的
最麻烦的其实是光标状态同步:Playwright 的键盘操作和编辑器内部的 selection/caret 管理不是 100% 对齐的,尤其在连续格式化操作后,press("Control+i") 可能作用于错误位置。这时候得穿插 page.evaluate() 主动读取 getSelection().toString() 或编辑器 API 的 getSelection() 来校验,而不是盲目相信上一步操作成功了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











