Cypress 用户交互 #
点击操作 #
基本点击 #
javascript
// 单击
cy.get('.button').click();
// 双击
cy.get('.item').dblclick();
// 右键点击
cy.get('.context-menu').rightclick();
点击位置 #
javascript
// 点击元素中心(默认)
cy.get('.button').click();
// 点击特定位置
cy.get('.canvas').click('topLeft');
cy.get('.canvas').click('top');
cy.get('.canvas').click('topRight');
cy.get('.canvas').click('left');
cy.get('.canvas').click('center');
cy.get('.canvas').click('right');
cy.get('.canvas').click('bottomLeft');
cy.get('.canvas').click('bottom');
cy.get('.canvas').click('bottomRight');
// 点击坐标位置
cy.get('.canvas').click(100, 200); // x: 100, y: 200
// 相对位置
cy.get('.canvas').click(10, 20, { position: 'topLeft' });
点击选项 #
javascript
cy.get('.button').click({
force: true, // 强制点击,忽略可见性检查
multiple: true, // 点击多个匹配元素
timeout: 5000, // 超时时间
scrollBehavior: 'top', // 滚动行为
shiftKey: true, // 按住 Shift
ctrlKey: true, // 按住 Ctrl
altKey: true, // 按住 Alt
metaKey: true // 按住 Meta (Cmd)
});
强制点击 #
javascript
// 元素被遮挡时强制点击
cy.get('.hidden-button').click({ force: true });
// 元素不可见时强制点击
cy.get('.invisible-element').click({ force: true });
输入操作 #
文本输入 #
javascript
// 输入文本
cy.get('input').type('Hello World');
// 追加输入
cy.get('input').type('Hello').type(' World');
// 清空后输入
cy.get('input').clear().type('New text');
特殊按键 #
javascript
// 回车键
cy.get('input').type('{enter}');
// 删除键
cy.get('input').type('{backspace}');
cy.get('input').type('{del}');
// 方向键
cy.get('input').type('{leftArrow}');
cy.get('input').type('{rightArrow}');
cy.get('input').type('{upArrow}');
cy.get('input').type('{downArrow}');
// 功能键
cy.get('input').type('{esc}');
cy.get('input').type('{tab}');
cy.get('input').type('{home}');
cy.get('input').type('{end}');
cy.get('input').type('{pageUp}');
cy.get('input').type('{pageDown}');
// 组合键
cy.get('input').type('{ctrl}a'); // Ctrl+A
cy.get('input').type('{cmd}c'); // Cmd+C
cy.get('input').type('{shift}{leftArrow}'); // Shift+Left
输入选项 #
javascript
cy.get('input').type('Hello', {
delay: 100, // 每个字符延迟 100ms
force: true, // 强制输入
release: false, // 不释放按键
timeout: 10000, // 超时时间
scrollBehavior: 'top' // 滚动行为
});
模拟打字速度 #
javascript
// 快速输入
cy.get('input').type('Hello World', { delay: 0 });
// 慢速输入(模拟真实打字)
cy.get('input').type('Hello World', { delay: 100 });
清除操作 #
javascript
// 清除输入框
cy.get('input').clear();
// 清除后输入
cy.get('input').clear().type('New value');
// 清除选项
cy.get('input').clear({
force: true,
timeout: 5000
});
选择操作 #
下拉选择 #
javascript
// 选择文本值
cy.get('select').select('选项1');
// 选择 value 值
cy.get('select').select('option1');
// 选择多个值(多选下拉)
cy.get('select').select(['option1', 'option2']);
复选框和单选框 #
javascript
// 勾选复选框
cy.get('input[type="checkbox"]').check();
// 取消勾选
cy.get('input[type="checkbox"]').uncheck();
// 勾选特定值
cy.get('input[type="checkbox"]').check('option1');
cy.get('input[type="checkbox"]').check(['option1', 'option2']);
// 单选框选择
cy.get('input[type="radio"]').check('radio1');
选择选项 #
javascript
cy.get('input[type="checkbox"]').check({
force: true, // 强制操作
timeout: 5000, // 超时时间
scrollBehavior: 'center'
});
聚焦操作 #
聚焦和失焦 #
javascript
// 聚焦元素
cy.get('input').focus();
// 失焦元素
cy.get('input').blur();
// 验证聚焦状态
cy.get('input').should('be.focused');
触发焦点事件 #
javascript
cy.get('input')
.focus()
.should('have.class', 'focused')
.blur()
.should('not.have.class', 'focused');
滚动操作 #
滚动到元素 #
javascript
// 滚动到元素
cy.get('.section').scrollIntoView();
// 滚动选项
cy.get('.section').scrollIntoView({
duration: 1000, // 动画时长
easing: 'swing', // 缓动效果
offset: { top: -50 } // 偏移量
});
滚动到位置 #
javascript
// 滚动到顶部
cy.scrollTo('top');
// 滚动到底部
cy.scrollTo('bottom');
// 滚动到指定位置
cy.scrollTo(0, 500); // x: 0, y: 500
// 滚动百分比
cy.scrollTo('50%', '50%');
滚动容器 #
javascript
// 滚动特定容器
cy.get('.scroll-container').scrollTo('bottom');
// 滚动选项
cy.get('.scroll-container').scrollTo('bottom', {
duration: 500,
easing: 'linear',
ensureScrollable: false
});
拖拽操作 #
拖拽元素 #
javascript
// 拖拽到目标元素
cy.get('.draggable').drag('.dropzone');
// 使用 trigger 模拟拖拽
cy.get('.draggable')
.trigger('mousedown', { which: 1 })
.trigger('mousemove', { clientX: 500, clientY: 500 })
.trigger('mouseup', { force: true });
滑块操作 #
javascript
// 移动滑块
cy.get('.slider')
.invoke('val', 75)
.trigger('change');
// 使用 trigger 模拟拖拽
cy.get('.slider')
.trigger('mousedown', { which: 1, pageX: 0, pageY: 0 })
.trigger('mousemove', { which: 1, pageX: 200, pageY: 0 })
.trigger('mouseup');
悬停操作 #
鼠标悬停 #
javascript
// 触发 hover 事件
cy.get('.menu-item').trigger('mouseover');
// 触发鼠标移入
cy.get('.tooltip').trigger('mouseenter');
// 触发鼠标移出
cy.get('.tooltip').trigger('mouseleave');
实际悬停效果 #
javascript
// 使用 realHover 插件(需要安装 cypress-real-events)
cy.get('.menu-item').realHover();
// 或者使用 trigger 链
cy.get('.dropdown')
.trigger('mouseover')
.find('.dropdown-menu')
.should('be.visible');
触发事件 #
trigger 方法 #
javascript
// 触发自定义事件
cy.get('.element').trigger('custom-event');
// 触发带数据的事件
cy.get('.element').trigger('change', { value: 'new value' });
// 触发鼠标事件
cy.get('.element').trigger('mousedown');
cy.get('.element').trigger('mouseup');
cy.get('.element').trigger('mousemove', { clientX: 100, clientY: 200 });
事件选项 #
javascript
cy.get('.element').trigger('click', {
bubbles: true, // 事件冒泡
cancelable: true, // 可取消
composed: true, // 可组合
force: true, // 强制触发
timeout: 5000 // 超时时间
});
文件操作 #
文件上传 #
javascript
// 安装插件:npm install --save-dev cypress-file-upload
// 上传单个文件
cy.get('input[type="file"]').attachFile('test.pdf');
// 上传多个文件
cy.get('input[type="file"]').attachFile(['file1.pdf', 'file2.pdf']);
// 自定义文件内容
cy.get('input[type="file"]').attachFile({
fileContent: 'file content here',
fileName: 'test.txt',
mimeType: 'text/plain'
});
文件下载 #
javascript
// 验证下载链接
cy.get('.download-link')
.should('have.attr', 'href')
.and('include', '.pdf');
// 下载文件并验证
cy.request('/download/test.pdf').then((response) => {
expect(response.status).to.eq(200);
expect(response.headers['content-type']).to.eq('application/pdf');
});
表单提交 #
javascript
// 提交表单
cy.get('form').submit();
// 点击提交按钮
cy.get('button[type="submit"]').click();
// 回车提交
cy.get('input').type('{enter}');
键盘快捷键 #
javascript
// Ctrl+C 复制
cy.get('input').type('{ctrl}c');
// Ctrl+V 粘贴
cy.get('input').type('{ctrl}v');
// Ctrl+A 全选
cy.get('input').type('{ctrl}a');
// Ctrl+Z 撤销
cy.get('input').type('{ctrl}z');
// Cmd 组合键(macOS)
cy.get('input').type('{cmd}a');
高级交互 #
模拟用户登录流程 #
javascript
describe('登录流程', () => {
it('用户登录', () => {
cy.visit('/login');
// 输入用户名
cy.get('#username')
.clear()
.type('testuser')
.should('have.value', 'testuser');
// 输入密码
cy.get('#password')
.type('Password123!')
.should('have.value', 'Password123!');
// 勾选记住我
cy.get('#remember-me').check();
// 点击登录
cy.get('button[type="submit"]').click();
// 验证登录成功
cy.url().should('include', '/dashboard');
});
});
模拟表单填写 #
javascript
describe('表单填写', () => {
it('填写联系表单', () => {
cy.visit('/contact');
// 填写基本信息
cy.get('#name').type('张三');
cy.get('#email').type('zhangsan@example.com');
cy.get('#phone').type('13800138000');
// 选择主题
cy.get('#subject').select('咨询');
// 填写消息
cy.get('#message').type('这是一条测试消息...');
// 上传附件
cy.get('#attachment').attachFile('test.pdf');
// 勾选协议
cy.get('#agreement').check();
// 提交表单
cy.get('form').submit();
// 验证成功
cy.get('.success-message').should('be.visible');
});
});
模拟购物流程 #
javascript
describe('购物流程', () => {
it('添加商品到购物车', () => {
cy.visit('/products');
// 搜索商品
cy.get('.search-input').type('手机{enter}');
// 选择商品
cy.get('.product-item').first().click();
// 选择规格
cy.get('.color-option').contains('黑色').click();
cy.get('.size-option').contains('128GB').click();
// 设置数量
cy.get('.quantity-input').clear().type('2');
// 加入购物车
cy.get('.add-to-cart').click();
// 验证购物车
cy.get('.cart-count').should('contain', '2');
});
});
交互最佳实践 #
1. 等待元素可交互 #
javascript
// ✅ 好的做法 - 等待元素可见后再操作
cy.get('.button').should('be.visible').click();
// ❌ 不好的做法 - 直接操作可能失败的元素
cy.get('.button').click();
2. 使用语义化操作 #
javascript
// ✅ 好的做法 - 使用语义化命令
cy.get('input').clear().type('Hello');
cy.get('select').select('option1');
cy.get('input[type="checkbox"]').check();
// ❌ 不好的做法 - 使用底层事件
cy.get('input').trigger('input', { value: 'Hello' });
3. 合理使用 force #
javascript
// ✅ 必要时使用 force
cy.get('.hidden-button').click({ force: true });
// ❌ 滥用 force 可能隐藏真实问题
cy.get('.button').click({ force: true }); // 按钮可能真的不可点击
4. 验证操作结果 #
javascript
// ✅ 好的做法 - 验证操作后的状态
cy.get('.button').click();
cy.get('.result').should('be.visible');
// ❌ 不好的做法 - 只操作不验证
cy.get('.button').click();
完整示例 #
javascript
describe('用户交互示例', () => {
beforeEach(() => {
cy.visit('/demo');
});
it('完整的用户交互流程', () => {
// 点击导航
cy.get('.nav-toggle').click();
cy.get('.nav-menu').should('be.visible');
// 导航到表单页面
cy.get('.nav-menu').contains('表单').click();
cy.url().should('include', '/form');
// 填写表单
cy.get('#username')
.focus()
.type('testuser')
.should('have.value', 'testuser');
cy.get('#email')
.type('test@example.com')
.blur();
// 选择选项
cy.get('#country').select('China');
cy.get('input[value="male"]').check();
cy.get('input[type="checkbox"]').check(['reading', 'coding']);
// 文件上传
cy.get('#avatar').attachFile('avatar.png');
// 滚动到底部
cy.scrollTo('bottom');
// 提交表单
cy.get('button[type="submit"]')
.should('not.be.disabled')
.click();
// 验证结果
cy.get('.success-modal')
.should('be.visible')
.within(() => {
cy.get('.close-button').click();
});
});
it('拖拽排序', () => {
cy.get('.sortable-item').first().as('firstItem');
cy.get('.sortable-item').last().as('lastItem');
// 模拟拖拽
cy.get('@firstItem')
.trigger('mousedown', { which: 1 })
.trigger('mousemove', { clientY: 300 })
.trigger('mouseup', { force: true });
// 验证顺序变化
cy.get('.sortable-item').first().should('not.contain', 'Item 1');
});
it('键盘导航', () => {
cy.get('body').tab(); // 需要插件支持
cy.get('input').first().should('be.focused');
cy.focused().type('{tab}');
cy.get('input').eq(1).should('be.focused');
});
});
下一步 #
现在你已经掌握了 Cypress 用户交互的使用方法,接下来学习 异步处理 了解如何处理异步操作!
最后更新:2026-03-28