From 225c4328e6d36ac42af6e0eac6e59bed09287310 Mon Sep 17 00:00:00 2001 From: Romfos Date: Sat, 13 Jan 2024 14:17:42 +0100 Subject: [PATCH] Added argument transformation prototype --- .../NGherkinTestExecutor.cs | 32 ++++++++++++++----- src/NGherkin.Tests/Features/Feature1.feature | 4 +++ src/NGherkin.Tests/Startup.cs | 13 ++++++++ src/NGherkin.Tests/Steps/StepClass.cs | 9 ++++++ src/NGherkin/ArgumentTransformation.cs | 3 ++ src/NGherkin/ServiceCollectionExtensions.cs | 14 ++++++++ 6 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 src/NGherkin/ArgumentTransformation.cs diff --git a/src/NGherkin.TestAdapter/NGherkinTestExecutor.cs b/src/NGherkin.TestAdapter/NGherkinTestExecutor.cs index dfa9472..7c4a188 100644 --- a/src/NGherkin.TestAdapter/NGherkinTestExecutor.cs +++ b/src/NGherkin.TestAdapter/NGherkinTestExecutor.cs @@ -44,7 +44,8 @@ public void RunTests(IEnumerable? tests, IRunContext? runContext, IFra if (testNames.Contains(testCase.FullyQualifiedName)) { using var scopedServiceProvider = serviceProvider.CreateScope(); - RunTest(frameworkHandle, scopedServiceProvider.ServiceProvider, gherkinStep, testCase); + var argumentTransformations = scopedServiceProvider.ServiceProvider.GetServices(); + RunTest(frameworkHandle, scopedServiceProvider.ServiceProvider, gherkinStep, argumentTransformations, testCase); } } } @@ -78,7 +79,8 @@ public void RunTests(IEnumerable? sources, IRunContext? runContext, IFra foreach (var testCase in NGherkinTestDiscoverer.GetTestCases(source, serviceProvider)) { using var scopedServiceProvider = serviceProvider.CreateScope(); - RunTest(frameworkHandle, scopedServiceProvider.ServiceProvider, gherkinStep, testCase); + var argumentTransformations = scopedServiceProvider.ServiceProvider.GetServices(); + RunTest(frameworkHandle, scopedServiceProvider.ServiceProvider, gherkinStep, argumentTransformations, testCase); } } catch (Exception exception) @@ -92,6 +94,7 @@ public void RunTests(IEnumerable? sources, IRunContext? runContext, IFra IFrameworkHandle frameworkHandle, IServiceProvider serviceProvider, IEnumerable gherkinSteps, + IEnumerable argumentTransformations, TestCase testCase) { frameworkHandle.RecordStart(testCase); @@ -109,7 +112,7 @@ public void RunTests(IEnumerable? sources, IRunContext? runContext, IFra foreach (var stepExecutionContext in stepExecutionContexts) { - RunTestStep(stepExecutionContext); + RunTestStep(stepExecutionContext, argumentTransformations); } testResult.Outcome = TestOutcome.Passed; @@ -201,9 +204,9 @@ public void RunTests(IEnumerable? sources, IRunContext? runContext, IFra return stepExecutionContext; } - private void RunTestStep(StepExecutionContext stepExecutionContext) + private void RunTestStep(StepExecutionContext stepExecutionContext, IEnumerable argumentTransformations) { - var arguments = ParseStepArguments(stepExecutionContext); + var arguments = ParseStepArguments(stepExecutionContext, argumentTransformations); var result = stepExecutionContext.Method.Invoke(stepExecutionContext.Service, arguments); if (result?.GetType().GetMethod("GetAwaiter") is MethodInfo getAwaiter) @@ -245,16 +248,29 @@ private string GetRealStepText(Step step, TestExecutionContext testExecutionCont return stepText; } - private object[] ParseStepArguments(StepExecutionContext stepExecutionContext) + private object[] ParseStepArguments(StepExecutionContext stepExecutionContext, IEnumerable argumentTransformations) { try { var parameters = stepExecutionContext.Method.GetParameters(); - var arguments = stepExecutionContext.Parameters.Select((value, index) => Convert.ChangeType(value, parameters[index].ParameterType)); + var arguments = stepExecutionContext.Parameters.Select((value, index) => + { + var argumentValue = argumentTransformations + .Select(argumentTransformation => argumentTransformation(value, parameters[index].ParameterType)) + .FirstOrDefault(x => x != null) ?? Convert.ChangeType(value, parameters[index].ParameterType); + + return argumentValue; + }); + if (stepExecutionContext.StepArgument != null) { - arguments = arguments.Concat([stepExecutionContext.StepArgument]); + var argumentValue = argumentTransformations + .Select(argumentTransformation => argumentTransformation(stepExecutionContext.StepArgument, parameters.Last().ParameterType)) + .FirstOrDefault(x => x != null) ?? stepExecutionContext.StepArgument; + + arguments = arguments.Concat([argumentValue]); } + return arguments.ToArray(); } catch (Exception exception) diff --git a/src/NGherkin.Tests/Features/Feature1.feature b/src/NGherkin.Tests/Features/Feature1.feature index 0cdcd9b..df747c9 100644 --- a/src/NGherkin.Tests/Features/Feature1.feature +++ b/src/NGherkin.Tests/Features/Feature1.feature @@ -14,6 +14,10 @@ Scenario: this is scenario When this is second when step with date '01/01/2020' argument And this is when step with async task Then this is then step + When step with model transformation + | Key | Value | + | 1 | One | + | 2 | Two | Scenario Outline: this is scenario outline When this is when step with with argument '' and value '' diff --git a/src/NGherkin.Tests/Startup.cs b/src/NGherkin.Tests/Startup.cs index 2ad873e..b84ed89 100644 --- a/src/NGherkin.Tests/Startup.cs +++ b/src/NGherkin.Tests/Startup.cs @@ -1,3 +1,4 @@ +using Gherkin.Ast; using Microsoft.Extensions.DependencyInjection; namespace NGherkin.Tests; @@ -8,5 +9,17 @@ public override void Configure(IServiceCollection services) { services.AddGherkinFeatures(); services.AddGherkinSteps(); + + services.AddArgumentTransformation(value => + { + if (value is DataTable dataTable + && dataTable.Rows.Count() > 2 + && dataTable.Rows.First().Cells.Count() == 2) + { + return dataTable.Rows.Skip(1).ToDictionary(x => int.Parse(x.Cells.First().Value), x => x.Cells.Last().Value); + } + + return null; + }); } } diff --git a/src/NGherkin.Tests/Steps/StepClass.cs b/src/NGherkin.Tests/Steps/StepClass.cs index 29909fa..107ce9d 100644 --- a/src/NGherkin.Tests/Steps/StepClass.cs +++ b/src/NGherkin.Tests/Steps/StepClass.cs @@ -55,6 +55,15 @@ public async Task When3() await Task.Yield(); } + [When("step with model transformation")] + public void When4(Dictionary dictionary) + { + if (dictionary.Count != 2 || dictionary[1] != "One" || dictionary[2] != "Two") + { + throw new ArgumentException(nameof(dictionary)); + } + } + [When("this is when step with with argument '(.*)' and value '(.*)'")] public void When4(int number, string text) { diff --git a/src/NGherkin/ArgumentTransformation.cs b/src/NGherkin/ArgumentTransformation.cs new file mode 100644 index 0000000..321e812 --- /dev/null +++ b/src/NGherkin/ArgumentTransformation.cs @@ -0,0 +1,3 @@ +namespace NGherkin; + +public delegate object? ArgumentTransformation(object value, Type targetType); \ No newline at end of file diff --git a/src/NGherkin/ServiceCollectionExtensions.cs b/src/NGherkin/ServiceCollectionExtensions.cs index 02bdd32..8c4dc28 100644 --- a/src/NGherkin/ServiceCollectionExtensions.cs +++ b/src/NGherkin/ServiceCollectionExtensions.cs @@ -8,6 +8,20 @@ namespace NGherkin; public static class ServiceCollectionExtensions { + public static void AddArgumentTransformation(this IServiceCollection services, Func converter) + { + ArgumentTransformation argumentTransformation = (object value, Type targetType) => + { + if (targetType == typeof(T)) + { + return converter(value); + } + return null; + }; + + services.AddSingleton(argumentTransformation); + } + public static void AddGherkinFeatures(this IServiceCollection services) { var assembly = Assembly.GetCallingAssembly() ?? throw new Exception("Unable to get calling assembly");