如何使用赛普拉斯和Auth0测试单页应用程序

时间:2020-01-09 13:09:32

标签: auth0 cypress auth0-lock

我正在使用@auth0/auth0-spa-js隐藏在Auth0锁后面的单页应用程序。我想使用赛普拉斯对其进行测试,所以我决定遵循官方的Auth0 blog post和约翰尼·赖利blog post

我能够使用建议的请求从auth0成功检索有效的JWT令牌。我不知道该怎么办:(

我面临的麻烦是以上两种方法都依赖于应用程序在本地存储JWT令牌(以cookie或localstorage形式)。 @auth0/auth0-spa-js使用的是另一种方法,我假设所有相关的cookie /本地存储都存储在auth0域中。

您有什么想法,是否有办法解决?

据报here于2018年7月提出了类似问题,但并未提供任何解决方案

3 个答案:

答案 0 :(得分:3)

我在@auth0/auth0-spa-js的github上找到了已解决的问题。 approach建议的cwmrowe似乎有效

解决方案是使用在e2e测试端生成的令牌来模拟oauth/token端点的响应。

这种方法似乎对我们有用

我正在复制提供的示例代码cwmrowe

Cypress.Commands.add(
  'login',
  (username, password, appState = { target: '/' }) => {
    cy.log(`Logging in as ${username}`);
    const options = {
      method: 'POST',
      url: Cypress.env('Auth0TokenUrl'),
      body: {
        grant_type: 'password',
        username,
        password,
        audience: Cypress.env('Auth0Audience'),
        scope: 'openid profile email',
        client_id: Cypress.env('Auth0ClientId'),
        client_secret: Cypress.env('Auth0ClientSecret')
      }
    };
    cy.request(options).then(({ body }) => {
      const { access_token, expires_in, id_token } = body;

      cy.server();

      // intercept Auth0 request for token and return what we have
      cy.route({
        url: 'oauth/token',
        method: 'POST',
        response: {
          access_token,
          expires_in,
          id_token,
          token_type: 'Bearer'
        }
      });

      // Auth0 SPA SDK will check for value in cookie to get appState
      // and validate nonce (which has been removed for simplicity)
      const stateId = 'test';
      const encodedAppState = encodeURI(JSON.stringify(appState));
      cy.setCookie(
        `a0.spajs.txs.${stateId}`,
        `{%22appState%22:${encodedAppState}%2C%22scope%22:%22openid%20profile%20email%22%2C%22audience%22:%22default%22}`
      );

      const callbackUrl = `/auth/callback?code=test-code&state=${stateId}`;
      return cy.visit(callbackUrl);
    });
  }
);

declare namespace Cypress {
  interface Chainable<Subject> {
    login(
      username: string,
      password: string,
      appState?: any
    ): Chainable<Subject>;
  }
}

答案 1 :(得分:0)

虽然不建议使用UI登录,但在进行所有测试之前,我自己做一次,然后对测试使用静默身份验证:-cy.visit("/")静默身份验证并允许访问应用程序。

integration / app.js

describe("App", () => {
  before(() => {
    Cypress.config("baseUrl", "http://localhost:3000");
    cy.login();
  });

  /** Uses silent auth for successive tests */
  beforeEach(() => {
    cy.restoreLocalStorage();
  });

  afterEach(() => {
    cy.saveLocalStorage();
  });

  /** tests */

support / commands.js

/**
 * Auth0 login
 * https://github.com/cypress-io/cypress/issues/461#issuecomment-392070888
 *
 * Allows silent auth login between tests
 */
let LOCAL_STORAGE_MEMORY = {};

Cypress.Commands.add("saveLocalStorage", () => {
  Object.keys(localStorage).forEach(key => {
    LOCAL_STORAGE_MEMORY[key] = localStorage[key];
  });
});

Cypress.Commands.add("restoreLocalStorage", () => {
  Object.keys(LOCAL_STORAGE_MEMORY).forEach(key => {
    localStorage.setItem(key, LOCAL_STORAGE_MEMORY[key]);
  });
});

Cypress.Commands.add("clearLocalStorage", () => {
  LOCAL_STORAGE_MEMORY = {};
});

答案 2 :(得分:0)

对于那些对于赛普拉斯的Google登录有问题的人,请查看插件:https://github.com/lirantal/cypress-social-logins/

  it('Login through Google', () => {
    const username = Cypress.env('googleSocialLoginUsername')
    const password = Cypress.env('googleSocialLoginPassword')
    const loginUrl = Cypress.env('loginUrl')
    const cookieName = Cypress.env('cookieName')
    const socialLoginOptions = {
      username,
      password,
      loginUrl,
      headless: false,
      isPopup: true,
      logs: false,
      loginSelector: 'a[href="/auth/auth0/google-oauth2"]',
      postLoginSelector: '.account-panel'
    }

    return cy.task('GoogleSocialLogin', socialLoginOptions).then(({cookies}) => {
      cy.clearCookies()

      const cookie = cookies.filter(cookie => cookie.name === cookieName).pop()
      if (cookie) {
        cy.setCookie(cookie.name, cookie.value, {
          domain: cookie.domain,
          expiry: cookie.expires,
          httpOnly: cookie.httpOnly,
          path: cookie.path,
          secure: cookie.secure
        })

        Cypress.Cookies.defaults({
          whitelist: cookieName
        })
      }
    })
  });
相关问题