Detox: [v18] Detox seems to not be able to connect to Android Emulator; then the test hangs

Describe the bug

Hello, I am maintaining a big, and relatively complex, monorepo for my employer, and we’re trying to get Detox tests to run on Android. Yet, the app starts, but the test won’t. I have read anything and everything about the new synchronization, and read through several issues that sounded like ours.

First and foremost: This configuration works perfectly fine and without a hitch on iOS!

Basically it seems like Detox somehow cannot connect to the app properly. When I found out that react-native-splash-screen causes issues, I uninstalled the package completely (wanted to switch to react-native-bootsplash anyway) and removed every call of and reference to it that I could find.

I basically modeled the configuration after the “React Native with Jest” example found in this repository. I specifically created and AOSP emulator and set up quick boot just for the e2e tests. I added a file called network_security_config.xml inside android/app/src/main/res/xml with the following contents:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">10.0.2.2</domain>
        <domain includeSubdomains="true">localhost</domain>
    </domain-config>
</network-security-config>

Then I added android:networkSecurityConfig="@xml/network_security_config" to our android/app/src/main/AndroidManifest.xml (we don’t have a debug variant).

I am also executing the test command with the --debug-synchronization 500 option, but that doesn’t do anything. I don’t get any debug-sync information, as you can see in the logs.

As you also will be able to see in the logs, I am getting the debug message [DetoxServer.js/CANNOT_FORWARD] role=app not connected, cannot fw action a couple of times, in conjunction with the warning

detox[80162] WARN:  [Client.js/PENDING_REQUESTS] App has not responded to the network requests below:
  (id = -1000) isReady: {}

Unresponded network requests might result in timeout errors in Detox tests.

Here’s my the contents of my detox.config.js:

detox.config.js

module.exports = {
  testRunner: 'jest',
  runnerConfig: 'e2e/config.json',
  specs: 'e2e',
  configurations: {
    'android.emu.devdemo.release': {
      binaryPath:
        'app-cineorder/android/app/build/outputs/apk/devdemo/release/app-devdemo-release.apk',
      build:
        'yarn app-cineorder cobt set-up-app -v devdemo && cd app-cineorder/android && ./gradlew assembleDevdemoRelease assembleDevdemoReleaseAndroidTest -DtestBuildType=release && cd ../..',
      type: 'android.emulator',
      device: {
        avdName: 'Pixel_API_29_AOSP',
      },
      artifacts: {
        pathBuilder: './e2e/detox.pathbuilder.android.js',
      },
    },
    'ios.sim.devdemo.release': {
      binaryPath:
        'app-cineorder/ios/DerivedData/Build/Products/Release-iphonesimulator/CineOrder.app',
      build:
        'export PROJECT_ROOT="$PWD/app-cineorder" && yarn app-cineorder cobt set-up-app -v devdemo && yarn app-cineorder install-pods && xcodebuild -workspace app-cineorder/ios/CineOrder.xcworkspace -scheme devdemo -configuration Release -sdk iphonesimulator -derivedDataPath app-cineorder/ios/DerivedData',
      type: 'ios.simulator',
      device: {
        type: 'iPhone 12 Pro',
      },
      artifacts: {
        pathBuilder: './e2e/detox.pathbuilder.ios.js',
      },
    },
  },
};

Here’s basically the whole content of my e2e directory:

Expand
config.json
{
    "setupFilesAfterEnv": ["./setup.ts"],
    "testEnvironment": "./environment",
    "testRunner": "jest-circus/runner",
    "testTimeout": 120000,
    "testRegex": "\\.e2e\\.ts$",
    "transform": {
      "\\.tsx?$": "ts-jest"
    },
    "reporters": ["detox/runners/jest/streamlineReporter"],
    "verbose": true
}
detox.pathbuilder.android.js
const CustomPathBuilder = require('./detox.pathbuilder');
module.exports = ({rootDir}) => new CustomPathBuilder({rootDir, platform: 'android'});
detox.pathbuilder.ios.js
const CustomPathBuilder = require('./detox.pathbuilder');
module.exports = ({rootDir}) => new CustomPathBuilder({rootDir, platform: 'ios'});
detox.pathbuilder.js
const path = require('path');
const sanitizeFilename = require('sanitize-filename');

const SANITIZE_OPTIONS = {replacement: '_'};
const sanitize = (filename) => sanitizeFilename(filename, SANITIZE_OPTIONS);

class CustomPathBuilder {
  constructor({platform, rootDir}) {
    this.platform = platform;
    this.rootDir = rootDir;
  }

  buildPathForTestArtifact(artifactName, testSummary = null) {
    const fullName = (testSummary && testSummary.fullName) || '';
    const segments = [this.rootDir, this.platform, sanitize(fullName), sanitize(artifactName)];

    return path.join(...segments.filter(Boolean));
  }
}

module.exports = CustomPathBuilder;
environment.js
const {
  DetoxCircusEnvironment,
  SpecReporter,
  WorkerAssignReporter,
} = require('detox/runners/jest-circus');

class CustomDetoxEnvironment extends DetoxCircusEnvironment {
  constructor(config, context) {
    super(config, context);

    // Can be safely removed, if you are content with the default value (=300000ms)
    this.initTimeout = 300000;

    // This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
    // This is strictly optional.
    this.registerListeners({
      SpecReporter,
      WorkerAssignReporter,
    });
  }
}

module.exports = CustomDetoxEnvironment;
firstTest.e2e.ts
/* eslint-disable no-undef */
import {expect} from 'detox';

describe('test "change tabs"', () => {
  it('should have centerSelection screen', async () => {
    await expect(element(by.id('centerSelectionScreen'))).toBeVisible();
  });
});

export {};
setup.ts
/* eslint-disable no-undef */
beforeAll(async () => {
  await device.launchApp();
});

export {};

Okay, I hope someone can help me get to the bottom of this issue because I am completely out of ideas! Please let me know, if you need any further information/file contents/whatever about this. Thanks in advance!

Steps To Reproduce

  • I have tested this issue on the latest Detox release and it still reproduces

This is rather difficult because it might be specific to our project. But in general it’s

  1. Set up Detox exactly the way it’s described in the documentation.
  2. Create an AOSP emulator and set up quick boot
  3. Create the necessary configurations for building and running the test
  4. Build the apps and run the test

Expected behavior

The test starts.

Detox Trace-Logs

I provided Detox logs as part of the attached zip file.

Device logs (adb logcat)

I provided Logcat logs as part of the attached zip file.

Environment (please complete the following information):

  • Detox: 18.2.2
  • React Native: 0.63.4
  • Node: 15.4.0
  • Device: Android Emulator
  • OS: API-29 AOSP
  • Test-runner (select one): jest-circus

Attachments:

Edits

  • Edit no. 1: In the meantime, I updated our Detox from v18.2.1 to v18.2.2 and removed the unused e2e/setup.js. The problem still prevails.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 24
  • Comments: 54

Most upvoted comments

In my case i tried both with detox@17 and detox@18 but the physical devices and the emulator still hang after launch.

In my home screen’s app i use @react-native-community/masked-view, this library on android is causing low fps and Detox to stop work, the library seems to be moved under @react-native-masked-view/masked-view where the fix has just been released but unfortunately I cannot substitute the @react-native-community version because it’s included as a peer dependencies in react-navigation/stack.

Patching @react-native-community/masked-view like this PR solved for me.

Example patch that work on yarn

Other ref: 1, 2

@TheWirv Make sure that you added DetoxTest.java and it has the correct path: android/app/src/androidTest/java/com/example/DetoxTest.java

Any solution? In iOS simulator working fine. App not launch in android emulator throw error Detox can’t seems to connect to the test app!

after migration Detox from 17 to 18 our E2E tests on Android are failed

in debug looking it seems that detox server send messages but emulator not reacted to them ((

@WilGatlin @gabrielmoncea would you be willing to try to reproduce your issues on our ready-to-go repro project, Detox Template?

@PawanP1808 Android studio is not a part of the game when running Detox, I’m afraid.

I can confirm the patch solution posted by @franek-dev has fixed my issue as well.

In my case the problem was:

detox[24911] TRACE: [ARTIFACTS_LIFECYCLE] artifactsManager.onHookFailure({
  error: DetoxRuntimeError: Failed to run application on the device
  
  HINT: Most likely, your tests have timed out and called detox.cleanup() while it was waiting for "ready" message (over WebSocket) from the instrumentation process.
      at MonitoredInstrumentation._getInstrumentationCrashError (/Volumes/simpleTechs/universum-app/node_modules/detox/src/devices/drivers/android/tools/MonitoredInstrumentation.js:68:12)
      at MonitoredInstrumentation._rejectPendingCrashPromise (/Volumes/simpleTechs/universum-app/node_modules/detox/src/devices/drivers/android/tools/MonitoredInstrumentation.js:56:37)
      at MonitoredInstrumentation._onInstrumentationTerminated (/Volumes/simpleTechs/universum-app/node_modules/detox/src/devices/drivers/android/tools/MonitoredInstrumentation.js:51:10)
      at Instrumentation._onTerminated (/Volumes/simpleTechs/universum-app/node_modules/detox/src/devices/drivers/android/tools/Instrumentation.js:52:18)
      at processTicksAndRejections (internal/process/task_queues.js:97:5),
  hook: 'beforeAll'
})

After applying the patch on @react-native-community/masked-view@0.1.10 it is gone.

Thank you for posting this.

PS.: I also upgraded to "detox": "^18.12.0", and added --debug-synchronization 500 but these might not be relevant.

My 2 cents are that you can’t run more than 1 emulator unless you pass in the -read-only argument to all running emulators. Detox does that for you if you enable parallel-testing (e.g. --workers 2), and only for newly launched emulators.

I saw this and already made sure to delete the .lock files.

I am launching a new emulator instance from detox (Closing the previous one) I am looking for -read-only on the trace and it does not appear.

@d4vidi ~Sorry, I had seen it.~ Thanks a lot.

Logs, emulator totally new, (with android-studio)

Edited

@npoussu I’m looking into your case. I was not aware, personally, of this way of initializing RN (that you’ve applied):

   protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
...
                .addPackage(new MainReactPackage())
                .build();

        mReactRootView.startReactApplication(mReactInstanceManager, "AroundMe", null);
        setContentView(mReactRootView);
    }

I’m looking into whether in this case Detox’ listener of RN loading becomes futile. In any case, I do see that in your code, you manually add MainReactPackage to the instance manager. I think that should be enough. Are you absolutely sure that it is also required in MainApplication.getPackages()?

**@npoussu if you could push your Detox-support code to a branch or whatever, that would be very helpful 🙏🏻 **

@npoussu thanks so much for posting this. I am nonetheless falling short of understanding how your app could run at all without these changes, regardless of Detox. Am I missing something?

@TheWirv this case is highly intriguing and I would really like to get to the bottom of it.

Would you mind collecting the logs again - now that the suite runs with a longer time-out? Simply because when looking into your logs, the only thing I see that can account for failure is that the app didn’t go idle quickly enough. I’m concerned that due to the relatively long time it takes for the app to settle down, this time-out issue could be shadowing other issues.

@mackbrowne @npoussu I’d highly appreciate anyone willing to set up a very light demo app where this is reproduced 🙏🏻