我正在使用 cypress 设置一套 E2E 测试。我有一个 React typescript 应用程序,我正在尝试让它与 cypress 一起使用。我面临的主要问题是我使用 Auth0 作为我的身份验证提供程序。这意味着我需要在每次测试之前以编程方式让用户登录。但是我似乎无法获得执行此操作的正确方法。当我尝试它调用回调 url 但它似乎没有对用户进行身份验证,因为他们只是转到一个空白页面?我正在使用 @auth0/auth0-react 包,它有一个用于访问所有 Auth0 数据的钩子(Hook)。
Cypress 命令:
import jwt_decode from 'jwt-decode';
Cypress.Commands.add('login', () => {
cy.log(`logging in as ${Cypress.env('auth_username')}`);
cy.request({
method: 'POST',
url: Cypress.env('auth_url'),
body: {
grant_type: 'password',
username: Cypress.env('auth_username'),
password: Cypress.env('auth_password'),
audience: Cypress.env('auth_audience'),
scope: 'openid profile email',
client_id: Cypress.env('auth_client_id'),
client_secret: Cypress.env('auth_client_secret'),
},
}).then(({ body }) => {
const claims = jwt_decode(body.id_token);
const { nickname, name, picture, updated_at, email, email_verified, sub, exp } = claims;
const item = {
body: {
...body,
decodedToken: {
claims,
user: {
nickname,
name,
picture,
updated_at,
email,
email_verified,
sub,
},
audience: Cypress.env('auth_audience'),
client_id: Cypress.env('auth_client_id'),
},
},
expiresAt: exp,
};
window.localStorage.setItem('auth0Cypress', JSON.stringify(item));
});
});
最佳答案
我刚遇到同样的问题,终于找到了正确的解决方案:
You have to pass the
id_token
obtained from auth0 token endpoint to your app's callback endpoint as body of POST request
重要:我假设您遵循了 https://docs.cypress.io/guides/testing-strategies/auth0-authentication#Custom-Command-for-Auth0-Authentication 中描述的 auth0 设置或 https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/
来源:https://github.com/auth0/express-openid-connect/blob/65bd19eeac63e00e9a5b76973a0a15ecbe2623af/middleware/auth.js#L90第 90 行; https://github.com/auth0/express-openid-connect/blob/65bd19eeac63e00e9a5b76973a0a15ecbe2623af/lib/client.js#L88第 88 行; https://github.com/panva/node-openid-client/blob/main/lib/client.js#L333第 333 行。
工作解决方案:
Cypress.Commands.add("login", (overrides = {}) => {
const tenantURL = Cypress.env("auth0_tenant_url");
const options = {
method: "POST",
url: `${tenantURL}/oauth/token`,
body: {
grant_type: "password",
username: Cypress.env("auth_username"),
password: Cypress.env("auth_password"),
audience: `${tenantURL}/api/v2/`,
scope: "openid profile email",
client_id: Cypress.env("auth0_client_id"),
client_secret: Cypress.env("auth0_client_secret"),
},
};
cy.request(options).then((resp) => {
const { id_token } = resp.body;
cy.request({ // this is the crucial part. Passing id_token to callback endpoint
method: "POST", // callback endpoint sets the session cookie which is picked up by cypress and used to authenticate subsequent requests
url: "/callback",
body: { id_token }, // Must pass only the access_token. Passing full response from oauth causes the 'missing at_hash error'
});
});
});
示例 cypress.env.json
:
{
"auth0_tenant_url": "auth0 tenant url",
"auth0_client_id": "auth0 client id",
"auth0_client_secret": "auth0 secret",
"auth_username": "user@fakeemail",
"auth_password": "password"
}
那么你只需要:
describe("Logged in route test", () => {
beforeEach(() => {
cy.login();
cy.visit("/");
});
it("displays content for logged in users", () => {
cy.get("button[role=buy]").should("exist");
});
});
您可以在我的 Clampfit 导出器应用程序中查看完整示例:
关于typescript - 让 Cypress 正确登录到 Auth0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66612150/