You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:04:56