diff --git a/specs/Qowaiv.Specs/Chemistry/CAS_Registry_Number_specs.cs b/specs/Qowaiv.Specs/Chemistry/CAS_Registry_Number_specs.cs index 2c670711..484d1f37 100644 --- a/specs/Qowaiv.Specs/Chemistry/CAS_Registry_Number_specs.cs +++ b/specs/Qowaiv.Specs/Chemistry/CAS_Registry_Number_specs.cs @@ -4,488 +4,486 @@ namespace Chemistry.CAS_Registry_Number_specs; public class With_domain_logic { - [TestCase(true, "73–24–5")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, CasRegistryNumber svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, "73–24–5")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, CasRegistryNumber svo) => svo.IsKnown.Should().Be(result); - - [TestCase("")] - [TestCase("?")] - public void has_length_zero_for_empty_and_unknown(CasRegistryNumber svo) - => svo.Length.Should().Be(0); - - [TestCase(5, "73–24–5")] - [TestCase(7, "7732-18-5")] - [TestCase(8, "10028-14-5")] - public void has_length(int length, CasRegistryNumber svo) - => svo.Length.Should().Be(length); - - [TestCase(false, "10028-14-5")] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, CasRegistryNumber svo) - => svo.IsEmpty().Should().Be(result); - - [TestCase(false, "10028-14-5")] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, CasRegistryNumber svo) - => svo.IsEmptyOrUnknown().Should().Be(result); - - [TestCase(false, "10028-14-5")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, CasRegistryNumber svo) - => svo.IsUnknown().Should().Be(result); + [TestCase(true, "73–24–5")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, CasRegistryNumber svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, "73–24–5")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, CasRegistryNumber svo) => svo.IsKnown.Should().Be(result); + + [TestCase("")] + [TestCase("?")] + public void has_length_zero_for_empty_and_unknown(CasRegistryNumber svo) + => svo.Length.Should().Be(0); + + [TestCase(5, "73–24–5")] + [TestCase(7, "7732-18-5")] + [TestCase(8, "10028-14-5")] + public void has_length(int length, CasRegistryNumber svo) + => svo.Length.Should().Be(length); + + [TestCase(false, "10028-14-5")] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, CasRegistryNumber svo) + => svo.IsEmpty().Should().Be(result); + + [TestCase(false, "10028-14-5")] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, CasRegistryNumber svo) + => svo.IsEmptyOrUnknown().Should().Be(result); + + [TestCase(false, "10028-14-5")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, CasRegistryNumber svo) + => svo.IsUnknown().Should().Be(result); } public class Is_valid_for { - [TestCase("10028-14-5")] - [TestCase("10028-14-5")] - public void strings_representing_SVO(string input) - => CasRegistryNumber.Parse(input).IsEmptyOrUnknown().Should().BeFalse(); + [TestCase("10028-14-5")] + [TestCase("10028-14-5")] + public void strings_representing_SVO(string input) + => CasRegistryNumber.Parse(input).IsEmptyOrUnknown().Should().BeFalse(); } public class Is_not_valid_for { - [Test] - public void Numbers_with_less_then_5_digits() - => CasRegistryNumber.TryParse("9-99-4").Should().BeNull(); - - [Test] - public void Numbers_with_more_then_10_digits() - => CasRegistryNumber.TryParse("10000000-00-0").Should().BeNull(); - - [TestCase("10028-14-3")] - [TestCase("10028-15-5")] - [TestCase("10028-84-5")] - [TestCase("10020-14-5")] - [TestCase("10068-14-5")] - [TestCase("10128-14-5")] - [TestCase("32028-14-5")] - public void checksum_mismatches(string number) - => CasRegistryNumber.TryParse(number).Should().BeNull(); + [Test] + public void Numbers_with_less_then_5_digits() + => CasRegistryNumber.TryParse("9-99-4").Should().BeNull(); + + [Test] + public void Numbers_with_more_then_10_digits() + => CasRegistryNumber.TryParse("10000000-00-0").Should().BeNull(); + + [TestCase("10028-14-3")] + [TestCase("10028-15-5")] + [TestCase("10028-84-5")] + [TestCase("10020-14-5")] + [TestCase("10068-14-5")] + [TestCase("10128-14-5")] + [TestCase("32028-14-5")] + public void checksum_mismatches(string number) + => CasRegistryNumber.TryParse(number).Should().BeNull(); } public class Has_constant { - [Test] - public void Empty_represent_default_value() - => CasRegistryNumber.Empty.Should().Be(default); + [Test] + public void Empty_represent_default_value() + => CasRegistryNumber.Empty.Should().Be(default); } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - => Svo.CasRegistryNumber.Equals(null).Should().BeFalse(); - - [Test] - public void not_equal_to_other_type() - => Svo.CasRegistryNumber.Equals(new object()).Should().BeFalse(); - - [Test] - public void not_equal_to_different_value() - => Svo.CasRegistryNumber.Equals(7732_18_5.CasNr()).Should().BeFalse(); - - [Test] - public void equal_to_same_value() - => Svo.CasRegistryNumber.Equals(10028_14_5.CasNr()).Should().BeTrue(); - - [Test] - public void equal_operator_returns_true_for_same_values() - => (Svo.CasRegistryNumber == 10028_14_5.CasNr()).Should().BeTrue(); - - [Test] - public void equal_operator_returns_false_for_different_values() - => (Svo.CasRegistryNumber == 7732_18_5.CasNr()).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_false_for_same_values() - => (Svo.CasRegistryNumber != 10028_14_5.CasNr()).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_true_for_different_values() - => (Svo.CasRegistryNumber != 7732_18_5.CasNr()).Should().BeTrue(); - - [TestCase("", 0)] - [TestCase("10028-14-5", 657830306)] - public void hash_code_is_value_based(CasRegistryNumber svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + => Svo.CasRegistryNumber.Equals(null).Should().BeFalse(); + + [Test] + public void not_equal_to_other_type() + => Svo.CasRegistryNumber.Equals(new object()).Should().BeFalse(); + + [Test] + public void not_equal_to_different_value() + => Svo.CasRegistryNumber.Equals(7732_18_5.CasNr()).Should().BeFalse(); + + [Test] + public void equal_to_same_value() + => Svo.CasRegistryNumber.Equals(10028_14_5.CasNr()).Should().BeTrue(); + + [Test] + public void equal_operator_returns_true_for_same_values() + => (Svo.CasRegistryNumber == 10028_14_5.CasNr()).Should().BeTrue(); + + [Test] + public void equal_operator_returns_false_for_different_values() + => (Svo.CasRegistryNumber == 7732_18_5.CasNr()).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_false_for_same_values() + => (Svo.CasRegistryNumber != 10028_14_5.CasNr()).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_true_for_different_values() + => (Svo.CasRegistryNumber != 7732_18_5.CasNr()).Should().BeTrue(); + + [TestCase("", 0)] + [TestCase("10028-14-5", 657830306)] + public void hash_code_is_value_based(CasRegistryNumber svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - => CasRegistryNumber.Parse(null).Should().Be(CasRegistryNumber.Empty); - - [Test] - public void from_empty_string_represents_Empty() - => CasRegistryNumber.Parse(string.Empty).Should().Be(CasRegistryNumber.Empty); - - [Test] - public void from_question_mark_represents_Unknown() - => CasRegistryNumber.Parse("?").Should().Be(CasRegistryNumber.Unknown); - - [TestCase("en-US", "10028145")] - [TestCase("en-GB", "10028-14-5")] - [TestCase("en-US", "10028.14.5")] - [TestCase("en-GB", "10028 14 5")] - [TestCase("en-CA", "100.281.45")] - [TestCase("nl-BE", "10028-14-5")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - CasRegistryNumber.Parse(input).Should().Be(Svo.CasRegistryNumber); - } - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - "not a CAS registry".Invoking(CasRegistryNumber.Parse) - .Should().Throw() - .WithMessage("Not a valid CAS Registry Number") - .And.InnerException.Should().BeEquivalentTo(new - { - Type = "Qowaiv.Chemistry.CasRegistryNumber", - Value = "not a CAS registry" - }); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - => CasRegistryNumber.TryParse("invalid input", out _).Should().BeFalse(); - - [Test] - public void from_invalid_as_null_with_TryParse() - => CasRegistryNumber.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - => CasRegistryNumber.TryParse("10028-14-5").Should().Be(Svo.CasRegistryNumber); + [Test] + public void from_null_string_represents_Empty() + => CasRegistryNumber.Parse(null).Should().Be(CasRegistryNumber.Empty); + + [Test] + public void from_empty_string_represents_Empty() + => CasRegistryNumber.Parse(string.Empty).Should().Be(CasRegistryNumber.Empty); + + [Test] + public void from_question_mark_represents_Unknown() + => CasRegistryNumber.Parse("?").Should().Be(CasRegistryNumber.Unknown); + + [TestCase("en-US", "10028145")] + [TestCase("en-GB", "10028-14-5")] + [TestCase("en-US", "10028.14.5")] + [TestCase("en-GB", "10028 14 5")] + [TestCase("en-CA", "100.281.45")] + [TestCase("nl-BE", "10028-14-5")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + CasRegistryNumber.Parse(input).Should().Be(Svo.CasRegistryNumber); + } + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + "not a CAS registry".Invoking(CasRegistryNumber.Parse) + .Should().Throw() + .WithMessage("Not a valid CAS Registry Number") + .And.InnerException.Should().BeEquivalentTo(new + { + Type = "Qowaiv.Chemistry.CasRegistryNumber", + Value = "not a CAS registry" + }); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + => CasRegistryNumber.TryParse("invalid input", out _).Should().BeFalse(); + + [Test] + public void from_invalid_as_null_with_TryParse() + => CasRegistryNumber.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + => CasRegistryNumber.TryParse("10028-14-5").Should().Be(Svo.CasRegistryNumber); } public class Has_custom_formatting { - [Test] - public void _default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.CasRegistryNumber.ToString().Should().Be("10028-14-5"); - } - } - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.CasRegistryNumber.ToString().Should().Be(Svo.CasRegistryNumber.ToString(default(string))); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.CasRegistryNumber.ToString().Should().Be(Svo.CasRegistryNumber.ToString(string.Empty)); - } - } - - [Test] - public void default_value_is_represented_as_string_empty() - => default(CasRegistryNumber).ToString().Should().BeEmpty(); - - [Test] - public void unknown_value_is_represented_as_unknown() - => CasRegistryNumber.Unknown.ToString().Should().Be("?"); - - [Test] - public void with_empty_format_provider() - { - using (TestCultures.es_EC.Scoped()) - { - Svo.CasRegistryNumber.ToString(FormatProvider.Empty).Should().Be("10028-14-5"); - } - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.CasRegistryNumber.ToString("#_00_00_0", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: '100_28_14_5', format: '#_00_00_0'"); - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope( culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) - { - Svo.CasRegistryNumber.ToString(provider: null).Should().Be("10028-14-5"); - } - } + [Test] + public void _default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.CasRegistryNumber.ToString().Should().Be("10028-14-5"); + } + } + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.CasRegistryNumber.ToString().Should().Be(Svo.CasRegistryNumber.ToString(default(string))); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.CasRegistryNumber.ToString().Should().Be(Svo.CasRegistryNumber.ToString(string.Empty)); + } + } + + [Test] + public void default_value_is_represented_as_string_empty() + => default(CasRegistryNumber).ToString().Should().BeEmpty(); + + [Test] + public void unknown_value_is_represented_as_unknown() + => CasRegistryNumber.Unknown.ToString().Should().Be("?"); + + [Test] + public void with_empty_format_provider() + { + using (TestCultures.es_EC.Scoped()) + { + Svo.CasRegistryNumber.ToString(FormatProvider.Empty).Should().Be("10028-14-5"); + } + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.CasRegistryNumber.ToString("#_00_00_0", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: '100_28_14_5', format: '#_00_00_0'"); + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) + { + Svo.CasRegistryNumber.ToString(provider: null).Should().Be("10028-14-5"); + } + } } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.CasRegistryNumber.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_CasRegistryNumber_as_object() - { - object obj = Svo.CasRegistryNumber; - Svo.CasRegistryNumber.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_CasRegistryNumber_only() - { - Assert.Throws(() => Svo.CasRegistryNumber.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - default, - default, - 64_19_7.CasNr(), - 67_64_1.CasNr(), - 74_86_2.CasNr(), - CasRegistryNumber.Unknown, - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.CasRegistryNumber.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_CasRegistryNumber_as_object() + { + object obj = Svo.CasRegistryNumber; + Svo.CasRegistryNumber.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_CasRegistryNumber_only() + => new object().Invoking(Svo.CasRegistryNumber.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + default, + default, + 64_19_7.CasNr(), + 67_64_1.CasNr(), + 74_86_2.CasNr(), + CasRegistryNumber.Unknown, + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + + list.Should().BeEquivalentTo(sorted); + } } public class Casts { - [Test] - public void explicitly_from_int() - { - var casted = (CasRegistryNumber)10028_14_5; - casted.Should().Be(Svo.CasRegistryNumber); - } - - [Test] - public void explicitly_from_long() - { - var casted = (CasRegistryNumber)10028_14_5L; - casted.Should().Be(Svo.CasRegistryNumber); - } - - [Test] - public void explicitly_to_long() - { - var casted = (long)Svo.CasRegistryNumber; - casted.Should().Be(10028_14_5L); - } + [Test] + public void explicitly_from_int() + { + var casted = (CasRegistryNumber)10028_14_5; + casted.Should().Be(Svo.CasRegistryNumber); + } + + [Test] + public void explicitly_from_long() + { + var casted = (CasRegistryNumber)10028_14_5L; + casted.Should().Be(Svo.CasRegistryNumber); + } + + [Test] + public void explicitly_to_long() + { + var casted = (long)Svo.CasRegistryNumber; + casted.Should().Be(10028_14_5L); + } } public class Has_humanizer_creators { - [Test] - public void CasNr_from_int() => 10028_14_5.CasNr().Should().Be(Svo.CasRegistryNumber); + [Test] + public void CasNr_from_int() => 10028_14_5.CasNr().Should().Be(Svo.CasRegistryNumber); - [Test] - public void CasNr_from_long() => 10028_14_5L.CasNr().Should().Be(Svo.CasRegistryNumber); + [Test] + public void CasNr_from_long() => 10028_14_5L.CasNr().Should().Be(Svo.CasRegistryNumber); } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(CasRegistryNumber).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(CasRegistryNumber.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(CasRegistryNumber.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("10028-14-5").To().Should().Be(Svo.CasRegistryNumber); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.CasRegistryNumber).Should().Be("10028-14-5"); - } - } - - [Test] - public void from_long() - => Converting.From(10028_14_5L).To().Should().Be(Svo.CasRegistryNumber); - - [Test] - public void to_int() - => Converting.To().From(Svo.CasRegistryNumber).Should().Be(10028_14_5L); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(CasRegistryNumber).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(CasRegistryNumber.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(CasRegistryNumber.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("10028-14-5").To().Should().Be(Svo.CasRegistryNumber); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.CasRegistryNumber).Should().Be("10028-14-5"); + } + } + + [Test] + public void from_long() + => Converting.From(10028_14_5L).To().Should().Be(Svo.CasRegistryNumber); + + [Test] + public void to_int() + => Converting.To().From(Svo.CasRegistryNumber).Should().Be(10028_14_5L); } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase("?", "?")] - [TestCase(10028_14_5L, "10028-14-5")] - public void System_Text_JSON_deserialization(object json, CasRegistryNumber svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("10028-14-5", "10028-14-5")] - public void System_Text_JSON_serialization(CasRegistryNumber svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase("?", "?")] + [TestCase(10028_14_5L, "10028-14-5")] + public void System_Text_JSON_deserialization(object json, CasRegistryNumber svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("10028-14-5", "10028-14-5")] + public void System_Text_JSON_serialization(CasRegistryNumber svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("?", "?")] - [TestCase(10028_14_5L, "10028-14-5")] - public void convention_based_deserialization(object json, CasRegistryNumber svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("10028-14-5", "10028-14-5")] - public void convention_based_serialization(CasRegistryNumber svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - [TestCase(true, typeof(InvalidOperationException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("?", "?")] + [TestCase(10028_14_5L, "10028-14-5")] + public void convention_based_deserialization(object json, CasRegistryNumber svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("10028-14-5", "10028-14-5")] + public void convention_based_serialization(CasRegistryNumber svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + [TestCase(true, typeof(InvalidOperationException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.CasRegistryNumber); - xml.Should().Be("10028-14-5"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("10028-14-5"); - svo.Should().Be(Svo.CasRegistryNumber); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.CasRegistryNumber); - Svo.CasRegistryNumber.Should().Be(round_tripped); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.CasRegistryNumber); - var round_tripped = SerializeDeserialize.Xml(structure); - structure.Should().Be(round_tripped); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.CasRegistryNumber; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.CasRegistryNumber); + xml.Should().Be("10028-14-5"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("10028-14-5"); + svo.Should().Be(Svo.CasRegistryNumber); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.CasRegistryNumber); + Svo.CasRegistryNumber.Should().Be(round_tripped); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.CasRegistryNumber); + var round_tripped = SerializeDeserialize.Xml(structure); + structure.Should().Be(round_tripped); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.CasRegistryNumber; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(CasRegistryNumber)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(CasRegistryNumber), - description: "CAS Registry Number", - example: "7732-18-5", - type: "string", - format: "cas-nr", - pattern: "[1-9][0-9]+\\-[0-9]{2}\\-[0-9]", - nullable: true)); - - [TestCase("7732-18-5")] - [TestCase("10028-14-5")] - public void pattern_matches(string input) - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(CasRegistryNumber))!.Matches(input).Should().BeTrue(); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(CasRegistryNumber)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(CasRegistryNumber), + description: "CAS Registry Number", + example: "7732-18-5", + type: "string", + format: "cas-nr", + pattern: "[1-9][0-9]+\\-[0-9]{2}\\-[0-9]", + nullable: true)); + + [TestCase("7732-18-5")] + [TestCase("10028-14-5")] + public void pattern_matches(string input) + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(CasRegistryNumber))!.Matches(input).Should().BeTrue(); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.CasRegistryNumber); - round_tripped.Should().Be(Svo.CasRegistryNumber); - } - - [Test] - public void storing_long_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.CasRegistryNumber); - info.GetInt64("Value").Should().Be(10028_14_5L); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.CasRegistryNumber); + round_tripped.Should().Be(Svo.CasRegistryNumber); + } + + [Test] + public void storing_long_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.CasRegistryNumber); + info.GetInt64("Value").Should().Be(10028_14_5L); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("{unknown}", "?")] - [TestCase("10028-14-5", "10028-14-5")] - public void has_custom_display(object display, CasRegistryNumber svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("{unknown}", "?")] + [TestCase("10028-14-5", "10028-14-5")] + public void has_custom_display(object display, CasRegistryNumber svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Customization/Generic_SVO_specs.cs b/specs/Qowaiv.Specs/Customization/Generic_SVO_specs.cs index a91a0428..a912befe 100644 --- a/specs/Qowaiv.Specs/Customization/Generic_SVO_specs.cs +++ b/specs/Qowaiv.Specs/Customization/Generic_SVO_specs.cs @@ -2,453 +2,451 @@ public class Default_behavior { - [Test] - public void MinLength_is_0() - => new WithDefaultBehavior().MinLength.Should().Be(0); + [Test] + public void MinLength_is_0() + => new WithDefaultBehavior().MinLength.Should().Be(0); - [Test] - public void MaxLength_is_int_MaxValue() - => new WithDefaultBehavior().MaxLength.Should().Be(int.MaxValue); + [Test] + public void MaxLength_is_int_MaxValue() + => new WithDefaultBehavior().MaxLength.Should().Be(int.MaxValue); - [Test] - public void Regex_Pattern_is_null() - => new WithDefaultBehavior().Pattern.Should().BeNull(); + [Test] + public void Regex_Pattern_is_null() + => new WithDefaultBehavior().Pattern.Should().BeNull(); - [Test] - public void ToJson_returns_underlying_value() - => GenericSvo.Empty.ToJson().Should().BeNull(); + [Test] + public void ToJson_returns_underlying_value() + => GenericSvo.Empty.ToJson().Should().BeNull(); } public class With_domain_logic { - [TestCase(true, "QOWAIV")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, CustomSvo svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, "QOWAIV")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, CustomSvo svo) => svo.IsKnown.Should().Be(result); - - [TestCase("")] - [TestCase("?")] - public void has_length_zero_for_empty_and_unknown(CustomSvo svo) - => svo.Length.Should().Be(0); - - [TestCase(6, "QOWAIV")] - public void has_length(int length, CustomSvo svo) - => svo.Length.Should().Be(length); - - [TestCase(false, "QOWAIV")] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, CustomSvo svo) - => svo.IsEmpty().Should().Be(result); - - [TestCase(false, "QOWAIV")] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, CustomSvo svo) - => svo.IsEmptyOrUnknown().Should().Be(result); - - [TestCase(false, "QOWAIV")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, CustomSvo svo) - => svo.IsUnknown().Should().Be(result); + [TestCase(true, "QOWAIV")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, CustomSvo svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, "QOWAIV")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, CustomSvo svo) => svo.IsKnown.Should().Be(result); + + [TestCase("")] + [TestCase("?")] + public void has_length_zero_for_empty_and_unknown(CustomSvo svo) + => svo.Length.Should().Be(0); + + [TestCase(6, "QOWAIV")] + public void has_length(int length, CustomSvo svo) + => svo.Length.Should().Be(length); + + [TestCase(false, "QOWAIV")] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, CustomSvo svo) + => svo.IsEmpty().Should().Be(result); + + [TestCase(false, "QOWAIV")] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, CustomSvo svo) + => svo.IsEmptyOrUnknown().Should().Be(result); + + [TestCase(false, "QOWAIV")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, CustomSvo svo) + => svo.IsUnknown().Should().Be(result); } public class Has_constant { - [Test] - public void Empty_represent_default_value() - => CustomSvo.Empty.Should().Be(default); + [Test] + public void Empty_represent_default_value() + => CustomSvo.Empty.Should().Be(default); } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - => Svo.CustomSvo.Equals(null).Should().BeFalse(); - - [Test] - public void not_equal_to_other_type() - => Svo.CustomSvo.Equals(new object()).Should().BeFalse(); - - [Test] - public void not_equal_to_different_value() - => Svo.CustomSvo.Equals(CustomSvo.Parse("different")).Should().BeFalse(); - - [Test] - public void equal_to_same_value() - => Svo.CustomSvo.Equals(CustomSvo.Parse("QOWAIV")).Should().BeTrue(); - - [Test] - public void equal_operator_returns_true_for_same_values() - => (Svo.CustomSvo == CustomSvo.Parse("QOWAIV")).Should().BeTrue(); - - [Test] - public void equal_operator_returns_false_for_different_values() - => (Svo.CustomSvo == CustomSvo.Parse("different")).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_false_for_same_values() - => (Svo.CustomSvo != CustomSvo.Parse("QOWAIV")).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_true_for_different_values() - => (Svo.CustomSvo != CustomSvo.Parse("different")).Should().BeTrue(); - - [TestCase("", 0)] - [TestCase("QOWAIV", 467820648)] - public void hash_code_is_value_based(CustomSvo svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + => Svo.CustomSvo.Equals(null).Should().BeFalse(); + + [Test] + public void not_equal_to_other_type() + => Svo.CustomSvo.Equals(new object()).Should().BeFalse(); + + [Test] + public void not_equal_to_different_value() + => Svo.CustomSvo.Equals(CustomSvo.Parse("different")).Should().BeFalse(); + + [Test] + public void equal_to_same_value() + => Svo.CustomSvo.Equals(CustomSvo.Parse("QOWAIV")).Should().BeTrue(); + + [Test] + public void equal_operator_returns_true_for_same_values() + => (Svo.CustomSvo == CustomSvo.Parse("QOWAIV")).Should().BeTrue(); + + [Test] + public void equal_operator_returns_false_for_different_values() + => (Svo.CustomSvo == CustomSvo.Parse("different")).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_false_for_same_values() + => (Svo.CustomSvo != CustomSvo.Parse("QOWAIV")).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_true_for_different_values() + => (Svo.CustomSvo != CustomSvo.Parse("different")).Should().BeTrue(); + + [TestCase("", 0)] + [TestCase("QOWAIV", 467820648)] + public void hash_code_is_value_based(CustomSvo svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - => CustomSvo.Parse(null).Should().Be(CustomSvo.Empty); - - [Test] - public void from_empty_string_represents_Empty() - => CustomSvo.Parse(string.Empty).Should().Be(CustomSvo.Empty); - - [Test] - public void from_question_mark_represents_Unknown() - => CustomSvo.Parse("?").Should().Be(CustomSvo.Unknown); - - [TestCase("en", "QOWAIV")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - CustomSvo.Parse(input).Should().Be(Svo.CustomSvo); - } - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - Func parse = () => CustomSvo.Parse("invalid input!"); - parse.Should().Throw() - .WithMessage("Not a valid CustomSvo"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - => CustomSvo.TryParse("invalid input", out _).Should().BeFalse(); - - [Test] - public void from_invalid_as_null_with_TryParse() - => CustomSvo.TryParse("invalid input!").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - => CustomSvo.TryParse("QOWAIV").Should().Be(Svo.CustomSvo); + [Test] + public void from_null_string_represents_Empty() + => CustomSvo.Parse(null).Should().Be(CustomSvo.Empty); + + [Test] + public void from_empty_string_represents_Empty() + => CustomSvo.Parse(string.Empty).Should().Be(CustomSvo.Empty); + + [Test] + public void from_question_mark_represents_Unknown() + => CustomSvo.Parse("?").Should().Be(CustomSvo.Unknown); + + [TestCase("en", "QOWAIV")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + CustomSvo.Parse(input).Should().Be(Svo.CustomSvo); + } + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + Func parse = () => CustomSvo.Parse("invalid input!"); + parse.Should().Throw() + .WithMessage("Not a valid CustomSvo"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + => CustomSvo.TryParse("invalid input", out _).Should().BeFalse(); + + [Test] + public void from_invalid_as_null_with_TryParse() + => CustomSvo.TryParse("invalid input!").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + => CustomSvo.TryParse("QOWAIV").Should().Be(Svo.CustomSvo); } public class Has_custom_formatting { - [Test] - public void _default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.CustomSvo.ToString().Should().Be("QOWAIV"); - } - } - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.CustomSvo.ToString().Should().Be(Svo.CustomSvo.ToString(default(string))); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.CustomSvo.ToString().Should().Be(Svo.CustomSvo.ToString(string.Empty)); - } - } - - [Test] - public void default_value_is_represented_as_string_empty() - => default(CustomSvo).ToString().Should().BeEmpty(); - - [Test] - public void unknown_value_is_represented_as_unknown() - => CustomSvo.Unknown.ToString().Should().Be("?"); - - [Test] - public void with_empty_format_provider() - { - using (TestCultures.es_EC.Scoped()) - { - Svo.CustomSvo.ToString(FormatProvider.Empty).Should().Be("QOWAIV"); - } - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.CustomSvo.ToString("SomeFormat", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: 'QOWAIV', format: 'SomeFormat'"); - } - - [TestCase("en-GB", null, "QOWAIV", "QOWAIV")] - [TestCase("nl-BE", "f", "QOWAIV", "QOWAIV")] - public void culture_dependent(CultureInfo culture, string format, CustomSvo svo, string expected) - { - using (culture.Scoped()) - { - svo.ToString(format).Should().Be(expected); - } - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope( - culture: TestCultures.nl_NL, - cultureUI: TestCultures.en_GB)) - { - Svo.CustomSvo.ToString(provider: null).Should().Be("QOWAIV"); - } - } + [Test] + public void _default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.CustomSvo.ToString().Should().Be("QOWAIV"); + } + } + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.CustomSvo.ToString().Should().Be(Svo.CustomSvo.ToString(default(string))); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.CustomSvo.ToString().Should().Be(Svo.CustomSvo.ToString(string.Empty)); + } + } + + [Test] + public void default_value_is_represented_as_string_empty() + => default(CustomSvo).ToString().Should().BeEmpty(); + + [Test] + public void unknown_value_is_represented_as_unknown() + => CustomSvo.Unknown.ToString().Should().Be("?"); + + [Test] + public void with_empty_format_provider() + { + using (TestCultures.es_EC.Scoped()) + { + Svo.CustomSvo.ToString(FormatProvider.Empty).Should().Be("QOWAIV"); + } + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.CustomSvo.ToString("SomeFormat", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: 'QOWAIV', format: 'SomeFormat'"); + } + + [TestCase("en-GB", null, "QOWAIV", "QOWAIV")] + [TestCase("nl-BE", "f", "QOWAIV", "QOWAIV")] + public void culture_dependent(CultureInfo culture, string format, CustomSvo svo, string expected) + { + using (culture.Scoped()) + { + svo.ToString(format).Should().Be(expected); + } + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope( + culture: TestCultures.nl_NL, + cultureUI: TestCultures.en_GB)) + { + Svo.CustomSvo.ToString(provider: null).Should().Be("QOWAIV"); + } + } } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.CustomSvo.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_Svo_as_object() - { - object obj = Svo.CustomSvo; - Svo.CustomSvo.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Svo_only() - { - Assert.Throws(() => Svo.CustomSvo.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - default, - default, - CustomSvo.Parse("ABC"), - CustomSvo.Parse("ABCD"), - CustomSvo.Parse("ABCDE"), - CustomSvo.Unknown, - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.CustomSvo.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_Svo_as_object() + { + object obj = Svo.CustomSvo; + Svo.CustomSvo.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Svo_only() + => new object().Invoking(Svo.CustomSvo.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + default, + default, + CustomSvo.Parse("ABC"), + CustomSvo.Parse("ABCD"), + CustomSvo.Parse("ABCDE"), + CustomSvo.Unknown, + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + + list.Should().BeEquivalentTo(sorted); + } } public class Casts { - [Test] - public void explicitly_from_string() - { - var casted = (CustomSvo)"QOWAIV"; - casted.Should().Be(Svo.CustomSvo); - } - - [Test] - public void explicitly_to_string() - { - var casted = (string)Svo.CustomSvo; - casted.Should().Be("QOWAIV"); - } + [Test] + public void explicitly_from_string() + { + var casted = (CustomSvo)"QOWAIV"; + casted.Should().Be(Svo.CustomSvo); + } + + [Test] + public void explicitly_to_string() + { + var casted = (string)Svo.CustomSvo; + casted.Should().Be("QOWAIV"); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(CustomSvo).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(CustomSvo.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(CustomSvo.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("QOWAIV").To().Should().Be(Svo.CustomSvo); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.CustomSvo).Should().Be("QOWAIV"); - } - } + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(CustomSvo).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(CustomSvo.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(CustomSvo.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("QOWAIV").To().Should().Be(Svo.CustomSvo); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.CustomSvo).Should().Be("QOWAIV"); + } + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase(null, null)] - [TestCase("?", "?")] - [TestCase("QOWAIV", "QOWAIV")] - public void System_Text_JSON_deserialization(object json, CustomSvo svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("QOWAIV", "QOWAIV")] - public void System_Text_JSON_serialization(CustomSvo svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); - - [TestCase("{}")] - public void System_Text_JSON_throws_on(string json) - { - json.Invoking(json => System.Text.Json.JsonSerializer.Deserialize(json)) - .Should().Throw(); - } + [TestCase(null, null)] + [TestCase("?", "?")] + [TestCase("QOWAIV", "QOWAIV")] + public void System_Text_JSON_deserialization(object json, CustomSvo svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("QOWAIV", "QOWAIV")] + public void System_Text_JSON_serialization(CustomSvo svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + + [TestCase("{}")] + public void System_Text_JSON_throws_on(string json) + { + json.Invoking(json => System.Text.Json.JsonSerializer.Deserialize(json)) + .Should().Throw(); + } #endif - [TestCase("?", "?")] - [TestCase("QOWAIV", "QOWAIV")] - public void convention_based_deserialization(object json, CustomSvo svo) - => JsonTester.Read(json).Should().Be(svo); - - - [TestCase(null, null)] - [TestCase("QOWAIV", "QOWAIV")] - public void convention_based_serialization(CustomSvo svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input!", typeof(FormatException))] - [TestCase(5L, typeof(InvalidOperationException))] - public void throws_for_invalid_json(object json, Type exceptionType) - { - Func read = () => JsonTester.Read(json); - read.Should().Throw().Subject.Single().Should().BeOfType(exceptionType); - } + [TestCase("?", "?")] + [TestCase("QOWAIV", "QOWAIV")] + public void convention_based_deserialization(object json, CustomSvo svo) + => JsonTester.Read(json).Should().Be(svo); + + + [TestCase(null, null)] + [TestCase("QOWAIV", "QOWAIV")] + public void convention_based_serialization(CustomSvo svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input!", typeof(FormatException))] + [TestCase(5L, typeof(InvalidOperationException))] + public void throws_for_invalid_json(object json, Type exceptionType) + { + Func read = () => JsonTester.Read(json); + read.Should().Throw().Subject.Single().Should().BeOfType(exceptionType); + } } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.CustomSvo); - xml.Should().Be("QOWAIV"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("QOWAIV"); - svo.Should().Be(Svo.CustomSvo); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.CustomSvo); - Svo.CustomSvo.Should().Be(round_tripped); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.CustomSvo); - var round_tripped = SerializeDeserialize.Xml(structure); - structure.Should().Be(round_tripped); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.CustomSvo; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.CustomSvo); + xml.Should().Be("QOWAIV"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("QOWAIV"); + svo.Should().Be(Svo.CustomSvo); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.CustomSvo); + Svo.CustomSvo.Should().Be(round_tripped); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.CustomSvo); + var round_tripped = SerializeDeserialize.Xml(structure); + structure.Should().Be(round_tripped); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.CustomSvo; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(ForCustomSvo)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(CustomSvo), - description: "Custom SVO Example", - example: "QOWAIV", - type: "string", - format: "custom", - pattern: null)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(ForCustomSvo)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(CustomSvo), + description: "Custom SVO Example", + example: "QOWAIV", + type: "string", + format: "custom", + pattern: null)); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.CustomSvo); - round_tripped.Should().Be(Svo.CustomSvo); - } - [Test] - public void storing_string_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.CustomSvo); - info.GetString("Value").Should().Be("QOWAIV"); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.CustomSvo); + round_tripped.Should().Be(Svo.CustomSvo); + } + [Test] + public void storing_string_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.CustomSvo); + info.GetString("Value").Should().Be("QOWAIV"); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("{unknown}", "?")] - [TestCase("QOWAIV", "QOWAIV")] - public void has_custom_display(object display, CustomSvo svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("{unknown}", "?")] + [TestCase("QOWAIV", "QOWAIV")] + public void has_custom_display(object display, CustomSvo svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Email_address_specs.cs b/specs/Qowaiv.Specs/Email_address_specs.cs index b6a698b1..8da36b5d 100644 --- a/specs/Qowaiv.Specs/Email_address_specs.cs +++ b/specs/Qowaiv.Specs/Email_address_specs.cs @@ -2,492 +2,488 @@ public class With_domain_logic { - [TestCase(true, "info@qowaiv.org")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, EmailAddress svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, "info@qowaiv.org")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, EmailAddress svo) => svo.IsKnown.Should().Be(result); - - [TestCase("")] - [TestCase("?")] - public void has_length_zero_for_empty_and_unknown(EmailAddress svo) - => svo.Length.Should().Be(0); - - [TestCase(15, "info@qowaiv.org")] - public void has_length(int length, EmailAddress svo) - => svo.Length.Should().Be(length); - - [TestCase(false, "info@qowaiv.org")] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, EmailAddress svo) - => svo.IsEmpty().Should().Be(result); - - [TestCase(false, "info@qowaiv.org")] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, EmailAddress svo) - => svo.IsEmptyOrUnknown().Should().Be(result); - - [TestCase(false, "info@qowaiv.org")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, EmailAddress svo) - => svo.IsUnknown().Should().Be(result); - - [TestCase(false, "info@qowaiv.org")] - [TestCase(true, "info@[192.0.2.1]")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsIPBased_returns(bool result, EmailAddress svo) - => svo.IsIPBased.Should().Be(result); - - [TestCase("info@qowaiv.org", "255.255.255.255")] - [TestCase("info@[192.0.2.1]", "192.0.2.1")] - [TestCase("info@[IPv6:2001:0db8:0000:0000:0000:ff00:0042:8329]", "1:db8::ff00:42:8329")] - public void IP_domain(EmailAddress email, string address) - => email.IPDomain.ToString().Should().Be(address); - - [TestCase("info", "info@qowaiv.org")] - [TestCase("", "?")] - [TestCase("", "")] - public void Local_part_returns(string local, EmailAddress email) - => email.Local.Should().Be(local); - - [TestCase("qowaiv.org", "info@qowaiv.org")] - [TestCase("[192.0.2.1]", "info@192.0.2.1")] - [TestCase("", "?")] - [TestCase("", "")] - public void Domain_part_returns(string local, EmailAddress email) - => email.Domain.Should().Be(local); + [TestCase(true, "info@qowaiv.org")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, EmailAddress svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, "info@qowaiv.org")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, EmailAddress svo) => svo.IsKnown.Should().Be(result); + + [TestCase("")] + [TestCase("?")] + public void has_length_zero_for_empty_and_unknown(EmailAddress svo) + => svo.Length.Should().Be(0); + + [TestCase(15, "info@qowaiv.org")] + public void has_length(int length, EmailAddress svo) + => svo.Length.Should().Be(length); + + [TestCase(false, "info@qowaiv.org")] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, EmailAddress svo) + => svo.IsEmpty().Should().Be(result); + + [TestCase(false, "info@qowaiv.org")] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, EmailAddress svo) + => svo.IsEmptyOrUnknown().Should().Be(result); + + [TestCase(false, "info@qowaiv.org")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, EmailAddress svo) + => svo.IsUnknown().Should().Be(result); + + [TestCase(false, "info@qowaiv.org")] + [TestCase(true, "info@[192.0.2.1]")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsIPBased_returns(bool result, EmailAddress svo) + => svo.IsIPBased.Should().Be(result); + + [TestCase("info@qowaiv.org", "255.255.255.255")] + [TestCase("info@[192.0.2.1]", "192.0.2.1")] + [TestCase("info@[IPv6:2001:0db8:0000:0000:0000:ff00:0042:8329]", "1:db8::ff00:42:8329")] + public void IP_domain(EmailAddress email, string address) + => email.IPDomain.ToString().Should().Be(address); + + [TestCase("info", "info@qowaiv.org")] + [TestCase("", "?")] + [TestCase("", "")] + public void Local_part_returns(string local, EmailAddress email) + => email.Local.Should().Be(local); + + [TestCase("qowaiv.org", "info@qowaiv.org")] + [TestCase("[192.0.2.1]", "info@192.0.2.1")] + [TestCase("", "?")] + [TestCase("", "")] + public void Domain_part_returns(string local, EmailAddress email) + => email.Domain.Should().Be(local); } public class Has_constant { - [Test] - public void Empty_represent_default_value() - => EmailAddress.Empty.Should().Be(default); + [Test] + public void Empty_represent_default_value() + => EmailAddress.Empty.Should().Be(default); } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - { - Svo.EmailAddress.Equals(null).Should().BeFalse(); - } - - [Test] - public void not_equal_to_other_type() - { - Svo.EmailAddress.Equals(new object()).Should().BeFalse(); - } - - [Test] - public void not_equal_to_different_value() - { - Svo.EmailAddress.Equals(EmailAddress.Parse("no_spam@qowaiv.org")).Should().BeFalse(); - } - - [Test] - public void equal_to_same_value() - { - Svo.EmailAddress.Equals(EmailAddress.Parse("info@qowaiv.org")).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_true_for_same_values() - { - (Svo.EmailAddress == EmailAddress.Parse("info@qowaiv.org")).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_false_for_different_values() - { - (Svo.EmailAddress == EmailAddress.Parse("no_spam@qowaiv.org")).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_false_for_same_values() - { - (Svo.EmailAddress != EmailAddress.Parse("info@qowaiv.org")).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_true_for_different_values() - { - (Svo.EmailAddress != EmailAddress.Parse("no_spam@qowaiv.org")).Should().BeTrue(); - } - - [TestCase("", 0)] - [TestCase("info@qowaiv.org", 798543550)] - public void hash_code_is_value_based(EmailAddress svo, int hashCode) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hashCode); - } - } + [Test] + public void not_equal_to_null() + { + Svo.EmailAddress.Equals(null).Should().BeFalse(); + } + + [Test] + public void not_equal_to_other_type() + { + Svo.EmailAddress.Equals(new object()).Should().BeFalse(); + } + + [Test] + public void not_equal_to_different_value() + { + Svo.EmailAddress.Equals(EmailAddress.Parse("no_spam@qowaiv.org")).Should().BeFalse(); + } + + [Test] + public void equal_to_same_value() + { + Svo.EmailAddress.Equals(EmailAddress.Parse("info@qowaiv.org")).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_true_for_same_values() + { + (Svo.EmailAddress == EmailAddress.Parse("info@qowaiv.org")).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_false_for_different_values() + { + (Svo.EmailAddress == EmailAddress.Parse("no_spam@qowaiv.org")).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_false_for_same_values() + { + (Svo.EmailAddress != EmailAddress.Parse("info@qowaiv.org")).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_true_for_different_values() + { + (Svo.EmailAddress != EmailAddress.Parse("no_spam@qowaiv.org")).Should().BeTrue(); + } + + [TestCase("", 0)] + [TestCase("info@qowaiv.org", 798543550)] + public void hash_code_is_value_based(EmailAddress svo, int hashCode) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hashCode); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - { - EmailAddress.Parse(null).Should().Be(EmailAddress.Empty); - } - - [Test] - public void from_empty_string_represents_Empty() - { - EmailAddress.Parse(string.Empty).Should().Be(EmailAddress.Empty); - } - - [Test] - public void from_question_mark_represents_Unknown() - { - EmailAddress.Parse("?").Should().Be(EmailAddress.Unknown); - } - - [TestCase("en", "info@qowaiv.org")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - var parsed = EmailAddress.Parse(input); - parsed.Should().Be(Svo.EmailAddress); - } - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - "invalid input".Invoking(EmailAddress.Parse) - .Should().Throw() - .WithMessage("Not a valid email address"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - { - EmailAddress.TryParse("invalid input", out _).Should().BeFalse(); - } - - [Test] - public void from_invalid_as_null_with_TryParse() - => EmailAddress.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - { - EmailAddress.TryParse("info@qowaiv.org").Should().Be(Svo.EmailAddress); - } + [Test] + public void from_null_string_represents_Empty() + { + EmailAddress.Parse(null).Should().Be(EmailAddress.Empty); + } + + [Test] + public void from_empty_string_represents_Empty() + { + EmailAddress.Parse(string.Empty).Should().Be(EmailAddress.Empty); + } + + [Test] + public void from_question_mark_represents_Unknown() + { + EmailAddress.Parse("?").Should().Be(EmailAddress.Unknown); + } + + [TestCase("en", "info@qowaiv.org")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + var parsed = EmailAddress.Parse(input); + parsed.Should().Be(Svo.EmailAddress); + } + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + "invalid input".Invoking(EmailAddress.Parse) + .Should().Throw() + .WithMessage("Not a valid email address"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + { + EmailAddress.TryParse("invalid input", out _).Should().BeFalse(); + } + + [Test] + public void from_invalid_as_null_with_TryParse() + => EmailAddress.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + { + EmailAddress.TryParse("info@qowaiv.org").Should().Be(Svo.EmailAddress); + } } public class Has_custom_formatting { - [Test] - public void _default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.EmailAddress.ToString().Should().Be("info@qowaiv.org"); - } - } - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.EmailAddress.ToString(default(string)).Should().Be(Svo.EmailAddress.ToString()); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.EmailAddress.ToString(string.Empty).Should().Be(Svo.EmailAddress.ToString()); - } - } - - [Test] - public void default_value_is_represented_as_string_empty() - { - default(EmailAddress).ToString().Should().Be(string.Empty); - } - - [Test] - public void unknown_value_is_represented_as_unknown() - { - EmailAddress.Unknown.ToString().Should().Be("?"); - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.EmailAddress.ToString("f", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: 'info@qowaiv.org', format: 'f'"); - } - - [TestCase("en-GB", null, "info@qowaiv.org", "info@qowaiv.org")] - [TestCase("nl-BE", "f", "info@qowaiv.org", "info@qowaiv.org")] - public void culture_dependent(CultureInfo culture, string format, EmailAddress svo, string expected) - { - using (culture.Scoped()) - { - svo.ToString(format).Should().Be(expected); - } - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) - { - Svo.EmailAddress.ToString(provider: null).Should().Be("info@qowaiv.org"); - } - } - - [TestCase("info@qowaiv.org", null)] - [TestCase("info@qowaiv.org", "")] - [TestCase("info@qowaiv.org", "f")] - [TestCase("INFO@QOWAIV.ORG", "U")] - [TestCase("INFO", "L")] - [TestCase("info", "l")] - [TestCase("qowaiv.org", "d")] - [TestCase("QOWAIV.ORG", "D")] - [TestCase("info@qowaiv.org", "l@d")] - public void with_format(string formatted, string format) - { - Assert.That(Svo.EmailAddress.ToString(format), Is.EqualTo(formatted)); - } + [Test] + public void _default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.EmailAddress.ToString().Should().Be("info@qowaiv.org"); + } + } + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.EmailAddress.ToString(default(string)).Should().Be(Svo.EmailAddress.ToString()); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.EmailAddress.ToString(string.Empty).Should().Be(Svo.EmailAddress.ToString()); + } + } + + [Test] + public void default_value_is_represented_as_string_empty() + { + default(EmailAddress).ToString().Should().Be(string.Empty); + } + + [Test] + public void unknown_value_is_represented_as_unknown() + { + EmailAddress.Unknown.ToString().Should().Be("?"); + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.EmailAddress.ToString("f", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: 'info@qowaiv.org', format: 'f'"); + } + + [TestCase("en-GB", null, "info@qowaiv.org", "info@qowaiv.org")] + [TestCase("nl-BE", "f", "info@qowaiv.org", "info@qowaiv.org")] + public void culture_dependent(CultureInfo culture, string format, EmailAddress svo, string expected) + { + using (culture.Scoped()) + { + svo.ToString(format).Should().Be(expected); + } + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) + { + Svo.EmailAddress.ToString(provider: null).Should().Be("info@qowaiv.org"); + } + } + + [TestCase("info@qowaiv.org", null)] + [TestCase("info@qowaiv.org", "")] + [TestCase("info@qowaiv.org", "f")] + [TestCase("INFO@QOWAIV.ORG", "U")] + [TestCase("INFO", "L")] + [TestCase("info", "l")] + [TestCase("qowaiv.org", "d")] + [TestCase("QOWAIV.ORG", "D")] + [TestCase("info@qowaiv.org", "l@d")] + public void with_format(string formatted, string format) + => Svo.EmailAddress.ToString(format).Should().Be(formatted); } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.EmailAddress.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_EmailAddress_as_object() - { - object obj = Svo.EmailAddress; - Svo.EmailAddress.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_EmailAddress_only() - { - Assert.Throws(() => Svo.EmailAddress.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - default, - default, - EmailAddress.Unknown, - EmailAddress.Parse("info@qowaiv.com"), - EmailAddress.Parse("info@qowaiv.org"), - EmailAddress.Parse("spam@qowaiv.org"), - }; - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.EmailAddress.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_EmailAddress_as_object() + { + object obj = Svo.EmailAddress; + Svo.EmailAddress.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_EmailAddress_only() + => new object().Invoking(Svo.EmailAddress.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + default, + default, + EmailAddress.Unknown, + EmailAddress.Parse("info@qowaiv.com"), + EmailAddress.Parse("info@qowaiv.org"), + EmailAddress.Parse("spam@qowaiv.org"), + }; + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(EmailAddress).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(EmailAddress.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(EmailAddress.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("info@qowaiv.org").To().Should().Be(Svo.EmailAddress); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.EmailAddress).Should().Be("info@qowaiv.org"); - } - } + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(EmailAddress).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(EmailAddress.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(EmailAddress.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("info@qowaiv.org").To().Should().Be(Svo.EmailAddress); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.EmailAddress).Should().Be("info@qowaiv.org"); + } + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase("?", "?")] - [TestCase("info@qowaiv.org", "info@qowaiv.org")] - public void System_Text_JSON_deserialization(object json, EmailAddress svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("info@qowaiv.org", "info@qowaiv.org")] - public void System_Text_JSON_serialization(object json, EmailAddress svo) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); - - [Test] - public void System_Text_JSON_deserialization_of_dictionary_keys() - { - System.Text.Json.JsonSerializer.Deserialize>(@"{""info@qowaiv.org"":42}") - .Should().BeEquivalentTo(new Dictionary() - { - [Svo.EmailAddress] = 42, - }); - } - - [Test] - public void System_Text_JSON_serialization_of_dictionary_keys() - { - var dictionary = new Dictionary() - { - [default] = 17, - [Svo.EmailAddress] = 42, - }; - System.Text.Json.JsonSerializer.Serialize(dictionary) - .Should().Be(@"{"""":17,""info@qowaiv.org"":42}"); - } + [TestCase("?", "?")] + [TestCase("info@qowaiv.org", "info@qowaiv.org")] + public void System_Text_JSON_deserialization(object json, EmailAddress svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("info@qowaiv.org", "info@qowaiv.org")] + public void System_Text_JSON_serialization(object json, EmailAddress svo) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + + [Test] + public void System_Text_JSON_deserialization_of_dictionary_keys() + { + System.Text.Json.JsonSerializer.Deserialize>(@"{""info@qowaiv.org"":42}") + .Should().BeEquivalentTo(new Dictionary() + { + [Svo.EmailAddress] = 42, + }); + } + + [Test] + public void System_Text_JSON_serialization_of_dictionary_keys() + { + var dictionary = new Dictionary() + { + [default] = 17, + [Svo.EmailAddress] = 42, + }; + System.Text.Json.JsonSerializer.Serialize(dictionary) + .Should().Be(@"{"""":17,""info@qowaiv.org"":42}"); + } #endif - [TestCase("?", "?")] - [TestCase("info@qowaiv.org", "info@qowaiv.org")] - public void convention_based_deserialization(object json, EmailAddress svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("info@qowaiv.org", "info@qowaiv.org")] - public void convention_based_serialization(object json, EmailAddress svo) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("?", "?")] + [TestCase("info@qowaiv.org", "info@qowaiv.org")] + public void convention_based_deserialization(object json, EmailAddress svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("info@qowaiv.org", "info@qowaiv.org")] + public void convention_based_serialization(object json, EmailAddress svo) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.EmailAddress); - xml.Should().Be("info@qowaiv.org"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("info@qowaiv.org"); - svo.Should().Be(Svo.EmailAddress); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.EmailAddress); - round_tripped.Should().Be(Svo.EmailAddress); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.EmailAddress); - var round_tripped = SerializeDeserialize.Xml(structure); - round_tripped.Should().Be(structure); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.EmailAddress; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.EmailAddress); + xml.Should().Be("info@qowaiv.org"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("info@qowaiv.org"); + svo.Should().Be(Svo.EmailAddress); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.EmailAddress); + round_tripped.Should().Be(Svo.EmailAddress); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.EmailAddress); + var round_tripped = SerializeDeserialize.Xml(structure); + round_tripped.Should().Be(structure); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.EmailAddress; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(EmailAddress)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(EmailAddress), - description: "Email notation as defined by RFC 5322.", - type: "string", - example: "svo@qowaiv.org", - format: "email", - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(EmailAddress)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(EmailAddress), + description: "Email notation as defined by RFC 5322.", + type: "string", + example: "svo@qowaiv.org", + format: "email", + nullable: true)); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.EmailAddress); - round_tripped.Should().Be(Svo.EmailAddress); - } - - [Test] - public void storing_string_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.EmailAddress); - info.GetString("Value").Should().Be("info@qowaiv.org"); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.EmailAddress); + round_tripped.Should().Be(Svo.EmailAddress); + } + + [Test] + public void storing_string_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.EmailAddress); + info.GetString("Value").Should().Be("info@qowaiv.org"); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("{unknown}", "?")] - [TestCase("info@qowaiv.org", "info@qowaiv.org")] - public void has_custom_display(object display, EmailAddress svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("{unknown}", "?")] + [TestCase("info@qowaiv.org", "info@qowaiv.org")] + public void has_custom_display(object display, EmailAddress svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Financial/IBAN_specs.cs b/specs/Qowaiv.Specs/Financial/IBAN_specs.cs index 6948bb90..6f1209d3 100644 --- a/specs/Qowaiv.Specs/Financial/IBAN_specs.cs +++ b/specs/Qowaiv.Specs/Financial/IBAN_specs.cs @@ -2,573 +2,572 @@ public class Supported { - private static readonly Country[] All = - [ - Country.AD, Country.AE, Country.AL, Country.AO, Country.AT, Country.AZ, - Country.BA, Country.BE, Country.BF, Country.BG, Country.BH, Country.BI, Country.BJ, Country.BR, Country.BY, - Country.CF, Country.CG, Country.CH,Country.CI, Country.CM, Country.CR, Country.CV, Country.CY, Country.CZ, - Country.DE, Country.DJ, Country.DK, Country.DO, Country.DZ, - Country.EE, Country.EG, Country.ES, - Country.FI, Country.FO, Country.FR, - Country.GA, Country.GB, Country.GE, Country.GI, Country.GL, Country.GQ, Country.GR, Country.GT, Country.GW, - Country.HN, Country.HR, Country.HU, - Country.IE, Country.IL, Country.IQ, Country.IR, Country.IS, Country.IT, - Country.JO, - Country.KM, Country.KW, Country.KZ, - Country.LB, Country.LC, Country.LI, Country.LT, Country.LU, Country.LV, Country.LY, - Country.MA, Country.MC, Country.MD, Country.ME, Country.MG, Country.MK, Country.ML, Country.MR, Country.MT, Country.MU, - Country.MZ, Country.NE, Country.NI, Country.NL, Country.NO, - Country.PK, Country.PL, Country.PS, Country.PT, - Country.QA, - Country.RO, Country.RS, Country.RU, - Country.SA, Country.SC, Country.SD, Country.SE, Country.SI, Country.SK, Country.SM, Country.SN, Country.ST, Country.SV, - Country.TD, Country.TG, Country.TL, Country.TN, Country.TR, - Country.UA, Country.VA, Country.VG, - Country.XK, - ]; - - [Test] - public void by_106_Countries() - { - InternationalBankAccountNumber.Supported.OrderBy(c => c.IsoAlpha2Code).Should().BeEquivalentTo(All); - InternationalBankAccountNumber.Supported.Count.Should().Be(106); - } + private static readonly Country[] All = + [ + Country.AD, Country.AE, Country.AL, Country.AO, Country.AT, Country.AZ, + Country.BA, Country.BE, Country.BF, Country.BG, Country.BH, Country.BI, Country.BJ, Country.BR, Country.BY, + Country.CF, Country.CG, Country.CH,Country.CI, Country.CM, Country.CR, Country.CV, Country.CY, Country.CZ, + Country.DE, Country.DJ, Country.DK, Country.DO, Country.DZ, + Country.EE, Country.EG, Country.ES, + Country.FI, Country.FO, Country.FR, + Country.GA, Country.GB, Country.GE, Country.GI, Country.GL, Country.GQ, Country.GR, Country.GT, Country.GW, + Country.HN, Country.HR, Country.HU, + Country.IE, Country.IL, Country.IQ, Country.IR, Country.IS, Country.IT, + Country.JO, + Country.KM, Country.KW, Country.KZ, + Country.LB, Country.LC, Country.LI, Country.LT, Country.LU, Country.LV, Country.LY, + Country.MA, Country.MC, Country.MD, Country.ME, Country.MG, Country.MK, Country.ML, Country.MR, Country.MT, Country.MU, + Country.MZ, Country.NE, Country.NI, Country.NL, Country.NO, + Country.PK, Country.PL, Country.PS, Country.PT, + Country.QA, + Country.RO, Country.RS, Country.RU, + Country.SA, Country.SC, Country.SD, Country.SE, Country.SI, Country.SK, Country.SM, Country.SN, Country.ST, Country.SV, + Country.TD, Country.TG, Country.TL, Country.TN, Country.TR, + Country.UA, Country.VA, Country.VG, + Country.XK, + ]; + + [Test] + public void by_106_Countries() + { + InternationalBankAccountNumber.Supported.OrderBy(c => c.IsoAlpha2Code).Should().BeEquivalentTo(All); + InternationalBankAccountNumber.Supported.Count.Should().Be(106); + } } public class With_domain_logic { - [TestCase("")] - [TestCase("?")] - public void has_length_zero_for_empty_and_unknown(InternationalBankAccountNumber svo) - => svo.Length.Should().Be(0); - - [TestCase(18, "NL20INGB0001234567")] - public void has_length(int length, InternationalBankAccountNumber svo) - => svo.Length.Should().Be(length); - - [TestCase(false, "NL20INGB0001234567")] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, InternationalBankAccountNumber svo) - => svo.IsEmpty().Should().Be(result); - - [TestCase(false, "NL20INGB0001234567")] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, InternationalBankAccountNumber svo) - => svo.IsEmptyOrUnknown().Should().Be(result); - - [TestCase(false, "NL20INGB0001234567")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, InternationalBankAccountNumber svo) - => svo.IsUnknown().Should().Be(result); - - [TestCase(true, "NL20INGB0001234567")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, InternationalBankAccountNumber svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, "NL20INGB0001234567")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, InternationalBankAccountNumber svo) => svo.IsKnown.Should().Be(result); - - [TestCase("", "")] - [TestCase("?", "?")] - [TestCase("NL", "NL20INGB0001234567")] - public void with_county(Country country, InternationalBankAccountNumber svo) - => svo.Country.Should().Be(country); + [TestCase("")] + [TestCase("?")] + public void has_length_zero_for_empty_and_unknown(InternationalBankAccountNumber svo) + => svo.Length.Should().Be(0); + + [TestCase(18, "NL20INGB0001234567")] + public void has_length(int length, InternationalBankAccountNumber svo) + => svo.Length.Should().Be(length); + + [TestCase(false, "NL20INGB0001234567")] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, InternationalBankAccountNumber svo) + => svo.IsEmpty().Should().Be(result); + + [TestCase(false, "NL20INGB0001234567")] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, InternationalBankAccountNumber svo) + => svo.IsEmptyOrUnknown().Should().Be(result); + + [TestCase(false, "NL20INGB0001234567")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, InternationalBankAccountNumber svo) + => svo.IsUnknown().Should().Be(result); + + [TestCase(true, "NL20INGB0001234567")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, InternationalBankAccountNumber svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, "NL20INGB0001234567")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, InternationalBankAccountNumber svo) => svo.IsKnown.Should().Be(result); + + [TestCase("", "")] + [TestCase("?", "?")] + [TestCase("NL", "NL20INGB0001234567")] + public void with_county(Country country, InternationalBankAccountNumber svo) + => svo.Country.Should().Be(country); } public class Has_constant { - [Test] - public void Empty() => InternationalBankAccountNumber.Empty.Should().Be(default); + [Test] + public void Empty() => InternationalBankAccountNumber.Empty.Should().Be(default); - [Test] - public void Unknown() => InternationalBankAccountNumber.Unknown.Should().Be(InternationalBankAccountNumber.Parse("?")); + [Test] + public void Unknown() => InternationalBankAccountNumber.Unknown.Should().Be(InternationalBankAccountNumber.Parse("?")); } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - => Svo.Iban.Equals(null).Should().BeFalse(); - - [Test] - public void not_equal_to_other_type() - => Svo.Iban.Equals(new object()).Should().BeFalse(); - - [Test] - public void not_equal_to_DE68210501700012345678_value() - => Svo.Iban.Equals(InternationalBankAccountNumber.Parse("DE68210501700012345678")).Should().BeFalse(); - - [Test] - public void equal_to_same_value() - => Svo.Iban.Equals(InternationalBankAccountNumber.Parse("NL20INGB0001234567")).Should().BeTrue(); - - [Test] - public void equal_operator_returns_true_for_same_values() - => (Svo.Iban == InternationalBankAccountNumber.Parse("NL20INGB0001234567")).Should().BeTrue(); - - [Test] - public void equal_operator_returns_false_for_DE68210501700012345678_values() - => (Svo.Iban == InternationalBankAccountNumber.Parse("DE68210501700012345678")).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_false_for_same_values() - => (Svo.Iban != InternationalBankAccountNumber.Parse("NL20INGB0001234567")).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_true_for_DE68210501700012345678_values() - => (Svo.Iban != InternationalBankAccountNumber.Parse("DE68210501700012345678")).Should().BeTrue(); - - [TestCase("", 0)] - [TestCase("NL20INGB0001234567", 684896179)] - public void hash_code_is_value_based(InternationalBankAccountNumber svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + => Svo.Iban.Equals(null).Should().BeFalse(); + + [Test] + public void not_equal_to_other_type() + => Svo.Iban.Equals(new object()).Should().BeFalse(); + + [Test] + public void not_equal_to_DE68210501700012345678_value() + => Svo.Iban.Equals(InternationalBankAccountNumber.Parse("DE68210501700012345678")).Should().BeFalse(); + + [Test] + public void equal_to_same_value() + => Svo.Iban.Equals(InternationalBankAccountNumber.Parse("NL20INGB0001234567")).Should().BeTrue(); + + [Test] + public void equal_operator_returns_true_for_same_values() + => (Svo.Iban == InternationalBankAccountNumber.Parse("NL20INGB0001234567")).Should().BeTrue(); + + [Test] + public void equal_operator_returns_false_for_DE68210501700012345678_values() + => (Svo.Iban == InternationalBankAccountNumber.Parse("DE68210501700012345678")).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_false_for_same_values() + => (Svo.Iban != InternationalBankAccountNumber.Parse("NL20INGB0001234567")).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_true_for_DE68210501700012345678_values() + => (Svo.Iban != InternationalBankAccountNumber.Parse("DE68210501700012345678")).Should().BeTrue(); + + [TestCase("", 0)] + [TestCase("NL20INGB0001234567", 684896179)] + public void hash_code_is_value_based(InternationalBankAccountNumber svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.Iban.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_InternationalBankAccountNumber_as_object() - { - object obj = Svo.Iban; - Svo.Iban.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_InternationalBankAccountNumber_only() - => Svo.Iban.Invoking(svo => svo.CompareTo(new object())) - .Should().Throw(); - - [Test] - public void can_be_sorted_using_compare() - { - InternationalBankAccountNumber[] sorted = - [ - default, - default, - InternationalBankAccountNumber.Parse("CG39 3001 1000 1010 1345 1300 019"), - InternationalBankAccountNumber.Parse("CH36 0838 7000 0010 8017 3"), - InternationalBankAccountNumber.Parse("CI02 N259 9162 9182 8879 7488 1965"), - InternationalBankAccountNumber.Unknown, - ]; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.Iban.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_InternationalBankAccountNumber_as_object() + { + object obj = Svo.Iban; + Svo.Iban.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_InternationalBankAccountNumber_only() + => new object().Invoking(Svo.Iban.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + InternationalBankAccountNumber[] sorted = + [ + default, + default, + InternationalBankAccountNumber.Parse("CG39 3001 1000 1010 1345 1300 019"), + InternationalBankAccountNumber.Parse("CH36 0838 7000 0010 8017 3"), + InternationalBankAccountNumber.Parse("CI02 N259 9162 9182 8879 7488 1965"), + InternationalBankAccountNumber.Unknown, + ]; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Has_custom_formatting { - [Test] - public void _default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Iban.ToString().Should().Be("NL20INGB0001234567"); - } - } - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Iban.ToString().Should().Be(Svo.Iban.ToString(default(string))); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Iban.ToString().Should().Be(Svo.Iban.ToString(string.Empty)); - } - } - - [Test] - public void default_value_is_represented_as_string_empty() - => default(InternationalBankAccountNumber).ToString().Should().BeEmpty(); - - [Test] - public void unknown_value_is_represented_as_unknown() - => InternationalBankAccountNumber.Unknown.ToString().Should().Be("?"); - - [Test] - public void with_empty_format_provider() - { - using (TestCultures.es_EC.Scoped()) - { - Svo.Iban.ToString(FormatProvider.Empty).Should().Be("NL20INGB0001234567"); - } - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.Iban.ToString("F", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: 'NL20 INGB 0001 2345 67', format: 'F'"); - } - - [TestCase(null, "NL20INGB0001234567", "NL20INGB0001234567")] - [TestCase("f", "NL20INGB0001234567", "nl20 ingb 0001 2345 67")] - [TestCase("h", "NL20INGB0001234567", "nl20 ingb 0001 2345 67")] - [TestCase("H", "NL20INGB0001234567", "NL20 INGB 0001 2345 67")] - [TestCase("u", "NL20INGB0001234567", "nl20ingb0001234567")] - [TestCase("U", "NL20INGB0001234567", "NL20INGB0001234567")] - [TestCase("m", "NL20INGB0001234567", "nl20ingb0001234567")] - [TestCase("M", "NL20INGB0001234567", "NL20INGB0001234567")] - [TestCase("F", "HR1723600001101234565", /*.......*/ "HR17 2360 0001 1012 3456 5")] - [TestCase("F", "NL20INGB0001234567", /*..........*/ "NL20 INGB 0001 2345 67")] - [TestCase("F", "FR1420041010050500013M02606", /*.*/ "FR14 2004 1010 0505 0001 3M02 606")] - [TestCase("F", "EE382200221020145685", /*........*/ "EE38 2200 2210 2014 5685")] - [TestCase("F", "", "")] - [TestCase("F", "?", "?")] - public void with_format(string format, InternationalBankAccountNumber svo, string formatted) - => svo.ToString(format).Should().Be(formatted); + [Test] + public void _default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Iban.ToString().Should().Be("NL20INGB0001234567"); + } + } + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Iban.ToString().Should().Be(Svo.Iban.ToString(default(string))); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Iban.ToString().Should().Be(Svo.Iban.ToString(string.Empty)); + } + } + + [Test] + public void default_value_is_represented_as_string_empty() + => default(InternationalBankAccountNumber).ToString().Should().BeEmpty(); + + [Test] + public void unknown_value_is_represented_as_unknown() + => InternationalBankAccountNumber.Unknown.ToString().Should().Be("?"); + + [Test] + public void with_empty_format_provider() + { + using (TestCultures.es_EC.Scoped()) + { + Svo.Iban.ToString(FormatProvider.Empty).Should().Be("NL20INGB0001234567"); + } + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.Iban.ToString("F", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: 'NL20 INGB 0001 2345 67', format: 'F'"); + } + + [TestCase(null, "NL20INGB0001234567", "NL20INGB0001234567")] + [TestCase("f", "NL20INGB0001234567", "nl20 ingb 0001 2345 67")] + [TestCase("h", "NL20INGB0001234567", "nl20 ingb 0001 2345 67")] + [TestCase("H", "NL20INGB0001234567", "NL20 INGB 0001 2345 67")] + [TestCase("u", "NL20INGB0001234567", "nl20ingb0001234567")] + [TestCase("U", "NL20INGB0001234567", "NL20INGB0001234567")] + [TestCase("m", "NL20INGB0001234567", "nl20ingb0001234567")] + [TestCase("M", "NL20INGB0001234567", "NL20INGB0001234567")] + [TestCase("F", "HR1723600001101234565", /*.......*/ "HR17 2360 0001 1012 3456 5")] + [TestCase("F", "NL20INGB0001234567", /*..........*/ "NL20 INGB 0001 2345 67")] + [TestCase("F", "FR1420041010050500013M02606", /*.*/ "FR14 2004 1010 0505 0001 3M02 606")] + [TestCase("F", "EE382200221020145685", /*........*/ "EE38 2200 2210 2014 5685")] + [TestCase("F", "", "")] + [TestCase("F", "?", "?")] + public void with_format(string format, InternationalBankAccountNumber svo, string formatted) + => svo.ToString(format).Should().Be(formatted); } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - => InternationalBankAccountNumber.Parse(null).Should().Be(InternationalBankAccountNumber.Empty); - - [Test] - public void from_empty_string_represents_Empty() - => InternationalBankAccountNumber.Parse(string.Empty).Should().Be(InternationalBankAccountNumber.Empty); - - [Test] - public void from_question_mark_represents_Unknown() - => InternationalBankAccountNumber.Parse("?").Should().Be(InternationalBankAccountNumber.Unknown); - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - Func parse = () => InternationalBankAccountNumber.Parse("invalid input"); - parse.Should().Throw() - .WithMessage("Not a valid IBAN"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - => (InternationalBankAccountNumber.TryParse("invalid input", out _)).Should().BeFalse(); - - [Test] - public void from_invalid_as_null_with_TryParse() - => InternationalBankAccountNumber.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - => InternationalBankAccountNumber.TryParse("NL20INGB0001234567").Should().Be(Svo.Iban); - - [TestCase(' ')] - [TestCase((char)160)] - [TestCase('\t')] - [TestCase('\r')] - [TestCase('\n')] - [TestCase('-')] - [TestCase('_')] - [TestCase('.')] - public void ignoring_formatting(char ch) - { - var iban = InternationalBankAccountNumber.Parse($"{ch}NL{ch}20{ch}INGB00{ch}0123456{ch}7{ch}"); - iban.Should().Be(Svo.Iban); - } + [Test] + public void from_null_string_represents_Empty() + => InternationalBankAccountNumber.Parse(null).Should().Be(InternationalBankAccountNumber.Empty); + + [Test] + public void from_empty_string_represents_Empty() + => InternationalBankAccountNumber.Parse(string.Empty).Should().Be(InternationalBankAccountNumber.Empty); + + [Test] + public void from_question_mark_represents_Unknown() + => InternationalBankAccountNumber.Parse("?").Should().Be(InternationalBankAccountNumber.Unknown); + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + Func parse = () => InternationalBankAccountNumber.Parse("invalid input"); + parse.Should().Throw() + .WithMessage("Not a valid IBAN"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + => (InternationalBankAccountNumber.TryParse("invalid input", out _)).Should().BeFalse(); + + [Test] + public void from_invalid_as_null_with_TryParse() + => InternationalBankAccountNumber.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + => InternationalBankAccountNumber.TryParse("NL20INGB0001234567").Should().Be(Svo.Iban); + + [TestCase(' ')] + [TestCase((char)160)] + [TestCase('\t')] + [TestCase('\r')] + [TestCase('\n')] + [TestCase('-')] + [TestCase('_')] + [TestCase('.')] + public void ignoring_formatting(char ch) + { + var iban = InternationalBankAccountNumber.Parse($"{ch}NL{ch}20{ch}INGB00{ch}0123456{ch}7{ch}"); + iban.Should().Be(Svo.Iban); + } } public class Can_not_be_parsed { - [Test] - public void with_markup_within_the_country_code() - => InternationalBankAccountNumber.TryParse("N L20INGB0001234567").Should().BeNull(); + [Test] + public void with_markup_within_the_country_code() + => InternationalBankAccountNumber.TryParse("N L20INGB0001234567").Should().BeNull(); - [Test] - public void with_markup_within_the_checksum_code() - => InternationalBankAccountNumber.TryParse("NL2 0INGB0001234567").Should().BeNull(); + [Test] + public void with_markup_within_the_checksum_code() + => InternationalBankAccountNumber.TryParse("NL2 0INGB0001234567").Should().BeNull(); } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(InternationalBankAccountNumber).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(InternationalBankAccountNumber.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(InternationalBankAccountNumber.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("NL20 INGB 0001 2345 67").To().Should().Be(Svo.Iban); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.Iban).Should().Be("NL20INGB0001234567"); - } - } + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(InternationalBankAccountNumber).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(InternationalBankAccountNumber.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(InternationalBankAccountNumber.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("NL20 INGB 0001 2345 67").To().Should().Be(Svo.Iban); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.Iban).Should().Be("NL20INGB0001234567"); + } + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase(null, null)] - [TestCase("NL20INGB0001234567", "NL20INGB0001234567")] - public void System_Text_JSON_deserialization(object json, InternationalBankAccountNumber svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("NL20INGB0001234567", "NL20INGB0001234567")] - public void System_Text_JSON_serialization(InternationalBankAccountNumber svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase(null, null)] + [TestCase("NL20INGB0001234567", "NL20INGB0001234567")] + public void System_Text_JSON_deserialization(object json, InternationalBankAccountNumber svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("NL20INGB0001234567", "NL20INGB0001234567")] + public void System_Text_JSON_serialization(InternationalBankAccountNumber svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("NL20INGB0001234567", "NL20INGB0001234567")] - public void convention_based_deserialization(object json, InternationalBankAccountNumber svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("NL20INGB0001234567", "NL20INGB0001234567")] - public void convention_based_serialization(InternationalBankAccountNumber svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - [TestCase(true, typeof(InvalidOperationException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("NL20INGB0001234567", "NL20INGB0001234567")] + public void convention_based_deserialization(object json, InternationalBankAccountNumber svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("NL20INGB0001234567", "NL20INGB0001234567")] + public void convention_based_serialization(InternationalBankAccountNumber svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + [TestCase(true, typeof(InvalidOperationException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.Iban); - xml.Should().Be("NL20INGB0001234567"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("NL20INGB0001234567"); - svo.Should().Be(Svo.Iban); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.Iban); - Svo.Iban.Should().Be(round_tripped); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.Iban); - var round_tripped = SerializeDeserialize.Xml(structure); - structure.Should().Be(round_tripped); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.Iban; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.Iban); + xml.Should().Be("NL20INGB0001234567"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("NL20INGB0001234567"); + svo.Should().Be(Svo.Iban); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.Iban); + Svo.Iban.Should().Be(round_tripped); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.Iban); + var round_tripped = SerializeDeserialize.Xml(structure); + structure.Should().Be(round_tripped); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.Iban; + obj.GetSchema().Should().BeNull(); + } } public class Input_is_invalid_when { - [Test] - public void country_does_not_exist() - => InternationalBankAccountNumber.TryParse("XX950210000000693123456").Should().BeNull(); - - [TestCase(" X")] - [TestCase("US34 5678 9AB")] - public void shorter_than_12(string iban) - => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); - - [Test] - public void longer_than_36() - => InternationalBankAccountNumber.TryParse("US00 2222 3333 4444 5555 6666 7777 8888 9999 A").Should().BeNull(); - - [TestCase("NL76 CZHQ 9695 4545 9")] - [TestCase("NL45 HEQN 0564 4242 147")] - public void length_does_not_match_country_BBAN(string iban) - => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); - - [Test] - public void other_than_alpha_numeric() - => InternationalBankAccountNumber.TryParse("AE20 #$12 0070 3456 7890 1234 5678").Should().BeNull(); - - [TestCase("ibanNL20INGB0001234567")] - [TestCase("iban :NL20INGB0001234567")] - [TestCase("iban : NL20INGB0001234567")] - [TestCase("(IB AN) NL20INGB0001234567")] - [TestCase("IBA-N NL20INGB0001234567")] - [TestCase("IBAN IBAN NL20INGB0001234567")] - [TestCase("(IBAN) IBAN NL20INGB0001234567")] - [TestCase("IBAN (IBAN) NL20INGB0001234567")] - public void string_with_malformed_IBAN_prefix(string str) - => InternationalBankAccountNumber.TryParse(str).Should().BeNull(); - - [TestCase("MU60 BOMM 0835 4151 5881 3959 000A BC")] - [TestCase("MU53 BOMM 0835 4151 5881 3959 000Z ZZ")] - public void Mauritius_does_not_end_with_currency_code(string iban) - => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); - - [TestCase("SC96 BANK 0835 4151 5881 3959 8706 ABC")] - [TestCase("SC89 BANK 0835 4151 5881 3959 8706 ZZZ")] - public void Seychelles_does_not_end_with_currency_code(string iban) - => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); - - [TestCase("BA23 1973 0058 1527 443")] - [TestCase("ME74 0986 4623 4212 3918 5")] - [TestCase("MK14 3935 0032 6437 91")] - [TestCase("MR34 8380 0832 4152 5888 3958 87")] - [TestCase("PT43 1185 0586 3461 2219 4930")] - [TestCase("RS07 8688 9281 0642 3946 9")] - [TestCase("SI72 3749 8042 5870 17")] - [TestCase("TL96 4551 5574 6824 5444 05")] - [TestCase("TN33 6926 5530 1193 5329 855")] - public void IBANs_with_fixed_checksum_have_a_different_one(string iban) - => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); + [Test] + public void country_does_not_exist() + => InternationalBankAccountNumber.TryParse("XX950210000000693123456").Should().BeNull(); + + [TestCase(" X")] + [TestCase("US34 5678 9AB")] + public void shorter_than_12(string iban) + => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); + + [Test] + public void longer_than_36() + => InternationalBankAccountNumber.TryParse("US00 2222 3333 4444 5555 6666 7777 8888 9999 A").Should().BeNull(); + + [TestCase("NL76 CZHQ 9695 4545 9")] + [TestCase("NL45 HEQN 0564 4242 147")] + public void length_does_not_match_country_BBAN(string iban) + => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); + + [Test] + public void other_than_alpha_numeric() + => InternationalBankAccountNumber.TryParse("AE20 #$12 0070 3456 7890 1234 5678").Should().BeNull(); + + [TestCase("ibanNL20INGB0001234567")] + [TestCase("iban :NL20INGB0001234567")] + [TestCase("iban : NL20INGB0001234567")] + [TestCase("(IB AN) NL20INGB0001234567")] + [TestCase("IBA-N NL20INGB0001234567")] + [TestCase("IBAN IBAN NL20INGB0001234567")] + [TestCase("(IBAN) IBAN NL20INGB0001234567")] + [TestCase("IBAN (IBAN) NL20INGB0001234567")] + public void string_with_malformed_IBAN_prefix(string str) + => InternationalBankAccountNumber.TryParse(str).Should().BeNull(); + + [TestCase("MU60 BOMM 0835 4151 5881 3959 000A BC")] + [TestCase("MU53 BOMM 0835 4151 5881 3959 000Z ZZ")] + public void Mauritius_does_not_end_with_currency_code(string iban) + => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); + + [TestCase("SC96 BANK 0835 4151 5881 3959 8706 ABC")] + [TestCase("SC89 BANK 0835 4151 5881 3959 8706 ZZZ")] + public void Seychelles_does_not_end_with_currency_code(string iban) + => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); + + [TestCase("BA23 1973 0058 1527 443")] + [TestCase("ME74 0986 4623 4212 3918 5")] + [TestCase("MK14 3935 0032 6437 91")] + [TestCase("MR34 8380 0832 4152 5888 3958 87")] + [TestCase("PT43 1185 0586 3461 2219 4930")] + [TestCase("RS07 8688 9281 0642 3946 9")] + [TestCase("SI72 3749 8042 5870 17")] + [TestCase("TL96 4551 5574 6824 5444 05")] + [TestCase("TN33 6926 5530 1193 5329 855")] + public void IBANs_with_fixed_checksum_have_a_different_one(string iban) + => InternationalBankAccountNumber.TryParse(iban).Should().BeNull(); } public class Input_is_valid { - [TestCase("iban NL20INGB0001234567")] - [TestCase("iban:NL20INGB0001234567")] - [TestCase("iban: NL20INGB0001234567")] - [TestCase("(iban)NL20INGB0001234567")] - [TestCase("(iban) NL20INGB0001234567")] - [TestCase("(Iban) NL20INGB0001234567")] - [TestCase("(IBAN) NL20INGB0001234567")] - [TestCase("Iban-NL20INGB0001234567")] - [TestCase("Iban NL20INGB0001234567")] - [TestCase("IBAN NL20INGB0001234567")] - [TestCase(" IBAN NL20INGB0001234567")] - [TestCase(" IBAN\tNL20INGB0001234567")] - [TestCase(" IBAN NL20INGB0001234567")] - public void string_with_IBAN_prefix(string str) - => InternationalBankAccountNumber.Parse(str).Should().Be(Svo.Iban); - - [TestCase("US70 ABCD 1234")] - [TestCase("US41 1234 5678 90AB CDEF GHIJ KLMN OPQR")] - [TestCase("US19 T3NB 32YP 2588 8395 8870 7523 1343 8517")] - public void for_countries_without_IBAN(string str) - { - var iban = InternationalBankAccountNumber.Parse(str); - InternationalBankAccountNumber.Supported.Should().NotContain(iban.Country); - } - - [Test] - public void despite_irregular_white_spacing() - => InternationalBankAccountNumber.Parse("AE950 2100000006 93123456").IsEmptyOrUnknown().Should().BeFalse(); - - [TestCase("CZ55 0800 0000 0012 3456 7899")] - [TestCase("CZ65 0800 0000 1920 0014 5399")] - [TestCase("EE86 2200 2210 6411 5891")] - [TestCase("HR17 2360 0001 1012 3456 5")] - [TestCase("HU13 1176 3842 0065 8885 0000 0000")] - [TestCase("HU39 1176 3842 0073 9012 0000 0000")] - [TestCase("HU32 1040 5004 0002 6548 0000 0009")] - [TestCase("HU32 1170 5008 2046 4565 0000 0000")] - [TestCase("PL02 2490 0005 0000 4600 8316 8772")] - [TestCase("PL16 1160 2202 0000 0002 7718 3060")] - [TestCase("PL53 1240 4650 1787 0010 7345 2383")] - [TestCase("PL83 2030 0045 1110 0000 0390 3540")] - public void for_countries_with_extended_validation(string iban) - => InternationalBankAccountNumber.TryParse(iban).Should().NotBeNull(); + [TestCase("iban NL20INGB0001234567")] + [TestCase("iban:NL20INGB0001234567")] + [TestCase("iban: NL20INGB0001234567")] + [TestCase("(iban)NL20INGB0001234567")] + [TestCase("(iban) NL20INGB0001234567")] + [TestCase("(Iban) NL20INGB0001234567")] + [TestCase("(IBAN) NL20INGB0001234567")] + [TestCase("Iban-NL20INGB0001234567")] + [TestCase("Iban NL20INGB0001234567")] + [TestCase("IBAN NL20INGB0001234567")] + [TestCase(" IBAN NL20INGB0001234567")] + [TestCase(" IBAN\tNL20INGB0001234567")] + [TestCase(" IBAN NL20INGB0001234567")] + public void string_with_IBAN_prefix(string str) + => InternationalBankAccountNumber.Parse(str).Should().Be(Svo.Iban); + + [TestCase("US70 ABCD 1234")] + [TestCase("US41 1234 5678 90AB CDEF GHIJ KLMN OPQR")] + [TestCase("US19 T3NB 32YP 2588 8395 8870 7523 1343 8517")] + public void for_countries_without_IBAN(string str) + { + var iban = InternationalBankAccountNumber.Parse(str); + InternationalBankAccountNumber.Supported.Should().NotContain(iban.Country); + } + + [Test] + public void despite_irregular_white_spacing() + => InternationalBankAccountNumber.Parse("AE950 2100000006 93123456").IsEmptyOrUnknown().Should().BeFalse(); + + [TestCase("CZ55 0800 0000 0012 3456 7899")] + [TestCase("CZ65 0800 0000 1920 0014 5399")] + [TestCase("EE86 2200 2210 6411 5891")] + [TestCase("HR17 2360 0001 1012 3456 5")] + [TestCase("HU13 1176 3842 0065 8885 0000 0000")] + [TestCase("HU39 1176 3842 0073 9012 0000 0000")] + [TestCase("HU32 1040 5004 0002 6548 0000 0009")] + [TestCase("HU32 1170 5008 2046 4565 0000 0000")] + [TestCase("PL02 2490 0005 0000 4600 8316 8772")] + [TestCase("PL16 1160 2202 0000 0002 7718 3060")] + [TestCase("PL53 1240 4650 1787 0010 7345 2383")] + [TestCase("PL83 2030 0045 1110 0000 0390 3540")] + public void for_countries_with_extended_validation(string iban) + => InternationalBankAccountNumber.TryParse(iban).Should().NotBeNull(); } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(InternationalBankAccountNumber)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType : typeof(InternationalBankAccountNumber), - description: "International Bank Account Number notation as defined by ISO 13616:2007.", - example: "BE71096123456769", - type: "string", - format: "iban", - pattern: "[A-Z]{2}[0-9]{2}[A-Z0-9]{8,32}", - nullable: true)); - - [TestCase("NL20INGB0001234567")] - public void pattern_matches(string input) - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(InternationalBankAccountNumber))!.Matches(input).Should().BeTrue(); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(InternationalBankAccountNumber)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(InternationalBankAccountNumber), + description: "International Bank Account Number notation as defined by ISO 13616:2007.", + example: "BE71096123456769", + type: "string", + format: "iban", + pattern: "[A-Z]{2}[0-9]{2}[A-Z0-9]{8,32}", + nullable: true)); + + [TestCase("NL20INGB0001234567")] + public void pattern_matches(string input) + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(InternationalBankAccountNumber))!.Matches(input).Should().BeTrue(); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Iban); - Svo.Iban.Should().Be(round_tripped); - } - - [Test] - public void storing_string_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Iban); - info.GetString("Value").Should().Be("NL20INGB0001234567"); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Iban); + Svo.Iban.Should().Be(round_tripped); + } + + [Test] + public void storing_string_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Iban); + info.GetString("Value").Should().Be("NL20INGB0001234567"); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("{unknown}", "?")] - [TestCase("NL20 INGB 0001 2345 67", "NL20INGB0001234567")] - public void has_custom_display(object display, InternationalBankAccountNumber svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("{unknown}", "?")] + [TestCase("NL20 INGB 0001 2345 67", "NL20INGB0001234567")] + public void has_custom_display(object display, InternationalBankAccountNumber svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Identifiers/Id_for_Guid_specs.cs b/specs/Qowaiv.Specs/Identifiers/Id_for_Guid_specs.cs index 3aebaee2..4f2511db 100644 --- a/specs/Qowaiv.Specs/Identifiers/Id_for_Guid_specs.cs +++ b/specs/Qowaiv.Specs/Identifiers/Id_for_Guid_specs.cs @@ -2,139 +2,139 @@ public class With_domain_logic { - [TestCase(true, "33ef5805-c472-4b1f-88bb-2f0723c43889")] - [TestCase(false, "")] - public void HasValue_is(bool result, CustomGuid svo) => svo.HasValue.Should().Be(result); + [TestCase(true, "33ef5805-c472-4b1f-88bb-2f0723c43889")] + [TestCase(false, "")] + public void HasValue_is(bool result, CustomGuid svo) => svo.HasValue.Should().Be(result); } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.CustomGuid.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_CustomGuid_as_object() - { - object obj = Svo.CustomGuid; - Svo.CustomGuid.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_CustomGuid_only() - => Assert.Throws(() => Svo.CustomGuid.CompareTo(new object())); - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - CustomGuid.Empty, - CustomGuid.Parse("33ef5805-c472-4b1f-88bb-2f0723c43889"), - CustomGuid.Parse("58617a65-2a14-4a9a-82a8-c1a82c956c25"), - CustomGuid.Parse("853634b4-e474-4b0f-b9ba-01fc732b56d8"), - CustomGuid.Parse("93ca7b43-8fb3-44e5-a21f-feeebb8e0f6f"), - CustomGuid.Parse("f5e6c39a-adcf-4eca-bcf2-6b8317ac502c"), - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.CustomGuid.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_CustomGuid_as_object() + { + object obj = Svo.CustomGuid; + Svo.CustomGuid.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_CustomGuid_only() + => new object().Invoking(Svo.CustomGuid.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + CustomGuid.Empty, + CustomGuid.Parse("33ef5805-c472-4b1f-88bb-2f0723c43889"), + CustomGuid.Parse("58617a65-2a14-4a9a-82a8-c1a82c956c25"), + CustomGuid.Parse("853634b4-e474-4b0f-b9ba-01fc732b56d8"), + CustomGuid.Parse("93ca7b43-8fb3-44e5-a21f-feeebb8e0f6f"), + CustomGuid.Parse("f5e6c39a-adcf-4eca-bcf2-6b8317ac502c"), + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(CustomGuid).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(CustomGuid.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(CustomGuid.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("8A1A8C42-D2FF-E254-E26E-B6ABCBF19420").To().Should().Be(Svo.CustomGuid); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.CustomGuid).Should().Be("8a1a8c42-d2ff-e254-e26e-b6abcbf19420"); - } - } - - [Test] - public void from_Guid() - => Converting.From(Svo.Guid).To().Should().Be(Svo.CustomGuid); - - - [Test] - public void from_Uuid() - => Converting.From(Svo.Uuid).To().Should().Be(Svo.CustomGuid); - - [Test] - public void to_Guid() - => Converting.To().From(Svo.CustomGuid).Should().Be(Svo.Guid); - - [Test] - public void to_Uuid() - => Converting.To().From(Svo.CustomGuid).Should().Be(Svo.Uuid); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(CustomGuid).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(CustomGuid.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(CustomGuid.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("8A1A8C42-D2FF-E254-E26E-B6ABCBF19420").To().Should().Be(Svo.CustomGuid); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.CustomGuid).Should().Be("8a1a8c42-d2ff-e254-e26e-b6abcbf19420"); + } + } + + [Test] + public void from_Guid() + => Converting.From(Svo.Guid).To().Should().Be(Svo.CustomGuid); + + + [Test] + public void from_Uuid() + => Converting.From(Svo.Uuid).To().Should().Be(Svo.CustomGuid); + + [Test] + public void to_Guid() + => Converting.To().From(Svo.CustomGuid).Should().Be(Svo.Guid); + + [Test] + public void to_Uuid() + => Converting.To().From(Svo.CustomGuid).Should().Be(Svo.Uuid); } public class Supports_JSON_serialization { - [Test] - public void writes_null_for_default_value() - => JsonTester.Write(default(CustomGuid)).Should().BeNull(); + [Test] + public void writes_null_for_default_value() + => JsonTester.Write(default(CustomGuid)).Should().BeNull(); - [Test] - public void writes_GUID_for_non_default_value() - => JsonTester.Write(Svo.CustomGuid).Should().Be("8a1a8c42-d2ff-e254-e26e-b6abcbf19420"); + [Test] + public void writes_GUID_for_non_default_value() + => JsonTester.Write(Svo.CustomGuid).Should().Be("8a1a8c42-d2ff-e254-e26e-b6abcbf19420"); #if NET6_0_OR_GREATER - [Test] - public void System_Text_JSON_deserialization_of_dictionary_keys() - { - System.Text.Json.JsonSerializer.Deserialize>(@"{""8a1a8c42-d2ff-e254-e26e-b6abcbf19420"":42}") - .Should().BeEquivalentTo(new Dictionary() - { - [Svo.CustomGuid] = 42, - }); - } - - [Test] - public void System_Text_JSON_serialization_of_dictionary_keys() - { - var dictionary = new Dictionary() - { - [default] = 17, - [Svo.CustomGuid] = 42, - }; - System.Text.Json.JsonSerializer.Serialize(dictionary) - .Should().Be(@"{"""":17,""8a1a8c42-d2ff-e254-e26e-b6abcbf19420"":42}"); - } + [Test] + public void System_Text_JSON_deserialization_of_dictionary_keys() + { + System.Text.Json.JsonSerializer.Deserialize>(@"{""8a1a8c42-d2ff-e254-e26e-b6abcbf19420"":42}") + .Should().BeEquivalentTo(new Dictionary() + { + [Svo.CustomGuid] = 42, + }); + } + + [Test] + public void System_Text_JSON_serialization_of_dictionary_keys() + { + var dictionary = new Dictionary() + { + [default] = 17, + [Svo.CustomGuid] = 42, + }; + System.Text.Json.JsonSerializer.Serialize(dictionary) + .Should().Be(@"{"""":17,""8a1a8c42-d2ff-e254-e26e-b6abcbf19420"":42}"); + } #endif } @@ -142,33 +142,33 @@ public void System_Text_JSON_serialization_of_dictionary_keys() #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.CustomGuid); - round_tripped.Should().Be(Svo.CustomGuid); - } - - [Test] - public void storing_value_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.CustomGuid); - info.GetValue("Value", typeof(Guid)).Should().Be(Guid.Parse("8A1A8C42-D2FF-E254-E26E-B6ABCBF19420")); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.CustomGuid); + round_tripped.Should().Be(Svo.CustomGuid); + } + + [Test] + public void storing_value_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.CustomGuid); + info.GetValue("Value", typeof(Guid)).Should().Be(Guid.Parse("8A1A8C42-D2FF-E254-E26E-B6ABCBF19420")); + } } #endif public class Is_Open_API_data_type { - [Test] - public void with_info() - => OpenApiDataType.FromType(typeof(ForGuid)) - .Should().Be(new OpenApiDataType( - dataType: typeof(CustomGuid), - description: "GUID based identifier", - example: "8a1a8c42-d2ff-e254-e26e-b6abcbf19420", - type: "string", - format: "guid", - nullable: true)); + [Test] + public void with_info() + => OpenApiDataType.FromType(typeof(ForGuid)) + .Should().Be(new OpenApiDataType( + dataType: typeof(CustomGuid), + description: "GUID based identifier", + example: "8a1a8c42-d2ff-e254-e26e-b6abcbf19420", + type: "string", + format: "guid", + nullable: true)); } diff --git a/specs/Qowaiv.Specs/Identifiers/Id_for_Int32_specs.cs b/specs/Qowaiv.Specs/Identifiers/Id_for_Int32_specs.cs index d2e8cfea..09b04c9f 100644 --- a/specs/Qowaiv.Specs/Identifiers/Id_for_Int32_specs.cs +++ b/specs/Qowaiv.Specs/Identifiers/Id_for_Int32_specs.cs @@ -2,180 +2,180 @@ public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.Int32Id.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_Int32Id_as_object() - { - object obj = Svo.Int32Id; - Svo.Int32Id.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Int32Id_only() - => Assert.Throws(() => Svo.Int32Id.CompareTo(new object())); - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - default, - Int32Id.Create(1), - Int32Id.Create(2), - Int32Id.Create(3), - Int32Id.Create(4), - Int32Id.Create(17), - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.Int32Id.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_Int32Id_as_object() + { + object obj = Svo.Int32Id; + Svo.Int32Id.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Int32Id_only() + => new object().Invoking(Svo.Int32Id.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + default, + Int32Id.Create(1), + Int32Id.Create(2), + Int32Id.Create(3), + Int32Id.Create(4), + Int32Id.Create(17), + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - - [TestCase("", "")] - [TestCase(12345678L, 12345678)] - [TestCase("12345678", 12345678)] - public void System_Text_JSON_deserialization(object json, Int32Id svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase("", null)] - [TestCase("12345678", 12345678L)] - public void System_Text_JSON_serialization(Int32Id svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); - - [TestCase(-2)] - [TestCase(17)] - [TestCase("17")] - [TestCase(int.MaxValue + 1L)] - public void taking_constrains_into_account(object json) - { - json.Invoking(JsonTester.Read_System_Text_JSON>) - .Should().Throw() - .WithMessage("Not a valid identifier."); - } - - private sealed class ForEven : Int32IdBehavior - { - public override bool TryCreate(object? obj, out object? id) - { - if(obj is int even && even % 2 == 0) - { - id = even; - return true; - } - else - { - id = null; - return false; - } - } - - public override bool TryParse(string? str, out object? id) - => TryCreate(int.TryParse(str, out int even) ? even : null, out id); - } + + [TestCase("", "")] + [TestCase(12345678L, 12345678)] + [TestCase("12345678", 12345678)] + public void System_Text_JSON_deserialization(object json, Int32Id svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase("", null)] + [TestCase("12345678", 12345678L)] + public void System_Text_JSON_serialization(Int32Id svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + + [TestCase(-2)] + [TestCase(17)] + [TestCase("17")] + [TestCase(int.MaxValue + 1L)] + public void taking_constrains_into_account(object json) + { + json.Invoking(JsonTester.Read_System_Text_JSON>) + .Should().Throw() + .WithMessage("Not a valid identifier."); + } + + private sealed class ForEven : Int32IdBehavior + { + public override bool TryCreate(object? obj, out object? id) + { + if (obj is int even && even % 2 == 0) + { + id = even; + return true; + } + else + { + id = null; + return false; + } + } + + public override bool TryParse(string? str, out object? id) + => TryCreate(int.TryParse(str, out int even) ? even : null, out id); + } #endif - [TestCase("", "")] - [TestCase(12345678L, 12345678)] - [TestCase("12345678", 12345678)] - public void convention_based_deserialization(object json, Int32Id svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase("", null)] - [TestCase("12345678", 12345678L)] - public void convention_based_serialization(Int32Id svo, object json) - => JsonTester.Write(svo).Should().Be(json); + [TestCase("", "")] + [TestCase(12345678L, 12345678)] + [TestCase("12345678", 12345678)] + public void convention_based_deserialization(object json, Int32Id svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase("", null)] + [TestCase("12345678", 12345678L)] + public void convention_based_serialization(Int32Id svo, object json) + => JsonTester.Write(svo).Should().Be(json); } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(Int32Id).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(Int32Id.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(Int32Id.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("PREFIX17").To().Should().Be(Svo.Int32Id); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.Int32Id).Should().Be("17"); - } - } - - [Test] - public void from_int() - => Converting.From(17).To().Should().Be(Svo.Int32Id); - - [Test] - public void to_int() - => Converting.To().From(Svo.Int32Id).Should().Be(17); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(Int32Id).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(Int32Id.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(Int32Id.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("PREFIX17").To().Should().Be(Svo.Int32Id); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.Int32Id).Should().Be("17"); + } + } + + [Test] + public void from_int() + => Converting.From(17).To().Should().Be(Svo.Int32Id); + + [Test] + public void to_int() + => Converting.To().From(Svo.Int32Id).Should().Be(17); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Int32Id); - round_tripped.Should().Be(Svo.Int32Id); - } - - [Test] - public void storing_value_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Int32Id); - info.GetInt32("Value").Should().Be(17); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Int32Id); + round_tripped.Should().Be(Svo.Int32Id); + } + + [Test] + public void storing_value_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Int32Id); + info.GetInt32("Value").Should().Be(17); + } } #endif public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(ForInt32)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(Int32Id), - description: "Int32 based identifier", - example: 17, - type: "integer", - format: "identifier", - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(ForInt32)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(Int32Id), + description: "Int32 based identifier", + example: 17, + type: "integer", + format: "identifier", + nullable: true)); } diff --git a/specs/Qowaiv.Specs/Identifiers/Id_for_Int64_specs.cs b/specs/Qowaiv.Specs/Identifiers/Id_for_Int64_specs.cs index 68bca9b8..d631ec8d 100644 --- a/specs/Qowaiv.Specs/Identifiers/Id_for_Int64_specs.cs +++ b/specs/Qowaiv.Specs/Identifiers/Id_for_Int64_specs.cs @@ -2,191 +2,191 @@ public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.Int64Id.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_Int64Id_as_object() - { - object obj = Svo.Int64Id; - Svo.Int64Id.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Int64Id_only() - => Assert.Throws(() => Svo.Int64Id.CompareTo(new object())); - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - Int64Id.Empty, - Int64Id.Create(1L), - Int64Id.Create(3L), - Int64Id.Create(7L), - Int64Id.Create(11L), - Int64Id.Create(17L), - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.Int64Id.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_Int64Id_as_object() + { + object obj = Svo.Int64Id; + Svo.Int64Id.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Int64Id_only() + => new object().Invoking(Svo.Int64Id.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + Int64Id.Empty, + Int64Id.Create(1L), + Int64Id.Create(3L), + Int64Id.Create(7L), + Int64Id.Create(11L), + Int64Id.Create(17L), + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase("", null)] - [TestCase(null, null)] - [TestCase(123456789L, 123456789L)] - [TestCase("123456789", 123456789L)] - public void System_Text_JSON_deserialization(object json, Int64Id svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase(123456789L, "123456789")] - public void System_Text_JSON_serialization(Int64Id svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); - - [TestCase(-2)] - [TestCase(17)] - [TestCase("17")] - public void taking_constrains_into_account(object json) - { - json.Invoking(JsonTester.Read_System_Text_JSON>) - .Should().Throw() - .WithMessage("Not a valid identifier."); - } - - private sealed class ForEven : Int64IdBehavior - { - public override bool TryCreate(object? obj, out object? id) - { - if (obj is long even && even % 2 == 0) - { - id = even; - return true; - } - else - { - id = null; - return false; - } - } - - public override bool TryParse(string? str, out object? id) - => TryCreate(long.TryParse(str, out long even) ? even : null, out id); - } + [TestCase("", null)] + [TestCase(null, null)] + [TestCase(123456789L, 123456789L)] + [TestCase("123456789", 123456789L)] + public void System_Text_JSON_deserialization(object json, Int64Id svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase(123456789L, "123456789")] + public void System_Text_JSON_serialization(Int64Id svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + + [TestCase(-2)] + [TestCase(17)] + [TestCase("17")] + public void taking_constrains_into_account(object json) + { + json.Invoking(JsonTester.Read_System_Text_JSON>) + .Should().Throw() + .WithMessage("Not a valid identifier."); + } + + private sealed class ForEven : Int64IdBehavior + { + public override bool TryCreate(object? obj, out object? id) + { + if (obj is long even && even % 2 == 0) + { + id = even; + return true; + } + else + { + id = null; + return false; + } + } + + public override bool TryParse(string? str, out object? id) + => TryCreate(long.TryParse(str, out long even) ? even : null, out id); + } #endif - [TestCase("", null)] - [TestCase(123456789L, 123456789L)] - [TestCase("123456789", 123456789L)] - public void convention_based_deserialization(object json, Int64Id svo) - => JsonTester.Read(json).Should().Be(svo); + [TestCase("", null)] + [TestCase(123456789L, 123456789L)] + [TestCase("123456789", 123456789L)] + public void convention_based_deserialization(object json, Int64Id svo) + => JsonTester.Read(json).Should().Be(svo); - [TestCase(null, null)] - [TestCase(123456789L, "123456789")] - public void convention_based_serialization(Int64Id svo, object json) - => JsonTester.Write(svo).Should().Be(json); + [TestCase(null, null)] + [TestCase(123456789L, "123456789")] + public void convention_based_serialization(Int64Id svo, object json) + => JsonTester.Write(svo).Should().Be(json); } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(Int64Id).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(Int64Id.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(Int64Id.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("PREFIX987654321").To().Should().Be(Svo.Int64Id); - } - } - - [Test] - public void to_string() - => Converting.ToString().From(Svo.Int64Id).Should().Be("987654321"); - - [Test] - public void from_long() - => Converting.From(987654321L).To().Should().Be(Svo.Int64Id); - - [Test] - public void to_long() - => Converting.To().From(Svo.Int64Id).Should().Be(987654321L); - - [TestCase("666")] - [TestCase("PREF17")] - public void from_invalid_string(string str) - { - Func convert = () => Converting.From(str).To(); - convert.Should().Throw() - .WithMessage("Cast from string to Qowaiv.Identifiers.Id is not valid."); - } - - [TestCase(-18)] - [TestCase(666)] - public void from_invalid_number(long number) - { - Func convert = () => Converting.From(number).To(); - convert.Should().Throw() - .WithMessage("Cast from long to Qowaiv.Identifiers.Id is not valid."); - } + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(Int64Id).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(Int64Id.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(Int64Id.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("PREFIX987654321").To().Should().Be(Svo.Int64Id); + } + } + + [Test] + public void to_string() + => Converting.ToString().From(Svo.Int64Id).Should().Be("987654321"); + + [Test] + public void from_long() + => Converting.From(987654321L).To().Should().Be(Svo.Int64Id); + + [Test] + public void to_long() + => Converting.To().From(Svo.Int64Id).Should().Be(987654321L); + + [TestCase("666")] + [TestCase("PREF17")] + public void from_invalid_string(string str) + { + Func convert = () => Converting.From(str).To(); + convert.Should().Throw() + .WithMessage("Cast from string to Qowaiv.Identifiers.Id is not valid."); + } + + [TestCase(-18)] + [TestCase(666)] + public void from_invalid_number(long number) + { + Func convert = () => Converting.From(number).To(); + convert.Should().Throw() + .WithMessage("Cast from long to Qowaiv.Identifiers.Id is not valid."); + } } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Int64Id); - round_tripped.Should().Be(Svo.Int64Id); - } - - [Test] - public void storing_value_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Int64Id); - info.GetInt64("Value").Should().Be(987654321L); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Int64Id); + round_tripped.Should().Be(Svo.Int64Id); + } + + [Test] + public void storing_value_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Int64Id); + info.GetInt64("Value").Should().Be(987654321L); + } } #endif public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(ForInt64)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(Int64Id), - description: "Int64 based identifier", - example: 17, - type: "integer", - format: "identifier", - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(ForInt64)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(Int64Id), + description: "Int64 based identifier", + example: 17, + type: "integer", + format: "identifier", + nullable: true)); } diff --git a/specs/Qowaiv.Specs/Identifiers/Id_for_String_specs.cs b/specs/Qowaiv.Specs/Identifiers/Id_for_String_specs.cs index 89b9d9dc..dec8f145 100644 --- a/specs/Qowaiv.Specs/Identifiers/Id_for_String_specs.cs +++ b/specs/Qowaiv.Specs/Identifiers/Id_for_String_specs.cs @@ -2,113 +2,113 @@ public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.StringId.CompareTo(Nil.Object).Should().Be(1); + [Test] + public void to_null_is_1() => Svo.StringId.CompareTo(Nil.Object).Should().Be(1); - [Test] - public void to_StringId_as_object() - { - object obj = Svo.StringId; - Svo.StringId.CompareTo(obj).Should().Be(0); - } + [Test] + public void to_StringId_as_object() + { + object obj = Svo.StringId; + Svo.StringId.CompareTo(obj).Should().Be(0); + } - [Test] - public void to_StringId_only() - => Assert.Throws(() => Svo.StringId.CompareTo(new object())); + [Test] + public void to_StringId_only() + => new object().Invoking(Svo.StringId.CompareTo).Should().Throw(); - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - StringId.Empty, - StringId.Parse("33ef5805c472"), - StringId.Parse("58617a652a14"), - StringId.Parse("853634b4e474"), - StringId.Parse("93ca7b438fb3"), - StringId.Parse("f5e6c39aadcf"), - }; + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + StringId.Empty, + StringId.Parse("33ef5805c472"), + StringId.Parse("58617a652a14"), + StringId.Parse("853634b4e474"), + StringId.Parse("93ca7b438fb3"), + StringId.Parse("f5e6c39aadcf"), + }; - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(StringId).Should().HaveTypeConverterDefined(); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(StringId).Should().HaveTypeConverterDefined(); - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(StringId.Empty); - } - } + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(StringId.Empty); + } + } - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(StringId.Empty); - } - } + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(StringId.Empty); + } + } - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("Qowaiv-ID").To().Should().Be(Svo.StringId); - } - } + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("Qowaiv-ID").To().Should().Be(Svo.StringId); + } + } - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.StringId).Should().Be("Qowaiv-ID"); - } - } + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.StringId).Should().Be("Qowaiv-ID"); + } + } } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.StringId); - round_tripped.Should().Be(Svo.StringId); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.StringId); + round_tripped.Should().Be(Svo.StringId); + } - [Test] - public void storing_value_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.StringId); - info.GetString("Value").Should().Be("Qowaiv-ID"); - } + [Test] + public void storing_value_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.StringId); + info.GetString("Value").Should().Be("Qowaiv-ID"); + } } #endif public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(ForString)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(StringId), - description: "String based identifier", - example: "Order-UK-2022-215", - type: "string", - format: "identifier", - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(ForString)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(StringId), + description: "String based identifier", + example: "Order-UK-2022-215", + type: "string", + format: "identifier", + nullable: true)); } diff --git a/specs/Qowaiv.Specs/Identifiers/Id_for_Uuid_specs.cs b/specs/Qowaiv.Specs/Identifiers/Id_for_Uuid_specs.cs index 3ab500db..ba320f8d 100644 --- a/specs/Qowaiv.Specs/Identifiers/Id_for_Uuid_specs.cs +++ b/specs/Qowaiv.Specs/Identifiers/Id_for_Uuid_specs.cs @@ -2,139 +2,139 @@ public class With_domain_logic { - [TestCase(true, "Qowaiv_SVOLibrary_GUIA")] - [TestCase(false, "")] - public void HasValue_is(bool result, CustomUuid svo) => svo.HasValue.Should().Be(result); + [TestCase(true, "Qowaiv_SVOLibrary_GUIA")] + [TestCase(false, "")] + public void HasValue_is(bool result, CustomUuid svo) => svo.HasValue.Should().Be(result); } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.CustomUuid.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_CustomUuid_as_object() - { - object obj = Svo.CustomUuid; - Svo.CustomUuid.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_CustomUuid_only() - => Assert.Throws(() => Svo.CustomUuid.CompareTo(new object())); - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - CustomUuid.Empty, - CustomUuid.Parse("33ef5805-c472-4b1f-88bb-2f0723c43889"), - CustomUuid.Parse("58617a65-2a14-4a9a-82a8-c1a82c956c25"), - CustomUuid.Parse("853634b4-e474-4b0f-b9ba-01fc732b56d8"), - CustomUuid.Parse("93ca7b43-8fb3-44e5-a21f-feeebb8e0f6f"), - CustomUuid.Parse("f5e6c39a-adcf-4eca-bcf2-6b8317ac502c"), - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.CustomUuid.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_CustomUuid_as_object() + { + object obj = Svo.CustomUuid; + Svo.CustomUuid.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_CustomUuid_only() + => new object().Invoking(Svo.CustomUuid.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + CustomUuid.Empty, + CustomUuid.Parse("33ef5805-c472-4b1f-88bb-2f0723c43889"), + CustomUuid.Parse("58617a65-2a14-4a9a-82a8-c1a82c956c25"), + CustomUuid.Parse("853634b4-e474-4b0f-b9ba-01fc732b56d8"), + CustomUuid.Parse("93ca7b43-8fb3-44e5-a21f-feeebb8e0f6f"), + CustomUuid.Parse("f5e6c39a-adcf-4eca-bcf2-6b8317ac502c"), + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(CustomUuid).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(CustomUuid.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(CustomUuid.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("Qowaiv_SVOLibrary_GUIA").To().Should().Be(Svo.CustomUuid); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.CustomUuid).Should().Be("Qowaiv_SVOLibrary_GUIA"); - } - } - - [Test] - public void from_Guid() - => Converting.From(Svo.Guid).To().Should().Be(Svo.CustomUuid); - - - [Test] - public void from_Uuid() - => Converting.From(Svo.Uuid).To().Should().Be(Svo.CustomUuid); - - [Test] - public void to_Guid() - => Converting.To().From(Svo.CustomUuid).Should().Be(Svo.Guid); - - [Test] - public void to_Uuid() - => Converting.To().From(Svo.CustomUuid).Should().Be(Svo.Uuid); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(CustomUuid).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(CustomUuid.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(CustomUuid.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("Qowaiv_SVOLibrary_GUIA").To().Should().Be(Svo.CustomUuid); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.CustomUuid).Should().Be("Qowaiv_SVOLibrary_GUIA"); + } + } + + [Test] + public void from_Guid() + => Converting.From(Svo.Guid).To().Should().Be(Svo.CustomUuid); + + + [Test] + public void from_Uuid() + => Converting.From(Svo.Uuid).To().Should().Be(Svo.CustomUuid); + + [Test] + public void to_Guid() + => Converting.To().From(Svo.CustomUuid).Should().Be(Svo.Guid); + + [Test] + public void to_Uuid() + => Converting.To().From(Svo.CustomUuid).Should().Be(Svo.Uuid); } public class Supports_JSON_serialization { - [Test] - public void writes_null_for_default_value() - => JsonTester.Write(default(CustomUuid)).Should().BeNull(); + [Test] + public void writes_null_for_default_value() + => JsonTester.Write(default(CustomUuid)).Should().BeNull(); - [Test] - public void writes_Base64_string_for_non_default_value() - => JsonTester.Write(Svo.CustomUuid).Should().Be("Qowaiv_SVOLibrary_GUIA"); + [Test] + public void writes_Base64_string_for_non_default_value() + => JsonTester.Write(Svo.CustomUuid).Should().Be("Qowaiv_SVOLibrary_GUIA"); #if NET6_0_OR_GREATER - [Test] - public void System_Text_JSON_deserialization_of_dictionary_keys() - { - System.Text.Json.JsonSerializer.Deserialize>(@"{""Qowaiv_SVOLibrary_GUIA"":42}") - .Should().BeEquivalentTo(new Dictionary() - { - [Svo.CustomUuid] = 42, - }); - } - - [Test] - public void System_Text_JSON_serialization_of_dictionary_keys() - { - var dictionary = new Dictionary() - { - [default] = 17, - [Svo.CustomUuid] = 42, - }; - System.Text.Json.JsonSerializer.Serialize(dictionary) - .Should().Be(@"{"""":17,""Qowaiv_SVOLibrary_GUIA"":42}"); - } + [Test] + public void System_Text_JSON_deserialization_of_dictionary_keys() + { + System.Text.Json.JsonSerializer.Deserialize>(@"{""Qowaiv_SVOLibrary_GUIA"":42}") + .Should().BeEquivalentTo(new Dictionary() + { + [Svo.CustomUuid] = 42, + }); + } + + [Test] + public void System_Text_JSON_serialization_of_dictionary_keys() + { + var dictionary = new Dictionary() + { + [default] = 17, + [Svo.CustomUuid] = 42, + }; + System.Text.Json.JsonSerializer.Serialize(dictionary) + .Should().Be(@"{"""":17,""Qowaiv_SVOLibrary_GUIA"":42}"); + } #endif } @@ -142,33 +142,33 @@ public void System_Text_JSON_serialization_of_dictionary_keys() #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.CustomUuid); - round_tripped.Should().Be(Svo.CustomUuid); - } - - [Test] - public void storing_value_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.CustomUuid); - info.GetValue("Value", typeof(Guid)).Should().Be(Guid.Parse("8A1A8C42-D2FF-E254-E26E-B6ABCBF19420")); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.CustomUuid); + round_tripped.Should().Be(Svo.CustomUuid); + } + + [Test] + public void storing_value_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.CustomUuid); + info.GetValue("Value", typeof(Guid)).Should().Be(Guid.Parse("8A1A8C42-D2FF-E254-E26E-B6ABCBF19420")); + } } #endif public class Is_Open_API_data_type { - [Test] - public void with_info() - => OpenApiDataType.FromType(typeof(ForUuid)) - .Should().Be(new OpenApiDataType( - dataType: typeof(CustomUuid), - description: "UUID based identifier", - example: "lmZO_haEOTCwGsCcbIZFFg", - type: "string", - format: "uuid-base64", - nullable: true)); + [Test] + public void with_info() + => OpenApiDataType.FromType(typeof(ForUuid)) + .Should().Be(new OpenApiDataType( + dataType: typeof(CustomUuid), + description: "UUID based identifier", + example: "lmZO_haEOTCwGsCcbIZFFg", + type: "string", + format: "uuid-base64", + nullable: true)); } diff --git a/specs/Qowaiv.Specs/Mathematics/Fraction_specs.cs b/specs/Qowaiv.Specs/Mathematics/Fraction_specs.cs index 90528057..27ec25ec 100644 --- a/specs/Qowaiv.Specs/Mathematics/Fraction_specs.cs +++ b/specs/Qowaiv.Specs/Mathematics/Fraction_specs.cs @@ -4,953 +4,953 @@ namespace Mathematics.Fraction_specs; public class Defines { - [TestCase("0", "0")] - [TestCase("17/3", "17/3")] - [TestCase("-7/3", "-7/3")] - public void plus(Fraction fraction, Fraction negated) => (+fraction).Should().Be(negated); - - [TestCase("0", "0")] - [TestCase("-7/3", "+7/3")] - [TestCase("+7/3", "-7/3")] - public void negation(Fraction fraction, Fraction negated) => (-fraction).Should().Be(negated); - - [Test] - public void increment() - { - var fraction = Svo.Fraction; - fraction++; - fraction.Should().Be(-52.DividedBy(17)); - } - - [Test] - public void decrement() - { - var fraction = Svo.Fraction; - fraction--; - fraction.Should().Be(-86.DividedBy(17)); - } - - public class Multiplication - { - [TestCase("1/3", "0", "0")] - [TestCase("0", "5/7", "0")] - [TestCase("1/3", "1/4", "1/12")] - [TestCase("-1/3", "-1/4", "1/12")] - [TestCase("1/4", "4/7", "1/7")] - [TestCase("2/5", "11/16", "11/40")] - [TestCase("-2/5", "4", "-8/5")] - [TestCase("2/3", "-8/9", "-16/27")] - public void between_fractions(Fraction left, Fraction right, Fraction product) - => (left * right).Should().Be(product); - - [Test] - public void between_fractions_and_longs() - => (1.DividedBy(3) * 4L).Should().Be(4.DividedBy(3)); - - [Test] - public void between_fractions_and_ints() - => (1.DividedBy(3) * 4).Should().Be(4.DividedBy(3)); - - - [Test] - public void between_longs_and_fractions() - => (4L * 1.DividedBy(3)).Should().Be(4.DividedBy(3)); - - [Test] - public void between_ints_and_fractions() - => (4 * 1.DividedBy(3)).Should().Be(4.DividedBy(3)); - } - - public class Division - { - [TestCase("0", "1/3", "0")] - [TestCase("1/3", "1/4", "4/3")] - [TestCase("-1/3", "-1/4", "4/3")] - [TestCase("1/4", "4/7", "7/16")] - [TestCase("2/5", "11/16", "32/55")] - [TestCase("-2/5", "4", "-1/10")] - [TestCase("2/3", "-8/9", "-3/4")] - public void between_Fractions(Fraction left, Fraction right, Fraction division) - => (left / right).Should().Be(division); - - [Test] - public void between_fractions([RandomFraction(3)] Fraction left, [RandomFraction(3, false)] Fraction right) - { - var division = ((decimal)left) / ((decimal)right); - (left / right).Should().Be(division.Fraction()); - } - - [Test] - public void between_fractions_and_longs() - => (1.DividedBy(3) / 4L).Should().Be(1.DividedBy(12)); - - [Test] - public void between_fractions_and_ints() - => (1.DividedBy(3) / 4).Should().Be(1.DividedBy(12)); - - - [Test] - public void between_longs_and_fractions() - => (5L / 2.DividedBy(3)).Should().Be(15.DividedBy(2)); - - [Test] - public void between_ints_and_fractions() - => (5 / 2.DividedBy(3)).Should().Be(15.DividedBy(2)); - } - - public class Addition - { - [TestCase("1/4", "0", "1/4")] - [TestCase("0", "1/4", "1/4")] - [TestCase("5/7", "0", "5/7")] - [TestCase("1/3", "1/4", "7/12")] - [TestCase("1/4", "1/3", "7/12")] - [TestCase("1/4", "1/12", "1/3")] - [TestCase("-1/4", "-1/12", "-1/3")] - [TestCase("-1/4", "1/12", "-1/6")] - [TestCase("1/5", "2/5", "3/5")] - [TestCase("8/3", "1/2", "19/6")] - public void between_fractions(Fraction left, Fraction right, Fraction addition) - => (left + right).Should().Be(addition); - - [Test] - public void between_fractions([RandomFraction(3)] Fraction left, [RandomFraction(3)] Fraction right) - { - var sum = ((decimal)left) + ((decimal)right); - (left + right).Should().Be(sum.Fraction()); - } - - [Test] - public void between_fractions_and_longs() - => (1.DividedBy(3) + 4L).Should().Be(13.DividedBy(3)); - - [Test] - public void between_fractions_and_ints() - => (1.DividedBy(3) + 4).Should().Be(13.DividedBy(3)); - - - [Test] - public void between_longs_and_fractions() - => (4L + 1.DividedBy(3)).Should().Be(13.DividedBy(3)); - - [Test] - public void between_ints_and_fractions() - => (4 + 1.DividedBy(3)).Should().Be(13.DividedBy(3)); - } - - public class Subtraction - { - [TestCase("1/4", "0", "1/4")] - [TestCase("0", "1/4", "-1/4")] - [TestCase("1/3", "1/4", "1/12")] - [TestCase("1/4", "1/3", "-1/12")] - [TestCase("1/4", "1/12", "1/6")] - [TestCase("-1/4", "-1/12", "-1/6")] - [TestCase("-1/4", "1/12", "-1/3")] - public void between_fractions(Fraction left, Fraction right, Fraction subtraction) - => (left - right).Should().Be(subtraction); - - [Test] - public void between_fractions([RandomFraction(3)] Fraction left, [RandomFraction(3)] Fraction right) - { - var subtraction = ((decimal)left) - ((decimal)right); - (left - right).Should().Be(subtraction.Fraction()); - } - - [Test] - public void between_fractions_and_longs() - => (1.DividedBy(3) - 4L).Should().Be(-11.DividedBy(3)); - - [Test] - public void between_fractions_and_ints() - => (1.DividedBy(3) - 4).Should().Be(-11.DividedBy(3)); - - [Test] - public void between_longs_and_fractions() - => (4L - 1.DividedBy(3)).Should().Be(11.DividedBy(3)); - - [Test] - public void between_ints_and_fractions() - => (4 - 1.DividedBy(3)).Should().Be(11.DividedBy(3)); - } - - public class Modulation - { - [TestCase("5/4", "1/1", "1/4")] - [TestCase("-5/4", "1/1", "-1/4")] - [TestCase("5/3", "2/3", "1/3")] - public void between_fractions(Fraction fraction, Fraction divider, Fraction remainder) - => (fraction % divider).Should().Be(remainder); - - [Test] - public void between_fractions([RandomFraction(3)] Fraction fraction, [RandomFraction(3, false)] Fraction divider) - { - var modulo = ((decimal)fraction) % ((decimal)divider); - (fraction % divider).Should().Be(modulo.Fraction()); - } - - [Test] - public void between_fractions_and_longs() - => (1.DividedBy(3) % 4L).Should().Be(1.DividedBy(3)); - - [Test] - public void between_fractions_and_ints() - => (1.DividedBy(3) % 4).Should().Be(1.DividedBy(3)); - - [Test] - public void between_longs_and_fractions() - => (4L % 3.DividedBy(1)).Should().Be(1.DividedBy(1)); - - [Test] - public void between_ints_and_fractions() - => (4 % 3.DividedBy(1)).Should().Be(1.DividedBy(1)); - } - - [TestCase("0", "0")] - [TestCase("17/3", "17/3")] - [TestCase("-7/3", "+7/3")] - public void abs(Fraction fraction, Fraction absolute) - => fraction.Abs().Should().Be(absolute); - - [TestCase("+1/4", "4/1")] - [TestCase("-2/3", "-3/2")] - public void inverse(Fraction faction, Fraction inverse) - => faction.Inverse().Should().Be(inverse); - - [TestCase("0", 0)] - [TestCase("-1/4", -1)] - [TestCase("+1/4", +1)] - public void sign(Fraction fraction, int sign) - => fraction.Sign().Should().Be(sign); - - [TestCase("-69/17", 1)] - [TestCase("+69/17", 1)] - [TestCase("0", 0)] - public void remainder_as_positive_value(Fraction fraction, int remainder) - => fraction.Remainder.Should().Be(remainder); - - [TestCase("-69/17", -4)] - [TestCase("+69/17", +4)] - [TestCase("0", 0)] - public void whole(Fraction fraction, int remainder) - => fraction.Whole.Should().Be(remainder); + [TestCase("0", "0")] + [TestCase("17/3", "17/3")] + [TestCase("-7/3", "-7/3")] + public void plus(Fraction fraction, Fraction negated) => (+fraction).Should().Be(negated); + + [TestCase("0", "0")] + [TestCase("-7/3", "+7/3")] + [TestCase("+7/3", "-7/3")] + public void negation(Fraction fraction, Fraction negated) => (-fraction).Should().Be(negated); + + [Test] + public void increment() + { + var fraction = Svo.Fraction; + fraction++; + fraction.Should().Be(-52.DividedBy(17)); + } + + [Test] + public void decrement() + { + var fraction = Svo.Fraction; + fraction--; + fraction.Should().Be(-86.DividedBy(17)); + } + + public class Multiplication + { + [TestCase("1/3", "0", "0")] + [TestCase("0", "5/7", "0")] + [TestCase("1/3", "1/4", "1/12")] + [TestCase("-1/3", "-1/4", "1/12")] + [TestCase("1/4", "4/7", "1/7")] + [TestCase("2/5", "11/16", "11/40")] + [TestCase("-2/5", "4", "-8/5")] + [TestCase("2/3", "-8/9", "-16/27")] + public void between_fractions(Fraction left, Fraction right, Fraction product) + => (left * right).Should().Be(product); + + [Test] + public void between_fractions_and_longs() + => (1.DividedBy(3) * 4L).Should().Be(4.DividedBy(3)); + + [Test] + public void between_fractions_and_ints() + => (1.DividedBy(3) * 4).Should().Be(4.DividedBy(3)); + + + [Test] + public void between_longs_and_fractions() + => (4L * 1.DividedBy(3)).Should().Be(4.DividedBy(3)); + + [Test] + public void between_ints_and_fractions() + => (4 * 1.DividedBy(3)).Should().Be(4.DividedBy(3)); + } + + public class Division + { + [TestCase("0", "1/3", "0")] + [TestCase("1/3", "1/4", "4/3")] + [TestCase("-1/3", "-1/4", "4/3")] + [TestCase("1/4", "4/7", "7/16")] + [TestCase("2/5", "11/16", "32/55")] + [TestCase("-2/5", "4", "-1/10")] + [TestCase("2/3", "-8/9", "-3/4")] + public void between_Fractions(Fraction left, Fraction right, Fraction division) + => (left / right).Should().Be(division); + + [Test] + public void between_fractions([RandomFraction(3)] Fraction left, [RandomFraction(3, false)] Fraction right) + { + var division = ((decimal)left) / ((decimal)right); + (left / right).Should().Be(division.Fraction()); + } + + [Test] + public void between_fractions_and_longs() + => (1.DividedBy(3) / 4L).Should().Be(1.DividedBy(12)); + + [Test] + public void between_fractions_and_ints() + => (1.DividedBy(3) / 4).Should().Be(1.DividedBy(12)); + + + [Test] + public void between_longs_and_fractions() + => (5L / 2.DividedBy(3)).Should().Be(15.DividedBy(2)); + + [Test] + public void between_ints_and_fractions() + => (5 / 2.DividedBy(3)).Should().Be(15.DividedBy(2)); + } + + public class Addition + { + [TestCase("1/4", "0", "1/4")] + [TestCase("0", "1/4", "1/4")] + [TestCase("5/7", "0", "5/7")] + [TestCase("1/3", "1/4", "7/12")] + [TestCase("1/4", "1/3", "7/12")] + [TestCase("1/4", "1/12", "1/3")] + [TestCase("-1/4", "-1/12", "-1/3")] + [TestCase("-1/4", "1/12", "-1/6")] + [TestCase("1/5", "2/5", "3/5")] + [TestCase("8/3", "1/2", "19/6")] + public void between_fractions(Fraction left, Fraction right, Fraction addition) + => (left + right).Should().Be(addition); + + [Test] + public void between_fractions([RandomFraction(3)] Fraction left, [RandomFraction(3)] Fraction right) + { + var sum = ((decimal)left) + ((decimal)right); + (left + right).Should().Be(sum.Fraction()); + } + + [Test] + public void between_fractions_and_longs() + => (1.DividedBy(3) + 4L).Should().Be(13.DividedBy(3)); + + [Test] + public void between_fractions_and_ints() + => (1.DividedBy(3) + 4).Should().Be(13.DividedBy(3)); + + + [Test] + public void between_longs_and_fractions() + => (4L + 1.DividedBy(3)).Should().Be(13.DividedBy(3)); + + [Test] + public void between_ints_and_fractions() + => (4 + 1.DividedBy(3)).Should().Be(13.DividedBy(3)); + } + + public class Subtraction + { + [TestCase("1/4", "0", "1/4")] + [TestCase("0", "1/4", "-1/4")] + [TestCase("1/3", "1/4", "1/12")] + [TestCase("1/4", "1/3", "-1/12")] + [TestCase("1/4", "1/12", "1/6")] + [TestCase("-1/4", "-1/12", "-1/6")] + [TestCase("-1/4", "1/12", "-1/3")] + public void between_fractions(Fraction left, Fraction right, Fraction subtraction) + => (left - right).Should().Be(subtraction); + + [Test] + public void between_fractions([RandomFraction(3)] Fraction left, [RandomFraction(3)] Fraction right) + { + var subtraction = ((decimal)left) - ((decimal)right); + (left - right).Should().Be(subtraction.Fraction()); + } + + [Test] + public void between_fractions_and_longs() + => (1.DividedBy(3) - 4L).Should().Be(-11.DividedBy(3)); + + [Test] + public void between_fractions_and_ints() + => (1.DividedBy(3) - 4).Should().Be(-11.DividedBy(3)); + + [Test] + public void between_longs_and_fractions() + => (4L - 1.DividedBy(3)).Should().Be(11.DividedBy(3)); + + [Test] + public void between_ints_and_fractions() + => (4 - 1.DividedBy(3)).Should().Be(11.DividedBy(3)); + } + + public class Modulation + { + [TestCase("5/4", "1/1", "1/4")] + [TestCase("-5/4", "1/1", "-1/4")] + [TestCase("5/3", "2/3", "1/3")] + public void between_fractions(Fraction fraction, Fraction divider, Fraction remainder) + => (fraction % divider).Should().Be(remainder); + + [Test] + public void between_fractions([RandomFraction(3)] Fraction fraction, [RandomFraction(3, false)] Fraction divider) + { + var modulo = ((decimal)fraction) % ((decimal)divider); + (fraction % divider).Should().Be(modulo.Fraction()); + } + + [Test] + public void between_fractions_and_longs() + => (1.DividedBy(3) % 4L).Should().Be(1.DividedBy(3)); + + [Test] + public void between_fractions_and_ints() + => (1.DividedBy(3) % 4).Should().Be(1.DividedBy(3)); + + [Test] + public void between_longs_and_fractions() + => (4L % 3.DividedBy(1)).Should().Be(1.DividedBy(1)); + + [Test] + public void between_ints_and_fractions() + => (4 % 3.DividedBy(1)).Should().Be(1.DividedBy(1)); + } + + [TestCase("0", "0")] + [TestCase("17/3", "17/3")] + [TestCase("-7/3", "+7/3")] + public void abs(Fraction fraction, Fraction absolute) + => fraction.Abs().Should().Be(absolute); + + [TestCase("+1/4", "4/1")] + [TestCase("-2/3", "-3/2")] + public void inverse(Fraction faction, Fraction inverse) + => faction.Inverse().Should().Be(inverse); + + [TestCase("0", 0)] + [TestCase("-1/4", -1)] + [TestCase("+1/4", +1)] + public void sign(Fraction fraction, int sign) + => fraction.Sign().Should().Be(sign); + + [TestCase("-69/17", 1)] + [TestCase("+69/17", 1)] + [TestCase("0", 0)] + public void remainder_as_positive_value(Fraction fraction, int remainder) + => fraction.Remainder.Should().Be(remainder); + + [TestCase("-69/17", -4)] + [TestCase("+69/17", +4)] + [TestCase("0", 0)] + public void whole(Fraction fraction, int remainder) + => fraction.Whole.Should().Be(remainder); } public class Has_constant { - [Test] - public void Zero_represent_0_divided_by_1() - => Fraction.Zero.Should().BeEquivalentTo(new - { - Numerator = 0L, - Denominator = 1L, - }); - - [Test] - public void Zero_equal_to_default() - => Fraction.Zero.Should().Be(default); - - [Test] - public void One_represent_0_divided_by_1() - => Fraction.One.Should().BeEquivalentTo(new - { - Numerator = 1L, - Denominator = 1L, - }); - - [Test] - public void Epsilon_represent_0_divided_by_1() - => Fraction.Epsilon.Should().BeEquivalentTo(new - { - Numerator = 1L, - Denominator = long.MaxValue, - }); - - [Test] - public void MinValue_represent_0_divided_by_1() - => Fraction.MinValue.Should().BeEquivalentTo(new - { - Numerator = -long.MaxValue, - Denominator = 1L, - }); - - [Test] - public void MaxValue_represent_0_divided_by_1() - => Fraction.MaxValue.Should().BeEquivalentTo(new - { - Numerator = long.MaxValue, - Denominator = 1L, - }); + [Test] + public void Zero_represent_0_divided_by_1() + => Fraction.Zero.Should().BeEquivalentTo(new + { + Numerator = 0L, + Denominator = 1L, + }); + + [Test] + public void Zero_equal_to_default() + => Fraction.Zero.Should().Be(default); + + [Test] + public void One_represent_0_divided_by_1() + => Fraction.One.Should().BeEquivalentTo(new + { + Numerator = 1L, + Denominator = 1L, + }); + + [Test] + public void Epsilon_represent_0_divided_by_1() + => Fraction.Epsilon.Should().BeEquivalentTo(new + { + Numerator = 1L, + Denominator = long.MaxValue, + }); + + [Test] + public void MinValue_represent_0_divided_by_1() + => Fraction.MinValue.Should().BeEquivalentTo(new + { + Numerator = -long.MaxValue, + Denominator = 1L, + }); + + [Test] + public void MaxValue_represent_0_divided_by_1() + => Fraction.MaxValue.Should().BeEquivalentTo(new + { + Numerator = long.MaxValue, + Denominator = 1L, + }); } public class Prevents_overflow { - [Test] - public void on_additions() - { - var l = 1.DividedBy(4_000_000_000L); - var r = 1.DividedBy(8_000_000_000L); - (l + r).Should().Be(3.DividedBy(8_000_000_000L)); - } - - [Test] - public void on_multiplications() - { - var l = 1.DividedBy(4_000_000_000L); - var r = 8_000_000_000L.DividedBy(3); - (l * r).Should().Be(2.DividedBy(3)); - } + [Test] + public void on_additions() + { + var l = 1.DividedBy(4_000_000_000L); + var r = 1.DividedBy(8_000_000_000L); + (l + r).Should().Be(3.DividedBy(8_000_000_000L)); + } + + [Test] + public void on_multiplications() + { + var l = 1.DividedBy(4_000_000_000L); + var r = 8_000_000_000L.DividedBy(3); + (l * r).Should().Be(2.DividedBy(3)); + } } public class Does_not_define { - [Test] - public void inverse_on_zero() - => Fraction.Zero.Invoking(f => f.Inverse()).Should().Throw(); + [Test] + public void inverse_on_zero() + => Fraction.Zero.Invoking(f => f.Inverse()).Should().Throw(); } public class Throws_when { - [Test] - public void multiplication_can_not_be_represented_by_a_long() - { - var x = (long.MaxValue - 3).DividedBy(1); - var y = (long.MaxValue - 4).DividedBy(1); - - x.Invoking(_ => x * y) - .Should().Throw() - .WithMessage("Arithmetic operation resulted in an overflow.*"); - } - - [Test] - public void division_can_not_be_represented_by_a_long() - { - var x = (long.MaxValue - 3).DividedBy(1); - var y = (long.MaxValue - 4).DividedBy(long.MaxValue - 7); - - x.Invoking(_ => x / y) - .Should().Throw() - .WithMessage("Arithmetic operation resulted in an overflow.*"); - } - - [Test] - public void addition_can_not_be_represented_by_a_long() - { - var x = 17.DividedBy(long.MaxValue - 3); - var y = 13.DividedBy(long.MaxValue - 4); - - x.Invoking(_ => x + y) - .Should().Throw() - .WithMessage("Arithmetic operation resulted in an overflow.*"); - } - - [Test] - public void subtraction_can_not_be_represented_by_a_long() - { - var x = 17.DividedBy(long.MaxValue - 3); - var y = 13.DividedBy(long.MaxValue - 4); - - x.Invoking(_ => x - y) - .Should().Throw() - .WithMessage("Arithmetic operation resulted in an overflow.*"); - } - - [TestCase(-19223372036854775809.0)] - [TestCase(+19223372036854775809.0)] - public void double_can_not_be_casted_to_fraction(double dbl) - => dbl.Invoking(d => (Fraction)d).Should().Throw() - .WithMessage("Value was either too large or too small for a Fraction."); - - [TestCase(-9223372036854775808.0)] - [TestCase(+9223372036854775808.0)] - public void decimal_can_not_be_casted_to_fraction(decimal dec) - => dec.Invoking(d => (Fraction)d).Should().Throw() - .WithMessage("Value was either too large or too small for a Fraction."); - - [TestCase(-9223372036854775808.0)] - [TestCase(+9223372036854775808.0)] - public void fraction_can_no_be_created_form_double(double dbl) - => dbl.Invoking(Fraction.Create).Should().Throw() - .WithMessage("Value was either too large or too small for a Fraction. *"); - - [TestCase(-9223372036854775808.0)] - [TestCase(+9223372036854775808.0)] - public void fraction_can_no_be_created_form_decimal(decimal dec) - => dec.Invoking(Fraction.Create).Should().Throw() - .WithMessage("Value was either too large or too small for a Fraction. *"); - - [Test] - public void invalid_input_is_parsed() - => "NaN".Invoking(Fraction.Parse) - .Should().Throw() - .WithMessage("Not a valid fraction"); + [Test] + public void multiplication_can_not_be_represented_by_a_long() + { + var x = (long.MaxValue - 3).DividedBy(1); + var y = (long.MaxValue - 4).DividedBy(1); + + x.Invoking(_ => x * y) + .Should().Throw() + .WithMessage("Arithmetic operation resulted in an overflow.*"); + } + + [Test] + public void division_can_not_be_represented_by_a_long() + { + var x = (long.MaxValue - 3).DividedBy(1); + var y = (long.MaxValue - 4).DividedBy(long.MaxValue - 7); + + x.Invoking(_ => x / y) + .Should().Throw() + .WithMessage("Arithmetic operation resulted in an overflow.*"); + } + + [Test] + public void addition_can_not_be_represented_by_a_long() + { + var x = 17.DividedBy(long.MaxValue - 3); + var y = 13.DividedBy(long.MaxValue - 4); + + x.Invoking(_ => x + y) + .Should().Throw() + .WithMessage("Arithmetic operation resulted in an overflow.*"); + } + + [Test] + public void subtraction_can_not_be_represented_by_a_long() + { + var x = 17.DividedBy(long.MaxValue - 3); + var y = 13.DividedBy(long.MaxValue - 4); + + x.Invoking(_ => x - y) + .Should().Throw() + .WithMessage("Arithmetic operation resulted in an overflow.*"); + } + + [TestCase(-19223372036854775809.0)] + [TestCase(+19223372036854775809.0)] + public void double_can_not_be_casted_to_fraction(double dbl) + => dbl.Invoking(d => (Fraction)d).Should().Throw() + .WithMessage("Value was either too large or too small for a Fraction."); + + [TestCase(-9223372036854775808.0)] + [TestCase(+9223372036854775808.0)] + public void decimal_can_not_be_casted_to_fraction(decimal dec) + => dec.Invoking(d => (Fraction)d).Should().Throw() + .WithMessage("Value was either too large or too small for a Fraction."); + + [TestCase(-9223372036854775808.0)] + [TestCase(+9223372036854775808.0)] + public void fraction_can_no_be_created_form_double(double dbl) + => dbl.Invoking(Fraction.Create).Should().Throw() + .WithMessage("Value was either too large or too small for a Fraction. *"); + + [TestCase(-9223372036854775808.0)] + [TestCase(+9223372036854775808.0)] + public void fraction_can_no_be_created_form_decimal(decimal dec) + => dec.Invoking(Fraction.Create).Should().Throw() + .WithMessage("Value was either too large or too small for a Fraction. *"); + + [Test] + public void invalid_input_is_parsed() + => "NaN".Invoking(Fraction.Parse) + .Should().Throw() + .WithMessage("Not a valid fraction"); } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - => Svo.Fraction.Equals(null).Should().BeFalse(); - - [Test] - public void not_equal_to_other_type() - => Svo.Fraction.Equals(new object()).Should().BeFalse(); - - [Test] - public void not_equal_to_different_value() - => Svo.Fraction.Equals(17.DividedBy(42)).Should().BeFalse(); - - [Test] - public void equal_to_same_value() - => Svo.Fraction.Equals(-69.DividedBy(17)).Should().BeTrue(); - - [Test] - public void equal_operator_returns_true_for_same_values() - => (Svo.Fraction == -69.DividedBy(17)).Should().BeTrue(); - - [Test] - public void equal_operator_returns_false_for_different_values() - => (Svo.Fraction == 17.DividedBy(42)).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_false_for_same_values() - => (Svo.Fraction != -69.DividedBy(17)).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_true_for_different_values() - => (Svo.Fraction != 17.DividedBy(42)).Should().BeTrue(); - - [TestCase(0, 0)] - [TestCase("17/42", 490960136)] - public void hash_code_is_value_based(Fraction svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + => Svo.Fraction.Equals(null).Should().BeFalse(); + + [Test] + public void not_equal_to_other_type() + => Svo.Fraction.Equals(new object()).Should().BeFalse(); + + [Test] + public void not_equal_to_different_value() + => Svo.Fraction.Equals(17.DividedBy(42)).Should().BeFalse(); + + [Test] + public void equal_to_same_value() + => Svo.Fraction.Equals(-69.DividedBy(17)).Should().BeTrue(); + + [Test] + public void equal_operator_returns_true_for_same_values() + => (Svo.Fraction == -69.DividedBy(17)).Should().BeTrue(); + + [Test] + public void equal_operator_returns_false_for_different_values() + => (Svo.Fraction == 17.DividedBy(42)).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_false_for_same_values() + => (Svo.Fraction != -69.DividedBy(17)).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_true_for_different_values() + => (Svo.Fraction != 17.DividedBy(42)).Should().BeTrue(); + + [TestCase(0, 0)] + [TestCase("17/42", 490960136)] + public void hash_code_is_value_based(Fraction svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [TestCase(17, 1, "17")] - [TestCase(17, 1, "+17")] - [TestCase(-12, 1, "-12")] - public void from_integer(long numerator, long denominator, string num) - => Fraction.Parse(num, CultureInfo.InvariantCulture).Should().Be(numerator.DividedBy(denominator)); - - [TestCase(12_345, 1, "12,345")] - [TestCase(-1, 4, "-0.25")] - public void from_decimal(long numerator, long denominator, string dec) - => Fraction.Parse(dec, CultureInfo.InvariantCulture).Should().Be(numerator.DividedBy(denominator)); - - [TestCase(487, 1000, "48.70%")] - [TestCase(487, 1000, "487.0‰")] - public void from_percentage(long numerator, long denominator, string percentage) - => Fraction.Parse(percentage, CultureInfo.InvariantCulture).Should().Be(numerator.DividedBy(denominator)); - - [TestCase(+1, 2, "½")] - [TestCase(-1, 2, "-½")] - [TestCase(+3, 4, "¾")] - [TestCase(11, 4, "2¾")] - [TestCase(11, 4, "2 ¾")] - public void from_vulgar(long numerator, long denominator, string vulgar) - => Fraction.Parse(vulgar).Should().Be(numerator.DividedBy(denominator)); - - [TestCase(9, 7, "1²/₇")] - [TestCase(3, 7, "³/7")] - [TestCase(9, 7, "1 ²/7")] - [TestCase(23, 47, "²³/₄₇")] - public void from_super_script_numerator(long numerator, long denominator, string superScript) - => Fraction.Parse(superScript).Should().Be(numerator.DividedBy(denominator)); - - [TestCase(-2, 7, "-²/₇")] - [TestCase(+9, 7, "1 2/₇")] - [TestCase(+3, 7, "3/₇")] - [TestCase(23, 47, "23/₄₇")] - public void from_sub_script_denominator(long numerator, long denominator, string subScript) - => Fraction.Parse(subScript).Should().Be(numerator.DividedBy(denominator)); - - [TestCase(1, 3, "+1/3")] - [TestCase(-1, 3, "-1/3")] - [TestCase(11, 43, "11/43")] - [TestCase(4, 3, "1 1/3")] - [TestCase(21, 2, "10 1/2")] - public void from_fraction_strings(long numerator, long denominator, string str) - => Fraction.Parse(str, CultureInfo.InvariantCulture).Should().Be(numerator.DividedBy(denominator)); - - [TestCase("1/3")] - [TestCase("1:3")] - [TestCase("1÷3")] - [TestCase("1⁄3")] - [TestCase("1⁄3")] - [TestCase("1⁄3")] - [TestCase("1∕3")] - public void from_multiple_bar_chars(string bar) - => Fraction.Parse(bar, CultureInfo.InvariantCulture).Should().Be(1.DividedBy(3)); - - [Test] - public void without_specifying_format_provider() - { - Fraction.TryParse("-69/17", out var fraction).Should().BeTrue(); - fraction.Should().Be(Svo.Fraction); - } - - [Test] - public void using_pure_try_parse() => Fraction.TryParse("-69/17").Should().Be(Svo.Fraction); + [TestCase(17, 1, "17")] + [TestCase(17, 1, "+17")] + [TestCase(-12, 1, "-12")] + public void from_integer(long numerator, long denominator, string num) + => Fraction.Parse(num, CultureInfo.InvariantCulture).Should().Be(numerator.DividedBy(denominator)); + + [TestCase(12_345, 1, "12,345")] + [TestCase(-1, 4, "-0.25")] + public void from_decimal(long numerator, long denominator, string dec) + => Fraction.Parse(dec, CultureInfo.InvariantCulture).Should().Be(numerator.DividedBy(denominator)); + + [TestCase(487, 1000, "48.70%")] + [TestCase(487, 1000, "487.0‰")] + public void from_percentage(long numerator, long denominator, string percentage) + => Fraction.Parse(percentage, CultureInfo.InvariantCulture).Should().Be(numerator.DividedBy(denominator)); + + [TestCase(+1, 2, "½")] + [TestCase(-1, 2, "-½")] + [TestCase(+3, 4, "¾")] + [TestCase(11, 4, "2¾")] + [TestCase(11, 4, "2 ¾")] + public void from_vulgar(long numerator, long denominator, string vulgar) + => Fraction.Parse(vulgar).Should().Be(numerator.DividedBy(denominator)); + + [TestCase(9, 7, "1²/₇")] + [TestCase(3, 7, "³/7")] + [TestCase(9, 7, "1 ²/7")] + [TestCase(23, 47, "²³/₄₇")] + public void from_super_script_numerator(long numerator, long denominator, string superScript) + => Fraction.Parse(superScript).Should().Be(numerator.DividedBy(denominator)); + + [TestCase(-2, 7, "-²/₇")] + [TestCase(+9, 7, "1 2/₇")] + [TestCase(+3, 7, "3/₇")] + [TestCase(23, 47, "23/₄₇")] + public void from_sub_script_denominator(long numerator, long denominator, string subScript) + => Fraction.Parse(subScript).Should().Be(numerator.DividedBy(denominator)); + + [TestCase(1, 3, "+1/3")] + [TestCase(-1, 3, "-1/3")] + [TestCase(11, 43, "11/43")] + [TestCase(4, 3, "1 1/3")] + [TestCase(21, 2, "10 1/2")] + public void from_fraction_strings(long numerator, long denominator, string str) + => Fraction.Parse(str, CultureInfo.InvariantCulture).Should().Be(numerator.DividedBy(denominator)); + + [TestCase("1/3")] + [TestCase("1:3")] + [TestCase("1÷3")] + [TestCase("1⁄3")] + [TestCase("1⁄3")] + [TestCase("1⁄3")] + [TestCase("1∕3")] + public void from_multiple_bar_chars(string bar) + => Fraction.Parse(bar, CultureInfo.InvariantCulture).Should().Be(1.DividedBy(3)); + + [Test] + public void without_specifying_format_provider() + { + Fraction.TryParse("-69/17", out var fraction).Should().BeTrue(); + fraction.Should().Be(Svo.Fraction); + } + + [Test] + public void using_pure_try_parse() => Fraction.TryParse("-69/17").Should().Be(Svo.Fraction); } public class Can_not_be_parsed { - [Test] - public void string_empty() => Fraction.TryParse(string.Empty).Should().BeNull(); - - [Test] - public void @null() => Fraction.TryParse(null).Should().BeNull(); - - [TestCase("--3/7")] - [TestCase("-+3/7")] - [TestCase("+-3/7")] - [TestCase("++3/7")] - public void multiple_signs(string multiple) => Fraction.TryParse(multiple).Should().BeNull(); - - [TestCase("3/+7")] - public void plus_sign_denominator(string denominator) => Fraction.TryParse(denominator).Should().BeNull(); - - [TestCase("3/0")] - [TestCase("²/₀")] - public void zero_denominator(string divideByZero) => Fraction.TryParse(divideByZero).Should().BeNull(); - - [TestCase("NaN", "NaN")] - [TestCase("-Infinity", "-Infinity")] - [TestCase("+Infinity", "+Infinity")] - [TestCase("0xFF", "Hexa-decimal")] - [TestCase("15/", "Ends with an operator")] - [TestCase("1//4", "Two division operators")] - [TestCase("1/½", "Vulgar with division operator")] - [TestCase("½1", "Vulgar not at the end")] - [TestCase("²3/₇", "Normal and superscript mixed")] - [TestCase("²/₇3", "Normal and subscript mixed")] - [TestCase("²/3₇", "Normal and subscript mixed")] - [TestCase("₇/3", "Subscript first")] - [TestCase("92233720368547758 17/32464364", "Numerator overflow")] - [TestCase("9223372036854775808", "Long.MaxValue + 1")] - [TestCase("-9223372036854775808", "Long.MinValue")] - [TestCase("-9223372036854775809", "Long.MinValue - 1")] - public void non_fractional_strings(string str, string because) - => Fraction.TryParse(str).Should().BeNull(because); - - [Test] - public void retrieving_null_for_invalid_input() => Fraction.TryParse("invalid").Should().BeNull(); + [Test] + public void string_empty() => Fraction.TryParse(string.Empty).Should().BeNull(); + + [Test] + public void @null() => Fraction.TryParse(null).Should().BeNull(); + + [TestCase("--3/7")] + [TestCase("-+3/7")] + [TestCase("+-3/7")] + [TestCase("++3/7")] + public void multiple_signs(string multiple) => Fraction.TryParse(multiple).Should().BeNull(); + + [TestCase("3/+7")] + public void plus_sign_denominator(string denominator) => Fraction.TryParse(denominator).Should().BeNull(); + + [TestCase("3/0")] + [TestCase("²/₀")] + public void zero_denominator(string divideByZero) => Fraction.TryParse(divideByZero).Should().BeNull(); + + [TestCase("NaN", "NaN")] + [TestCase("-Infinity", "-Infinity")] + [TestCase("+Infinity", "+Infinity")] + [TestCase("0xFF", "Hexa-decimal")] + [TestCase("15/", "Ends with an operator")] + [TestCase("1//4", "Two division operators")] + [TestCase("1/½", "Vulgar with division operator")] + [TestCase("½1", "Vulgar not at the end")] + [TestCase("²3/₇", "Normal and superscript mixed")] + [TestCase("²/₇3", "Normal and subscript mixed")] + [TestCase("²/3₇", "Normal and subscript mixed")] + [TestCase("₇/3", "Subscript first")] + [TestCase("92233720368547758 17/32464364", "Numerator overflow")] + [TestCase("9223372036854775808", "Long.MaxValue + 1")] + [TestCase("-9223372036854775808", "Long.MinValue")] + [TestCase("-9223372036854775809", "Long.MinValue - 1")] + public void non_fractional_strings(string str, string because) + => Fraction.TryParse(str).Should().BeNull(because); + + [Test] + public void retrieving_null_for_invalid_input() => Fraction.TryParse("invalid").Should().BeNull(); } public class Can_be_created { - [TestCase("0/1", 0, 8, "Should set zero")] - [TestCase("1/4", 2, 8, "Should reduce")] - [TestCase("-1/4", -2, 8, "Should reduce")] - [TestCase("1/4", 3, 12, "Should reduce")] - [TestCase("-1/4", -3, 12, "Should reduce")] - [TestCase("3/7", -3, -7, "Should have no signs")] - [TestCase("-3/7", 3, -7, "Should have no sign on denominator")] - [TestCase("-3/7", -3, 7, "Should have no sign on denominator")] - public void with_constructor(Fraction fraction, long numerator, long denominator, string because) - => new Fraction(numerator, denominator).Should().Be(fraction, because); - - [TestCase(0, 1, "0")] - [TestCase(00000003, 000000010, "0.3")] - [TestCase(00000033, 000000100, "0.33")] - [TestCase(00000333, 000001000, "0.333")] - [TestCase(00003333, 000010000, "0.3333")] - [TestCase(00033333, 000100000, "0.33333")] - [TestCase(00333333, 001000000, "0.333333")] - [TestCase(03333333, 010000000, "0.3333333")] - [TestCase(33333333, 100000000, "0.33333333")] - [TestCase(333333333, 1000000000, "0.333333333")] - [TestCase(1, 3, "0.33333333333333333333333")] - public void from_decimals(long numerator, long denominator, decimal number) - => Fraction.Create(number).Should().Be(numerator.DividedBy(denominator)); - - [TestCase(0, 1, 0.5, 0.6)] - [TestCase(1, 1, 0.6, 0.5)] - public void from_decimals_with_error(long numerator, long denominator, decimal number, decimal error) - => Fraction.Create(number, error).Should().Be(numerator.DividedBy(denominator)); - - [TestCase(100)] - public void from_decimals_without_precision_loss(int runs) - { - var rnd = new Random(); - var failures = new List(runs); - - foreach (var fraction in Enumerable.Range(0, runs).Select(i => rnd.Next(int.MinValue, int.MaxValue).DividedBy(rnd.Next(3, int.MaxValue)))) - { - var created = Fraction.Create((decimal)fraction); - if (created != fraction) - { - failures.Add(fraction); - } - } - failures.Should().BeEmpty(); - } - - [Test] - public void applying_greatest_common_divisor() - => 60.DividedBy(420).Should().BeEquivalentTo(new - { - Numerator = 1L, - Denominator = 7L, - }); + [TestCase("0/1", 0, 8, "Should set zero")] + [TestCase("1/4", 2, 8, "Should reduce")] + [TestCase("-1/4", -2, 8, "Should reduce")] + [TestCase("1/4", 3, 12, "Should reduce")] + [TestCase("-1/4", -3, 12, "Should reduce")] + [TestCase("3/7", -3, -7, "Should have no signs")] + [TestCase("-3/7", 3, -7, "Should have no sign on denominator")] + [TestCase("-3/7", -3, 7, "Should have no sign on denominator")] + public void with_constructor(Fraction fraction, long numerator, long denominator, string because) + => new Fraction(numerator, denominator).Should().Be(fraction, because); + + [TestCase(0, 1, "0")] + [TestCase(00000003, 000000010, "0.3")] + [TestCase(00000033, 000000100, "0.33")] + [TestCase(00000333, 000001000, "0.333")] + [TestCase(00003333, 000010000, "0.3333")] + [TestCase(00033333, 000100000, "0.33333")] + [TestCase(00333333, 001000000, "0.333333")] + [TestCase(03333333, 010000000, "0.3333333")] + [TestCase(33333333, 100000000, "0.33333333")] + [TestCase(333333333, 1000000000, "0.333333333")] + [TestCase(1, 3, "0.33333333333333333333333")] + public void from_decimals(long numerator, long denominator, decimal number) + => Fraction.Create(number).Should().Be(numerator.DividedBy(denominator)); + + [TestCase(0, 1, 0.5, 0.6)] + [TestCase(1, 1, 0.6, 0.5)] + public void from_decimals_with_error(long numerator, long denominator, decimal number, decimal error) + => Fraction.Create(number, error).Should().Be(numerator.DividedBy(denominator)); + + [TestCase(100)] + public void from_decimals_without_precision_loss(int runs) + { + var rnd = new Random(); + var failures = new List(runs); + + foreach (var fraction in Enumerable.Range(0, runs).Select(i => rnd.Next(int.MinValue, int.MaxValue).DividedBy(rnd.Next(3, int.MaxValue)))) + { + var created = Fraction.Create((decimal)fraction); + if (created != fraction) + { + failures.Add(fraction); + } + } + failures.Should().BeEmpty(); + } + + [Test] + public void applying_greatest_common_divisor() + => 60.DividedBy(420).Should().BeEquivalentTo(new + { + Numerator = 1L, + Denominator = 7L, + }); } public class Can_not_be_created { - [TestCase(-10e18)] - [TestCase(+10e18)] - public void from_decimal_out_of_long_range(decimal dec) - { - Func create = () => Fraction.Create(dec); - create.Should().Throw(); - } - - [TestCase(1e-19)] - [TestCase(+1.000001)] - public void from_decimal_with_error_out_of_range(decimal error) - { - Func create = () => Fraction.Create(0, error); - create.Should().Throw(); - } + [TestCase(-10e18)] + [TestCase(+10e18)] + public void from_decimal_out_of_long_range(decimal dec) + { + Func create = () => Fraction.Create(dec); + create.Should().Throw(); + } + + [TestCase(1e-19)] + [TestCase(+1.000001)] + public void from_decimal_with_error_out_of_range(decimal error) + { + Func create = () => Fraction.Create(0, error); + create.Should().Throw(); + } } public class Can_be_casted_explicit { - [TestCase(0, 0)] - [TestCase("-69/17", -69 / 17)] - public void to_Int32(Fraction fraction, int casted) => ((int)fraction).Should().Be(casted); + [TestCase(0, 0)] + [TestCase("-69/17", -69 / 17)] + public void to_Int32(Fraction fraction, int casted) => ((int)fraction).Should().Be(casted); - [TestCase(0, 0)] - [TestCase("-69/17", -69 / 17)] - public void to_Int64(Fraction fraction, long casted) => ((long)fraction).Should().Be(casted); + [TestCase(0, 0)] + [TestCase("-69/17", -69 / 17)] + public void to_Int64(Fraction fraction, long casted) => ((long)fraction).Should().Be(casted); - [TestCase(0, 0)] - [TestCase("-69/17", -69.0 / 17.0)] - public void to_double(Fraction fraction, double casted) => ((double)fraction).Should().Be(casted); + [TestCase(0, 0)] + [TestCase("-69/17", -69.0 / 17.0)] + public void to_double(Fraction fraction, double casted) => ((double)fraction).Should().Be(casted); - [TestCase(0, 0)] - [TestCase(-84, -84)] - public void to_decimal(Fraction fraction, decimal casted) => ((decimal)fraction).Should().Be(casted); + [TestCase(0, 0)] + [TestCase(-84, -84)] + public void to_decimal(Fraction fraction, decimal casted) => ((decimal)fraction).Should().Be(casted); - [Test] - public void to_percent() => ((Percentage)1.DividedBy(4)).Should().Be(25.Percent()); + [Test] + public void to_percent() => ((Percentage)1.DividedBy(4)).Should().Be(25.Percent()); - [Test] - public void from_Int32() => ((Fraction)42).Should().Be(42.DividedBy(1)); + [Test] + public void from_Int32() => ((Fraction)42).Should().Be(42.DividedBy(1)); - [Test] - public void from_Int64() => ((Fraction)42L).Should().Be(42.DividedBy(1)); + [Test] + public void from_Int64() => ((Fraction)42L).Should().Be(42.DividedBy(1)); - [Test] - public void from_double() => ((Fraction)(-1.0/16.0)).Should().Be(-1.DividedBy(16)); + [Test] + public void from_double() => ((Fraction)(-1.0 / 16.0)).Should().Be(-1.DividedBy(16)); - [Test] - public void from_decimal() => ((Fraction)(-69m / 17m)).Should().Be(Svo.Fraction); + [Test] + public void from_decimal() => ((Fraction)(-69m / 17m)).Should().Be(Svo.Fraction); - [Test] - public void from_percent() => ((Fraction)25.Percent()).Should().Be(1.DividedBy(4)); + [Test] + public void from_percent() => ((Fraction)25.Percent()).Should().Be(1.DividedBy(4)); } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.Fraction.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_Fraction_as_object() - { - object obj = Svo.Fraction; - Svo.Fraction.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Fraction_only() - => Assert.Throws(() => Svo.Fraction.CompareTo(new object())); - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - (-1).DividedBy(12), - Fraction.Zero, - 1.DividedBy(42), - 1.DividedBy(17), - 1.DividedBy(11), - 201.DividedBy(42), - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } - - [Test] - public void by_operators_for_different_values() - { - var smaller = 1.DividedBy(17); - var bigger = 2.DividedBy(3); - - (smaller < bigger).Should().BeTrue(); - (smaller <= bigger).Should().BeTrue(); - (smaller > bigger).Should().BeFalse(); - (smaller >= bigger).Should().BeFalse(); - } - - [Test] - public void by_operators_for_equal_values() - { - var left = 1.DividedBy(17); - var right = 1.DividedBy(17); - - (left < right).Should().BeFalse(); - (left <= right).Should().BeTrue(); - (left > right).Should().BeFalse(); - (left >= right).Should().BeTrue(); - } + [Test] + public void to_null_is_1() => Svo.Fraction.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_Fraction_as_object() + { + object obj = Svo.Fraction; + Svo.Fraction.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Fraction_only() + => new object().Invoking(Svo.Fraction.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + (-1).DividedBy(12), + Fraction.Zero, + 1.DividedBy(42), + 1.DividedBy(17), + 1.DividedBy(11), + 201.DividedBy(42), + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } + + [Test] + public void by_operators_for_different_values() + { + var smaller = 1.DividedBy(17); + var bigger = 2.DividedBy(3); + + (smaller < bigger).Should().BeTrue(); + (smaller <= bigger).Should().BeTrue(); + (smaller > bigger).Should().BeFalse(); + (smaller >= bigger).Should().BeFalse(); + } + + [Test] + public void by_operators_for_equal_values() + { + var left = 1.DividedBy(17); + var right = 1.DividedBy(17); + + (left < right).Should().BeFalse(); + (left <= right).Should().BeTrue(); + (left > right).Should().BeFalse(); + (left >= right).Should().BeTrue(); + } } public class Has_custom_formatting { - [Test] - public void _default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Fraction.ToString().Should().Be("-69/17"); - } - } - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Fraction.ToString().Should().Be(Svo.Fraction.ToString(default(string))); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Fraction.ToString().Should().Be(Svo.Fraction.ToString(string.Empty)); - } - } - - [Test] - public void default_value_is_represented_as_zero() - => default(Fraction).ToString().Should().Be("0/1"); - - [Test] - public void with_empty_format_provider() - { - using (TestCultures.es_EC.Scoped()) - { - Svo.Fraction.ToString(FormatProvider.Empty).Should().Be("-69/17"); - } - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.Fraction.ToString("[0]super⁄sub", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: '-4¹⁄₁₇', format: '[0]super⁄sub'"); - } - - [TestCase(null, /*............*/ "-2/7", "-2/7")] - [TestCase("", /*..............*/ "-2/7", "-2/7")] - [TestCase("0:0", /*...........*/ "-2:7", "-2/7")] - [TestCase("0÷0", /*...........*/ "4÷3", "4/3")] - [TestCase("[0]0/0", /*........*/ "1 1/3", "4/3")] - [TestCase("[0]0/0", /*........*/ "-1 1/3", "-4/3")] - [TestCase("[0 ]0/0",/*........*/ "-1 1/3", "-4/3")] - [TestCase("#.00", /*..........*/ ".33", "1/3")] - [TestCase("[0]super⁄sub", /*..*/ "5¹¹⁄₁₂", "71/12")] - [TestCase("[0]super⁄0", /*....*/ "5¹¹⁄12", "71/12")] - [TestCase("[0] 0⁄sub", /*.....*/ "5 11⁄₁₂", "71/12")] - [TestCase("[0]super⁄sub", /*..*/ "-3¹⁄₂", "-7/2")] - [TestCase("[0 ]super⁄sub", /*.*/ "-3 ¹⁄₂", "-7/2")] - [TestCase("[#]super⁄sub", /*..*/ "-¹⁄₂", "-1/2")] - [TestCase("[0]super⁄sub", /*..*/ "-0¹⁄₂", "-1/2")] - [TestCase("super⁄sub", /*.....*/ "⁷¹⁄₁₂", "71/12")] - [TestCase("super⁄sub", /*.....*/ "-⁷⁄₂", "-7/2")] - public void for_format(string format, string formatted, Fraction fraction) - => fraction.ToString(format, CultureInfo.InvariantCulture).Should().Be(formatted); - - [Test] - public void that_throws_for_invalid_formats() - => "/invalid".Invoking(Svo.Fraction.ToString).Should().Throw(); + [Test] + public void _default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Fraction.ToString().Should().Be("-69/17"); + } + } + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Fraction.ToString().Should().Be(Svo.Fraction.ToString(default(string))); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Fraction.ToString().Should().Be(Svo.Fraction.ToString(string.Empty)); + } + } + + [Test] + public void default_value_is_represented_as_zero() + => default(Fraction).ToString().Should().Be("0/1"); + + [Test] + public void with_empty_format_provider() + { + using (TestCultures.es_EC.Scoped()) + { + Svo.Fraction.ToString(FormatProvider.Empty).Should().Be("-69/17"); + } + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.Fraction.ToString("[0]super⁄sub", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: '-4¹⁄₁₇', format: '[0]super⁄sub'"); + } + + [TestCase(null, /*............*/ "-2/7", "-2/7")] + [TestCase("", /*..............*/ "-2/7", "-2/7")] + [TestCase("0:0", /*...........*/ "-2:7", "-2/7")] + [TestCase("0÷0", /*...........*/ "4÷3", "4/3")] + [TestCase("[0]0/0", /*........*/ "1 1/3", "4/3")] + [TestCase("[0]0/0", /*........*/ "-1 1/3", "-4/3")] + [TestCase("[0 ]0/0",/*........*/ "-1 1/3", "-4/3")] + [TestCase("#.00", /*..........*/ ".33", "1/3")] + [TestCase("[0]super⁄sub", /*..*/ "5¹¹⁄₁₂", "71/12")] + [TestCase("[0]super⁄0", /*....*/ "5¹¹⁄12", "71/12")] + [TestCase("[0] 0⁄sub", /*.....*/ "5 11⁄₁₂", "71/12")] + [TestCase("[0]super⁄sub", /*..*/ "-3¹⁄₂", "-7/2")] + [TestCase("[0 ]super⁄sub", /*.*/ "-3 ¹⁄₂", "-7/2")] + [TestCase("[#]super⁄sub", /*..*/ "-¹⁄₂", "-1/2")] + [TestCase("[0]super⁄sub", /*..*/ "-0¹⁄₂", "-1/2")] + [TestCase("super⁄sub", /*.....*/ "⁷¹⁄₁₂", "71/12")] + [TestCase("super⁄sub", /*.....*/ "-⁷⁄₂", "-7/2")] + public void for_format(string format, string formatted, Fraction fraction) + => fraction.ToString(format, CultureInfo.InvariantCulture).Should().Be(formatted); + + [Test] + public void that_throws_for_invalid_formats() + => "/invalid".Invoking(Svo.Fraction.ToString).Should().Throw(); } public class Has_humanizer_creators { - [Test] - public void int_DividedBy_int() - => 12.DividedBy(24).Should().Be(new Fraction(1, 2)); + [Test] + public void int_DividedBy_int() + => 12.DividedBy(24).Should().Be(new Fraction(1, 2)); - [Test] - public void long_DividedBy_long() - => 12L.DividedBy(24L).Should().Be(new Fraction(1, 2)); + [Test] + public void long_DividedBy_long() + => 12L.DividedBy(24L).Should().Be(new Fraction(1, 2)); - [Test] - public void Fraction_from_double() - => 0.5.Fraction().Should().Be(new Fraction(1, 2)); + [Test] + public void Fraction_from_double() + => 0.5.Fraction().Should().Be(new Fraction(1, 2)); - [Test] - public void Fraction_from_decimal() - => 0.5m.Fraction().Should().Be(new Fraction(1, 2)); + [Test] + public void Fraction_from_decimal() + => 0.5m.Fraction().Should().Be(new Fraction(1, 2)); } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(Fraction).Should().HaveTypeConverterDefined(); - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("-69/17").To().Should().Be(Svo.Fraction); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.Fraction).Should().Be("-69/17"); - } - } + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(Fraction).Should().HaveTypeConverterDefined(); + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("-69/17").To().Should().Be(Svo.Fraction); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.Fraction).Should().Be("-69/17"); + } + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase(4L, "4/1")] - [TestCase(0.25d, "1/4")] - [TestCase("13%", "13/100")] - [TestCase("14/42", "1/3")] - public void System_Text_JSON_deserialization(object json, Fraction svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase("1/3", "1/3")] - [TestCase("4/3", "4/3")] - public void System_Text_JSON_serialization(Fraction svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase(4L, "4/1")] + [TestCase(0.25d, "1/4")] + [TestCase("13%", "13/100")] + [TestCase("14/42", "1/3")] + public void System_Text_JSON_deserialization(object json, Fraction svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase("1/3", "1/3")] + [TestCase("4/3", "4/3")] + public void System_Text_JSON_serialization(Fraction svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase(4L, "4/1")] - [TestCase(3d, "3/1")] - [TestCase("13%", "13/100")] - [TestCase("14/42", "1/3")] - public void convention_based_deserialization(object json, Fraction svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase("1/3", "1/3")] - [TestCase("4/3", "4/3")] - public void convention_based_serialization(Fraction svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase(double.MaxValue, typeof(OverflowException))] - [TestCase(double.MinValue, typeof(OverflowException))] - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase(4L, "4/1")] + [TestCase(3d, "3/1")] + [TestCase("13%", "13/100")] + [TestCase("14/42", "1/3")] + public void convention_based_deserialization(object json, Fraction svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase("1/3", "1/3")] + [TestCase("4/3", "4/3")] + public void convention_based_serialization(Fraction svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase(double.MaxValue, typeof(OverflowException))] + [TestCase(double.MinValue, typeof(OverflowException))] + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Fraction); - round_tripped.Should().Be(Svo.Fraction); - } - - [Test] - public void storing_values_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Fraction); - info.GetInt64("numerator").Should().Be(-69); - info.GetInt64("denominator").Should().Be(17); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Fraction); + round_tripped.Should().Be(Svo.Fraction); + } + + [Test] + public void storing_values_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Fraction); + info.GetInt64("numerator").Should().Be(-69); + info.GetInt64("denominator").Should().Be(17); + } } #endif public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.Fraction); - xml.Should().Be("-69/17"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("-69/17"); - svo.Should().Be(Svo.Fraction); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.Fraction); - Svo.Fraction.Should().Be(round_tripped); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.Fraction); - var round_tripped = SerializeDeserialize.Xml(structure); - structure.Should().Be(round_tripped); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.Fraction; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.Fraction); + xml.Should().Be("-69/17"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("-69/17"); + svo.Should().Be(Svo.Fraction); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.Fraction); + Svo.Fraction.Should().Be(round_tripped); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.Fraction); + var round_tripped = SerializeDeserialize.Xml(structure); + structure.Should().Be(round_tripped); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.Fraction; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Fraction)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(Fraction), - description: "Faction", - type: "string", - format: "faction", - pattern: "-?[0-9]+(/[0-9]+)?", - example: "13/42")); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Fraction)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(Fraction), + description: "Faction", + type: "string", + format: "faction", + pattern: "-?[0-9]+(/[0-9]+)?", + example: "13/42")); } public class Debugger { - [TestCase("⁰⁄₁ = 0", "0")] - [TestCase("-⁴²⁄₁₇ = -2.47058824", "-42/17")] - public void has_custom_display(object display, Fraction svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("⁰⁄₁ = 0", "0")] + [TestCase("-⁴²⁄₁₇ = -2.47058824", "-42/17")] + public void has_custom_display(object display, Fraction svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Month_span_specs.cs b/specs/Qowaiv.Specs/Month_span_specs.cs index 0440e262..3be0c25f 100644 --- a/specs/Qowaiv.Specs/Month_span_specs.cs +++ b/specs/Qowaiv.Specs/Month_span_specs.cs @@ -2,271 +2,271 @@ public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - => Svo.MonthSpan.Equals(null).Should().BeFalse(); - - [Test] - public void not_equal_to_other_type() - => Svo.MonthSpan.Equals(new object()).Should().BeFalse(); - - [Test] - public void not_equal_to_different_value() - => Svo.MonthSpan.Equals(MonthSpan.MinValue).Should().BeFalse(); - - [Test] - public void equal_to_same_value() - => Svo.MonthSpan.Equals(MonthSpan.FromMonths(69)).Should().BeTrue(); - - [Test] - public void equal_operator_returns_true_for_same_values() - => (MonthSpan.FromMonths(69) == Svo.MonthSpan).Should().BeTrue(); - - [Test] - public void equal_operator_returns_false_for_different_values() - => (MonthSpan.FromMonths(69) == MonthSpan.MinValue).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_false_for_same_values() - => (MonthSpan.FromMonths(69) != Svo.MonthSpan).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_true_for_different_values() - => (MonthSpan.FromMonths(69) != MonthSpan.MinValue).Should().BeTrue(); - - [TestCase("0Y+0M", 0)] - [TestCase("5Y+9M", 665630102)] - public void hash_code_is_value_based(MonthSpan svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + => Svo.MonthSpan.Equals(null).Should().BeFalse(); + + [Test] + public void not_equal_to_other_type() + => Svo.MonthSpan.Equals(new object()).Should().BeFalse(); + + [Test] + public void not_equal_to_different_value() + => Svo.MonthSpan.Equals(MonthSpan.MinValue).Should().BeFalse(); + + [Test] + public void equal_to_same_value() + => Svo.MonthSpan.Equals(MonthSpan.FromMonths(69)).Should().BeTrue(); + + [Test] + public void equal_operator_returns_true_for_same_values() + => (MonthSpan.FromMonths(69) == Svo.MonthSpan).Should().BeTrue(); + + [Test] + public void equal_operator_returns_false_for_different_values() + => (MonthSpan.FromMonths(69) == MonthSpan.MinValue).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_false_for_same_values() + => (MonthSpan.FromMonths(69) != Svo.MonthSpan).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_true_for_different_values() + => (MonthSpan.FromMonths(69) != MonthSpan.MinValue).Should().BeTrue(); + + [TestCase("0Y+0M", 0)] + [TestCase("5Y+9M", 665630102)] + public void hash_code_is_value_based(MonthSpan svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_transformed { - [Test] - public void negate() => (-Svo.MonthSpan).Should().Be(MonthSpan.FromMonths(-69)); - - [Test] - public void increment() - { - var span = Svo.MonthSpan; - span++; - span.Should().Be(MonthSpan.FromMonths(70)); - } - [Test] - public void decrement() - { - var span = Svo.MonthSpan; - span--; - span.Should().Be(MonthSpan.FromMonths(68)); - } - - [Test] - public void multiply_by_int() => (Svo.MonthSpan * 3).Should().Be(MonthSpan.FromMonths(207)); - - [Test] - public void multiply_by_short() => (Svo.MonthSpan * (short)3).Should().Be(MonthSpan.FromMonths(207)); - - [Test] - public void multiply_by_double() => (Svo.MonthSpan * 0.608698).Should().Be(MonthSpan.FromMonths(42)); - - [Test] - public void multiply_by_decimal() => (Svo.MonthSpan * 0.608698m).Should().Be(MonthSpan.FromMonths(42)); - - [Test] - public void divide_by_int() => (Svo.MonthSpan / 3).Should().Be(MonthSpan.FromMonths(23)); - - [Test] - public void divide_by_short() => (Svo.MonthSpan / (short)3).Should().Be(MonthSpan.FromMonths(23)); - - [Test] - public void divide_by_double() => (Svo.MonthSpan / 4.0588).Should().Be(MonthSpan.FromMonths(17)); - - [Test] - public void divide_by_decimal() => (Svo.MonthSpan / 4.0588m).Should().Be(MonthSpan.FromMonths(17)); + [Test] + public void negate() => (-Svo.MonthSpan).Should().Be(MonthSpan.FromMonths(-69)); + + [Test] + public void increment() + { + var span = Svo.MonthSpan; + span++; + span.Should().Be(MonthSpan.FromMonths(70)); + } + [Test] + public void decrement() + { + var span = Svo.MonthSpan; + span--; + span.Should().Be(MonthSpan.FromMonths(68)); + } + + [Test] + public void multiply_by_int() => (Svo.MonthSpan * 3).Should().Be(MonthSpan.FromMonths(207)); + + [Test] + public void multiply_by_short() => (Svo.MonthSpan * (short)3).Should().Be(MonthSpan.FromMonths(207)); + + [Test] + public void multiply_by_double() => (Svo.MonthSpan * 0.608698).Should().Be(MonthSpan.FromMonths(42)); + + [Test] + public void multiply_by_decimal() => (Svo.MonthSpan * 0.608698m).Should().Be(MonthSpan.FromMonths(42)); + + [Test] + public void divide_by_int() => (Svo.MonthSpan / 3).Should().Be(MonthSpan.FromMonths(23)); + + [Test] + public void divide_by_short() => (Svo.MonthSpan / (short)3).Should().Be(MonthSpan.FromMonths(23)); + + [Test] + public void divide_by_double() => (Svo.MonthSpan / 4.0588).Should().Be(MonthSpan.FromMonths(17)); + + [Test] + public void divide_by_decimal() => (Svo.MonthSpan / 4.0588m).Should().Be(MonthSpan.FromMonths(17)); } public class Can_subtract { - [TestCase("2020-04-30", "1710-02-01", "310Y+2M")] - [TestCase("2020-04-30", "2020-04-01", 00)] - [TestCase("2020-04-30", "2020-03-31", 01)] - [TestCase("2020-01-01", "2019-01-02", 11)] - [TestCase("2020-01-01", "2019-03-13", 09)] - [TestCase("2020-01-01", "2019-03-01", 10)] - [TestCase("2020-01-01", "2020-02-20", -1)] - public void two_dates(Date d1, Date d2, MonthSpan expected) - => MonthSpan.Subtract(d1, d2).Should().Be(expected); + [TestCase("2020-04-30", "1710-02-01", "310Y+2M")] + [TestCase("2020-04-30", "2020-04-01", 00)] + [TestCase("2020-04-30", "2020-03-31", 01)] + [TestCase("2020-01-01", "2019-01-02", 11)] + [TestCase("2020-01-01", "2019-03-13", 09)] + [TestCase("2020-01-01", "2019-03-01", 10)] + [TestCase("2020-01-01", "2020-02-20", -1)] + public void two_dates(Date d1, Date d2, MonthSpan expected) + => MonthSpan.Subtract(d1, d2).Should().Be(expected); #if NET6_0_OR_GREATER - [TestCase("2020-04-30", "1710-02-01", "310Y+2M")] - [TestCase("2020-04-30", "2020-04-01", 00)] - [TestCase("2020-04-30", "2020-03-31", 01)] - [TestCase("2020-01-01", "2019-01-02", 11)] - [TestCase("2020-01-01", "2019-03-13", 09)] - [TestCase("2020-01-01", "2019-03-01", 10)] - [TestCase("2020-01-01", "2020-02-20", -1)] - public void two_date_onlys(Date d1, Date d2, MonthSpan expected) - => MonthSpan.Subtract((DateOnly)d1, (DateOnly)d2).Should().Be(expected); + [TestCase("2020-04-30", "1710-02-01", "310Y+2M")] + [TestCase("2020-04-30", "2020-04-01", 00)] + [TestCase("2020-04-30", "2020-03-31", 01)] + [TestCase("2020-01-01", "2019-01-02", 11)] + [TestCase("2020-01-01", "2019-03-13", 09)] + [TestCase("2020-01-01", "2019-03-01", 10)] + [TestCase("2020-01-01", "2020-02-20", -1)] + public void two_date_onlys(Date d1, Date d2, MonthSpan expected) + => MonthSpan.Subtract((DateOnly)d1, (DateOnly)d2).Should().Be(expected); #endif } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.MonthSpan.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_MonthSpan_as_object() - { - object obj = Svo.MonthSpan; - Svo.MonthSpan.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_MonthSpan_only() - => Assert.Throws(() => Svo.MonthSpan.CompareTo(new object())); - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - MonthSpan.FromMonths(-3), - MonthSpan.Zero, - MonthSpan.FromMonths(1), - MonthSpan.FromMonths(12), - MonthSpan.FromMonths(13), - MonthSpan.FromMonths(145), - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } - - [Test] - public void by_operators_for_different_values() - { - var smaller = MonthSpan.FromMonths(17); - var bigger = MonthSpan.FromMonths(42); - - (smaller < bigger).Should().BeTrue(); - (smaller <= bigger).Should().BeTrue(); - (smaller > bigger).Should().BeFalse(); - (smaller >= bigger).Should().BeFalse(); - } - - [Test] - public void by_operators_for_equal_values() - { - var left = MonthSpan.FromMonths(17); - var right = MonthSpan.FromMonths(17); - - (left < right).Should().BeFalse(); - (left <= right).Should().BeTrue(); - (left > right).Should().BeFalse(); - (left >= right).Should().BeTrue(); - } + [Test] + public void to_null_is_1() => Svo.MonthSpan.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_MonthSpan_as_object() + { + object obj = Svo.MonthSpan; + Svo.MonthSpan.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_MonthSpan_only() + => new object().Invoking(Svo.Month.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + MonthSpan.FromMonths(-3), + MonthSpan.Zero, + MonthSpan.FromMonths(1), + MonthSpan.FromMonths(12), + MonthSpan.FromMonths(13), + MonthSpan.FromMonths(145), + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } + + [Test] + public void by_operators_for_different_values() + { + var smaller = MonthSpan.FromMonths(17); + var bigger = MonthSpan.FromMonths(42); + + (smaller < bigger).Should().BeTrue(); + (smaller <= bigger).Should().BeTrue(); + (smaller > bigger).Should().BeFalse(); + (smaller >= bigger).Should().BeFalse(); + } + + [Test] + public void by_operators_for_equal_values() + { + var left = MonthSpan.FromMonths(17); + var right = MonthSpan.FromMonths(17); + + (left < right).Should().BeFalse(); + (left <= right).Should().BeTrue(); + (left > right).Should().BeFalse(); + (left >= right).Should().BeTrue(); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(MonthSpan).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(MonthSpan.Zero); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(MonthSpan.Zero); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("5Y+9M").To().Should().Be(Svo.MonthSpan); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.MonthSpan).Should().Be("5Y+9M"); - } - } - - [Test] - public void from_int() - => Converting.From(69).To().Should().Be(Svo.MonthSpan); - - [Test] - public void to_int() - => Converting.To().From(Svo.MonthSpan).Should().Be(69); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(MonthSpan).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(MonthSpan.Zero); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(MonthSpan.Zero); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("5Y+9M").To().Should().Be(Svo.MonthSpan); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.MonthSpan).Should().Be("5Y+9M"); + } + } + + [Test] + public void from_int() + => Converting.From(69).To().Should().Be(Svo.MonthSpan); + + [Test] + public void to_int() + => Converting.To().From(Svo.MonthSpan).Should().Be(69); } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase(69d, "5Y+9M")] - [TestCase(69L, "5Y+9M")] - [TestCase("5Y+9M", "5Y+9M")] - public void System_Text_JSON_deserialization(object json, MonthSpan svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase("5Y+9M", "5Y+9M")] - public void System_Text_JSON_serialization(MonthSpan svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase(69d, "5Y+9M")] + [TestCase(69L, "5Y+9M")] + [TestCase("5Y+9M", "5Y+9M")] + public void System_Text_JSON_deserialization(object json, MonthSpan svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase("5Y+9M", "5Y+9M")] + public void System_Text_JSON_serialization(MonthSpan svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase(69L, "5Y+9M")] - [TestCase("5Y+9M", "5Y+9M")] - public void convention_based_deserialization(object json, MonthSpan svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase("5Y+9M", "5Y+9M")] - public void convention_based_serialization(MonthSpan svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - [TestCase(true, typeof(InvalidOperationException))] - public void throws_for_invalid_json(object json, Type exceptionType) - { - json.Invoking(JsonTester.Read) - .Should().Throw().Which.Should().BeOfType(exceptionType); - } + [TestCase(69L, "5Y+9M")] + [TestCase("5Y+9M", "5Y+9M")] + public void convention_based_deserialization(object json, MonthSpan svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase("5Y+9M", "5Y+9M")] + public void convention_based_serialization(MonthSpan svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + [TestCase(true, typeof(InvalidOperationException))] + public void throws_for_invalid_json(object json, Type exceptionType) + { + json.Invoking(JsonTester.Read) + .Should().Throw().Which.Should().BeOfType(exceptionType); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(MonthSpan)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(MonthSpan), - description: "Month span, specified in years and months.", - example: "1Y+10M", - type: "string", - format: "month-span", - pattern: @"[+-]?[0-9]+Y[+-][0-9]+M")); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(MonthSpan)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(MonthSpan), + description: "Month span, specified in years and months.", + example: "1Y+10M", + type: "string", + format: "month-span", + pattern: @"[+-]?[0-9]+Y[+-][0-9]+M")); } diff --git a/specs/Qowaiv.Specs/Month_specs.cs b/specs/Qowaiv.Specs/Month_specs.cs index 58717d90..4b485999 100644 --- a/specs/Qowaiv.Specs/Month_specs.cs +++ b/specs/Qowaiv.Specs/Month_specs.cs @@ -2,581 +2,579 @@ public class With_domain_logic { - [TestCase(true, "February")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, Month svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, "February")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, Month svo) => svo.IsKnown.Should().Be(result); - - [TestCase(false, "February")] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, Month svo) - { - svo.IsEmpty().Should().Be(result); - } - - [TestCase(false, "February")] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, Month svo) - { - svo.IsEmptyOrUnknown().Should().Be(result); - } - - [TestCase(false, "February")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, Month svo) - { - svo.IsUnknown().Should().Be(result); - } + [TestCase(true, "February")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, Month svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, "February")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, Month svo) => svo.IsKnown.Should().Be(result); + + [TestCase(false, "February")] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, Month svo) + { + svo.IsEmpty().Should().Be(result); + } + + [TestCase(false, "February")] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, Month svo) + { + svo.IsEmptyOrUnknown().Should().Be(result); + } + + [TestCase(false, "February")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, Month svo) + { + svo.IsUnknown().Should().Be(result); + } } public class Days { - [TestCase(-1, "", 1999)] - [TestCase(-1, "February", "?")] - [TestCase(28, "February", 1999)] - [TestCase(29, "February", 2020)] - [TestCase(31, "January", 2020)] - [TestCase(30, "November", 2020)] - public void per_year(int days, Month month, Year year) - { - month.Days(year).Should().Be(days); - } + [TestCase(-1, "", 1999)] + [TestCase(-1, "February", "?")] + [TestCase(28, "February", 1999)] + [TestCase(29, "February", 2020)] + [TestCase(31, "January", 2020)] + [TestCase(30, "November", 2020)] + public void per_year(int days, Month month, Year year) + { + month.Days(year).Should().Be(days); + } } public class Short_name { - [Test] - public void is_string_empty_for_empty() - { - Month.Empty.ShortName.Should().Be(string.Empty); - } - [Test] - public void is_question_mark_for_unknown() - { - Month.Unknown.ShortName.Should().Be("?"); - } - [Test] - public void picks_current_culture() - { - using (TestCultures.nl_BE.Scoped()) - { - Svo.Month.ShortName.Should().Be("feb."); - } - } - [Test] - public void supports_custom_culture() - { - Svo.Month.GetShortName(TestCultures.nl_BE).Should().Be("feb."); - } + [Test] + public void is_string_empty_for_empty() + { + Month.Empty.ShortName.Should().Be(string.Empty); + } + [Test] + public void is_question_mark_for_unknown() + { + Month.Unknown.ShortName.Should().Be("?"); + } + [Test] + public void picks_current_culture() + { + using (TestCultures.nl_BE.Scoped()) + { + Svo.Month.ShortName.Should().Be("feb."); + } + } + [Test] + public void supports_custom_culture() + { + Svo.Month.GetShortName(TestCultures.nl_BE).Should().Be("feb."); + } } public class Full_name { - [Test] - public void is_string_empty_for_empty() - { - Month.Empty.FullName.Should().Be(string.Empty); - } - [Test] - public void is_question_mark_for_unknown() - { - Month.Unknown.FullName.Should().Be("?"); - } - [Test] - public void picks_current_culture() - { - using (TestCultures.nl_BE.Scoped()) - { - Svo.Month.FullName.Should().Be("februari"); - } - } - [Test] - public void supports_custom_culture() - { - Svo.Month.GetFullName(TestCultures.nl_BE).Should().Be("februari"); - } + [Test] + public void is_string_empty_for_empty() + { + Month.Empty.FullName.Should().Be(string.Empty); + } + [Test] + public void is_question_mark_for_unknown() + { + Month.Unknown.FullName.Should().Be("?"); + } + [Test] + public void picks_current_culture() + { + using (TestCultures.nl_BE.Scoped()) + { + Svo.Month.FullName.Should().Be("februari"); + } + } + [Test] + public void supports_custom_culture() + { + Svo.Month.GetFullName(TestCultures.nl_BE).Should().Be("februari"); + } } public class Has_constant { - [Test] - public void Empty_represent_default_value() - => Month.Empty.Should().Be(default); + [Test] + public void Empty_represent_default_value() + => Month.Empty.Should().Be(default); } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - { - Svo.Month.Equals(null).Should().BeFalse(); - } - - [Test] - public void not_equal_to_other_type() - { - Svo.Month.Equals(new object()).Should().BeFalse(); - } - - [Test] - public void not_equal_to_different_value() - { - Svo.Month.Equals(Month.December).Should().BeFalse(); - } - - [Test] - public void equal_to_same_value() - { - Svo.Month.Equals(Month.February).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_true_for_same_values() - { - (Svo.Month == Month.February).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_false_for_different_values() - { - (Svo.Month == Month.December).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_false_for_same_values() - { - (Svo.Month != Month.February).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_true_for_different_values() - { - (Svo.Month != Month.December).Should().BeTrue(); - } - - [TestCase("", 0)] - [TestCase("February", 665630161)] - public void hash_code_is_value_based(Month svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + { + Svo.Month.Equals(null).Should().BeFalse(); + } + + [Test] + public void not_equal_to_other_type() + { + Svo.Month.Equals(new object()).Should().BeFalse(); + } + + [Test] + public void not_equal_to_different_value() + { + Svo.Month.Equals(Month.December).Should().BeFalse(); + } + + [Test] + public void equal_to_same_value() + { + Svo.Month.Equals(Month.February).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_true_for_same_values() + { + (Svo.Month == Month.February).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_false_for_different_values() + { + (Svo.Month == Month.December).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_false_for_same_values() + { + (Svo.Month != Month.February).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_true_for_different_values() + { + (Svo.Month != Month.December).Should().BeTrue(); + } + + [TestCase("", 0)] + [TestCase("February", 665630161)] + public void hash_code_is_value_based(Month svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - { - Month.Parse(null).Should().Be(Month.Empty); - } - - [Test] - public void from_empty_string_represents_Empty() - { - Month.Parse(string.Empty).Should().Be(Month.Empty); - } - - [Test] - public void from_question_mark_represents_Unknown() - { - Month.Parse("?").Should().Be(Month.Unknown); - } - - [TestCase("en", "February")] - [TestCase("en", "02")] - [TestCase("en", "2")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - var parsed = Month.Parse(input); - parsed.Should().Be(Svo.Month); - } - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - "invalid input".Invoking(Month.Parse) - .Should().Throw() - .WithMessage("Not a valid month"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - { - Month.TryParse("invalid input", out _).Should().BeFalse(); - } - - [Test] - public void from_invalid_as_null_with_TryParse() - => Month.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - { - Month.TryParse("February").Should().Be(Svo.Month); - } + [Test] + public void from_null_string_represents_Empty() + { + Month.Parse(null).Should().Be(Month.Empty); + } + + [Test] + public void from_empty_string_represents_Empty() + { + Month.Parse(string.Empty).Should().Be(Month.Empty); + } + + [Test] + public void from_question_mark_represents_Unknown() + { + Month.Parse("?").Should().Be(Month.Unknown); + } + + [TestCase("en", "February")] + [TestCase("en", "02")] + [TestCase("en", "2")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + var parsed = Month.Parse(input); + parsed.Should().Be(Svo.Month); + } + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + "invalid input".Invoking(Month.Parse) + .Should().Throw() + .WithMessage("Not a valid month"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + { + Month.TryParse("invalid input", out _).Should().BeFalse(); + } + + [Test] + public void from_invalid_as_null_with_TryParse() + => Month.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + { + Month.TryParse("February").Should().Be(Svo.Month); + } } public class Can_be_created { - [Test] - public void with_TryCreate_returns_SVO() - { - Month.TryCreate(2).Should().Be(Svo.Month); - } - [Test] - public void with_TryCreate_returns_Empty() - { - Month.TryCreate(null).Should().Be(Month.Empty); - } + [Test] + public void with_TryCreate_returns_SVO() + { + Month.TryCreate(2).Should().Be(Svo.Month); + } + [Test] + public void with_TryCreate_returns_Empty() + { + Month.TryCreate(null).Should().Be(Month.Empty); + } } public class Has_custom_formatting { - [Test] - public void _default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Month.ToString().Should().Be("February"); - } - } - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Month.ToString(default(string)).Should().Be(Svo.Month.ToString()); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Month.ToString(string.Empty).Should().Be(Svo.Month.ToString()); - } - } - - [Test] - public void default_value_is_represented_as_string_empty() - { - default(Month).ToString().Should().Be(string.Empty); - } - - [Test] - public void unknown_value_is_represented_as_unknown() - { - Month.Unknown.ToString().Should().Be("?"); - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.Month.ToString("f", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: 'February', format: 'f'"); - } - - [TestCase("en-GB", null, "February", "February")] - [TestCase("en-GB", "s", "February", "Feb")] - [TestCase("en-GB", "M", "February", "2")] - [TestCase("en-GB", "m", "February", "02")] - [TestCase("nl-BE", "f", "February", "februari")] - [TestCase("en-GB", "M", "?", "?")] - [TestCase("en-GB", "m", "", "")] - public void culture_dependent(CultureInfo culture, string format, Month svo, string expected) - { - using (culture.Scoped()) - { - svo.ToString(format).Should().Be(expected); - } - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) - { - Svo.Month.ToString(provider: null).Should().Be("februari"); - } - } + [Test] + public void _default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Month.ToString().Should().Be("February"); + } + } + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Month.ToString(default(string)).Should().Be(Svo.Month.ToString()); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Month.ToString(string.Empty).Should().Be(Svo.Month.ToString()); + } + } + + [Test] + public void default_value_is_represented_as_string_empty() + { + default(Month).ToString().Should().Be(string.Empty); + } + + [Test] + public void unknown_value_is_represented_as_unknown() + { + Month.Unknown.ToString().Should().Be("?"); + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.Month.ToString("f", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: 'February', format: 'f'"); + } + + [TestCase("en-GB", null, "February", "February")] + [TestCase("en-GB", "s", "February", "Feb")] + [TestCase("en-GB", "M", "February", "2")] + [TestCase("en-GB", "m", "February", "02")] + [TestCase("nl-BE", "f", "February", "februari")] + [TestCase("en-GB", "M", "?", "?")] + [TestCase("en-GB", "m", "", "")] + public void culture_dependent(CultureInfo culture, string format, Month svo, string expected) + { + using (culture.Scoped()) + { + svo.ToString(format).Should().Be(expected); + } + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) + { + Svo.Month.ToString(provider: null).Should().Be("februari"); + } + } } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.Month.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_Month_as_object() - { - object obj = Svo.Month; - Svo.Month.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Month_only() - { - Assert.Throws(() => Svo.Month.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - default, - default, - Month.January, - Month.February, - Month.March, - Month.Unknown, - }; - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } - - [Test] - public void by_operators_for_different_values() - { - Month smaller = Month.February; - Month bigger = Month.March; - (smaller < bigger).Should().BeTrue(); - (smaller <= bigger).Should().BeTrue(); - (smaller > bigger).Should().BeFalse(); - (smaller >= bigger).Should().BeFalse(); - } - - [Test] - public void by_operators_for_equal_values() - { - Month left = Month.February; - Month right = Svo.Month; - (left < right).Should().BeFalse(); - (left <= right).Should().BeTrue(); - (left > right).Should().BeFalse(); - (left >= right).Should().BeTrue(); - } - - [TestCase("", "February")] - [TestCase("?", "February")] - [TestCase("February", "")] - [TestCase("February", "?")] - public void by_operators_for_empty_or_unknown_always_false(Month l, Month r) - { - (l < r).Should().BeFalse(); - (l <= r).Should().BeFalse(); - (l > r).Should().BeFalse(); - (l >= r).Should().BeFalse(); - } + [Test] + public void to_null_is_1() => Svo.Month.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_Month_as_object() + { + object obj = Svo.Month; + Svo.Month.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Month_only() + => new object().Invoking(Svo.Month.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + default, + default, + Month.January, + Month.February, + Month.March, + Month.Unknown, + }; + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } + + [Test] + public void by_operators_for_different_values() + { + Month smaller = Month.February; + Month bigger = Month.March; + (smaller < bigger).Should().BeTrue(); + (smaller <= bigger).Should().BeTrue(); + (smaller > bigger).Should().BeFalse(); + (smaller >= bigger).Should().BeFalse(); + } + + [Test] + public void by_operators_for_equal_values() + { + Month left = Month.February; + Month right = Svo.Month; + (left < right).Should().BeFalse(); + (left <= right).Should().BeTrue(); + (left > right).Should().BeFalse(); + (left >= right).Should().BeTrue(); + } + + [TestCase("", "February")] + [TestCase("?", "February")] + [TestCase("February", "")] + [TestCase("February", "?")] + public void by_operators_for_empty_or_unknown_always_false(Month l, Month r) + { + (l < r).Should().BeFalse(); + (l <= r).Should().BeFalse(); + (l > r).Should().BeFalse(); + (l >= r).Should().BeFalse(); + } } public class Casts { - [Test] - public void explicitly_from_byte() - { - var casted = (Month)2; - casted.Should().Be(Svo.Month); - } - - [Test] - public void explicitly_to_byte() - { - var casted = (byte)Svo.Month; - casted.Should().Be(2); - } + [Test] + public void explicitly_from_byte() + { + var casted = (Month)2; + casted.Should().Be(Svo.Month); + } + + [Test] + public void explicitly_to_byte() + { + var casted = (byte)Svo.Month; + casted.Should().Be(2); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(Month).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(default); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(default); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("February").To().Should().Be(Svo.Month); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.Month).Should().Be("February"); - } - } - - [Test] - public void from_int() - => Converting.From(2).To().Should().Be(Svo.Month); - - [Test] - public void to_int() - => Converting.To().From(Svo.Month).Should().Be(2); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(Month).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(default); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(default); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("February").To().Should().Be(Svo.Month); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.Month).Should().Be("February"); + } + } + + [Test] + public void from_int() + => Converting.From(2).To().Should().Be(Svo.Month); + + [Test] + public void to_int() + => Converting.To().From(Svo.Month).Should().Be(2); } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase(null, null)] - [TestCase("?", "?")] - [TestCase(2.0, "February")] - [TestCase(2L, "February")] - [TestCase("feb", "February")] - public void System_Text_JSON_deserialization(object json, Month svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("Feb", "Feb")] - public void System_Text_JSON_serialization(Month svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase(null, null)] + [TestCase("?", "?")] + [TestCase(2.0, "February")] + [TestCase(2L, "February")] + [TestCase("feb", "February")] + public void System_Text_JSON_deserialization(object json, Month svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("Feb", "Feb")] + public void System_Text_JSON_serialization(Month svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("?", "?")] - [TestCase(2.0, "February")] - [TestCase(2L, "February")] - [TestCase("feb", "February")] - public void convention_based_deserialization(object json, Month svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("Feb", "Feb")] - public void convention_based_serialization(Month svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - [TestCase(-1L, typeof(ArgumentOutOfRangeException))] - [TestCase(long.MaxValue, typeof(ArgumentOutOfRangeException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("?", "?")] + [TestCase(2.0, "February")] + [TestCase(2L, "February")] + [TestCase("feb", "February")] + public void convention_based_deserialization(object json, Month svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("Feb", "Feb")] + public void convention_based_serialization(Month svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + [TestCase(-1L, typeof(ArgumentOutOfRangeException))] + [TestCase(long.MaxValue, typeof(ArgumentOutOfRangeException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.Month); - xml.Should().Be("Feb"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("Feb"); - Svo.Month.Should().Be(svo); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.Month); - round_tripped.Should().Be(Svo.Month); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.Month); - var round_tripped = SerializeDeserialize.Xml(structure); - round_tripped.Should().Be(structure); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.Month; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.Month); + xml.Should().Be("Feb"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("Feb"); + Svo.Month.Should().Be(svo); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.Month); + round_tripped.Should().Be(Svo.Month); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.Month); + var round_tripped = SerializeDeserialize.Xml(structure); + round_tripped.Should().Be(structure); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.Month; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Month)) - .Should().BeEquivalentTo(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(Month), - description: "Month(-only) notation.", - type: "string", - example: "Jun", - format: "month", - @enum: new[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "?" }, - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Month)) + .Should().BeEquivalentTo(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(Month), + description: "Month(-only) notation.", + type: "string", + example: "Jun", + format: "month", + @enum: new[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "?" }, + nullable: true)); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Month); - round_tripped.Should().Be(Svo.Month); - } - - [Test] - public void storing_byte_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Month); - info.GetByte("Value").Should().Be((byte)2); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Month); + round_tripped.Should().Be(Svo.Month); + } + + [Test] + public void storing_byte_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Month); + info.GetByte("Value").Should().Be((byte)2); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("{unknown}", "?")] - [TestCase("February (02)", "February")] - public void has_custom_display(object display, Month svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("{unknown}", "?")] + [TestCase("February (02)", "February")] + public void has_custom_display(object display, Month svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Percentage_specs.cs b/specs/Qowaiv.Specs/Percentage_specs.cs index 38d5146b..dc2a3a2d 100644 --- a/specs/Qowaiv.Specs/Percentage_specs.cs +++ b/specs/Qowaiv.Specs/Percentage_specs.cs @@ -2,1221 +2,1217 @@ public class Is_valid_for { - [TestCase("1751‱", "en")] - [TestCase("175.1‰", "en")] - [TestCase("17.51", "en")] - [TestCase("17.51%", "en")] - [TestCase("17,51%", "nl")] - public void strings_representing_SVO(string input, CultureInfo culture) - => Percentage.TryParse(input, culture).Should().NotBeNull(); - - [TestCase("175.1<>", "en")] - [TestCase("17,51#", "nl")] - public void custom_culture_with_different_symbols(string input, CultureInfo culture) - { - using (culture.WithPercentageSymbols("#", "<>").Scoped()) - { - Percentage.TryParse(input).Should().NotBeNull(); - } - } + [TestCase("1751‱", "en")] + [TestCase("175.1‰", "en")] + [TestCase("17.51", "en")] + [TestCase("17.51%", "en")] + [TestCase("17,51%", "nl")] + public void strings_representing_SVO(string input, CultureInfo culture) + => Percentage.TryParse(input, culture).Should().NotBeNull(); + + [TestCase("175.1<>", "en")] + [TestCase("17,51#", "nl")] + public void custom_culture_with_different_symbols(string input, CultureInfo culture) + { + using (culture.WithPercentageSymbols("#", "<>").Scoped()) + { + Percentage.TryParse(input).Should().NotBeNull(); + } + } } public class Is_not_valid_for { - [TestCase("‱1‱")] - [TestCase("‱1‰")] - [TestCase("‱1%")] - public void two_symbols(string str) - => Percentage.TryParse(str).Should().BeNull(); - - [TestCase("1‱1")] - [TestCase("1‰1")] - [TestCase("1%1")] - public void symbol_in_the_middle(string str) - => Percentage.TryParse(str).Should().BeNull(); + [TestCase("‱1‱")] + [TestCase("‱1‰")] + [TestCase("‱1%")] + public void two_symbols(string str) + => Percentage.TryParse(str).Should().BeNull(); + + [TestCase("1‱1")] + [TestCase("1‰1")] + [TestCase("1%1")] + public void symbol_in_the_middle(string str) + => Percentage.TryParse(str).Should().BeNull(); } public class Has_constant { - [Test] - public void Zero_represent_default_value() - { - Percentage.Zero.Should().Be(default); - } - - [Test] - public void One_represent_1_percent() - => Percentage.One.ToString("0%", CultureInfo.InvariantCulture).Should().Be("1%"); - - [Test] - public void Hundred_represent_100_percent() - => Percentage.Hundred.ToString("0%", CultureInfo.InvariantCulture).Should().Be("100%"); + [Test] + public void Zero_represent_default_value() + { + Percentage.Zero.Should().Be(default); + } + + [Test] + public void One_represent_1_percent() + => Percentage.One.ToString("0%", CultureInfo.InvariantCulture).Should().Be("1%"); + + [Test] + public void Hundred_represent_100_percent() + => Percentage.Hundred.ToString("0%", CultureInfo.InvariantCulture).Should().Be("100%"); } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - { - Svo.Percentage.Equals(null).Should().BeFalse(); - } - - [Test] - public void not_equal_to_other_type() - { - Svo.Percentage.Equals(new object()).Should().BeFalse(); - } - - [Test] - public void not_equal_to_different_value() - { - Svo.Percentage.Equals(84.17.Percent()).Should().BeFalse(); - } - - [Test] - public void equal_to_same_value() - { - Svo.Percentage.Equals(17.51.Percent()).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_true_for_same_values() - { - (Svo.Percentage == 17.51.Percent()).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_false_for_different_values() - { - (Svo.Percentage == 6.66.Percent()).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_false_for_same_values() - { - (Svo.Percentage != 17.51.Percent()).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_true_for_different_values() - { - (Svo.Percentage != 6.66.Percent()).Should().BeTrue(); - } - - [TestCase("0%", 0)] - [TestCase("17.51%", 665367300)] - public void hash_code_is_value_based(Percentage svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + { + Svo.Percentage.Equals(null).Should().BeFalse(); + } + + [Test] + public void not_equal_to_other_type() + { + Svo.Percentage.Equals(new object()).Should().BeFalse(); + } + + [Test] + public void not_equal_to_different_value() + { + Svo.Percentage.Equals(84.17.Percent()).Should().BeFalse(); + } + + [Test] + public void equal_to_same_value() + { + Svo.Percentage.Equals(17.51.Percent()).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_true_for_same_values() + { + (Svo.Percentage == 17.51.Percent()).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_false_for_different_values() + { + (Svo.Percentage == 6.66.Percent()).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_false_for_same_values() + { + (Svo.Percentage != 17.51.Percent()).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_true_for_different_values() + { + (Svo.Percentage != 6.66.Percent()).Should().BeTrue(); + } + + [TestCase("0%", 0)] + [TestCase("17.51%", 665367300)] + public void hash_code_is_value_based(Percentage svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [TestCase("en", "175.1‰")] - [TestCase("en", "175.1‰")] - [TestCase("en", "1751‱")] - [TestCase("nl", "17,51%")] - [TestCase("fr-FR", "%17,51")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - var parsed = Percentage.Parse(input); - parsed.Should().Be(Svo.Percentage); - } - } - - [TestCase("175.1<>", "en")] - [TestCase("17,51#", "nl")] - public void with_custom_culture_with_different_symbols(string input, CultureInfo culture) - { - var parsed = Percentage.Parse(input, culture.WithPercentageSymbols("#", "<>")); - parsed.Should().Be(Svo.Percentage); - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - "invalid input".Invoking(Percentage.Parse) - .Should().Throw() - .WithMessage("Not a valid percentage"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - { - Percentage.TryParse("invalid input", out _).Should().BeFalse(); - } - - [Test] - public void from_invalid_as_null_with_TryParse() - => Percentage.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - { - using (TestCultures.en_GB.Scoped()) - { - Percentage.TryParse("17.51%").Should().Be(Svo.Percentage); - } - } + [TestCase("en", "175.1‰")] + [TestCase("en", "175.1‰")] + [TestCase("en", "1751‱")] + [TestCase("nl", "17,51%")] + [TestCase("fr-FR", "%17,51")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + var parsed = Percentage.Parse(input); + parsed.Should().Be(Svo.Percentage); + } + } + + [TestCase("175.1<>", "en")] + [TestCase("17,51#", "nl")] + public void with_custom_culture_with_different_symbols(string input, CultureInfo culture) + { + var parsed = Percentage.Parse(input, culture.WithPercentageSymbols("#", "<>")); + parsed.Should().Be(Svo.Percentage); + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + "invalid input".Invoking(Percentage.Parse) + .Should().Throw() + .WithMessage("Not a valid percentage"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + { + Percentage.TryParse("invalid input", out _).Should().BeFalse(); + } + + [Test] + public void from_invalid_as_null_with_TryParse() + => Percentage.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + { + using (TestCultures.en_GB.Scoped()) + { + Percentage.TryParse("17.51%").Should().Be(Svo.Percentage); + } + } } public class Can_not_be_parsed { - [TestCase(NumberStyles.HexNumber)] - [TestCase(NumberStyles.AllowExponent)] - public void using_a_number_style_other_then_Number(NumberStyles style) - => style.Invoking(s => Percentage.TryParse("4.5%", s, CultureInfo.InvariantCulture, out _)) - .Should().Throw() - .WithMessage("The number style '*' is not supported.*"); + [TestCase(NumberStyles.HexNumber)] + [TestCase(NumberStyles.AllowExponent)] + public void using_a_number_style_other_then_Number(NumberStyles style) + => style.Invoking(s => Percentage.TryParse("4.5%", s, CultureInfo.InvariantCulture, out _)) + .Should().Throw() + .WithMessage("The number style '*' is not supported.*"); } public class Can_be_created_with_percentage_extension { - [Test] - public void from_int() - { - var p = 3.Percent(); - p.ToString(CultureInfo.InvariantCulture).Should().Be("3%"); - } - - [Test] - public void from_double() - { - var p = 3.14.Percent(); - p.ToString(CultureInfo.InvariantCulture).Should().Be("3.14%"); - } - - [Test] - public void from_decimal() - { - var p = 3.14m.Percent(); - p.ToString(CultureInfo.InvariantCulture).Should().Be("3.14%"); - } + [Test] + public void from_int() + { + var p = 3.Percent(); + p.ToString(CultureInfo.InvariantCulture).Should().Be("3%"); + } + + [Test] + public void from_double() + { + var p = 3.14.Percent(); + p.ToString(CultureInfo.InvariantCulture).Should().Be("3.14%"); + } + + [Test] + public void from_decimal() + { + var p = 3.14m.Percent(); + p.ToString(CultureInfo.InvariantCulture).Should().Be("3.14%"); + } } public class Has_custom_formatting { - [Test] - public void _default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Percentage.ToString().Should().Be("17.51%"); - } - } - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Percentage.ToString(default(string)).Should().Be(Svo.Percentage.ToString()); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Percentage.ToString(string.Empty).Should().Be(Svo.Percentage.ToString()); - } - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.Percentage.ToString("0.000%", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: '17.510%', format: '0.000%'"); - } - - [TestCase("en-GB", null, "17.51%", "17.51%")] - [TestCase("nl-BE", "0.000%", "17.51%", "17,510%")] - [TestCase("en", "%0.###", "17.51%", "%17.51")] - [TestCase("en", "‰0.###", "17.51%", "‰175.1")] - [TestCase("en", "‱0.###", "17.51%", "‱1751")] - [TestCase("en", "0.###%", "17.51%", "17.51%")] - [TestCase("en", "0.###‰", "17.51%", "175.1‰")] - [TestCase("en", "0.###‱", "17.51%", "1751‱")] - [TestCase("en", "0.###", "17.51%", "17.51")] - public void culture_dependent(CultureInfo culture, string format, Percentage svo, string expected) - { - using (culture.Scoped()) - { - svo.ToString(format).Should().Be(expected); - } - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) - { - Svo.Percentage.ToString(provider: null).Should().Be("17,51%"); - } - } - - [TestCase("fr-FR", "%")] - [TestCase("fa-IR", "٪")] - public void with_percent_sign_before_for(string culture, string sign) - => Svo.Percentage.ToString(TestCultures.Select(culture)).Should().StartWith(sign); - - [Test] - public void using_per_mille_sign() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Percentage.ToString("PM").Should().Be("175.1‰"); - } - } - - [Test] - public void using_per_then_thousand_sign() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Percentage.ToString("PT").Should().Be("1751‱"); - } - } - - [TestCase("0.##%", "792281625142643375935439503.35%")] - [TestCase("0.#‰", "7922816251426433759354395033.5‰")] - [TestCase("0‱", "79228162514264337593543950335‱")] - public void for_max_value(string format, string formatted) - => Percentage.MaxValue.ToString(format, CultureInfo.InvariantCulture).Should().Be(formatted); - - [TestCase("0.##%", "-792281625142643375935439503.35%")] - [TestCase("0.#‰", "-7922816251426433759354395033.5‰")] - [TestCase("0‱", "-79228162514264337593543950335‱")] - public void for_min_value(string format, string formatted) - => Percentage.MinValue.ToString(format, CultureInfo.InvariantCulture).Should().Be(formatted); + [Test] + public void _default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Percentage.ToString().Should().Be("17.51%"); + } + } + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Percentage.ToString(default(string)).Should().Be(Svo.Percentage.ToString()); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Percentage.ToString(string.Empty).Should().Be(Svo.Percentage.ToString()); + } + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.Percentage.ToString("0.000%", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: '17.510%', format: '0.000%'"); + } + + [TestCase("en-GB", null, "17.51%", "17.51%")] + [TestCase("nl-BE", "0.000%", "17.51%", "17,510%")] + [TestCase("en", "%0.###", "17.51%", "%17.51")] + [TestCase("en", "‰0.###", "17.51%", "‰175.1")] + [TestCase("en", "‱0.###", "17.51%", "‱1751")] + [TestCase("en", "0.###%", "17.51%", "17.51%")] + [TestCase("en", "0.###‰", "17.51%", "175.1‰")] + [TestCase("en", "0.###‱", "17.51%", "1751‱")] + [TestCase("en", "0.###", "17.51%", "17.51")] + public void culture_dependent(CultureInfo culture, string format, Percentage svo, string expected) + { + using (culture.Scoped()) + { + svo.ToString(format).Should().Be(expected); + } + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) + { + Svo.Percentage.ToString(provider: null).Should().Be("17,51%"); + } + } + + [TestCase("fr-FR", "%")] + [TestCase("fa-IR", "٪")] + public void with_percent_sign_before_for(string culture, string sign) + => Svo.Percentage.ToString(TestCultures.Select(culture)).Should().StartWith(sign); + + [Test] + public void using_per_mille_sign() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Percentage.ToString("PM").Should().Be("175.1‰"); + } + } + + [Test] + public void using_per_then_thousand_sign() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Percentage.ToString("PT").Should().Be("1751‱"); + } + } + + [TestCase("0.##%", "792281625142643375935439503.35%")] + [TestCase("0.#‰", "7922816251426433759354395033.5‰")] + [TestCase("0‱", "79228162514264337593543950335‱")] + public void for_max_value(string format, string formatted) + => Percentage.MaxValue.ToString(format, CultureInfo.InvariantCulture).Should().Be(formatted); + + [TestCase("0.##%", "-792281625142643375935439503.35%")] + [TestCase("0.#‰", "-7922816251426433759354395033.5‰")] + [TestCase("0‱", "-79228162514264337593543950335‱")] + public void for_min_value(string format, string formatted) + => Percentage.MinValue.ToString(format, CultureInfo.InvariantCulture).Should().Be(formatted); } public class Formatting_is_invalid { - [Test] - public void when_multiple_symbols_are_specified() - { - Assert.Catch(() => Svo.Percentage.ToString("0%%")); - } + [Test] + public void when_multiple_symbols_are_specified() + => "0%%".Invoking(Svo.Percentage.ToString).Should().Throw(); } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.Percentage.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_Percentage_as_object() - { - object obj = Svo.Percentage; - Svo.Percentage.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Percentage_only() - { - Assert.Throws(() => Svo.Percentage.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - Percentage.Zero, - Percentage.One, - 17.51.Percent(), - 33.33.Percent(), - 84.17.Percent(), - Percentage.Hundred, - }; - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } - - [Test] - public void _operators_for_different_values() - { - Percentage smaller = 17.51.Percent(); - Percentage bigger = 84.17.Percent(); - (smaller < bigger).Should().BeTrue(); - (smaller <= bigger).Should().BeTrue(); - (smaller > bigger).Should().BeFalse(); - (smaller >= bigger).Should().BeFalse(); - } - - [Test] - public void _operators_for_equal_values() - { - Percentage left = 17.51.Percent(); - Percentage right = 17.51.Percent(); - (left < right).Should().BeFalse(); - (left <= right).Should().BeTrue(); - (left > right).Should().BeFalse(); - (left >= right).Should().BeTrue(); - } + [Test] + public void to_null_is_1() => Svo.Percentage.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_Percentage_as_object() + { + object obj = Svo.Percentage; + Svo.Percentage.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Percentage_only() + => new object().Invoking(Svo.Percentage.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + Percentage.Zero, + Percentage.One, + 17.51.Percent(), + 33.33.Percent(), + 84.17.Percent(), + Percentage.Hundred, + }; + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } + + [Test] + public void _operators_for_different_values() + { + Percentage smaller = 17.51.Percent(); + Percentage bigger = 84.17.Percent(); + (smaller < bigger).Should().BeTrue(); + (smaller <= bigger).Should().BeTrue(); + (smaller > bigger).Should().BeFalse(); + (smaller >= bigger).Should().BeFalse(); + } + + [Test] + public void _operators_for_equal_values() + { + Percentage left = 17.51.Percent(); + Percentage right = 17.51.Percent(); + (left < right).Should().BeFalse(); + (left <= right).Should().BeTrue(); + (left > right).Should().BeFalse(); + (left >= right).Should().BeTrue(); + } } public class Casts { - [Test] - public void explicitly_from_decimal() - { - var casted = (Percentage)0.1751m; - casted.Should().Be(Svo.Percentage); - } - - [Test] - public void explicitly_to_decimal() - { - var casted = (decimal)Svo.Percentage; - casted.Should().Be(0.1751m); - } - - [Test] - public void explicitly_from_double() - { - var casted = (Percentage)0.1751; - casted.Should().Be(Svo.Percentage); - } - - [Test] - public void explicitly_to_double() - { - var casted = (double)Svo.Percentage; - casted.Should().Be(0.1751); - } + [Test] + public void explicitly_from_decimal() + { + var casted = (Percentage)0.1751m; + casted.Should().Be(Svo.Percentage); + } + + [Test] + public void explicitly_to_decimal() + { + var casted = (decimal)Svo.Percentage; + casted.Should().Be(0.1751m); + } + + [Test] + public void explicitly_from_double() + { + var casted = (Percentage)0.1751; + casted.Should().Be(Svo.Percentage); + } + + [Test] + public void explicitly_to_double() + { + var casted = (double)Svo.Percentage; + casted.Should().Be(0.1751); + } } public class Can_be_multiplied_by { - [Test] - public void _percentage() - { - var multiplied = 17.Percent() * 42.Percent(); - multiplied.Should().Be(7.14.Percent()); - } - - [Test] - public void _decimal() - { - var multiplied = 17.Percent() * 0.42m; - multiplied.Should().Be(7.14.Percent()); - } - - [Test] - public void _double() - { - var multiplied = 17.Percent() * 0.42; - multiplied.Should().Be(7.14.Percent()); - } - - [Test] - public void _float() - { - var multiplied = 17.Percent() * 0.42F; - multiplied.Should().Be(7.14.Percent()); - } - - [Test] - public void _int() - { - var multiplied = 17.Percent() * 2; - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _uint() - { - var multiplied = 17.Percent() * 2U; - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _long() - { - var multiplied = 17.Percent() * 2L; - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _ulong() - { - var multiplied = 17.Percent() * 2UL; - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _short() - { - var multiplied = 17.Percent() * ((short)2); - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _ushort() - { - var multiplied = 17.Percent() * ((ushort)2); - multiplied.Should().Be(34.Percent()); - } + [Test] + public void _percentage() + { + var multiplied = 17.Percent() * 42.Percent(); + multiplied.Should().Be(7.14.Percent()); + } + + [Test] + public void _decimal() + { + var multiplied = 17.Percent() * 0.42m; + multiplied.Should().Be(7.14.Percent()); + } + + [Test] + public void _double() + { + var multiplied = 17.Percent() * 0.42; + multiplied.Should().Be(7.14.Percent()); + } + + [Test] + public void _float() + { + var multiplied = 17.Percent() * 0.42F; + multiplied.Should().Be(7.14.Percent()); + } + + [Test] + public void _int() + { + var multiplied = 17.Percent() * 2; + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _uint() + { + var multiplied = 17.Percent() * 2U; + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _long() + { + var multiplied = 17.Percent() * 2L; + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _ulong() + { + var multiplied = 17.Percent() * 2UL; + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _short() + { + var multiplied = 17.Percent() * ((short)2); + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _ushort() + { + var multiplied = 17.Percent() * ((ushort)2); + multiplied.Should().Be(34.Percent()); + } } public class Can_be_divided_by { - [Test] - public void _percentage() - { - var multiplied = 17.Percent() / 50.Percent(); - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _decimal() - { - var multiplied = 17.Percent() / 0.5m; - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _double() - { - var multiplied = 17.Percent() / 0.5; - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _float() - { - var multiplied = 17.Percent() / 0.5F; - multiplied.Should().Be(34.Percent()); - } - - [Test] - public void _int() - { - var multiplied = 17.Percent() / 2; - multiplied.Should().Be(8.5.Percent()); - } - - [Test] - public void _uint() - { - var multiplied = 17.Percent() / 2U; - multiplied.Should().Be(8.5.Percent()); - } - - [Test] - public void _long() - { - var multiplied = 17.Percent() / 2L; - multiplied.Should().Be(8.5.Percent()); - } - - [Test] - public void _ulong() - { - var multiplied = 17.Percent() / 2UL; - multiplied.Should().Be(8.5.Percent()); - } - - [Test] - public void _short() - { - var multiplied = 17.Percent() / ((short)2); - multiplied.Should().Be(8.5.Percent()); - } - - [Test] - public void _ushort() - { - var multiplied = 17.Percent() / ((ushort)2); - multiplied.Should().Be(8.5.Percent()); - } + [Test] + public void _percentage() + { + var multiplied = 17.Percent() / 50.Percent(); + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _decimal() + { + var multiplied = 17.Percent() / 0.5m; + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _double() + { + var multiplied = 17.Percent() / 0.5; + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _float() + { + var multiplied = 17.Percent() / 0.5F; + multiplied.Should().Be(34.Percent()); + } + + [Test] + public void _int() + { + var multiplied = 17.Percent() / 2; + multiplied.Should().Be(8.5.Percent()); + } + + [Test] + public void _uint() + { + var multiplied = 17.Percent() / 2U; + multiplied.Should().Be(8.5.Percent()); + } + + [Test] + public void _long() + { + var multiplied = 17.Percent() / 2L; + multiplied.Should().Be(8.5.Percent()); + } + + [Test] + public void _ulong() + { + var multiplied = 17.Percent() / 2UL; + multiplied.Should().Be(8.5.Percent()); + } + + [Test] + public void _short() + { + var multiplied = 17.Percent() / ((short)2); + multiplied.Should().Be(8.5.Percent()); + } + + [Test] + public void _ushort() + { + var multiplied = 17.Percent() / ((ushort)2); + multiplied.Should().Be(8.5.Percent()); + } } public class Can_be_added_to { - [Test] - public void _percentage() - { - var addition = 13.Percent() + 34.Percent(); - addition.Should().Be(47.Percent()); - } - - [Test] - public void _amount() - { - var addition = (Amount)44 + 50.Percent(); - addition.Should().Be((Amount)66); - } - - [Test] - public void _money() - { - var addition = (44.6 + Currency.EUR) + 50.Percent(); - addition.Should().Be(66.9 + Currency.EUR); - } - - [Test] - public void _decimal() - { - var addition = 34.586m + 75.Percent(); - addition.Should().Be(60.5255m); - } - - [Test] - public void _double() - { - var addition = 34.586 + 75.Percent(); - addition.Should().BeApproximately(60.5255, 0.00001); - } - - [Test] - public void _float() - { - var addition = 34.586f + 75.Percent(); - Assert.That(addition, Is.EqualTo(60.5255f).Within(0.00001)); - } - - [Test] - public void _int() - { - var addition = 400 + 17.Percent(); - addition.Should().Be(468); - } - - [Test] - public void _uint() - { - var addition = 400U + 17.Percent(); - addition.Should().Be(468U); - } - - [Test] - public void _long() - { - var addition = 400L + 17.Percent(); - addition.Should().Be(468L); - } - - [Test] - public void _ulong() - { - var addition = 400UL + 17.Percent(); - addition.Should().Be(468UL); - } - - [Test] - public void _short() - { - var addition = ((short)400) + 17.Percent(); - addition.Should().Be((short)468); - } - - [Test] - public void _ushort() - { - var addition = ((ushort)400) + 17.Percent(); - addition.Should().Be((ushort)468); - } + [Test] + public void _percentage() + { + var addition = 13.Percent() + 34.Percent(); + addition.Should().Be(47.Percent()); + } + + [Test] + public void _amount() + { + var addition = (Amount)44 + 50.Percent(); + addition.Should().Be((Amount)66); + } + + [Test] + public void _money() + { + var addition = (44.6 + Currency.EUR) + 50.Percent(); + addition.Should().Be(66.9 + Currency.EUR); + } + + [Test] + public void _decimal() + { + var addition = 34.586m + 75.Percent(); + addition.Should().Be(60.5255m); + } + + [Test] + public void _double() + { + var addition = 34.586 + 75.Percent(); + addition.Should().BeApproximately(60.5255, 0.00001); + } + + [Test] + public void _float() + { + var addition = 34.586f + 75.Percent(); + Assert.That(addition, Is.EqualTo(60.5255f).Within(0.00001)); + } + + [Test] + public void _int() + { + var addition = 400 + 17.Percent(); + addition.Should().Be(468); + } + + [Test] + public void _uint() + { + var addition = 400U + 17.Percent(); + addition.Should().Be(468U); + } + + [Test] + public void _long() + { + var addition = 400L + 17.Percent(); + addition.Should().Be(468L); + } + + [Test] + public void _ulong() + { + var addition = 400UL + 17.Percent(); + addition.Should().Be(468UL); + } + + [Test] + public void _short() + { + var addition = ((short)400) + 17.Percent(); + addition.Should().Be((short)468); + } + + [Test] + public void _ushort() + { + var addition = ((ushort)400) + 17.Percent(); + addition.Should().Be((ushort)468); + } } public class Can_be_subtracted_from { - [Test] - public void _percentage() - { - var addition = 13.Percent() - 34.Percent(); - addition.Should().Be(-21.Percent()); - } - - [Test] - public void _amount() - { - var addition = (Amount)44.6 - 50.Percent(); - addition.Should().Be((Amount)22.3); - } - - [Test] - public void _money() - { - var addition = (44.6 + Currency.EUR) - 50.Percent(); - addition.Should().Be(22.3 + Currency.EUR); - } - - [Test] - public void _decimal() - { - var addition = 34.586m - 75.Percent(); - addition.Should().Be(8.6465m); - } - - [Test] - public void _double() - { - var addition = 34.586 - 75.Percent(); - Assert.That(addition, Is.EqualTo(8.6465).Within(0.00001)); - } - - [Test] - public void _float() - { - var addition = 34.586f - 75.Percent(); - Assert.That(addition, Is.EqualTo(8.6465f).Within(0.00001)); - } - - [Test] - public void _int() - { - var addition = 400 - 17.Percent(); - addition.Should().Be(332); - } - - [Test] - public void _uint() - { - var addition = 400U - 17.Percent(); - addition.Should().Be(332U); - } - - [Test] - public void _long() - { - var addition = 400L - 17.Percent(); - addition.Should().Be(332L); - } - - [Test] - public void _ulong() - { - var addition = 400UL - 17.Percent(); - addition.Should().Be(332UL); - } - - [Test] - public void _short() - { - var addition = ((short)400) - 17.Percent(); - addition.Should().Be((short)332); - } - - [Test] - public void _ushort() - { - var addition = ((ushort)400) - 17.Percent(); - addition.Should().Be((ushort)332); - } + [Test] + public void _percentage() + { + var addition = 13.Percent() - 34.Percent(); + addition.Should().Be(-21.Percent()); + } + + [Test] + public void _amount() + { + var addition = (Amount)44.6 - 50.Percent(); + addition.Should().Be((Amount)22.3); + } + + [Test] + public void _money() + { + var addition = (44.6 + Currency.EUR) - 50.Percent(); + addition.Should().Be(22.3 + Currency.EUR); + } + + [Test] + public void _decimal() + { + var addition = 34.586m - 75.Percent(); + addition.Should().Be(8.6465m); + } + + [Test] + public void _double() + { + var addition = 34.586 - 75.Percent(); + addition.Should().BeApproximately(8.6465, 0.00001); + } + + [Test] + public void _float() + { + var addition = 34.586f - 75.Percent(); + addition.Should().BeApproximately(8.6465f, 0.00001f); + } + + [Test] + public void _int() + { + var addition = 400 - 17.Percent(); + addition.Should().Be(332); + } + + [Test] + public void _uint() + { + var addition = 400U - 17.Percent(); + addition.Should().Be(332U); + } + + [Test] + public void _long() + { + var addition = 400L - 17.Percent(); + addition.Should().Be(332L); + } + + [Test] + public void _ulong() + { + var addition = 400UL - 17.Percent(); + addition.Should().Be(332UL); + } + + [Test] + public void _short() + { + var addition = ((short)400) - 17.Percent(); + addition.Should().Be((short)332); + } + + [Test] + public void _ushort() + { + var addition = ((ushort)400) - 17.Percent(); + addition.Should().Be((ushort)332); + } } public class Can_get_a_percentage_of { - [Test] - public void _percentage() - { - var addition = 13.Percent() * 34.Percent(); - addition.Should().Be(4.42.Percent()); - } - - [Test] - public void _amount() - { - var addition = (Amount)44.6 * 80.Percent(); - addition.Should().Be((Amount)35.68); - } - - [Test] - public void _money() - { - var addition = (44.6 + Currency.EUR) * 80.Percent(); - addition.Should().Be(35.68 + Currency.EUR); - } - - [Test] - public void _decimal() - { - var addition = 34.586m * 75.Percent(); - addition.Should().Be(25.9395m); - } - - [Test] - public void _double() - { - var addition = 34.586 * 75.Percent(); - Assert.That(addition, Is.EqualTo(25.9395).Within(0.00001)); - } - - [Test] - public void _float() - { - var addition = 34.586f * 75.Percent(); - Assert.That(addition, Is.EqualTo(25.9395f).Within(0.00001)); - } - - [Test] - public void _int() - { - var addition = 400 * 17.Percent(); - addition.Should().Be(68); - } - - [Test] - public void _uint() - { - var addition = 400U * 17.Percent(); - addition.Should().Be(68U); - } - - [Test] - public void _long() - { - var addition = 400L * 17.Percent(); - addition.Should().Be(68L); - } - - [Test] - public void _ulong() - { - var addition = 400UL * 17.Percent(); - addition.Should().Be(68UL); - } - - [Test] - public void _short() - { - var addition = ((short)400) * 17.Percent(); - addition.Should().Be((short)68); - } - - [Test] - public void _ushort() - { - var addition = ((ushort)400) * 17.Percent(); - addition.Should().Be((ushort)68); - } + [Test] + public void _percentage() + { + var addition = 13.Percent() * 34.Percent(); + addition.Should().Be(4.42.Percent()); + } + + [Test] + public void _amount() + { + var addition = (Amount)44.6 * 80.Percent(); + addition.Should().Be((Amount)35.68); + } + + [Test] + public void _money() + { + var addition = (44.6 + Currency.EUR) * 80.Percent(); + addition.Should().Be(35.68 + Currency.EUR); + } + + [Test] + public void _decimal() + { + var addition = 34.586m * 75.Percent(); + addition.Should().Be(25.9395m); + } + + [Test] + public void _double() + { + var addition = 34.586 * 75.Percent(); + Assert.That(addition, Is.EqualTo(25.9395).Within(0.00001)); + } + + [Test] + public void _float() + { + var addition = 34.586f * 75.Percent(); + Assert.That(addition, Is.EqualTo(25.9395f).Within(0.00001)); + } + + [Test] + public void _int() + { + var addition = 400 * 17.Percent(); + addition.Should().Be(68); + } + + [Test] + public void _uint() + { + var addition = 400U * 17.Percent(); + addition.Should().Be(68U); + } + + [Test] + public void _long() + { + var addition = 400L * 17.Percent(); + addition.Should().Be(68L); + } + + [Test] + public void _ulong() + { + var addition = 400UL * 17.Percent(); + addition.Should().Be(68UL); + } + + [Test] + public void _short() + { + var addition = ((short)400) * 17.Percent(); + addition.Should().Be((short)68); + } + + [Test] + public void _ushort() + { + var addition = ((ushort)400) * 17.Percent(); + addition.Should().Be((ushort)68); + } } public class Can_get_100_percent_based_on_percentage { - [Test] - public void _percentage() - { - var addition = 13.Percent() / 25.Percent(); - addition.Should().Be(52.Percent()); - } - - [Test] - public void _amount() - { - var addition = (Amount)44.6 / 80.Percent(); - addition.Should().Be((Amount)55.75); - } - - [Test] - public void _money() - { - var addition = (44.6 + Currency.EUR) / 80.Percent(); - addition.Should().Be(55.75 + Currency.EUR); - } - - [Test] - public void _decimal() - { - var addition = 34.586m / 75.Percent(); - Assert.That(addition, Is.EqualTo(46.11467m).Within(0.00001)); - } - - [Test] - public void _double() - { - var addition = 34.586 / 75.Percent(); - Assert.That(addition, Is.EqualTo(46.11467).Within(0.00001)); - } - - [Test] - public void _float() - { - var addition = 34.586f / 75.Percent(); - Assert.That(addition, Is.EqualTo(46.11467f).Within(0.00001)); - } - - [Test] - public void _int() - { - var addition = 400 / 17.Percent(); - addition.Should().Be(2352); - } - - [Test] - public void _uint() - { - var addition = 400U / 17.Percent(); - addition.Should().Be(2352U); - } - - [Test] - public void _long() - { - var addition = 400L / 17.Percent(); - addition.Should().Be(2352L); - } - - [Test] - public void _ulong() - { - var addition = 400UL / 17.Percent(); - addition.Should().Be(2352UL); - } - - [Test] - public void _short() - { - var addition = ((short)400) / 17.Percent(); - addition.Should().Be((short)2352); - } - - [Test] - public void _ushort() - { - var addition = ((ushort)400) / 17.Percent(); - addition.Should().Be((ushort)2352); - } + [Test] + public void _percentage() + { + var addition = 13.Percent() / 25.Percent(); + addition.Should().Be(52.Percent()); + } + + [Test] + public void _amount() + { + var addition = (Amount)44.6 / 80.Percent(); + addition.Should().Be((Amount)55.75); + } + + [Test] + public void _money() + { + var addition = (44.6 + Currency.EUR) / 80.Percent(); + addition.Should().Be(55.75 + Currency.EUR); + } + + [Test] + public void _decimal() + { + var addition = 34.586m / 75.Percent(); + Assert.That(addition, Is.EqualTo(46.11467m).Within(0.00001)); + } + + [Test] + public void _double() + { + var addition = 34.586 / 75.Percent(); + Assert.That(addition, Is.EqualTo(46.11467).Within(0.00001)); + } + + [Test] + public void _float() + { + var addition = 34.586f / 75.Percent(); + Assert.That(addition, Is.EqualTo(46.11467f).Within(0.00001)); + } + + [Test] + public void _int() + { + var addition = 400 / 17.Percent(); + addition.Should().Be(2352); + } + + [Test] + public void _uint() + { + var addition = 400U / 17.Percent(); + addition.Should().Be(2352U); + } + + [Test] + public void _long() + { + var addition = 400L / 17.Percent(); + addition.Should().Be(2352L); + } + + [Test] + public void _ulong() + { + var addition = 400UL / 17.Percent(); + addition.Should().Be(2352UL); + } + + [Test] + public void _short() + { + var addition = ((short)400) / 17.Percent(); + addition.Should().Be((short)2352); + } + + [Test] + public void _ushort() + { + var addition = ((ushort)400) / 17.Percent(); + addition.Should().Be((ushort)2352); + } } public class Can_be_rounded { - [Test] - public void zero_decimals() - { - var actual = Svo.Percentage.Round(); - actual.Should().Be(18.Percent()); - } - - [Test] - public void one_decimal() - { - var actual = Svo.Percentage.Round(1); - actual.Should().Be(17.5.Percent()); - } - - [Test] - public void away_from_zero() - { - var actual = 16.5.Percent().Round(0, DecimalRounding.AwayFromZero); - actual.Should().Be(17.Percent()); - } - - [Test] - public void to_even() - { - var actual = 16.5.Percent().Round(0, DecimalRounding.ToEven); - actual.Should().Be(16.Percent()); - } - - [Test] - public void to_multiple() - { - var actual = 16.4.Percent().RoundToMultiple(3.Percent()); - actual.Should().Be(15.Percent()); - } - - [TestCase(27)] - [TestCase(28)] - public void up_to_26_digits(int decimals) - => decimals.Invoking(Svo.Percentage.Round) - .Should().Throw() - .WithMessage("Percentages can only round to between -26 and 26 digits of precision.*"); - - [Test] - public void up_to_minus_26_digits() - { - Assert.Throws(() => Svo.Percentage.Round(-27)); - } - - [Test, Obsolete("Only exists for guidance towards decimal rounding methods.")] - public void using_system_midpoint_rounding() - { - var rounded = Svo.Percentage.Round(0, MidpointRounding.AwayFromZero); - rounded.Should().Be(18.Percent()); - } + [Test] + public void zero_decimals() + { + var actual = Svo.Percentage.Round(); + actual.Should().Be(18.Percent()); + } + + [Test] + public void one_decimal() + { + var actual = Svo.Percentage.Round(1); + actual.Should().Be(17.5.Percent()); + } + + [Test] + public void away_from_zero() + { + var actual = 16.5.Percent().Round(0, DecimalRounding.AwayFromZero); + actual.Should().Be(17.Percent()); + } + + [Test] + public void to_even() + { + var actual = 16.5.Percent().Round(0, DecimalRounding.ToEven); + actual.Should().Be(16.Percent()); + } + + [Test] + public void to_multiple() + { + var actual = 16.4.Percent().RoundToMultiple(3.Percent()); + actual.Should().Be(15.Percent()); + } + + [TestCase(27)] + [TestCase(28)] + public void up_to_26_digits(int decimals) + => decimals.Invoking(Svo.Percentage.Round) + .Should().Throw() + .WithMessage("Percentages can only round to between -26 and 26 digits of precision.*"); + + [Test] + public void up_to_minus_26_digits() + { + Assert.Throws(() => Svo.Percentage.Round(-27)); + } + + [Test, Obsolete("Only exists for guidance towards decimal rounding methods.")] + public void using_system_midpoint_rounding() + { + var rounded = Svo.Percentage.Round(0, MidpointRounding.AwayFromZero); + rounded.Should().Be(18.Percent()); + } } public class Can_be_increased { - [Test] - public void with_1_percent() - { - var increased = Svo.Percentage; - increased++; - increased.Should().Be(18.51.Percent()); - } + [Test] + public void with_1_percent() + { + var increased = Svo.Percentage; + increased++; + increased.Should().Be(18.51.Percent()); + } } public class Can_be_decreased { - [Test] - public void with_1_percent() - { - var decreased = Svo.Percentage; - decreased--; - decreased.Should().Be(16.51.Percent()); - } + [Test] + public void with_1_percent() + { + var decreased = Svo.Percentage; + decreased--; + decreased.Should().Be(16.51.Percent()); + } } public class Can_be_negated { - [TestCase("17.51%", "-17.51%")] - [TestCase("-17.51%", "17.51%")] - public void negate(Percentage negated, Percentage input) - => (-input).Should().Be(negated); + [TestCase("17.51%", "-17.51%")] + [TestCase("-17.51%", "17.51%")] + public void negate(Percentage negated, Percentage input) + => (-input).Should().Be(negated); } public class Can_be_plussed { - [TestCase("-17.51%", "-17.51%")] - [TestCase("17.51%", "17.51%")] - public void plus(Percentage plussed, Percentage input) - => (+input).Should().Be(plussed); + [TestCase("-17.51%", "-17.51%")] + [TestCase("17.51%", "17.51%")] + public void plus(Percentage plussed, Percentage input) + => (+input).Should().Be(plussed); } public class Can_get { - [TestCase(-1, "-3%")] - [TestCase(0, "0%")] - [TestCase(+1, "10%")] - public void Sign(int expected, Percentage percentage) - { - var actual = percentage.Sign(); - actual.Should().Be(expected); - } - - [TestCase("3%", "-3%")] - [TestCase("0%", "0%")] - [TestCase("10%", "10%")] - public void absolute_value(Percentage expected, Percentage percentage) - { - var actual = percentage.Abs(); - actual.Should().Be(expected); - } + [TestCase(-1, "-3%")] + [TestCase(0, "0%")] + [TestCase(+1, "10%")] + public void Sign(int expected, Percentage percentage) + { + var actual = percentage.Sign(); + actual.Should().Be(expected); + } + + [TestCase("3%", "-3%")] + [TestCase("0%", "0%")] + [TestCase("10%", "10%")] + public void absolute_value(Percentage expected, Percentage percentage) + { + var actual = percentage.Abs(); + actual.Should().Be(expected); + } } public class Can_get_maximum_of { - [TestCase("12%", "12%", "5%")] - [TestCase("15%", "5%", "15%")] - [TestCase("12%", "12%", "12%")] - public void two_values(Percentage max, Percentage p0, Percentage p1) - => Percentage.Max(p0, p1).Should().Be(max); - - [Test] - public void multiple_values() - { - var max = Percentage.Max(15.Percent(), 66.Percent(), -117.Percent()); - max.Should().Be(66.Percent()); - } + [TestCase("12%", "12%", "5%")] + [TestCase("15%", "5%", "15%")] + [TestCase("12%", "12%", "12%")] + public void two_values(Percentage max, Percentage p0, Percentage p1) + => Percentage.Max(p0, p1).Should().Be(max); + + [Test] + public void multiple_values() + { + var max = Percentage.Max(15.Percent(), 66.Percent(), -117.Percent()); + max.Should().Be(66.Percent()); + } } public class Can_get_minimum_of { - [TestCase("5%", "12%", "5%")] - [TestCase("5%", "5%", "15%")] - [TestCase("5%", "5%", "5%")] - public void two_values(Percentage min, Percentage p0, Percentage p1) - => Percentage.Min(p0, p1).Should().Be(min); - - [Test] - public void multiple_values() - { - var min = Percentage.Min(15.Percent(), 66.Percent(), -117.Percent()); - min.Should().Be(-117.Percent()); - } + [TestCase("5%", "12%", "5%")] + [TestCase("5%", "5%", "15%")] + [TestCase("5%", "5%", "5%")] + public void two_values(Percentage min, Percentage p0, Percentage p1) + => Percentage.Min(p0, p1).Should().Be(min); + + [Test] + public void multiple_values() + { + var min = Percentage.Min(15.Percent(), 66.Percent(), -117.Percent()); + min.Should().Be(-117.Percent()); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(Percentage).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(Percentage.Zero); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("17.51%").To().Should().Be(Svo.Percentage); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.Percentage).Should().Be("17.51%"); - } - } - - [Test] - public void from_int() - => Converting.From(-17).To().Should().Be(-1700.Percent()); - - [Test] - public void to_int() - => Converting.To().From(1700.Percent()).Should().Be(17); - - [Test] - public void from_decimal() - => Converting.From(0.1751m).To().Should().Be(Svo.Percentage); - - [Test] - public void to_decimal() - => Converting.To().From(Svo.Percentage).Should().Be(0.1751m); - - [Test] - public void from_double() - => Converting.From(0.1751).To().Should().Be(Svo.Percentage); - - [Test] - public void to_double() - => Converting.To().From(Svo.Percentage).Should().Be(0.1751); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(Percentage).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(Percentage.Zero); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("17.51%").To().Should().Be(Svo.Percentage); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.Percentage).Should().Be("17.51%"); + } + } + + [Test] + public void from_int() + => Converting.From(-17).To().Should().Be(-1700.Percent()); + + [Test] + public void to_int() + => Converting.To().From(1700.Percent()).Should().Be(17); + + [Test] + public void from_decimal() + => Converting.From(0.1751m).To().Should().Be(Svo.Percentage); + + [Test] + public void to_decimal() + => Converting.To().From(Svo.Percentage).Should().Be(0.1751m); + + [Test] + public void from_double() + => Converting.From(0.1751).To().Should().Be(Svo.Percentage); + + [Test] + public void to_double() + => Converting.To().From(Svo.Percentage).Should().Be(0.1751); } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase("17.51", "17.51%")] - [TestCase("175.1‰", "17.51%")] - [TestCase(0.1751, "17.51%")] - [TestCase(1L, "100%")] - public void System_Text_JSON_deserialization(object json, Percentage svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase("17.51%", "17.51%")] - public void System_Text_JSON_serialization(Percentage svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase("17.51", "17.51%")] + [TestCase("175.1‰", "17.51%")] + [TestCase(0.1751, "17.51%")] + [TestCase(1L, "100%")] + public void System_Text_JSON_deserialization(object json, Percentage svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase("17.51%", "17.51%")] + public void System_Text_JSON_serialization(Percentage svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("17.51", "17.51%")] - [TestCase("175.1‰", "17.51%")] - [TestCase(0.1751, "17.51%")] - public void convention_based_deserialization(object json, Percentage svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase("17.51%", "17.51%")] - public void convention_based_serialization(Percentage svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("17.51", "17.51%")] + [TestCase("175.1‰", "17.51%")] + [TestCase(0.1751, "17.51%")] + public void convention_based_deserialization(object json, Percentage svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase("17.51%", "17.51%")] + public void convention_based_serialization(Percentage svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.Percentage); - xml.Should().Be("17.51%"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("17.51%"); - svo.Should().Be(Svo.Percentage); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.Percentage); - round_tripped.Should().Be(Svo.Percentage); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.Percentage); - var round_tripped = SerializeDeserialize.Xml(structure); - round_tripped.Should().Be(structure); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.Percentage; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.Percentage); + xml.Should().Be("17.51%"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("17.51%"); + svo.Should().Be(Svo.Percentage); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.Percentage); + round_tripped.Should().Be(Svo.Percentage); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.Percentage); + var round_tripped = SerializeDeserialize.Xml(structure); + round_tripped.Should().Be(structure); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.Percentage; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Percentage)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(Percentage), - description: "Ratio expressed as a fraction of 100 denoted using the percent sign '%'.", - type: "string", - example: "13.76%", - format: "percentage", - pattern: @"-?[0-9]+(\.[0-9]+)?%")); - - [TestCase("17.51%")] - [TestCase("-4.1%")] - [TestCase("-0.1%")] - [TestCase("31%")] - public void pattern_matches(string input) - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Percentage))!.Matches(input).Should().BeTrue(); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Percentage)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(Percentage), + description: "Ratio expressed as a fraction of 100 denoted using the percent sign '%'.", + type: "string", + example: "13.76%", + format: "percentage", + pattern: @"-?[0-9]+(\.[0-9]+)?%")); + + [TestCase("17.51%")] + [TestCase("-4.1%")] + [TestCase("-0.1%")] + [TestCase("31%")] + public void pattern_matches(string input) + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Percentage))!.Matches(input).Should().BeTrue(); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Percentage); - round_tripped.Should().Be(Svo.Percentage); - } - - [Test] - public void storing_decimal_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Percentage); - info.GetDecimal("Value").Should().Be(0.1751m); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Percentage); + round_tripped.Should().Be(Svo.Percentage); + } + + [Test] + public void storing_decimal_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Percentage); + info.GetDecimal("Value").Should().Be(0.1751m); + } } #endif public class Debugger { - [TestCase("17.51%", "17.51%")] - public void has_custom_display(object display, Percentage svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("17.51%", "17.51%")] + public void has_custom_display(object display, Percentage svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Reflection/QowaivType_specs.cs b/specs/Qowaiv.Specs/Reflection/QowaivType_specs.cs index 40bd8f19..f9293961 100644 --- a/specs/Qowaiv.Specs/Reflection/QowaivType_specs.cs +++ b/specs/Qowaiv.Specs/Reflection/QowaivType_specs.cs @@ -7,20 +7,20 @@ public class NullOrDefault { [Test] public void Is_true_for_null() - => Assert.That(QowaivType.IsNullOrDefaultValue(null), Is.True); + => QowaivType.IsNullOrDefaultValue(null).Should().BeTrue(); [Test] public void Is_true_for_default_primitive() - => Assert.That(QowaivType.IsNullOrDefaultValue(0), Is.True); + => QowaivType.IsNullOrDefaultValue(0).Should().BeTrue(); [Test] public void Is_false_for_object() - => Assert.That(QowaivType.IsNullOrDefaultValue(new object()), Is.False); + => QowaivType.IsNullOrDefaultValue(new object()).Should().BeFalse(); [Test] public void Is_false_for_non_default_primitive() - => Assert.That(QowaivType.IsNullOrDefaultValue(17), Is.False); + => QowaivType.IsNullOrDefaultValue(17).Should().BeFalse(); } public class IsNullable @@ -28,11 +28,11 @@ public class IsNullable [TestCase(typeof(string))] [TestCase(typeof(int))] public void False_for_not_nullable(Type type) - => Assert.That(QowaivType.IsNullable(type), Is.False); + => QowaivType.IsNullable(type).Should().BeFalse(); [Test] public void True_for_nullable() - => Assert.That(QowaivType.IsNullable(typeof(int?)), Is.True); + => QowaivType.IsNullable(typeof(int?)).Should().BeTrue(); } public class NotNullableType @@ -63,7 +63,7 @@ public class IsNumeric [TestCase(typeof(double))] [TestCase(typeof(decimal))] public void Is_true_for_primitive_numerics(Type type) - => Assert.That(QowaivType.IsNumeric(type), Is.True); + => QowaivType.IsNumeric(type).Should().BeTrue(); [TestCase(typeof(object))] [TestCase(typeof(string))] @@ -73,7 +73,7 @@ public void Is_true_for_primitive_numerics(Type type) [TestCase(typeof(Amount))] [TestCase(typeof(BigInteger))] public void Is_false_for_all_other_types(Type type) - => Assert.That(QowaivType.IsNumeric(type), Is.False); + => QowaivType.IsNumeric(type).Should().BeFalse(); } public class IsDate { @@ -83,7 +83,7 @@ public class IsDate [TestCase(typeof(Date))] [TestCase(typeof(WeekDate))] public void Is_true_for_DateTime_and_Qowaiv_DateTypes(Type type) - => Assert.That(QowaivType.IsDate(type), Is.True); + => QowaivType.IsDate(type).Should().BeTrue(); [TestCase(typeof(object))] [TestCase(typeof(string))] @@ -93,5 +93,5 @@ public void Is_true_for_DateTime_and_Qowaiv_DateTypes(Type type) [TestCase(typeof(Amount))] [TestCase(typeof(BigInteger))] public void Is_false_for_all_other_types(Type type) - => Assert.That(QowaivType.IsDate(type), Is.False); + => QowaivType.IsDate(type).Should().BeFalse(); } diff --git a/specs/Qowaiv.Specs/Sex_specs.cs b/specs/Qowaiv.Specs/Sex_specs.cs index 7d62b691..56d401da 100644 --- a/specs/Qowaiv.Specs/Sex_specs.cs +++ b/specs/Qowaiv.Specs/Sex_specs.cs @@ -2,476 +2,474 @@ public class With_domain_logic { - [TestCase(true, "Male")] - [TestCase(true, "Female")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, Sex svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, "Male")] - [TestCase(true, "Female")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, Sex svo) => svo.IsKnown.Should().Be(result); - - [TestCase(false, "Male")] - [TestCase(false, "Female")] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, Sex svo) - => svo.IsEmpty().Should().Be(result); - - [TestCase(false, "Male")] - [TestCase(false, "Female")] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, Sex svo) - => svo.IsEmptyOrUnknown().Should().Be(result); - - [TestCase(false, "Male")] - [TestCase(false, "Female")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, Sex svo) - { - svo.IsUnknown().Should().Be(result); - } - - [TestCase(true, "Male")] - [TestCase(true, "Female")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsMaleOrFemale_returns(bool result, Sex svo) - { - svo.IsMaleOrFemale().Should().Be(result); - } + [TestCase(true, "Male")] + [TestCase(true, "Female")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, Sex svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, "Male")] + [TestCase(true, "Female")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, Sex svo) => svo.IsKnown.Should().Be(result); + + [TestCase(false, "Male")] + [TestCase(false, "Female")] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, Sex svo) + => svo.IsEmpty().Should().Be(result); + + [TestCase(false, "Male")] + [TestCase(false, "Female")] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, Sex svo) + => svo.IsEmptyOrUnknown().Should().Be(result); + + [TestCase(false, "Male")] + [TestCase(false, "Female")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, Sex svo) + { + svo.IsUnknown().Should().Be(result); + } + + [TestCase(true, "Male")] + [TestCase(true, "Female")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsMaleOrFemale_returns(bool result, Sex svo) + { + svo.IsMaleOrFemale().Should().Be(result); + } } public class Display_name { - [Test] - public void for_current_culture_by_default() - { - using (TestCultures.nl_BE.Scoped()) - { - Svo.Sex.DisplayName.Should().Be("Vrouwelijk"); - } - } - - [Test] - public void for_custom_culture_if_specified() - { - Svo.Sex.GetDisplayName(TestCultures.es_EC).Should().Be("Mujer"); - } + [Test] + public void for_current_culture_by_default() + { + using (TestCultures.nl_BE.Scoped()) + { + Svo.Sex.DisplayName.Should().Be("Vrouwelijk"); + } + } + + [Test] + public void for_custom_culture_if_specified() + { + Svo.Sex.GetDisplayName(TestCultures.es_EC).Should().Be("Mujer"); + } } public class Has_constant { - [Test] - public void Empty_represent_default_value() - { - Sex.Empty.Should().Be(default); - } + [Test] + public void Empty_represent_default_value() + { + Sex.Empty.Should().Be(default); + } } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - => Svo.Sex.Equals(null).Should().BeFalse(); - - [Test] - public void not_equal_to_other_type() - => Svo.Sex.Equals(new object()).Should().BeFalse(); - - [Test] - public void not_equal_to_different_value() - => Svo.Sex.Equals(Sex.Male).Should().BeFalse(); - - [Test] - public void equal_to_same_value() - => Svo.Sex.Equals(Sex.Female).Should().BeTrue(); - - [Test] - public void equal_operator_returns_true_for_same_values() - => (Svo.Sex == Sex.Female).Should().BeTrue(); - - [Test] - public void equal_operator_returns_false_for_different_values() - => (Svo.Sex == Sex.Male).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_false_for_same_values() - => (Svo.Sex != Sex.Female).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_true_for_different_values() - => (Svo.Sex != Sex.Male).Should().BeTrue(); - - [TestCase("", 0)] - [TestCase("Male", 665630161)] - [TestCase("Female", 665630167)] - public void hash_code_is_value_based(Sex svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + => Svo.Sex.Equals(null).Should().BeFalse(); + + [Test] + public void not_equal_to_other_type() + => Svo.Sex.Equals(new object()).Should().BeFalse(); + + [Test] + public void not_equal_to_different_value() + => Svo.Sex.Equals(Sex.Male).Should().BeFalse(); + + [Test] + public void equal_to_same_value() + => Svo.Sex.Equals(Sex.Female).Should().BeTrue(); + + [Test] + public void equal_operator_returns_true_for_same_values() + => (Svo.Sex == Sex.Female).Should().BeTrue(); + + [Test] + public void equal_operator_returns_false_for_different_values() + => (Svo.Sex == Sex.Male).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_false_for_same_values() + => (Svo.Sex != Sex.Female).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_true_for_different_values() + => (Svo.Sex != Sex.Male).Should().BeTrue(); + + [TestCase("", 0)] + [TestCase("Male", 665630161)] + [TestCase("Female", 665630167)] + public void hash_code_is_value_based(Sex svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - => Sex.Parse(null).Should().Be(Sex.Empty); - - [Test] - public void from_empty_string_represents_Empty() - => Sex.Parse(string.Empty).Should().Be(Sex.Empty); - - [Test] - public void from_question_mark_represents_Unknown() - => Sex.Parse("?").Should().Be(Sex.Unknown); - - [TestCase("en", "Female")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - Sex.Parse(input).Should().Be(Svo.Sex); - } - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - Func parse = () => Sex.Parse("invalid input"); - parse.Should().Throw() - .WithMessage("Not a valid sex"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - => (Sex.TryParse("invalid input", out _)).Should().BeFalse(); - - [Test] - public void from_invalid_as_empty_with_TryParse() - => Sex.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - => Sex.TryParse("Female").Should().Be(Svo.Sex); + [Test] + public void from_null_string_represents_Empty() + => Sex.Parse(null).Should().Be(Sex.Empty); + + [Test] + public void from_empty_string_represents_Empty() + => Sex.Parse(string.Empty).Should().Be(Sex.Empty); + + [Test] + public void from_question_mark_represents_Unknown() + => Sex.Parse("?").Should().Be(Sex.Unknown); + + [TestCase("en", "Female")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + Sex.Parse(input).Should().Be(Svo.Sex); + } + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + Func parse = () => Sex.Parse("invalid input"); + parse.Should().Throw() + .WithMessage("Not a valid sex"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + => (Sex.TryParse("invalid input", out _)).Should().BeFalse(); + + [Test] + public void from_invalid_as_empty_with_TryParse() + => Sex.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + => Sex.TryParse("Female").Should().Be(Svo.Sex); } public class Has_custom_formatting { - [Test] - public void _default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Sex.ToString().Should().Be("Female"); - } - } - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Sex.ToString(default(string)).Should().Be(Svo.Sex.ToString()); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.Sex.ToString(string.Empty).Should().Be(Svo.Sex.ToString()); - } - } - - [Test] - public void default_value_is_represented_as_string_empty() - { - default(Sex).ToString().Should().Be(string.Empty); - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.Sex.ToString("s", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: '♀', format: 's'"); - } - - [TestCase("en-GB", null, "Female", "Female")] - [TestCase("en-GB", "c", "Female", "F")] - [TestCase("ru-RU", "s", "Female", "♀")] - [TestCase("nl-BE", "i", "Female", "2")] - [TestCase("nl-BE", "h", "Female", "Mevr.")] - [TestCase("nl-BE", "f", "Female", "Vrouwelijk")] - public void culture_dependent(CultureInfo culture, string format, Sex svo, string expected) - { - using (culture.Scoped()) - { - svo.ToString(format).Should().Be(expected); - } - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) - { - Svo.Sex.ToString(provider: null).Should().Be("Vrouwelijk"); - } - } + [Test] + public void _default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Sex.ToString().Should().Be("Female"); + } + } + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Sex.ToString(default(string)).Should().Be(Svo.Sex.ToString()); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.Sex.ToString(string.Empty).Should().Be(Svo.Sex.ToString()); + } + } + + [Test] + public void default_value_is_represented_as_string_empty() + { + default(Sex).ToString().Should().Be(string.Empty); + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.Sex.ToString("s", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: '♀', format: 's'"); + } + + [TestCase("en-GB", null, "Female", "Female")] + [TestCase("en-GB", "c", "Female", "F")] + [TestCase("ru-RU", "s", "Female", "♀")] + [TestCase("nl-BE", "i", "Female", "2")] + [TestCase("nl-BE", "h", "Female", "Mevr.")] + [TestCase("nl-BE", "f", "Female", "Vrouwelijk")] + public void culture_dependent(CultureInfo culture, string format, Sex svo, string expected) + { + using (culture.Scoped()) + { + svo.ToString(format).Should().Be(expected); + } + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) + { + Svo.Sex.ToString(provider: null).Should().Be("Vrouwelijk"); + } + } } public class Is_comparable { - [Test] - public void to_null_is_1() - => Svo.Sex.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_Sex_as_object() - { - object obj = Svo.Sex; - Svo.Sex.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Sex_only() - { - Assert.Throws(() => Svo.Sex.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - default, - default, - Sex.Unknown, - Sex.Male, - Sex.Female, - }; - var list = new List { sorted[3], sorted[4], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() + => Svo.Sex.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_Sex_as_object() + { + object obj = Svo.Sex; + Svo.Sex.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Sex_only() + => new object().Invoking(Svo.Sex.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + default, + default, + Sex.Unknown, + Sex.Male, + Sex.Female, + }; + var list = new List { sorted[3], sorted[4], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Casts { - [Test] - public void explicitly_to_byte() - { - var casted = (byte)Svo.Sex; - casted.Should().Be((byte)2); - } - - [Test] - public void explicitly_to_int() - { - var casted = (int)Svo.Sex; - casted.Should().Be(2); - } - - [TestCase(2, "Female")] - [TestCase(null, "?")] - public void explicitly_to_nullable_int(int casted, Sex sex) - { - ((int?)sex).Should().Be(casted); - } - - [TestCase("Female", 2)] - [TestCase("", null)] - public void implicitly_from_nullable_int(Sex casted, int? value) - { - Sex sex = value; - sex.Should().Be(casted); - } - - [TestCase("Female", 2)] - [TestCase("?", 0)] - public void implicitly_from_int(Sex casted, int value) - { - Sex sex = value; - sex.Should().Be(casted); - } + [Test] + public void explicitly_to_byte() + { + var casted = (byte)Svo.Sex; + casted.Should().Be((byte)2); + } + + [Test] + public void explicitly_to_int() + { + var casted = (int)Svo.Sex; + casted.Should().Be(2); + } + + [TestCase(2, "Female")] + [TestCase(null, "?")] + public void explicitly_to_nullable_int(int casted, Sex sex) + { + ((int?)sex).Should().Be(casted); + } + + [TestCase("Female", 2)] + [TestCase("", null)] + public void implicitly_from_nullable_int(Sex casted, int? value) + { + Sex sex = value; + sex.Should().Be(casted); + } + + [TestCase("Female", 2)] + [TestCase("?", 0)] + public void implicitly_from_int(Sex casted, int value) + { + Sex sex = value; + sex.Should().Be(casted); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(Sex).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(Sex.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(Sex.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("Female").To().Should().Be(Svo.Sex); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.Sex).Should().Be("Female"); - } - } + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(Sex).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(Sex.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(Sex.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("Female").To().Should().Be(Svo.Sex); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.Sex).Should().Be("Female"); + } + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase("?", "?")] - [TestCase(null, null)] - [TestCase(2L, "Female")] - [TestCase(2d, "Female")] - [TestCase("Female", "Female")] - public void System_Text_JSON_deserialization(object json, Sex svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("Female", "Female")] - public void System_Text_JSON_serialization(Sex svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase("?", "?")] + [TestCase(null, null)] + [TestCase(2L, "Female")] + [TestCase(2d, "Female")] + [TestCase("Female", "Female")] + public void System_Text_JSON_deserialization(object json, Sex svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("Female", "Female")] + public void System_Text_JSON_serialization(Sex svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("?", "?")] - [TestCase(2L, "Female")] - [TestCase(2d, "Female")] - [TestCase("Female", "Female")] - public void convention_based_deserialization(object json, Sex svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("Female", "Female")] - public void convention_based_serialization(Sex svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - [TestCase(5L, typeof(ArgumentOutOfRangeException))] - [TestCase(long.MaxValue, typeof(ArgumentOutOfRangeException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("?", "?")] + [TestCase(2L, "Female")] + [TestCase(2d, "Female")] + [TestCase("Female", "Female")] + public void convention_based_deserialization(object json, Sex svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("Female", "Female")] + public void convention_based_serialization(Sex svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + [TestCase(5L, typeof(ArgumentOutOfRangeException))] + [TestCase(long.MaxValue, typeof(ArgumentOutOfRangeException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.Sex); - xml.Should().Be("Female"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("Female"); - Svo.Sex.Should().Be(svo); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.Sex); - Svo.Sex.Should().Be(round_tripped); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.Sex); - var round_tripped = SerializeDeserialize.Xml(structure); - structure.Should().Be(round_tripped); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.Sex; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.Sex); + xml.Should().Be("Female"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("Female"); + Svo.Sex.Should().Be(svo); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.Sex); + Svo.Sex.Should().Be(round_tripped); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.Sex); + var round_tripped = SerializeDeserialize.Xml(structure); + structure.Should().Be(round_tripped); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.Sex; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Sex)) - .Should().BeEquivalentTo(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(Sex), - description: "Sex as specified by ISO/IEC 5218.", - type: "string", - example: "female", - format: "sex", - @enum: new[] { "NotKnown", "Male", "Female", "NotApplicable" }, - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Sex)) + .Should().BeEquivalentTo(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(Sex), + description: "Sex as specified by ISO/IEC 5218.", + type: "string", + example: "female", + format: "sex", + @enum: new[] { "NotKnown", "Male", "Female", "NotApplicable" }, + nullable: true)); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Sex); - round_tripped.Should().Be(Svo.Sex); - } - - [Test] - public void storing_Byte_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Sex); - info.GetByte("Value").Should().Be((byte)4); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Sex); + round_tripped.Should().Be(Svo.Sex); + } + + [Test] + public void storing_Byte_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Sex); + info.GetByte("Value").Should().Be((byte)4); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("Not known", "?")] - [TestCase("Female", "Female")] - public void has_custom_display(object display, Sex svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("Not known", "?")] + [TestCase("Female", "Female")] + public void has_custom_display(object display, Sex svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Sustainability/Energy_label_specs.cs b/specs/Qowaiv.Specs/Sustainability/Energy_label_specs.cs index 1c91c388..40834c03 100644 --- a/specs/Qowaiv.Specs/Sustainability/Energy_label_specs.cs +++ b/specs/Qowaiv.Specs/Sustainability/Energy_label_specs.cs @@ -4,575 +4,575 @@ namespace Energy_label_specs; public class With_domain_logic { - [TestCase(true, "A++")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, EnergyLabel svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, "A++")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, EnergyLabel svo) => svo.IsKnown.Should().Be(result); - - [TestCase(false, "A++")] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, EnergyLabel svo) - => svo.IsEmpty().Should().Be(result); - - [TestCase(false, "A++")] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, EnergyLabel svo) - => svo.IsEmptyOrUnknown().Should().Be(result); - - [TestCase(false, "A++")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, EnergyLabel svo) - => svo.IsUnknown().Should().Be(result); - - [TestCase(-1)] - [TestCase(5)] - [TestCase(6)] - public void with_zero_to_four_plusses(int plusses) - => plusses.Invoking(_ => EnergyLabel.A(plusses)) - .Should().Throw(); + [TestCase(true, "A++")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, EnergyLabel svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, "A++")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, EnergyLabel svo) => svo.IsKnown.Should().Be(result); + + [TestCase(false, "A++")] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, EnergyLabel svo) + => svo.IsEmpty().Should().Be(result); + + [TestCase(false, "A++")] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, EnergyLabel svo) + => svo.IsEmptyOrUnknown().Should().Be(result); + + [TestCase(false, "A++")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, EnergyLabel svo) + => svo.IsUnknown().Should().Be(result); + + [TestCase(-1)] + [TestCase(5)] + [TestCase(6)] + public void with_zero_to_four_plusses(int plusses) + => plusses.Invoking(_ => EnergyLabel.A(plusses)) + .Should().Throw(); } public class Is_valid_for { - [Test] - public void whitespace() - => EnergyLabel.TryParse(" ").Should().NotBeNull(); - - [Test] - public void string_empty() - => EnergyLabel.TryParse(string.Empty).Should().NotBeNull(); - - [Test] - public void string_null() - => EnergyLabel.TryParse(null).Should().NotBeNull(); - - [TestCase("?")] - [TestCase("unknown")] - public void strings_representing_unknown(string input) - => EnergyLabel.TryParse(input).Should().NotBeNull(); - - [TestCase("g", "de")] - [TestCase("G", "de")] - [TestCase("F", "fr")] - [TestCase("E", "es")] - [TestCase("D", "nl")] - [TestCase("C", "nl")] - [TestCase("B", "nl")] - [TestCase("A", "nl")] - [TestCase("A+", "nl")] - [TestCase("A++", "nl")] - [TestCase("A+++", "nl")] - [TestCase("A++++", "nl")] - [TestCase("a++++", "pt")] - public void @string(string input, CultureInfo culture) - => EnergyLabel.TryParse(input, culture).Should().NotBeNull(); + [Test] + public void whitespace() + => EnergyLabel.TryParse(" ").Should().NotBeNull(); + + [Test] + public void string_empty() + => EnergyLabel.TryParse(string.Empty).Should().NotBeNull(); + + [Test] + public void string_null() + => EnergyLabel.TryParse(null).Should().NotBeNull(); + + [TestCase("?")] + [TestCase("unknown")] + public void strings_representing_unknown(string input) + => EnergyLabel.TryParse(input).Should().NotBeNull(); + + [TestCase("g", "de")] + [TestCase("G", "de")] + [TestCase("F", "fr")] + [TestCase("E", "es")] + [TestCase("D", "nl")] + [TestCase("C", "nl")] + [TestCase("B", "nl")] + [TestCase("A", "nl")] + [TestCase("A+", "nl")] + [TestCase("A++", "nl")] + [TestCase("A+++", "nl")] + [TestCase("A++++", "nl")] + [TestCase("a++++", "pt")] + public void @string(string input, CultureInfo culture) + => EnergyLabel.TryParse(input, culture).Should().NotBeNull(); } public class Is_not_valid_for { - [TestCase("H")] - [TestCase("I")] - public void H_and_lower(string label) - => EnergyLabel.TryParse(label).Should().BeNull(); - - [TestCase("G+")] - [TestCase("A+++++")] - [TestCase("A++++++")] - public void Plus_overload(string label) - => EnergyLabel.TryParse(label).Should().BeNull(); - - [Test] - public void garbage() - => EnergyLabel.TryParse("garbage").Should().BeNull(); + [TestCase("H")] + [TestCase("I")] + public void H_and_lower(string label) + => EnergyLabel.TryParse(label).Should().BeNull(); + + [TestCase("G+")] + [TestCase("A+++++")] + [TestCase("A++++++")] + public void Plus_overload(string label) + => EnergyLabel.TryParse(label).Should().BeNull(); + + [Test] + public void garbage() + => EnergyLabel.TryParse("garbage").Should().BeNull(); } public class Has_constant { - [Test] - public void Empty() => EnergyLabel.Empty.Should().Be(default); + [Test] + public void Empty() => EnergyLabel.Empty.Should().Be(default); - [Test] - public void A() => EnergyLabel.A().Should().Be(EnergyLabel.Parse("A")); + [Test] + public void A() => EnergyLabel.A().Should().Be(EnergyLabel.Parse("A")); - [Test] - public void A_plus([Range(1, 4)] int plus) => EnergyLabel.A(plus).Should().Be(EnergyLabel.Parse("A" + new string('+', plus))); + [Test] + public void A_plus([Range(1, 4)] int plus) => EnergyLabel.A(plus).Should().Be(EnergyLabel.Parse("A" + new string('+', plus))); - [Test] - public void B() => EnergyLabel.B.Should().Be(EnergyLabel.Parse("B")); + [Test] + public void B() => EnergyLabel.B.Should().Be(EnergyLabel.Parse("B")); - [Test] - public void C() => EnergyLabel.C.Should().Be(EnergyLabel.Parse("C")); + [Test] + public void C() => EnergyLabel.C.Should().Be(EnergyLabel.Parse("C")); - [Test] - public void D() => EnergyLabel.D.Should().Be(EnergyLabel.Parse("D")); + [Test] + public void D() => EnergyLabel.D.Should().Be(EnergyLabel.Parse("D")); - [Test] - public void E() => EnergyLabel.E.Should().Be(EnergyLabel.Parse("E")); + [Test] + public void E() => EnergyLabel.E.Should().Be(EnergyLabel.Parse("E")); - [Test] - public void F() => EnergyLabel.F.Should().Be(EnergyLabel.Parse("F")); + [Test] + public void F() => EnergyLabel.F.Should().Be(EnergyLabel.Parse("F")); - [Test] - public void G() => EnergyLabel.G.Should().Be(EnergyLabel.Parse("G")); + [Test] + public void G() => EnergyLabel.G.Should().Be(EnergyLabel.Parse("G")); - [Test] - public void Unknown() => EnergyLabel.Unknown.Should().Be(EnergyLabel.Parse("?")); + [Test] + public void Unknown() => EnergyLabel.Unknown.Should().Be(EnergyLabel.Parse("?")); } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - => Svo.EnergyLabel.Equals(null).Should().BeFalse(); - - [Test] - public void not_equal_to_other_type() - => Svo.EnergyLabel.Equals(new object()).Should().BeFalse(); - - [Test] - public void not_equal_to_different_value() - => Svo.EnergyLabel.Equals(EnergyLabel.G).Should().BeFalse(); - - [Test] - public void equal_to_same_value() - => Svo.EnergyLabel.Equals(EnergyLabel.A(2)).Should().BeTrue(); - - [Test] - public void equal_operator_returns_true_for_same_values() - => (Svo.EnergyLabel == EnergyLabel.A(2)).Should().BeTrue(); - - [Test] - public void equal_operator_returns_false_for_different_values() - => (Svo.EnergyLabel == EnergyLabel.G).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_false_for_same_values() - => (Svo.EnergyLabel != EnergyLabel.A(2)).Should().BeFalse(); - - [Test] - public void not_equal_operator_returns_true_for_different_values() - => (Svo.EnergyLabel != EnergyLabel.G).Should().BeTrue(); - - [TestCase("", 0)] - [TestCase("A++", 665630170)] - public void hash_code_is_value_based(EnergyLabel svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + => Svo.EnergyLabel.Equals(null).Should().BeFalse(); + + [Test] + public void not_equal_to_other_type() + => Svo.EnergyLabel.Equals(new object()).Should().BeFalse(); + + [Test] + public void not_equal_to_different_value() + => Svo.EnergyLabel.Equals(EnergyLabel.G).Should().BeFalse(); + + [Test] + public void equal_to_same_value() + => Svo.EnergyLabel.Equals(EnergyLabel.A(2)).Should().BeTrue(); + + [Test] + public void equal_operator_returns_true_for_same_values() + => (Svo.EnergyLabel == EnergyLabel.A(2)).Should().BeTrue(); + + [Test] + public void equal_operator_returns_false_for_different_values() + => (Svo.EnergyLabel == EnergyLabel.G).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_false_for_same_values() + => (Svo.EnergyLabel != EnergyLabel.A(2)).Should().BeFalse(); + + [Test] + public void not_equal_operator_returns_true_for_different_values() + => (Svo.EnergyLabel != EnergyLabel.G).Should().BeTrue(); + + [TestCase("", 0)] + [TestCase("A++", 665630170)] + public void hash_code_is_value_based(EnergyLabel svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - => EnergyLabel.Parse(null).Should().Be(EnergyLabel.Empty); - - [Test] - public void from_empty_string_represents_Empty() - => EnergyLabel.Parse(string.Empty).Should().Be(EnergyLabel.Empty); - - [Test] - public void from_question_mark_represents_Unknown() - => EnergyLabel.Parse("?").Should().Be(EnergyLabel.Unknown); - - [TestCase("en", "a++")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - EnergyLabel.Parse(input).Should().Be(Svo.EnergyLabel); - } - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - Func parse = () => EnergyLabel.Parse("invalid input"); - parse.Should().Throw() - .WithMessage("Not a valid energy label"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - => (EnergyLabel.TryParse("invalid input", out _)).Should().BeFalse(); - - [Test] - public void from_invalid_as_null_with_TryParse() - => EnergyLabel.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - => EnergyLabel.TryParse("A++").Should().Be(Svo.EnergyLabel); + [Test] + public void from_null_string_represents_Empty() + => EnergyLabel.Parse(null).Should().Be(EnergyLabel.Empty); + + [Test] + public void from_empty_string_represents_Empty() + => EnergyLabel.Parse(string.Empty).Should().Be(EnergyLabel.Empty); + + [Test] + public void from_question_mark_represents_Unknown() + => EnergyLabel.Parse("?").Should().Be(EnergyLabel.Unknown); + + [TestCase("en", "a++")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + EnergyLabel.Parse(input).Should().Be(Svo.EnergyLabel); + } + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + Func parse = () => EnergyLabel.Parse("invalid input"); + parse.Should().Throw() + .WithMessage("Not a valid energy label"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + => (EnergyLabel.TryParse("invalid input", out _)).Should().BeFalse(); + + [Test] + public void from_invalid_as_null_with_TryParse() + => EnergyLabel.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + => EnergyLabel.TryParse("A++").Should().Be(Svo.EnergyLabel); } public class Has_custom_formatting { - [TestCase("G")] - [TestCase("F")] - [TestCase("E")] - [TestCase("D")] - [TestCase("C")] - [TestCase("B")] - [TestCase("A")] - [TestCase("A+")] - [TestCase("A++")] - [TestCase("A+++")] - [TestCase("A++++")] - public void _default(string label) - => EnergyLabel.Parse(label).ToString().Should().Be(label); - - [Test] - public void with_null_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.EnergyLabel.ToString().Should().Be(Svo.EnergyLabel.ToString(default(string))); - } - } - - [Test] - public void with_string_empty_pattern_equal_to_default() - { - using (TestCultures.en_GB.Scoped()) - { - Svo.EnergyLabel.ToString().Should().Be(Svo.EnergyLabel.ToString(string.Empty)); - } - } - - [Test] - public void default_value_is_represented_as_string_empty() - => default(EnergyLabel).ToString().Should().BeEmpty(); - - [Test] - public void unknown_value_is_represented_as_unknown() - => EnergyLabel.Unknown.ToString().Should().Be("?"); - - [Test] - public void with_empty_format_provider() - { - using (TestCultures.es_EC.Scoped()) - { - Svo.EnergyLabel.ToString(FormatProvider.Empty).Should().Be("A++"); - } - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.EnergyLabel.ToString("SomeFormat", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: 'A++', format: 'SomeFormat'"); - } - - [TestCase(null, "A++", "A++")] - [TestCase("U", "B", "B")] - [TestCase("l", "G", "g")] - [TestCase("l", "A++", "a++")] - public void format_dependent(string format, EnergyLabel svo, string formatted) - => svo.ToString(format).Should().Be(formatted); + [TestCase("G")] + [TestCase("F")] + [TestCase("E")] + [TestCase("D")] + [TestCase("C")] + [TestCase("B")] + [TestCase("A")] + [TestCase("A+")] + [TestCase("A++")] + [TestCase("A+++")] + [TestCase("A++++")] + public void _default(string label) + => EnergyLabel.Parse(label).ToString().Should().Be(label); + + [Test] + public void with_null_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.EnergyLabel.ToString().Should().Be(Svo.EnergyLabel.ToString(default(string))); + } + } + + [Test] + public void with_string_empty_pattern_equal_to_default() + { + using (TestCultures.en_GB.Scoped()) + { + Svo.EnergyLabel.ToString().Should().Be(Svo.EnergyLabel.ToString(string.Empty)); + } + } + + [Test] + public void default_value_is_represented_as_string_empty() + => default(EnergyLabel).ToString().Should().BeEmpty(); + + [Test] + public void unknown_value_is_represented_as_unknown() + => EnergyLabel.Unknown.ToString().Should().Be("?"); + + [Test] + public void with_empty_format_provider() + { + using (TestCultures.es_EC.Scoped()) + { + Svo.EnergyLabel.ToString(FormatProvider.Empty).Should().Be("A++"); + } + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.EnergyLabel.ToString("SomeFormat", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: 'A++', format: 'SomeFormat'"); + } + + [TestCase(null, "A++", "A++")] + [TestCase("U", "B", "B")] + [TestCase("l", "G", "g")] + [TestCase("l", "A++", "a++")] + public void format_dependent(string format, EnergyLabel svo, string formatted) + => svo.ToString(format).Should().Be(formatted); #if NET6_0_OR_GREATER - public class Span_formattable - { - [Test] - public void Skips_custom_formatters() - { - Span span = stackalloc char[128]; - Svo.EnergyLabel.TryFormat(span, out int charsWritten, default, FormatProvider.CustomFormatter).Should().BeFalse(); - charsWritten.Should().Be(0); - } - - [Test] - public void formats_empty() => $"{EnergyLabel.Empty}".Should().BeEmpty(); - - [Test] - public void formats_unknown() => $"{EnergyLabel.Unknown}".Should().Be("?"); - - [Test] - public void formats_known() => $"{Svo.EnergyLabel:l}".Should().Be("a++"); - - [Test] - public void Skips_insufficient_span_sizes() - { - Span span = stackalloc char[2]; - Svo.EnergyLabel.TryFormat(span, out int charsWritten, default, TestCultures.nl_NL).Should().BeFalse(); - charsWritten.Should().Be(0); - } - } + public class Span_formattable + { + [Test] + public void Skips_custom_formatters() + { + Span span = stackalloc char[128]; + Svo.EnergyLabel.TryFormat(span, out int charsWritten, default, FormatProvider.CustomFormatter).Should().BeFalse(); + charsWritten.Should().Be(0); + } + + [Test] + public void formats_empty() => $"{EnergyLabel.Empty}".Should().BeEmpty(); + + [Test] + public void formats_unknown() => $"{EnergyLabel.Unknown}".Should().Be("?"); + + [Test] + public void formats_known() => $"{Svo.EnergyLabel:l}".Should().Be("a++"); + + [Test] + public void Skips_insufficient_span_sizes() + { + Span span = stackalloc char[2]; + Svo.EnergyLabel.TryFormat(span, out int charsWritten, default, TestCultures.nl_NL).Should().BeFalse(); + charsWritten.Should().Be(0); + } + } #endif } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.EnergyLabel.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_EnergyLabel_as_object() - { - object obj = Svo.EnergyLabel; - Svo.EnergyLabel.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_EnergyLabel_only() - => Assert.Throws(() => Svo.EnergyLabel.CompareTo(new object())); - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - default, - default, - EnergyLabel.F, - EnergyLabel.C, - EnergyLabel.A(), - EnergyLabel.Unknown, - }; - - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } - - [Test] - public void by_operators_for_different_values() - { - var smaller = EnergyLabel.B; - var bigger = EnergyLabel.A(2); - - (smaller < bigger).Should().BeTrue(); - (smaller <= bigger).Should().BeTrue(); - (smaller > bigger).Should().BeFalse(); - (smaller >= bigger).Should().BeFalse(); - } - - [Test] - public void by_operators_for_equal_values() - { - var left = EnergyLabel.A(2); - var right = EnergyLabel.A(2); - - (left < right).Should().BeFalse(); - (left <= right).Should().BeTrue(); - (left > right).Should().BeFalse(); - (left >= right).Should().BeTrue(); - } - - [TestCase("?", "A++")] - [TestCase("?", "")] - [TestCase("A++", "?")] - [TestCase("", "?")] - [TestCase("?", "?")] - public void by_operators_unknown_always_false(EnergyLabel l, EnergyLabel r) - { - (l < r).Should().BeFalse(); - (l <= r).Should().BeFalse(); - (l > r).Should().BeFalse(); - (l >= r).Should().BeFalse(); - } + [Test] + public void to_null_is_1() => Svo.EnergyLabel.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_EnergyLabel_as_object() + { + object obj = Svo.EnergyLabel; + Svo.EnergyLabel.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_EnergyLabel_only() + => new object().Invoking(Svo.EnergyLabel.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + default, + default, + EnergyLabel.F, + EnergyLabel.C, + EnergyLabel.A(), + EnergyLabel.Unknown, + }; + + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } + + [Test] + public void by_operators_for_different_values() + { + var smaller = EnergyLabel.B; + var bigger = EnergyLabel.A(2); + + (smaller < bigger).Should().BeTrue(); + (smaller <= bigger).Should().BeTrue(); + (smaller > bigger).Should().BeFalse(); + (smaller >= bigger).Should().BeFalse(); + } + + [Test] + public void by_operators_for_equal_values() + { + var left = EnergyLabel.A(2); + var right = EnergyLabel.A(2); + + (left < right).Should().BeFalse(); + (left <= right).Should().BeTrue(); + (left > right).Should().BeFalse(); + (left >= right).Should().BeTrue(); + } + + [TestCase("?", "A++")] + [TestCase("?", "")] + [TestCase("A++", "?")] + [TestCase("", "?")] + [TestCase("?", "?")] + public void by_operators_unknown_always_false(EnergyLabel l, EnergyLabel r) + { + (l < r).Should().BeFalse(); + (l <= r).Should().BeFalse(); + (l > r).Should().BeFalse(); + (l >= r).Should().BeFalse(); + } } public class Casts { - [Test] - public void explicitly_from_string() - { - var casted = (EnergyLabel)"A++"; - casted.Should().Be(Svo.EnergyLabel); - } - - [Test] - public void explicitly_to_string() - { - var casted = (string)Svo.EnergyLabel; - casted.Should().Be("A++"); - } + [Test] + public void explicitly_from_string() + { + var casted = (EnergyLabel)"A++"; + casted.Should().Be(Svo.EnergyLabel); + } + + [Test] + public void explicitly_to_string() + { + var casted = (string)Svo.EnergyLabel; + casted.Should().Be("A++"); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(EnergyLabel).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(EnergyLabel.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(EnergyLabel.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("A++").To().Should().Be(Svo.EnergyLabel); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.EnergyLabel).Should().Be("A++"); - } - } + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(EnergyLabel).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(EnergyLabel.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(EnergyLabel.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("A++").To().Should().Be(Svo.EnergyLabel); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.EnergyLabel).Should().Be("A++"); + } + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase("?", "?")] - [TestCase("C", "C")] - [TestCase("A++", "A++")] - public void System_Text_JSON_deserialization(object json, EnergyLabel svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase("?", "?")] - [TestCase("C", "C")] - [TestCase("A++", "A++")] - public void System_Text_JSON_serialization(EnergyLabel svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase("?", "?")] + [TestCase("C", "C")] + [TestCase("A++", "A++")] + public void System_Text_JSON_deserialization(object json, EnergyLabel svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase("?", "?")] + [TestCase("C", "C")] + [TestCase("A++", "A++")] + public void System_Text_JSON_serialization(EnergyLabel svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("?", "unknown")] - [TestCase("C", "C")] - [TestCase("A++", "A++")] - public void convention_based_deserialization(EnergyLabel svo, object json) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, "")] - [TestCase("C", "C")] - [TestCase("A++", "A++")] - public void convention_based_serialization(object json, EnergyLabel svo) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - [TestCase(5L, typeof(InvalidOperationException))] - public void throws_for_invalid_json(object json, Type exceptionType) - { - Func read = () => JsonTester.Read(json); - read.Should().Throw().Subject.Single().Should().BeOfType(exceptionType); - } + [TestCase("?", "unknown")] + [TestCase("C", "C")] + [TestCase("A++", "A++")] + public void convention_based_deserialization(EnergyLabel svo, object json) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, "")] + [TestCase("C", "C")] + [TestCase("A++", "A++")] + public void convention_based_serialization(object json, EnergyLabel svo) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + [TestCase(5L, typeof(InvalidOperationException))] + public void throws_for_invalid_json(object json, Type exceptionType) + { + Func read = () => JsonTester.Read(json); + read.Should().Throw().Subject.Single().Should().BeOfType(exceptionType); + } } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.EnergyLabel); - xml.Should().Be("A++"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("A++"); - svo.Should().Be(Svo.EnergyLabel); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.EnergyLabel); - Svo.EnergyLabel.Should().Be(round_tripped); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.EnergyLabel); - var round_tripped = SerializeDeserialize.Xml(structure); - structure.Should().Be(round_tripped); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.EnergyLabel; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.EnergyLabel); + xml.Should().Be("A++"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("A++"); + svo.Should().Be(Svo.EnergyLabel); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.EnergyLabel); + Svo.EnergyLabel.Should().Be(round_tripped); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.EnergyLabel); + var round_tripped = SerializeDeserialize.Xml(structure); + structure.Should().Be(round_tripped); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.EnergyLabel; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(EnergyLabel)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(EnergyLabel), - description: "EU energy label", - example: "A++", - type: "string", - format: "energy-label", - pattern: @"[A-H]|A\+{1,4}", - nullable: true)); - - [TestCase("G")] - [TestCase("B")] - [TestCase("A")] - [TestCase("A+")] - [TestCase("A++++")] - public void pattern_matches(string input) - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(EnergyLabel))!.Matches(input).Should().BeTrue(); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(EnergyLabel)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(EnergyLabel), + description: "EU energy label", + example: "A++", + type: "string", + format: "energy-label", + pattern: @"[A-H]|A\+{1,4}", + nullable: true)); + + [TestCase("G")] + [TestCase("B")] + [TestCase("A")] + [TestCase("A+")] + [TestCase("A++++")] + public void pattern_matches(string input) + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(EnergyLabel))!.Matches(input).Should().BeTrue(); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.EnergyLabel); - round_tripped.Should().Be(Svo.EnergyLabel); - } - - [Test] - public void storing_int_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.EnergyLabel); - info.GetInt32("Value").Should().Be(9); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.EnergyLabel); + round_tripped.Should().Be(Svo.EnergyLabel); + } + + [Test] + public void storing_int_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.EnergyLabel); + info.GetInt32("Value").Should().Be(9); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("{unknown}", "?")] - [TestCase("A++", "A++")] - public void has_custom_display(object display, EnergyLabel svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("{unknown}", "?")] + [TestCase("A++", "A++")] + public void has_custom_display(object display, EnergyLabel svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/UUID_specs.cs b/specs/Qowaiv.Specs/UUID_specs.cs index 4cf4e314..901d7024 100644 --- a/specs/Qowaiv.Specs/UUID_specs.cs +++ b/specs/Qowaiv.Specs/UUID_specs.cs @@ -2,646 +2,644 @@ public class With_domain_logic { - [TestCase(true, "Qowaiv_SVOLibrary_GUIA")] - [TestCase(false, "")] - public void HasValue_is(bool result, Uuid svo) => svo.HasValue.Should().Be(result); - - [TestCase(false, "Qowaiv_SVOLibrary_GUIA")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, Uuid svo) - { - svo.IsEmpty().Should().Be(result); - } + [TestCase(true, "Qowaiv_SVOLibrary_GUIA")] + [TestCase(false, "")] + public void HasValue_is(bool result, Uuid svo) => svo.HasValue.Should().Be(result); + + [TestCase(false, "Qowaiv_SVOLibrary_GUIA")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, Uuid svo) + { + svo.IsEmpty().Should().Be(result); + } } public class Has_version { - [Test] - public void Random_for_new() - { - var id = Uuid.NewUuid(); - id.Version.Should().Be(UuidVersion.Random); - } - - [Test] - public void Sequential_for_new_sequential() - { - var id = Uuid.NewSequential(); - id.Version.Should().Be(UuidVersion.Sequential); - } - - [Test] - public void MD5_for_generated_with_MD5() - { - var id = Uuid.GenerateWithMD5(Encoding.UTF8.GetBytes("Qowaiv")); - id.Version.Should().Be(UuidVersion.MD5); - } - - [Test] - public void SHA1_for_generated_with_SHA1() - { - var id = Uuid.GenerateWithSHA1(Encoding.UTF8.GetBytes("Qowaiv")); - id.Version.Should().Be(UuidVersion.SHA1); - } + [Test] + public void Random_for_new() + { + var id = Uuid.NewUuid(); + id.Version.Should().Be(UuidVersion.Random); + } + + [Test] + public void Sequential_for_new_sequential() + { + var id = Uuid.NewSequential(); + id.Version.Should().Be(UuidVersion.Sequential); + } + + [Test] + public void MD5_for_generated_with_MD5() + { + var id = Uuid.GenerateWithMD5(Encoding.UTF8.GetBytes("Qowaiv")); + id.Version.Should().Be(UuidVersion.MD5); + } + + [Test] + public void SHA1_for_generated_with_SHA1() + { + var id = Uuid.GenerateWithSHA1(Encoding.UTF8.GetBytes("Qowaiv")); + id.Version.Should().Be(UuidVersion.SHA1); + } } public class Has_constant { - [Test] - public void Empty_represent_default_value() - { - Uuid.Empty.Should().Be(default); - } + [Test] + public void Empty_represent_default_value() + { + Uuid.Empty.Should().Be(default); + } } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - { - Svo.Uuid.Equals(null).Should().BeFalse(); - } - - [Test] - public void not_equal_to_other_type() - { - Svo.Uuid.Equals(new object()).Should().BeFalse(); - } - - [Test] - public void not_equal_to_different_value() - { - Svo.Uuid.Equals(Uuid.Parse("6D775128-6365-4A96-BDE8-0972CE6CB0BC")).Should().BeFalse(); - } - - [Test] - public void equal_to_same_value() - { - Svo.Uuid.Equals(Uuid.Parse("Qowaiv_SVOLibrary_GUIA")).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_true_for_same_values() - { - (Svo.Uuid == Uuid.Parse("Qowaiv_SVOLibrary_GUIA")).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_false_for_different_values() - { - (Svo.Uuid == Uuid.Parse("6D775128-6365-4A96-BDE8-0972CE6CB0BC")).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_false_for_same_values() - { - (Svo.Uuid != Uuid.Parse("Qowaiv_SVOLibrary_GUIA")).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_true_for_different_values() - { - (Svo.Uuid != Uuid.Parse("6D775128-6365-4A96-BDE8-0972CE6CB0BC")).Should().BeTrue(); - } - - [TestCase("", 0)] - [TestCase("Qowaiv_SVOLibrary_GUIA", -994020281)] - public void hash_code_is_value_based(Uuid svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + { + Svo.Uuid.Equals(null).Should().BeFalse(); + } + + [Test] + public void not_equal_to_other_type() + { + Svo.Uuid.Equals(new object()).Should().BeFalse(); + } + + [Test] + public void not_equal_to_different_value() + { + Svo.Uuid.Equals(Uuid.Parse("6D775128-6365-4A96-BDE8-0972CE6CB0BC")).Should().BeFalse(); + } + + [Test] + public void equal_to_same_value() + { + Svo.Uuid.Equals(Uuid.Parse("Qowaiv_SVOLibrary_GUIA")).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_true_for_same_values() + { + (Svo.Uuid == Uuid.Parse("Qowaiv_SVOLibrary_GUIA")).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_false_for_different_values() + { + (Svo.Uuid == Uuid.Parse("6D775128-6365-4A96-BDE8-0972CE6CB0BC")).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_false_for_same_values() + { + (Svo.Uuid != Uuid.Parse("Qowaiv_SVOLibrary_GUIA")).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_true_for_different_values() + { + (Svo.Uuid != Uuid.Parse("6D775128-6365-4A96-BDE8-0972CE6CB0BC")).Should().BeTrue(); + } + + [TestCase("", 0)] + [TestCase("Qowaiv_SVOLibrary_GUIA", -994020281)] + public void hash_code_is_value_based(Uuid svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - { - Uuid.Parse(null).Should().Be(Uuid.Empty); - } - - [Test] - public void from_empty_string_represents_Empty() - { - Uuid.Parse(string.Empty).Should().Be(Uuid.Empty); - } - - public class from_GUID - { - [Test] - public void LowerCase() - => Uuid.Parse("8a1a8c42-d2ff-e254-e26e-b6abcbf19420").Should().Be(Svo.Uuid); - - [Test] - public void UpperCase() - => Uuid.Parse("8A1A8C42-D2FF-E254-E26E-B6ABCBF19420").Should().Be(Svo.Uuid); - - [Test] - public void With_brackets() - => Uuid.Parse("(8A1A8C42-D2FF-E254-E26E-B6ABCBF19420)").Should().Be(Svo.Uuid); - - [Test] - public void With_curly_brackets() - => Uuid.Parse("{8A1A8C42-D2FF-E254-E26E-B6ABCBF19420}").Should().Be(Svo.Uuid); - - [Test] - public void without_dashes() - => Uuid.Parse("8A1A8C42D2FFE254E26EB6ABCBF19420").Should().Be(Svo.Uuid); - } - - public class from_Base64 - { - [TestCase("Qowaiv_SVOLibrary_GUIA=")] - [TestCase("Qowaiv_SVOLibrary_GUIA==")] - public void with_equal_sign_suffix(string s) - => Uuid.Parse(s).Should().Be(Svo.Uuid); - - [Test] - public void with_under_scores_equvilent_to_forward_slashes() - => Uuid.Parse("Qowaiv/SVOLibrary/GUIA").Should().Be(Uuid.Parse("Qowaiv_SVOLibrary_GUIA")); - - [Test] - public void with_dashes_equvilent_to_plusses() - => Uuid.Parse("Qowaiv-SVOLibrary-GUIA").Should().Be(Uuid.Parse("Qowaiv+SVOLibrary+GUIA")); - } - - public class from_Base32 - { - [Test] - public void LowerCase() - => Uuid.Parse("ikgbvcx72jkofytow2v4x4muea").Should().Be(Svo.Uuid); - - [Test] - public void UpperCase() - => Uuid.Parse("IKGBVCX72JKOFYTOW2V4X4MUEA").Should().Be(Svo.Uuid); - - [Test] - public void with_0s_equivilent_to_Os() - => Uuid.Parse("IKGBVCX72JK0FYT0W2V4X4MUEA").Should().Be(Uuid.Parse("IKGBVCX72JKOFYTOW2V4X4MUEA")); - - [Test] - public void with_1s_equivilent_to_Is() - => Uuid.Parse("1KGBVCX72JKOFYTOW2V4X4MUEA").Should().Be(Uuid.Parse("IKGBVCX72JKOFYTOW2V4X4MUEA")); - } - - [TestCase("en", "Qowaiv_SVOLibrary_GUIA")] - [TestCase("en", "8A1A8C42-D2FF-E254-E26E-B6ABCBF19420")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - var parsed = Uuid.Parse(input); - parsed.Should().Be(Svo.Uuid); - } - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - "invalid input".Invoking(Uuid.Parse) - .Should().Throw() - .WithMessage("Not a valid GUID"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - { - Uuid.TryParse("invalid input", out _).Should().BeFalse(); - } - - [Test] - public void from_invalid_as_null_with_TryParse() - => Uuid.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - { - Uuid.TryParse("Qowaiv_SVOLibrary_GUIA").Should().Be(Svo.Uuid); - } + [Test] + public void from_null_string_represents_Empty() + { + Uuid.Parse(null).Should().Be(Uuid.Empty); + } + + [Test] + public void from_empty_string_represents_Empty() + { + Uuid.Parse(string.Empty).Should().Be(Uuid.Empty); + } + + public class from_GUID + { + [Test] + public void LowerCase() + => Uuid.Parse("8a1a8c42-d2ff-e254-e26e-b6abcbf19420").Should().Be(Svo.Uuid); + + [Test] + public void UpperCase() + => Uuid.Parse("8A1A8C42-D2FF-E254-E26E-B6ABCBF19420").Should().Be(Svo.Uuid); + + [Test] + public void With_brackets() + => Uuid.Parse("(8A1A8C42-D2FF-E254-E26E-B6ABCBF19420)").Should().Be(Svo.Uuid); + + [Test] + public void With_curly_brackets() + => Uuid.Parse("{8A1A8C42-D2FF-E254-E26E-B6ABCBF19420}").Should().Be(Svo.Uuid); + + [Test] + public void without_dashes() + => Uuid.Parse("8A1A8C42D2FFE254E26EB6ABCBF19420").Should().Be(Svo.Uuid); + } + + public class from_Base64 + { + [TestCase("Qowaiv_SVOLibrary_GUIA=")] + [TestCase("Qowaiv_SVOLibrary_GUIA==")] + public void with_equal_sign_suffix(string s) + => Uuid.Parse(s).Should().Be(Svo.Uuid); + + [Test] + public void with_under_scores_equvilent_to_forward_slashes() + => Uuid.Parse("Qowaiv/SVOLibrary/GUIA").Should().Be(Uuid.Parse("Qowaiv_SVOLibrary_GUIA")); + + [Test] + public void with_dashes_equvilent_to_plusses() + => Uuid.Parse("Qowaiv-SVOLibrary-GUIA").Should().Be(Uuid.Parse("Qowaiv+SVOLibrary+GUIA")); + } + + public class from_Base32 + { + [Test] + public void LowerCase() + => Uuid.Parse("ikgbvcx72jkofytow2v4x4muea").Should().Be(Svo.Uuid); + + [Test] + public void UpperCase() + => Uuid.Parse("IKGBVCX72JKOFYTOW2V4X4MUEA").Should().Be(Svo.Uuid); + + [Test] + public void with_0s_equivilent_to_Os() + => Uuid.Parse("IKGBVCX72JK0FYT0W2V4X4MUEA").Should().Be(Uuid.Parse("IKGBVCX72JKOFYTOW2V4X4MUEA")); + + [Test] + public void with_1s_equivilent_to_Is() + => Uuid.Parse("1KGBVCX72JKOFYTOW2V4X4MUEA").Should().Be(Uuid.Parse("IKGBVCX72JKOFYTOW2V4X4MUEA")); + } + + [TestCase("en", "Qowaiv_SVOLibrary_GUIA")] + [TestCase("en", "8A1A8C42-D2FF-E254-E26E-B6ABCBF19420")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + var parsed = Uuid.Parse(input); + parsed.Should().Be(Svo.Uuid); + } + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + "invalid input".Invoking(Uuid.Parse) + .Should().Throw() + .WithMessage("Not a valid GUID"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + { + Uuid.TryParse("invalid input", out _).Should().BeFalse(); + } + + [Test] + public void from_invalid_as_null_with_TryParse() + => Uuid.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + { + Uuid.TryParse("Qowaiv_SVOLibrary_GUIA").Should().Be(Svo.Uuid); + } } public class Can_not_be_parsed { - public class from_Base64 - { - [Test] - public void with_suffix_containing_non_equals_char() - => Uuid.TryParse("0123456789012345678901=@").Should().BeNull(); - } + public class from_Base64 + { + [Test] + public void with_suffix_containing_non_equals_char() + => Uuid.TryParse("0123456789012345678901=@").Should().BeNull(); + } } public class Can_be_created { - [Test] - public void with_global_unique_value() - => Enumerable.Range(0, 10_000).Select(i => Uuid.NewUuid()).ToHashSet() - .Should().HaveCount(10_000); - - [Test] - public void with_MD5() - { - var hashed = Uuid.GenerateWithMD5(Encoding.UTF8.GetBytes("Qowaiv")); - hashed.Should().Be(Uuid.Parse("lmZO_haEOTCwGsCcbIZFFg")); - } - - [Test] - public void with_SHA1() - { - var hashed = Uuid.GenerateWithSHA1(Encoding.UTF8.GetBytes("Qowaiv")); - hashed.Should().Be(Uuid.Parse("39h-Y1rR51ym_t78x9h0bA")); - } + [Test] + public void with_global_unique_value() + => Enumerable.Range(0, 10_000).Select(i => Uuid.NewUuid()).ToHashSet() + .Should().HaveCount(10_000); + + [Test] + public void with_MD5() + { + var hashed = Uuid.GenerateWithMD5(Encoding.UTF8.GetBytes("Qowaiv")); + hashed.Should().Be(Uuid.Parse("lmZO_haEOTCwGsCcbIZFFg")); + } + + [Test] + public void with_SHA1() + { + var hashed = Uuid.GenerateWithSHA1(Encoding.UTF8.GetBytes("Qowaiv")); + hashed.Should().Be(Uuid.Parse("39h-Y1rR51ym_t78x9h0bA")); + } } public class Can_be_created_sequential { - [Test] - public void from_1_Jan_1970_on() - { - using (Clock.SetTimeForCurrentContext(() => DateTime.UnixEpoch.AddTicks(-1))) - { - Assert.Catch(() => Uuid.NewSequential()); - } - } - - [Test] - public void until_3_Dec_9276() - { - using (Clock.SetTimeForCurrentContext(() => new DateTime(9276, 12, 04, 00, 00, 000, DateTimeKind.Utc))) - { - Assert.Catch(() => Uuid.NewSequential()); - } - } - - [Test] - public void on_min_date_first_6_bytes_are_0_for_default() - { - using (Clock.SetTimeForCurrentContext(() => DateTime.UnixEpoch)) - { - Uuid.NewSequential().Should().HavePattern( - 0, 0, 0, 0, - 0, 0, null, 0x60, - null, null, null, null, - null, null, null, null); - } - } - - [Test] - public void on_min_date_last_6_bytes_are_0_for_SQL_Server() - { - using (Clock.SetTimeForCurrentContext(() => DateTime.UnixEpoch)) - { - Uuid.NewSequential(UuidComparer.SqlServer).Should().HavePattern( - null, null, null, null, - null, null, null, null, - 0, null, 0, 0, - 0, 0, 0, 0); - } - } - - [Test] - public void on_max_date_first_6_bytes_are_255_for_default() - { - using (Clock.SetTimeForCurrentContext(() => MaxDate)) - { - Uuid.NewSequential().Should().HavePattern( - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, null, 0x6F, - null, null, null, null, - null, null, null, null); - } - } - - [Test] - public void on_max_date_last_6_bytes_are_255_for_SQL_Server() - { - using (Clock.SetTimeForCurrentContext(() => MaxDate)) - { - Uuid.NewSequential(UuidComparer.SqlServer).Should().HavePattern( - null, null, null, null, - null, null, null, null, - 0xFF, null, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF); - } - } - - [Test] - public void is_sorted_for_default() => AssertIsSorted(UuidComparer.Default); - - [Test] - public void is_sorted_for_MongoDb() => AssertIsSorted(UuidComparer.MongoDb); - - [Test] - public void is_sorted_for_SQL_Server() => AssertIsSorted(UuidComparer.SqlServer); - - private const int MultipleCount = 10000; - - private static DateTime MaxDate => new DateTime(9276, 12, 03, 18, 42, 01, DateTimeKind.Utc).AddTicks(3693920); - - private static void AssertIsSorted(UuidComparer comparer) - { - var ids = new List(MultipleCount); - - foreach (var date in GetTimes().Take(MultipleCount)) - { - using (Clock.SetTimeForCurrentContext(() => date)) - { - ids.Add(Uuid.NewSequential(comparer)); - } - } - - ids.Should().BeInAscendingOrder(comparer); - } - - private static IEnumerable GetTimes() - { - var i = 17; - - var date = DateTime.UnixEpoch; - - while (date < DateTime.MaxValue) - { - date = date.AddSeconds(3).AddTicks(i++); - yield return date; - } - } + [Test] + public void from_1_Jan_1970_on() + { + using (Clock.SetTimeForCurrentContext(() => DateTime.UnixEpoch.AddTicks(-1))) + { + Assert.Catch(() => Uuid.NewSequential()); + } + } + + [Test] + public void until_3_Dec_9276() + { + using (Clock.SetTimeForCurrentContext(() => new DateTime(9276, 12, 04, 00, 00, 000, DateTimeKind.Utc))) + { + Assert.Catch(() => Uuid.NewSequential()); + } + } + + [Test] + public void on_min_date_first_6_bytes_are_0_for_default() + { + using (Clock.SetTimeForCurrentContext(() => DateTime.UnixEpoch)) + { + Uuid.NewSequential().Should().HavePattern( + 0, 0, 0, 0, + 0, 0, null, 0x60, + null, null, null, null, + null, null, null, null); + } + } + + [Test] + public void on_min_date_last_6_bytes_are_0_for_SQL_Server() + { + using (Clock.SetTimeForCurrentContext(() => DateTime.UnixEpoch)) + { + Uuid.NewSequential(UuidComparer.SqlServer).Should().HavePattern( + null, null, null, null, + null, null, null, null, + 0, null, 0, 0, + 0, 0, 0, 0); + } + } + + [Test] + public void on_max_date_first_6_bytes_are_255_for_default() + { + using (Clock.SetTimeForCurrentContext(() => MaxDate)) + { + Uuid.NewSequential().Should().HavePattern( + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, null, 0x6F, + null, null, null, null, + null, null, null, null); + } + } + + [Test] + public void on_max_date_last_6_bytes_are_255_for_SQL_Server() + { + using (Clock.SetTimeForCurrentContext(() => MaxDate)) + { + Uuid.NewSequential(UuidComparer.SqlServer).Should().HavePattern( + null, null, null, null, + null, null, null, null, + 0xFF, null, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF); + } + } + + [Test] + public void is_sorted_for_default() => AssertIsSorted(UuidComparer.Default); + + [Test] + public void is_sorted_for_MongoDb() => AssertIsSorted(UuidComparer.MongoDb); + + [Test] + public void is_sorted_for_SQL_Server() => AssertIsSorted(UuidComparer.SqlServer); + + private const int MultipleCount = 10000; + + private static DateTime MaxDate => new DateTime(9276, 12, 03, 18, 42, 01, DateTimeKind.Utc).AddTicks(3693920); + + private static void AssertIsSorted(UuidComparer comparer) + { + var ids = new List(MultipleCount); + + foreach (var date in GetTimes().Take(MultipleCount)) + { + using (Clock.SetTimeForCurrentContext(() => date)) + { + ids.Add(Uuid.NewSequential(comparer)); + } + } + + ids.Should().BeInAscendingOrder(comparer); + } + + private static IEnumerable GetTimes() + { + var i = 17; + + var date = DateTime.UnixEpoch; + + while (date < DateTime.MaxValue) + { + date = date.AddSeconds(3).AddTicks(i++); + yield return date; + } + } } public class Has_custom_formatting { - [Test] - public void default_value_is_represented_as_string_empty() - { - default(Uuid).ToString().Should().Be(string.Empty); - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.Uuid.ToString("B", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: '{8A1A8C42-D2FF-E254-E26E-B6ABCBF19420}', format: 'B'"); - } - - [TestCase("en-GB", null, "Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] - [TestCase("en-GB", "S", "Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] - [TestCase("en-GB", "H", "Qowaiv_SVOLibrary_GUIA", "IKGBVCX72JKOFYTOW2V4X4MUEA")] - [TestCase("en-GB", "h", "Qowaiv_SVOLibrary_GUIA", "ikgbvcx72jkofytow2v4x4muea")] - [TestCase("en-GB", "N", "Qowaiv_SVOLibrary_GUIA", "8A1A8C42D2FFE254E26EB6ABCBF19420")] - [TestCase("en-GB", "n", "Qowaiv_SVOLibrary_GUIA", "8a1a8c42d2ffe254e26eb6abcbf19420")] - [TestCase("en-GB", "D", "Qowaiv_SVOLibrary_GUIA", "8A1A8C42-D2FF-E254-E26E-B6ABCBF19420")] - [TestCase("en-GB", "d", "Qowaiv_SVOLibrary_GUIA", "8a1a8c42-d2ff-e254-e26e-b6abcbf19420")] - [TestCase("nl-BE", "B", "Qowaiv_SVOLibrary_GUIA", "{8A1A8C42-D2FF-E254-E26E-B6ABCBF19420}")] - [TestCase("nl-BE", "b", "Qowaiv_SVOLibrary_GUIA", "{8a1a8c42-d2ff-e254-e26e-b6abcbf19420}")] - [TestCase("nl-BE", "B", "Qowaiv_SVOLibrary_GUIA", "{8A1A8C42-D2FF-E254-E26E-B6ABCBF19420}")] - [TestCase("nl-BE", "b", "Qowaiv_SVOLibrary_GUIA", "{8a1a8c42-d2ff-e254-e26e-b6abcbf19420}")] - [TestCase("nl-BE", "P", "Qowaiv_SVOLibrary_GUIA", "(8A1A8C42-D2FF-E254-E26E-B6ABCBF19420)")] - [TestCase("nl-BE", "p", "Qowaiv_SVOLibrary_GUIA", "(8a1a8c42-d2ff-e254-e26e-b6abcbf19420)")] - [TestCase("nl-BE", "X", "Qowaiv_SVOLibrary_GUIA", "{0x8A1A8C42,0xD2FF,0xE254,{0xE2,0x6E,0xB6,0xAB,0xCB,0xF1,0x94,0x20}}")] - public void culture_independent(CultureInfo culture, string format, Uuid svo, string expected) - { - using (culture.Scoped()) - { - svo.ToString(format).Should().Be(expected); - } - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) - { - Svo.Uuid.ToString(provider: null).Should().Be("Qowaiv_SVOLibrary_GUIA"); - } - } + [Test] + public void default_value_is_represented_as_string_empty() + { + default(Uuid).ToString().Should().Be(string.Empty); + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.Uuid.ToString("B", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: '{8A1A8C42-D2FF-E254-E26E-B6ABCBF19420}', format: 'B'"); + } + + [TestCase("en-GB", null, "Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] + [TestCase("en-GB", "S", "Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] + [TestCase("en-GB", "H", "Qowaiv_SVOLibrary_GUIA", "IKGBVCX72JKOFYTOW2V4X4MUEA")] + [TestCase("en-GB", "h", "Qowaiv_SVOLibrary_GUIA", "ikgbvcx72jkofytow2v4x4muea")] + [TestCase("en-GB", "N", "Qowaiv_SVOLibrary_GUIA", "8A1A8C42D2FFE254E26EB6ABCBF19420")] + [TestCase("en-GB", "n", "Qowaiv_SVOLibrary_GUIA", "8a1a8c42d2ffe254e26eb6abcbf19420")] + [TestCase("en-GB", "D", "Qowaiv_SVOLibrary_GUIA", "8A1A8C42-D2FF-E254-E26E-B6ABCBF19420")] + [TestCase("en-GB", "d", "Qowaiv_SVOLibrary_GUIA", "8a1a8c42-d2ff-e254-e26e-b6abcbf19420")] + [TestCase("nl-BE", "B", "Qowaiv_SVOLibrary_GUIA", "{8A1A8C42-D2FF-E254-E26E-B6ABCBF19420}")] + [TestCase("nl-BE", "b", "Qowaiv_SVOLibrary_GUIA", "{8a1a8c42-d2ff-e254-e26e-b6abcbf19420}")] + [TestCase("nl-BE", "B", "Qowaiv_SVOLibrary_GUIA", "{8A1A8C42-D2FF-E254-E26E-B6ABCBF19420}")] + [TestCase("nl-BE", "b", "Qowaiv_SVOLibrary_GUIA", "{8a1a8c42-d2ff-e254-e26e-b6abcbf19420}")] + [TestCase("nl-BE", "P", "Qowaiv_SVOLibrary_GUIA", "(8A1A8C42-D2FF-E254-E26E-B6ABCBF19420)")] + [TestCase("nl-BE", "p", "Qowaiv_SVOLibrary_GUIA", "(8a1a8c42-d2ff-e254-e26e-b6abcbf19420)")] + [TestCase("nl-BE", "X", "Qowaiv_SVOLibrary_GUIA", "{0x8A1A8C42,0xD2FF,0xE254,{0xE2,0x6E,0xB6,0xAB,0xCB,0xF1,0x94,0x20}}")] + public void culture_independent(CultureInfo culture, string format, Uuid svo, string expected) + { + using (culture.Scoped()) + { + svo.ToString(format).Should().Be(expected); + } + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) + { + Svo.Uuid.ToString(provider: null).Should().Be("Qowaiv_SVOLibrary_GUIA"); + } + } } public class Is_comparable { - [Test] - public void to_null_is_1() - { - Svo.Uuid.CompareTo(null).Should().Be(1); - } - - [Test] - public void to_Uuid_as_object() - { - object obj = Svo.Uuid; - Svo.Uuid.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Uuid_only() - { - Assert.Throws(() => Svo.Uuid.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - default, - default, - Uuid.Parse("Qowaiv_SVOLibrary_GUI0"), - Uuid.Parse("Qowaiv_SVOLibrary_GUI1"), - Uuid.Parse("Qowaiv_SVOLibrary_GUI2"), - Uuid.Parse("Qowaiv_SVOLibrary_GUI3"), - }; - var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() + { + Svo.Uuid.CompareTo(null).Should().Be(1); + } + + [Test] + public void to_Uuid_as_object() + { + object obj = Svo.Uuid; + Svo.Uuid.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Uuid_only() + => new object().Invoking(Svo.Uuid.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + default, + default, + Uuid.Parse("Qowaiv_SVOLibrary_GUI0"), + Uuid.Parse("Qowaiv_SVOLibrary_GUI1"), + Uuid.Parse("Qowaiv_SVOLibrary_GUI2"), + Uuid.Parse("Qowaiv_SVOLibrary_GUI3"), + }; + var list = new List { sorted[3], sorted[4], sorted[5], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } } public class Casts { - [Test] - public void explicitly_from_Guid() - { - var casted = (Uuid)Svo.Guid; - casted.Should().Be(Svo.Uuid); - } - - [Test] - public void explicitly_to_Guid() - { - var casted = (Guid)Svo.Uuid; - casted.Should().Be(Svo.Guid); - } + [Test] + public void explicitly_from_Guid() + { + var casted = (Uuid)Svo.Guid; + casted.Should().Be(Svo.Uuid); + } + + [Test] + public void explicitly_to_Guid() + { + var casted = (Guid)Svo.Uuid; + casted.Should().Be(Svo.Guid); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(Uuid).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(default); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(default); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("Qowaiv_SVOLibrary_GUID").To().Should().Be(Svo.Uuid); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.Uuid).Should().Be("Qowaiv_SVOLibrary_GUIA"); - } - } - - [Test] - public void from_Guid() - => Converting.From(Svo.Guid).To().Should().Be(Svo.Uuid); - - [Test] - public void to_Guid() - => Converting.To().From(Svo.Uuid).Should().Be(Svo.Guid); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(Uuid).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(default); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(default); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("Qowaiv_SVOLibrary_GUID").To().Should().Be(Svo.Uuid); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.Uuid).Should().Be("Qowaiv_SVOLibrary_GUIA"); + } + } + + [Test] + public void from_Guid() + => Converting.From(Svo.Guid).To().Should().Be(Svo.Uuid); + + [Test] + public void to_Guid() + => Converting.To().From(Svo.Uuid).Should().Be(Svo.Guid); } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase("", null)] - [TestCase(null, null)] - [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] - public void System_Text_JSON_deserialization(object json, Uuid svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - [TestCase(null, null)] - [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] - public void System_Text_JSON_serialization(Uuid svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase("", null)] + [TestCase(null, null)] + [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] + public void System_Text_JSON_deserialization(object json, Uuid svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + [TestCase(null, null)] + [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] + public void System_Text_JSON_serialization(Uuid svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] - public void convention_based_deserialization(object json, Uuid svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] - public void convention_based_serialization(Uuid svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] + public void convention_based_deserialization(object json, Uuid svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] + public void convention_based_serialization(Uuid svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.Uuid); - xml.Should().Be("Qowaiv_SVOLibrary_GUIA"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("Qowaiv_SVOLibrary_GUIA"); - svo.Should().Be(Svo.Uuid); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.Uuid); - round_tripped.Should().Be(Svo.Uuid); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.Uuid); - var round_tripped = SerializeDeserialize.Xml(structure); - round_tripped.Should().Be(structure); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.Uuid; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.Uuid); + xml.Should().Be("Qowaiv_SVOLibrary_GUIA"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("Qowaiv_SVOLibrary_GUIA"); + svo.Should().Be(Svo.Uuid); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.Uuid); + round_tripped.Should().Be(Svo.Uuid); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.Uuid); + var round_tripped = SerializeDeserialize.Xml(structure); + round_tripped.Should().Be(structure); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.Uuid; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Uuid)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(Uuid), - description: "Universally unique identifier, Base64 encoded.", - example: "lmZO_haEOTCwGsCcbIZFFg", - type: "string", - format: "uuid-base64", - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Uuid)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(Uuid), + description: "Universally unique identifier, Base64 encoded.", + example: "lmZO_haEOTCwGsCcbIZFFg", + type: "string", + format: "uuid-base64", + nullable: true)); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Uuid); - round_tripped.Should().Be(Svo.Uuid); - } - - [Test] - public void storing_Guid_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Uuid); - Assert.AreEqual(Svo.Guid, info.GetValue("Value", typeof(Guid))); - } - - [Test] - public void export_to_byte_array_equal_to_GUID_equivalent() - { - var bytes = Svo.Uuid.ToByteArray(); - bytes.Should().BeEquivalentTo(((Guid)Svo.Uuid).ToByteArray()); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Uuid); + round_tripped.Should().Be(Svo.Uuid); + } + + [Test] + public void storing_Guid_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Uuid); + Assert.AreEqual(Svo.Guid, info.GetValue("Value", typeof(Guid))); + } + + [Test] + public void export_to_byte_array_equal_to_GUID_equivalent() + { + var bytes = Svo.Uuid.ToByteArray(); + bytes.Should().BeEquivalentTo(((Guid)Svo.Uuid).ToByteArray()); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] - public void has_custom_display(object display, Uuid svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("Qowaiv_SVOLibrary_GUIA", "Qowaiv_SVOLibrary_GUIA")] + public void has_custom_display(object display, Uuid svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/Year_specs.cs b/specs/Qowaiv.Specs/Year_specs.cs index bb533ef5..6ba7377b 100644 --- a/specs/Qowaiv.Specs/Year_specs.cs +++ b/specs/Qowaiv.Specs/Year_specs.cs @@ -2,553 +2,551 @@ public class With_domain_logic { - [TestCase(true, 1979)] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, Year svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, 1979)] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, Year svo) => svo.IsKnown.Should().Be(result); - - [TestCase(false, 1979)] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, Year svo) - { - svo.IsEmpty().Should().Be(result); - } - - [TestCase(false, 1979)] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, Year svo) - { - svo.IsEmptyOrUnknown().Should().Be(result); - } - - [TestCase(false, 1979)] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, Year svo) - { - svo.IsUnknown().Should().Be(result); - } + [TestCase(true, 1979)] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, Year svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, 1979)] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, Year svo) => svo.IsKnown.Should().Be(result); + + [TestCase(false, 1979)] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, Year svo) + { + svo.IsEmpty().Should().Be(result); + } + + [TestCase(false, 1979)] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, Year svo) + { + svo.IsEmptyOrUnknown().Should().Be(result); + } + + [TestCase(false, 1979)] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, Year svo) + { + svo.IsUnknown().Should().Be(result); + } } public class Is_not_leap_year_when { - [TestCase("")] - [TestCase("?")] - public void empty_or_unknown(Year year) - { - year.IsLeapYear.Should().BeFalse(); - } - - [TestCase(1979)] - [TestCase(2017)] - public void not_dividable_by_4(Year year) - { - year.IsLeapYear.Should().BeFalse(); - } - - [TestCase(1800)] - [TestCase(1900)] - public void dividable_by_100_not_by_400(Year year) - { - year.IsLeapYear.Should().BeFalse(); - } + [TestCase("")] + [TestCase("?")] + public void empty_or_unknown(Year year) + { + year.IsLeapYear.Should().BeFalse(); + } + + [TestCase(1979)] + [TestCase(2017)] + public void not_dividable_by_4(Year year) + { + year.IsLeapYear.Should().BeFalse(); + } + + [TestCase(1800)] + [TestCase(1900)] + public void dividable_by_100_not_by_400(Year year) + { + year.IsLeapYear.Should().BeFalse(); + } } public class Is_leap_year { - [TestCase(1988)] - [TestCase(2004)] - public void dividable_by_4_not_by_100(Year year) - { - year.IsLeapYear.Should().BeTrue(); - } - - [TestCase(1600)] - [TestCase(2000)] - public void dividable_by_400(Year year) - { - year.IsLeapYear.Should().BeTrue(); - } + [TestCase(1988)] + [TestCase(2004)] + public void dividable_by_4_not_by_100(Year year) + { + year.IsLeapYear.Should().BeTrue(); + } + + [TestCase(1600)] + [TestCase(2000)] + public void dividable_by_400(Year year) + { + year.IsLeapYear.Should().BeTrue(); + } } public class Has_constant { - [Test] - public void Empty_represent_default_value() - { - Year.Empty.Should().Be(default); - } - - [Test] - public void MinValue_represents_1() - { - Year min = 1.CE(); - Year.MinValue.Should().Be(min); - } - - [Test] - public void MaxValue_represents_9999() - { - Year max = 9999.CE(); - Year.MaxValue.Should().Be(max); - } + [Test] + public void Empty_represent_default_value() + { + Year.Empty.Should().Be(default); + } + + [Test] + public void MinValue_represents_1() + { + Year min = 1.CE(); + Year.MinValue.Should().Be(min); + } + + [Test] + public void MaxValue_represents_9999() + { + Year max = 9999.CE(); + Year.MaxValue.Should().Be(max); + } } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - { - Svo.Year.Equals(null).Should().BeFalse(); - } - - [Test] - public void not_equal_to_other_type() - { - Svo.Year.Equals(new object()).Should().BeFalse(); - } - - [Test] - public void not_equal_to_different_value() - { - Year other = 2017.CE(); - Svo.Year.Equals(other).Should().BeFalse(); - } - - [Test] - public void equal_to_same_value() - { - Svo.Year.Equals(1979.CE()).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_true_for_same_values() - { - (Svo.Year == 1979.CE()).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_false_for_different_values() - { - (Svo.Year == 2017.CE()).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_false_for_same_values() - { - (Svo.Year != 1979.CE()).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_true_for_different_values() - { - (Svo.Year != 2017.CE()).Should().BeTrue(); - } - - [TestCase("", 0)] - [TestCase("1979", 665629288)] - public void hash_code_is_value_based(Year svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + { + Svo.Year.Equals(null).Should().BeFalse(); + } + + [Test] + public void not_equal_to_other_type() + { + Svo.Year.Equals(new object()).Should().BeFalse(); + } + + [Test] + public void not_equal_to_different_value() + { + Year other = 2017.CE(); + Svo.Year.Equals(other).Should().BeFalse(); + } + + [Test] + public void equal_to_same_value() + { + Svo.Year.Equals(1979.CE()).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_true_for_same_values() + { + (Svo.Year == 1979.CE()).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_false_for_different_values() + { + (Svo.Year == 2017.CE()).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_false_for_same_values() + { + (Svo.Year != 1979.CE()).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_true_for_different_values() + { + (Svo.Year != 2017.CE()).Should().BeTrue(); + } + + [TestCase("", 0)] + [TestCase("1979", 665629288)] + public void hash_code_is_value_based(Year svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - { - Year.Parse(null).Should().Be(Year.Empty); - } - - [Test] - public void from_empty_string_represents_Empty() - { - Year.Parse(string.Empty).Should().Be(Year.Empty); - } - - [Test] - public void from_question_mark_represents_Unknown() - { - Year.Parse("?").Should().Be(Year.Unknown); - } - - [Test] - public void from_string() - { - var parsed = Year.Parse("1979"); - parsed.Should().Be(Svo.Year); - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - "invalid input".Invoking(Year.Parse) - .Should().Throw() - .WithMessage("Not a valid year"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - { - Year.TryParse("invalid input", out _).Should().BeFalse(); - } - - [Test] - public void from_invalid_as_null_with_TryParse() - => Year.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - { - Year.TryParse("1979").Should().Be(Svo.Year); - } + [Test] + public void from_null_string_represents_Empty() + { + Year.Parse(null).Should().Be(Year.Empty); + } + + [Test] + public void from_empty_string_represents_Empty() + { + Year.Parse(string.Empty).Should().Be(Year.Empty); + } + + [Test] + public void from_question_mark_represents_Unknown() + { + Year.Parse("?").Should().Be(Year.Unknown); + } + + [Test] + public void from_string() + { + var parsed = Year.Parse("1979"); + parsed.Should().Be(Svo.Year); + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + "invalid input".Invoking(Year.Parse) + .Should().Throw() + .WithMessage("Not a valid year"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + { + Year.TryParse("invalid input", out _).Should().BeFalse(); + } + + [Test] + public void from_invalid_as_null_with_TryParse() + => Year.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + { + Year.TryParse("1979").Should().Be(Svo.Year); + } } public class Can_be_created_from_int { - [Test] - public void empty_for_not_set_int() - => Year.TryCreate(default).Should().Be(Year.Empty); - - [Test] - public void empty_for_not_invalid_int() - => Year.TryCreate(-10).Should().Be(Year.Empty); - - [Test] - public void within_range() - { - Year.TryCreate(1979).Should().Be(Svo.Year); - } - - [TestCase(0)] - [TestCase(10000)] - public void but_not_outside_1_to_9999(int year) - { - Year.TryCreate(year, out _).Should().BeFalse(); - } + [Test] + public void empty_for_not_set_int() + => Year.TryCreate(default).Should().Be(Year.Empty); + + [Test] + public void empty_for_not_invalid_int() + => Year.TryCreate(-10).Should().Be(Year.Empty); + + [Test] + public void within_range() + { + Year.TryCreate(1979).Should().Be(Svo.Year); + } + + [TestCase(0)] + [TestCase(10000)] + public void but_not_outside_1_to_9999(int year) + { + Year.TryCreate(year, out _).Should().BeFalse(); + } } public class Has_custom_formatting { - [Test] - public void default_value_is_represented_as_string_empty() - { - default(Year).ToString().Should().Be(string.Empty); - } - - [Test] - public void unknown_value_is_represented_as_unknown() - { - Year.Unknown.ToString().Should().Be("?"); - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.Year.ToString("#,##0", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: '1,979', format: '#,##0'"); - } - - [TestCase("en-GB", null, 1979, "1979")] - [TestCase("nl-BE", "#,##0", 1979, "1.979")] - [TestCase("en-US", "00000", 1979, "01979")] - public void culture_dependent(CultureInfo culture, string format, Year svo, string expected) - { - using (culture.Scoped()) - { - svo.ToString(format).Should().Be(expected); - } - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) - { - Svo.Year.ToString(provider: null).Should().Be("1979"); - } - } + [Test] + public void default_value_is_represented_as_string_empty() + { + default(Year).ToString().Should().Be(string.Empty); + } + + [Test] + public void unknown_value_is_represented_as_unknown() + { + Year.Unknown.ToString().Should().Be("?"); + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.Year.ToString("#,##0", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: '1,979', format: '#,##0'"); + } + + [TestCase("en-GB", null, 1979, "1979")] + [TestCase("nl-BE", "#,##0", 1979, "1.979")] + [TestCase("en-US", "00000", 1979, "01979")] + public void culture_dependent(CultureInfo culture, string format, Year svo, string expected) + { + using (culture.Scoped()) + { + svo.ToString(format).Should().Be(expected); + } + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope(culture: TestCultures.nl_NL, cultureUI: TestCultures.en_GB)) + { + Svo.Year.ToString(provider: null).Should().Be("1979"); + } + } } public class Is_comparable { - [Test] - public void to_null_is_1() - { - Svo.Year.CompareTo(null).Should().Be(1); - } - - [Test] - public void to_Year_as_object() - { - object obj = Svo.Year; - Svo.Year.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_Year_only() - { - Assert.Throws(() => Svo.Year.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] { - default, - default, - 1970.CE(), - 1971.CE(), - 1972.CE(), - Year.Unknown, - }; - var list = new List { sorted[3], sorted[5], sorted[4], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - list.Should().BeEquivalentTo(sorted); - } - - [Test] - public void by_operators_for_different_values() - { - Year smaller = 1979.CE(); - Year bigger = 2017.CE(); - - (smaller < bigger).Should().BeTrue(); - (smaller <= bigger).Should().BeTrue(); - (smaller > bigger).Should().BeFalse(); - (smaller >= bigger).Should().BeFalse(); - } - - [Test] - public void by_operators_for_equal_values() - { - Year left = 2071.CE(); - Year right = 2071.CE(); - - (left < right).Should().BeFalse(); - (left <= right).Should().BeTrue(); - (left > right).Should().BeFalse(); - (left >= right).Should().BeTrue(); - } - - [TestCase("", 1979)] - [TestCase("?", 1979)] - [TestCase(1979, "")] - [TestCase(1979, "?")] - public void by_operators_for_empty_or_unknown_always_false(Year l, Year r) - { - (l <= r).Should().BeFalse(); - (l < r).Should().BeFalse(); - (l > r).Should().BeFalse(); - (l >= r).Should().BeFalse(); - } + [Test] + public void to_null_is_1() + { + Svo.Year.CompareTo(null).Should().Be(1); + } + + [Test] + public void to_Year_as_object() + { + object obj = Svo.Year; + Svo.Year.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_Year_only() + => new object().Invoking(Svo.Year.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] { + default, + default, + 1970.CE(), + 1971.CE(), + 1972.CE(), + Year.Unknown, + }; + var list = new List { sorted[3], sorted[5], sorted[4], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + list.Should().BeEquivalentTo(sorted); + } + + [Test] + public void by_operators_for_different_values() + { + Year smaller = 1979.CE(); + Year bigger = 2017.CE(); + + (smaller < bigger).Should().BeTrue(); + (smaller <= bigger).Should().BeTrue(); + (smaller > bigger).Should().BeFalse(); + (smaller >= bigger).Should().BeFalse(); + } + + [Test] + public void by_operators_for_equal_values() + { + Year left = 2071.CE(); + Year right = 2071.CE(); + + (left < right).Should().BeFalse(); + (left <= right).Should().BeTrue(); + (left > right).Should().BeFalse(); + (left >= right).Should().BeTrue(); + } + + [TestCase("", 1979)] + [TestCase("?", 1979)] + [TestCase(1979, "")] + [TestCase(1979, "?")] + public void by_operators_for_empty_or_unknown_always_false(Year l, Year r) + { + (l <= r).Should().BeFalse(); + (l < r).Should().BeFalse(); + (l > r).Should().BeFalse(); + (l >= r).Should().BeFalse(); + } } public class Casts { - [Test] - public void explicitly_from_short() - { - var casted = (Year)1979; - casted.Should().Be(Svo.Year); - } - - [Test] - public void explicitly_to_short() - { - var casted = (short)Svo.Year; - casted.Should().Be((short)1979); - } + [Test] + public void explicitly_from_short() + { + var casted = (Year)1979; + casted.Should().Be(Svo.Year); + } + + [Test] + public void explicitly_to_short() + { + var casted = (short)Svo.Year; + casted.Should().Be((short)1979); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(Year).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(Year.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(Year.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("1979").To().Should().Be(Svo.Year); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.Year).Should().Be("1979"); - } - } - - [Test] - public void from_int_0() - => Converting.From(0).To().Should().Be(Year.Empty); - - [Test] - public void from_int() - => Converting.From(1979).To().Should().Be(Svo.Year); - - [Test] - public void to_int() - => Converting.To().From(Svo.Year).Should().Be(1979); + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(Year).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(Year.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(Year.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("1979").To().Should().Be(Svo.Year); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.Year).Should().Be("1979"); + } + } + + [Test] + public void from_int_0() + => Converting.From(0).To().Should().Be(Year.Empty); + + [Test] + public void from_int() + => Converting.From(1979).To().Should().Be(Svo.Year); + + [Test] + public void to_int() + => Converting.To().From(Svo.Year).Should().Be(1979); } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase("?", "?")] - [TestCase(null, null)] - [TestCase(2017d, 2017)] - [TestCase(2017L, 2017)] - [TestCase("2017", 2017)] - public void System_Text_JSON_deserialization(object json, Year svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase(2017, 2017L)] - public void System_Text_JSON_serialization(Year svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase("?", "?")] + [TestCase(null, null)] + [TestCase(2017d, 2017)] + [TestCase(2017L, 2017)] + [TestCase("2017", 2017)] + public void System_Text_JSON_deserialization(object json, Year svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase(2017, 2017L)] + public void System_Text_JSON_serialization(Year svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("?", "?")] - [TestCase(2017d, 2017)] - [TestCase(2017L, 2017)] - [TestCase("2017", 2017)] - public void convention_based_deserialization(object json, Year svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase(2017, 2017L)] - public void convention_based_serialization(Year svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - [TestCase(-5L, typeof(ArgumentOutOfRangeException))] - [TestCase(-2.3, typeof(ArgumentOutOfRangeException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("?", "?")] + [TestCase(2017d, 2017)] + [TestCase(2017L, 2017)] + [TestCase("2017", 2017)] + public void convention_based_deserialization(object json, Year svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase(2017, 2017L)] + public void convention_based_serialization(Year svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + [TestCase(-5L, typeof(ArgumentOutOfRangeException))] + [TestCase(-2.3, typeof(ArgumentOutOfRangeException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.Year); - xml.Should().Be("1979"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("1979"); - svo.Should().Be(Svo.Year); - } - - [Test] - public void using_DataContractSerializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.Year); - round_tripped.Should().Be(Svo.Year); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.Year); - var round_tripped = SerializeDeserialize.Xml(structure); - round_tripped.Should().Be(structure); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.Year; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.Year); + xml.Should().Be("1979"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("1979"); + svo.Should().Be(Svo.Year); + } + + [Test] + public void using_DataContractSerializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.Year); + round_tripped.Should().Be(Svo.Year); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.Year); + var round_tripped = SerializeDeserialize.Xml(structure); + round_tripped.Should().Be(structure); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.Year; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Year)) - .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(Year), - description: "Year(-only) notation.", - example: 1983, - type: "integer", - format: "year", - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(Year)) + .Should().Be(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(Year), + description: "Year(-only) notation.", + example: 1983, + type: "integer", + format: "year", + nullable: true)); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.Year); - round_tripped.Should().Be(Svo.Year); - } - - [Test] - public void storing_short_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.Year); - info.GetInt16("Value").Should().Be((short)1979); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.Year); + round_tripped.Should().Be(Svo.Year); + } + + [Test] + public void storing_short_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.Year); + info.GetInt16("Value").Should().Be((short)1979); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("{unknown}", "?")] - [TestCase("1979", (short)1979)] - public void has_custom_display(object display, Year svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("{unknown}", "?")] + [TestCase("1979", (short)1979)] + public void has_custom_display(object display, Year svo) + => svo.Should().HaveDebuggerDisplay(display); } diff --git a/specs/Qowaiv.Specs/YesNo_specs.cs b/specs/Qowaiv.Specs/YesNo_specs.cs index a63ac7a4..01b00d6f 100644 --- a/specs/Qowaiv.Specs/YesNo_specs.cs +++ b/specs/Qowaiv.Specs/YesNo_specs.cs @@ -2,560 +2,558 @@ namespace YesNo_specs; public class With_domain_logic { - [TestCase(true, "yes")] - [TestCase(true, "no")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void HasValue_is(bool result, YesNo svo) => svo.HasValue.Should().Be(result); - - [TestCase(true, "yes")] - [TestCase(true, "no")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsKnown_is(bool result, YesNo svo) => svo.IsKnown.Should().Be(result); - - [TestCase(false, "yes")] - [TestCase(false, "no")] - [TestCase(false, "?")] - [TestCase(true, "")] - public void IsEmpty_returns(bool result, YesNo svo) => svo.IsEmpty().Should().Be(result); - - [TestCase(false, "yes")] - [TestCase(false, "no")] - [TestCase(true, "?")] - [TestCase(true, "")] - public void IsEmptyOrUnknown_returns(bool result, YesNo svo) => svo.IsEmptyOrUnknown().Should().Be(result); - - [TestCase(false, "yes")] - [TestCase(false, "no")] - [TestCase(true, "?")] - [TestCase(false, "")] - public void IsUnknown_returns(bool result, YesNo svo) => svo.IsUnknown().Should().Be(result); - - [TestCase(true, "yes")] - [TestCase(true, "no")] - [TestCase(false, "?")] - [TestCase(false, "")] - public void IsYesOrNo_returns(bool result, YesNo svo) => svo.IsYesOrNo().Should().Be(result); - - - [TestCase(false, "")] - [TestCase(false, "N")] - [TestCase(true, "Y")] - [TestCase(false, "?")] - - public void IsYes_returns(bool result, YesNo svo) => svo.IsYes().Should().Be(result); - - [TestCase(false, "")] - [TestCase(true, "N")] - [TestCase(false, "Y")] - [TestCase(false, "?")] - - public void IsNo_returns(bool result, YesNo svo) => svo.IsNo().Should().Be(result); + [TestCase(true, "yes")] + [TestCase(true, "no")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void HasValue_is(bool result, YesNo svo) => svo.HasValue.Should().Be(result); + + [TestCase(true, "yes")] + [TestCase(true, "no")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsKnown_is(bool result, YesNo svo) => svo.IsKnown.Should().Be(result); + + [TestCase(false, "yes")] + [TestCase(false, "no")] + [TestCase(false, "?")] + [TestCase(true, "")] + public void IsEmpty_returns(bool result, YesNo svo) => svo.IsEmpty().Should().Be(result); + + [TestCase(false, "yes")] + [TestCase(false, "no")] + [TestCase(true, "?")] + [TestCase(true, "")] + public void IsEmptyOrUnknown_returns(bool result, YesNo svo) => svo.IsEmptyOrUnknown().Should().Be(result); + + [TestCase(false, "yes")] + [TestCase(false, "no")] + [TestCase(true, "?")] + [TestCase(false, "")] + public void IsUnknown_returns(bool result, YesNo svo) => svo.IsUnknown().Should().Be(result); + + [TestCase(true, "yes")] + [TestCase(true, "no")] + [TestCase(false, "?")] + [TestCase(false, "")] + public void IsYesOrNo_returns(bool result, YesNo svo) => svo.IsYesOrNo().Should().Be(result); + + + [TestCase(false, "")] + [TestCase(false, "N")] + [TestCase(true, "Y")] + [TestCase(false, "?")] + + public void IsYes_returns(bool result, YesNo svo) => svo.IsYes().Should().Be(result); + + [TestCase(false, "")] + [TestCase(true, "N")] + [TestCase(false, "Y")] + [TestCase(false, "?")] + + public void IsNo_returns(bool result, YesNo svo) => svo.IsNo().Should().Be(result); } public class Is_valid_for { - [TestCase("ja", "nl")] - [TestCase("yes", "en-GB")] - [TestCase("y", null)] - [TestCase("true", null)] - public void strings_representing_yes(string input, CultureInfo culture) - => YesNo.Parse(input, culture).Should().Be(YesNo.Yes); - - [TestCase("nee", "nl")] - [TestCase("no", "en-GB")] - [TestCase("n", null)] - [TestCase("false", null)] - public void strings_representing_no(string input, CultureInfo culture) - => YesNo.Parse(input, culture).Should().Be(YesNo.No); + [TestCase("ja", "nl")] + [TestCase("yes", "en-GB")] + [TestCase("y", null)] + [TestCase("true", null)] + public void strings_representing_yes(string input, CultureInfo culture) + => YesNo.Parse(input, culture).Should().Be(YesNo.Yes); + + [TestCase("nee", "nl")] + [TestCase("no", "en-GB")] + [TestCase("n", null)] + [TestCase("false", null)] + public void strings_representing_no(string input, CultureInfo culture) + => YesNo.Parse(input, culture).Should().Be(YesNo.No); } public class Has_constant { - [Test] - public void Empty_represent_default_value() - { - YesNo.Empty.Should().Be(default); - } + [Test] + public void Empty_represent_default_value() + { + YesNo.Empty.Should().Be(default); + } } public class Is_equal_by_value { - [Test] - public void not_equal_to_null() - { - Svo.YesNo.Equals(null).Should().BeFalse(); - } - - [Test] - public void not_equal_to_other_type() - { - Svo.YesNo.Equals(new object()).Should().BeFalse(); - } - - [Test] - public void not_equal_to_different_value() - { - Svo.YesNo.Equals(YesNo.Unknown).Should().BeFalse(); - } - - [Test] - public void equal_to_same_value() - { - Svo.YesNo.Equals(YesNo.Yes).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_true_for_same_values() - { - (YesNo.Yes == Svo.YesNo).Should().BeTrue(); - } - - [Test] - public void equal_operator_returns_false_for_different_values() - { - (YesNo.Yes == YesNo.No).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_false_for_same_values() - { - (YesNo.Yes != Svo.YesNo).Should().BeFalse(); - } - - [Test] - public void not_equal_operator_returns_true_for_different_values() - { - (YesNo.Yes != YesNo.No).Should().BeTrue(); - } - - [TestCase("", 0)] - [TestCase("yes", 665630161)] - public void hash_code_is_value_based(YesNo svo, int hash) - { - using (Hash.WithoutRandomizer()) - { - svo.GetHashCode().Should().Be(hash); - } - } + [Test] + public void not_equal_to_null() + { + Svo.YesNo.Equals(null).Should().BeFalse(); + } + + [Test] + public void not_equal_to_other_type() + { + Svo.YesNo.Equals(new object()).Should().BeFalse(); + } + + [Test] + public void not_equal_to_different_value() + { + Svo.YesNo.Equals(YesNo.Unknown).Should().BeFalse(); + } + + [Test] + public void equal_to_same_value() + { + Svo.YesNo.Equals(YesNo.Yes).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_true_for_same_values() + { + (YesNo.Yes == Svo.YesNo).Should().BeTrue(); + } + + [Test] + public void equal_operator_returns_false_for_different_values() + { + (YesNo.Yes == YesNo.No).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_false_for_same_values() + { + (YesNo.Yes != Svo.YesNo).Should().BeFalse(); + } + + [Test] + public void not_equal_operator_returns_true_for_different_values() + { + (YesNo.Yes != YesNo.No).Should().BeTrue(); + } + + [TestCase("", 0)] + [TestCase("yes", 665630161)] + public void hash_code_is_value_based(YesNo svo, int hash) + { + using (Hash.WithoutRandomizer()) + { + svo.GetHashCode().Should().Be(hash); + } + } } public class Can_be_parsed { - [Test] - public void from_null_string_represents_Empty() - { - YesNo.Parse(null).Should().Be(YesNo.Empty); - } - - [Test] - public void from_empty_string_represents_Empty() - { - YesNo.Parse(string.Empty).Should().Be(YesNo.Empty); - } - - [Test] - public void from_question_mark_represents_Unknown() - { - YesNo.Parse("?").Should().Be(YesNo.Unknown); - } - - [TestCase("en", "y")] - [TestCase("nl", "j")] - [TestCase("nl", "ja")] - [TestCase("fr", "oui")] - public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) - { - using (culture.Scoped()) - { - var parsed = YesNo.Parse(input); - parsed.Should().Be(Svo.YesNo); - } - } - - [Test] - public void from_valid_input_only_otherwise_throws_on_Parse() - { - using (TestCultures.en_GB.Scoped()) - { - "invalid input".Invoking(YesNo.Parse) - .Should().Throw() - .WithMessage("Not a valid yes-no value"); - } - } - - [Test] - public void from_valid_input_only_otherwise_return_false_on_TryParse() - { - YesNo.TryParse("invalid input", out _).Should().BeFalse(); - } - - [Test] - public void from_invalid_as_null_with_TryParse() - => YesNo.TryParse("invalid input").Should().BeNull(); - - [Test] - public void with_TryParse_returns_SVO() - { - YesNo.TryParse("yes").Should().Be(Svo.YesNo); - } + [Test] + public void from_null_string_represents_Empty() + { + YesNo.Parse(null).Should().Be(YesNo.Empty); + } + + [Test] + public void from_empty_string_represents_Empty() + { + YesNo.Parse(string.Empty).Should().Be(YesNo.Empty); + } + + [Test] + public void from_question_mark_represents_Unknown() + { + YesNo.Parse("?").Should().Be(YesNo.Unknown); + } + + [TestCase("en", "y")] + [TestCase("nl", "j")] + [TestCase("nl", "ja")] + [TestCase("fr", "oui")] + public void from_string_with_different_formatting_and_cultures(CultureInfo culture, string input) + { + using (culture.Scoped()) + { + var parsed = YesNo.Parse(input); + parsed.Should().Be(Svo.YesNo); + } + } + + [Test] + public void from_valid_input_only_otherwise_throws_on_Parse() + { + using (TestCultures.en_GB.Scoped()) + { + "invalid input".Invoking(YesNo.Parse) + .Should().Throw() + .WithMessage("Not a valid yes-no value"); + } + } + + [Test] + public void from_valid_input_only_otherwise_return_false_on_TryParse() + { + YesNo.TryParse("invalid input", out _).Should().BeFalse(); + } + + [Test] + public void from_invalid_as_null_with_TryParse() + => YesNo.TryParse("invalid input").Should().BeNull(); + + [Test] + public void with_TryParse_returns_SVO() + { + YesNo.TryParse("yes").Should().Be(Svo.YesNo); + } } public class Has_custom_formatting { - [Test] - public void default_value_is_represented_as_string_empty() - { - default(YesNo).ToString().Should().Be(string.Empty); - } - - [Test] - public void unknown_value_is_represented_as_unknown() - { - YesNo.Unknown.ToString(CultureInfo.InvariantCulture).Should().Be("unknown"); - } - - [Test] - public void custom_format_provider_is_applied() - { - var formatted = Svo.YesNo.ToString("B", FormatProvider.CustomFormatter); - formatted.Should().Be("Unit Test Formatter, value: 'True', format: 'B'"); - } - - [Test] - public void with_empty_format_provider() - { - using (TestCultures.es_EC.Scoped()) - { - Svo.YesNo.ToString(FormatProvider.Empty).Should().Be("si"); - } - } - - [TestCase("en-GB", null, "Yes", "yes")] - [TestCase("nl-BE", "f", "Yes", "ja")] - [TestCase("es-EQ", "F", "Yes", "Si")] - [TestCase("en-GB", null, "No", "no")] - [TestCase("nl-BE", "f", "No", "nee")] - [TestCase("es-EQ", "F", "No", "No")] - [TestCase("en-GB", "C", "Yes", "Y")] - [TestCase("nl-BE", "C", "Yes", "J")] - [TestCase("es-EQ", "C", "Yes", "S")] - [TestCase("en-GB", "C", "No", "N")] - [TestCase("nl-BE", "c", "No", "n")] - [TestCase("es-EQ", "c", "No", "n")] - [TestCase("en-US", "B", "Yes", "True")] - [TestCase("en-US", "b", "No", "false")] - [TestCase("en-US", "i", "Yes", "1")] - [TestCase("en-US", "i", "No", "0")] - [TestCase("en-US", "i", "?", "?")] - public void culture_dependent(CultureInfo culture, string format, YesNo svo, string expected) - { - using (culture.Scoped()) - { - svo.ToString(format).Should().Be(expected); - } - } - - [Test] - public void with_current_thread_culture_as_default() - { - using (new CultureInfoScope( - culture: TestCultures.nl_NL, - cultureUI: TestCultures.en_GB)) - { - Svo.YesNo.ToString(provider: null).Should().Be("ja"); - } - } + [Test] + public void default_value_is_represented_as_string_empty() + { + default(YesNo).ToString().Should().Be(string.Empty); + } + + [Test] + public void unknown_value_is_represented_as_unknown() + { + YesNo.Unknown.ToString(CultureInfo.InvariantCulture).Should().Be("unknown"); + } + + [Test] + public void custom_format_provider_is_applied() + { + var formatted = Svo.YesNo.ToString("B", FormatProvider.CustomFormatter); + formatted.Should().Be("Unit Test Formatter, value: 'True', format: 'B'"); + } + + [Test] + public void with_empty_format_provider() + { + using (TestCultures.es_EC.Scoped()) + { + Svo.YesNo.ToString(FormatProvider.Empty).Should().Be("si"); + } + } + + [TestCase("en-GB", null, "Yes", "yes")] + [TestCase("nl-BE", "f", "Yes", "ja")] + [TestCase("es-EQ", "F", "Yes", "Si")] + [TestCase("en-GB", null, "No", "no")] + [TestCase("nl-BE", "f", "No", "nee")] + [TestCase("es-EQ", "F", "No", "No")] + [TestCase("en-GB", "C", "Yes", "Y")] + [TestCase("nl-BE", "C", "Yes", "J")] + [TestCase("es-EQ", "C", "Yes", "S")] + [TestCase("en-GB", "C", "No", "N")] + [TestCase("nl-BE", "c", "No", "n")] + [TestCase("es-EQ", "c", "No", "n")] + [TestCase("en-US", "B", "Yes", "True")] + [TestCase("en-US", "b", "No", "false")] + [TestCase("en-US", "i", "Yes", "1")] + [TestCase("en-US", "i", "No", "0")] + [TestCase("en-US", "i", "?", "?")] + public void culture_dependent(CultureInfo culture, string format, YesNo svo, string expected) + { + using (culture.Scoped()) + { + svo.ToString(format).Should().Be(expected); + } + } + + [Test] + public void with_current_thread_culture_as_default() + { + using (new CultureInfoScope( + culture: TestCultures.nl_NL, + cultureUI: TestCultures.en_GB)) + { + Svo.YesNo.ToString(provider: null).Should().Be("ja"); + } + } } public class Is_comparable { - [Test] - public void to_null_is_1() => Svo.YesNo.CompareTo(Nil.Object).Should().Be(1); - - [Test] - public void to_YesNo_as_object() - { - object obj = Svo.YesNo; - Svo.YesNo.CompareTo(obj).Should().Be(0); - } - - [Test] - public void to_YesNo_only() - { - Assert.Throws(() => Svo.YesNo.CompareTo(new object())); - } - - [Test] - public void can_be_sorted_using_compare() - { - var sorted = new[] - { - YesNo.Empty, - YesNo.Empty, - YesNo.No, - YesNo.Yes, - YesNo.Unknown, - }; - var list = new List { sorted[3], sorted[4], sorted[2], sorted[0], sorted[1] }; - list.Sort(); - - list.Should().BeEquivalentTo(sorted); - } + [Test] + public void to_null_is_1() => Svo.YesNo.CompareTo(Nil.Object).Should().Be(1); + + [Test] + public void to_YesNo_as_object() + { + object obj = Svo.YesNo; + Svo.YesNo.CompareTo(obj).Should().Be(0); + } + + [Test] + public void to_YesNo_only() + => new object().Invoking(Svo.YesNo.CompareTo).Should().Throw(); + + [Test] + public void can_be_sorted_using_compare() + { + var sorted = new[] + { + YesNo.Empty, + YesNo.Empty, + YesNo.No, + YesNo.Yes, + YesNo.Unknown, + }; + var list = new List { sorted[3], sorted[4], sorted[2], sorted[0], sorted[1] }; + list.Sort(); + + list.Should().BeEquivalentTo(sorted); + } } public class Casts { - [TestCase("yes", true)] - [TestCase("no", false)] - public void explicitly_from_boolean(YesNo casted, bool boolean) - { - ((YesNo)boolean).Should().Be(casted); - } - - [Test] - public void yes_implicitly_to_true() - { - var result = YesNo.Yes ? "passed" : "failed"; - result.Should().Be("passed"); - } - - [Test] - public void no_implicitly_to_false() - { - var result = YesNo.No ? "passed" : "failed"; - result.Should().Be("failed"); - } - - [TestCase(null, "")] - [TestCase(true, "y")] - [TestCase(false, "n")] - public void explicitly_from_nullable_boolean(bool? value, YesNo expected) - { - var casted = (YesNo)value; - casted.Should().Be(expected); - } - - [TestCase("", null)] - [TestCase("y", true)] - [TestCase("n", false)] - [TestCase("?", null)] - public void explicitly_to_nullable_boolean(YesNo svo, bool? expected) - { - var casted = (bool?)svo; - casted.Should().Be(expected); - } - - [TestCase("", null)] - [TestCase("y", true)] - [TestCase("n", false)] - [TestCase("?", false)] - public void explicitly_to_boolean(YesNo svo, bool expected) - { - var casted = (bool)svo; - casted.Should().Be(expected); - } + [TestCase("yes", true)] + [TestCase("no", false)] + public void explicitly_from_boolean(YesNo casted, bool boolean) + { + ((YesNo)boolean).Should().Be(casted); + } + + [Test] + public void yes_implicitly_to_true() + { + var result = YesNo.Yes ? "passed" : "failed"; + result.Should().Be("passed"); + } + + [Test] + public void no_implicitly_to_false() + { + var result = YesNo.No ? "passed" : "failed"; + result.Should().Be("failed"); + } + + [TestCase(null, "")] + [TestCase(true, "y")] + [TestCase(false, "n")] + public void explicitly_from_nullable_boolean(bool? value, YesNo expected) + { + var casted = (YesNo)value; + casted.Should().Be(expected); + } + + [TestCase("", null)] + [TestCase("y", true)] + [TestCase("n", false)] + [TestCase("?", null)] + public void explicitly_to_nullable_boolean(YesNo svo, bool? expected) + { + var casted = (bool?)svo; + casted.Should().Be(expected); + } + + [TestCase("", null)] + [TestCase("y", true)] + [TestCase("n", false)] + [TestCase("?", false)] + public void explicitly_to_boolean(YesNo svo, bool expected) + { + var casted = (bool)svo; + casted.Should().Be(expected); + } } public class Supports_type_conversion { - [Test] - public void via_TypeConverter_registered_with_attribute() - => typeof(YesNo).Should().HaveTypeConverterDefined(); - - [Test] - public void from_null_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.FromNull().To().Should().Be(YesNo.Empty); - } - } - - [Test] - public void from_empty_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(string.Empty).To().Should().Be(YesNo.Empty); - } - } - - [Test] - public void from_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From("Yes").To().Should().Be(Svo.YesNo); - } - } - - [Test] - public void to_string() - { - using (TestCultures.en_GB.Scoped()) - { - Converting.ToString().From(Svo.YesNo).Should().Be("yes"); - } - } - - [TestCase(true, "yes")] - [TestCase(false, "no")] - public void from_boolean(bool from, YesNo yesNo) - { - using (TestCultures.en_GB.Scoped()) - { - Converting.From(from).To().Should().Be(yesNo); - } - } - - [TestCase("yes", true)] - [TestCase("no", false)] - public void to_boolean(YesNo yesNo, bool boolean) - { - using (TestCultures.en_GB.Scoped()) - { - Converting.To().From(yesNo).Should().Be(boolean); - } - } + [Test] + public void via_TypeConverter_registered_with_attribute() + => typeof(YesNo).Should().HaveTypeConverterDefined(); + + [Test] + public void from_null_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.FromNull().To().Should().Be(YesNo.Empty); + } + } + + [Test] + public void from_empty_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(string.Empty).To().Should().Be(YesNo.Empty); + } + } + + [Test] + public void from_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From("Yes").To().Should().Be(Svo.YesNo); + } + } + + [Test] + public void to_string() + { + using (TestCultures.en_GB.Scoped()) + { + Converting.ToString().From(Svo.YesNo).Should().Be("yes"); + } + } + + [TestCase(true, "yes")] + [TestCase(false, "no")] + public void from_boolean(bool from, YesNo yesNo) + { + using (TestCultures.en_GB.Scoped()) + { + Converting.From(from).To().Should().Be(yesNo); + } + } + + [TestCase("yes", true)] + [TestCase("no", false)] + public void to_boolean(YesNo yesNo, bool boolean) + { + using (TestCultures.en_GB.Scoped()) + { + Converting.To().From(yesNo).Should().Be(boolean); + } + } } public class Supports_JSON_serialization { #if NET6_0_OR_GREATER - [TestCase(null, null)] - [TestCase("yes", "yes")] - [TestCase("no", "no")] - [TestCase(true, "yes")] - [TestCase(false, "no")] - [TestCase(1L, "yes")] - [TestCase(1.0, "yes")] - [TestCase(0.0, "no")] - [TestCase((long)byte.MaxValue, "?")] - [TestCase((long)short.MaxValue, "?")] - [TestCase((long)int.MaxValue, "?")] - [TestCase(long.MaxValue, "?")] - [TestCase("?", "?")] - public void System_Text_JSON_deserialization(object json, YesNo svo) - => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("yes", "yes")] - public void System_Text_JSON_serialization(YesNo svo, object json) - => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + [TestCase(null, null)] + [TestCase("yes", "yes")] + [TestCase("no", "no")] + [TestCase(true, "yes")] + [TestCase(false, "no")] + [TestCase(1L, "yes")] + [TestCase(1.0, "yes")] + [TestCase(0.0, "no")] + [TestCase((long)byte.MaxValue, "?")] + [TestCase((long)short.MaxValue, "?")] + [TestCase((long)int.MaxValue, "?")] + [TestCase(long.MaxValue, "?")] + [TestCase("?", "?")] + public void System_Text_JSON_deserialization(object json, YesNo svo) + => JsonTester.Read_System_Text_JSON(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("yes", "yes")] + public void System_Text_JSON_serialization(YesNo svo, object json) + => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); #endif - [TestCase("yes", "yes")] - [TestCase("no", "no")] - [TestCase(true, "yes")] - [TestCase(false, "no")] - [TestCase(1L, "yes")] - [TestCase(1.0, "yes")] - [TestCase(0.0, "no")] - [TestCase((long)byte.MaxValue, "?")] - [TestCase((long)short.MaxValue, "?")] - [TestCase((long)int.MaxValue, "?")] - [TestCase(long.MaxValue, "?")] - [TestCase("?", "?")] - public void convention_based_deserialization(object json, YesNo svo) - => JsonTester.Read(json).Should().Be(svo); - - [TestCase(null, null)] - [TestCase("yes", "yes")] - public void convention_based_serialization(YesNo svo, object json) - => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase("2017-06-11", typeof(FormatException))] - [TestCase(5L, typeof(InvalidCastException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json - .Invoking(JsonTester.Read) - .Should().Throw() - .And.Should().BeOfType(exceptionType); + [TestCase("yes", "yes")] + [TestCase("no", "no")] + [TestCase(true, "yes")] + [TestCase(false, "no")] + [TestCase(1L, "yes")] + [TestCase(1.0, "yes")] + [TestCase(0.0, "no")] + [TestCase((long)byte.MaxValue, "?")] + [TestCase((long)short.MaxValue, "?")] + [TestCase((long)int.MaxValue, "?")] + [TestCase(long.MaxValue, "?")] + [TestCase("?", "?")] + public void convention_based_deserialization(object json, YesNo svo) + => JsonTester.Read(json).Should().Be(svo); + + [TestCase(null, null)] + [TestCase("yes", "yes")] + public void convention_based_serialization(YesNo svo, object json) + => JsonTester.Write(svo).Should().Be(json); + + [TestCase("Invalid input", typeof(FormatException))] + [TestCase("2017-06-11", typeof(FormatException))] + [TestCase(5L, typeof(InvalidCastException))] + public void throws_for_invalid_json(object json, Type exceptionType) + => json + .Invoking(JsonTester.Read) + .Should().Throw() + .And.Should().BeOfType(exceptionType); } public class Supports_XML_serialization { - [Test] - public void using_XmlSerializer_to_serialize() - { - var xml = Serialize.Xml(Svo.YesNo); - xml.Should().Be("yes"); - } - - [Test] - public void using_XmlSerializer_to_deserialize() - { - var svo = Deserialize.Xml("yes"); - svo.Should().Be(Svo.YesNo); - } - - [Test] - public void using_data_contract_serializer() - { - var round_tripped = SerializeDeserialize.DataContract(Svo.YesNo); - round_tripped.Should().Be(Svo.YesNo); - } - - [Test] - public void as_part_of_a_structure() - { - var structure = XmlStructure.New(Svo.YesNo); - var round_tripped = SerializeDeserialize.Xml(structure); - - round_tripped.Should().Be(structure); - } - - [Test] - public void has_no_custom_XML_schema() - { - IXmlSerializable obj = Svo.YesNo; - obj.GetSchema().Should().BeNull(); - } + [Test] + public void using_XmlSerializer_to_serialize() + { + var xml = Serialize.Xml(Svo.YesNo); + xml.Should().Be("yes"); + } + + [Test] + public void using_XmlSerializer_to_deserialize() + { + var svo = Deserialize.Xml("yes"); + svo.Should().Be(Svo.YesNo); + } + + [Test] + public void using_data_contract_serializer() + { + var round_tripped = SerializeDeserialize.DataContract(Svo.YesNo); + round_tripped.Should().Be(Svo.YesNo); + } + + [Test] + public void as_part_of_a_structure() + { + var structure = XmlStructure.New(Svo.YesNo); + var round_tripped = SerializeDeserialize.Xml(structure); + + round_tripped.Should().Be(structure); + } + + [Test] + public void has_no_custom_XML_schema() + { + IXmlSerializable obj = Svo.YesNo; + obj.GetSchema().Should().BeNull(); + } } public class Is_Open_API_data_type { - [Test] - public void with_info() - => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(YesNo)) - .Should().BeEquivalentTo(new Qowaiv.OpenApi.OpenApiDataType( - dataType: typeof(YesNo), - description: "Yes-No notation.", - example: "yes", - type: "string", - format: "yes-no", - @enum: new[] { "yes", "no", "?" }, - nullable: true)); + [Test] + public void with_info() + => Qowaiv.OpenApi.OpenApiDataType.FromType(typeof(YesNo)) + .Should().BeEquivalentTo(new Qowaiv.OpenApi.OpenApiDataType( + dataType: typeof(YesNo), + description: "Yes-No notation.", + example: "yes", + type: "string", + format: "yes-no", + @enum: new[] { "yes", "no", "?" }, + nullable: true)); } #if NET8_0_OR_GREATER #else public class Supports_binary_serialization { - [Test] - [Obsolete("Usage of the binary formatter is considered harmful.")] - public void using_BinaryFormatter() - { - var round_tripped = SerializeDeserialize.Binary(Svo.YesNo); - round_tripped.Should().Be(Svo.YesNo); - } - - [Test] - public void storing_byte_in_SerializationInfo() - { - var info = Serialize.GetInfo(Svo.YesNo); - info.GetByte("Value").Should().Be((byte)2); - } + [Test] + [Obsolete("Usage of the binary formatter is considered harmful.")] + public void using_BinaryFormatter() + { + var round_tripped = SerializeDeserialize.Binary(Svo.YesNo); + round_tripped.Should().Be(Svo.YesNo); + } + + [Test] + public void storing_byte_in_SerializationInfo() + { + var info = Serialize.GetInfo(Svo.YesNo); + info.GetByte("Value").Should().Be((byte)2); + } } #endif public class Debugger { - [TestCase("{empty}", "")] - [TestCase("{unknown}", "?")] - [TestCase("yes", "Y")] - public void has_custom_display(object display, YesNo svo) - => svo.Should().HaveDebuggerDisplay(display); + [TestCase("{empty}", "")] + [TestCase("{unknown}", "?")] + [TestCase("yes", "Y")] + public void has_custom_display(object display, YesNo svo) + => svo.Should().HaveDebuggerDisplay(display); }