Cypress 12 TypeScript项目AWS Cognito程序化认证报错求助
解决Cypress 12.5 + TypeScript中AWS Cognito认证的
Class extends value undefined错误 问题根源
错误堆栈指向@aws-sdk/client-lex-runtime-service模块,本质是AWS Amplify v5+依赖的AWS SDK v3与Cypress的Webpack打包环境不兼容:导入完整aws-amplify包会自动加载大量无关模块(如Lex服务),这些模块的基类在Cypress运行时无法被正确解析,导致继承错误。
解决方案
以下提供两种可行方案,优先推荐方案2(无Amplify依赖,更稳定):
方案1:调整Amplify导入与Webpack配置
仅导入所需的Auth模块,排除冲突的AWS SDK模块:
1.1 修改cypress/support/cognito.ts
替换完整Amplify导入为单独Auth模块导入,并直接配置Auth:
import { Auth, SignInResult } from '@aws-amplify/auth' // 仅配置Auth模块,无需加载整个Amplify Auth.configure(Cypress.env('cognito.config')) Cypress.Commands.add('loginByCognitoApi', (username: string, password: string) => { const log = Cypress.log({ displayName: 'COGNITO LOGIN', message: [`🔐 Authenticating | ${username}`], autoEnd: false, }) log.snapshot('before') return cy.wrap(Auth.signIn({ username, password }), { log: false }).then((cognitoResponse: SignInResult) => { if (!cognitoResponse.signInUserSession) { throw new Error('Cognito会话获取失败') } const { username: cognitoUsername, keyPrefix } = cognitoResponse const keyPrefixWithUsername = `${keyPrefix}.${cognitoUsername}` window.localStorage.setItem(`${keyPrefixWithUsername}.idToken`, cognitoResponse.signInUserSession.idToken.jwtToken) window.localStorage.setItem(`${keyPrefixWithUsername}.accessToken`, cognitoResponse.signInUserSession.accessToken.jwtToken) window.localStorage.setItem(`${keyPrefixWithUsername}.refreshToken`, cognitoResponse.signInUserSession.refreshToken.token) window.localStorage.setItem(`${keyPrefixWithUsername}.clockDrift`, cognitoResponse.signInUserSession.clockDrift.toString()) window.localStorage.setItem(`${keyPrefix}.LastAuthUser`, cognitoUsername) window.localStorage.setItem('amplify-authenticator-authState', 'signedIn') log.snapshot('after') log.end() }) })
1.2 修复TypeScript类型声明(cypress/support/index.ts)
修正命令返回类型(该命令不返回DOM元素):
export {} declare global { namespace Cypress { interface Chainable<Subject = any> { loginAs(role: string): Chainable<JQuery<HTMLElement>>; clickMenuLink(linkText: string): Chainable<JQuery<HTMLElement>>; loginByCognitoApi(username: string, password: string): Chainable<void>; } } }
1.3 配置Cypress Webpack排除冲突模块
在cypress.config.ts中添加Webpack预处理器配置:
import { defineConfig } from 'cypress' import webpack from '@cypress/webpack-preprocessor' export default defineConfig({ e2e: { setupNodeEvents(on, config) { const webpackOptions = { resolve: { extensions: ['.ts', '.js'] }, module: { rules: [ { test: /\.ts$/, exclude: /node_modules/, use: { loader: 'ts-loader' } } ] }, externals: { // 排除引发错误的Lex服务模块 '@aws-sdk/client-lex-runtime-service': 'commonjs @aws-sdk/client-lex-runtime-service', // 可选:排除其他无需的AWS SDK v3模块 '@aws-sdk/client-cognito-identity': 'commonjs @aws-sdk/client-cognito-identity' } } on('file:preprocessor', webpack({ webpackOptions })) return config }, env: { cognito: { config: { userPoolId: '你的用户池ID', userPoolWebClientId: '你的客户端ID', region: '你的区域' } } } } })
方案2:直接调用Cognito API(无Amplify依赖)
完全避开Amplify库,用cy.request直接调用Cognito的InitiateAuth接口,稳定性更高:
修改cypress/support/cognito.ts
Cypress.Commands.add('loginByCognitoApi', (username: string, password: string) => { const log = Cypress.log({ displayName: 'COGNITO LOGIN', message: [`🔐 Authenticating | ${username}`], autoEnd: false, }) log.snapshot('before') const { userPoolId, userPoolWebClientId, region } = Cypress.env('cognito.config') return cy.request({ method: 'POST', url: `https://cognito-idp.${region}.amazonaws.com/`, headers: { 'Content-Type': 'application/x-amz-json-1.1', 'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth' }, body: { AuthFlow: 'USER_PASSWORD_AUTH', ClientId: userPoolWebClientId, AuthParameters: { USERNAME: username, PASSWORD: password } } }).then((response) => { const { IdToken, AccessToken, RefreshToken } = response.body.AuthenticationResult const keyPrefix = `CognitoIdentityServiceProvider.${userPoolWebClientId}` const keyPrefixWithUsername = `${keyPrefix}.${username}` window.localStorage.setItem(`${keyPrefixWithUsername}.idToken`, IdToken) window.localStorage.setItem(`${keyPrefixWithUsername}.accessToken`, AccessToken) window.localStorage.setItem(`${keyPrefixWithUsername}.refreshToken`, RefreshToken) window.localStorage.setItem(`${keyPrefix}.LastAuthUser`, username) window.localStorage.setItem('amplify-authenticator-authState', 'signedIn') log.snapshot('after') log.end() }) })
测试验证
在测试用例中调用命令:
describe('认证测试', () => { it('通过Cognito登录', () => { cy.loginByCognitoApi('测试用户名', '测试密码') cy.visit('https://myurl.com/login') // 验证登录状态,比如检查用户信息元素 cy.get('.user-profile').should('be.visible') }) })
内容的提问来源于stack exchange,提问作者Dave H
相关产品推荐
相关产品推荐

