首页 > 解决方案 > 如何测试用户是否可以使用赛普拉斯链接 OAuth 提供者?

问题描述

我正在开发一个项目,用户可以使用电话号码、Google 或 Github 登录。我使用 Firebase 进行身份验证。我目前正在使用赛普拉斯添加集成测试。我的问题是我无法正确测试用户是否可以链接或取消链接提供商。要链接提供者,我使用linkWithRedirect()firebase 方法。
起初,我试图模拟一个按钮点击。但这不起作用,因为赛普拉斯不允许在一次测试中访问多个域。
我的下一个尝试是使用linkWithCredential()方法。我从开发人员工具中获取 cookie 和提供者的身份验证 URL,以获取授权代码并使用此代码获取访问令牌。
我的赛普拉斯命令获取 Google 令牌:

Cypress.Commands.add(
  'getGoogleToken',
  () => {
    cy.request({
      url: Cypress.env("GOOGLE_AUTH_URL"),
      headers: {
        cookie: Cypress.env("GOOGLE_AUTH_COOKIE")
      }, 
      followRedirect: false
    })
    .its("redirectedToUrl")
    .then(redirectedToUrl => {
      const url = new URL(redirectedToUrl);
      const code = url.searchParams.get("code");
      cy.request({
        url: "https://www.googleapis.com/oauth2/v4/token",
        method: "POST",
        form: true,
        body: {
          code,
          redirect_uri: Cypress.env("GOOGLE_REDIRECT_URI"),
          client_id: Cypress.env("GOOGLE_CLIENT_ID"),
          client_secret: Cypress.env("GOOGLE_CLIENT_SECRET"),
          grant_type: "authorization_code"
        }
      })
      .its("body")
      .then(body => body.access_token);
    });
});

使用这个令牌我调用我自己的linkWithGoogleWithToken方法,该方法调用linkWithCredential方法:

Cypress.Commands.add(
  'linkWithGoogle', 
  () => {
    cy.getGoogleToken()
      .then(token => {
        cy.get("@auth")
          .invoke("linkWithGoogleWithToken", token);
      });
});

在我的测试中,我调用了几个函数来链接一个提供者,然后链接另一个提供者,然后取消链接提供者,等等。有时此命令按预期工作,但有时它会永远处于挂起状态。我找不到原因。搜索没有帮助,似乎没有人遇到过这个问题。
因此,我正在寻找以编程方式链接 OAuth 提供程序的方法,而不是使用 UI。我正在考虑 Firebase Admin SDK,但在其文档中找不到链接提供程序的方法。我将不胜感激遇到此问题的任何人的帮助。

标签: javascriptreactjsfirebasecypress

解决方案


我发现了为什么我会遇到这个问题。关键是访问该页面后,我添加了一个别名来引用我的 firebase 函数:

Cypress.Commands.add(
  'init',
  () => {
    cy.visit("/");
    cy.window()
      .its("firebase")
      .its("auth").as("auth");
    cy.nullifyUsername();
});

当我第一次调用该invoke方法时,一切正常。然后我重新加载了页面,因为我需要使用此信息更新页面。

cy.linkGoogle();
    cy.reload();
    cy.get("@googleButton")
      .contains(/^unlink$/i);

之后,下次我尝试链接另一个提供程序时,调用方法仍处于挂起状态。发生这种情况是因为重新加载页面后,我的别名被引用到一个不再存在的函数。我的解决方案是在重新加载页面后添加别名。所以,我为此创建了自定义命令:

Cypress.Commands.add(
  'refresh',
  () => {
    cy.reload();
    cy.window()
      .its("firebase")
      .its("auth").as("auth");
});

推荐阅读