diff --git a/package.json b/package.json index 3a3a1ac..2d9b420 100644 --- a/package.json +++ b/package.json @@ -84,10 +84,10 @@ "run", "debug" ], - "description": "Enable desired codeLens, possible value : 'run', 'debug', 'watch', 'coverage'. Defaults to ['run', 'debug'] ", + "description": "Enable desired codeLens, possible value : 'run', 'debug', 'watch', 'coverage', 'current-test-coverage'. Defaults to ['run', 'debug'] ", "items": { "type": "string", - "description": "Either 'run', 'debug', 'watch', 'coverage'" + "description": "Either 'run', 'debug', 'watch', 'coverage', 'current-test-coverage'" }, "scope": "window" }, diff --git a/src/JestRunnerCodeLensProvider.ts b/src/JestRunnerCodeLensProvider.ts index 9e69976..edb571b 100644 --- a/src/JestRunnerCodeLensProvider.ts +++ b/src/JestRunnerCodeLensProvider.ts @@ -8,12 +8,14 @@ function getCodeLensForOption(range: Range, codeLensOption: CodeLensOption, full debug: 'Debug', watch: 'Run --watch', coverage: 'Run --coverage', + 'current-test-coverage': 'Run --collectCoverageFrom (target file/dir)' }; const commandMap: Record = { run: 'extension.runJest', debug: 'extension.debugJest', watch: 'extension.watchJest', coverage: 'extension.runJestCoverage', + 'current-test-coverage': 'extension.runJestCurrentTestCoverage' }; return new CodeLens(range, { arguments: [fullTestName], diff --git a/src/extension.ts b/src/extension.ts index 285a04d..e43eec5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -24,6 +24,13 @@ export function activate(context: vscode.ExtensionContext): void { } ); + const runJestCurrentTestCoverage = vscode.commands.registerCommand( + 'extension.runJestCurrentTestCoverage', + async (argument: Record | string) => { + return jestRunner.runCurrentTest(argument, ['--coverage'], true); + } + ); + const runJestPath = vscode.commands.registerCommand('extension.runJestPath', async (argument: vscode.Uri) => jestRunner.runTestsOnPath(argument.path) ); @@ -71,6 +78,7 @@ export function activate(context: vscode.ExtensionContext): void { } context.subscriptions.push(runJest); context.subscriptions.push(runJestCoverage); + context.subscriptions.push(runJestCurrentTestCoverage); context.subscriptions.push(runJestAndUpdateSnapshots); context.subscriptions.push(runJestFile); context.subscriptions.push(runJestPath); diff --git a/src/jestRunner.ts b/src/jestRunner.ts index 3597673..1d52fd5 100644 --- a/src/jestRunner.ts +++ b/src/jestRunner.ts @@ -1,4 +1,5 @@ import * as vscode from 'vscode'; +import * as fs from 'fs'; import { JestRunnerConfig } from './jestRunnerConfig'; import { parse } from './parser'; @@ -7,6 +8,8 @@ import { escapeRegExpForPath, escapeSingleQuotes, findFullTestName, + getFileName, + getDirName, normalizePath, pushMany, quote, @@ -50,7 +53,11 @@ export class JestRunner { await this.runExternalNativeTerminalCommand(this.commands); } - public async runCurrentTest(argument?: Record | string, options?: string[]): Promise { + public async runCurrentTest( + argument?: Record | string, + options?: string[], + collectCoverageFromCurrentFile?: boolean, + ): Promise { const currentTestName = typeof argument === 'string' ? argument : undefined; const editor = vscode.window.activeTextEditor; if (!editor) { @@ -60,9 +67,25 @@ export class JestRunner { await editor.document.save(); const filePath = editor.document.fileName; + + const finalOptions = options; + if (collectCoverageFromCurrentFile) { + const targetFileDir = getDirName(filePath); + const targetFileName = getFileName(filePath).replace(/\.(test|spec)\./, '.'); + + // if a file does not exist with the same name as the test file but without the test/spec part + // use test file's directory for coverage target + const coverageTarget = fs.existsSync(`${targetFileDir}/${targetFileName}`) + ? `**/${targetFileName}` + : `**/${getFileName(targetFileDir)}/**`; + + finalOptions.push('--collectCoverageFrom'); + finalOptions.push(quote(coverageTarget)); + } + const testName = currentTestName || this.findCurrentTestName(editor); const resolvedTestName = updateTestNameIfUsingProperties(testName); - const command = this.buildJestCommand(filePath, resolvedTestName, options); + const command = this.buildJestCommand(filePath, resolvedTestName, finalOptions); this.previousCommand = command; diff --git a/src/util.ts b/src/util.ts index c35cead..51313ff 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,5 +1,14 @@ +import * as path from 'path'; import { execSync } from 'child_process'; +export function getDirName(filePath: string): string { + return path.dirname(filePath); +} + +export function getFileName(filePath: string): string { + return path.basename(filePath); +} + export function isWindows(): boolean { return process.platform.includes('win32'); } @@ -74,10 +83,10 @@ export function pushMany(arr: T[], items: T[]): number { return Array.prototype.push.apply(arr, items); } -export type CodeLensOption = 'run' | 'debug' | 'watch' | 'coverage'; +export type CodeLensOption = 'run' | 'debug' | 'watch' | 'coverage' | 'current-test-coverage'; function isCodeLensOption(option: string): option is CodeLensOption { - return ['run', 'debug', 'watch', 'coverage'].includes(option); + return ['run', 'debug', 'watch', 'coverage', 'current-test-coverage'].includes(option); } export function validateCodeLensOptions(maybeCodeLensOptions: string[]): CodeLensOption[] {