Cypress:如何在“cy.intercept”中等待“cy.task”

And*_*ies 7 cypress

我遇到一种情况,我想在拦截中生成 JWT 令牌并将其返回到其主体中。问题在于,在该令牌的有效负载中,应该使用另一个拦截中的值。这意味着我只能在拦截期间生成令牌。

const code = '1234567890ABCDEFGH';
let accessTokenSource, idTokenSource, accessToken, idToken;
Run Code Online (Sandbox Code Playgroud)
cy.fixture('access.token.json').then((source) => (accessTokenSource = source));
cy.fixture('id.token.json').then((source) => (idTokenSource = source));    
Run Code Online (Sandbox Code Playgroud)
cy.intercept('https://****/authorize', (req) => {
  const url = new URL(req.url);

  idTokenSource.claims.nonce = url.searchParams.get('nonce');

  req.redirect(`${Cypress.config().baseUrl}?code=${code}&state=${url.searchParams.get('state')}`);
});    
Run Code Online (Sandbox Code Playgroud)
cy.intercept('https://****/oauth/token', (req) => {
  cy.task('generateToken', accessTokenSource).then((token) => (accessToken = token));
  cy.task('generateToken', idTokenSource).then((token) => (idToken = token));

  console.log('accessToken', accessToken);
  console.log('idToken', idToken);

  req.reply({
    body: {
      access_token: accessToken,
      expires_in: 86400,
      id_token: idToken,
      scope: 'openid profile email',
      token_type: 'Bearer',
    },
    headers: {
      'content-type': 'application/json',
    },
  });
});
Run Code Online (Sandbox Code Playgroud)

正如您可能已经想到的,accessTokenidToken是空的。

我应该在这里更改什么以等待generateToken任务完成才能在 中使用它req.reply

ps我已经尝试过这个,但它不起作用:

cy.task('generateToken', accessTokenSource).as('generateAccessToken');
cy.task('generateToken', idTokenSource).as('generateIdToken');

cy.wait('@generateAccessToken').then((token) => (accessToken = token));
cy.wait('@generateIdToken').then((token) => (idToken = token));

console.log('accessToken', accessToken);
console.log('idToken', idToken);
Run Code Online (Sandbox Code Playgroud)

PS2。当我将其放入测试中时,效果generateToken很好。it()

And*_*ies 0

我创建了一个解决方法,不再使用该插件,而是直接执行签名函数。

在 cypress 测试文件之上:

import jwt from 'jsonwebtoken';

const generateToken = function (privateKey, options) {
  return jwt.sign(options.claims, privateKey, { algorithm: 'RS256', expiresIn: options.expires, issuer: options.issuer });
};
Run Code Online (Sandbox Code Playgroud)

测试开始:

let authCode, privateKey, accessTokenSource, idTokenSource, accessToken, idToken;

authCode = Cypress.env('authCode');
cy.readFile(Cypress.env('jwtPrivateKey')).then((key) => (privateKey = key));
cy.fixture('access.token.json').then((source) => (accessTokenSource = source));
cy.fixture('id.token.json').then((source) => (idTokenSource = source));
Run Code Online (Sandbox Code Playgroud)

截距:

cy.intercept('https://***/oauth/token', (req) => {
  const params = new URLSearchParams(req.body);
  expect(params.get('code')).to.equal(authCode);

  accessToken = generateToken(privateKey, accessTokenSource);
  idToken = generateToken(privateKey, idTokenSource);

  req.reply({
    body: {
      access_token: accessToken,
      expires_in: 86400,
      id_token: idToken,
      scope: 'openid profile email',
      token_type: 'Bearer',
    },
    headers: {
      'content-type': 'application/json',
    },
  });
});
Run Code Online (Sandbox Code Playgroud)