Test is failing in Detox when the layout is overlayed.

huangapple go评论74阅读模式
英文:

Test is failing in Detox when the layout is overlayed

问题

Detox在测试点击按钮时出现以下错误,点击动作生效,但由于状态更改导致组件重新渲染,测试奇怪地希望再次点击按钮,但由于按钮不在视图中,测试失败。

测试失败:等待
[com.wix.detox.reactnative.idlingresources.AnimatedModuleIdlingResource]
变为空闲已超时

我的测试脚本:

await element(by.id("post-1-cm")).tap();

await waitFor(element(by.id("comment-error")))
  .not.toExist()
  .withTimeout(5000);

按钮组件:

<AppButton
  onPress={() => toggleComments(true)}
  disabled={disabled || submitting}
  inverted
  testID={`${testID}-cm`}
  buttonStyles={styles.button}>

当点击按钮并且toggleComments更改showComments状态为True时,渲染的组件代码:

{showComments && (
  <CommentsModal
    reloadPosts={props.reload}
    visible={showComments}
    blockUser={blockUser}
    close={() => toggleComments(false)}
  />
)}
英文:

I get the following error in Detox when the test clicks on a button, the click works but after the component re-renders because of a state change, the test strangely wants to click on the button again but since the button is not in the view, the test fails.
> Test Failed: Wait for
> [com.wix.detox.reactnative.idlingresources.AnimatedModuleIdlingResource]
> to become idle timed out

My test script:

await element(by.id(&quot;post-1-cm&quot;)).tap();

await waitFor(element(by.id(&quot;comment-error&quot;)))
  .not.toExist()
  .withTimeout(5000);

The Button component:

&lt;AppButton
          onPress={() =&gt; toggleComments(true)}
          disabled={disabled || submitting}
          inverted
          testID={`${testID}-cm`}
          buttonStyles={styles.button}&gt;

Code of the component that gets rendered when the button is clicked and toggleComments changes the showComments state to True:

  {showComments &amp;&amp; (
    &lt;CommentsModal
      reloadPosts={props.reload}
      visible={showComments}
      blockUser={blockUser}
      close={() =&gt; toggleComments(false)}
    /&gt;
  )}

答案1

得分: 1

Detox android/espressoapi/UIDevice.js 中有一个 waitForIdle(element) 函数。

但如果这不适用于您的用例,您可以尝试将测试脚本包装在 InteractionManager 中:

InteractionManager.runAfterInteractions(() => {
  // ...长时间运行的同步任务...
  element(by.id("post-1-cm")).tap();
});

这样,您可以在运行测试之前首先检查是否足够让您的 AnimatedModuleIdlingResource 变为空闲状态。

由于在 Detox 测试文件中导入 InteractionManager 复杂或不可能,因为 InteractionManager 是 React Native API 的一部分,旨在用于应用程序代码,而不是测试代码,您可能需要另一种方法。

我了解 Detox 测试旨在与应用程序的 UI 进行交互并模拟用户操作。它们在单独的 JavaScript 环境中运行,没有直接访问应用程序代码中使用的 React Native API。

因此,您可能需要等待 CommentsModal 组件出现,然后再检查按钮不存在。这应该有助于确保测试在视图中不存在按钮时不会再次尝试点击按钮,从而避免错误。

如果可能的话,请尝试在代码中为 CommentsModal 组件添加一个 testID

{showComments && (
  <CommentsModal
    testID="CommentsModal"
    reloadPosts={props.reload}
    visible={showComments}
    blockUser={blockUser}
    close={() => toggleComments(false)}
  />
)}

这将允许脚本等待 CommentsModal 出现,然后再检查按钮不存在。

await element(by.id("post-1-cm")).tap();

// 等待CommentsModal出现
await waitFor(element(by.id("CommentsModal")))
  .toBeVisible()
  .withTimeout(5000);

await waitFor(element(by.id("comment-error")))
  .not.toExist()
  .withTimeout(5000);

如果这还不够,如讨论中所见,您可以尝试 禁用同步

可以通过 await device.disableSynchronization(); 进行禁用。
或者使用启动参数,例如 -detoxEnableSynchronization NO

OP 确认 await device.disableSynchronization(); 已足够。

英文:

Detox android/espressoapi/UIDevice.js does have a waitForIdle(element) function.

But if this does not apply to your use case, you might try and wrap your test script in a InteractionManager:

InteractionManager.runAfterInteractions(() =&gt; {
  // ...long-running synchronous task...
  element(by.id(&quot;post-1-cm&quot;)).tap();
});

That way, you can check if that is enough to allow your AnimatedModuleIdlingResource to become idle first, before running your rest.


Since importing InteractionManager in the Detox test file is complex/impossible, because InteractionManager is part of the React Native API and is intended for use within the application code, not the test code, you might need another approach.

I understand Detox tests are designed to interact with the application's UI and simulate user actions. They run in a separate JavaScript environment and don't have direct access to the React Native APIs that are used in the application code.

So you might have to wait for the CommentsModal component to appear before checking for the non-existence of the button. This should help ensure that the test doesn't try to click the button again when it's not in the view, thus avoiding the error.

If possible, try and add a testID to the CommentsModal component in your code:

{showComments &amp;&amp; (
  &lt;CommentsModal
    testID=&quot;CommentsModal&quot;
    reloadPosts={props.reload}
    visible={showComments}
    blockUser={blockUser}
    close={() =&gt; toggleComments(false)}
  /&gt;
)}

That would allow for the script to wait for the CommentsModal to appear before checking for the non-existence of the button.

await element(by.id(&quot;post-1-cm&quot;)).tap();

// Wait for CommentsModal to appear
await waitFor(element(by.id(&quot;CommentsModal&quot;)))
  .toBeVisible()
  .withTimeout(5000);

await waitFor(element(by.id(&quot;comment-error&quot;)))
  .not.toExist()
  .withTimeout(5000);

If this is not enough, as seen in the discussion, you can try and try and disable synchronization.

Either through await device.disableSynchronization();
Or with a launch parameter like -detoxEnableSynchronization NO.

The OP confirms await device.disableSynchronization(); was enough.

huangapple
  • 本文由 发表于 2023年4月17日 20:47:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76035323.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定