Issue
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("post-1-cm")).tap();
await waitFor(element(by.id("comment-error")))
.not.toExist()
.withTimeout(5000);
The Button component:
<AppButton
onPress={() => toggleComments(true)}
disabled={disabled || submitting}
inverted
testID={`${testID}-cm`}
buttonStyles={styles.button}>
Code of the component that gets rendered when the button is clicked and toggleComments changes the showComments state to True:
{showComments && (
<CommentsModal
reloadPosts={props.reload}
visible={showComments}
blockUser={blockUser}
close={() => toggleComments(false)}
/>
)}
Solution
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(() => {
// ...long-running synchronous task...
element(by.id("post-1-cm")).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 && (
<CommentsModal
testID="CommentsModal"
reloadPosts={props.reload}
visible={showComments}
blockUser={blockUser}
close={() => toggleComments(false)}
/>
)}
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("post-1-cm")).tap();
// Wait for CommentsModal to appear
await waitFor(element(by.id("CommentsModal")))
.toBeVisible()
.withTimeout(5000);
await waitFor(element(by.id("comment-error")))
.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.
Answered By - VonC
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.