|
|
|
@ -25,7 +25,7 @@ public class NullConditionalBindingTests |
|
|
|
[Theory] |
|
|
|
[InlineData(false)] |
|
|
|
[InlineData(true)] |
|
|
|
public void Should_Report_Error_Without_Null_Conditional_Operator(bool compileBindings) |
|
|
|
public void Should_Report_Error_Without_Null_Conditional_Operator_For_Clr_Property(bool compileBindings) |
|
|
|
{ |
|
|
|
// Testing the baseline: should report a null error without null conditionals.
|
|
|
|
using var app = Start(); |
|
|
|
@ -40,7 +40,7 @@ public class NullConditionalBindingTests |
|
|
|
<local:ErrorCollectingTextBox Text='{Binding Second.Third.Final}'/> |
|
|
|
</Window> |
|
|
|
""";
|
|
|
|
var data = new First(new Second(null)); |
|
|
|
var data = new First { Second = new Second() }; |
|
|
|
var window = CreateTarget(xaml, data); |
|
|
|
var textBox = Assert.IsType<ErrorCollectingTextBox>(window.Content); |
|
|
|
var error = Assert.IsType<BindingChainException>(textBox.Error); |
|
|
|
@ -56,7 +56,38 @@ public class NullConditionalBindingTests |
|
|
|
[Theory] |
|
|
|
[InlineData(false)] |
|
|
|
[InlineData(true)] |
|
|
|
public void Should_Not_Report_Error_With_Null_Conditional_Operator(bool compileBindings) |
|
|
|
public void Should_Report_Error_Without_Null_Conditional_Operator_For_Avalonia_Property(bool compileBindings) |
|
|
|
{ |
|
|
|
// Testing the baseline: should report a null error without null conditionals.
|
|
|
|
using var app = Start(); |
|
|
|
using var log = TestLogger.Create(); |
|
|
|
|
|
|
|
var xaml = $$$"""
|
|
|
|
<Window xmlns='https://github.com/avaloniaui'
|
|
|
|
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
|
|
|
|
xmlns:local='using:Avalonia.Base.UnitTests.Data.Core' |
|
|
|
x:DataType='local:NullConditionalBindingTests+First' |
|
|
|
x:CompileBindings='{{{compileBindings}}}'> |
|
|
|
<local:ErrorCollectingTextBox Text='{Binding StyledSecond.StyledThird.StyledFinal}'/> |
|
|
|
</Window> |
|
|
|
""";
|
|
|
|
var data = new First { StyledSecond = new Second() }; |
|
|
|
var window = CreateTarget(xaml, data); |
|
|
|
var textBox = Assert.IsType<ErrorCollectingTextBox>(window.Content); |
|
|
|
var error = Assert.IsType<BindingChainException>(textBox.Error); |
|
|
|
var message = Assert.Single(log.Messages); |
|
|
|
|
|
|
|
Assert.Null(textBox.Text); |
|
|
|
Assert.Equal("StyledSecond.StyledThird.StyledFinal", error.Expression); |
|
|
|
Assert.Equal("StyledThird", error.ExpressionErrorPoint); |
|
|
|
Assert.Equal(BindingValueType.BindingError, textBox.ErrorState); |
|
|
|
Assert.Equal("An error occurred binding {Property} to {Expression} at {ExpressionErrorPoint}: {Message}", message); |
|
|
|
} |
|
|
|
|
|
|
|
[Theory] |
|
|
|
[InlineData(false)] |
|
|
|
[InlineData(true)] |
|
|
|
public void Should_Not_Report_Error_With_Null_Conditional_Operator_For_Clr_Property(bool compileBindings) |
|
|
|
{ |
|
|
|
using var app = Start(); |
|
|
|
using var log = TestLogger.Create(); |
|
|
|
@ -69,7 +100,7 @@ public class NullConditionalBindingTests |
|
|
|
<local:ErrorCollectingTextBox Text='{Binding Second.Third?.Final}'/> |
|
|
|
</Window> |
|
|
|
""";
|
|
|
|
var data = new First(new Second(null)); |
|
|
|
var data = new First { Second = new Second() }; |
|
|
|
var window = CreateTarget(xaml, data); |
|
|
|
var textBox = Assert.IsType<ErrorCollectingTextBox>(window.Content); |
|
|
|
|
|
|
|
@ -82,7 +113,33 @@ public class NullConditionalBindingTests |
|
|
|
[Theory] |
|
|
|
[InlineData(false)] |
|
|
|
[InlineData(true)] |
|
|
|
public void Should_Not_Report_Error_With_Null_Conditional_Operator_Before_Method(bool compileBindings) |
|
|
|
public void Should_Not_Report_Error_With_Null_Conditional_Operator_For_Avalonia_Property(bool compileBindings) |
|
|
|
{ |
|
|
|
using var app = Start(); |
|
|
|
using var log = TestLogger.Create(); |
|
|
|
var xaml = $$$"""
|
|
|
|
<Window xmlns='https://github.com/avaloniaui'
|
|
|
|
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
|
|
|
|
xmlns:local='using:Avalonia.Base.UnitTests.Data.Core' |
|
|
|
x:DataType='local:NullConditionalBindingTests+First' |
|
|
|
x:CompileBindings='{{{compileBindings}}}'> |
|
|
|
<local:ErrorCollectingTextBox Text='{Binding StyledSecond.StyledThird?.StyledFinal}'/> |
|
|
|
</Window> |
|
|
|
""";
|
|
|
|
var data = new First { StyledSecond = new Second() }; |
|
|
|
var window = CreateTarget(xaml, data); |
|
|
|
var textBox = Assert.IsType<ErrorCollectingTextBox>(window.Content); |
|
|
|
|
|
|
|
Assert.Null(textBox.Text); |
|
|
|
Assert.Null(textBox.Error); |
|
|
|
Assert.Equal(BindingValueType.Value, textBox.ErrorState); |
|
|
|
Assert.Empty(log.Messages); |
|
|
|
} |
|
|
|
|
|
|
|
[Theory] |
|
|
|
[InlineData(false)] |
|
|
|
[InlineData(true)] |
|
|
|
public void Should_Not_Report_Error_With_Null_Conditional_Operator_Before_Method_For_Clr_Property(bool compileBindings) |
|
|
|
{ |
|
|
|
using var app = Start(); |
|
|
|
using var log = TestLogger.Create(); |
|
|
|
@ -95,7 +152,33 @@ public class NullConditionalBindingTests |
|
|
|
<local:ErrorCollectingTextBox Text='{Binding Second.Third?.Greeting}'/> |
|
|
|
</Window> |
|
|
|
""";
|
|
|
|
var data = new First(new Second(null)); |
|
|
|
var data = new First { Second = new Second() }; |
|
|
|
var window = CreateTarget(xaml, data); |
|
|
|
var textBox = Assert.IsType<ErrorCollectingTextBox>(window.Content); |
|
|
|
|
|
|
|
Assert.Null(textBox.Text); |
|
|
|
Assert.Null(textBox.Error); |
|
|
|
Assert.Equal(BindingValueType.Value, textBox.ErrorState); |
|
|
|
Assert.Empty(log.Messages); |
|
|
|
} |
|
|
|
|
|
|
|
[Theory] |
|
|
|
[InlineData(false)] |
|
|
|
[InlineData(true)] |
|
|
|
public void Should_Not_Report_Error_With_Null_Conditional_Operator_Before_Method_For_Avalonia_Property(bool compileBindings) |
|
|
|
{ |
|
|
|
using var app = Start(); |
|
|
|
using var log = TestLogger.Create(); |
|
|
|
var xaml = $$$"""
|
|
|
|
<Window xmlns='https://github.com/avaloniaui'
|
|
|
|
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
|
|
|
|
xmlns:local='using:Avalonia.Base.UnitTests.Data.Core' |
|
|
|
x:DataType='local:NullConditionalBindingTests+First' |
|
|
|
x:CompileBindings='{{{compileBindings}}}'> |
|
|
|
<local:ErrorCollectingTextBox Text='{Binding StyledSecond.StyledThird?.Greeting}'/> |
|
|
|
</Window> |
|
|
|
""";
|
|
|
|
var data = new First { StyledSecond = new Second() }; |
|
|
|
var window = CreateTarget(xaml, data); |
|
|
|
var textBox = Assert.IsType<ErrorCollectingTextBox>(window.Content); |
|
|
|
|
|
|
|
@ -108,7 +191,7 @@ public class NullConditionalBindingTests |
|
|
|
[Theory] |
|
|
|
[InlineData(false)] |
|
|
|
[InlineData(true)] |
|
|
|
public void Should_Use_TargetNullValue_With_Null_Conditional_Operator(bool compileBindings) |
|
|
|
public void Should_Use_TargetNullValue_With_Null_Conditional_Operator_For_Clr_Property(bool compileBindings) |
|
|
|
{ |
|
|
|
using var app = Start(); |
|
|
|
using var log = TestLogger.Create(); |
|
|
|
@ -121,7 +204,33 @@ public class NullConditionalBindingTests |
|
|
|
<local:ErrorCollectingTextBox Text='{Binding Second.Third?.Final, TargetNullValue=ItsNull}'/> |
|
|
|
</Window> |
|
|
|
""";
|
|
|
|
var data = new First(new Second(null)); |
|
|
|
var data = new First { Second = new Second() }; |
|
|
|
var window = CreateTarget(xaml, data); |
|
|
|
var textBox = Assert.IsType<ErrorCollectingTextBox>(window.Content); |
|
|
|
|
|
|
|
Assert.Equal("ItsNull", textBox.Text); |
|
|
|
Assert.Null(textBox.Error); |
|
|
|
Assert.Equal(BindingValueType.Value, textBox.ErrorState); |
|
|
|
Assert.Empty(log.Messages); |
|
|
|
} |
|
|
|
|
|
|
|
[Theory] |
|
|
|
[InlineData(false)] |
|
|
|
[InlineData(true)] |
|
|
|
public void Should_Use_TargetNullValue_With_Null_Conditional_Operator_For_Avalonia_Property(bool compileBindings) |
|
|
|
{ |
|
|
|
using var app = Start(); |
|
|
|
using var log = TestLogger.Create(); |
|
|
|
var xaml = $$$"""
|
|
|
|
<Window xmlns='https://github.com/avaloniaui'
|
|
|
|
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
|
|
|
|
xmlns:local='using:Avalonia.Base.UnitTests.Data.Core' |
|
|
|
x:DataType='local:NullConditionalBindingTests+First' |
|
|
|
x:CompileBindings='{{{compileBindings}}}'> |
|
|
|
<local:ErrorCollectingTextBox Text='{Binding StyledSecond.StyledThird?.StyledFinal, TargetNullValue=ItsNull}'/> |
|
|
|
</Window> |
|
|
|
""";
|
|
|
|
var data = new First { StyledSecond = new Second() }; |
|
|
|
var window = CreateTarget(xaml, data); |
|
|
|
var textBox = Assert.IsType<ErrorCollectingTextBox>(window.Content); |
|
|
|
|
|
|
|
@ -144,10 +253,47 @@ public class NullConditionalBindingTests |
|
|
|
return UnitTestApplication.Start(TestServices.StyledWindow); |
|
|
|
} |
|
|
|
|
|
|
|
public record First(Second? Second); |
|
|
|
public record Second(Third? Third); |
|
|
|
public record Third(string Final) |
|
|
|
public class First : StyledElement |
|
|
|
{ |
|
|
|
public static readonly StyledProperty<Second?> StyledSecondProperty = |
|
|
|
AvaloniaProperty.Register<First, Second?>(nameof(StyledSecond)); |
|
|
|
|
|
|
|
public Second? Second { get; set; } |
|
|
|
|
|
|
|
public Second? StyledSecond |
|
|
|
{ |
|
|
|
get => GetValue(StyledSecondProperty); |
|
|
|
set => SetValue(StyledSecondProperty, value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class Second : StyledElement |
|
|
|
{ |
|
|
|
public static readonly StyledProperty<Third?> StyledThirdProperty = |
|
|
|
AvaloniaProperty.Register<Second, Third?>(nameof(StyledThird)); |
|
|
|
|
|
|
|
public Third? Third { get; set; } |
|
|
|
|
|
|
|
public Third? StyledThird |
|
|
|
{ |
|
|
|
get => GetValue(StyledThirdProperty); |
|
|
|
set => SetValue(StyledThirdProperty, value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class Third : StyledElement |
|
|
|
{ |
|
|
|
public static readonly StyledProperty<string?> StyledFinalProperty = |
|
|
|
AvaloniaProperty.Register<Third, string?>(nameof(StyledFinal)); |
|
|
|
|
|
|
|
public string? Final { get; set; } |
|
|
|
|
|
|
|
public string? StyledFinal |
|
|
|
{ |
|
|
|
get => GetValue(StyledFinalProperty); |
|
|
|
set => SetValue(StyledFinalProperty, value); |
|
|
|
} |
|
|
|
|
|
|
|
public string Greeting() => "Hello!"; |
|
|
|
} |
|
|
|
|
|
|
|
|