Cypress集成speakeasy报错:'list'参数必须为Buffer数组
问题:Cypress中使用speakeasy生成TOTP验证码报错
"list" argument must be an Array of Buffers 问题背景
在Cypress自动化测试中使用speakeasy库生成TOTP验证码,单独运行验证码生成脚本可正常生成验证码并完成登录,但将其导入到Cypress测试代码时,出现"list" argument must be an Array of Buffers错误。
验证码生成脚本(authcodegen.js)
const token = speakeasy.totp({ secret: '(my secret key)', encoding: 'base32' }); getAuthCode = () => { return token; } module.exports = { getAuthCode };
Cypress测试代码
const { getAuthCode } = require('../support/authcodegen') describe('Test', () => { const emailInput = '[id = "email"]' const passInput = '[id = "password"]' const loginBtn = '[type = "submit"]' it('Login Test', () => { cy.on('uncaught:exception', (err, runnable) => {return false}) cy.visit('My Website'); cy.get(emailInput).type('My email'); cy.get(passInput).type('My Password'); cy.get(loginBtn).click(); const authCode = getAuthCode(); cy.log(authCode); }) })
错误堆栈信息
at Function.concat (webpack://automation/../../Library/Caches/Cypress/13.13.0/Cypress.app/Contents/Resources/app/node_modules/buffer/index.js:423) at new Hmac (webpack://automation/../../Library/Caches/Cypress/13.13.0/Cypress.app/Contents/Resources/app/node_modules/create-hmac/browser.js:27) at Object.createHmac (webpack://automation/../../Library/Caches/Cypress/13.13.0/Cypress.app/Contents/Resources/app/node_modules/create-hmac/browser.js:61) at Object.digest (webpack://automation/./node_modules/speakeasy/index.js:56) at Object.hotpGenerate (webpack://automation/./node_modules/speakeasy/index.js:95) at Object.totpGenerate (webpack://automation/./node_modules/speakeasy/index.js:293) at ./cypress/support/authcodegen.js (webpack://automation/./cypress/support/authcodegen.js:3:24) at __webpack_require__ (webpack://automation/webpack/bootstrap:19) at eval (webpack://automation/./cypress/e2e/cocoshome.cy.js:1:24) at eval (http://localhost:49752/__cypress/tests?p=cypress/e2e/cocoshome.cy.js:39694:3) From previous event: at Promise.longStackTracesCaptureStackTrace [as _captureStackTrace] (http://localhost:49752/__cypress/runner/cypress_runner.js:3486:19) at Promise._then (http://localhost:49752/__cypress/runner/cypress_runner.js:1239:17) at Promise.then (http://localhost:49752/__cypress/runner/cypress_runner.js:11132:17) at runScriptsFromUrls (http://localhost:49752/__cypress/runner/cypress_runner.js:111340:136) at Object.runScripts (http://localhost:49752/__cypress/runner/cypress_runner.js:111381:12) at $Cypress.onSpecWindow (http://localhost:49752/__cypress/runner/cypress_runner.js:40896:67)
解决方案
1. 问题根源
Cypress测试代码运行在浏览器环境,而speakeasy库更适配Node.js环境。报错是因为webpack打包时对Node.js核心模块的模拟存在兼容性问题,导致buffer模块的concat方法接收参数不符合预期。
2. 修复方案
方法一:将验证码生成逻辑移到Cypress Node.js环境(推荐)
利用cy.task()在Node.js端运行验证码生成逻辑,规避浏览器环境的兼容性问题:
- 在
cypress.config.js中注册task:
const { defineConfig } = require("cypress"); const speakeasy = require('speakeasy'); module.exports = defineConfig({ e2e: { setupNodeEvents(on, config) { on('task', { generateAuthCode() { return speakeasy.totp({ secret: '(my secret key)', encoding: 'base32' }); } }); }, }, });
- 修改Cypress测试代码,通过
cy.task()获取实时生成的验证码:
describe('Test', () => { const emailInput = '[id = "email"]' const passInput = '[id = "password"]' const loginBtn = '[type = "submit"]' it('Login Test', () => { cy.on('uncaught:exception', (err, runnable) => {return false}) cy.visit('My Website'); cy.get(emailInput).type('My email'); cy.get(passInput).type('My Password'); cy.get(loginBtn).click(); cy.task('generateAuthCode').then(authCode => { cy.log(authCode); // 此处可继续使用authCode完成验证码输入操作 }); }) })
方法二:修复浏览器环境下的speakeasy兼容性
若必须在浏览器环境运行,需确保buffer模块正确加载:
- 安装
buffer包:
npm install buffer
- 修改验证码生成脚本,显式引入并挂载
buffer到全局:
const { Buffer } = require('buffer'); global.Buffer = Buffer; const speakeasy = require('speakeasy'); function getAuthCode() { // 实时生成验证码,避免模块加载时生成导致过期 return speakeasy.totp({ secret: '(my secret key)', encoding: 'base32' }); } module.exports = { getAuthCode };
3. 额外优化点
- 原代码在模块加载时就生成
token,会导致验证码过期,改为调用getAuthCode时实时生成更合理。 - 将全局函数
getAuthCode改为声明式函数,避免作用域问题。
内容的提问来源于stack exchange,提问作者octavio González Censori
相关产品推荐
相关产品推荐

