Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Improvements:

* The 'Define Steps' command honors the StepDefinitionSkeletonStyle setting in the project reqnroll.json configuration file and will generate step skeletons using 'Async' appropriately.

## Bug fixes:

*Contributors of this release (in alphabetical order):*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ public void Populate(string jsonString, DeveroomConfiguration config)
config.ConfiguredBindingCulture = bindingCulture;
if (reqnrollJsonConfiguration.Trace != null &&
reqnrollJsonConfiguration.Trace.TryGetValue("stepDefinitionSkeletonStyle", out var sdSnippetStyle)) {
if (sdSnippetStyle == "CucumberExpressionAttribute")
config.SnippetExpressionStyle = SnippetExpressionStyle.CucumberExpression;
if (sdSnippetStyle == "RegexAttribute")
config.SnippetExpressionStyle = SnippetExpressionStyle.RegularExpression;
config.SnippetExpressionStyle = sdSnippetStyle switch
{
"CucumberExpressionAttribute" => SnippetExpressionStyle.CucumberExpression,
"RegexAttribute" => SnippetExpressionStyle.RegularExpression,
"AsyncCucumberExpressionAttribute" => SnippetExpressionStyle.AsyncCucumberExpression,
"AsyncRegexAttribute" => SnippetExpressionStyle.AsyncRegularExpression,
_ => SnippetExpressionStyle.CucumberExpression
};
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace Reqnroll.VisualStudio.Snippets.Fallback;

public class CucumberExpressionSkeletonProvider : DeveroomStepDefinitionSkeletonProvider
{
public CucumberExpressionSkeletonProvider(ReqnrollProjectTraits projectTraits)
: base(projectTraits)
public CucumberExpressionSkeletonProvider(ReqnrollProjectTraits projectTraits, bool useAsync)
: base(projectTraits, useAsync)
{

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ public abstract class DeveroomStepDefinitionSkeletonProvider
{
protected ReqnrollProjectTraits ProjectTraits { get; }
protected abstract bool UseVerbatimStringForExpression { get; }
protected bool UseAsync { get; }

protected DeveroomStepDefinitionSkeletonProvider(ReqnrollProjectTraits projectTraits)
protected DeveroomStepDefinitionSkeletonProvider(ReqnrollProjectTraits projectTraits, bool useAsync)
{
ProjectTraits = projectTraits;
UseAsync = useAsync;
}

public string GetStepDefinitionSkeletonSnippet(UndefinedStepDescriptor undefinedStep,
Expand All @@ -23,9 +25,10 @@ public string GetStepDefinitionSkeletonSnippet(UndefinedStepDescriptor undefined
var methodName = GetMethodName(undefinedStep, analyzedStepText);
var parameters = string.Join(", ", analyzedStepText.Parameters.Select(ToDeclaration));
var stringPrefix = UseVerbatimStringForExpression ? "@" : "";
var returnSignature = UseAsync ? "async Task" : "void";

var method = $"[{undefinedStep.ScenarioBlock}({stringPrefix}\"{regex}\")]" + newLine +
$"public void {methodName}({parameters})" + newLine +
$"public {returnSignature} {methodName}{(UseAsync ? "Async" : "")}({parameters})" + newLine +
"{" + newLine +
$"{indent}throw new PendingStepException();" + newLine +
"}" + newLine;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace Reqnroll.VisualStudio.Snippets.Fallback;

public class RegexStepDefinitionSkeletonProvider : DeveroomStepDefinitionSkeletonProvider
{
public RegexStepDefinitionSkeletonProvider(ReqnrollProjectTraits projectTraits) : base(projectTraits)
public RegexStepDefinitionSkeletonProvider(ReqnrollProjectTraits projectTraits, bool useAsync) : base(projectTraits, useAsync)
{
}

Expand Down
23 changes: 22 additions & 1 deletion Reqnroll.VisualStudio/Snippets/SnippetExpressionStyle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,26 @@ namespace Reqnroll.VisualStudio.Snippets;
public enum SnippetExpressionStyle
{
RegularExpression,
CucumberExpression
CucumberExpression,
AsyncRegularExpression,
AsyncCucumberExpression
}

public static class SnippetExpressionStyleExtensions
{
public static bool IsAsync(this SnippetExpressionStyle style)
{
if (style == SnippetExpressionStyle.AsyncRegularExpression
|| style == SnippetExpressionStyle.AsyncCucumberExpression)
return true;
return false;
}

public static bool IsCucumber(this SnippetExpressionStyle style)
{
if (style == SnippetExpressionStyle.CucumberExpression
|| style == SnippetExpressionStyle.AsyncCucumberExpression)
return true;
return false;
}
}
6 changes: 3 additions & 3 deletions Reqnroll.VisualStudio/Snippets/SnippetService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public string GetStepDefinitionSkeletonSnippet(UndefinedStepDescriptor undefined
try
{
var projectTraits = _projectScope.GetProjectSettings().ReqnrollProjectTraits;
var skeletonProvider = expressionStyle == SnippetExpressionStyle.CucumberExpression
? (DeveroomStepDefinitionSkeletonProvider) new CucumberExpressionSkeletonProvider(projectTraits)
: new RegexStepDefinitionSkeletonProvider(projectTraits);
var skeletonProvider = expressionStyle.IsCucumber()
? (DeveroomStepDefinitionSkeletonProvider) new CucumberExpressionSkeletonProvider(projectTraits, expressionStyle.IsAsync())
: new RegexStepDefinitionSkeletonProvider(projectTraits, expressionStyle.IsAsync());

var configuration = _projectScope.GetDeveroomConfiguration();
newLine = newLine ?? Environment.NewLine;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,44 @@ Scenario: DefineSteps command properly escapes empty brackets when using Regex e
| type | expression |
| When | I use \\(parenthesis\), \\{curly braces}, \\\ backslash, and/or \\. period |

Scenario: DefineSteps command abides by reqnroll.json configuration for async method declaration
Given there is a Reqnroll project scope
And the following feature file in the editor
"""
Feature: Feature Using Regex Style

Scenario: Client has a simple basket
Given the client has a basket
"""
And the reqnroll.json configuration file contains
"""
{
"trace": { "stepDefinitionSkeletonStyle": "AsyncRegexAttribute" }
}
"""
And the project is built and the initial binding discovery is performed
When I invoke the "Define Steps" command
Then the define steps dialog should be opened with the following step definition skeletons
| Method |
| MyProject.StepDefinitions1.GivenTheClientHasABasketAsync |

Scenario: DefineSteps command abides by reqnroll.json configuration for synchronous method declaration
Given there is a Reqnroll project scope
And the following feature file in the editor
"""
Feature: Feature Using Regex Style

Scenario: Client has a simple basket
Given the client has a basket
"""
And the reqnroll.json configuration file contains
"""
{
"trace": { "stepDefinitionSkeletonStyle": "RegexAttribute" }
}
"""
And the project is built and the initial binding discovery is performed
When I invoke the "Define Steps" command
Then the define steps dialog should be opened with the following step definition skeletons
| Method |
| MyProject.StepDefinitions1.GivenTheClientHasABasket |
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,8 @@ private StepDefinitionSnippetData[] ParseSnippetsFromFile(string text,
{
Type = sd.Type,
Regex = sd.Regex,
Expression = sd.Expression
Expression = sd.Expression,
Method = sd.Method
}).ToArray();
}

Expand Down Expand Up @@ -987,5 +988,6 @@ private class StepDefinitionSnippetData
public string Type { get; set; }
public string Regex { get; set; }
public string Expression { get; set; }
public string Method { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using FluentAssertions;
using Reqnroll.VisualStudio.Configuration;
using Reqnroll.VisualStudio.Snippets;
using Xunit;

namespace Reqnroll.VisualStudio.Tests.Configuration;
Expand Down Expand Up @@ -149,4 +150,37 @@ public void Should_prioritize_language_binding_over_legacy_bindingCulture()
config.ConfiguredBindingCulture.Should().Be("fr-FR"); // language.binding takes priority
config.BindingCulture.Should().Be("fr-FR");
}

[Theory]
[InlineData("RegexAttribute", SnippetExpressionStyle.RegularExpression)]
[InlineData("CucumberExpressionAttribute", SnippetExpressionStyle.CucumberExpression)]
[InlineData("AsyncRegexAttribute", SnippetExpressionStyle.AsyncRegularExpression)]
[InlineData("AsyncCucumberExpressionAttribute", SnippetExpressionStyle.AsyncCucumberExpression)]
[InlineData("InvalidValue", SnippetExpressionStyle.CucumberExpression)] // Default fallback
[InlineData("", SnippetExpressionStyle.CucumberExpression)] // Default fallback
[InlineData(null, SnippetExpressionStyle.CucumberExpression)] // Default fallback
public void Should_set_stepDefinitionSkeletonStyle_from_reqnroll_json(string styleValue, SnippetExpressionStyle expectedStyle)
{
// Arrange
var deserializer = new ReqnrollConfigDeserializer();
var config = new DeveroomConfiguration();
var styleJson = styleValue != null
? $@"
{{
""trace"": {{
""stepDefinitionSkeletonStyle"": ""{styleValue}""
}}
}}"
: @"
{
""trace"": {
}
}";

// Act
deserializer.Populate(styleJson, config);

// Assert
config.SnippetExpressionStyle.Should().Be(expectedStyle);
}
}
53 changes: 53 additions & 0 deletions Tests/Reqnroll.VisualStudio.Tests/Snippets/SnippetServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using FluentAssertions;
using NSubstitute;
using Reqnroll.VisualStudio.Snippets;
using Reqnroll.VisualStudio.ProjectSystem;
using Reqnroll.VisualStudio.ProjectSystem.Configuration;
using Xunit;

namespace Reqnroll.VisualStudio.Tests.Snippets
{
public class SnippetServiceTests
{
private readonly IProjectScope _projectScope;
private readonly IIdeScope _ideScope;
private readonly IDeveroomLogger _logger;
private readonly SnippetService _service;
private readonly DeveroomConfiguration _defaultDeveroomConfig;
private readonly ITestOutputHelper testOutputHelper;

public SnippetServiceTests(ITestOutputHelper testOutputHelper)
{
_ideScope = new StubIdeScope(testOutputHelper);
_logger = new StubLogger();
_projectScope = new StubProjectScope(@"C:\", "bin", _ideScope, new List<NuGetPackageReference>(), "net8");

_defaultDeveroomConfig = new DeveroomConfiguration();

// Construct the service with the substitute
_service = new SnippetService(_projectScope);
this.testOutputHelper = testOutputHelper;
}

[Theory]
[InlineData(SnippetExpressionStyle.RegularExpression, "[Given(@\"pattern\")]\npublic void GivenPattern()\n{\nthrow new PendingStepException();\n}\n")]
[InlineData(SnippetExpressionStyle.AsyncRegularExpression, "[Given(@\"pattern\")]\npublic async Task GivenPatternAsync()\n{\nthrow new PendingStepException();\n}\n")]
[InlineData(SnippetExpressionStyle.CucumberExpression, "[Given(\"pattern\")]\npublic void GivenPattern()\n{\nthrow new PendingStepException();\n}\n")]
[InlineData(SnippetExpressionStyle.AsyncCucumberExpression, "[Given(\"pattern\")]\npublic async Task GivenPatternAsync()\n{\nthrow new PendingStepException();\n}\n")]
public void Generates_correct_step_definition_snippet(SnippetExpressionStyle style, string expectedSnippet)
{
// Arrange
var undefinedStep = new DeveroomGherkinStep(new Gherkin.Ast.Location(0, 0), "Given ", Gherkin.StepKeywordType.Context, "pattern", null, StepKeyword.Given, ScenarioBlock.Given);
var undefinedStepDescriptor = new UndefinedStepDescriptor(undefinedStep, "pattern");
var indent = "";
var newLine = "\n";

// Act
var snippet = _service.GetStepDefinitionSkeletonSnippet(
undefinedStepDescriptor, style, indent, newLine);

// Assert
snippet.Should().Be(expectedSnippet);
}
}
}
Loading