Unable to do Parallel testing with Detox and Jest - react-native

I have seen similar questions on Stack Overflow but I don't feel like we're having the same issue and its been one year for the last question with no answers.
I have followed the documentation and all my tests are working fine, but when I open 4 simulators to try parallel testing only one of them reacts.
package.json
{
...
"detox": {
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/AppName/Build/Products/Debug-iphonesimulator/AppName.app",
"build": "xcodebuild -project ios/AppName.xcodeproj -scheme AppName -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"type": "ios.simulator",
"device": {
"type": "iPhone 11"
}
}
},
"test-runner": "jest --detectOpenHandles --verbose",
"runner-config": "tests/detox/jest.config.js"
}
}
tests/detox/jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
setupFilesAfterEnv: ['./init.ts']
};
init.ts
import { cleanup, init } from 'detox';
const adapter = require('detox/runners/jest/adapter');
const config = require('../../package.json').detox;
jest.setTimeout(90000);
jasmine.getEnv().addReporter(adapter);
beforeAll(async () => {
await init(config, { initGlobals: false });
}, 90000);
afterAll(async () => {
await adapter.afterAll();
await cleanup();
});
And here is the command I use to start tests, after having 4 IOS simulators running and ready
detox test -l warn -w 4 ./path-to-all-tests
Dependencies
MacOS catalina
xed version 11.4
detox: ^16.0.2
jest: ^24.9.0
ts-jest: ^24.1.0

--detectOpenHandles makes the test run synchronously.
from jest docs:
--detectOpenHandles
Attempt to collect and print open handles preventing Jest from exiting
cleanly. Use this in cases where you need to use --forceExit in order
for Jest to exit to potentially track down the reason. This implies
--runInBand, making tests run serially. Implemented using async_hooks. This option has a significant performance penalty and should only be
used for debugging.
https://jestjs.io/docs/cli
You must remove it to run tests in parallel

Related

Updates.channel is coming as null after setting up expo-updates

In my project I am using expo-sdk:43 along with expo-updates.
I have setup the channel property in eas.json file.
{
"cli": {
"version": ">= 0.52.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"channel":"dev"
},
"preview": {
"android": {
"buildType": "apk"
},
"channel":"preview"
},
"production": {}
},
"submit": {
"production": {}
}
}
I have tried to publish my updates through EAS update, but it is not working and the app is not receiving any update. I have tried to do an apk build for the application, and tried to get the output of Updates.Channel and it is outputting as undefined.
eas build -p android --profile --preview
eas update --branch preview --message "update"
But, when I build the app, the build is successful, in the eas logs I can see that it shows that channel property has also been configured.
Can someone please help what might be the possible issue in this case?
I have also tried to do the same steps with an expo-init command (But with expo sdk:47) and minimal app setup and it is working as expected.

Parametrize android package and ios bundle id with EAS on Bare workflow

I'm currently working on a expo project and I had the bundle configuration parametrized with environment variables declared on eas.json and used on app.config.ts.
Some like this
eas.json
{
"cli": {
"version": ">= 0.48.2"
},
"build": {
"develop": {
"distribution": "store",
"env": {
"ENVIRONMENT": "develop"
},
"releaseChannel": "dev-v1"
},
"production": {
"releaseChannel": "prod-v1",
"env": {
"ENVIRONMENT": "production"
},
"distribution": "store"
}
}
app.config.ts
//removed a lot of not relevant code
ios: {
supportsTablet: true,
bundleIdentifier: getBundleId(), // returns correct bundle id based on ENVIRONMENT variable.
buildNumber: '1.0.4',
},
android: {
adaptiveIcon: {
foregroundImage: './assets/adaptive-icon.png',
backgroundColor: '#FFFFFF',
},
package: getBundleId(), // same of ios BundleIdentifier
versionCode: 104,
},
But now, for some requirements I have to eject the project into the bare workflow, and because of that I'm getting the follow message when I want to generate a new build with eas (with eas build -p=ios --profile=production)
Specifying "ios.bundleIdentifier" in app.config.ts is deprecated for bare workflow projects.
EAS Build depends only on the value in the native code. Please remove the deprecated configuration.
Does exist any way to keep bundleIdentifier, packageId and also the app schema parametrized by environment after eject?

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './build/types' is not defined by "exports" in .../node_modules/jest-circus/package.json

I'm trying to setup detox for e2e testing for my React Native app using jest and jest-circus. I am able to build my iOS app with detox by running detox build --configuration ios but have been unable to run the sample firstTest.e2e.js test with detox run --configuration ios. I get the following error:
● Test suite failed to run
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './build/types' is not defined by "exports" in [project path]/node_modules/jest-circus/package.json
at Object.<anonymous> (../node_modules/detox/runners/jest-circus/listeners/DetoxCoreListener.js:11:25)
detox[92379] ERROR: [cli.js] Command failed: jest --config e2e/config.json --testNamePattern '^((?!:android:).)*$' --maxWorkers 1 e2e
My package.json has the following libraries installed:
"detox": "^18.12.1",
"jest": "^24.9.0",
"jest-circus": "^27.1.0",
My .detoxrc.json file looks like this:
{
"testRunner": "jest",
"runnerConfig": "e2e/config.json",
"apps": {
"ios": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/appname.app",
"build": "xcodebuild -workspace ios/appname.xcworkspace -scheme appname -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build EXCLUDED_ARCHS=arm64"
}
},
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 11"
}
}
},
"configurations": {
"ios": {
"device": "simulator",
"app": "ios"
}
}
}
and my e2e/config.json file looks like this:
{
"testEnvironment": "./environment",
"testRunner": "jest-circus/runner",
"testTimeout": 120000,
"testRegex": "\\.e2e\\.js$",
"reporters": ["detox/runners/jest/streamlineReporter"],
"verbose": true
}
This is a fairly old project, and I am already using jest for unit testing. I wonder if there might be some other configuration file interfering with my e2e config but can't seem to figure it out just yet. Any help is welcome!
you should try another jest-circus version:
"jest": "^26.0.1",
"jest-circus": "^26.0.1",

How to debug custom mocha test reporter?

I'm writing a mocha test reporter that I want to use for customized Cypress tests documentation.
Which is the right way to debug reporter code (maybe with intellij Idea)?
EDIT
I tried to debug using intellij Idea tools, running cypress (both open and run) in debug mode.
I also tried the IntelliJ Cypress plugin pro version that allow test debugging.
I can't stop in breakpoints.
So I'm trying at least to print some debug log but I can't see my logs anywere.
I couldn't make it work with Cypress, but I could do with Mocha in VSCode.
Working example here
Steps to debug:
Install ts-node and typescript for your project: npm i ts-node typescript --save-dev
Create custom-reporter.ts in your src folder with this content: (taken from https://mochajs.org/api/tutorial-custom-reporter.html and modified slightly )
import { reporters, Runner, Suite, Test } from 'mocha';
const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_SUITE_BEGIN, EVENT_SUITE_END } = Runner.constants;
// This reporter outputs test results, indenting two spaces per suite
export class CustomReporter extends reporters.Base {
private indents = 0;
constructor(runner: Runner) {
super(runner);
const stats = runner.stats;
runner
.once(EVENT_RUN_BEGIN, () => {
console.info('start');
})
.on(EVENT_SUITE_BEGIN, (suite: Suite) => {
this.increaseIndent();
})
.on(EVENT_SUITE_END, (suite: Suite) => {
this.decreaseIndent();
})
.on(EVENT_TEST_PASS, (test: Test) => {
// Test#fullTitle() returns the suite name(s)
// prepended to the test title
console.log(`${this.indent()}pass: ${test.fullTitle()}`);
})
.on(EVENT_TEST_FAIL, (test: Test, err: any) => {
console.log(`${this.indent()}fail: ${test.fullTitle()} - error: ${err.message}`);
})
.once(EVENT_RUN_END, () => {
console.log(`end: ${stats.passes}/${stats.passes + stats.failures} ok`);
});
}
private indent() {
return Array(this.indents).join(' ');
}
private increaseIndent() {
this.indents++;
}
private decreaseIndent() {
this.indents--;
}
}
We will compile custom-reporter.ts by ts-node at runtime, but we have to pass a .js to Mocha as a reporter.
Therefore we create index.js as follows and we export our reporter as follows:
module.exports = require("./src/custom-reporter").CustomReporter;
Add test script to your package.json if you want to run without debugging:
"scripts": {
"test": "mocha -r ts-node/register specs/*.spec.ts --reporter index"
},
Create .vscode/launch.json in your project root, and add the following code:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Mocha tests",
"cwd": "${workspaceRoot}",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"args": [
"-r",
"ts-node/register",
"--reporter",
"index",
"${workspaceFolder}/specs/**/*.spec.ts"
],
"protocol": "inspector",
"sourceMaps": true,
"console": "integratedTerminal"
},
]
}
Place some breakpoints in VSCode into src/custom-reporter.ts
In VSCode open the Run and Debug panel (Ctrl+Shift+D), select Debug Mocha tests and press the play button
This way you should be able to start the test running and hit your breakpoints in VSCode.
Cheers!

Detox using jest timeout error: "is assigned to undefined"

I'm trying to add detox using jest and jest-circus to my ReactNative app but I'm currently struggling making it work. Detox, jest and jest-circus have been added from scratch at the latest version.
When launching my test, after a successful build, it launches the simulator but hangs at the first test and stops with a timeout and a is assigned to undefined error. It seems like it doesn't find the simulator but it's correctly running and the uninstall / install app process correctly worked too.
Here's the code.
environment.js
const {
DetoxCircusEnvironment,
SpecReporter,
WorkerAssignReporter,
} = require('detox/runners/jest-circus')
class CustomDetoxEnvironment extends DetoxCircusEnvironment {
constructor(config) {
super(config)
// Can be safely removed, if you are content with the default value (=300000ms)
this.initTimeout = 30000
// 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
config.json for jest
{
"testEnvironment": "./environment",
"testRunner": "jest-circus/runner",
"testTimeout": 120000,
"testRegex": "\\.spec\\.js$",
"reporters": ["detox/runners/jest/streamlineReporter"],
"verbose": true
}
.detoxrc.json
{
"testRunner": "jest",
"runnerConfig": "test/tdd/config.json",
"specs": "test/tdd",
"configurations": {
"ios.sim.release": {
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/BetaSeriesNative.app",
"build": "export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/BetaSeriesNative.xcworkspace -UseNewBuildSystem=NO -scheme BetaSeriesNative -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet",
"type": "ios.simulator",
"device": {
"type": "iPhone 8"
},
"artifacts": {
"pathBuilder": "./test/tdd/detox.pathbuilder.ios.js"
}
}
}
}
login.spec.js test
describe('When on the incentive page', () => {
beforeEach(async () => {
await device.reloadReactNative()
})
it('it should open the login view', async () => {
await expect(element(by.id('LoginView'))).toBeVisible()
await expect(element(by.id('LoginView_button'))).toBeVisible()
await element(by.id('LoginView_button')).tap()
await expect(element(by.id('LoginView_form'))).toBeVisible()
})
})
Here's the error.
Thanks!
Ok, it seems like I found where the problem was coming from.
I added await device.disableSynchronization() and removed await device.reloadReactNative() in the beforeEach hook.
I also commented a lot of code in my app and I ended returning null in my first homepage view render.
I tried of course to just return null in my render without adding/removing those lines in my test, but without it, it still doesn't work.
Weird thing though. Sometimes it still hangs when launching the test and I still got the same error as before: is assigned to undefined. And when I relaunch it, sometimes it works like the screenshot below. I'd say it's working now maybe 2 out of 3. Maybe there is still some code in my app that is hanging the test and then times out, so I'll keep looking.
Anyway, I think a better error or maybe a warning that it might come from elsewhere, or the app itself, would be better to understand that kind of error. It's pretty unclear for now to know where the source of the error is coming from, even with debug and verbose enabled.
Hopefully it will help some of you guys.
Cheers.
P.S in the screenshot my test still fails because I didn't edit the test, but at least it's running the test alright :)