-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Full parameterized tests support #649
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,30 @@ | ||
import * as vscode from 'vscode'; | ||
import { TestIdentifier } from '../TestResults'; | ||
|
||
export type DebugTestIdentifier = string | TestIdentifier; | ||
export class DebugCodeLens extends vscode.CodeLens { | ||
readonly fileName: string; | ||
readonly testName: string; | ||
readonly testIds: DebugTestIdentifier[]; | ||
readonly document: vscode.TextDocument; | ||
|
||
/** | ||
* | ||
* @param document | ||
* @param range | ||
* @param fileName | ||
* @param testIds test name/pattern. | ||
* Because a test block can have multiple test results, such as for paramertized tests (i.e. test.each/describe.each), there could be multiple debuggable candidates, thus it takes multiple test identifiers. | ||
* Noite: If a test id is a string array, it should represent the hierarchiical relationship of a test structure, such as [describe-id, test-id]. | ||
*/ | ||
constructor( | ||
document: vscode.TextDocument, | ||
range: vscode.Range, | ||
fileName: string, | ||
testName: string | ||
...testIds: DebugTestIdentifier[] | ||
) { | ||
super(range); | ||
this.document = document; | ||
this.fileName = fileName; | ||
this.testName = testName; | ||
this.testIds = testIds; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,8 @@ | ||
import * as vscode from 'vscode'; | ||
import { extensionName } from '../appGlobals'; | ||
import { escapeRegExp } from '../helpers'; | ||
import { basename } from 'path'; | ||
import { DebugCodeLens } from './DebugCodeLens'; | ||
import { TestReconciliationState } from '../TestResults'; | ||
import { TestReconciliationStateType } from '../TestResults'; | ||
import { TestState, TestStateByTestReconciliationState } from './TestState'; | ||
import { GetJestExtByURI } from '../extensionManager'; | ||
|
||
|
@@ -18,7 +17,7 @@ export class DebugCodeLensProvider implements vscode.CodeLensProvider { | |
this.onDidChange = new vscode.EventEmitter(); | ||
} | ||
|
||
get showWhenTestStateIn() { | ||
get showWhenTestStateIn(): TestState[] { | ||
return this._showWhenTestStateIn; | ||
} | ||
|
||
|
@@ -31,7 +30,7 @@ export class DebugCodeLensProvider implements vscode.CodeLensProvider { | |
return this.onDidChange.event; | ||
} | ||
|
||
provideCodeLenses(document: vscode.TextDocument, _: vscode.CancellationToken): vscode.CodeLens[] { | ||
provideCodeLenses(document: vscode.TextDocument, _: vscode.CancellationToken): DebugCodeLens[] { | ||
const result = []; | ||
const ext = this.getJestExt(document.uri); | ||
if (!ext || this._showWhenTestStateIn.length === 0 || document.isUntitled) { | ||
|
@@ -43,20 +42,24 @@ export class DebugCodeLensProvider implements vscode.CodeLensProvider { | |
const fileName = basename(document.fileName); | ||
|
||
for (const test of testResults) { | ||
if (!this.showCodeLensAboveTest(test)) { | ||
const results = test.multiResults ? [test, ...test.multiResults] : [test]; | ||
const allIds = results.filter((r) => this.showCodeLensAboveTest(r)).map((r) => r.identifier); | ||
|
||
if (!allIds.length) { | ||
continue; | ||
} | ||
|
||
const start = new vscode.Position(test.start.line, test.start.column); | ||
const end = new vscode.Position(test.end.line, test.start.column + 5); | ||
const range = new vscode.Range(start, end); | ||
result.push(new DebugCodeLens(document, range, fileName, test.name)); | ||
|
||
result.push(new DebugCodeLens(document, range, fileName, ...allIds)); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
showCodeLensAboveTest(test: { status: TestReconciliationState }) { | ||
showCodeLensAboveTest(test: { status: TestReconciliationStateType }): boolean { | ||
const state = TestStateByTestReconciliationState[test.status]; | ||
return this._showWhenTestStateIn.includes(state); | ||
} | ||
|
@@ -67,16 +70,16 @@ export class DebugCodeLensProvider implements vscode.CodeLensProvider { | |
): vscode.ProviderResult<vscode.CodeLens> { | ||
if (codeLens instanceof DebugCodeLens) { | ||
codeLens.command = { | ||
arguments: [codeLens.document, codeLens.fileName, escapeRegExp(codeLens.testName)], | ||
arguments: [codeLens.document, codeLens.fileName, ...codeLens.testIds], | ||
command: `${extensionName}.run-test`, | ||
title: 'Debug', | ||
title: codeLens.testIds.length > 1 ? `Debug(${codeLens.testIds.length})` : 'Debug', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's add a space after "Debug"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}; | ||
} | ||
|
||
return codeLens; | ||
} | ||
|
||
didChange() { | ||
didChange(): void { | ||
this.onDidChange.fire(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { DebugCodeLensProvider } from './DebugCodeLensProvider'; | ||
export { TestState } from './TestState'; | ||
export { DebugTestIdentifier } from './DebugCodeLens'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,16 +11,24 @@ import { | |
TestResult, | ||
resultsWithLowerCaseWindowsDriveLetters, | ||
SortedTestResults, | ||
TestResultStatusInfo, | ||
TestReconciliationStateType, | ||
} from './TestResults'; | ||
import { cleanAnsi, getJestCommandSettings } from './helpers'; | ||
import { | ||
cleanAnsi, | ||
testIdString, | ||
IdStringType, | ||
getJestCommandSettings, | ||
escapeRegExp, | ||
} from './helpers'; | ||
import { CoverageMapProvider, CoverageCodeLensProvider } from './Coverage'; | ||
import { | ||
updateDiagnostics, | ||
updateCurrentDiagnostics, | ||
resetDiagnostics, | ||
failedSuiteCount, | ||
} from './diagnostics'; | ||
import { DebugCodeLensProvider } from './DebugCodeLens'; | ||
import { DebugCodeLensProvider, DebugTestIdentifier } from './DebugCodeLens'; | ||
import { DebugConfigurationProvider } from './DebugConfigurationProvider'; | ||
import { DecorationOptions } from './types'; | ||
import { isOpenInMultipleEditors } from './editor'; | ||
|
@@ -35,6 +43,9 @@ interface InstanceSettings { | |
multirootEnv: boolean; | ||
} | ||
|
||
interface RunTestPickItem extends vscode.QuickPickItem { | ||
id: DebugTestIdentifier; | ||
} | ||
export class JestExt { | ||
coverageMapProvider: CoverageMapProvider; | ||
coverageOverlay: CoverageOverlay; | ||
|
@@ -297,19 +308,43 @@ export class JestExt { | |
public runTest = async ( | ||
workspaceFolder: vscode.WorkspaceFolder, | ||
fileName: string, | ||
identifier: string | ||
...ids: DebugTestIdentifier[] | ||
): Promise<void> => { | ||
const restart = this.jestProcessManager.numberOfProcesses > 0; | ||
this.jestProcessManager.stopAll(); | ||
const idString = (type: IdStringType, id: DebugTestIdentifier): string => | ||
typeof id === 'string' ? id : testIdString(type, id); | ||
const selectTest = async ( | ||
testIdentifiers: DebugTestIdentifier[] | ||
): Promise<DebugTestIdentifier | undefined> => { | ||
const items: RunTestPickItem[] = testIdentifiers.map((id) => ({ | ||
label: idString('display-reverse', id), | ||
id, | ||
})); | ||
const selected = await vscode.window.showQuickPick<RunTestPickItem>(items, { | ||
placeHolder: 'select a test to debug', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about an uppercase "Select"? |
||
}); | ||
|
||
this.debugConfigurationProvider.prepareTestRun(fileName, identifier); | ||
return selected?.id; | ||
}; | ||
let testId: DebugTestIdentifier | undefined; | ||
switch (ids.length) { | ||
case 0: | ||
return; | ||
case 1: | ||
testId = ids[0]; | ||
break; | ||
default: | ||
testId = await selectTest(ids); | ||
break; | ||
} | ||
|
||
const handle = vscode.debug.onDidTerminateDebugSession(() => { | ||
handle.dispose(); | ||
if (restart) { | ||
this.startProcess(); | ||
} | ||
}); | ||
if (!testId) { | ||
return; | ||
} | ||
|
||
this.debugConfigurationProvider.prepareTestRun( | ||
fileName, | ||
escapeRegExp(idString('full-name', testId)) | ||
); | ||
|
||
try { | ||
// try to run the debug configuration from launch.json | ||
|
@@ -551,22 +586,12 @@ export class JestExt { | |
|
||
private generateDotsForItBlocks( | ||
blocks: TestResult[], | ||
state: TestReconciliationState | ||
state: TestReconciliationStateType | ||
): DecorationOptions[] { | ||
const nameForState = { | ||
[TestReconciliationState.KnownSuccess]: 'Passed', | ||
[TestReconciliationState.KnownFail]: 'Failed', | ||
[TestReconciliationState.KnownSkip]: 'Skipped', | ||
[TestReconciliationState.Unknown]: | ||
'Test has not run yet, due to Jest only running tests related to changes.', | ||
}; | ||
|
||
return blocks.map((it) => { | ||
return { | ||
range: new vscode.Range(it.start.line, it.start.column, it.start.line, it.start.column + 1), | ||
hoverMessage: nameForState[state], | ||
identifier: it.name, | ||
}; | ||
}); | ||
return blocks.map((it) => ({ | ||
range: new vscode.Range(it.start.line, it.start.column, it.start.line, it.start.column + 1), | ||
hoverMessage: TestResultStatusInfo[state].desc, | ||
identifier: it.name, | ||
})); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,11 @@ | ||
export type TestReconciliationState = 'Unknown' | 'KnownSuccess' | 'KnownFail' | 'KnownSkip'; | ||
export type TestReconciliationStateType = 'Unknown' | 'KnownSuccess' | 'KnownFail' | 'KnownSkip'; | ||
|
||
// tslint:disable-next-line variable-name | ||
export const TestReconciliationState = { | ||
Unknown: 'Unknown' as TestReconciliationState, | ||
KnownSuccess: 'KnownSuccess' as TestReconciliationState, | ||
KnownFail: 'KnownFail' as TestReconciliationState, | ||
KnownSkip: 'KnownSkip' as TestReconciliationState, | ||
export const TestReconciliationState: { | ||
[key in TestReconciliationStateType]: TestReconciliationStateType; | ||
} = { | ||
Unknown: 'Unknown', | ||
KnownSuccess: 'KnownSuccess', | ||
KnownFail: 'KnownFail', | ||
KnownSkip: 'KnownSkip', | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typos ("Noite", "hierarchiical")