Skip to content

Commit 95a7c48

Browse files
committed
Add a ICodeLensProvider for running Pester tests
This change adds an ICodeLensProvider implementation which adds CodeLenses on Pester "Describe" blocks so that the tests in these blocks can be ran or debugged easily from within an editor.
1 parent 863c4e0 commit 95a7c48

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

src/PowerShellEditorServices.Host/CodeLens/CodeLensFeature.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ public static CodeLensFeature Create(
5858
new ReferencesCodeLensProvider(
5959
editorSession));
6060

61+
codeLenses.Providers.Add(
62+
new PesterCodeLensProvider(
63+
editorSession));
6164

6265
editorSession.Components.Register<ICodeLenses>(codeLenses);
6366

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using Microsoft.PowerShell.EditorServices.Commands;
7+
using Microsoft.PowerShell.EditorServices.Symbols;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
14+
namespace Microsoft.PowerShell.EditorServices.CodeLenses
15+
{
16+
internal class PesterCodeLensProvider : FeatureProviderBase, ICodeLensProvider
17+
{
18+
private static char[] QuoteChars = new char[] { '\'', '"'};
19+
20+
private EditorSession editorSession;
21+
private IDocumentSymbolProvider symbolProvider;
22+
23+
public PesterCodeLensProvider(EditorSession editorSession)
24+
{
25+
this.editorSession = editorSession;
26+
this.symbolProvider = new PesterDocumentSymbolProvider();
27+
}
28+
29+
private IEnumerable<CodeLens> GetPesterLens(
30+
SymbolReference symbol,
31+
ScriptFile scriptFile)
32+
{
33+
// Trim the Describe "" { from the symbol name
34+
int startQuoteIndex = symbol.SourceLine.IndexOfAny(QuoteChars) + 1;
35+
int endQuoteIndex = symbol.SourceLine.LastIndexOfAny(QuoteChars);
36+
37+
string describeBlockName =
38+
symbol.SourceLine.Substring(
39+
startQuoteIndex,
40+
endQuoteIndex - startQuoteIndex);
41+
42+
var clientCommands = new ClientCommand[]
43+
{
44+
new ClientCommand(
45+
"PowerShell.RunPesterTests",
46+
"run tests",
47+
new object[]
48+
{
49+
scriptFile.ClientFilePath,
50+
false, // Don't debug
51+
describeBlockName,
52+
}),
53+
54+
new ClientCommand(
55+
"PowerShell.RunPesterTests",
56+
"debug tests",
57+
new object[]
58+
{
59+
scriptFile.ClientFilePath,
60+
true, // Run in debugger
61+
describeBlockName,
62+
}),
63+
};
64+
65+
return
66+
clientCommands.Select(
67+
command =>
68+
new CodeLens(
69+
this,
70+
scriptFile,
71+
symbol.ScriptRegion,
72+
command));
73+
}
74+
75+
public CodeLens[] ProvideCodeLenses(ScriptFile scriptFile)
76+
{
77+
var symbols =
78+
this.symbolProvider
79+
.ProvideDocumentSymbols(scriptFile);
80+
81+
var lenses =
82+
symbols
83+
.Where(s => s.SymbolName.StartsWith("Describe"))
84+
.SelectMany(s => this.GetPesterLens(s, scriptFile))
85+
.ToArray();
86+
87+
return lenses;
88+
}
89+
90+
public Task<CodeLens> ResolveCodeLensAsync(
91+
CodeLens codeLens,
92+
CancellationToken cancellationToken)
93+
{
94+
// This provider has no specific behavior for
95+
// resolving CodeLenses.
96+
return Task.FromResult(codeLens);
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)