diff --git a/src/Mermaid.Flowcharts/Flowchart.cs b/src/Mermaid.Flowcharts/Flowchart.cs index be2ae74..744dce9 100644 --- a/src/Mermaid.Flowcharts/Flowchart.cs +++ b/src/Mermaid.Flowcharts/Flowchart.cs @@ -1,11 +1,9 @@ using System.Text; -using System.Runtime.CompilerServices; using Mermaid.Flowcharts.Links; using Mermaid.Flowcharts.Nodes; using Mermaid.Flowcharts.Styling; using Mermaid.Flowcharts.Subgraphs; -[assembly: InternalsVisibleTo("Mermaid.Flowcharts.Tests")] namespace Mermaid.Flowcharts; public class Flowchart : IMermaidPrintable diff --git a/src/Mermaid.Flowcharts/Links/LinkText.cs b/src/Mermaid.Flowcharts/Links/LinkText.cs index db36705..3954ba7 100644 --- a/src/Mermaid.Flowcharts/Links/LinkText.cs +++ b/src/Mermaid.Flowcharts/Links/LinkText.cs @@ -27,12 +27,9 @@ public LinkText() { } private LinkText(NonEmptyString text) => Value = text; - public static LinkText FromString(string value) + public static LinkText FromString(string text) { - if (string.IsNullOrWhiteSpace(value)) - { - return new(value); - } + NonEmptyString value = NonEmptyString.FromString(text); // Split on all variations of
tags string[] segments = MermaidAcceptedHtmlLineBreaks.Split(value.ReplaceLineEndings()); @@ -61,7 +58,7 @@ public static LinkText FromString(string value) } } - return new(builder.ToString()); + return new(NonEmptyString.FromString(builder.ToString())); } public override string ToString() diff --git a/src/Mermaid.Flowcharts/Mermaid.Flowcharts.csproj b/src/Mermaid.Flowcharts/Mermaid.Flowcharts.csproj index aee34b8..25d68c6 100644 --- a/src/Mermaid.Flowcharts/Mermaid.Flowcharts.csproj +++ b/src/Mermaid.Flowcharts/Mermaid.Flowcharts.csproj @@ -30,4 +30,8 @@ + + + + diff --git a/src/Mermaid.Flowcharts/Nodes/NodeText/MarkdownText.cs b/src/Mermaid.Flowcharts/Nodes/NodeText/MarkdownText.cs index 2e99c8a..e827f9d 100644 --- a/src/Mermaid.Flowcharts/Nodes/NodeText/MarkdownText.cs +++ b/src/Mermaid.Flowcharts/Nodes/NodeText/MarkdownText.cs @@ -23,15 +23,11 @@ private MarkdownText(NonEmptyString text) public static MarkdownText FromString(string text) { - if (string.IsNullOrWhiteSpace(text)) - { - return new(text); - } + NonEmptyString nonEmpty = NonEmptyString.FromString(text); - NonEmptyString nonEmpty = text; StringBuilder builder = new(); builder.Append('`'); - foreach (char character in (string)nonEmpty) + foreach (char character in nonEmpty.AsSpan()) { if (EscapedCharacters.TryGetValue(character, out string? escapedValue)) { @@ -43,7 +39,7 @@ public static MarkdownText FromString(string text) } } builder.Append('`'); - return new MarkdownText(builder.ToString()); + return new(NonEmptyString.FromString(builder.ToString())); } public override string ToString() diff --git a/src/Mermaid.Flowcharts/Nodes/NodeText/MermaidUnicodeText.cs b/src/Mermaid.Flowcharts/Nodes/NodeText/MermaidUnicodeText.cs index 2e9c24f..a751485 100644 --- a/src/Mermaid.Flowcharts/Nodes/NodeText/MermaidUnicodeText.cs +++ b/src/Mermaid.Flowcharts/Nodes/NodeText/MermaidUnicodeText.cs @@ -29,9 +29,10 @@ private MermaidUnicodeText(NonEmptySingleLineString text) public static MermaidUnicodeText FromString(string text) { - NonEmptySingleLineString nonEmptySingleLine = text; + NonEmptySingleLineString nonEmptySingleLine = NonEmptySingleLineString.FromString(text); + StringBuilder builder = new(); - foreach (char character in (string)nonEmptySingleLine) + foreach (char character in nonEmptySingleLine.AsSpan()) { if (EscapedCharacters.TryGetValue(character, out string? escapedValue)) { @@ -42,7 +43,7 @@ public static MermaidUnicodeText FromString(string text) builder.Append(character); } } - return new MermaidUnicodeText(builder.ToString()); + return new(NonEmptySingleLineString.FromString(builder.ToString())); } public override string ToString() diff --git a/src/Mermaid.Flowcharts/NonEmptyStringTypes/NonEmptySingleLineString.cs b/src/Mermaid.Flowcharts/NonEmptyStringTypes/NonEmptySingleLineString.cs index 6691de9..60d266c 100644 --- a/src/Mermaid.Flowcharts/NonEmptyStringTypes/NonEmptySingleLineString.cs +++ b/src/Mermaid.Flowcharts/NonEmptyStringTypes/NonEmptySingleLineString.cs @@ -2,23 +2,42 @@ namespace Mermaid.Flowcharts.NonEmptyStringTypes; -public readonly record struct NonEmptySingleLineString +internal readonly record struct NonEmptySingleLineString { public static readonly SearchValues NewLineSearchValues = SearchValues.Create("\n\r\u2028\u2029\u0085"); public NonEmptyString Value { get; } - public NonEmptySingleLineString(NonEmptyString value) + [Obsolete(error: true, message: $"Please use the factory methods instead of the default constructor to create a new {nameof(NonEmptySingleLineString)}.")] +#pragma warning disable CS8618 // This constructor is never used + public NonEmptySingleLineString() { } +#pragma warning restore CS8618 + private NonEmptySingleLineString(NonEmptyString value) { - if (value.Value.AsSpan().IndexOfAny(NewLineSearchValues) > -1) + Value = value; + } + + public static NonEmptySingleLineString FromString(string value) + { + NonEmptyString nonEmpty = NonEmptyString.FromString(value); + + if (nonEmpty.AsSpan().IndexOfAny(NewLineSearchValues) > -1) { throw new ArgumentException("Non-empty single line string must not contain any newline characters or carriage returns.", nameof(value)); } - Value = value; + return new(nonEmpty); } + public ReadOnlySpan AsSpan() + => Value.AsSpan(); + + public bool Contains(char value) + => Value.Contains(value); + + public NonEmptySingleLineString Trim() + => FromString(Value.Trim()); + public static implicit operator string(NonEmptySingleLineString nesls) => nesls.Value; - public static implicit operator NonEmptySingleLineString(string s) => new(s); public override string ToString() => Value; diff --git a/src/Mermaid.Flowcharts/NonEmptyStringTypes/NonEmptyString.cs b/src/Mermaid.Flowcharts/NonEmptyStringTypes/NonEmptyString.cs index 714d4c9..d58cf3f 100644 --- a/src/Mermaid.Flowcharts/NonEmptyStringTypes/NonEmptyString.cs +++ b/src/Mermaid.Flowcharts/NonEmptyStringTypes/NonEmptyString.cs @@ -1,22 +1,44 @@ namespace Mermaid.Flowcharts.NonEmptyStringTypes; -public readonly record struct NonEmptyString +internal readonly record struct NonEmptyString { - public string Value { get; } + private readonly string _value; + public string Value => _value ?? throw new InvalidOperationException($"{nameof(NonEmptyString)} value must never be null. Make sure you use the {nameof(FromString)} factory method to construct a new {nameof(NonEmptyString)}."); - public NonEmptyString(string value) + [Obsolete(error: true, message: $"Please use the factory methods instead of the default constructor to create a new {nameof(NonEmptyString)}.")] +#pragma warning disable CS8618 // This constructor is never used + public NonEmptyString() { } +#pragma warning restore CS8618 + private NonEmptyString(string value) + { + _value = value; + } + + public static NonEmptyString FromString(string value) { if (string.IsNullOrWhiteSpace(value)) { throw new ArgumentException("Non-empty string must not be null or empty or whitespace.", nameof(value)); } - Value = value; + return new(value); } + public ReadOnlySpan AsSpan() + => Value.AsSpan(); + + public bool Contains(char value) + => Value.Contains(value); + + public NonEmptyString ReplaceLineEndings(string replacementText = "\n") + => FromString(Value.ReplaceLineEndings(replacementText)); + + public NonEmptyString Trim() + => FromString(Value.Trim()); + public static implicit operator string(NonEmptyString nes) => nes.Value; - public static implicit operator NonEmptyString(string s) => new(s); public override string ToString() => Value; } + diff --git a/src/Mermaid.Flowcharts/Numerical/Percentage.cs b/src/Mermaid.Flowcharts/Numerical/Percentage.cs index ae1ed3e..151ac4a 100644 --- a/src/Mermaid.Flowcharts/Numerical/Percentage.cs +++ b/src/Mermaid.Flowcharts/Numerical/Percentage.cs @@ -4,21 +4,30 @@ namespace Mermaid.Flowcharts.Numerical; { public double Value { get; } - public Percentage(double value) + [Obsolete(error: true, message: $"Please use the factory methods instead of the default constructor to create a new {nameof(Percentage)}.")] +#pragma warning disable CS8618 // This constructor is never used + public Percentage() { } +#pragma warning restore CS8618 + private Percentage(double value) + { + Value = value; + } + + public static Percentage FromDouble(double value) { if (double.IsNaN(value) || double.IsInfinity(value)) { throw new ArgumentOutOfRangeException(nameof(value), "Percentage must be a real and finite number."); } - ArgumentOutOfRangeException.ThrowIfLessThan(value, 0.0, "Percentage must not be negative."); + if (value < 0.0) + { + throw new ArgumentOutOfRangeException(nameof(value), "Percentage must not be negative."); + } - Value = value; + return new(value); } - public static implicit operator Percentage(double value) - => new(value); - public string ToNumericalString() => $"{Value.ToNumberString()}%"; } diff --git a/src/Mermaid.Flowcharts/Numerical/UnitInterval.cs b/src/Mermaid.Flowcharts/Numerical/UnitInterval.cs index 4cd7e28..6cc6f35 100644 --- a/src/Mermaid.Flowcharts/Numerical/UnitInterval.cs +++ b/src/Mermaid.Flowcharts/Numerical/UnitInterval.cs @@ -4,22 +4,34 @@ namespace Mermaid.Flowcharts.Numerical; { public double Value { get; } - public UnitInterval(double value) + [Obsolete(error: true, message: $"Please use the factory method instead of the default constructor to create a new {nameof(UnitInterval)}.")] +#pragma warning disable CS8618 // This constructor is never used + public UnitInterval() { } +#pragma warning restore CS8618 + private UnitInterval(double value) + { + Value = value; + } + + public static UnitInterval FromDouble(double value) { if (double.IsNaN(value) || double.IsInfinity(value)) { throw new ArgumentOutOfRangeException(nameof(value), "Unit interval must be a real number between 0 and 1."); } - ArgumentOutOfRangeException.ThrowIfLessThan(value, 0.0, "Unit interval should be at least 0."); - ArgumentOutOfRangeException.ThrowIfGreaterThan(value, 1.0, "Unit interval should be at most 1."); - - Value = value; - } + if (value < 0.0) + { + throw new ArgumentOutOfRangeException(nameof(value), "Unit interval should be at least 0."); + } - public static implicit operator UnitInterval(double value) - => new(value); + if (value > 1.0) + { + throw new ArgumentOutOfRangeException(nameof(value), "Unit interval should be at most 1."); + } + return new(value); + } public string ToNumericalString() => Value.ToNumberString(); diff --git a/src/Mermaid.Flowcharts/StringExtensions.cs b/src/Mermaid.Flowcharts/StringExtensions.cs index 27b6958..f5b8e06 100644 --- a/src/Mermaid.Flowcharts/StringExtensions.cs +++ b/src/Mermaid.Flowcharts/StringExtensions.cs @@ -1,6 +1,6 @@ namespace Mermaid.Flowcharts; -public static class StringExtensions +internal static class StringExtensions { public static string Repeat(this string text, int count) { diff --git a/src/Mermaid.Flowcharts/Styling/Attributes/Color.cs b/src/Mermaid.Flowcharts/Styling/Attributes/Color.cs index 15dd7b6..979086d 100644 --- a/src/Mermaid.Flowcharts/Styling/Attributes/Color.cs +++ b/src/Mermaid.Flowcharts/Styling/Attributes/Color.cs @@ -9,9 +9,10 @@ public readonly record struct Color(byte Red, byte Green, byte Blue) : ICssAttri public static Color FromRGB(byte red, byte green, byte blue) => new(red, green, blue); - public static Color FromHex(NonEmptySingleLineString hex) + public static Color FromHex(string hex) { - string s = ((string)hex).Trim(); + NonEmptySingleLineString nes = NonEmptySingleLineString.FromString(hex); + string s = nes.Trim(); if (s.Length == 0) { throw new ArgumentException("Hex color must not be empty or whitespace.", nameof(hex)); diff --git a/src/Mermaid.Flowcharts/Styling/Attributes/DashOffset.cs b/src/Mermaid.Flowcharts/Styling/Attributes/DashOffset.cs index bd166be..4f94088 100644 --- a/src/Mermaid.Flowcharts/Styling/Attributes/DashOffset.cs +++ b/src/Mermaid.Flowcharts/Styling/Attributes/DashOffset.cs @@ -50,7 +50,7 @@ public NumericalDashOffset(double size) } public static LengthDashOffset Length(double size, Unit unit) => new(size, unit); - public static PercentageDashOffset Percentage(Percentage percentageOffset) => new(percentageOffset); + public static PercentageDashOffset Percentage(double percentageOffset) => new(Numerical.Percentage.FromDouble(percentageOffset)); public static NumericalDashOffset Number(double size) => new(size); public string ToMermaidString() diff --git a/src/Mermaid.Flowcharts/Styling/Attributes/DashSize.cs b/src/Mermaid.Flowcharts/Styling/Attributes/DashSize.cs index 6ad067a..c11aaf5 100644 --- a/src/Mermaid.Flowcharts/Styling/Attributes/DashSize.cs +++ b/src/Mermaid.Flowcharts/Styling/Attributes/DashSize.cs @@ -53,7 +53,7 @@ public NumericalDashSize(double size) } public static LengthDashSize Length(double size, Unit unit) => new(size, unit); - public static PercentageDashSize Percentage(Percentage percentageSize) => new(percentageSize); + public static PercentageDashSize Percentage(double percentageSize) => new(Numerical.Percentage.FromDouble(percentageSize)); public static NumericalDashSize Number(double size) => new(size); public string ToMermaidString() diff --git a/src/Mermaid.Flowcharts/Styling/Attributes/Fonts/FontFamilyComponent.cs b/src/Mermaid.Flowcharts/Styling/Attributes/Fonts/FontFamilyComponent.cs index cdfa763..70b2d50 100644 --- a/src/Mermaid.Flowcharts/Styling/Attributes/Fonts/FontFamilyComponent.cs +++ b/src/Mermaid.Flowcharts/Styling/Attributes/Fonts/FontFamilyComponent.cs @@ -5,21 +5,22 @@ namespace Mermaid.Flowcharts.Styling.Attributes.Fonts; public partial record FontFamilyComponent { - public NonEmptySingleLineString Value { get; } + public string Value { get; } - public FontFamilyComponent(NonEmptySingleLineString value) + public FontFamilyComponent(string name) { - if (((string)value).Contains('"') || ((string)value).Contains('\'')) + NonEmptySingleLineString nes = NonEmptySingleLineString.FromString(name); + if (nes.Contains('"') || nes.Contains('\'')) { - throw new ArgumentException("Font family component must not contain single or double quotes.", nameof(value)); + throw new ArgumentException("Font family component must not contain single or double quotes.", nameof(name)); } - if (!SpaceOrHyphenSeparatedWordsRegex().IsMatch(value)) + if (!SpaceOrHyphenSeparatedWordsRegex().IsMatch(nes.AsSpan())) { - throw new ArgumentException("Font family component must only contain words that are separated by at most one space.", nameof(value)); + throw new ArgumentException("Font family component must only contain words that are separated by at most one space.", nameof(name)); } - Value = value; + Value = nes; } [GeneratedRegex("^[a-zA-Z]+([ -][a-zA-Z]+)*$")] diff --git a/src/Mermaid.Flowcharts/Styling/Attributes/Fonts/FontSize.cs b/src/Mermaid.Flowcharts/Styling/Attributes/Fonts/FontSize.cs index 4105502..a8ca4f6 100644 --- a/src/Mermaid.Flowcharts/Styling/Attributes/Fonts/FontSize.cs +++ b/src/Mermaid.Flowcharts/Styling/Attributes/Fonts/FontSize.cs @@ -27,7 +27,7 @@ public LengthFontSize(double size, Unit unit) public static AbsoluteFontSize Absolute(AbsoluteSize size) => new(size); public static RelativeFontSize Relative(RelativeSize size) => new(size); - public static PercentageFontSize Percentage(Percentage sizePercentage) => new(sizePercentage); + public static PercentageFontSize Percentage(double sizePercentage) => new(Numerical.Percentage.FromDouble(sizePercentage)); public static LengthFontSize Length(double size, Unit unit) => new(size, unit); public string ToMermaidString() diff --git a/src/Mermaid.Flowcharts/Styling/Attributes/Opacity.cs b/src/Mermaid.Flowcharts/Styling/Attributes/Opacity.cs index 5392a36..aa5d43b 100644 --- a/src/Mermaid.Flowcharts/Styling/Attributes/Opacity.cs +++ b/src/Mermaid.Flowcharts/Styling/Attributes/Opacity.cs @@ -5,9 +5,18 @@ namespace Mermaid.Flowcharts.Styling.Attributes; public readonly record struct Opacity : ICssAttribute { - public double Value { get; } + public UnitInterval Interval { get; } - public Opacity(double value) + [Obsolete(error: true, message: $"Please use the factory methods instead of the default constructor to create a new {nameof(Opacity)}.")] +#pragma warning disable CS8618 // This constructor is never used + public Opacity() { } +#pragma warning restore CS8618 + private Opacity(UnitInterval value) + { + Interval = value; + } + + public static Opacity FromDouble(double value) { if (double.IsNaN(value)) { @@ -24,11 +33,9 @@ public Opacity(double value) throw new ArgumentOutOfRangeException(nameof(value), "Opacity must not be greater than 1."); } - Value = value; + return new(UnitInterval.FromDouble(value)); } - public static implicit operator Opacity(double value) => new(value); - public string ToCss() - => Value.ToNumberString(); + => Interval.Value.ToNumberString(); } diff --git a/src/Mermaid.Flowcharts/Styling/Attributes/StrokeWidth.cs b/src/Mermaid.Flowcharts/Styling/Attributes/StrokeWidth.cs index 89c0fa5..3bcf101 100644 --- a/src/Mermaid.Flowcharts/Styling/Attributes/StrokeWidth.cs +++ b/src/Mermaid.Flowcharts/Styling/Attributes/StrokeWidth.cs @@ -40,7 +40,7 @@ public NumericalStrokeWidth(double width) } public static LengthStrokeWidth Length(double width, Unit unit) => new(width, unit); - public static PercentageStrokeWidth Percentage(Percentage percentageWidth) => new(percentageWidth); + public static PercentageStrokeWidth Percentage(double percentageWidth) => new(Numerical.Percentage.FromDouble(percentageWidth)); public static NumericalStrokeWidth Number(double width) => new(width); public string ToMermaidString() diff --git a/src/Mermaid.Flowcharts/Styling/EnumExtensions.cs b/src/Mermaid.Flowcharts/Styling/EnumExtensions.cs index a476017..c6beb37 100644 --- a/src/Mermaid.Flowcharts/Styling/EnumExtensions.cs +++ b/src/Mermaid.Flowcharts/Styling/EnumExtensions.cs @@ -2,7 +2,7 @@ namespace Mermaid.Flowcharts.Styling; -public static class EnumExtensions +internal static class EnumExtensions { public static string ToAbsoluteSizeString(this AbsoluteSize absoluteSize) => absoluteSize switch diff --git a/src/Mermaid.Flowcharts/Styling/StyleOpacity.cs b/src/Mermaid.Flowcharts/Styling/StyleOpacity.cs index 61e447d..d3e4598 100644 --- a/src/Mermaid.Flowcharts/Styling/StyleOpacity.cs +++ b/src/Mermaid.Flowcharts/Styling/StyleOpacity.cs @@ -2,8 +2,15 @@ namespace Mermaid.Flowcharts.Styling; -public record StyleOpacity(Opacity Opacity) : IStyleClassComponent +public record StyleOpacity : IStyleClassComponent { + public Opacity Opacity { get; } + + public StyleOpacity(double opacity) + { + Opacity = Opacity.FromDouble(opacity); + } + public string ToMermaidString() => $"opacity:{Opacity.ToCss()}"; } diff --git a/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptySingleLineStringTests.cs b/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptySingleLineStringTests.cs index 0793084..7e80fe9 100644 --- a/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptySingleLineStringTests.cs +++ b/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptySingleLineStringTests.cs @@ -8,10 +8,10 @@ public class NonEmptySingleLineStringTests public void Constructor_WithValidSingleLineString_ShouldSetValue() { // Arrange - NonEmptyString input = new("valid single line"); + string input = "valid single line"; // Act - NonEmptySingleLineString result = new(input); + NonEmptySingleLineString result = NonEmptySingleLineString.FromString(input); // Assert Assert.Equal(input, result.Value); @@ -21,10 +21,10 @@ public void Constructor_WithValidSingleLineString_ShouldSetValue() public void Constructor_WithStringContainingNewline_ShouldThrowArgumentException() { // Arrange - NonEmptyString input = new("line1\nline2"); + string input = "line1\nline2"; // Act & Assert - ArgumentException exception = Assert.Throws(() => new NonEmptySingleLineString(input)); + ArgumentException exception = Assert.Throws(() => NonEmptySingleLineString.FromString(input)); Assert.Contains("Non-empty single line string must not contain any newline characters or carriage returns", exception.Message); Assert.Equal("value", exception.ParamName); } @@ -33,10 +33,10 @@ public void Constructor_WithStringContainingNewline_ShouldThrowArgumentException public void Constructor_WithStringContainingCarriageReturn_ShouldThrowArgumentException() { // Arrange - NonEmptyString input = new("line1\rline2"); + string input = "line1\rline2"; // Act & Assert - ArgumentException exception = Assert.Throws(() => new NonEmptySingleLineString(input)); + ArgumentException exception = Assert.Throws(() => NonEmptySingleLineString.FromString(input)); Assert.Contains("Non-empty single line string must not contain any newline characters or carriage returns", exception.Message); Assert.Equal("value", exception.ParamName); } @@ -45,10 +45,10 @@ public void Constructor_WithStringContainingCarriageReturn_ShouldThrowArgumentEx public void Constructor_WithStringContainingBothNewlineAndCarriageReturn_ShouldThrowArgumentException() { // Arrange - NonEmptyString input = new("line1\r\nline2"); + string input = "line1\r\nline2"; // Act & Assert - ArgumentException exception = Assert.Throws(() => new NonEmptySingleLineString(input)); + ArgumentException exception = Assert.Throws(() => NonEmptySingleLineString.FromString(input)); Assert.Contains("Non-empty single line string must not contain any newline characters or carriage returns", exception.Message); } @@ -60,7 +60,7 @@ public void Constructor_WithStringContainingBothNewlineAndCarriageReturn_ShouldT public void Constructor_WithValidSingleLineStrings_ShouldSucceed(string validText) { // Act & Assert (should not throw) - NonEmptySingleLineString result = new(new NonEmptyString(validText)); + NonEmptySingleLineString result = NonEmptySingleLineString.FromString(validText); Assert.Equal(validText, result.Value); } @@ -68,7 +68,7 @@ public void Constructor_WithValidSingleLineStrings_ShouldSucceed(string validTex public void ImplicitConversionToString_ShouldReturnValue() { // Arrange - NonEmptySingleLineString nesls = new(new NonEmptyString("test")); + NonEmptySingleLineString nesls = NonEmptySingleLineString.FromString("test"); // Act string result = nesls; @@ -84,7 +84,7 @@ public void ImplicitConversionFromString_WithValidString_ShouldCreateInstance() string input = "test"; // Act - NonEmptySingleLineString result = input; + NonEmptySingleLineString result = NonEmptySingleLineString.FromString(input); // Assert Assert.Equal(input, result.Value); @@ -97,7 +97,7 @@ public void ImplicitConversionFromString_WithNull_ShouldThrowArgumentException() // Act & Assert Assert.Throws(() => { - NonEmptySingleLineString result = null!; + NonEmptySingleLineString result = NonEmptySingleLineString.FromString(null!); }); } @@ -108,7 +108,7 @@ public void ImplicitConversionFromString_WithEmptyString_ShouldThrowArgumentExce // Act & Assert Assert.Throws(() => { - NonEmptySingleLineString result = ""; + NonEmptySingleLineString result = NonEmptySingleLineString.FromString(""); }); } @@ -118,7 +118,7 @@ public void ImplicitConversionFromString_WithNewline_ShouldThrowArgumentExceptio // Act & Assert Assert.Throws(() => { - NonEmptySingleLineString result = "line1\nline2"; + NonEmptySingleLineString result = NonEmptySingleLineString.FromString("line1\nline2"); }); } @@ -128,7 +128,7 @@ public void ImplicitConversionFromString_WithCarriageReturn_ShouldThrowArgumentE // Act & Assert Assert.Throws(() => { - NonEmptySingleLineString result = "line1\rline2"; + NonEmptySingleLineString result = NonEmptySingleLineString.FromString("line1\rline2"); }); } @@ -136,7 +136,7 @@ public void ImplicitConversionFromString_WithCarriageReturn_ShouldThrowArgumentE public void ToString_ShouldReturnValue() { // Arrange - NonEmptySingleLineString nesls = new(new NonEmptyString("test value")); + NonEmptySingleLineString nesls = NonEmptySingleLineString.FromString("test value"); // Act string result = nesls.ToString(); @@ -149,8 +149,8 @@ public void ToString_ShouldReturnValue() public void Equality_WithSameValue_ShouldBeEqual() { // Arrange - NonEmptySingleLineString nesls1 = new(new NonEmptyString("same")); - NonEmptySingleLineString nesls2 = new(new NonEmptyString("same")); + NonEmptySingleLineString nesls1 = NonEmptySingleLineString.FromString("same"); + NonEmptySingleLineString nesls2 = NonEmptySingleLineString.FromString("same"); // Act & Assert Assert.Equal(nesls1, nesls2); @@ -162,8 +162,8 @@ public void Equality_WithSameValue_ShouldBeEqual() public void Equality_WithDifferentValues_ShouldNotBeEqual() { // Arrange - NonEmptySingleLineString nesls1 = new(new NonEmptyString("different1")); - NonEmptySingleLineString nesls2 = new(new NonEmptyString("different2")); + NonEmptySingleLineString nesls1 = NonEmptySingleLineString.FromString("different1"); + NonEmptySingleLineString nesls2 = NonEmptySingleLineString.FromString("different2"); // Act & Assert Assert.NotEqual(nesls1, nesls2); @@ -175,8 +175,8 @@ public void Equality_WithDifferentValues_ShouldNotBeEqual() public void GetHashCode_WithSameValue_ShouldHaveSameHashCode() { // Arrange - NonEmptySingleLineString nesls1 = new(new NonEmptyString("same")); - NonEmptySingleLineString nesls2 = new(new NonEmptyString("same")); + NonEmptySingleLineString nesls1 = NonEmptySingleLineString.FromString("same"); + NonEmptySingleLineString nesls2 = NonEmptySingleLineString.FromString("same"); // Act & Assert Assert.Equal(nesls1.GetHashCode(), nesls2.GetHashCode()); @@ -191,7 +191,7 @@ public void Constructor_WithUnicodeLineSeparators_ShouldThrowArgumentException(s { // Updated: These should now be rejected as line separators // Act & Assert - ArgumentException exception = Assert.Throws(() => new NonEmptySingleLineString(new NonEmptyString(textWithUnicodeLineSeparators))); + ArgumentException exception = Assert.Throws(() => NonEmptySingleLineString.FromString(textWithUnicodeLineSeparators)); Assert.Contains("Non-empty single line string must not contain any newline characters or carriage returns", exception.Message); } } diff --git a/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptyStringTests.cs b/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptyStringTests.cs index 7653537..768eeb9 100644 --- a/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptyStringTests.cs +++ b/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptyStringTests.cs @@ -11,7 +11,7 @@ public void Constructor_WithValidString_ShouldSetValue() string input = "valid string"; // Act - NonEmptyString result = new(input); + NonEmptyString result = NonEmptyString.FromString(input); // Assert Assert.Equal(input, result.Value); @@ -21,7 +21,7 @@ public void Constructor_WithValidString_ShouldSetValue() public void Constructor_WithNull_ShouldThrowArgumentException() { // Act & Assert - ArgumentException exception = Assert.Throws(() => new NonEmptyString(null!)); + ArgumentException exception = Assert.Throws(() => NonEmptyString.FromString(null!)); Assert.Contains("Non-empty string must not be null or empty", exception.Message); Assert.Equal("value", exception.ParamName); } @@ -30,7 +30,7 @@ public void Constructor_WithNull_ShouldThrowArgumentException() public void Constructor_WithEmptyString_ShouldThrowArgumentException() { // Act & Assert - ArgumentException exception = Assert.Throws(() => new NonEmptyString("")); + ArgumentException exception = Assert.Throws(() => NonEmptyString.FromString("")); Assert.Contains("Non-empty string must not be null or empty", exception.Message); Assert.Equal("value", exception.ParamName); } @@ -45,7 +45,7 @@ public void Constructor_WithWhitespaceOnly_ShouldThrowArgumentException(string w { // Updated: whitespace-only strings should now be rejected // Act & Assert - ArgumentException exception = Assert.Throws(() => new NonEmptyString(whitespace)); + ArgumentException exception = Assert.Throws(() => NonEmptyString.FromString(whitespace)); Assert.Contains("Non-empty string must not be null or empty", exception.Message); Assert.Equal("value", exception.ParamName); } @@ -54,7 +54,7 @@ public void Constructor_WithWhitespaceOnly_ShouldThrowArgumentException(string w public void ImplicitConversionToString_ShouldReturnValue() { // Arrange - NonEmptyString nes = new("test"); + NonEmptyString nes = NonEmptyString.FromString("test"); // Act string result = nes; @@ -70,7 +70,7 @@ public void ImplicitConversionFromString_WithValidString_ShouldCreateInstance() string input = "test"; // Act - NonEmptyString result = input; + NonEmptyString result = NonEmptyString.FromString(input); // Assert Assert.Equal(input, result.Value); @@ -82,7 +82,7 @@ public void ImplicitConversionFromString_WithNull_ShouldThrowArgumentException() // Act & Assert Assert.Throws(() => { - NonEmptyString result = null!; + NonEmptyString result = NonEmptyString.FromString(null!); }); } @@ -92,7 +92,7 @@ public void ImplicitConversionFromString_WithEmptyString_ShouldThrowArgumentExce // Act & Assert Assert.Throws(() => { - NonEmptyString result = ""; + NonEmptyString result = NonEmptyString.FromString(""); }); } @@ -100,7 +100,7 @@ public void ImplicitConversionFromString_WithEmptyString_ShouldThrowArgumentExce public void ToString_ShouldReturnValue() { // Arrange - NonEmptyString nes = new("test value"); + NonEmptyString nes = NonEmptyString.FromString("test value"); // Act string result = nes.ToString(); @@ -113,8 +113,8 @@ public void ToString_ShouldReturnValue() public void Equality_WithSameValue_ShouldBeEqual() { // Arrange - NonEmptyString nes1 = new("same"); - NonEmptyString nes2 = new("same"); + NonEmptyString nes1 = NonEmptyString.FromString("same"); + NonEmptyString nes2 = NonEmptyString.FromString("same"); // Act & Assert Assert.Equal(nes1, nes2); @@ -126,8 +126,8 @@ public void Equality_WithSameValue_ShouldBeEqual() public void Equality_WithDifferentValues_ShouldNotBeEqual() { // Arrange - NonEmptyString nes1 = new("different1"); - NonEmptyString nes2 = new("different2"); + NonEmptyString nes1 = NonEmptyString.FromString("different1"); + NonEmptyString nes2 = NonEmptyString.FromString("different2"); // Act & Assert Assert.NotEqual(nes1, nes2); @@ -139,8 +139,8 @@ public void Equality_WithDifferentValues_ShouldNotBeEqual() public void GetHashCode_WithSameValue_ShouldHaveSameHashCode() { // Arrange - NonEmptyString nes1 = new("same"); - NonEmptyString nes2 = new("same"); + NonEmptyString nes1 = NonEmptyString.FromString("same"); + NonEmptyString nes2 = NonEmptyString.FromString("same"); // Act & Assert Assert.Equal(nes1.GetHashCode(), nes2.GetHashCode()); diff --git a/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptyStringTypeIntegrationTests.cs b/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptyStringTypeIntegrationTests.cs index 56916a3..27cc380 100644 --- a/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptyStringTypeIntegrationTests.cs +++ b/tests/Mermaid.Flowcharts.Tests/NonEmptyStringTypes/NonEmptyStringTypeIntegrationTests.cs @@ -9,7 +9,7 @@ public class NonEmptyStringTypeIntegrationTests public void NonEmptySingleLineString_CanBeAssignedToNonEmptyString() { // Arrange - NonEmptySingleLineString nesls = new(new NonEmptyString("test")); + NonEmptySingleLineString nesls = NonEmptySingleLineString.FromString("test"); // Act NonEmptyString nes = nesls.Value; @@ -25,27 +25,10 @@ public void ChainedImplicitConversions_ShouldWork() string original = "test string"; // Act - chain conversions - NonEmptySingleLineString nesls = original; + NonEmptySingleLineString nesls = NonEmptySingleLineString.FromString(original); string result = nesls; // Assert Assert.Equal(original, result); } - - [Fact] - public void MixedUsageInCollections_ShouldWork() - { - // Arrange - string[] strings = ["first", "second", "third"]; - - // Act - NonEmptyString[] nonEmptyStrings = [.. strings.Select(s => (NonEmptyString)s)]; - NonEmptySingleLineString[] singleLineStrings = [.. nonEmptyStrings.Select(nes => new NonEmptySingleLineString(nes))]; - - // Assert - Assert.Equal(3, singleLineStrings.Length); - Assert.Equal("first", singleLineStrings[0].Value); - Assert.Equal("second", singleLineStrings[1].Value); - Assert.Equal("third", singleLineStrings[2].Value); - } } diff --git a/tests/Mermaid.Flowcharts.Tests/Numerical/PercentageTests.cs b/tests/Mermaid.Flowcharts.Tests/Numerical/PercentageTests.cs index 09fee8d..3a0393d 100644 --- a/tests/Mermaid.Flowcharts.Tests/Numerical/PercentageTests.cs +++ b/tests/Mermaid.Flowcharts.Tests/Numerical/PercentageTests.cs @@ -13,7 +13,7 @@ public void Percentage_WhenValueIsNonFinite_ShouldThrow(double invalid) { // Act ArgumentOutOfRangeException? ex = Assert.Throws( - () => new Percentage(invalid) + () => Percentage.FromDouble(invalid) ); // Assert @@ -28,7 +28,7 @@ public void Percentage_WhenNegative_ShouldThrow(double negative) { // Act ArgumentOutOfRangeException? ex = Assert.Throws( - () => new Percentage(negative) + () => Percentage.FromDouble(negative) ); // Assert @@ -44,7 +44,7 @@ public void Percentage_WhenNegative_ShouldThrow(double negative) public void Percentage_ShouldRoundToThreeDecimals(double value, string output) { // Arrange - Percentage percentage = new(value); + Percentage percentage = Percentage.FromDouble(value); // Act string percentageString = percentage.ToNumericalString(); diff --git a/tests/Mermaid.Flowcharts.Tests/Numerical/UnitIntervalTests.cs b/tests/Mermaid.Flowcharts.Tests/Numerical/UnitIntervalTests.cs index 8f97b87..bd18053 100644 --- a/tests/Mermaid.Flowcharts.Tests/Numerical/UnitIntervalTests.cs +++ b/tests/Mermaid.Flowcharts.Tests/Numerical/UnitIntervalTests.cs @@ -13,7 +13,7 @@ public void UnitInterval_WhenValueIsNonFinite_ShouldThrow(double invalid) { // Act ArgumentOutOfRangeException? ex = Assert.Throws( - () => new UnitInterval(invalid) + () => UnitInterval.FromDouble(invalid) ); // Assert @@ -28,7 +28,7 @@ public void UnitInterval_WhenNegative_ShouldThrow(double negative) { // Act ArgumentOutOfRangeException? ex = Assert.Throws( - () => new UnitInterval(negative) + () => UnitInterval.FromDouble(negative) ); // Assert @@ -43,7 +43,7 @@ public void UnitInterval_WhenGreaterThanOne_ShouldThrow(double greaterThanOne) { // Act ArgumentOutOfRangeException? ex = Assert.Throws( - () => new UnitInterval(greaterThanOne) + () => UnitInterval.FromDouble(greaterThanOne) ); // Assert @@ -59,7 +59,7 @@ public void UnitInterval_WhenGreaterThanOne_ShouldThrow(double greaterThanOne) public void UnitInterval_ShouldRoundToThreeDecimals(double value, string output) { // Arrange - UnitInterval interval = new(value); + UnitInterval interval = UnitInterval.FromDouble(value); // Act string intervalString = interval.ToNumericalString(); diff --git a/tests/Mermaid.Flowcharts.Tests/Styling/Attributes/OpacityTests.cs b/tests/Mermaid.Flowcharts.Tests/Styling/Attributes/OpacityTests.cs index 8351ffc..44823bd 100644 --- a/tests/Mermaid.Flowcharts.Tests/Styling/Attributes/OpacityTests.cs +++ b/tests/Mermaid.Flowcharts.Tests/Styling/Attributes/OpacityTests.cs @@ -9,7 +9,7 @@ public void Opacity_WhenNaN_ShouldThrow() { // Act ArgumentOutOfRangeException? ex = Assert.Throws( - () => new Opacity(double.NaN) + () => Opacity.FromDouble(double.NaN) ); // Assert @@ -25,7 +25,7 @@ public void Opacity_WhenNegative_ShouldThrow(double negative) { // Act ArgumentOutOfRangeException? ex = Assert.Throws( - () => new Opacity(negative) + () => Opacity.FromDouble(negative) ); // Assert @@ -41,7 +41,7 @@ public void Opacity_WhenGreaterThanOne_ShouldThrow(double greaterThanOne) { // Act ArgumentOutOfRangeException? ex = Assert.Throws( - () => new Opacity(greaterThanOne) + () => Opacity.FromDouble(greaterThanOne) ); // Assert