Protractor重定向到Auth0非Angular页面后同步到Angular页面

3
我有一个使用Protractor进行e2e测试的Angular Web应用程序。最近添加了OAuth0身份验证。我在重定向到非Angular OAuth0页面之前使用await browser.waitForAngularEnabled(false)禁用了Angular同步,这个操作很好用。然而,我无法在整个spec文件测试套件的其余部分中再次使用await browser.waitForAngularEnabled(true)重新启用Angular同步,否则我会遇到臭名昭著的protractor超时错误。我想重新启用Angular同步,否则我必须使用预期条件、等待和休眠来确保后续页面已加载,这可能导致间歇性错误。
我已经阅读了所有的问题和答案,尝试了所有明显的解决方法-重新加载页面、获取新页面、等待、长时间等待等等。
所以我的问题相当具体,而不是寻求建议-是否有人了解Protractor与Angular页面同步的机制,并且是否知道在重定向到并从非Angular页面返回后Angular是否可以重新同步,即我是否在寻找修复的过程中浪费了时间。我稍微研究了一下这个机制-它加载要在页面上运行的脚本但我不确定为什么在从auth0重定向返回后执行browser.get('/')时不能再次加载该脚本。
请注意,我可以禁用Angular同步并使事情正常工作,所以我不是在寻求有关如何使事情正常工作的建议。如果您遇到过这个特定问题并找到了解决方法,我很想听听您的意见。
感谢任何帮助。

我可以说,这是一个非常出色措辞的问题! - pixelbits
2个回答

2

答案 - 是的,您可以在Protractor中重新启用Angular。但是,Protractor并不总是与Angular应用程序兼容。因此,请确保Protractors同步将按照应用程序的要求工作,并且页面已准备就绪。

首先,手动打开应用程序并进行授权。然后在控制台中运行getAllAngularTestabilities()。如果此命令不可用,则protractor无法使用angular。如果该命令成功,则查看返回的对象,特别是obj [0]._ngZonehasPendingMacrotaskshasPendingMicrotasks属性。如果其中任何一个为true,则protractor无法使用此页面。如果两者都为false,则可以继续下一步。

现在,当您知道页面可以使用browser.waitForAngularEnabled(true)与Protractor交互时,您需要为您的测试实施以下方法:

let login = async function (username, password) {
  await browser.waitForAngularEnabled(false);
  await browser.get(url);
  await $usernameInput.sendKeys(username);
  await $passwordInput.sendKeys(password);
  await $loginButton.click();
  // MOST IMPORTANTLY, YOU HAVE TO WAIT UNTIL YOUR APP FULLY LOADED
  await browser.wait(
    // whatever you need to wait for,
    timeout,
    'failure message'
  );
  // AND FINALLY
  await browser.waitForAngularEnabled(true);
}

我是说您不必使用此方法,我只是向您展示了实现结果所需遵循的操作顺序。
基本上,重点是在登录时确保非Angular登录页面已消失,并且您的Angular页面完全加载后再重新启用等待Angular。
您可以使用以下两种方法之一:
- 等待所有关键元素出现 - 或编写一个函数,该函数将返回return !obj[0]._ngZone.hasPendingMacrotasks && !obj[0]._ngZone.hasPendingMicrotasks,并将其传递给browser.wait

非常感谢您的帮助,这对调试非常有帮助。似乎在从Auth0网站(成功认证后)重定向后调用auth0-spa-js SDK的createAuth0Client方法(用于在Angular SPA应用程序上实现Auth0身份验证)时,hasPendingMacroTasks被设置为true并且永远不会重置。这会阻止像您上面解释的那样进行Protractor同步。 - cname87

0

我的回答是供大家了解的:

似乎在从Auth0站点(成功认证后)重定向后调用auth0-spa-js SDK的createAuth0Client方法(用于在Angular SPA应用程序上实现Auth0身份验证)时,hasPendingMacroTasks被设置为true并且永远不会被重置。这阻止了如上所述的Protractor同步。

我重新设计了我的auth0-spa-js实现,以匹配Auth0网站上最新的指南(使用Observable而不是async-await),但仍存在完全相同的问题。

我研究了一下 createAuth0Client 的功能:在重定向到应用程序之前,它从 Auth0 服务器获取了一个 JWT(令牌),当它被调用时缓存该令牌并设置定时器以删除该缓存条目。createAuth0Client 中的 setTimeout 调用被 Angular Zone 包装,并保持 hasPendingMacroTasks 为 true,这会阻止 Protractor 获取通知表明 Angular 已完成加载。定时器设置为令牌的生命周期,即在 Auth0 服务器上设置的设置,因此我通过将令牌超时设置为 3s 进行了测试,并等待了 5s,在我的 e2e 测试中 hasPendingMacroTasks 重置为 false 并成功同步了 Protractor,但是在计时器过期之后,Protractor 必须再次登录到 Auth0 服务器才能进行 API 调用,因此缩短计时器不是可行的解决方法。
我研究了在 Angular NgZone 外运行 createAuth0Client,但发现这极其困难,甚至是不可能的:
  1. 您需要访问已创建的Auth0客户端实例,一旦在NgZone中可用,您将再次看到hasPendingMacroTasks设置为true。
  2. 您不能仅仅将SDK方法(例如登录、注销)作为可用项返回到NgZone中,因为它们需要客户端实例上下文才能运行(我认为您无法在Angular区域外部保持状态(Auth0客户端实例)并在需要时访问它)。
  3. 每次需要运行SDK函数时,您不能在Angular区域外创建客户端实例并运行SDK函数,因为如果创建多个客户端实例,可能会出现错误。

1
这就是为什么我总是禁用 waitForAngular 的原因。我从来没有好运气让它正常工作。有太多的变量可能会阻止它正常工作。禁用它然后使用 ExpectedConditions 和一些自定义等待函数来确保页面已经准备好,这样更容易。 - tehbeardedone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接