Skip to content

Commit

Permalink
Add symbols for Pester setup and teardown blocks (#1899)
Browse files Browse the repository at this point in the history
* add symbols for Pester setup and teardown blocks

* update tests

* exclude Pester setup/teardown symbols from search
  • Loading branch information
fflaten authored Aug 18, 2022
1 parent 0b96dae commit 17d56d9
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,19 @@ public CodeLens[] ProvideCodeLenses(ScriptFile scriptFile, CancellationToken can
List<CodeLens> lenses = new();
foreach (SymbolReference symbol in _symbolProvider.ProvideDocumentSymbols(scriptFile))
{
cancellationToken.ThrowIfCancellationRequested();

if (symbol is not PesterSymbolReference pesterSymbol)
{
continue;
}

cancellationToken.ThrowIfCancellationRequested();
// Skip codelense for setup/teardown block
if (!PesterSymbolReference.IsPesterTestCommand(pesterSymbol.Command))
{
continue;
}

if (_configurationService.CurrentSettings.Pester.UseLegacyCodeLens
&& pesterSymbol.Command != PesterCommandType.Describe)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,33 +91,35 @@ private static PesterSymbolReference ConvertPesterAstToSymbolReference(ScriptFil
return null;
}

// Search for a name for the test
// If the test has more than one argument for names, we set it to null
string testName = null;
bool alreadySawName = false;
for (int i = 1; i < pesterCommandAst.CommandElements.Count; i++)
{
CommandElementAst currentCommandElement = pesterCommandAst.CommandElements[i];

// Check for an explicit "-Name" parameter
if (currentCommandElement is CommandParameterAst)
if (PesterSymbolReference.IsPesterTestCommand(commandName.Value)) {
// Search for a name for the test
// If the test has more than one argument for names, we set it to null
bool alreadySawName = false;
for (int i = 1; i < pesterCommandAst.CommandElements.Count; i++)
{
// Found -Name parameter, move to next element which is the argument for -TestName
i++;
CommandElementAst currentCommandElement = pesterCommandAst.CommandElements[i];

// Check for an explicit "-Name" parameter
if (currentCommandElement is CommandParameterAst)
{
// Found -Name parameter, move to next element which is the argument for -TestName
i++;

if (!alreadySawName && TryGetTestNameArgument(pesterCommandAst.CommandElements[i], out testName))
{
alreadySawName = true;
}

continue;
}

// Otherwise, if an argument is given with no parameter, we assume it's the name
// If we've already seen a name, we set the name to null
if (!alreadySawName && TryGetTestNameArgument(pesterCommandAst.CommandElements[i], out testName))
{
alreadySawName = true;
}

continue;
}

// Otherwise, if an argument is given with no parameter, we assume it's the name
// If we've already seen a name, we set the name to null
if (!alreadySawName && TryGetTestNameArgument(pesterCommandAst.CommandElements[i], out testName))
{
alreadySawName = true;
}
}

Expand Down Expand Up @@ -145,7 +147,7 @@ private static bool TryGetTestNameArgument(CommandElementAst commandElementAst,
}

/// <summary>
/// Defines command types for Pester test blocks.
/// Defines command types for Pester blocks.
/// </summary>
internal enum PesterCommandType
{
Expand All @@ -162,7 +164,32 @@ internal enum PesterCommandType
/// <summary>
/// Identifies an It block.
/// </summary>
It
It,

/// <summary>
/// Identifies an BeforeAll block.
/// </summary>
BeforeAll,

/// <summary>
/// Identifies an BeforeEach block.
/// </summary>
BeforeEach,

/// <summary>
/// Identifies an AfterAll block.
/// </summary>
AfterAll,

/// <summary>
/// Identifies an AfterEach block.
/// </summary>
AfterEach,

/// <summary>
/// Identifies an BeforeDiscovery block.
/// </summary>
BeforeDiscovery
}

/// <summary>
Expand Down Expand Up @@ -216,5 +243,18 @@ internal PesterSymbolReference(
}
return pesterCommandType;
}

/// <summary>
/// Checks if the PesterCommandType is a block with executable tests (Describe/Context/It).
/// </summary>
/// <param name="pesterCommandType">the PesterCommandType representing the Pester command</param>
/// <returns>True if command type is a block used to trigger test run. False if setup/teardown/support-block.</returns>
internal static bool IsPesterTestCommand(PesterCommandType pesterCommandType)
{
return pesterCommandType is
PesterCommandType.Describe or
PesterCommandType.Context or
PesterCommandType.It;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ public override async Task<Container<SymbolInformation>> Handle(WorkspaceSymbolP
continue;
}

// Exclude Pester setup/teardown symbols as they're unnamed
if (foundOccurrence is PesterSymbolReference pesterSymbol &&
!PesterSymbolReference.IsPesterTestCommand(pesterSymbol.Command))
{
continue;
}

Location location = new()
{
Uri = DocumentUri.From(foundOccurrence.FilePath),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
Describe "A dummy test" {
Context "When a pester file is given" {
BeforeDiscovery {

}

BeforeAll {

}

Describe "Testing Pester symbols" {
Context "When a Pester file is given" {
BeforeAll {

}

BeforeEach {

}

It "Should return it symbols" {

}
Expand All @@ -11,5 +27,17 @@
It "Should return describe symbols" {

}

It "Should return setup and teardown symbols" {

}

AfterEach {

}
}

AfterAll {

}
}
46 changes: 38 additions & 8 deletions test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,25 +315,55 @@ public void FindsSymbolsInFile()
public void FindsSymbolsInPesterFile()
{
List<PesterSymbolReference> symbolsResult = FindSymbolsInFile(FindSymbolsInPesterFile.SourceDetails).OfType<PesterSymbolReference>().ToList();
Assert.Equal(5, symbolsResult.Count(r => r.SymbolType == SymbolType.Function));
Assert.Equal(12, symbolsResult.Count(r => r.SymbolType == SymbolType.Function));

Assert.Equal(1, symbolsResult.Count(r => r.Command == PesterCommandType.Describe));
SymbolReference firstDescribeSymbol = symbolsResult.First(r => r.Command == PesterCommandType.Describe);
Assert.Equal("Describe \"A dummy test\"", firstDescribeSymbol.SymbolName);
Assert.Equal(1, firstDescribeSymbol.ScriptRegion.StartLineNumber);
Assert.Equal("Describe \"Testing Pester symbols\"", firstDescribeSymbol.SymbolName);
Assert.Equal(9, firstDescribeSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(1, firstDescribeSymbol.ScriptRegion.StartColumnNumber);

Assert.Equal(1, symbolsResult.Count(r => r.Command == PesterCommandType.Context));
SymbolReference firstContextSymbol = symbolsResult.First(r => r.Command == PesterCommandType.Context);
Assert.Equal("Context \"When a pester file is given\"", firstContextSymbol.SymbolName);
Assert.Equal(2, firstContextSymbol.ScriptRegion.StartLineNumber);
Assert.Equal("Context \"When a Pester file is given\"", firstContextSymbol.SymbolName);
Assert.Equal(10, firstContextSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(5, firstContextSymbol.ScriptRegion.StartColumnNumber);

Assert.Equal(3, symbolsResult.Count(r => r.Command == PesterCommandType.It));
Assert.Equal(4, symbolsResult.Count(r => r.Command == PesterCommandType.It));
SymbolReference lastItSymbol = symbolsResult.Last(r => r.Command == PesterCommandType.It);
Assert.Equal("It \"Should return describe symbols\"", lastItSymbol.SymbolName);
Assert.Equal(11, lastItSymbol.ScriptRegion.StartLineNumber);
Assert.Equal("It \"Should return setup and teardown symbols\"", lastItSymbol.SymbolName);
Assert.Equal(31, lastItSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(9, lastItSymbol.ScriptRegion.StartColumnNumber);

Assert.Equal(1, symbolsResult.Count(r => r.Command == PesterCommandType.BeforeDiscovery));
SymbolReference firstBeforeDisocverySymbol = symbolsResult.First(r => r.Command == PesterCommandType.BeforeDiscovery);
Assert.Equal("BeforeDiscovery", firstBeforeDisocverySymbol.SymbolName);
Assert.Equal(1, firstBeforeDisocverySymbol.ScriptRegion.StartLineNumber);
Assert.Equal(1, firstBeforeDisocverySymbol.ScriptRegion.StartColumnNumber);

Assert.Equal(2, symbolsResult.Count(r => r.Command == PesterCommandType.BeforeAll));
SymbolReference lastBeforeAllSymbol = symbolsResult.Last(r => r.Command == PesterCommandType.BeforeAll);
Assert.Equal("BeforeAll", lastBeforeAllSymbol.SymbolName);
Assert.Equal(11, lastBeforeAllSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(9, lastBeforeAllSymbol.ScriptRegion.StartColumnNumber);

Assert.Equal(1, symbolsResult.Count(r => r.Command == PesterCommandType.BeforeEach));
SymbolReference firstBeforeEachSymbol = symbolsResult.First(r => r.Command == PesterCommandType.BeforeEach);
Assert.Equal("BeforeEach", firstBeforeEachSymbol.SymbolName);
Assert.Equal(15, firstBeforeEachSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(9, firstBeforeEachSymbol.ScriptRegion.StartColumnNumber);

Assert.Equal(1, symbolsResult.Count(r => r.Command == PesterCommandType.AfterEach));
SymbolReference firstAfterEachSymbol = symbolsResult.First(r => r.Command == PesterCommandType.AfterEach);
Assert.Equal("AfterEach", firstAfterEachSymbol.SymbolName);
Assert.Equal(35, firstAfterEachSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(9, firstAfterEachSymbol.ScriptRegion.StartColumnNumber);

Assert.Equal(1, symbolsResult.Count(r => r.Command == PesterCommandType.AfterAll));
SymbolReference firstAfterAllSymbol = symbolsResult.First(r => r.Command == PesterCommandType.AfterAll);
Assert.Equal("AfterAll", firstAfterAllSymbol.SymbolName);
Assert.Equal(40, firstAfterAllSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(5, firstAfterAllSymbol.ScriptRegion.StartColumnNumber);
}

[Fact]
Expand Down

0 comments on commit 17d56d9

Please sign in to comment.