如何使用赛普拉斯在E2E测试中登录Auth0?

Mik*_*kel 17 testing mocking e2e-testing auth0 cypress

我已经开始测试一个反应webapp但我没有走远,因为我遇到了登录问题.我正在使用cypress e2e测试工具.

将显示一个欢迎页面,其中包含一个要登录的按钮,该按钮将重定向到您的auth0服务.用户使用电子邮件和密码登录,然后使用令牌重定向回webapp.

我尝试了许多不同的方法,导致了不同的问题.

注意:我不想测试Auth0,我只想输入我的webapp.

尝试1.单击登录按钮

尝试:赛普拉斯应该像用户一样做,因此测试将点击登录按钮并转到Auth0并填写凭据.问题:赛普拉斯不允许您在测试期间导航到其他域.

由于赛普拉斯更改了自己的主机URL以匹配您的应用程序的URL,因此它要求您的应用程序保留在同一个超级域中以进行单个测试.

您应该能够禁用该设置"chromeWebSecurity": false,cypress.json但它无法使用,因为您只能访问单个域cy.visit()

尝试2.从测试中以编程方式登录

尝试:使用auth0-js库登录cypress测试,因此不需要单击登录按钮,因此不会发生域更改.

describe('Waiting to fetch', () => {
  beforeEach(() => {
    this.fetchAuthDeferred = getDeferred()
    cy.visit('http://localhost:3000', {
      onBeforeLoad(win) {
        cy.stub(win, 'fetch')
          .withArgs($url)
          .as('fetchAuth')
          .returns(this.fetchAuthDeferred.promise)
      }
    })
  })

  it('login', () => {
    cy.visit('http://localhost:3000')

    const auth = new auth0.WebAuth(authOptions)
    auth.login(loginOptions)

    cy.get('@fetchAuth', { timeout: 10000 }).should('haveOwnProperty', 'token')

    cy.visit('http://localhost:3000')
    cy.get('[class*="hamburger"]').click()
  })
})
Run Code Online (Sandbox Code Playgroud)

问题:cy.route() 不等待获取请求,解决方法是使用cy.stub(win, 'fetch').它不会等待:

在此输入图像描述

尝试3.从webapp以编程方式登录

尝试:我开始认为柏树只是从应用程序发出的间谍请求,而不是来自测试本身(正如我在上面的观点中所尝试的那样).

我在欢迎页面中添加了一个假登录按钮,该按钮将auth0-js使用硬编码凭据调用(因此不会更改域名)并从测试中单击它

cy.get('#fake-login').click()
Run Code Online (Sandbox Code Playgroud)

问题:该策略有效,但当然我不想在欢迎页面中添加带凭据的按钮.所以我尝试在测试期间将按钮元素添加到webapp:

it('Login adding element', () => {
  cy.visit('http://localhost:3000')
  const = document.createElement('div')
  fakeLogin.innerHTML = 'Fake login'
  fakeLogin.onclick = function() {
    const auth = new auth0.WebAuth(authOptions)
    auth.login(loginOptions)
  }
  fakeLogin.style.position = 'absolute'
  fakeLogin.style.zIndex = 1000
  fakeLogin.id = 'fake-login'

  cy.get('#root').invoke('prepend', fakeLogin)
  cy.get('#fake-login').click()
  cy.get('[class*="hamburger"]').click() // Visible when logged in
})
Run Code Online (Sandbox Code Playgroud)

由于某些原因,这不起作用,元素被添加但是不会等到请求发出.

所以我不知道还有什么可以尝试的.也许所有事情都是对如何在E2E中进行登录的误解,我是否应该使用模拟数据以便不需要登录?

Bra*_*don 4

赛普拉斯目前不支持此功能。不过,我建立了一个可能有帮助的解决方法。

我设置了一个与 cypress 并行运行的简单服务器。端点打开 Puppeteer 的无头实例并完成登录流程,使用所有 cookie 响应调用:

const micro = require("micro");
const puppeteer = require("puppeteer");
const url = require("url");

const login = async (email, password) => {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto("https://my-login-page.com");
  // do whatever you have to do to get to your auth0 lock screen, then:
  await page.waitFor(".auth0-lock-input-email");
  await page.waitFor("span.auth0-label-submit");
  await page.type(".auth0-lock-input-email input", email);
  await page.type(".auth0-lock-input-password input", password);
  await page.click("span.auth0-label-submit");
  await page.waitFor("some-selector-on-your-post-auth-page");
  return page.cookies();
 };

const server = micro(async (req, res) => {
  // expect request Url of form `http://localhost:3005?email=blahblah&password=blahblah
  const data = url.parse(req.url, true);
  const { email, password} = data.query;
  console.log(`Logging ${email} in.`);
  return login(email, password);
});

server.listen(3005);
Run Code Online (Sandbox Code Playgroud)

然后我只需扩展 Cypress 来添加login命令:

Cypress.Commands.add("login", (email, password) => {
  const reqUrl = `http://localhost:3005?email=${encodeURIComponent(
    email
  )}&password=${encodeURIComponent(password)}`;
  console.log("Beginning login.", reqUrl);
  cy.request(reqUrl).then(res => {
    const cookies = res.body;
    cookies.forEach((c) => {
      cy.setCookie(c.name, c.value, c);
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

每次调用都需要大约 5-10 秒,这很糟糕,但比根本没有任何身份验证要好:/