如何在 Cypress 的 E2E 测试中登录 Auth0?

2024-04-29

我已经开始测试 React Web 应用程序,但我没有走得太远,因为我遇到了登录问题。我在用cypress https://www.cypress.io/e2e测试工具。

将显示一个带有登录按钮的欢迎页面,该页面会将您重定向到auth0 https://auth0.com/服务。用户使用电子邮件和密码登录,然后使用令牌重定向回 Web 应用程序。

我尝试了许多不同的方法,每种方法都导致了不同的问题。

注意:我不想测试Auth0,我只想进入我的web应用程序。

尝试1.点击登录按钮

尝试过:Cypress 应该执行与用户相同的操作,因此测试将单击登录按钮并转到 Auth0 并填写凭据。 问题:Cypress 不允许您在测试期间导航到另一个域。

由于赛普拉斯会更改自己的主机 URL 以匹配您的应用程序的主机 URL,因此它要求您的应用程序在整个单个测试中保持在同一超级域上。 https://docs.cypress.io/guides/guides/web-security.html#One-Superdomain-per-Test

您应该能够禁用该设置"chromeWebSecurity": false in cypress.json但这还行不通,因为您只能访问一个域cy.visit() https://github.com/cypress-io/cypress/issues/944

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

尝试过:从 cypress 测试登录auth0-js https://github.com/auth0/auth0.js库,因此不需要单击登录按钮,因此不会发生域更改。

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()
  })
})

问题:cy.route() 不等待获取请求 https://github.com/cypress-io/cypress/issues/95,解决方法是使用cy.stub(win, 'fetch') https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/stubbing-spying__window-fetch/cypress/integration/spy-stub-clock-spec.js。它不会等待:

尝试 3. 从 web 应用程序以编程方式登录

尝试过:我开始认为 cypress 只监视来自应用程序的间谍请求,而不是来自测试本身的请求(正如我在上面的观点中尝试的那样)。

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

cy.get('#fake-login').click()

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

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
})

由于某种原因,这不起作用,元素已添加,但不会等到发出请求。

所以我不知道还能尝试什么。 也许一切都是对如何在 E2E 中完成登录的误解,我是否应该使用模拟数据以便不需要登录?


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

我设置了一个与 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);

然后我只需扩展 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);
    });
  });
});

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Cypress 的 E2E 测试中登录 Auth0? 的相关文章

随机推荐

  • 如何在杂志/报纸等砖石布局中浮动元素?

    我正在尝试实现一种布局 其中项目将像报纸 杂志文章部分一样浮动 它类似于什么jQuery 的砌体 http masonry desandro com 做 但我试图仅使用 CSS3 来实现这一点 我想也许box显示属性可以做到这一点 尽管尝试
  • 如何在WebView中隐藏滚动条?

    我切换到WKWebView因为UIWeb视图Apple 不再建议使用 使用以下代码从 WebView 中的容器加载 HTML 文件 let webview myWKWebViewClass webview for Bundle main f
  • 按字段关联 ELK 中的消息

    相关 在ELK中合并日志和查询 https stackoverflow com questions 28429607 combine logs and query in elk 我们正在设置 ELK 并希望在 Kibana 4 中创建可视化
  • 如何在 PhantomJS 中使用 JavaScript 检测网页上的声音?

    我需要检测带有横幅的网页中的所有声音 我怎样才能做到这一点 我查看 PhantomJS 但找不到浏览器声音的 API PhantomJS 1 x 和 2 不支持 Flash
  • 延迟加载使用 document.write 的双击广告的最佳方法是什么?

    通过 doubleclick 请求的广告通常由广告提供商网络提供服务 该网络返回 javascript 进而执行 document write 以将广告放置在页面中 使用 document write 要求文档处于打开状态 这意味着页面尚未
  • 使用 Mono Cecil 添加 try-catch

    我正在使用 Mono Cecil 在另一个方法中注入代码 我想在我的代码周围添加一个 Try Catch 块 所以我写了一个带有 try catch 块的 HelloWorld exe 并反编译了它 Try Catch 的 Reflecto
  • ng-bootstrap - ngbtooltip 不适用于 [(ngModel)]

    我是 Angular 4 和 bootstrap beta 2 的新手 并尝试使用ngbtooltip显示工具提示文本 当只有输入没有时 标签上的工具提示工作正常 ngModel 我一用过 ngModel 在输入文本控件中 工具提示仅显示第
  • Twitter Bootstrap 2 模式表单对话框

    我有以下对话框 div class modal div class modal header a class close a h3 Add Tags h3 div div class modal body div div
  • M1 MacBook Pro 和 cmake 的编译错误

    我刚刚拿到了新的 M1 MacBook Pro 正在尝试编译大学工作所需的代码库 以下是我已采取的步骤 我使用 Rosetta 将终端设置为始终打开 安装的自制程序using bin bash c curl fsSL https raw g
  • 通过 StackExchange.Redis 连接到 Redis Servier

    我尝试使用以下方法制作一个测试项目Redis https redis io服务器 通过 Virtual Box 安装在 Linux Ubuntu 虚拟机上 Linux 机器通过 Virtual Box 的桥接适配器与本地网络连接 Virtu
  • Mac OS Snow Leopard 上的两个版本的 PHP 以及使用 PECL 安装 xdebug

    我正在使用MAMP在我阅读一些有关内置 Apache PHP 的文章之前 我已经在 PHP 开发 标准 中使用过一段时间了雪豹 我决定转向那些我提供的但似乎有很多问题的人 第一件事是当我使用MAMP时 我将PEAR从1 9 0升级到1 9
  • 使用 gradle kotlin dsl 执行 JavaExec 任务

    我创建了简单的build gradle kts file group com lapots breed version 1 0 SNAPSHOT plugins java java sourceCompatibility JavaVersi
  • 跨页面加载跟踪子窗口

    如果重新加载父页面 是否可以跟踪子窗口 我目前打开窗口如下 var childWindow childWindow window open url 当我想重新打开同一个子窗口时 childWindow focus 明显的问题是 如果刷新父窗
  • Discord JS - DiscordAPIError:缺少访问权限

    所以我按照磨损钥匙教程来不和谐机器人 我不知道问题是什么 这是错误 home container node modules discord js src rest RequestHandler js 349 throw new Discor
  • cron 作业或 PHP 调度程序

    我使用 MYSQL 作为我的数据库 PHP 作为我的编程语言 我想运行一个 cron 作业 该作业将运行直到当前系统日期与我的数据库表中名为 PROJECT 的 截止日期 日期 列匹配 一旦日期相同的是 必须运行更新查询 这会将状态 项目表
  • Linux 中如何确定哪个进程正在使用某个端口

    我目前正在其默认端口上运行 RethinkDB 因为如果我将浏览器指向localhost 8080我看到 RethinkDB Web 界面 我想关闭 RethinkDB 并使用以下命令在另一个端口上重新打开它 port offset争论 然
  • 特定模型的自定义 REST url

    Ember 有没有办法为特定模型配置自定义 REST url 就像这个模型一样 App Post DS Model extend title DS attr string comments DS hasMany App Comment Ap
  • SQL原型设计:面对使用varchar(N)静默截断数据——有更好的选择吗? (天数据)

    情况 varchar 20 好像默默地截断在 Teradata 和not当遇到长度超过 20 个字符的字符串时扩展或抱怨 这有点令人惊讶 因为我预计列会自动扩展以适应更大的字符串 例如 30 个字符 或者如果更大的字符串会抛出错误遇到字符串
  • 在 Angular 中强制进行摘要

    在用户操作后的某个时刻 我希望发生摘要 因此 UI 反映了支持它的数据模型的更改 我有一个服务在回调中执行一些更改 异步 我明白那个 scope仅在控制器的上下文中才有意义 我可以通过执行来达到相同的效果吗 apply on the roo
  • 如何在 Cypress 的 E2E 测试中登录 Auth0?

    我已经开始测试 React Web 应用程序 但我没有走得太远 因为我遇到了登录问题 我在用cypress https www cypress io e2e测试工具 将显示一个带有登录按钮的欢迎页面 该页面会将您重定向到auth0 http