Skip to content

Commit

Permalink
Allow to convert type to same type or one of base types with StepArgu…
Browse files Browse the repository at this point in the history
…mentTransformation (#1110)

* Type to same or derived type conversion added

* Tests added

* Tests fixing

* Fixed by gasparnagy remartks

* Changelog updated
  • Loading branch information
ChernyavskiyAlex authored and gasparnagy committed Apr 28, 2018
1 parent d099aea commit 6c3bfe8
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 18 deletions.
18 changes: 10 additions & 8 deletions TechTalk.SpecFlow/Bindings/StepArgumentTypeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,15 @@ protected virtual IStepArgumentTransformationBinding GetMatchingStepTransformati
public object Convert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
{
if (value == null) throw new ArgumentNullException("value");

if (typeToConvertTo == value.GetType())
return value;


var stepTransformation = GetMatchingStepTransformation(value, typeToConvertTo, true);
if (stepTransformation != null)
return DoTransform(stepTransformation, value, cultureInfo);

var convertToType = typeToConvertTo as RuntimeBindingType;
if (convertToType != null && convertToType.Type.IsAssignableFrom(value.GetType()))
return value;

return ConvertSimple(typeToConvertTo, value, cultureInfo);
}

Expand Down Expand Up @@ -79,15 +80,16 @@ private object[] GetStepTransformationArgumentsFromRegex(IStepArgumentTransforma

public bool CanConvert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
{
if (value == null) throw new ArgumentNullException("value");

if (typeToConvertTo == value.GetType())
return true;
if (value == null) throw new ArgumentNullException("value");

var stepTransformation = GetMatchingStepTransformation(value, typeToConvertTo, false);
if (stepTransformation != null)
return true;

var convertToType = typeToConvertTo as RuntimeBindingType;
if (convertToType != null && convertToType.Type.IsAssignableFrom(value.GetType()))
return true;

return CanConvertSimple(typeToConvertTo, value, cultureInfo);
}

Expand Down
5 changes: 1 addition & 4 deletions TechTalk.SpecFlow/Infrastructure/TestExecutionEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -436,10 +436,7 @@ private object ConvertArg(object value, IBindingType typeToConvertTo)
{
Debug.Assert(value != null);
Debug.Assert(typeToConvertTo != null);

if (typeToConvertTo.IsAssignableTo(value.GetType()))
return value;


return stepArgumentTypeConverter.Convert(value, typeToConvertTo, FeatureContext.BindingCulture);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static object Convert(this IStepArgumentTypeConverter converter, object v
Arg<string>.Is.Equal(argument),
Arg<IBindingType>.Matches(bt => bt.TypeEquals(type)),
Arg<CultureInfo>.Is.Anything);
}
}
}

[Binding]
Expand Down Expand Up @@ -148,6 +148,7 @@ public void ShouldCallTheOnlyThatCanConvertWithTable()
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetCanConvertMethodFilter("argument", typeof(double))).Return(true);
StepArgumentTypeConverterStub.Stub(c => c.CanConvert(null, null, null)).IgnoreArguments().Return(false);

StepArgumentTypeConverterStub.Expect(LegacyStepArgumentTypeConverterExtensions.GetConvertMethodFilter(table, typeof(Table))).Return(table);
StepArgumentTypeConverterStub.Expect(LegacyStepArgumentTypeConverterExtensions.GetConvertMethodFilter("argument", typeof(double))).Return(1.23);
bindingInstance.Expect(b => b.DoubleArgWithTable(1.23, table));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ public void ShouldCallTheUserConverterToConvertTableWithTableAndMultilineArg()

Table table = new Table("h1");
var user = new User();

var multiLineArg = "multi-line arg";
// return false unless its a User
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetCanConvertMethodFilter(table, typeof(User))).Return(true);
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetCanConvertMethodFilter(table, typeof(User))).Return(true);
StepArgumentTypeConverterStub.Stub(c => c.CanConvert(null, null, null)).IgnoreArguments().Return(false);
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetConvertMethodFilter(multiLineArg, typeof(string))).Return(multiLineArg);
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetConvertMethodFilter(table, typeof(User))).Return(user);


var multiLineArg = "multi-line arg";

bindingInstance.Expect(b => b.MultilineArgumentAndTable(multiLineArg, user));
MockRepository.ReplayAll();

Expand All @@ -90,14 +92,16 @@ public void ShouldCallTheUserConverterToConvertTableWithTableAndMultilineArgAndP
Table table = new Table("h1");
string argumentValue = "argument";
var user = new User();

var multiLineArg = "multi-line arg";
// return false unless its a User
// must also stub CanConvert & Convert for the string argument as we've introduced a parameter
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetCanConvertMethodFilter(table, typeof(User))).Return(true);
StepArgumentTypeConverterStub.Stub(c => c.CanConvert(null, null, null)).IgnoreArguments().Return(false);
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetConvertMethodFilter(table, typeof(User))).Return(user);
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetConvertMethodFilter(argumentValue, typeof(string))).Return(argumentValue);
StepArgumentTypeConverterStub.Stub(LegacyStepArgumentTypeConverterExtensions.GetConvertMethodFilter(multiLineArg, typeof(string))).Return(multiLineArg);

var multiLineArg = "multi-line arg";

bindingInstance.Expect(b => b.ParameterMultilineArgumentAndTable(argumentValue, multiLineArg, user));
MockRepository.ReplayAll();

Expand Down
73 changes: 73 additions & 0 deletions Tests/TechTalk.SpecFlow.RuntimeTests/StepTransformationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,32 @@ public IEnumerable<User> CreateUsers(Table table)
}
}

[Binding]
public class TypeToTypeConverter
{
[StepArgumentTransformation("string (w+)")]
public string StringToStringConvertRegex(string value)
{
return string.Concat("prefix ", value);
}

[StepArgumentTransformation]
public string StringToStringConvert(string value)
{
return string.Concat("prefix ", value);
}

[StepArgumentTransformation]
public Table TableToTableConvert(Table table)
{
var transformedTable = new List<string>();
transformedTable.Add("transformed column");
transformedTable.AddRange(table.Header);

return new Table(transformedTable.ToArray());
}
}

[TestFixture]
public class StepTransformationTests
{
Expand Down Expand Up @@ -80,6 +106,53 @@ public void UserConverterShouldConvertStringToUser()
Assert.NotNull(result);
Assert.That(result.GetType(), Is.EqualTo(typeof(User)));
Assert.That(((User)result).Name, Is.EqualTo("xyz"));
}

[Test]
public void TypeToTypeConverterShouldConvertStringToStringUsingRegex()
{
TypeToTypeConverter stepTransformationInstance = new TypeToTypeConverter();
var transformMethod = stepTransformationInstance.GetType().GetMethod("StringToStringConvertRegex");
var stepTransformationBinding = CreateStepTransformationBinding(@"string (\w+)", transformMethod);

Assert.True(stepTransformationBinding.Regex.IsMatch("string xyz"));

var invoker = new BindingInvoker(ConfigurationLoader.GetDefault(), new Mock<IErrorProvider>().Object);
TimeSpan duration;
var result = invoker.InvokeBinding(stepTransformationBinding, contextManagerStub.Object, new object[] { "xyz" }, new Mock<ITestTracer>().Object, out duration);
Assert.NotNull(result);
Assert.That(result.GetType(), Is.EqualTo(typeof(string)));
Assert.That(((string)result), Is.EqualTo("prefix xyz"));
}

[Test]
public void TypeToTypeConverterShouldConvertStringToString()
{
TypeToTypeConverter stepTransformationInstance = new TypeToTypeConverter();
var transformMethod = stepTransformationInstance.GetType().GetMethod("StringToStringConvert");
var stepTransformationBinding = CreateStepTransformationBinding(@"", transformMethod);

var invoker = new BindingInvoker(ConfigurationLoader.GetDefault(), new Mock<IErrorProvider>().Object);
TimeSpan duration;
var result = invoker.InvokeBinding(stepTransformationBinding, contextManagerStub.Object, new object[] { "xyz" }, new Mock<ITestTracer>().Object, out duration);
Assert.NotNull(result);
Assert.That(result.GetType(), Is.EqualTo(typeof(string)));
Assert.That(((string)result), Is.EqualTo("prefix xyz"));
}

[Test]
public void TypeToTypeConverterShouldConvertTableToTable()
{
TypeToTypeConverter stepTransformationInstance = new TypeToTypeConverter();
var transformMethod = stepTransformationInstance.GetType().GetMethod("TableToTableConvert");
var stepTransformationBinding = CreateStepTransformationBinding(@"", transformMethod);

var invoker = new BindingInvoker(ConfigurationLoader.GetDefault(), new Mock<IErrorProvider>().Object);
TimeSpan duration;
var result = invoker.InvokeBinding(stepTransformationBinding, contextManagerStub.Object, new object[] { new Table("h1") }, new Mock<ITestTracer>().Object, out duration);
Assert.NotNull(result);
Assert.That(result.GetType(), Is.EqualTo(typeof(Table)));
Assert.That(((Table)result).Header, Is.EqualTo(new string[] { "transformed column", "h1" }));
}

[Test]
Expand Down
5 changes: 5 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
2.4 - 2018-??-??
New Features:
+ Added ability to convert type to same type or one of the base types https://github.com/techtalk/SpecFlow/pull/1110


Fixes:
+ Expose ScenarioInfo.Description parameter to get from context https://github.com/techtalk/SpecFlow/pull/1078
+ Resolved loading plugins multiple times. Issue: https://github.com/techtalk/SpecFlow/issues/888


2.3.2 - 2018-04-17
Fixes:
+ Fix issue when using environment variables in a generator plugin's path https://github.com/techtalk/SpecFlow/pull/1045
Expand Down

0 comments on commit 6c3bfe8

Please sign in to comment.