Skip to content

Commit 7ec908b

Browse files
committed
Migrate Pester version detection into an InovkePester stub script
1 parent 1917544 commit 7ec908b

File tree

2 files changed

+85
-19
lines changed

2 files changed

+85
-19
lines changed

InvokePesterStub.ps1

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env pwsh
2+
3+
<#
4+
.SYNOPSIS
5+
Stub around Invoke-Pester command used by VSCode PowerShell extension.
6+
.DESCRIPTION
7+
Stub around Invoke-Pester command used by VSCode PowerShell extension.
8+
The stub checks the version of Pester and if >= 4.6.0, invokes Pester
9+
using the LineNumber parameter (if specified). Otherwise, it invokes
10+
using the TestName parameter (if specified).
11+
.EXAMPLE
12+
PS C:\> .\InvokePesterStub.ps1 ~\project\test\foo.tests.ps1 -LineNumber 14
13+
Invokes a specific test by line number in the specified file.
14+
.EXAMPLE
15+
PS C:\> .\InvokePesterStub.ps1 ~\project\test\foo.tests.ps1 -TestName 'Foo Tests'
16+
Invokes a specific test by test name in the specified file.
17+
.EXAMPLE
18+
PS C:\> .\InvokePesterStub.ps1 ~\project\test\foo.tests.ps1
19+
Invokes all tests in the specified file.
20+
.INPUTS
21+
None
22+
.OUTPUTS
23+
None
24+
#>
25+
param(
26+
# Specifies the path to the test script.
27+
[Parameter(Position=0, Mandatory)]
28+
[ValidateNotNullOrEmpty()]
29+
[string]
30+
$ScriptPath,
31+
32+
# Specifies the name of the test taken from the Describe block's name.
33+
[Parameter()]
34+
[string]
35+
$TestName,
36+
37+
# Specifies the starting line number of the DescribeBlock. This feature requires
38+
# Pester 4.6.0 or higher.
39+
[Parameter()]
40+
[ValidatePattern('\d*')]
41+
[string]
42+
$LineNumber
43+
)
44+
45+
try {
46+
$pesterVersion = (Microsoft.PowerShell.Core\Get-Command Invoke-Pester -ErrorAction Stop).Version
47+
if (($pesterVersion -ge '4.6.0') -and ($LineNumber -match '\d+')) {
48+
$pesterOption = New-PesterOption -ScriptBlockFilter @(
49+
@{ IncludeVSCodeMarker=$true; Line=$LineNumber; Path=$ScriptPath } )
50+
Invoke-Pester -Script $ScriptPath -PesterOption $pesterOption
51+
}
52+
elseif ($TestName) {
53+
Invoke-Pester -Script $ScriptPath -PesterOption @{ IncludeVSCodeMarker=$true } -TestName $TestName
54+
}
55+
else {
56+
Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true}
57+
}
58+
}
59+
catch [System.Management.Automation.CommandNotFoundException] {
60+
Write-Warning "You must install Pester to run or debug Pester Tests. You can install Pester by executing:"
61+
Write-Warning "Install-Module Pester -Scope CurrentUser -Force"
62+
}

src/features/PesterTests.ts

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ export class PesterTestsFeature implements IFeature {
1818

1919
private command: vscode.Disposable;
2020
private languageClient: LanguageClient;
21+
private invokePesterStubScriptPath: string;
2122

2223
constructor(private sessionManager: SessionManager) {
24+
this.invokePesterStubScriptPath = path.resolve(__dirname, "../../../InvokePesterStub.ps1");
25+
2326
// File context-menu command - Run Pester Tests
2427
this.command = vscode.commands.registerCommand(
2528
"PowerShell.RunPesterTestsFromFile",
@@ -35,8 +38,8 @@ export class PesterTestsFeature implements IFeature {
3538
// This command is provided for usage by PowerShellEditorServices (PSES) only
3639
this.command = vscode.commands.registerCommand(
3740
"PowerShell.RunPesterTests",
38-
(uriString, runInDebugger, describeBlockName?) => {
39-
this.launchTests(uriString, runInDebugger, describeBlockName);
41+
(uriString, runInDebugger, describeBlockName?, describeBlockLineNumber?) => {
42+
this.launchTests(uriString, runInDebugger, describeBlockName, describeBlockLineNumber);
4043
});
4144
}
4245

@@ -54,7 +57,7 @@ export class PesterTestsFeature implements IFeature {
5457
this.launch(launchConfig);
5558
}
5659

57-
private async launchTests(uriString: string, runInDebugger: boolean, describeBlockName?: string) {
60+
private async launchTests(uriString: string, runInDebugger: boolean, describeBlockName?: string, lineNum?: number) {
5861
// PSES passes null for the describeBlockName to signal that it can't evaluate the TestName.
5962
if (!describeBlockName) {
6063
const answer = await vscode.window.showErrorMessage(
@@ -68,21 +71,11 @@ export class PesterTestsFeature implements IFeature {
6871
}
6972

7073
const launchType = runInDebugger ? LaunchType.Debug : LaunchType.Run;
71-
const launchConfig = this.createLaunchConfig(uriString, launchType);
72-
73-
if (describeBlockName) {
74-
launchConfig.args.push("-TestName");
75-
// Escape single quotes inside double quotes by doubling them up
76-
if (describeBlockName.includes("'")) {
77-
describeBlockName = describeBlockName.replace(/'/g, "''");
78-
}
79-
launchConfig.args.push(`'${describeBlockName}'`);
80-
}
81-
74+
const launchConfig = this.createLaunchConfig(uriString, launchType, describeBlockName, lineNum);
8275
this.launch(launchConfig);
8376
}
8477

85-
private createLaunchConfig(uriString: string, launchType: LaunchType) {
78+
private createLaunchConfig(uriString: string, launchType: LaunchType, testName?: string, lineNum?: number) {
8679
const uri = vscode.Uri.parse(uriString);
8780
const currentDocument = vscode.window.activeTextEditor.document;
8881
const settings = Settings.load();
@@ -95,12 +88,10 @@ export class PesterTestsFeature implements IFeature {
9588
request: "launch",
9689
type: "PowerShell",
9790
name: "PowerShell Launch Pester Tests",
98-
script: "Invoke-Pester",
91+
script: this.invokePesterStubScriptPath,
9992
args: [
100-
"-Script",
93+
"-ScriptPath",
10194
`'${scriptPath}'`,
102-
"-PesterOption",
103-
"@{IncludeVSCodeMarker=$true}",
10495
],
10596
internalConsoleOptions: "neverOpen",
10697
noDebug: (launchType === LaunchType.Run),
@@ -111,6 +102,19 @@ export class PesterTestsFeature implements IFeature {
111102
: path.dirname(currentDocument.fileName),
112103
};
113104

105+
if (lineNum) {
106+
launchConfig.args.push("-LineNumber", `${lineNum}`);
107+
}
108+
109+
if (testName) {
110+
// Escape single quotes inside double quotes by doubling them up
111+
if (testName.includes("'")) {
112+
testName = testName.replace(/'/g, "''");
113+
}
114+
115+
launchConfig.args.push("-TestName", `'${testName}'`);
116+
}
117+
114118
return launchConfig;
115119
}
116120

0 commit comments

Comments
 (0)