diff --git a/src/Directory.Build.props b/src/Directory.Build.props index bb07e743..35120582 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -12,5 +12,6 @@ false false false + enable \ No newline at end of file diff --git a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleTableTests.cs b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleTableTests.cs index 90777fb8..2a9f2bbc 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleTableTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleTableTests.cs @@ -53,5 +53,58 @@ public void TableToStringWithAdditionalColumn() table.ToString(new[] { "Additional" }, new[] { new[] { "SomeAdditional Value" } }) .ShouldMatchApproved(); } + + [Fact] + public void Add_WhenColumnCountMismatch_Throws() + { + var table = new ExampleTable("A", "B"); + var ex = Should.Throw(() => table.Add(1, 2, 3)); + ex.Message.ShouldContain("Number of column values does not match"); + } + + [Fact] + public void CollectionOperations_WorkCorrectly() + { + var table = new ExampleTable("A"); + table.Add("val1"); + table.Add("val2"); + + table.Count.ShouldBe(2); + table.IsReadOnly.ShouldBeFalse(); + + var first = table.First(); + table.Contains(first).ShouldBeTrue(); + table.Remove(first).ShouldBeTrue(); + table.Count.ShouldBe(1); + + table.Clear(); + table.Count.ShouldBe(0); + } + + [Fact] + public void CopyTo_CopiesElements() + { + var table = new ExampleTable("A"); + table.Add("x"); + table.Add("y"); + + var array = new Example[3]; + table.CopyTo(array, 1); + + array[0].ShouldBeNull(); + array[1].ShouldNotBeNull(); + array[2].ShouldNotBeNull(); + } + + [Theory] + [InlineData("MyHeader", "my header", true)] + [InlineData("MyHeader", "my_header", true)] + [InlineData("MyHeader", "MYHEADER", true)] + [InlineData("MyHeader", "Other", false)] + [InlineData("MyHeader", null, false)] + public void HeaderMatches_VariousCases(string header, string? name, bool expected) + { + ExampleTable.HeaderMatches(header, name).ShouldBe(expected); + } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleValueTests.cs b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleValueTests.cs index 36b1dfbf..ca27accf 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleValueTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleValueTests.cs @@ -1,4 +1,5 @@ -using Shouldly; +using System; +using Shouldly; using Xunit; namespace TestStack.BDDfy.Tests.Scanner.Examples @@ -13,5 +14,92 @@ public void CanFormatAsStringTests() new ExampleValue("Header", new object(), () => 0).GetValueAsString().ShouldBe("System.Object"); new ExampleValue("Header", new[] {1, 2}, () => 0).GetValueAsString().ShouldBe("1, 2"); } + + [Fact] + public void GetValue_WhenTargetTypeMatchesDirectly_ReturnsValue() + { + var value = new ExampleValue("Col", 42, () => 0); + value.GetValue(typeof(int)).ShouldBe(42); + value.ValueHasBeenUsed.ShouldBeTrue(); + } + + [Fact] + public void GetValue_WhenNullAndTargetIsNullable_ReturnsNull() + { + var value = new ExampleValue("Col", null, () => 0); + value.GetValue(typeof(int?)).ShouldBeNull(); + value.ValueHasBeenUsed.ShouldBeTrue(); + } + + [Fact] + public void GetValue_WhenNullAndTargetIsReferenceType_ReturnsNull() + { + var value = new ExampleValue("Col", null, () => 0); + value.GetValue(typeof(string)).ShouldBeNull(); + } + + [Fact] + public void GetValue_WhenNullAndTargetIsValueType_Throws() + { + var value = new ExampleValue("Col", null, () => 2); + var ex = Should.Throw(() => value.GetValue(typeof(int))); + ex.Message.ShouldContain("Cannot convert to Int32"); + ex.Message.ShouldContain("Column: 'Col'"); + ex.Message.ShouldContain("Row: 3"); + } + + [Theory] + [InlineData("123", typeof(int), 123)] + [InlineData("45.6", typeof(double), 45.6)] + [InlineData("true", typeof(bool), true)] + public void GetValue_UsesConvertChangeType(string input, Type targetType, object expected) + { + var value = new ExampleValue("Col", input, () => 0); + value.GetValue(targetType).ShouldBe(expected); + } + + [Fact] + public void GetValue_WhenEnumString_ParsesEnum() + { + var value = new ExampleValue("Col", "Transition", () => 0); + value.GetValue(typeof(ExecutionOrder)).ShouldBe(ExecutionOrder.Transition); + } + + [Fact] + public void GetValue_WhenDateTimeString_ParsesDateTime() + { + var value = new ExampleValue("Col", "2023-06-15", () => 0); + value.GetValue(typeof(DateTime)).ShouldBe(new DateTime(2023, 6, 15)); + } + + [Fact] + public void GetValue_WhenInvalidCast_ThrowsUnassignableExampleException() + { + var value = new ExampleValue("Col", new object(), () => 1); + var ex = Should.Throw(() => value.GetValue(typeof(int))); + ex.Message.ShouldContain("cannot be assigned to Int32"); + ex.Message.ShouldContain("Column: 'Col'"); + ex.Message.ShouldContain("Row: 2"); + } + + [Theory] + [InlineData("myHeader", "myHeader", true)] + [InlineData("my header", "myHeader", true)] + [InlineData("my_header", "myHeader", true)] + [InlineData("MyHeader", "myheader", true)] + [InlineData("Header1", "Header2", false)] + [InlineData("Header", null, false)] + public void MatchesName_VariousInputs(string header, string? name, bool expected) + { + var value = new ExampleValue(header, "x", () => 0); + value.MatchesName(name).ShouldBe(expected); + } + + [Fact] + public void Row_ReturnsOneBasedIndex() + { + var value = new ExampleValue("Col", "x", () => 4); + value.Row.ShouldBe(5); + } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy.Tests/TypeExtensionsTests.cs b/src/TestStack.BDDfy.Tests/TypeExtensionsTests.cs new file mode 100644 index 00000000..1bf864fc --- /dev/null +++ b/src/TestStack.BDDfy.Tests/TypeExtensionsTests.cs @@ -0,0 +1,60 @@ +using System; +using Shouldly; +using Xunit; + +namespace TestStack.BDDfy.Tests +{ + public class TypeExtensionsTests + { + [Theory] + [InlineData(typeof(int), true)] + [InlineData(typeof(string), false)] + [InlineData(typeof(DateTime), true)] + [InlineData(typeof(object), false)] + public void IsValueType_ReturnsExpected(Type type, bool expected) + { + type.IsValueType().ShouldBe(expected); + } + + [Theory] + [InlineData(typeof(DayOfWeek), true)] + [InlineData(typeof(int), false)] + [InlineData(typeof(string), false)] + public void IsEnum_ReturnsExpected(Type type, bool expected) + { + type.IsEnum().ShouldBe(expected); + } + + [Theory] + [InlineData(typeof(int?), true)] + [InlineData(typeof(System.Collections.Generic.List), true)] + [InlineData(typeof(int), false)] + [InlineData(typeof(string), false)] + public void IsGenericType_ReturnsExpected(Type type, bool expected) + { + type.IsGenericType().ShouldBe(expected); + } + + [Fact] + public void IsInstanceOfType_ReturnsCorrectly() + { + typeof(string).IsInstanceOfType("hello").ShouldBeTrue(); + typeof(int).IsInstanceOfType("hello").ShouldBeFalse(); + typeof(object).IsInstanceOfType(42).ShouldBeTrue(); + } + + [Fact] + public void Assembly_ReturnsCorrectAssembly() + { + typeof(string).Assembly().ShouldBe(typeof(string).Assembly); + } + + [Fact] + public void GetCustomAttributes_ReturnsAttributes() + { + var attrs = typeof(FlagsAttribute).GetCustomAttributes(typeof(AttributeUsageAttribute), true); + attrs.ShouldNotBeEmpty(); + attrs[0].ShouldBeOfType(); + } + } +} diff --git a/src/TestStack.BDDfy.Tests/WithTagsExtensionsTests.cs b/src/TestStack.BDDfy.Tests/WithTagsExtensionsTests.cs new file mode 100644 index 00000000..9875994f --- /dev/null +++ b/src/TestStack.BDDfy.Tests/WithTagsExtensionsTests.cs @@ -0,0 +1,33 @@ +using System.Linq; +using Shouldly; +using Xunit; + +namespace TestStack.BDDfy.Tests +{ + public class WithTagsExtensionsTests + { + [Fact] + public void WithTags_AddsTags_ToTestContext() + { + var testObject = new TestClass(); + var result = testObject.WithTags("tag1", "tag2"); + + result.ShouldBeSameAs(testObject); + var context = TestContext.GetContext(testObject); + context.Tags.ShouldContain("tag1"); + context.Tags.ShouldContain("tag2"); + } + + [Fact] + public void WithTags_CanBeCalledMultipleTimes() + { + var testObject = new TestClass(); + testObject.WithTags("a").WithTags("b", "c"); + + var context = TestContext.GetContext(testObject); + context.Tags.Count.ShouldBe(3); + } + + private class TestClass { } + } +} diff --git a/src/TestStack.BDDfy/Processors/AsyncTestRunner.cs b/src/TestStack.BDDfy/Processors/AsyncTestRunner.cs index 9e6c5ed8..19e48e14 100644 --- a/src/TestStack.BDDfy/Processors/AsyncTestRunner.cs +++ b/src/TestStack.BDDfy/Processors/AsyncTestRunner.cs @@ -7,7 +7,7 @@ namespace TestStack.BDDfy.Processors { public static class AsyncTestRunner { - public static void Run(Func performStep) + public static void Run(Func performStep) { var oldSyncContext = SynchronizationContext.Current; try diff --git a/src/TestStack.BDDfy/TestStack.BDDfy.csproj b/src/TestStack.BDDfy/TestStack.BDDfy.csproj index 26ee1b63..42b5e783 100644 --- a/src/TestStack.BDDfy/TestStack.BDDfy.csproj +++ b/src/TestStack.BDDfy/TestStack.BDDfy.csproj @@ -1,7 +1,6 @@  true - enable