Repository: wix/Detox (js)

Issue:
Pick tests by the name
**Problem**
Detox allows run specific tests by passing a path/fileName only. E.g. `detox test e2e/testSuite.spec.js`.
There is no way to run a specific test list from the suite. E.g. `testSuite.spec.js` script is
```
it('test name 1', () => {...});
it('test name 2', () => {...});
it('test name 3, () => {...});
it('test name 4, () => {...});
...
```
I want to run `test name 1` and `test name 3` tests only (I'm not talking about development stage where I can use `it.only`)

**Usage**
I have a huge number of e2e tests that take a lot of time. I can't run all of them on every PR/commit coz it will significantly increase development cycle time. Instead, I want to create a specific list of the tests that will run (kind of sanity suite). 

**Solution**
If Detox runs with Jest, I can run a specific list of the tests by their name using `--testNamePattern` (https://jestjs.io/docs/en/cli#--testnamepatternregex). Currently, it's occupied by a regexp that Detox sets `--testNamePattern=^((?!:android:).)*$` for iOS ad `--testNamePattern=^((?!:ios:).)*$` for Android, so the value I pass is ignored.

Pull request description:
fix(jest): allow `-t, --testNamePattern` overriding
**Description:**

Resolves #1881.

E.g.:

```bash
detox test -c ios.sim.release -t hello.*tap
```

as expected, translates to:

```bash
configuration="ios.sim.release" ... jest ... --testNamePattern "hello.*tap"
```

instead of the former:

```bash
configuration="ios.sim.release" ... jest ...  --testNamePattern '^((?!:android:).)*$'  --testNamePattern "hello.*tap"
```

/cc @andy-zy 

Patch:
diff --git a/detox/local-cli/utils/splitArgv.js b/detox/local-cli/utils/splitArgv.js
index a83ccb9f8..af8c5039c 100644
--- a/detox/local-cli/utils/splitArgv.js
+++ b/detox/local-cli/utils/splitArgv.js
@@ -117,7 +117,16 @@ function splitMochaArgv(argv) {
 }
 
 function splitJestArgv(argv) {
-  return disengageBooleanArgs(argv, getJestBooleanArgs());
+  return realiasJestArgv(disengageBooleanArgs(argv, getJestBooleanArgs()));
+}
+
+function realiasJestArgv({ specs, passthrough }) {
+  if (passthrough.hasOwnProperty('t')) {
+    passthrough.testNamePattern = passthrough.t;
+    delete passthrough.t;
+  }
+
+  return { specs, passthrough };
 }
 
 module.exports = {


Test patch:
diff --git a/detox/local-cli/test.js b/detox/local-cli/test.js
index 3de904db6..1fb83bcce 100644
--- a/detox/local-cli/test.js
+++ b/detox/local-cli/test.js
@@ -24,7 +24,6 @@ module.exports.handler = async function test(argv) {
   const prepareArgs = choosePrepareArgs({
     cliConfig,
     runner,
-    platform,
     detoxArgs,
   });
 
@@ -49,7 +48,7 @@ module.exports.handler = async function test(argv) {
   await runTestRunnerWithRetries(forwardedArgs, retries);
 };
 
-function choosePrepareArgs({ cliConfig, detoxArgs, runner, platform }) {
+function choosePrepareArgs({ cliConfig, detoxArgs, runner }) {
   if (runner === 'mocha') {
     if (hasMultipleWorkers(cliConfig)) {
       log.warn('Cannot use -w, --workers. Parallel test execution is only supported with iOS and Jest');
@@ -132,14 +131,14 @@ function prepareJestArgs({ cliConfig, runnerArgs, runnerConfig, platform }) {
   const platformFilter = getPlatformSpecificString(platform);
 
   return {
-    argv: {
+    argv: _.omitBy({
       color: !cliConfig.noColor && undefined,
       config: runnerConfig.runnerConfig /* istanbul ignore next */ || undefined,
       testNamePattern: platformFilter ? shellQuote(`^((?!${platformFilter}).)*$`) : undefined,
       maxWorkers: cliConfig.workers,
 
       ...passthrough,
-    },
+    }, _.isUndefined),
 
     env: _.omitBy({
       ..._.pick(cliConfig, _.compact([
diff --git a/detox/local-cli/test.test.js b/detox/local-cli/test.test.js
index 40959d754..9dd1970e4 100644
--- a/detox/local-cli/test.test.js
+++ b/detox/local-cli/test.test.js
@@ -403,6 +403,22 @@ describe('CLI', () => {
       expect(cliCall().command).toContain('--maxWorkers 2');
     });
 
+    test.each([['-w'], ['--workers']])('%s <value> should be replaced with --maxWorkers <value>', async (__workers) => {
+      await run(`${__workers} 2 --maxWorkers 3`);
+
+      const { command } = cliCall();
+      expect(command).toContain('--maxWorkers 3');
+      expect(command).not.toContain('--maxWorkers 2');
+    });
+
+    test.each([['-w'], ['--workers']])('%s <value> can be overriden by a later value', async (__workers) => {
+      await run(`${__workers} 2 ${__workers} 3`);
+
+      const { command } = cliCall();
+      expect(command).toContain('--maxWorkers 3');
+      expect(command).not.toContain('--maxWorkers 2');
+    });
+
     test.each([['-w'], ['--workers']])('%s <value> should not warn anything for iOS', async (__workers) => {
       singleConfig().type = 'ios.simulator';
       await run(`${__workers} 2`);
@@ -435,6 +451,14 @@ describe('CLI', () => {
       expect(cliCall().command).not.toContain('--testNamePattern');
     });
 
+    test.each([['-t'], ['--testNamePattern']])('should override --testNamePattern if a custom %s value is passed', async (__testNamePattern) => {
+      await run(`${__testNamePattern} customPattern`);
+      const { command } = cliCall();
+
+      expect(command).not.toMatch(/--testNamePattern .*(ios|android)/);
+      expect(command).toMatch(/--testNamePattern customPattern($| )/);
+    });
+
     test('--jest-report-specs, by default, should be true, as environment variable', async () => {
       await run();
       expect(cliCall().env).toEqual(expect.objectContaining({ reportSpecs: true }));