如何使用Cypress和Auth0测试单页应用程序

如何使用Cypress和Auth0测试单页应用程序,auth0,cypress,auth0-lock,Auth0,Cypress,Auth0 Lock,我有一个单页应用程序隐藏在Auth0锁后面,使用。我想用Cypress来测试它,所以我决定跟随这位官员以及Johnny Reilly 我能够使用建议的请求从auth0成功检索有效的JWT令牌。我不知道该怎么办:( 我面临的问题是,上述两种方法都依赖于应用程序在本地存储JWT令牌(在cookie或localstorage中)。但是,使用不同的方法,我假设所有相关的cookie/localstorage存储在auth0域上 你知道有什么办法可以绕过它吗 据报道,2018年7月提出了一个类似的问题,没

我有一个单页应用程序隐藏在Auth0锁后面,使用。我想用Cypress来测试它,所以我决定跟随这位官员以及Johnny Reilly

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

我面临的问题是,上述两种方法都依赖于应用程序在本地存储JWT令牌(在cookie或localstorage中)。但是,使用不同的方法,我假设所有相关的cookie/localstorage存储在auth0域上

你知道有什么办法可以绕过它吗


据报道,2018年7月提出了一个类似的问题,没有真正提供任何解决方案

我在
@auth0/auth0 spa js
github上发现了一个已解决的问题。建议的解决方案似乎有效

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

这种方法似乎对我们有效

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

Cypress.Commands.add(
“登录”,
(用户名、密码、appState={target:'/'})=>{
cy.log(`Logging as${username}`);
常量选项={
方法:“POST”,
url:Cypress.env('Auth0TokenUrl'),
正文:{
授予类型:“密码”,
用户名,
密码,
受众:Cypress.env('Auth0Audience'),
范围:“openid配置文件电子邮件”,
客户端id:Cypress.env('Auth0ClientId'),
客户端密码:Cypress.env('Auth0ClientSecret')
}
};
cy.request(options).then({body})=>{
const{access_token,expires_in,id_token}=body;
cy.server();
//拦截令牌的Auth0请求并返回我们拥有的
赛道({
url:'oauth/token',
方法:“POST”,
答复:{
访问令牌,
在,,
身份证,
令牌类型:“持票人”
}
});
//Auth0 SPA SDK将检查cookie中的值以获取appState
//和验证nonce(为了简单起见已删除)
const stateId='test';
const encodedAppState=encodeURI(JSON.stringify(appState));
赛特库奇(
`a0.spajs.txs.${stateId}`,
`{%22appState%22:${encodedAppState}%2C%22scope%22:%22openid%20profile%20email%22%2C%22audience%22:%22默认值%22}`
);
const callbackUrl=`/auth/callback?code=test code&state=${stateId}`;
返回cy.visit(callbackUrl);
});
}
);
声明命名空间Cypress{
可链接接口{
登录(
用户名:string,
密码:string,
应用状态?:有吗
):可链接;
}
}

虽然不建议使用用户界面登录,但在所有测试之前,我会亲自登录一次,然后使用静默身份验证进行测试:-
cy.visit(“/”)
静默身份验证并允许访问应用程序

集成/app.js

support/commands.js


对于那些对Google登录Cypress有疑问的用户,请查看该插件:


通过使用基于表单的身份验证运行oauth2认证的spring boot/security应用程序,我解决了测试oauth2认证的spring boot/security应用程序的问题,使cypress使用非常简单,可以从json fixture文件中读取凭据。在测试期间,您能够使用不同的身份验证机制吗?我假设这意味着,您必须在logi中输入电子邮件和地址n由Auth0生成的表单。我假设我可以这样做,但是我的测试实际上是测试Auth0表单,这超出了我的控制范围。我更愿意生成一个令牌,然后指示Auth0使用它。不,这意味着我通过使用基于普通用户名/密码的表单来回避将oauth与cypress集成的问题运行我的功能性ui测试时的安全性。哦,您有两种身份验证方法。一种是对所有用户使用auth0,然后将“隐藏”分开一个用于e2e?这可能不适用于我的用例,因为JWT稍后用于授权属于不同服务的单独REST调用是的,但基于表单的方式仅用于测试。稍后的REST调用是否可以在Cypress中存根?请注意,这可能会影响测试的集成方面。无论如何,我想你明白我的意思了,当面对问题时,闪避一下。。
describe("App", () => {
  before(() => {
    Cypress.config("baseUrl", "http://localhost:3000");
    cy.login();
  });

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

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

  /** tests */
/**
 * 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 = {};
});
  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
        })
      }
    })
  });