如何在Cypress测试中途重新执行插件配置以刷新凭证?
Cypress测试中凭证过期的重新获取方案
测试所用角色权限仅1小时,且角色链无法扩展权限。需要在测试中途、测试失败或凭证过期时,重新执行cypress/plugins/index.ts中的代码获取新凭证,但在测试中途或失败事件处理器中执行时无法识别Node环境变量,不清楚有哪些合适的钩子能让插件代码正常运行。
Plugin/index.ts 代码
import * as secretsManager from '@amzn/cypress-midway-plugin/secret_manager'; import PluginEvents = Cypress.PluginEvents; import PluginConfigOptions = Cypress.PluginConfigOptions; import * as AWS from 'aws-sdk' import { CYPRESS_PRINCIPAL, CYPRESS_SECRET_ID, REGION, STAGE } from '../resources/constants'; import fetchSigv4Session from "./sigv4"; import getEnvVariables from "./env-variables"; /** * @type {Cypress.PluginConfig} */ export default async (on: PluginEvents, config: PluginConfigOptions): Promise<PluginConfigOptions> => { // `on` is used to hook into various events Cypress emits // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config // assuming running from Hydra on('task', { log (message) { console.log(message) return null } }) config.env.SIGV4_SESSION = await fetchSigv4Session(AWS); config.env.REGION = REGION; config.env.CYPRESS_ENV_VARIABLES = getEnvVariables(STAGE) on('after:run', () => { console.log("Test finished at: ", new Date()) }); return config; };
Support/index.ts 代码
// Import commands.js using ES2015 syntax: import AWS = require('aws-sdk'); import fetchSigv4Session from '../plugins/sigv4'; import './commands' // Alternatively you can use CommonJS syntax: // require('./commands') const CYPRESS_LOG_NAME = 'Login with Midway'; Cypress.on('uncaught:exception', (err, runnable) => { // returning false here prevents Cypress from // failing the test console.warn('Uncaught exception (suppressed):', err); return false; }); //Runs at start of each test suites before(() => { cy.log("Starting Authentication") cy.setCookie('region', Cypress.env('REGION')); cy.setCookie('session', Cypress.env('SIGV4_SESSION')); const preserve = [ 'session', 'cypress', 'region' ]; Cypress.Cookies.defaults({ preserve }); return cy.request({ url: `https://authentication.api.com/api/session-status`, method: 'GET', headers: {'Clear-Site-Data': "*"} //This will allow us to do a fresh call rather than using browser's cache }, ).then(async response => { Cypress.log({ name: CYPRESS_LOG_NAME, message: [`Logged in and running cypress tests.`] }); cy.wrap(response, {log: false}); }) });
解决方案
1. 将凭证获取逻辑封装为Cypress任务
在插件文件中新增专属任务,运行在Node环境(可正常访问环境变量),用于随时获取新的SIGV4会话凭证:
修改Plugin/index.ts,添加refreshSigv4Session任务:
export default async (on: PluginEvents, config: PluginConfigOptions): Promise<PluginConfigOptions> => { // 保留原有代码... // 新增刷新凭证的任务 on('task', { log(message) { console.log(message) return null }, async refreshSigv4Session() { const newSession = await fetchSigv4Session(AWS); // 更新全局配置中的环境变量,确保后续测试能读取到新值 config.env.SIGV4_SESSION = newSession; return newSession; } }) // 保留原有代码... return config; };
2. 多时机触发凭证刷新
针对不同场景设置触发逻辑,确保凭证始终有效:
修改Support/index.ts:
// 新增检查并刷新凭证的函数 const refreshCredentials = async () => { try { // 调用插件任务获取新凭证 const newSession = await cy.task('refreshSigv4Session'); // 更新Cookie和Cypress环境变量 cy.setCookie('session', newSession); Cypress.env('SIGV4_SESSION', newSession); cy.log('凭证已刷新'); } catch (err) { cy.log(`凭证刷新失败: ${err}`); throw err; } }; // 检查会话状态,无效则触发刷新 const validateSession = async () => { try { const response = await cy.request({ url: `https://authentication.api.com/api/session-status`, method: 'GET', failOnStatusCode: false // 不直接失败,自行处理状态码 }); if (response.status !== 200) { await refreshCredentials(); } } catch (err) { // 请求失败大概率是凭证过期,直接刷新 await refreshCredentials(); } }; // 每个测试用例执行前检查凭证有效性 beforeEach(() => { validateSession(); }); // 监听测试失败事件,针对凭证过期错误触发刷新并重试 Cypress.on('fail', async (err, runnable) => { if (err.message.includes('Unauthorized') || err.message.includes('session expired')) { await refreshCredentials(); // 限制重试次数,避免无限循环 runnable._testRetryCount = (runnable._testRetryCount || 0) + 1; if (runnable._testRetryCount < 2) { return false; // 返回false阻止测试标记失败,触发重试 } } throw err; // 其他错误正常抛出 }); // 调整原有初始化逻辑,依赖凭证检查 before(() => { cy.log("Starting Authentication") cy.setCookie('region', Cypress.env('REGION')); return validateSession().then(() => { const preserve = [ 'session', 'cypress', 'region' ]; Cypress.Cookies.defaults({ preserve }); Cypress.log({ name: CYPRESS_LOG_NAME, message: [`Logged in and running cypress tests.`] }); }); });
3. 确保环境变量全局可访问
插件运行在Node环境,直接从process.env读取常量即可保证初始化和任务执行时都能正确获取:
修改../resources/constants.ts:
export const REGION = process.env.REGION || 'default-region'; export const STAGE = process.env.STAGE || 'default-stage'; export const CYPRESS_PRINCIPAL = process.env.CYPRESS_PRINCIPAL || ''; export const CYPRESS_SECRET_ID = process.env.CYPRESS_SECRET_ID || '';
内容的提问来源于stack exchange,提问作者Hima Chitalia
相关产品推荐
相关产品推荐

