Cypress中cy.type()失败因目标为禁用元素的解决方法
Cypress 验证码输入流程报错修复
问题场景
在commands.js中通过自定义loginByGoogleApi命令调用Google API登录Gmail账号,获取验证邮件正文后提取验证码存入常量code,计划在testFile.cy.js测试用例中填入提取到的验证码完成登录。目前登录流程可正常触发,但Cypress运行时抛出错误:
cy.type() failed because it targeted a disabled element.
原始代码
commands.js
/// <reference types="cypress" import { parseString } from "xml2js"; Cypress.Commands.add('loginByGoogleApi', () => { cy.request({ method: 'POST', url: 'https://www.googleapis.com/oauth2/v4/token', body: { grant_type: 'refresh_token', client_id: Cypress.env('googleClientId'), client_secret: Cypress.env('googleClientSecret'), refresh_token: Cypress.env('googleRefreshToken'), }, }).then(({ body }) => { const { access_token, id_token } = body cy.log('Opening emails including code to verify') cy.request({ method: 'GET', url: 'https://mail.google.com/mail/feed/atom/verifyCode', headers: { Authorization: Bearer ${access_token} }, }).then(({ body }) => { parseString(body, function (err, results) { let data = JSON.stringify(results) let codeTitle = JSON.parse(data).feed.entry[0].title[0]; let code = codeTitle.replace('Chaine confirmation code: ',''); cy.log(code) }); }); }) })
testFile.cy.js
const { Code } = require("@chaine/keychaine"); describe('Open login page', () => { it('Enter your email to login', () => { cy.visit('https://chaineapp.com/staging/login%27) cy.get('#field-1').click().type('paras@loadtap.com'); cy.get('[class*="chakra-button css-yg51i0"]').click(); cy.get('#pin-input-2-0').type(<need to put code here>); }) it('get code', () => { cy.loginByGoogleApi() }) })
报错详情
cy.type() failed because it targeted a disabled element.
本次type操作的目标元素为:
<input aria-label="Please enter your pin code" inputmode="numeric" type="tel" id="pin-input-2-5" autocomplete="one-time-code" placeholder="" class="chakra-pin-input css-jyb0wy" value="1" data-index="5" disabled="">
请在执行type操作前确认目标元素不存在disabled属性。
根因分析
- 执行顺序错误:把输入验证码、拉取验证码拆成了两个独立的
it用例,默认先执行输验证码的逻辑,此时不仅没拿到验证码,PIN输入框还没完成加载解锁。 - PIN输入框交互逻辑问题:报错指向的
#pin-input-2-5是第6位验证码的输入框,Chakra的PIN输入组件初始状态下除第一位外,其余输入框默认带disabled属性,只有前一位输入完成才会解锁下一位,直接操作未解锁的输入框就会触发disabled报错。 - 自定义命令存在缺陷:
- 提取到的
code是parseString回调内的局部变量,没有对外返回,测试用例无法获取到验证码值 parseString是回调风格的异步方法,没有做Promise包装,Cypress不会等待XML解析完成就继续执行后续逻辑- 存在语法错误:请求头
Authorization的Bearer token拼接没用模板字符串反引号,cy.visit的URL末尾多了冗余单引号
- 提取到的
- 缺少状态等待:点击登录按钮后没有等待第一个PIN输入框解锁就直接执行输入操作,容易命中元素未就绪的状态。
修复方案
- 改造自定义
loginByGoogleApi命令,包装异步解析逻辑,将提取到的验证码作为返回值返回,修复原有语法错误 - 合并测试流程,不要把拉取验证码、填写验证码拆成独立
it块,保证验证码时效性,避免流程断裂 - 增加元素状态断言,每次输入验证码前确认当前位的输入框已移除
disabled属性,逐位输入验证码自动解锁下一位输入框
修正后代码
commands.js
/// <reference types="cypress" /> import { parseString } from "xml2js"; Cypress.Commands.add('loginByGoogleApi', () => { return cy.request({ method: 'POST', url: 'https://www.googleapis.com/oauth2/v4/token', body: { grant_type: 'refresh_token', client_id: Cypress.env('googleClientId'), client_secret: Cypress.env('googleClientSecret'), refresh_token: Cypress.env('googleRefreshToken'), }, }).then(({ body }) => { const { access_token } = body cy.log('拉取验证邮件中') return cy.request({ method: 'GET', url: 'https://mail.google.com/mail/feed/atom/verifyCode', headers: { Authorization: `Bearer ${access_token}` }, }).then(({ body }) => { return new Promise((resolve, reject) => { parseString(body, (err, results) => { if (err) return reject(err) const codeTitle = results.feed.entry[0].title[0]; const verifyCode = codeTitle.replace('Chaine confirmation code: ',''); cy.log(`提取到验证码:${verifyCode}`) resolve(verifyCode) }); }) }); }) })
testFile.cy.js
const { Code } = require("@chaine/keychaine"); describe('登录流程测试', () => { it('输入邮箱-拉取验证码-完成登录', () => { cy.visit('https://chaineapp.com/staging/login') cy.get('#field-1').click().type('paras@loadtap.com'); cy.get('[class*="chakra-button css-yg51i0"]').click(); // 等待第一位验证码输入框解锁 cy.get('#pin-input-2-0').should('not.be.disabled') // 调用自定义命令获取验证码 cy.loginByGoogleApi().then(verifyCode => { // 逐位输入验证码,每输入一位前确认当前输入框已解锁 verifyCode.split('').forEach((num, index) => { cy.get(`#pin-input-2-${index}`) .should('not.be.disabled') .type(num) }) // 后续登录成功断言、业务操作写在这里 }) }) })
内容的提问来源于stack exchange,提问作者Paras Verma
相关产品推荐
相关产品推荐

