diff --git a/CHANGELOG.md b/CHANGELOG.md index bde92e1..ca23a68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,5 +16,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `IServiceCollection` extension methods - `String` extension methods - `DateTime` extension methods +- `StringBuilder` extension methods - `IFormFile` extension method (AspNetCore package only) - `DbSet` extension methods for ISortableEntity interface (EntityFrameworkCore package only) diff --git a/Neolution.Utilities.UnitTests/Extensions/StringBuilderExtensionsTests.cs b/Neolution.Utilities.UnitTests/Extensions/StringBuilderExtensionsTests.cs new file mode 100644 index 0000000..178f8a2 --- /dev/null +++ b/Neolution.Utilities.UnitTests/Extensions/StringBuilderExtensionsTests.cs @@ -0,0 +1,92 @@ +namespace Neolution.Utilities.UnitTests.Extensions; + +using System.Text; + +/// +/// Unit tests for the class. +/// +public class StringBuilderExtensionsTests +{ + /// + /// Test that given the null string builder when AppendLine called then throws argument null exception. + /// + [Fact] + public void GivenNullStringBuilder_WhenAppendLineCalled_ThenThrowsArgumentNullException() + { + // Arrange + StringBuilder? sb = null; + + // Act + var act = () => sb!.AppendLine("value", 0); + + // Assert + var ex = Should.Throw(act); + ex.ParamName.ShouldBe("stringBuilder"); + } + + /// + /// Test that given the negative padding when AppendLine called then throws argument out of range exception. + /// + [Fact] + public void GivenNegativePadding_WhenAppendLineCalled_ThenThrowsArgumentOutOfRangeException() + { + // Arrange + var sb = new StringBuilder(); + + // Act + var act = () => sb.AppendLine("value", -1); + + // Assert + var ex = Should.Throw(act); + ex.ParamName.ShouldBe("padding"); + } + + /// + /// Test that given value and padding when AppendLine called then appends expected padded line. + /// + /// The value. + /// The padding. + [Theory] + [InlineData("Test", 0)] + [InlineData("Hello", 4)] + [InlineData("", 3)] + [InlineData(null, 2)] + public void GivenValueAndPadding_WhenAppendLineCalled_ThenAppendsWithPadding(string? value, int padding) + { + // Arrange + var sb = new StringBuilder(); + + // Act + sb.AppendLine(value, padding); + + // Assert + var expected = new string(' ', padding) + (value ?? string.Empty) + Environment.NewLine; + sb.ToString().ShouldBe(expected); + } + + /// + /// Test that given multiple calls when AppendLine called then appends sequentially and returns same instance. + /// + [Fact] + public void GivenMultipleCalls_WhenAppendLineCalled_ThenAppendsSequentiallyAndReturnsSameInstance() + { + // Arrange + var sb = new StringBuilder(); + + // Act + var returned1 = sb.AppendLine("First", 1); + var returned2 = sb.AppendLine("Second", 2); + var returned3 = sb.AppendLine(null, 0); + + // Assert + returned1.ShouldBeSameAs(sb); + returned2.ShouldBeSameAs(sb); + returned3.ShouldBeSameAs(sb); + + var expected = + " First" + Environment.NewLine + + " Second" + Environment.NewLine + + Environment.NewLine; // last call: padding 0 + null value => just newline + sb.ToString().ShouldBe(expected); + } +} diff --git a/Neolution.Utilities/Extensions/StringBuilderExtensions.cs b/Neolution.Utilities/Extensions/StringBuilderExtensions.cs new file mode 100644 index 0000000..da0165c --- /dev/null +++ b/Neolution.Utilities/Extensions/StringBuilderExtensions.cs @@ -0,0 +1,23 @@ +namespace Neolution.Utilities.Extensions; + +using System.Text; + +/// +/// StringBuilder Extensions +/// +public static class StringBuilderExtensions +{ + /// + /// Appends the line with the specified padding + /// + /// The string builder + /// The value + /// The padding + /// A reference to this instance after the append operation has completed. + public static StringBuilder AppendLine(this StringBuilder stringBuilder, string? value, int padding) + { + ArgumentNullException.ThrowIfNull(stringBuilder); + ArgumentOutOfRangeException.ThrowIfNegative(padding); + return stringBuilder.Append(' ', padding).AppendLine(value); + } +}