Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

allow TextCaseConverter to handle any value type #1053

Merged
merged 7 commits into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Xamarin.CommunityToolkit.Converters;
using Xamarin.CommunityToolkit.UnitTests.Mocks;
using Xunit;

namespace Xamarin.CommunityToolkit.UnitTests.Converters
Expand All @@ -10,35 +12,50 @@ public class TextCaseConverter_Tests
const string test = nameof(test);
const string t = nameof(t);

static IEnumerable<object[]> GetTestData()
{
yield return new object[] { test, TextCaseType.Lower, test };
yield return new object[] { test, TextCaseType.Upper, "TEST" };
yield return new object[] { test, TextCaseType.None, test };
yield return new object[] { test, TextCaseType.FirstUpperRestLower, "Test" };
yield return new object[] { t, TextCaseType.Upper, "T" };
yield return new object[] { t, TextCaseType.Lower, t };
yield return new object[] { t, TextCaseType.None, t };
yield return new object[] { t, TextCaseType.FirstUpperRestLower, "T" };
yield return new object[] { string.Empty, TextCaseType.FirstUpperRestLower, string.Empty };
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
yield return new object[] { null, TextCaseType.None, null };
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
yield return new object[] { MockEnum.Foo, TextCaseType.Lower, "foo" };
yield return new object[] { MockEnum.Bar, TextCaseType.None, "Bar" };
yield return new object[] { MockEnum.Baz, TextCaseType.Upper, "BAZ" };
yield return new object[] { new MockItem { Title = "Test Item", Completed = true }, TextCaseType.Upper, "TEST ITEM IS COMPLETED" };
}

[Theory]
[InlineData(test, TextCaseType.Lower, test)]
[InlineData(test, TextCaseType.Upper, "TEST")]
[InlineData(test, TextCaseType.None, test)]
[InlineData(test, TextCaseType.FirstUpperRestLower, "Test")]
[InlineData(t, TextCaseType.Upper, "T")]
[InlineData(t, TextCaseType.Lower, t)]
[InlineData(t, TextCaseType.None, t)]
[InlineData(t, TextCaseType.FirstUpperRestLower, "T")]
[InlineData("", TextCaseType.FirstUpperRestLower, "")]
[MemberData(nameof(GetTestData))]
[InlineData(null, null, null)]
public void TextCaseConverter(object value, object comparedValue, object expectedResult)
public void TextCaseConverterWithParameter(object? value, object? comparedValue, object? expectedResult)
{
var textCaseConverter = new TextCaseConverter();

var result = textCaseConverter.Convert(value, typeof(TextCaseConverter_Tests), comparedValue, CultureInfo.CurrentCulture);
var result = textCaseConverter.Convert(value, typeof(string), comparedValue, CultureInfo.CurrentCulture);

Assert.Equal(result, expectedResult);
}

[Theory]
[InlineData(0)]
[InlineData(int.MinValue)]
[InlineData(double.MaxValue)]
public void InValidConverterValuesThrowArgumenException(object value)
[MemberData(nameof(GetTestData))]
public void TextCaseConverterWithExplicitType(object? value, TextCaseType textCaseType, object? expectedResult)
{
var textCaseConverter = new TextCaseConverter();
var textCaseConverter = new TextCaseConverter
{
Type = textCaseType
};

var result = textCaseConverter.Convert(value, typeof(string), null, CultureInfo.CurrentCulture);

Assert.Throws<ArgumentException>(() => textCaseConverter.Convert(value, typeof(TextCaseConverter_Tests), null, CultureInfo.CurrentCulture));
Assert.Equal(result, expectedResult);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Xamarin.CommunityToolkit.UnitTests.Mocks
{
public enum MockEnum
{
Foo,
Bar,
Baz
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Xamarin.CommunityToolkit.UnitTests.Mocks
{
public class MockItem
{
public string? Title { get; set; }

public bool Completed { get; set; }

public override string ToString() => Completed ?
$"{Title} is completed" : $"{Title} has yet to be completed";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,19 @@ public class TextCaseConverter : ValueConverterExtension, IValueConverter
/// <param name="culture">The culture to use in the converter. This is not implemented.</param>
/// <returns>The converted text representation with the desired casing.</returns>
public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture)
=> value == null || value is string || value is char
? Convert(value?.ToString(), parameter)
: throw new ArgumentException("Value is neither a string nor a char", nameof(value));
{
var str = value?.ToString();
if (str == null || string.IsNullOrWhiteSpace(str))
return str;

return GetParameter(parameter) switch
{
TextCaseType.Lower => str.ToLowerInvariant(),
TextCaseType.Upper => str.ToUpperInvariant(),
TextCaseType.FirstUpperRestLower => str.Substring(0, 1).ToUpperInvariant() + str.ToString().Substring(1).ToLowerInvariant(),
_ => str
};
}

/// <summary>
/// This method is not implemented and will throw a <see cref="NotImplementedException"/>.
Expand All @@ -37,18 +47,10 @@ public class TextCaseConverter : ValueConverterExtension, IValueConverter
/// <param name="parameter">N/A</param>
/// <param name="culture">N/A</param>
/// <returns>N/A</returns>
public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture)
public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture)
=> throw new NotImplementedException();

object? Convert(string? value, object? parameter) => GetParameter(parameter) switch
{
TextCaseType.Lower => value?.ToLowerInvariant(),
TextCaseType.Upper => value?.ToUpperInvariant(),
TextCaseType.FirstUpperRestLower when value != null && !string.IsNullOrWhiteSpace(value) => value.Substring(0, 1).ToUpperInvariant() + value.Substring(1).ToLowerInvariant(),
_ => value
};

TextCaseType GetParameter(object? parameter) => parameter == null ? Type : parameter switch
TextCaseType GetParameter(object? parameter) => parameter switch
{
TextCaseType type => type,
string typeString => Enum.TryParse(typeString, out TextCaseType result)
Expand All @@ -57,7 +59,7 @@ public object ConvertBack(object? value, Type? targetType, object? parameter, Cu
int typeInt => Enum.IsDefined(typeof(TextCaseType), typeInt)
? (TextCaseType)typeInt
: throw new ArgumentException("Cannot convert integer to text case enum value", nameof(parameter)),
_ => TextCaseType.None,
_ => Type,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public enum TextCaseType

/// <summary>Convert to lowercase</summary>
Lower,

/// <summary>Converts the first letter to upper only</summary>
FirstUpperRestLower,
}
}