Skip to content

Commit 008f00b

Browse files
Ma-hawajsheremet-va
andauthoredAug 29, 2024··
feat(cli): Extend existing list command to output only a list of file names (#6392)
Co-authored-by: Vladimir <sleuths.slews0s@icloud.com>
1 parent 122e4fe commit 008f00b

File tree

7 files changed

+183
-12
lines changed

7 files changed

+183
-12
lines changed
 

‎docs/guide/cli.md

+11
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,17 @@ vitest list filename.spec.ts -t="some-test" --json=./file.json
8686

8787
If `--json` flag doesn't receive a value, it will output the JSON into stdout.
8888

89+
You also can pass down `--filesOnly` flag to print the test files only:
90+
91+
```bash
92+
vitest list --filesOnly
93+
```
94+
95+
```txt
96+
tests/test1.test.ts
97+
tests/test2.test.ts
98+
```
99+
89100
## Options
90101

91102
::: tip

‎packages/vitest/LICENSE.md

+29
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,35 @@ Repository: sindresorhus/p-locate
12351235
12361236
---------------------------------------
12371237

1238+
## package-manager-detector
1239+
License: MIT
1240+
By: Anthony Fu
1241+
Repository: git+https://github.com/antfu-collective/package-manager-detector.git
1242+
1243+
> MIT License
1244+
>
1245+
> Copyright (c) 2020-PRESENT Anthony Fu <https://github.com/antfu>
1246+
>
1247+
> Permission is hereby granted, free of charge, to any person obtaining a copy
1248+
> of this software and associated documentation files (the "Software"), to deal
1249+
> in the Software without restriction, including without limitation the rights
1250+
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1251+
> copies of the Software, and to permit persons to whom the Software is
1252+
> furnished to do so, subject to the following conditions:
1253+
>
1254+
> The above copyright notice and this permission notice shall be included in all
1255+
> copies or substantial portions of the Software.
1256+
>
1257+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1258+
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1259+
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1260+
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1261+
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1262+
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1263+
> SOFTWARE.
1264+
1265+
---------------------------------------
1266+
12381267
## picomatch
12391268
License: MIT
12401269
By: Jon Schlinkert

‎packages/vitest/src/node/cli/cac.ts

+16-10
Original file line numberDiff line numberDiff line change
@@ -300,24 +300,30 @@ async function collect(mode: VitestRunMode, cliFilters: string[], options: CliOp
300300
catch {}
301301

302302
try {
303-
const { prepareVitest, processCollected } = await import('./cli-api')
303+
const { prepareVitest, processCollected, outputFileList } = await import('./cli-api')
304304
const ctx = await prepareVitest(mode, {
305305
...normalizeCliOptions(options),
306306
watch: false,
307307
run: true,
308308
})
309+
if (!options.filesOnly) {
310+
const { tests, errors } = await ctx.collect(cliFilters.map(normalize))
311+
312+
if (errors.length) {
313+
console.error('\nThere were unhandled errors during test collection')
314+
errors.forEach(e => console.error(e))
315+
console.error('\n\n')
316+
await ctx.close()
317+
return
318+
}
309319

310-
const { tests, errors } = await ctx.collect(cliFilters.map(normalize))
311-
312-
if (errors.length) {
313-
console.error('\nThere were unhandled errors during test collection')
314-
errors.forEach(e => console.error(e))
315-
console.error('\n\n')
316-
await ctx.close()
317-
return
320+
processCollected(ctx, tests, options)
321+
}
322+
else {
323+
const files = await ctx.listFiles(cliFilters.map(normalize))
324+
outputFileList(files, options)
318325
}
319326

320-
processCollected(ctx, tests, options)
321327
await ctx.close()
322328
}
323329
catch (e) {

‎packages/vitest/src/node/cli/cli-api.ts

+48-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable no-console */
22

33
import { mkdirSync, writeFileSync } from 'node:fs'
4-
import { dirname, resolve } from 'pathe'
4+
import { dirname, relative, resolve } from 'pathe'
55
import type { UserConfig as ViteUserConfig } from 'vite'
66
import type { File, Suite, Task } from '@vitest/runner'
77
import { CoverageProviderMap } from '../../integrations/coverage'
@@ -12,6 +12,7 @@ import type { Vitest, VitestOptions } from '../core'
1212
import { FilesNotFoundError, GitNotFoundError } from '../errors'
1313
import { getNames, getTests } from '../../utils'
1414
import type { UserConfig, VitestEnvironment, VitestRunMode } from '../types/config'
15+
import type { WorkspaceSpec } from '../pool'
1516

1617
export interface CliOptions extends UserConfig {
1718
/**
@@ -26,6 +27,10 @@ export interface CliOptions extends UserConfig {
2627
* Output collected tests as JSON or to a file
2728
*/
2829
json?: string | boolean
30+
/**
31+
* Output collected test files only
32+
*/
33+
filesOnly?: boolean
2934
}
3035

3136
/**
@@ -184,6 +189,48 @@ export function processCollected(ctx: Vitest, files: File[], options: CliOptions
184189
return formatCollectedAsString(files).forEach(test => console.log(test))
185190
}
186191

192+
export function outputFileList(files: WorkspaceSpec[], options: CliOptions) {
193+
if (typeof options.json !== 'undefined') {
194+
return outputJsonFileList(files, options)
195+
}
196+
197+
return formatFilesAsString(files, options).map(file => console.log(file))
198+
}
199+
200+
function outputJsonFileList(files: WorkspaceSpec[], options: CliOptions) {
201+
if (typeof options.json === 'boolean') {
202+
return console.log(JSON.stringify(formatFilesAsJSON(files), null, 2))
203+
}
204+
if (typeof options.json === 'string') {
205+
const jsonPath = resolve(options.root || process.cwd(), options.json)
206+
mkdirSync(dirname(jsonPath), { recursive: true })
207+
writeFileSync(jsonPath, JSON.stringify(formatFilesAsJSON(files), null, 2))
208+
}
209+
}
210+
211+
function formatFilesAsJSON(files: WorkspaceSpec[]) {
212+
return files.map((file) => {
213+
const result: any = {
214+
file: file.moduleId,
215+
}
216+
217+
if (file.project.name) {
218+
result.projectName = file.project.name
219+
}
220+
return result
221+
})
222+
}
223+
224+
function formatFilesAsString(files: WorkspaceSpec[], options: CliOptions) {
225+
return files.map((file) => {
226+
let name = relative(options.root || process.cwd(), file.moduleId)
227+
if (file.project.name) {
228+
name = `[${file.project.name}] ${name}`
229+
}
230+
return name
231+
})
232+
}
233+
187234
function processJsonOutput(files: File[], options: CliOptions) {
188235
if (typeof options.json === 'boolean') {
189236
return console.log(JSON.stringify(formatCollectedAsJSON(files), null, 2))

‎packages/vitest/src/node/cli/cli-config.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ export const cliOptionsConfig: VitestCLIOptions = {
795795
outputJson: null,
796796
json: null,
797797
provide: null,
798+
filesOnly: null,
798799
}
799800

800801
export const benchCliOptionsConfig: Pick<
@@ -813,10 +814,13 @@ export const benchCliOptionsConfig: Pick<
813814

814815
export const collectCliOptionsConfig: Pick<
815816
VitestCLIOptions,
816-
'json'
817+
'json' | 'filesOnly'
817818
> = {
818819
json: {
819820
description: 'Print collected tests as JSON or write to a file (Default: false)',
820821
argument: '[true/path]',
821822
},
823+
filesOnly: {
824+
description: 'Print only test files with out the test cases',
825+
},
822826
}

‎packages/vitest/src/node/core.ts

+8
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,14 @@ export class Vitest {
374374
}
375375
}
376376

377+
async listFiles(filters?: string[]) {
378+
const files = await this.filterTestsBySource(
379+
await this.globTestFiles(filters),
380+
)
381+
382+
return files
383+
}
384+
377385
async start(filters?: string[]) {
378386
this._onClose = []
379387

‎test/cli/test/list.test.ts

+66
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,22 @@ test('correctly outputs json', async () => {
5858
expect(exitCode).toBe(0)
5959
})
6060

61+
test('correctly outputs files only json', async () => {
62+
const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json', '--filesOnly')
63+
expect(relative(stdout)).toMatchInlineSnapshot(`
64+
"[
65+
{
66+
"file": "<root>/fixtures/list/basic.test.ts"
67+
},
68+
{
69+
"file": "<root>/fixtures/list/math.test.ts"
70+
}
71+
]
72+
"
73+
`)
74+
expect(exitCode).toBe(0)
75+
})
76+
6177
test('correctly saves json', async () => {
6278
const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json=./list.json')
6379
onTestFinished(() => {
@@ -96,6 +112,26 @@ test('correctly saves json', async () => {
96112
expect(exitCode).toBe(0)
97113
})
98114

115+
test('correctly saves files only json', async () => {
116+
const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json=./list.json', '--filesOnly')
117+
onTestFinished(() => {
118+
rmSync('./fixtures/list/list.json')
119+
})
120+
const json = readFileSync('./fixtures/list/list.json', 'utf-8')
121+
expect(stdout).toBe('')
122+
expect(relative(json)).toMatchInlineSnapshot(`
123+
"[
124+
{
125+
"file": "<root>/fixtures/list/basic.test.ts"
126+
},
127+
{
128+
"file": "<root>/fixtures/list/math.test.ts"
129+
}
130+
]"
131+
`)
132+
expect(exitCode).toBe(0)
133+
})
134+
99135
test('correctly filters by file', async () => {
100136
const { stdout, exitCode } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list')
101137
expect(stdout).toMatchInlineSnapshot(`
@@ -106,6 +142,15 @@ test('correctly filters by file', async () => {
106142
expect(exitCode).toBe(0)
107143
})
108144

145+
test('correctly filters by file when using --filesOnly', async () => {
146+
const { stdout, exitCode } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--filesOnly')
147+
expect(stdout).toMatchInlineSnapshot(`
148+
"math.test.ts
149+
"
150+
`)
151+
expect(exitCode).toBe(0)
152+
})
153+
109154
test('correctly prints project name in basic report', async () => {
110155
const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--config=./custom.config.ts')
111156
expect(stdout).toMatchInlineSnapshot(`
@@ -115,6 +160,14 @@ test('correctly prints project name in basic report', async () => {
115160
`)
116161
})
117162

163+
test('correctly prints project name in basic report when using --filesOnly', async () => {
164+
const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--config=./custom.config.ts', '--filesOnly')
165+
expect(stdout).toMatchInlineSnapshot(`
166+
"[custom] math.test.ts
167+
"
168+
`)
169+
})
170+
118171
test('correctly prints project name and locations in json report', async () => {
119172
const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--json', '--config=./custom.config.ts')
120173
expect(relative(stdout)).toMatchInlineSnapshot(`
@@ -142,6 +195,19 @@ test('correctly prints project name and locations in json report', async () => {
142195
`)
143196
})
144197

198+
test('correctly prints project name in json report when using --filesOnly', async () => {
199+
const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--json', '--config=./custom.config.ts', '--filesOnly')
200+
expect(relative(stdout)).toMatchInlineSnapshot(`
201+
"[
202+
{
203+
"file": "<root>/fixtures/list/math.test.ts",
204+
"projectName": "custom"
205+
}
206+
]
207+
"
208+
`)
209+
})
210+
145211
test('correctly filters by test name', async () => {
146212
const { stdout } = await runVitestCli('list', '-t=inner', '-r=./fixtures/list')
147213
expect(stdout).toMatchInlineSnapshot(`

0 commit comments

Comments
 (0)
Please sign in to comment.