Repository: jestjs/jest (TypeScript)

Issue:
[Feature]: outputFile support for listTests option
### 🚀 Feature Proposal

Right now, the --listTests option will just write the list of tests to the console. My proposal is to use the --outputFile option along with the --listTests option to write the output to the file.

### Motivation

We wanted to use the list of tests in the custom sequencers. This feature will help to store the list in the file so that the sequencers can access it.

Note that this is just my usecase. There may be different use cases as well.

### Example

Pass `--outputFile=test-lists.json` along with `--listTests`

`yarn test --listTests --json --outputFile=test-lists.json`

### Pitch

The listTests option is a core feature of Jest and would be great if it support --outputFile as well
Support outputFile option for listTests option
## Summary

Added to Feature Proposal as well -> https://github.com/jestjs/jest/issues/14943

🚀 Feature Proposal
Right now, the --listTests option will just write the list of tests to the console. My proposal is to use the --outputFile option along with the --listTests option to write the output to the file.

Motivation
We wanted to use the list of tests in the custom sequencers. This feature will help to store the list in the file so that the sequencers can access it.

Note that this is just my usecase. There may be different use cases as well.

Example
Pass --outputFile=test-lists.json along with --listTests

yarn test --listTests --json --outputFile=test-lists.json



Hints:
Raised Pull Request here -> https://github.com/jestjs/jest/pull/14944
 <a href="https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/35323119/15062869/14944/#/?version=2"><img src="https://s3.amazonaws.com/cla-project-logo-prod/cla-not-signed.svg" alt="CLA Not Signed" align="left" height="28" width="328"></a><br/><br /><ul><li>:white_check_mark: login: manoraj / name: Manoraj K  (3493ace221bee9222de2cbdc7b9138927edc7e09, 29dc6551de167ff8ec8ec17e39ea118734db4e02, 04f2cc9f572b0451922178ad7851d45b1e503cb4)</li><li>:white_check_mark: login: SimenB / name: Simen Bekkhus  (1cd4dbd5bb608e656405dec42752f752d78c8894, bb4bb87e5dac25b4816fbcc9bc3e0e7ce31ad32d, 13b15e5c8e30e9fca940de62efee2102b177e767, 74ad24339fb17d00f9edc2c9d03127620ab99b03, 5e61b726aa0ed8f21523bf5ef683f4563abc2736)</li><li><a href='https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/35323119/15062869/14944/#/?version=2' target='_blank'>:x:</a> - login: @mkenchugonde . The commit (3d0a90d7c38d638d65e7fed25b9498a84ac7f626, d4841c1d3b3bb9c78fc323ba151e380cb45b8671, e004aac30652e7af7d859b22842687f57583c984, 9b3939dfe487611ba7f77ffd95593dd2f0169e25, fe67e6da4b017f44116933b1cac362432de04fb2) is not authorized under a signed CLA. <a href='https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/35323119/15062869/14944/#/?version=2' target='_blank'>Please click here to be authorized</a>. For further assistance with EasyCLA, <a href='https://jira.linuxfoundation.org/servicedesk/customer/portal/4' target='_blank'>please submit a support request ticket</a>.</li></ul>
### <span aria-hidden="true">✅</span> Deploy Preview for *jestjs* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 74ad24339fb17d00f9edc2c9d03127620ab99b03 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/jestjs/deploys/65f556ba501c7700086b8d91 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-14944--jestjs.netlify.app](https://deploy-preview-14944--jestjs.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTE0OTQ0LS1qZXN0anMubmV0bGlmeS5hcHAifQ.2DpsX0E5URg6cbBxEt83Tkf8An-k6Z0aamZt-pBebzU)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---

_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/jestjs/configuration/deploys#deploy-notifications)._
@mkenchugonde hello! 👋 could you sign the CLA? 🙂 
> @mkenchugonde hello! 👋 could you sign the CLA? 🙂

I am not sure how I ended up pushing commits from @mkenchugonde ( I intend to use my personal account @manoraj ). I have signed the CLA from @mkenchugonde, but it needs approval from the organization I guess. I will wait for one or two days before seeking help for next steps.
If it's all you, you should be able to just rebase and change author or squash the commits 

Patch:
diff --git a/packages/jest-core/src/runJest.ts b/packages/jest-core/src/runJest.ts
--- a/packages/jest-core/src/runJest.ts
+++ b/packages/jest-core/src/runJest.ts
@@ -214,13 +214,21 @@ export default async function runJest({
 
   if (globalConfig.listTests) {
     const testsPaths = [...new Set(allTests.map(test => test.path))];
-    /* eslint-disable no-console */
+    let testsListOutput;
+
     if (globalConfig.json) {
-      console.log(JSON.stringify(testsPaths));
+      testsListOutput = JSON.stringify(testsPaths);
+    } else {
+      testsListOutput = testsPaths.join('\n');
+    }
+
+    if (globalConfig.outputFile) {
+      const outputFile = path.resolve(process.cwd(), globalConfig.outputFile);
+      fs.writeFileSync(outputFile, testsListOutput, 'utf8');
     } else {
-      console.log(testsPaths.join('\n'));
+      // eslint-disable-next-line no-console
+      console.log(testsListOutput);
     }
-    /* eslint-enable */
 
     onComplete && onComplete(makeEmptyAggregatedTestResult());
     return;


Test patch:
diff --git a/e2e/__tests__/__snapshots__/listTests.test.ts.snap b/e2e/__tests__/__snapshots__/listTests.test.ts.snap
--- a/e2e/__tests__/__snapshots__/listTests.test.ts.snap
+++ b/e2e/__tests__/__snapshots__/listTests.test.ts.snap
@@ -1,5 +1,12 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`--listTests flag --outputFile flag causes tests to be saved in the file as JSON 1`] = `"["/MOCK_ABSOLUTE_PATH/e2e/list-tests/__tests__/dummy.test.js","/MOCK_ABSOLUTE_PATH/e2e/list-tests/__tests__/other.test.js"]"`;
+
+exports[`--listTests flag --outputFile flag causes tests to be saved in the file in different lines 1`] = `
+"/MOCK_ABSOLUTE_PATH/e2e/list-tests/__tests__/dummy.test.js
+/MOCK_ABSOLUTE_PATH/e2e/list-tests/__tests__/other.test.js"
+`;
+
 exports[`--listTests flag causes tests to be printed in different lines 1`] = `
 "/MOCK_ABSOLUTE_PATH/e2e/list-tests/__tests__/dummy.test.js
 /MOCK_ABSOLUTE_PATH/e2e/list-tests/__tests__/other.test.js"
diff --git a/e2e/__tests__/listTests.test.ts b/e2e/__tests__/listTests.test.ts
--- a/e2e/__tests__/listTests.test.ts
+++ b/e2e/__tests__/listTests.test.ts
@@ -6,6 +6,7 @@
  */
 
 import * as path from 'path';
+import * as fs from 'graceful-fs';
 import runJest from '../runJest';
 
 const testRootDir = path.resolve(__dirname, '..', '..');
@@ -36,4 +37,52 @@ describe('--listTests flag', () => {
       JSON.stringify(JSON.parse(stdout).map(normalizePaths).sort()),
     ).toMatchSnapshot();
   });
+
+  describe('--outputFile flag', () => {
+    const outputFilePath = path.resolve('.', 'test-lists.json');
+    afterAll(() => {
+      fs.unlinkSync(outputFilePath);
+    });
+    it('causes tests to be saved in the file as JSON', () => {
+      const {exitCode, stdout} = runJest('list-tests', [
+        '--listTests',
+        '--json',
+        '--outputFile',
+        outputFilePath,
+      ]);
+
+      expect(exitCode).toBe(0);
+      expect(stdout).toBe('');
+
+      const outputFileExists = fs.existsSync(outputFilePath);
+      expect(outputFileExists).toBe(true);
+
+      const outputFileContent = fs.readFileSync(outputFilePath, 'utf8');
+      expect(() => JSON.parse(outputFileContent)).not.toThrow();
+      expect(
+        JSON.stringify(
+          JSON.parse(outputFileContent).map(normalizePaths).sort(),
+        ),
+      ).toMatchSnapshot();
+    });
+
+    it('causes tests to be saved in the file in different lines', () => {
+      const {exitCode, stdout} = runJest('list-tests', [
+        '--listTests',
+        '--outputFile',
+        outputFilePath,
+      ]);
+
+      expect(exitCode).toBe(0);
+      expect(stdout).toBe('');
+
+      const outputFileExists = fs.existsSync(outputFilePath);
+      expect(outputFileExists).toBe(true);
+
+      const outputFileContent = fs.readFileSync(outputFilePath, 'utf8');
+      expect(
+        normalizePaths(outputFileContent).split('\n').sort().join('\n'),
+      ).toMatchSnapshot();
+    });
+  });
 });