Skip to content

Commit

Permalink
Improved handling of Step Definitions decorated with the 'StepDefinit…
Browse files Browse the repository at this point in the history
…ion' attribute. (#24)

* Fixing issues with finding 'Unused Step Definitions' #22

* Merge with main

* Tweaking spacing.

* Adding unit test

* Updating Changelog

* Tweaking changelog
  • Loading branch information
UL-ChrisGlew authored Jun 14, 2024
1 parent c92042c commit 06b3c01
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 5 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# [vNext]

## Improvements:

* Find Unused Step Definitions Command: Improved handling of Step Definitions decorated with the 'StepDefinition' attribute. If a Step Definition is used in any Given/Then/When step in a Feature file, the step will no longer show in the 'Find Unused Step Definitions' context menu.

*Contributors of this release (in alphabetical order):* @UL-ChrisGlew

# v2024.2.93 - 2024-06-05

## Improvements:
Expand All @@ -19,4 +25,4 @@
* Support for .NET 8 projects
* New editor command: "Go To Hooks" (Ctrl B,H) to navigate to the hooks related to the scenario
* The "Go To Definition" lists hooks when invoked from scenario header (tags, header line, description)
* Initial release based on v2022.1.91 of the [SpecFlow for Visual Studio](https://github.com/SpecFlowOSS/SpecFlow.VS/) extension.
* Initial release based on v2022.1.91 of the [SpecFlow for Visual Studio](https://github.com/SpecFlowOSS/SpecFlow.VS/) extension.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ public UnusedStepDefinitionsFinder(IIdeScope ideScope) : base(ideScope)
_ideScope = ideScope;
}

public IEnumerable<ProjectStepDefinitionBinding> FindUnused(ProjectBindingRegistry bindingRegistry,
string[] featureFiles, DeveroomConfiguration configuration)
public IEnumerable<ProjectStepDefinitionBinding> FindUnused(ProjectBindingRegistry bindingRegistry, string[] featureFiles, DeveroomConfiguration configuration)
{
var stepDefUsageCounts = bindingRegistry.StepDefinitions.ToDictionary(stepDef => stepDef, _ => 0);
foreach (var ff in featureFiles)
Expand All @@ -28,7 +27,9 @@ public IEnumerable<ProjectStepDefinitionBinding> FindUnused(ProjectBindingRegist
foreach (var step in usedSteps) stepDefUsageCounts[step]++;
}

return stepDefUsageCounts.Where(x => x.Value == 0).Select(x => x.Key);
var allUsedSteps = stepDefUsageCounts.Where(x => x.Value > 0).Select(x => x.Key).ToList();
var allUnusedSteps = stepDefUsageCounts.Where(x => x.Value == 0).Select(x => x.Key);
return allUnusedSteps.Where(x => !allUsedSteps.Any(y => y.Expression.Equals(x.Expression) && ReferenceEquals(x.Implementation, y.Implementation)));
}

protected IEnumerable<ProjectStepDefinitionBinding> FindUsed(ProjectBindingRegistry bindingRegistry,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,19 @@ public async Task Can_find_a_StepDefinition_With_Multiple_Step_Attributes_Not_Us
.HaveCount(2).And
.Contain(mi => mi.Label == "Steps.cs(10,9): [When(\"I choose add\")] WhenIPressAdd");
}


[Fact]
public async Task Cannot_find_an_unused_StepDefinition_With_StepDefinition_Attribute()
{
var stepDefinition = ArrangeStepDefinition(@"""I press add""", "StepDefinition");
var featureFile = ArrangeOneFeatureFile();
var (textView, command) = await ArrangeSut(stepDefinition, featureFile);

await InvokeAndWaitAnalyticsEvent(command, textView);

(ProjectScope.IdeScope.Actions as StubIdeActions)!.LastShowContextMenuItems.Should()
.HaveCount(1).And
.Contain(mi => mi.Label == "There are no unused step definitions");
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using Gherkin.CucumberMessages.Types;
using Newtonsoft.Json;

namespace Reqnroll.VisualStudio.VsxStubs.StepDefinitions;

public class MockableDiscoveryService : DiscoveryService
Expand All @@ -22,11 +25,34 @@ public static MockableDiscoveryService SetupWithInitialStepDefinitions(IProjectS
{
var discoveryResultProviderMock = new Mock<IDiscoveryResultProvider>(MockBehavior.Strict);

var allStepDefinitions = new List<StepDefinition>();
foreach (var stepDefinition in stepDefinitions)
{
if (stepDefinition.Type.Equals("StepDefinition"))
{
var serialized = JsonConvert.SerializeObject(stepDefinition);
var stepDefAttributes = new List<string>() { "Given", "Then", "When" };
foreach (string stepDefAttribute in stepDefAttributes)
{
StepDefinition? clonedStepDef = JsonConvert.DeserializeObject<StepDefinition>(serialized);
if (clonedStepDef != null)
{
clonedStepDef.Type = stepDefAttribute;
allStepDefinitions.Add(clonedStepDef);
}
}
}
else
{
allStepDefinitions.Add(stepDefinition);
}
}

var discoveryService = new MockableDiscoveryService(projectScope, discoveryResultProviderMock)
{
LastDiscoveryResult = new DiscoveryResult
{
StepDefinitions = stepDefinitions,
StepDefinitions = allStepDefinitions.ToArray(),
Hooks = Array.Empty<Hook>()
}
};
Expand Down

0 comments on commit 06b3c01

Please sign in to comment.